diff --git a/README.md b/README.md index 5b14649..94f9276 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,12 @@ -# Hipster Shop: Cloud-Native Microservices Demo Application +

+ +

-This project contains a 10-tier microservices application. The application is a -web-based e-commerce app called **“Hipster Shop”** where users can browse items, + + +**Online Boutique** is a cloud-native microservices demo application. +Online Boutique consists of a 10-tier microservices application. The application is a +web-based e-commerce app where users can browse items, add them to the cart, and purchase them. **Google uses this application to demonstrate use of technologies like @@ -15,15 +20,17 @@ If you’re using this demo, please **★Star** this repository to show your int > [go/microservices-demo](http://go/microservices-demo) if you are using this > application. +Looking for the old Hipster Shop frontend interface? Use the [manifests](https://github.com/GoogleCloudPlatform/microservices-demo/tree/v0.1.4/kubernetes-manifests) in release [v0.1.4](https://github.com/GoogleCloudPlatform/microservices-demo/releases/v0.1.4). + ## Screenshots | Home Page | Checkout Screen | | ----------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ | -| [![Screenshot of store homepage](./docs/img/hipster-shop-frontend-1.png)](./docs/img/hipster-shop-frontend-1.png) | [![Screenshot of checkout screen](./docs/img/hipster-shop-frontend-2.png)](./docs/img/hipster-shop-frontend-2.png) | +| [![Screenshot of store homepage](./docs/img/online-boutique-frontend-1.png)](./docs/img/online-boutique-frontend-1.png) | [![Screenshot of checkout screen](./docs/img/online-boutique-frontend-2.png)](./docs/img/online-boutique-frontend-2.png) | ## Service Architecture -**Hipster Shop** is composed of many microservices written in different +**Online Boutique** is composed of many microservices written in different languages that talk to each other over gRPC. [![Architecture of @@ -310,7 +317,7 @@ If you've deployed the application with `kubectl apply -f [...]`, you can run `kubectl delete -f [...]` with the same argument to clean up the deployed resources. -## Conferences featuring Hipster Shop +## Conferences featuring Online Boutique - [Google Cloud Next'18 London – Keynote](https://youtu.be/nIq2pkNcfEI?t=3071) showing Stackdriver Incident Response Management diff --git a/docs/img/hipster-shop-frontend-1.png b/docs/img/hipster-shop-frontend-1.png deleted file mode 100644 index 8084e23..0000000 Binary files a/docs/img/hipster-shop-frontend-1.png and /dev/null differ diff --git a/docs/img/hipster-shop-frontend-2.png b/docs/img/hipster-shop-frontend-2.png deleted file mode 100644 index c5a686f..0000000 Binary files a/docs/img/hipster-shop-frontend-2.png and /dev/null differ diff --git a/docs/img/online-boutique-frontend-1.png b/docs/img/online-boutique-frontend-1.png new file mode 100644 index 0000000..8ea6e89 Binary files /dev/null and b/docs/img/online-boutique-frontend-1.png differ diff --git a/docs/img/online-boutique-frontend-2.png b/docs/img/online-boutique-frontend-2.png new file mode 100644 index 0000000..009ae34 Binary files /dev/null and b/docs/img/online-boutique-frontend-2.png differ diff --git a/kubernetes-manifests/frontend.yaml b/kubernetes-manifests/frontend.yaml index da1c7cc..faf461d 100644 --- a/kubernetes-manifests/frontend.yaml +++ b/kubernetes-manifests/frontend.yaml @@ -65,6 +65,8 @@ spec: value: "checkoutservice:5050" - name: AD_SERVICE_ADDR value: "adservice:9555" + - name: ENV_PLATFORM + value: "gcp" # - name: DISABLE_TRACING # value: "1" # - name: DISABLE_PROFILER diff --git a/src/frontend/handlers.go b/src/frontend/handlers.go index d7e8765..b6bd93d 100644 --- a/src/frontend/handlers.go +++ b/src/frontend/handlers.go @@ -22,6 +22,7 @@ import ( "net/http" "os" "strconv" + "strings" "time" "github.com/gorilla/mux" @@ -32,11 +33,17 @@ import ( "github.com/GoogleCloudPlatform/microservices-demo/src/frontend/money" ) +type platformDetails struct { + css string + provider string +} + var ( templates = template.Must(template.New(""). - Funcs(template.FuncMap{ + Funcs(template.FuncMap{ "renderMoney": renderMoney, }).ParseGlob("templates/*.html")) + plat platformDetails ) func (fe *frontendServer) homeHandler(w http.ResponseWriter, r *http.Request) { @@ -72,20 +79,43 @@ func (fe *frontendServer) homeHandler(w http.ResponseWriter, r *http.Request) { ps[i] = productView{p, price} } + //get env and render correct platform banner. + var env = os.Getenv("ENV_PLATFORM") + plat = platformDetails{} + plat.setPlatformDetails(strings.ToLower(env)) + if err := templates.ExecuteTemplate(w, "home", map[string]interface{}{ "session_id": sessionID(r), "request_id": r.Context().Value(ctxKeyRequestID{}), "user_currency": currentCurrency(r), "currencies": currencies, "products": ps, - "cart_size": len(cart), + "cart_size": cartSize(cart), "banner_color": os.Getenv("BANNER_COLOR"), // illustrates canary deployments "ad": fe.chooseAd(r.Context(), []string{}, log), + "platform_css": plat.css, + "platform_name": plat.provider, }); err != nil { log.Error(err) } } +func (plat *platformDetails) setPlatformDetails(env string) { + if env == "aws" { + plat.provider = "AWS" + plat.css = "aws-platform" + } else if env == "onprem" { + plat.provider = "On-Premises" + plat.css = "onprem-platform" + } else if env == "azure" { + plat.provider = "Azure" + plat.css = "azure-platform" + } else { + plat.provider = "Google Cloud" + plat.css = "gcp-platform" + } +} + func (fe *frontendServer) productHandler(w http.ResponseWriter, r *http.Request) { log := r.Context().Value(ctxKeyLog{}).(logrus.FieldLogger) id := mux.Vars(r)["id"] @@ -138,7 +168,9 @@ func (fe *frontendServer) productHandler(w http.ResponseWriter, r *http.Request) "currencies": currencies, "product": product, "recommendations": recommendations, - "cart_size": len(cart), + "cart_size": cartSize(cart), + "platform_css": plat.css, + "platform_name": plat.provider, }); err != nil { log.Println(err) } @@ -234,6 +266,8 @@ func (fe *frontendServer) viewCartHandler(w http.ResponseWriter, r *http.Request } totalPrice = money.Must(money.Sum(totalPrice, *shippingCost)) + log.Info("🌈 ITEMS: %v", items) + year := time.Now().Year() if err := templates.ExecuteTemplate(w, "cart", map[string]interface{}{ "session_id": sessionID(r), @@ -241,11 +275,13 @@ func (fe *frontendServer) viewCartHandler(w http.ResponseWriter, r *http.Request "user_currency": currentCurrency(r), "currencies": currencies, "recommendations": recommendations, - "cart_size": len(cart), + "cart_size": cartSize(cart), "shipping_cost": shippingCost, "total_cost": totalPrice, "items": items, "expiration_years": []int{year, year + 1, year + 2, year + 3, year + 4}, + "platform_css": plat.css, + "platform_name": plat.provider, }); err != nil { log.Println(err) } @@ -299,13 +335,22 @@ func (fe *frontendServer) placeOrderHandler(w http.ResponseWriter, r *http.Reque totalPaid = money.Must(money.Sum(totalPaid, *v.GetCost())) } + currencies, err := fe.getCurrencies(r.Context()) + if err != nil { + renderHTTPError(log, r, w, errors.Wrap(err, "could not retrieve currencies"), http.StatusInternalServerError) + return + } + if err := templates.ExecuteTemplate(w, "order", map[string]interface{}{ "session_id": sessionID(r), "request_id": r.Context().Value(ctxKeyRequestID{}), "user_currency": currentCurrency(r), + "currencies": currencies, "order": order.GetOrder(), "total_paid": &totalPaid, "recommendations": recommendations, + "platform_css": plat.css, + "platform_name": plat.provider, }); err != nil { log.Println(err) } @@ -392,6 +437,15 @@ func cartIDs(c []*pb.CartItem) []string { return out } +// get total # of items in cart +func cartSize(c []*pb.CartItem) int { + cartSize := 0 + for _, item := range c { + cartSize += int(item.GetQuantity()) + } + return cartSize +} + func renderMoney(money pb.Money) string { return fmt.Sprintf("%s %d.%02d", money.GetCurrencyCode(), money.GetUnits(), money.GetNanos()/10000000) } diff --git a/src/frontend/static/favicon.ico b/src/frontend/static/favicon.ico new file mode 100755 index 0000000..30acb27 Binary files /dev/null and b/src/frontend/static/favicon.ico differ diff --git a/src/frontend/static/icons/Hipster_Advert2.svg b/src/frontend/static/icons/Hipster_Advert2.svg new file mode 100755 index 0000000..6c32d48 --- /dev/null +++ b/src/frontend/static/icons/Hipster_Advert2.svg @@ -0,0 +1,40 @@ + + + + + Hipster + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/frontend/static/icons/Hipster_CartIcon.svg b/src/frontend/static/icons/Hipster_CartIcon.svg new file mode 100755 index 0000000..3f80cff --- /dev/null +++ b/src/frontend/static/icons/Hipster_CartIcon.svg @@ -0,0 +1,14 @@ + + + + + Hipster + + + + + diff --git a/src/frontend/static/icons/Hipster_CheckOutIcon.svg b/src/frontend/static/icons/Hipster_CheckOutIcon.svg new file mode 100755 index 0000000..3fef436 --- /dev/null +++ b/src/frontend/static/icons/Hipster_CheckOutIcon.svg @@ -0,0 +1,14 @@ + + + + + Hipster + + + + + diff --git a/src/frontend/static/icons/Hipster_CurrencyIcon.svg b/src/frontend/static/icons/Hipster_CurrencyIcon.svg new file mode 100755 index 0000000..58ba998 --- /dev/null +++ b/src/frontend/static/icons/Hipster_CurrencyIcon.svg @@ -0,0 +1,14 @@ + + + + + Hipster + + + + + diff --git a/src/frontend/static/icons/Hipster_DownArrow.svg b/src/frontend/static/icons/Hipster_DownArrow.svg new file mode 100755 index 0000000..0c7cd19 --- /dev/null +++ b/src/frontend/static/icons/Hipster_DownArrow.svg @@ -0,0 +1,11 @@ + + + + + Hipster + + diff --git a/src/frontend/static/icons/Hipster_FacebookIcon.svg b/src/frontend/static/icons/Hipster_FacebookIcon.svg new file mode 100755 index 0000000..988ce79 --- /dev/null +++ b/src/frontend/static/icons/Hipster_FacebookIcon.svg @@ -0,0 +1,14 @@ + + + + + Hipster + + + + + diff --git a/src/frontend/static/icons/Hipster_GooglePlayIcon.svg b/src/frontend/static/icons/Hipster_GooglePlayIcon.svg new file mode 100755 index 0000000..71ebf78 --- /dev/null +++ b/src/frontend/static/icons/Hipster_GooglePlayIcon.svg @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Hipster + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/frontend/static/icons/Hipster_HelpIcon.svg b/src/frontend/static/icons/Hipster_HelpIcon.svg new file mode 100755 index 0000000..cb17349 --- /dev/null +++ b/src/frontend/static/icons/Hipster_HelpIcon.svg @@ -0,0 +1,14 @@ + + + + + Hipster + + + + + diff --git a/src/frontend/static/icons/Hipster_HeroLogo.svg b/src/frontend/static/icons/Hipster_HeroLogo.svg new file mode 100755 index 0000000..b275f29 --- /dev/null +++ b/src/frontend/static/icons/Hipster_HeroLogo.svg @@ -0,0 +1,55 @@ + + + + + Hipster + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/frontend/static/icons/Hipster_HeroLogoCyan.svg b/src/frontend/static/icons/Hipster_HeroLogoCyan.svg new file mode 100755 index 0000000..523cb58 --- /dev/null +++ b/src/frontend/static/icons/Hipster_HeroLogoCyan.svg @@ -0,0 +1,55 @@ + + + + + Hipster + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/frontend/static/icons/Hipster_HotProducts.svg b/src/frontend/static/icons/Hipster_HotProducts.svg new file mode 100755 index 0000000..b1b7ae5 --- /dev/null +++ b/src/frontend/static/icons/Hipster_HotProducts.svg @@ -0,0 +1,28 @@ + + Hipster + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/frontend/static/icons/Hipster_InstagramIcon.svg b/src/frontend/static/icons/Hipster_InstagramIcon.svg new file mode 100755 index 0000000..73653f4 --- /dev/null +++ b/src/frontend/static/icons/Hipster_InstagramIcon.svg @@ -0,0 +1,15 @@ + + + + + Hipster + + + + + + diff --git a/src/frontend/static/icons/Hipster_KitchenwareOffer.svg b/src/frontend/static/icons/Hipster_KitchenwareOffer.svg new file mode 100755 index 0000000..827a851 --- /dev/null +++ b/src/frontend/static/icons/Hipster_KitchenwareOffer.svg @@ -0,0 +1,36 @@ + + Hipster + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/frontend/static/icons/Hipster_NavLogo.svg b/src/frontend/static/icons/Hipster_NavLogo.svg new file mode 100755 index 0000000..c566913 --- /dev/null +++ b/src/frontend/static/icons/Hipster_NavLogo.svg @@ -0,0 +1,36 @@ + + + + + Hipster + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/frontend/static/icons/Hipster_OtherProducts.svg b/src/frontend/static/icons/Hipster_OtherProducts.svg new file mode 100755 index 0000000..dbe320a --- /dev/null +++ b/src/frontend/static/icons/Hipster_OtherProducts.svg @@ -0,0 +1,36 @@ + + Hipster + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/frontend/static/icons/Hipster_PinterestIcon.svg b/src/frontend/static/icons/Hipster_PinterestIcon.svg new file mode 100755 index 0000000..08714df --- /dev/null +++ b/src/frontend/static/icons/Hipster_PinterestIcon.svg @@ -0,0 +1,14 @@ + + + + + Hipster + + + + + diff --git a/src/frontend/static/icons/Hipster_ProfileIcon.svg b/src/frontend/static/icons/Hipster_ProfileIcon.svg new file mode 100755 index 0000000..3dc87e4 --- /dev/null +++ b/src/frontend/static/icons/Hipster_ProfileIcon.svg @@ -0,0 +1,14 @@ + + + + + Hipster + + + + + diff --git a/src/frontend/static/icons/Hipster_SearchIcon.svg b/src/frontend/static/icons/Hipster_SearchIcon.svg new file mode 100755 index 0000000..583f959 --- /dev/null +++ b/src/frontend/static/icons/Hipster_SearchIcon.svg @@ -0,0 +1,11 @@ + + + + + Hipster + + diff --git a/src/frontend/static/icons/Hipster_TwitterIcon.svg b/src/frontend/static/icons/Hipster_TwitterIcon.svg new file mode 100755 index 0000000..8a4ff80 --- /dev/null +++ b/src/frontend/static/icons/Hipster_TwitterIcon.svg @@ -0,0 +1,11 @@ + + + + + Hipster + + diff --git a/src/frontend/static/icons/Hipster_UpDownControl.svg b/src/frontend/static/icons/Hipster_UpDownControl.svg new file mode 100755 index 0000000..be33647 --- /dev/null +++ b/src/frontend/static/icons/Hipster_UpDownControl.svg @@ -0,0 +1,7 @@ + + Hipster + + + + + diff --git a/src/frontend/static/icons/Hipster_YoutubeIcon.svg b/src/frontend/static/icons/Hipster_YoutubeIcon.svg new file mode 100755 index 0000000..edfe961 --- /dev/null +++ b/src/frontend/static/icons/Hipster_YoutubeIcon.svg @@ -0,0 +1,15 @@ + + + + + Hipster + + + + + + diff --git a/src/frontend/static/images/Advert2BannerImage.png b/src/frontend/static/images/Advert2BannerImage.png new file mode 100755 index 0000000..5754a0e Binary files /dev/null and b/src/frontend/static/images/Advert2BannerImage.png differ diff --git a/src/frontend/static/images/AdvertBannerImage.png b/src/frontend/static/images/AdvertBannerImage.png new file mode 100755 index 0000000..7d32353 Binary files /dev/null and b/src/frontend/static/images/AdvertBannerImage.png differ diff --git a/src/frontend/static/images/HeroBannerImage.png b/src/frontend/static/images/HeroBannerImage.png new file mode 100755 index 0000000..b05df63 Binary files /dev/null and b/src/frontend/static/images/HeroBannerImage.png differ diff --git a/src/frontend/static/images/HeroBannerImage2.png b/src/frontend/static/images/HeroBannerImage2.png new file mode 100755 index 0000000..26c4cef Binary files /dev/null and b/src/frontend/static/images/HeroBannerImage2.png differ diff --git a/src/frontend/static/images/VRHeadsets.png b/src/frontend/static/images/VRHeadsets.png new file mode 100755 index 0000000..ed4491a Binary files /dev/null and b/src/frontend/static/images/VRHeadsets.png differ diff --git a/src/frontend/static/styles/cart.css b/src/frontend/static/styles/cart.css new file mode 100755 index 0000000..5ec006f --- /dev/null +++ b/src/frontend/static/styles/cart.css @@ -0,0 +1,99 @@ +.cart-bg { + background: #f0f0f0; +} + +.cart .form-control { + border: none; + border-radius: 0; + -webkit-appearance: none; +} + +.cart h3 { + font-size: 36px; +} + +.cart form label { + color: #707070; +} + +.empty-btn { + margin-right: 20px; +} + +.btn { + border-radius: 0; + color: #111111; + background: #e9ecef; + border: 1px solid #d1d7dc; + font-size: 18px; + padding: 10px 15px; + text-transform: uppercase; + letter-spacing: 1.8px; +} + +.btn-info { + border: none; + background: #4cc8c6; +} + +.center-contents > * { + margin: auto; +} + +.product-item { + max-width: 540px; + margin: auto; + margin-bottom: 30px; +} + +.product-item .image { + max-width: 180px; + padding: 0; +} + +.product-item .image img { + width: 100%; + height: 100%; + object-fit: cover; +} + +.product-item .text { + background: white; + padding: 25px 30px; +} + +.product-item .text h4 { + font-size: 24px; + letter-spacing: 4.8px; + margin-bottom: 0; +} + +.product-item .text p { + margin-bottom: 20px; +} + +.product-item .text small { + font-size: 18px; +} + +.product-item .text .details { + font-size: 18px; +} + +.order-summary { + font-size: 24px; + color: #000000; + margin-bottom: 30px; +} + +.order-summary p { + font-size: 18px; +} + +.checkout h3 { + font-size: 36px; + margin-bottom: 30px; +} +.last-row { + margin-top: 30px; +} \ No newline at end of file diff --git a/src/frontend/static/styles/order.css b/src/frontend/static/styles/order.css new file mode 100755 index 0000000..27b0b75 --- /dev/null +++ b/src/frontend/static/styles/order.css @@ -0,0 +1,32 @@ +.order { + background: #f0f0f0; +} + +.order .container { + border-top: 1px solid #b4b2bb; +} + +.order-logo { + height: 100px; + margin-bottom: 35px; +} + +.order h3 { + font-size: 36px; + margin-bottom: 40px; +} + +.order p { + font-size: 24px; + margin-bottom: 0; + color: #707070; +} + +.order .mg-bt { + color: #111111; + margin-bottom: 35px; +} + +.order .btn { + margin: auto; +} \ No newline at end of file diff --git a/src/frontend/static/styles/styles.css b/src/frontend/static/styles/styles.css new file mode 100755 index 0000000..e22bb03 --- /dev/null +++ b/src/frontend/static/styles/styles.css @@ -0,0 +1,607 @@ +/* general */ + +html, body { + height: 100%; +} + +body { + color: #111111; + font-family: 'Roboto', sans-serif; + display: flex; + flex-direction: column; +} + +hr { + border-top: 1px solid #b4b2bb; +} + +.text-muted { + color: #707070; +} + +.badge { + display: inline-block !important; + width: 18px; + height: 18px; + color: #111111; + display: flex; + align-items: center; + justify-content: center; + font-size: 10px; + border-radius: 50%; + padding-left: 3px; +} + +.badge.badge-blue { + background-color: #4bc7c7; + padding-top: 5px; +} + +/*header*/ + +header .badge.badge-blue { + transform: translateY(-3px); +} + +header .navbar { + height: 38px; +} + +header .h-free-shipping { + font-size: 15px; +} + +header .h-free-shipping span:first-child { + font-weight: bold; +} + +header .h-free-shipping span:last-child { + font-size: 12px; + cursor: pointer; + text-decoration: underline; +} + +header .h-controls { + display: flex; + justify-content: flex-end; +} + +header .h-control { + display: flex; + align-items: center; + font-size: 12px; + position: relative; + margin-left: 40px; + color: #605f64; +} + +header .h-control:first-child { + margin-left: 0; +} + +header .h-control img { + width: 20px; + height: 20px; + margin-right: 8px; +} + +header .h-control input { + border: none; + padding: 0 31px 0 31px; + width: 250px; + height: 24px; + flex-shrink: 0; + background-color: #f2f2f2; + display: flex; + align-items: center; +} + +header .h-control input:focus { + outline: 0; + border: 0; + box-shadow: 0; +} + +header .icon { + width: 20px; + height: 20px; +} + +header .icon.arrow { + position: absolute; + right: 4px; + width: 11px; + height: 7px; +} + +header .icon.search-icon { + width: 12px; + height: 13px; + position: absolute; + left: 10px; +} + +header .h-control select { + background: transparent; + border-radius: 0; + border: 1px solid #acacac; + width: 100px; + height: 20px; + flex-shrink: 0; + padding: 0 7px; + display: flex; + align-items: center; +} + + +header .h-control::-webkit-input-placeholder { + /* Chrome/Opera/Safari */ + font-size: 12px; + color: #605f64; +} + +header .h-control::-moz-placeholder { + /* Firefox 19+ */ + font-size: 12px; + color: #605f64; +} + +header .h-control :-ms-input-placeholder { + /* IE 10+ */ + font-size: 12px; + color: #605f64; +} + +header .h-control :-moz-placeholder { + /* Firefox 18- */ + font-size: 12px; + color: #605f64; +} + +header .navbar.sub-navbar { + height: 60px; + background-color: #111111; + font-size: 15px; + color: #b4b2bb; + padding-top: 0; + padding-bottom: 0; +} + +header .navbar.sub-navbar .logo { + width: 209px; + height: 40px; +} + +header .navbar.sub-navbar .navbar-brand { + padding: 0; +} + +header .navbar.sub-navbar a { + color: #b4b2bb; +} + +header .navbar.sub-navbar nav a { + margin: 0 10px; +} + +header .navbar.sub-navbar .controls { + display: flex; + height: 60px; +} + +header .navbar.sub-navbar .controls a { + display: block; + width: 120px; + border-left: 1px solid #b4b2bb; + display: flex; + flex-flow: column; + align-items: center; + justify-content: center; +} + +header .navbar.sub-navbar .controls a img { + width: 20px; + height: 20px; + margin-bottom: 3px; +} + +header .navbar.sub-navbar .controls a:last-child { + border-right: 1px solid #b4b2bb; +} + +/*footer*/ + +footer.py-5 { + flex-shrink: 0; + padding: 0 !important; +} + +footer .footer-top { + background-color: #f0f0f0; +} + +footer .footer-top .footer-social, +footer .footer-top .footer-app, +footer .footer-links, +footer .footer-top .social, +footer .footer-top .app { + display: flex; + align-items: center; +} + +footer .footer-top .footer-social { + padding: 31px; +} + +footer .footer-top .footer-social h4 { + margin-bottom: 0; +} + +footer .footer-top .footer-social div { + width: 50%; +} + +.footer-top .social { + border-right: 1px solid #b4b2bb; +} + +.footer-top .social h4 { + font-size: 24px; + color: #111111; + font-weight: bold; + text-transform: uppercase; + margin-right: 37px; + line-height: 0.92; +} + +.footer-top .social img { + margin-right: 16px; + width: 48px; + height: 48px; +} + +.footer-top .app { + justify-content: flex-end; +} + +.footer-top .app h4 { + font-size: 24px; + font-weight: bold; + color: #111111; + line-height: 0.92; +} + +.footer-top .app h4 span { + color: #707070; + font-style: italic; +} + +.footer-top .app img { + width: 136px; + height: 41px; + margin-left: 42px; +} + +footer .footer-links { + padding-top: 37px; + justify-content: space-between; + align-items: flex-start; +} + +footer .links-group { + width: 164px; + flex-shrink: 0; + list-style: none; + color: #707070; + padding: 0; +} + +footer .links-group .group-header { + font-size: 16px; + text-transform: uppercase; + color: #111111; + font-weight: bold; + margin-bottom: 12px; +} + +footer .links-group li { + margin-bottom: 10px; + cursor: pointer; +} + +footer .links-group li:hover { + text-decoration: underline; +} + +footer .footer-bottom { + background-color: #111111; + font-size: 16px; + height: 80px; + padding: 23px 0; + display: flex; + justify-content: center; + flex-flow: column; +} + +footer .footer-bottom p { + text-align: center; + color: #b4b2bb; + padding: 0; + margin: 0; +} + +footer .footer-bottom p:first-child { + color: white; +} + +/*Home*/ + +main { + flex: 1 0 auto; +} + +main.home { + background-color: white; +} + +.h-jumbotron { + border-radius: 0; + background: url(/static/images/HeroBannerImage2.png) no-repeat top center; + background-size: cover; +} + +.h-jumbotron .container img { + width: 280px; + height: 210px; +} + +.h-row { + display: flex; + justify-content: center; + align-items: center; +} + +.h-row img { + width: 156px; + height: 100px; + margin-bottom: 45px; +} + +.h-grid .bg-light { + background-color: white; +} + +.card-title.h-card-title { + width: 100%; + font-size: 22px; + letter-spacing: 4.8px; + text-align: center; + color: #111111; + text-transform: uppercase; + margin-bottom: 0; +} + +.card-body.h-card-body { + padding: 1.25rem 0.75rem; +} + +.h-card-body .text-muted { + font-size: 18px; +} + +.ad-row { + padding-left: 68px; + height: 400px; + display: flex; + align-items: center; + background: url(/static/images/AdvertBannerImage.png) no-repeat top center; + background-size: cover; +} + +.ad-row-2 { + background: url(/static/images/Advert2BannerImage.png) no-repeat top center; +} + +.ad-row img { + width: 292px; + height: 280px; +} + +/*Product*/ + +.h-product { + background-color: #f0f0f0; + padding: 65px 16.96428571%; + color: #707070; + font-size: 18px; +} + +.h-product .col { + height: 540px; +} + +.h-product .col img { + width: 540px; +} + +.h-product .product-info { + width: calc(100% - 540px); +} + +.h-product .product-info .product-wrapper { + border-top: 1px solid #b4b2bb; + border-bottom: 1px solid #b4b2bb; + height: 100%; + margin-left: 15px; + display: flex; + flex-flow: column; + justify-content: center; +} + +.h-product .text-muted { + color: #707070 !important; + margin: 20px 0; +} + +.h-product .product-info h2 { + font-size: 48px; + line-height: 1.1; + letter-spacing: 9.6px; + color: #111111; +} + +.h-product .product-info h6 { + font-size: 18px; + color: #111111; + text-transform: uppercase; + margin: 0 0 3px 0; +} + +.h-product .product-info form { + margin-top: 100px; +} + +.h-product .input-group-text, +.h-product .btn.btn-info { + font-size: 18px; + line-height: 1.89; + letter-spacing: 3.6px; + text-align: center; + color: #111111; + text-transform: uppercase; + border-radius: 0; +} + +.h-product .input-group-text { + width: 150px; + height: 49px; + border: solid 1px #d1d7dc; + background-color: #e9ecef; +} + +.h-product select.form-control-lg.custom-select { + height: 49px; +} + +.h-product .btn.btn-info { + width: 178px; + height: 49px; + padding-left: 0.75rem; + padding-right: 0.75rem; + background-color: #4cc8c6; + margin-left: 30px; +} + +.h-product .btn.btn-info:hover { + color: #fff; + background-color: #138496; + border-color: #117a8b; +} + +.other-products-img { + width: 234px !important; + height: 80px !important; +} + +/*recommendations*/ + +.h-card.card { + border: none; + border-radius: 0 !important; + position: relative; + cursor: pointer; +} + +.h-card.card a { + position: relative; +} + +.h-card.card a .card-hover { + position: absolute; + height: 100%; + width: 100%; + top: 0; + left: 0; + background-color: transparent; +} + +.h-card.card:hover a .card-hover { + background-color: rgba(0, 0, 0, 0.3); +} + +/*platform banner*/ + +.aws-platform, +.onprem-platform, +.gcp-platform { + position: fixed; + top: 0; + left: 0; + width: 10px; + height: 100vh; + color: white; + font-size: 24px; + z-index: 999; +} + +.aws-platform, +.aws-platform .platform-flag { + background-color: #ff9900; + color: #000000; +} + +.onprem-platform, +.onprem-platform .platform-flag { + background-color: #34A853; +} + +.gcp-platform, +.gcp-platform .platform-flag { + background-color: #4285f4; +} + +.platform-flag { + position: absolute; + top: 98px; + left: 0; + width: 190px; + height: 50px; + display: flex; + justify-content: center; + align-items: center; +} + +@media (min-width: 1679px) { + + header .navbar, + header .navbar.sub-navbar, + footer .footer-top { + padding: 0 16.96428571%; + } +} + +.recommendations { + background: white; +} + +.recommendations .container .image { + text-align: center; +} + +.recommendations .container .image>img { + height: 80px; + margin: 50px 0; +} + +.recommendations .prods { + padding-bottom: 50px; +} + +.recommendations .card-img-top { + border-radius: 0; +} + +select { + -webkit-appearance: none; + -webkit-border-radius: 0px; +} \ No newline at end of file diff --git a/src/frontend/templates/ad.html b/src/frontend/templates/ad.html old mode 100644 new mode 100755 diff --git a/src/frontend/templates/cart.html b/src/frontend/templates/cart.html old mode 100644 new mode 100755 index 99812c9..59d726a --- a/src/frontend/templates/cart.html +++ b/src/frontend/templates/cart.html @@ -1,60 +1,64 @@ {{ define "cart" }} {{ template "header" . }} - -
-
-
+
+ + {{$.platform_name}} + +
+
+
+
{{ if eq (len $.items) 0 }}

Your shopping cart is empty!

Items you add to your shopping cart will appear here.

- Browse Products → + Browse Products → {{ else }}
-

{{ len $.items }} item - {{- if gt (len $.items) 1}}s{{end}} - in your Shopping Cart

+

{{ $.cart_size }} item + {{- if gt ($.cart_size) 1}}s{{end}} + in your cart

- - Browse more products → + + Keep browsing
- +
-
- + {{ range $.items }} -
-
- -
-
- {{.Item.Name}}
- SKU: #{{.Item.Id}} -
-
- Qty: {{.Quantity}}
- - {{ renderMoney .Price}} - +
+
+
+ +
+
+

{{ .Item.Name }}

+

SKU: #{{ .Item.Id }}

+
+ Quantity: {{ .Quantity }}
+ + {{ renderMoney .Price }} + +
+
- {{ end }} + {{ end }}
-
+

Shipping Cost: {{ renderMoney .shipping_cost }}

Total Cost: {{ renderMoney .total_cost }}
-
-
+
-

Checkout

+

Checkout

@@ -72,7 +76,7 @@
- +
@@ -88,7 +92,7 @@
@@ -116,7 +120,7 @@ - +
@@ -133,26 +137,22 @@
-
- +
+
{{ end }} - {{ if $.recommendations}} -
- {{ template "recommendations" $.recommendations }} - {{ end }} -
+ {{ if $.recommendations}} + {{ template "recommendations" $.recommendations }} + {{ end }}
- {{ template "footer" . }} -{{ end }} + {{ end }} diff --git a/src/frontend/templates/error.html b/src/frontend/templates/error.html old mode 100644 new mode 100755 index 0c9d163..8d7557f --- a/src/frontend/templates/error.html +++ b/src/frontend/templates/error.html @@ -1,12 +1,16 @@ {{ define "error" }} {{ template "header" . }} - +
+ + {{$.platform_name}} + +

Uh, oh!

Something has failed. Below are some details for debugging.

- +

HTTP Status: {{.status_code}} {{.status}}

@@ -17,4 +21,4 @@
     
{{ template "footer" . }} -{{ end }} + {{ end }} \ No newline at end of file diff --git a/src/frontend/templates/footer.html b/src/frontend/templates/footer.html old mode 100644 new mode 100755 index 0ca31e1..9d12557 --- a/src/frontend/templates/footer.html +++ b/src/frontend/templates/footer.html @@ -1,25 +1,18 @@ {{ define "footer" }} -
-
-

- © 2018 Google Inc - - (Source Code) - -

-

- - This website is hosted for demo purposes only. It is not an - actual shop. This is not an official Google project. - -

- - {{ if $.session_id }}session-id: {{ $.session_id }}
{{end}} - {{ if $.request_id }}request-id: {{ $.request_id }}
{{end}} -
+ +
+
- + +
+
+ + -{{ end }} +{{ end }} \ No newline at end of file diff --git a/src/frontend/templates/header.html b/src/frontend/templates/header.html old mode 100644 new mode 100755 index 62444cf..bf68d31 --- a/src/frontend/templates/header.html +++ b/src/frontend/templates/header.html @@ -1,35 +1,57 @@ {{ define "header" }} + - Hipster Shop - + Online Boutique + + + + + + - +
-
- - -{{end}} + {{end}} \ No newline at end of file diff --git a/src/frontend/templates/home.html b/src/frontend/templates/home.html old mode 100644 new mode 100755 index 1d97c6a..d04a4d5 --- a/src/frontend/templates/home.html +++ b/src/frontend/templates/home.html @@ -1,63 +1,49 @@ {{ define "home" }} - {{ template "header" . }} -
-
-
-

- One-stop for Hipster Fashion & Style Online -

-

- Tired of mainstream fashion ideas, popular trends and - societal norms? This line of lifestyle products will help - you catch up with the hipster trend and express your - personal style. Start shopping hip and vintage items now! -

-
-
+{{ template "header" . }} +
+ + {{$.platform_name}} + +
+
+
+
+ icon +
+
-
-
-
- {{ range $.products }} -
-
- - - -
-
- {{ .Item.Name }} -
-
- - - {{ renderMoney .Price }} - - -
-
-
-
- {{ end }} -
-
- {{ with $.ad }}{{ template "text_ad" . }}{{ end}} -
+
+
+
+ icon +
+
+ {{ range $.products }} +
+
+ + +
+
+
+
+ {{ .Item.Name }} +
+
+ + {{ renderMoney .Price }} + +
+
-
+ {{ end }} +
+
+ +
- {{ template "footer" . }} +{{ template "footer" . }} -{{ end }} +{{ end }} \ No newline at end of file diff --git a/src/frontend/templates/order.html b/src/frontend/templates/order.html old mode 100644 new mode 100755 index 7784918..a5772d8 --- a/src/frontend/templates/order.html +++ b/src/frontend/templates/order.html @@ -1,37 +1,41 @@ {{ define "order" }} {{ template "header" . }} - -
+
+ + {{$.platform_name}} + +
+
-
+
-
-

- Your order is complete! -

-

- Order Confirmation ID: {{.order.OrderId}} -
- Shipping Tracking ID: {{.order.ShippingTrackingId}} -

-

- Shipping Cost: {{renderMoney .order.ShippingCost}} -
- Total Paid: {{renderMoney .total_paid}} -

- Browse other products → +
+ +

+ Your order is complete! +

+

Order Confirmation ID

+

{{.order.OrderId}}

+

Shipping Tracking ID

+

{{.order.ShippingTrackingId}}

+

Shipping Cost

+

{{renderMoney .order.ShippingCost}}

+

Total Paid

+

{{renderMoney .total_paid}}

-
- {{ if $.recommendations }} -
- {{ template "recommendations" $.recommendations }} -
- {{ end }}
+
+ +
+ {{ if $.recommendations }} + {{ template "recommendations" $.recommendations }} + {{ end }}
{{ template "footer" . }} -{{ end }} + {{ end }} diff --git a/src/frontend/templates/product.html b/src/frontend/templates/product.html old mode 100644 new mode 100755 index e939987..f1ceb2a --- a/src/frontend/templates/product.html +++ b/src/frontend/templates/product.html @@ -1,56 +1,58 @@ {{ define "product" }} - {{ template "header" . }} +{{ template "header" . }} +
+ + {{$.platform_name}} + +
-
-
-
-
-
- -
-
-

{{$.product.Item.Name}}

- -

- {{ renderMoney $.product.Price}} -

-
-

-

Product Description:
- {{$.product.Item.Description}} -

-
+
+
+
+
+ +
+
+
+

{{$.product.Item.Name}}

-
- -
-
- -
- - -
-
-
-
- - {{ if $.recommendations}} -
- {{ template "recommendations" $.recommendations }} - {{ end }} - - {{ with $.ad }}{{ template "text_ad" . }}{{ end}} +

+ {{ renderMoney $.product.Price}} +

+
+
Product Description:
+ {{$.product.Item.Description}} +
+ +
+ +
+
+ +
+ +
+
- -
- {{ template "footer" . }} -{{ end }} +
+
+
+
+ {{ if $.recommendations}} + {{ template "recommendations" $.recommendations }} + {{ end }} + + {{ with $.ad }}{{ template "text_ad" . }}{{ end}} + +
+
+{{ template "footer" . }} +{{ end }} \ No newline at end of file diff --git a/src/frontend/templates/recommendations.html b/src/frontend/templates/recommendations.html old mode 100644 new mode 100755 index 10525af..5d83017 --- a/src/frontend/templates/recommendations.html +++ b/src/frontend/templates/recommendations.html @@ -1,21 +1,26 @@ {{ define "recommendations" }} -
Products you might like
-
- {{range . }} -
-
- - - -
- - {{ .Name }} - -
+
+
+
+ icon +
+
+ {{range . }} +
+
+ + +
+
+
+
+ {{ .Name }} +
+
+
+ {{ end }}
- {{ end }} -
-{{ end }} +
+ +{{ end }} \ No newline at end of file diff --git a/src/productcatalogservice/products.json b/src/productcatalogservice/products.json index f41b2d9..267d04a 100644 --- a/src/productcatalogservice/products.json +++ b/src/productcatalogservice/products.json @@ -107,4 +107,4 @@ "categories": ["gardening"] } ] -} +} \ No newline at end of file