├── resources
└── .gitkeep
├── translations
├── merged
│ ├── .gitkeep
│ ├── en-gb.untranslated.yaml
│ ├── de-de.all.yaml
│ ├── de-de.untranslated.yaml
│ └── en-gb.all.yaml
├── translated
│ └── .gitkeep
├── src
│ ├── de-de.home.json
│ ├── en-gb.home.json
│ ├── en-gb.common.json
│ ├── en-gb.productpage.json
│ ├── en-gb.checkout.json
│ ├── en-gb.cart.json
│ └── en-gb.search.json
└── Readme.md
├── frontend
├── src
│ ├── mock
│ │ └── _mockmap.js
│ ├── page
│ │ ├── error
│ │ │ ├── error.sass
│ │ │ ├── 503.pug
│ │ │ ├── withCode.pug
│ │ │ └── 404.pug
│ │ ├── home
│ │ │ ├── home.sass
│ │ │ ├── home.pug
│ │ │ └── molecule
│ │ │ │ └── carousel
│ │ │ │ └── carousel.pug
│ │ ├── search
│ │ │ ├── search.sass
│ │ │ └── products.pug
│ │ ├── category
│ │ │ ├── category.sass
│ │ │ └── category.pug
│ │ ├── product
│ │ │ ├── product.js
│ │ │ └── product.pug
│ │ ├── checkout
│ │ │ ├── checkout.js
│ │ │ ├── emptycart.pug
│ │ │ ├── carterror.pug
│ │ │ ├── cart.pug
│ │ │ ├── success.pug
│ │ │ ├── startcheckout.pug
│ │ │ ├── checkout.pug
│ │ │ ├── review.pug
│ │ │ └── organism
│ │ │ │ └── checkoutform.pug
│ │ └── offers
│ │ │ └── offers.pug
│ ├── index.js
│ ├── asset
│ │ ├── img
│ │ │ ├── sample.jpg
│ │ │ ├── overlays
│ │ │ │ ├── 01.png
│ │ │ │ ├── 02.png
│ │ │ │ ├── 03.png
│ │ │ │ ├── 04.png
│ │ │ │ ├── 05.png
│ │ │ │ ├── 06.png
│ │ │ │ ├── 07.png
│ │ │ │ ├── 08.png
│ │ │ │ └── 09.png
│ │ │ ├── flamingo-logo-black.png
│ │ │ ├── lightbox
│ │ │ │ ├── preloader.gif
│ │ │ │ ├── default-skin.png
│ │ │ │ └── default-skin.svg
│ │ │ ├── visuals
│ │ │ │ ├── flamingo-scetch.jpg
│ │ │ │ ├── flamingo-600205_1280.jpg
│ │ │ │ └── digital-art-3054735_1280.jpg
│ │ │ └── svg
│ │ │ │ ├── arrow_left.svg
│ │ │ │ └── arrow_right.svg
│ │ ├── font
│ │ │ └── roboto
│ │ │ │ ├── Roboto-Bold.eot
│ │ │ │ ├── Roboto-Bold.ttf
│ │ │ │ ├── Roboto-Bold.woff
│ │ │ │ ├── Roboto-Light.eot
│ │ │ │ ├── Roboto-Light.ttf
│ │ │ │ ├── Roboto-Thin.eot
│ │ │ │ ├── Roboto-Thin.ttf
│ │ │ │ ├── Roboto-Thin.woff
│ │ │ │ ├── Roboto-Bold.woff2
│ │ │ │ ├── Roboto-Light.woff
│ │ │ │ ├── Roboto-Light.woff2
│ │ │ │ ├── Roboto-Medium.eot
│ │ │ │ ├── Roboto-Medium.ttf
│ │ │ │ ├── Roboto-Medium.woff
│ │ │ │ ├── Roboto-Regular.eot
│ │ │ │ ├── Roboto-Regular.ttf
│ │ │ │ ├── Roboto-Thin.woff2
│ │ │ │ ├── Roboto-Medium.woff2
│ │ │ │ ├── Roboto-Regular.woff
│ │ │ │ └── Roboto-Regular.woff2
│ │ └── i18n
│ │ │ └── en-gb.js
│ ├── base
│ │ └── style
│ │ │ └── mdp-ecom-base
│ │ │ ├── free
│ │ │ ├── _dropdowns.sass
│ │ │ ├── _msc.sass
│ │ │ ├── _footers.sass
│ │ │ ├── _badges.sass
│ │ │ ├── _depreciated.sass
│ │ │ ├── _input-group.sass
│ │ │ ├── _cards.sass
│ │ │ ├── _list-group.sass
│ │ │ ├── _tables.sass
│ │ │ ├── _carousels.sass
│ │ │ ├── _pagination.sass
│ │ │ ├── _navbars.sass
│ │ │ ├── _buttons.sass
│ │ │ ├── _forms.sass
│ │ │ ├── _animations-basic.sass
│ │ │ └── _modals.sass
│ │ │ └── core
│ │ │ ├── _helpers.sass
│ │ │ ├── _global.sass
│ │ │ ├── _masks.sass
│ │ │ ├── bootstrap
│ │ │ └── _functions.sass
│ │ │ ├── _waves.sass
│ │ │ ├── _typography.sass
│ │ │ ├── _mixins.sass
│ │ │ └── _variables.sass
│ ├── molecule
│ │ ├── productTile
│ │ │ ├── productTileTruncate.pug
│ │ │ ├── productTile.sass
│ │ │ └── productTile.pug
│ │ ├── productMedia
│ │ │ └── productMedia.pug
│ │ └── pagination
│ │ │ └── pagination.pug
│ ├── organism
│ │ ├── productList
│ │ │ ├── productList.sass
│ │ │ └── productList.pug
│ │ └── cart
│ │ │ └── cart.pug
│ ├── atom
│ │ ├── debug
│ │ │ └── debug.pug
│ │ ├── console
│ │ │ └── console.pug
│ │ ├── dropdown
│ │ │ └── dropdown.pug
│ │ └── price
│ │ │ ├── price.pug
│ │ │ └── price.sass
│ ├── template
│ │ └── base
│ │ │ ├── style.sass
│ │ │ ├── molecule
│ │ │ ├── head
│ │ │ │ └── head.pug
│ │ │ ├── categoryMenu
│ │ │ │ └── categoryMenu.pug
│ │ │ └── footer
│ │ │ │ └── footer.pug
│ │ │ └── base.pug
│ └── index.sass
├── postcss.config.js
└── package.json
├── .dockerignore
├── graphql
├── schema
│ ├── schema.graphql
│ ├── flamingo.me_flamingo-commerce_v3_price_interfaces_graphql-Service.graphql
│ ├── flamingo.me_flamingo-commerce_v3_category_interfaces_graphql-Service.graphql
│ ├── flamingo.me_flamingo-commerce_v3_customer_interfaces_graphql-Service.graphql
│ ├── flamingo.me_flamingo-commerce_v3_search_interfaces_graphql-Service.graphql
│ ├── flamingo.me_flamingo-commerce_v3_checkout_interfaces_graphql-Service.graphql
│ └── flamingo.me_flamingo-commerce_v3_product_interfaces_graphql-Service.graphql
├── emptymodule.go
└── module.go
├── config
├── config_dev.yml
├── routes.yml
├── magento2
│ ├── config.yml
│ └── de
│ │ └── config.yml
├── csv
│ ├── config.yml
│ └── de
│ │ └── config.yml
└── config.yml
├── preparetranslations.sh
├── docs
├── swagger.yaml
├── swagger.json
└── docs.go
├── .gitignore
├── Dockerfile
├── Makefile
├── main.go
├── Readme.md
└── go.mod
/resources/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/translations/merged/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/frontend/src/mock/_mockmap.js:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/translations/translated/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/frontend/src/page/error/error.sass:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/translations/merged/en-gb.untranslated.yaml:
--------------------------------------------------------------------------------
1 | {}
2 |
--------------------------------------------------------------------------------
/.dockerignore:
--------------------------------------------------------------------------------
1 | config/config_local.yml
2 | resources/products.zip
--------------------------------------------------------------------------------
/frontend/src/index.js:
--------------------------------------------------------------------------------
1 | import 'index.sass'
2 | //import 'page/checkout/checkout.js'
3 | import 'page/product/product.js'
--------------------------------------------------------------------------------
/frontend/src/asset/img/sample.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i-love-flamingo/commerce-demo-carotene/HEAD/frontend/src/asset/img/sample.jpg
--------------------------------------------------------------------------------
/graphql/schema/schema.graphql:
--------------------------------------------------------------------------------
1 | type Query { flamingo: String }
2 | type Mutation { flamingo: String }
3 | scalar Time
4 | scalar Map
5 | scalar Date
--------------------------------------------------------------------------------
/frontend/src/asset/img/overlays/01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i-love-flamingo/commerce-demo-carotene/HEAD/frontend/src/asset/img/overlays/01.png
--------------------------------------------------------------------------------
/frontend/src/asset/img/overlays/02.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i-love-flamingo/commerce-demo-carotene/HEAD/frontend/src/asset/img/overlays/02.png
--------------------------------------------------------------------------------
/frontend/src/asset/img/overlays/03.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i-love-flamingo/commerce-demo-carotene/HEAD/frontend/src/asset/img/overlays/03.png
--------------------------------------------------------------------------------
/frontend/src/asset/img/overlays/04.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i-love-flamingo/commerce-demo-carotene/HEAD/frontend/src/asset/img/overlays/04.png
--------------------------------------------------------------------------------
/frontend/src/asset/img/overlays/05.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i-love-flamingo/commerce-demo-carotene/HEAD/frontend/src/asset/img/overlays/05.png
--------------------------------------------------------------------------------
/frontend/src/asset/img/overlays/06.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i-love-flamingo/commerce-demo-carotene/HEAD/frontend/src/asset/img/overlays/06.png
--------------------------------------------------------------------------------
/frontend/src/asset/img/overlays/07.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i-love-flamingo/commerce-demo-carotene/HEAD/frontend/src/asset/img/overlays/07.png
--------------------------------------------------------------------------------
/frontend/src/asset/img/overlays/08.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i-love-flamingo/commerce-demo-carotene/HEAD/frontend/src/asset/img/overlays/08.png
--------------------------------------------------------------------------------
/frontend/src/asset/img/overlays/09.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i-love-flamingo/commerce-demo-carotene/HEAD/frontend/src/asset/img/overlays/09.png
--------------------------------------------------------------------------------
/config/config_dev.yml:
--------------------------------------------------------------------------------
1 | flamingo:
2 | session:
3 | cookie:
4 | secure: false
5 | debug:
6 | mode: true
7 | core:
8 | zap:
9 | loglevel: Debug
--------------------------------------------------------------------------------
/frontend/src/asset/font/roboto/Roboto-Bold.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i-love-flamingo/commerce-demo-carotene/HEAD/frontend/src/asset/font/roboto/Roboto-Bold.eot
--------------------------------------------------------------------------------
/frontend/src/asset/font/roboto/Roboto-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i-love-flamingo/commerce-demo-carotene/HEAD/frontend/src/asset/font/roboto/Roboto-Bold.ttf
--------------------------------------------------------------------------------
/frontend/src/asset/font/roboto/Roboto-Bold.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i-love-flamingo/commerce-demo-carotene/HEAD/frontend/src/asset/font/roboto/Roboto-Bold.woff
--------------------------------------------------------------------------------
/frontend/src/asset/font/roboto/Roboto-Light.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i-love-flamingo/commerce-demo-carotene/HEAD/frontend/src/asset/font/roboto/Roboto-Light.eot
--------------------------------------------------------------------------------
/frontend/src/asset/font/roboto/Roboto-Light.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i-love-flamingo/commerce-demo-carotene/HEAD/frontend/src/asset/font/roboto/Roboto-Light.ttf
--------------------------------------------------------------------------------
/frontend/src/asset/font/roboto/Roboto-Thin.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i-love-flamingo/commerce-demo-carotene/HEAD/frontend/src/asset/font/roboto/Roboto-Thin.eot
--------------------------------------------------------------------------------
/frontend/src/asset/font/roboto/Roboto-Thin.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i-love-flamingo/commerce-demo-carotene/HEAD/frontend/src/asset/font/roboto/Roboto-Thin.ttf
--------------------------------------------------------------------------------
/frontend/src/asset/font/roboto/Roboto-Thin.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i-love-flamingo/commerce-demo-carotene/HEAD/frontend/src/asset/font/roboto/Roboto-Thin.woff
--------------------------------------------------------------------------------
/frontend/src/asset/img/flamingo-logo-black.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i-love-flamingo/commerce-demo-carotene/HEAD/frontend/src/asset/img/flamingo-logo-black.png
--------------------------------------------------------------------------------
/frontend/src/asset/img/lightbox/preloader.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i-love-flamingo/commerce-demo-carotene/HEAD/frontend/src/asset/img/lightbox/preloader.gif
--------------------------------------------------------------------------------
/translations/src/de-de.home.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "id": "header.welcome.subtitle",
4 | "translation": "Standart demo shop mit carotene templates"
5 | }
6 | ]
7 |
--------------------------------------------------------------------------------
/frontend/src/asset/font/roboto/Roboto-Bold.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i-love-flamingo/commerce-demo-carotene/HEAD/frontend/src/asset/font/roboto/Roboto-Bold.woff2
--------------------------------------------------------------------------------
/frontend/src/asset/font/roboto/Roboto-Light.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i-love-flamingo/commerce-demo-carotene/HEAD/frontend/src/asset/font/roboto/Roboto-Light.woff
--------------------------------------------------------------------------------
/frontend/src/asset/font/roboto/Roboto-Light.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i-love-flamingo/commerce-demo-carotene/HEAD/frontend/src/asset/font/roboto/Roboto-Light.woff2
--------------------------------------------------------------------------------
/frontend/src/asset/font/roboto/Roboto-Medium.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i-love-flamingo/commerce-demo-carotene/HEAD/frontend/src/asset/font/roboto/Roboto-Medium.eot
--------------------------------------------------------------------------------
/frontend/src/asset/font/roboto/Roboto-Medium.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i-love-flamingo/commerce-demo-carotene/HEAD/frontend/src/asset/font/roboto/Roboto-Medium.ttf
--------------------------------------------------------------------------------
/frontend/src/asset/font/roboto/Roboto-Medium.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i-love-flamingo/commerce-demo-carotene/HEAD/frontend/src/asset/font/roboto/Roboto-Medium.woff
--------------------------------------------------------------------------------
/frontend/src/asset/font/roboto/Roboto-Regular.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i-love-flamingo/commerce-demo-carotene/HEAD/frontend/src/asset/font/roboto/Roboto-Regular.eot
--------------------------------------------------------------------------------
/frontend/src/asset/font/roboto/Roboto-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i-love-flamingo/commerce-demo-carotene/HEAD/frontend/src/asset/font/roboto/Roboto-Regular.ttf
--------------------------------------------------------------------------------
/frontend/src/asset/font/roboto/Roboto-Thin.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i-love-flamingo/commerce-demo-carotene/HEAD/frontend/src/asset/font/roboto/Roboto-Thin.woff2
--------------------------------------------------------------------------------
/frontend/src/asset/img/lightbox/default-skin.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i-love-flamingo/commerce-demo-carotene/HEAD/frontend/src/asset/img/lightbox/default-skin.png
--------------------------------------------------------------------------------
/translations/src/en-gb.home.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "id": "header.welcome.subtitle",
4 | "translation": "Standard demo shop with carotene templates"
5 | }
6 | ]
7 |
--------------------------------------------------------------------------------
/frontend/src/asset/font/roboto/Roboto-Medium.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i-love-flamingo/commerce-demo-carotene/HEAD/frontend/src/asset/font/roboto/Roboto-Medium.woff2
--------------------------------------------------------------------------------
/frontend/src/asset/font/roboto/Roboto-Regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i-love-flamingo/commerce-demo-carotene/HEAD/frontend/src/asset/font/roboto/Roboto-Regular.woff
--------------------------------------------------------------------------------
/frontend/src/asset/font/roboto/Roboto-Regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i-love-flamingo/commerce-demo-carotene/HEAD/frontend/src/asset/font/roboto/Roboto-Regular.woff2
--------------------------------------------------------------------------------
/frontend/src/asset/img/visuals/flamingo-scetch.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i-love-flamingo/commerce-demo-carotene/HEAD/frontend/src/asset/img/visuals/flamingo-scetch.jpg
--------------------------------------------------------------------------------
/frontend/src/asset/img/visuals/flamingo-600205_1280.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i-love-flamingo/commerce-demo-carotene/HEAD/frontend/src/asset/img/visuals/flamingo-600205_1280.jpg
--------------------------------------------------------------------------------
/config/routes.yml:
--------------------------------------------------------------------------------
1 | - path: /
2 | name: index
3 | controller: flamingo.render(tpl="home/home")
4 |
5 | - path: /offers
6 | name: index
7 | controller: flamingo.render(tpl="offers/offers")
--------------------------------------------------------------------------------
/frontend/src/asset/img/visuals/digital-art-3054735_1280.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i-love-flamingo/commerce-demo-carotene/HEAD/frontend/src/asset/img/visuals/digital-art-3054735_1280.jpg
--------------------------------------------------------------------------------
/frontend/src/base/style/mdp-ecom-base/free/_dropdowns.sass:
--------------------------------------------------------------------------------
1 | // Dropdowns
2 | .dropdown
3 | .dropdown-menu
4 | .dropdown-item
5 | &:active
6 | background-color: $grey-darken-1
7 |
--------------------------------------------------------------------------------
/frontend/src/molecule/productTile/productTileTruncate.pug:
--------------------------------------------------------------------------------
1 | mixin productTileTruncate(text, maxLength)
2 | if text.length > maxLength
3 | = text.slice(0, maxLength-1) + '…'
4 | else
5 | = text
6 |
--------------------------------------------------------------------------------
/frontend/src/organism/productList/productList.sass:
--------------------------------------------------------------------------------
1 | .productList
2 | .product-image
3 | max-height: 220px
4 | margin: auto
5 | margin-top: 10px
6 |
7 | .product-card
8 | min-height: 400px
--------------------------------------------------------------------------------
/preparetranslations.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | echo "Preparing merged file for common side.. (main)"
4 | go run github.com/nicksnyder/go-i18n/goi18n merge -sourceLanguage en-gb -format yaml -outdir translations/merged translations/src/*.json
5 |
--------------------------------------------------------------------------------
/frontend/src/page/home/home.sass:
--------------------------------------------------------------------------------
1 | .carousel
2 | height: 60vh
3 |
4 | @media (max-width: 740px)
5 | .carousel
6 | height: 100vh
7 |
8 | @media (min-width: 800px) and (max-width: 850px)
9 | .carousel
10 | height: 100vh
11 |
--------------------------------------------------------------------------------
/frontend/src/asset/img/svg/arrow_left.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/frontend/src/asset/img/svg/arrow_right.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/frontend/src/asset/i18n/en-gb.js:
--------------------------------------------------------------------------------
1 | /* this file is generated via the carotene-cli buildAssets task */
2 | import i18n from 'carotene/src/base/js/lib/i18n'
3 | const translations = require('../../../dist/asset/i18n/en-gb.json')
4 | i18n.setLocaleMessage('default', translations)
5 |
--------------------------------------------------------------------------------
/frontend/src/base/style/mdp-ecom-base/free/_msc.sass:
--------------------------------------------------------------------------------
1 | // Miscellaneous
2 | // Edge Headers
3 | .edge-header
4 | display: block
5 | height: $edge-header-height
6 | background-color: $edge-header-background-color
7 |
8 | .free-bird
9 | margin-top: $edge-header-margin-top
10 |
--------------------------------------------------------------------------------
/frontend/src/atom/debug/debug.pug:
--------------------------------------------------------------------------------
1 | mixin debug(obj, headline)
2 | if config('flamingo.debug.mode')
3 | - var title = 'Debug:'
4 | if headline
5 | - title= 'Debug: ' + headline
6 |
7 | .utilDebug
8 | h5.utilDebugTitle= title
9 | pre.utilDebugContents= debug(obj)
10 |
--------------------------------------------------------------------------------
/frontend/src/page/search/search.sass:
--------------------------------------------------------------------------------
1 | .wrapper
2 | display: flex
3 | width: 100%
4 | align-items: stretch
5 |
6 | #sidebar
7 | min-width: 250px
8 | max-width: 250px
9 |
10 |
11 | .category
12 | a.active
13 | background-color: #dafdff
14 | .level2-item
15 | padding: .25rem 1.5rem
--------------------------------------------------------------------------------
/docs/swagger.yaml:
--------------------------------------------------------------------------------
1 | basePath: /en
2 | info:
3 | contact:
4 | email: flamingo@aoe.com
5 | name: Flamingo
6 | url: https://gitter.im/i-love-flamingo/community#
7 | license:
8 | name: MIT
9 | title: Flamingo Commerce Demo Shop
10 | version: "1.0"
11 | paths: {}
12 | swagger: "2.0"
13 |
--------------------------------------------------------------------------------
/frontend/src/page/category/category.sass:
--------------------------------------------------------------------------------
1 | .wrapper
2 | display: flex
3 | width: 100%
4 | align-items: stretch
5 |
6 | #sidebar
7 | min-width: 250px
8 | max-width: 250px
9 |
10 |
11 | .category
12 | a.active
13 | background-color: #dafdff
14 | .level2-item
15 | padding: .25rem 1.5rem
--------------------------------------------------------------------------------
/frontend/src/atom/console/console.pug:
--------------------------------------------------------------------------------
1 | mixin console(obj, group)
2 | if config('debug.mode')
3 | if group
4 | script!= 'console.group("' + group + '")'
5 |
6 | - var output = debug(obj, true)
7 |
8 | script!= 'console.log(' + output + ')'
9 |
10 | if group
11 | script!= 'console.groupEnd()'
12 |
--------------------------------------------------------------------------------
/frontend/src/page/product/product.js:
--------------------------------------------------------------------------------
1 |
2 | jQuery(function () {
3 | jQuery("#variant-selector").change(function () {
4 | let url = jQuery("#variant-selector").children("option:selected").data('url')
5 | if (url !== undefined && url !== "") {
6 | window.location.href = url
7 | }
8 | });
9 | });
--------------------------------------------------------------------------------
/frontend/src/page/checkout/checkout.js:
--------------------------------------------------------------------------------
1 |
2 | jQuery(function () {
3 | jQuery("#useBillingAddress").change(function () {
4 | if (jQuery("#useBillingAddress").prop('checked')) {
5 | jQuery("#useBillingAddressToggle").collapse("hide")
6 | }
7 | jQuery("#useBillingAddressToggle").collapse("show")
8 | });
9 | });
--------------------------------------------------------------------------------
/frontend/src/page/checkout/emptycart.pug:
--------------------------------------------------------------------------------
1 | extends /template/base/base
2 | include /organism/cart/cart
3 |
4 | block maincontent
5 | main.mt-5.pt-4
6 | div.container.wow.fadeIn
7 | h2.my-5.h2.text-center Checkout
8 | h3 Your cart is empty
9 | a.btn.btn-primary.btn-md.my-0.p(href=url("index")) Back to home
10 |
11 |
--------------------------------------------------------------------------------
/frontend/src/page/error/503.pug:
--------------------------------------------------------------------------------
1 | extends /template/base/base
2 |
3 |
4 | block content
5 | .errorTile
6 | h1.errorHeadline= __('error.503.headline', 'Sorry, something has gone wrong…')
7 | a(href='/')= __('error.homeButton', 'Go to homepage')
8 |
9 | if config('debug.mode')
10 | .errorDebug
11 | .errorDebugTitle Debug:
12 | pre.errorDebugContent= error
13 |
--------------------------------------------------------------------------------
/frontend/src/page/error/withCode.pug:
--------------------------------------------------------------------------------
1 | extends /template/base/base
2 |
3 |
4 | block content
5 | .errorTile
6 | h1.errorHeadline= __('error.common.headline', 'Sorry, something went wrong')
7 | a(href='/')= __('error.homeButton', 'Go to homepage')
8 |
9 | if config('debug.mode')
10 | .errorDebug
11 | .errorDebugTitle Debug:
12 | pre.errorDebugContent= error
13 |
--------------------------------------------------------------------------------
/frontend/src/base/style/mdp-ecom-base/free/_footers.sass:
--------------------------------------------------------------------------------
1 | // Footers
2 | footer
3 | &.page-footer
4 | bottom: 0
5 | color: $white-base
6 |
7 | .container-fluid
8 | width: auto
9 |
10 | .footer-copyright
11 | overflow: hidden
12 | background-color: $footer-copyright-bg-color
13 | color: $footer-copyright-color
14 |
15 | a
16 | color: $white-base
17 |
--------------------------------------------------------------------------------
/translations/src/en-gb.common.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "id": "error.common.headline",
4 | "translation": "Error occured"
5 | },
6 | {
7 | "id": "error.homeButton",
8 | "translation": "Back to home"
9 | },
10 | {
11 | "id": "error.404.headline",
12 | "translation": "Error 404"
13 | },
14 | {
15 | "id": "error.503.headline",
16 | "translation": "Error 503"
17 | }
18 | ]
19 |
--------------------------------------------------------------------------------
/frontend/src/base/style/mdp-ecom-base/free/_badges.sass:
--------------------------------------------------------------------------------
1 | // Badges
2 | .badge
3 | box-shadow: $z-depth-1
4 | border-radius: $border-radius-base
5 | color: $white !important
6 |
7 | .badge-pill
8 | border-radius: $badge-pill-border-radius
9 | padding-right: $badge-pill-padding-x
10 | padding-left: $badge-pill-padding-x
11 |
12 | @each $name, $color in $basic-mdb-colors
13 | +make-badge($name, $color)
14 |
--------------------------------------------------------------------------------
/frontend/src/page/error/404.pug:
--------------------------------------------------------------------------------
1 | extends /template/base/base
2 |
3 |
4 | block content
5 | .errorTile
6 | h1.errorHeadline= __('error.404.headline', 'Sorry, we can\'t find that page or something has gone wrong…')
7 | a(href='/')= __('error.homeButton', 'Go to homepage')
8 |
9 |
10 | if config('debug.mode')
11 | .errorDebug
12 | .errorDebugTitle Debug:
13 | pre.errorDebugContent= error
14 |
--------------------------------------------------------------------------------
/graphql/emptymodule.go:
--------------------------------------------------------------------------------
1 | // Code generated by flamingo.me/graphql DO NOT EDIT!
2 | //go:build graphql
3 | // +build graphql
4 |
5 | package graphql
6 |
7 | import "flamingo.me/dingo"
8 |
9 | // this empty module is used by go generate to provide a dingo module because module.go is not compiled during generate
10 | type Module struct{}
11 |
12 | // Configure dummy method
13 | func (Module) Configure(injector *dingo.Injector) {}
14 |
--------------------------------------------------------------------------------
/config/magento2/config.yml:
--------------------------------------------------------------------------------
1 | flamingo:
2 | router:
3 | path: /magento
4 |
5 | commerce:
6 | category:
7 | useCategoryFixedAdapter: false
8 |
9 | flamingo-commerce-adapter-magento2:
10 | product:
11 | csvPath: "resources/magento/catalog_product.csv"
12 | magento2:
13 | #accessToken: REPLACEME
14 | #host: local.magento
15 | #scheme: http
16 | path: /rest/default
17 |
18 | flamingo-commerce-adapter-standalone:
19 | enableIndexing: true
--------------------------------------------------------------------------------
/docs/swagger.json:
--------------------------------------------------------------------------------
1 | {
2 | "swagger": "2.0",
3 | "info": {
4 | "title": "Flamingo Commerce Demo Shop",
5 | "contact": {
6 | "name": "Flamingo",
7 | "url": "https://gitter.im/i-love-flamingo/community#",
8 | "email": "flamingo@aoe.com"
9 | },
10 | "license": {
11 | "name": "MIT"
12 | },
13 | "version": "1.0"
14 | },
15 | "basePath": "/en",
16 | "paths": {}
17 | }
--------------------------------------------------------------------------------
/frontend/src/page/checkout/carterror.pug:
--------------------------------------------------------------------------------
1 | extends /template/base/base
2 | include /organism/cart/cart
3 |
4 |
5 | block maincontent
6 | main.mt-5.pt-4
7 | div.container.wow.fadeIn.content-minheight
8 | //-h2.my-5.h2.text-center Cart
9 | h3.d-flex.justify-content-between.align-items-center.mb-3.mt-4=__("Your cart")
10 | h4 Error: Something unexpected happend
11 | a.btn.btn-primary.btn-md.my-0.p(href=url("cart.view")) Proceed to cart
12 |
13 |
--------------------------------------------------------------------------------
/config/csv/config.yml:
--------------------------------------------------------------------------------
1 | flamingo:
2 | router:
3 | path: /en
4 |
5 | # Configure the modules flamingoCommerceAdapterStandalone
6 | flamingoCommerceAdapterStandalone:
7 | csvindexing:
8 | products:
9 | file:
10 | path: "resources/products/products_en.csv"
11 | delimiter: ","
12 | categories:
13 | file:
14 | path: "resources/products/categories.csv"
15 | delimiter: ","
16 | locale: "en_GB"
17 | currency: "GBP"
18 |
--------------------------------------------------------------------------------
/frontend/src/page/checkout/cart.pug:
--------------------------------------------------------------------------------
1 | extends /template/base/base
2 | include /organism/cart/cart
3 |
4 |
5 | block maincontent
6 | main.mt-5.pt-4
7 | div.container.wow.fadeIn.content-minheight
8 | //-h2.my-5.h2.text-center Cart
9 | h3.d-flex.justify-content-between.align-items-center.mb-3.mt-4=__("Your cart")
10 | +cart(decoratedCart,cartValidationResult,true)
11 | a.btn.btn-primary.btn-md.my-0.p(href=url("checkout.start")) Proceed to checkout
12 |
13 |
--------------------------------------------------------------------------------
/frontend/src/base/style/mdp-ecom-base/free/_depreciated.sass:
--------------------------------------------------------------------------------
1 | // These settings will be only for one version
2 |
3 | // Masks
4 | .view
5 | .full-bg-img
6 | height: 100%
7 |
8 | .full-bg-img,
9 | .full-bg-img video
10 | background-repeat: no-repeat
11 | background-position: center center
12 | background-size: cover
13 |
14 | // Full background
15 | .full-height,
16 | .full-height body,
17 | .full-height header,
18 | .full-height header .view
19 | height: 100%
20 |
--------------------------------------------------------------------------------
/translations/src/en-gb.productpage.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "id": "product.attribute.__group_packageSizes",
4 | "translation": "Package size"
5 | },
6 | {
7 | "id": "product.attribute.washingInstructions",
8 | "translation": "Washing Instruction"
9 | },
10 | {
11 | "id": "product.attribute.baseColor",
12 | "translation": "Base color"
13 | },
14 | {
15 | "id": "product.attribute.manufacturerColor",
16 | "translation": "Manufacturer color"
17 | }
18 | ]
19 |
--------------------------------------------------------------------------------
/frontend/src/base/style/mdp-ecom-base/free/_input-group.sass:
--------------------------------------------------------------------------------
1 | // Input group
2 | .md-form
3 | &.input-group
4 | label
5 | top: 0
6 | margin-bottom: 0
7 |
8 | .input-group-text
9 | background-color: $input-group-text-bgc
10 |
11 | &.md-addon
12 | border: none
13 | background-color: transparent
14 | font-weight: 500
15 |
16 | .form-control
17 | margin: 0
18 | padding: $input-group-form-control-py $input-group-form-control-px
19 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | orders
2 | frontend.zip
3 | flamingo-commerce-demo-carotene
4 | frontend/dist
5 | .DS_Store
6 | .cache
7 | .idea
8 | .gradle
9 | .sass-cache
10 | .temp
11 | node_modules
12 | npm-debug.log
13 | yarn-error.log
14 | src/sass/.includes
15 | coverage
16 | junit.xml
17 | /vendor
18 | /integration-test/shared
19 | context_local.yml
20 | resources/magento
21 | resources/magento.zip
22 | resources/products
23 | resources/products.zip
24 | **/logs/pact.log
25 | **/pacts/*.json
26 | config/config_local.yml
27 |
--------------------------------------------------------------------------------
/frontend/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: [
3 | require('mqpacker')({
4 | sort: true
5 | }),
6 | require('autoprefixer'),
7 | require('postcss-plugin-px2rem')({
8 | rootValue: 16,
9 | unitPrecision: 5,
10 | propWhiteList: [],
11 | propBlackList: [],
12 | selectorBlackList: [],
13 | ignoreIdentifier: false,
14 | replace: true,
15 | mediaQuery: false,
16 | minPixelValue: 0
17 | }),
18 | require('postcss-object-fit-images')
19 | ]
20 | }
21 |
--------------------------------------------------------------------------------
/frontend/src/base/style/mdp-ecom-base/free/_cards.sass:
--------------------------------------------------------------------------------
1 | // Cards
2 | .card
3 | box-shadow: $z-depth-1
4 | border: 0
5 | font-weight: 400
6 |
7 | &[class*="border"]
8 | border: 1px solid $grey-base
9 | box-shadow: none
10 |
11 | .card-body
12 | h1, h2, h3, h4, h5, h6
13 | font-weight: 400
14 |
15 | .card-title
16 | a
17 | transition: $md-card-link-transition
18 |
19 | &:hover
20 | transition: $md-card-link-transition
21 |
22 | .card-text
23 | color: $md-card-text-color
24 | font-size: $md-card-font-size
25 | font-weight: 400
26 |
--------------------------------------------------------------------------------
/frontend/src/page/offers/offers.pug:
--------------------------------------------------------------------------------
1 | extends /template/base/base
2 |
3 | include /organism/productList/productList
4 |
5 |
6 | block maincontent
7 | main.mt-5.pt-4
8 | .container
9 | h1=__("special-offers").setDefaultLabel("Special Offers")
10 | section.text-center.mb-4
11 | // Grid row
12 | //+productListByProductSearchResult(findProducts("homepagewidget",{"query":"","pageSize": "10","sortDirection":"A","sortBy":'name'},{"categories":['laptops']}))
13 | +productListByProductSearchResult(findProducts("homepagewidget",{"query":"","pageSize": "8","sortDirection":"A","sortBy":'name'},{}))
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM golang:alpine AS builder
2 | RUN apk update && apk add --no-cache ca-certificates tzdata && update-ca-certificates
3 |
4 | FROM scratch
5 | COPY --from=builder /usr/share/zoneinfo /usr/share/zoneinfo
6 | COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
7 |
8 | ADD frontend/dist /frontend/dist
9 | ADD frontend/src /frontend/src
10 | ADD flamingo-commerce-demo-carotene /flamingo-commerce-demo-carotene
11 | ADD config /config
12 | ADD translations /translations
13 | ADD resources /resources
14 | ADD docs/swagger.json /docs/swagger.json
15 |
16 | ENTRYPOINT ["/flamingo-commerce-demo-carotene"]
17 | CMD ["serve"]
18 |
--------------------------------------------------------------------------------
/frontend/src/base/style/mdp-ecom-base/free/_list-group.sass:
--------------------------------------------------------------------------------
1 | // List group
2 | .media
3 | .media-left
4 | padding: $list-group-padding
5 |
6 | img
7 | box-shadow: $z-depth-1
8 |
9 | .list-group
10 | .list-group-item
11 | &:first-child
12 | border-top-left-radius: $border-radius-base
13 | border-top-right-radius: $border-radius-base
14 |
15 | &:last-child
16 | border-bottom-left-radius: $border-radius-base
17 | border-bottom-right-radius: $border-radius-base
18 |
19 | a,
20 | button
21 | transition: $list-group-transition
22 |
23 | &:hover
24 | transition: $list-group-transition
25 |
--------------------------------------------------------------------------------
/config/magento2/de/config.yml:
--------------------------------------------------------------------------------
1 | flamingo:
2 | router:
3 | path: /magento/de
4 | core:
5 | locale:
6 | locale: de-de
7 | fallbackLocales:
8 | - en-gb
9 | translationFiles:
10 | - translations/merged/de-de.all.yaml
11 | - translations/merged/en-gb.all.yaml
12 | accounting:
13 | thousand: '.'
14 | decimal: ','
15 | formatZero: '-,- %s'
16 | format: "%v %s"
17 | numbers:
18 | decimal: '.'
19 | thousand: ','
20 | precision: 1
21 | date:
22 | dateFormat: 02 Jan 2006
23 | timeFormat: 15:04
24 | dateTimeFormat: 02 Jan 2006 15:04:05
25 | location: Europe/Berlin
--------------------------------------------------------------------------------
/frontend/src/molecule/productMedia/productMedia.pug:
--------------------------------------------------------------------------------
1 | mixin productMedia(mediaItem, size)
2 | if !size
3 | - var size = "200x"
4 |
5 | case mediaItem.type
6 | when 'image-external'
7 | img(src=mediaItem.reference alt=mediaItem.title)&attributes(attributes)
8 | when 'magento-product-image'
9 | img(src="http://local.magento/pub/media/catalog/product/"+mediaItem.reference alt=mediaItem.title)&attributes(attributes)
10 | when 'csvCommerceReference'
11 | img(src=url("csvcommerce.image.get", {
12 | "size": size,
13 | "filename": mediaItem.reference
14 | }) alt=mediaItem.title)&attributes(attributes)
15 |
16 |
--------------------------------------------------------------------------------
/frontend/src/page/checkout/success.pug:
--------------------------------------------------------------------------------
1 | extends /template/base/base
2 | include /organism/cart/cart
3 |
4 | block maincontent
5 | main.mt-5.pt-4
6 | div.container
7 | //+debug(decoratedCart.cart)
8 | h2.my-5.h2.text-center Checkout - Thank you
9 | div.row
10 | div.col-md-8.mb-4
11 | h4.d-flex.justify-content-between.align-items-center.mb-3
12 | span.text-muted Your order has been received
13 | div.card
14 | .card-body
15 |
16 | p We will send an email to #{email}
17 |
18 | each placedOrder in placedOrderInfos
19 | p Order number #{placedOrder.orderNumber}
--------------------------------------------------------------------------------
/frontend/src/template/base/style.sass:
--------------------------------------------------------------------------------
1 | // Template style
2 |
3 | /* Required height of parents of the Half Page Carousel for proper displaying carousel itself
4 | html,
5 | body,
6 | .view
7 | height: 100%
8 |
9 | /* Half Page Carousel itself
10 | .carousel
11 | height: 50%
12 |
13 | .carousel-inner
14 | height: 100%
15 |
16 | .carousel-item,
17 | .active
18 | height: 100%
19 |
20 | /* Adjustment for mobile devices
21 | @media (max-width: 776px)
22 | .carousel
23 | height: 100%
24 |
25 | /* Footer color for sake of consistency with Navbar
26 | .page-footer
27 | background-color: #929FBA
28 |
29 | .content-minheight
30 | min-height: 500px
31 |
32 | #content
33 | width: 100%
--------------------------------------------------------------------------------
/frontend/src/page/checkout/startcheckout.pug:
--------------------------------------------------------------------------------
1 | extends /template/base/base
2 | include /organism/cart/cart
3 |
4 | block maincontent
5 | main.mt-5.pt-4
6 | div.container.wow.fadeIn
7 | h2.my-5.h2.text-center Checkout
8 | div.row
9 | div.col-md-8.mb-4
10 | div.card
11 | div.row.p-5
12 | div.col-md-6.mb-4
13 | h2 Login
14 | p (here link to login - see flamingo.auth module)
15 | div.col-md-6.mb-4
16 | h2 Guest
17 | a.btn.btn-primary.btn-md.my-0.p(href=url("checkout")) Proceed as guest
18 | div.col-md-4.mb-4
19 | +cart(decoratedCart,cartValidationResult,false)
20 |
21 |
--------------------------------------------------------------------------------
/frontend/src/template/base/molecule/head/head.pug:
--------------------------------------------------------------------------------
1 | head
2 | meta(charset='utf-8')
3 | meta(name='viewport', content='width=device-width, initial-scale=1, shrink-to-fit=no')
4 | meta(http-equiv='x-ua-compatible', content='ie=edge')
5 | block title
6 | title= config('template.defaultTitle')
7 | block styles
8 |
9 | // Font Awesome
10 | link(rel='stylesheet', href='https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css')
11 | // Bootstrap core CSS
12 | link(rel="stylesheet", href=asset("asset/css/bootstrap.min.css"))
13 | //our build app.css
14 | link(rel="stylesheet", href=asset("css/main.css"))
15 |
16 | block js-vendor
17 | //script(src=asset("js/vendor.js"))
18 |
19 |
--------------------------------------------------------------------------------
/frontend/src/atom/dropdown/dropdown.pug:
--------------------------------------------------------------------------------
1 | //-
2 | param: cfg [Object] The config object
3 | {
4 | size: 'medium' | 'large'
5 | emptyOption: true | false
6 | }
7 |
8 | mixin dropdown(cfg)
9 | -
10 | cfg = cfg || {}
11 | cfg.size = cfg.size || 'medium'
12 |
13 | if (Object.keys(cfg).indexOf('emptyOption') > -1)
14 | cfg.emptyOption = cfg.emptyOption
15 | else
16 | cfg.emptyOption = true
17 |
18 | var sizeClass = 'dropdownSize' + cfg.size.charAt(0).toUpperCase() + cfg.size.slice(1)
19 |
20 | .dropdownWrapper(class=sizeClass)
21 | select&attributes(attributes)
22 | if cfg.emptyOption
23 | option(value='')= __('Please select')
24 | if block
25 | block
26 |
--------------------------------------------------------------------------------
/config/csv/de/config.yml:
--------------------------------------------------------------------------------
1 | flamingo:
2 | router:
3 | path: /de
4 | core:
5 | locale:
6 | locale: de-de
7 | fallbackLocales:
8 | - en-gb
9 | translationFiles:
10 | - translations/merged/de-de.all.yaml
11 | - translations/merged/en-gb.all.yaml
12 | numbers:
13 | decimal: ','
14 | thousand: '.'
15 | precision: 1
16 | date:
17 | dateFormat: 02 Jan 2006
18 | timeFormat: 15:04
19 | dateTimeFormat: 02 Jan 2006 15:04:05
20 | location: Europe/Berlin
21 |
22 | # Configure the module flamingo-commerce-adapter-standalone
23 | flamingoCommerceAdapterStandalone:
24 | csvindexing:
25 | products:
26 | file:
27 | path: "resources/products/products_de.csv"
28 | delimiter: ","
29 | locale: "de_DE"
30 | currency: "EUR"
--------------------------------------------------------------------------------
/graphql/schema/flamingo.me_flamingo-commerce_v3_price_interfaces_graphql-Service.graphql:
--------------------------------------------------------------------------------
1 | type Commerce_Price{
2 | amount: Float
3 | currency: String!
4 | }
5 |
6 | type Commerce_Price_Charge {
7 | price: Commerce_Price!
8 | value: Commerce_Price!
9 | type: String!
10 | reference: String!
11 | }
12 |
13 | type Commerce_Price_ChargeQualifier {
14 | type: String!
15 | reference: String!
16 | }
17 |
18 | input Commerce_Price_ChargeQualifierInput {
19 | type: String!
20 | reference: String!
21 | }
22 |
23 | type Commerce_Price_Charges {
24 | items: [Commerce_Price_Charge!]
25 | hasType(ctype: String): Boolean
26 | hasChargeQualifier(qualifier: Commerce_Price_ChargeQualifierInput!): Boolean
27 | getByChargeQualifierForced(qualifier: Commerce_Price_ChargeQualifierInput!): Commerce_Price_Charge
28 | getByTypeForced(ctype: String): Commerce_Price_Charge
29 | }
--------------------------------------------------------------------------------
/frontend/src/index.sass:
--------------------------------------------------------------------------------
1 | @import 'base/style/mdp-ecom-base/core/bootstrap/functions.sass'
2 | @import 'base/style/mdp-ecom-base/core/bootstrap/variables.sass'
3 |
4 | @import 'base/style/mdp-ecom-base/core/mixins.sass'
5 | @import 'base/style/mdp-ecom-base/core/colors.sass'
6 | @import 'base/style/mdp-ecom-base/core/variables.sass'
7 | @import 'base/style/mdp-ecom-base/core/global.sass'
8 | @import 'base/style/mdp-ecom-base/core/helpers.sass'
9 | @import 'base/style/mdp-ecom-base/core/typography.sass'
10 | @import 'base/style/mdp-ecom-base/core/masks.sass'
11 | @import 'base/style/mdp-ecom-base/core/waves.sass'
12 |
13 | @import 'base/style/mdp-ecom-base/free/*.sass'
14 |
15 |
16 |
17 | // Import all sass files via glob
18 | // sass-lint:disable clean-import-paths
19 | //@import 'atom/**/*.sass'
20 | //@import 'molecule/**/*.sass'
21 | @import 'organism/**/*.sass'
22 | @import 'template/**/*.sass'
23 | @import 'page/**/*.sass'
24 | // sass-lint:enable clean-import-paths
--------------------------------------------------------------------------------
/frontend/src/page/checkout/checkout.pug:
--------------------------------------------------------------------------------
1 | extends /template/base/base
2 | include /organism/cart/cart
3 |
4 | block maincontent
5 | main.mt-5.pt-4
6 | div.container
7 | h2.my-5.h2.text-center Checkout
8 | if errorInfos
9 | if errorInfos.hasError
10 | if errorInfos.hasPaymentError
11 | div.alert.alert-error(role="alert") Payment Error
12 | div.alert.alert-warning(role="alert")=errorInfos.errorMessage
13 | div.row
14 | div.col-md-8.mb-4
15 | include /page/checkout/organism/checkoutform.pug
16 | div.col-md-4.mb-4
17 | if cartValidationResult
18 | if cartValidationResult.hasCommonError
19 | div.alert.alert-warning(role="alert")=cartValidationResult.commonErrorMessageKey
20 | each itemResult in cartValidationResult.itemResults
21 | div.alert.alert-warning(role="alert")=itemResult.errorMessageKey
22 | +cart(decoratedCart,cartValidationResult,false)
23 |
24 |
--------------------------------------------------------------------------------
/frontend/src/template/base/molecule/categoryMenu/categoryMenu.pug:
--------------------------------------------------------------------------------
1 | ul.navbar-nav.mr-auto
2 | - var rootTreeNode = data("category.tree",{'code': ''})
3 | li.nav-item.active
4 | a.nav-link.waves-effect(href='/')
5 | | Home
6 | span.sr-only (current)
7 | for treeNode in rootTreeNode.subTrees
8 | - var categoryUrl = url('category.view', {code: treeNode.code,name: treeNode.name})
9 | if treeNode.hasChilds
10 | li.nav-item.dropdown
11 | a(href="#", id="navbarDropdown", role="button",data-toggle="dropdown", aria-haspopup="true", aria-expanded="false").nav-link.dropdown-toggle=treeNode.name
12 | div(aria-labelledby="navbarDropdown").dropdown-menu.waves-effect
13 | for subTreeNode in treeNode.subTrees
14 | - var categoryUrl = url('category.view', {code: subTreeNode.code,name: subTreeNode.name})
15 | a.dropdown-item(href=categoryUrl)=subTreeNode.name
16 | else
17 | li.nav-item
18 | a(href=categoryUrl).nav-link=treeNode.name
--------------------------------------------------------------------------------
/frontend/src/base/style/mdp-ecom-base/core/_helpers.sass:
--------------------------------------------------------------------------------
1 | // Helpers
2 | // MDB helpers
3 | .img-fluid,
4 | .video-fluid
5 | max-width: 100%
6 | height: auto
7 |
8 | .flex-center
9 | display: flex
10 | justify-content: center
11 | align-items: center
12 | height: 100%
13 |
14 | p
15 | margin: 0
16 |
17 | ul
18 | text-align: center
19 |
20 | li
21 | margin-bottom: $flex-center-ul-mb
22 |
23 | &:last-of-type
24 | margin-bottom: 0
25 |
26 | .hr-light
27 | border-top: 1px solid $hr-light
28 |
29 | .hr-dark
30 | border-top: 1px solid $hr-dark
31 |
32 | // Responsive width
33 | .w-responsive
34 | width: 75%
35 |
36 | @media (max-width: 740px)
37 | width: 100%
38 |
39 | // Collapsible body
40 | .collapsible-body
41 | display: none
42 |
43 | .jumbotron
44 | box-shadow: $z-depth-1
45 | border-radius: $border-radius-base
46 | background-color: $white-base
47 |
48 | @each $name, $color in $basic-mdb-colors
49 | +bg-variant(".bg-#{$name}", $color)
50 |
51 | .border-#{$name}
52 | border-color: $color !important
53 |
--------------------------------------------------------------------------------
/frontend/src/base/style/mdp-ecom-base/free/_tables.sass:
--------------------------------------------------------------------------------
1 | // Tables
2 | table
3 | th
4 | font-size: $table-th-font-size
5 | font-weight: 400
6 |
7 | td
8 | font-size: $table-td-font-size
9 | font-weight: 300
10 |
11 | &.table
12 | thead th
13 | border-top: none
14 |
15 | th,
16 | td
17 | padding-top: $table-th-padding-top
18 | padding-bottom: $table-td-padding-bottom
19 |
20 | a
21 | margin: 0
22 | color: $table-a-color
23 |
24 | .label-table
25 | margin: 0
26 | padding: 0
27 | line-height: 15px
28 | height: 15px
29 |
30 | &.btn-table
31 | td
32 | vertical-align: middle
33 |
34 | &.table-hover
35 | tbody
36 | tr
37 | &:hover
38 | transition: $table-hover-transition
39 | background-color: $table-hover-background-color
40 |
41 | .th-lg
42 | min-width: 9rem
43 |
44 | .th-sm
45 | min-width: 6rem
46 |
47 | &.table-sm
48 | th,
49 | td
50 | padding-top: $table-sm-padding-y
51 | padding-bottom: $table-sm-padding-y
52 |
--------------------------------------------------------------------------------
/frontend/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "flamingo-commerce-demo-theme",
3 | "version": "1.2.0",
4 | "main": "postcss.config.js",
5 | "scripts": {
6 | "build": "rm -rf dist && rm -rf .cache && npx fc build",
7 | "dev": "npx fc dev",
8 | "test": "echo \"Error: no test specified\" && exit 1"
9 | },
10 | "author": "",
11 | "license": "ISC",
12 | "dependencies": {
13 | "@babel/core": "^7.23.0",
14 | "@babel/preset-env": "^7.22.20",
15 | "autoprefixer": "^10.4.16",
16 | "fast-sass-loader": "^2.0.1",
17 | "flamingo-carotene-core": "^9.0.0-alpha.13",
18 | "flamingo-carotene-dev-server": "^9.0.0-alpha.13",
19 | "flamingo-carotene-postcss": "^8.1.0",
20 | "flamingo-carotene-pug": "^9.0.0-alpha.13",
21 | "flamingo-carotene-static-asset": "^9.0.0-alpha.13",
22 | "flamingo-carotene-webpack": "^9.0.0-alpha.13",
23 | "mqpacker": "^7.0.0",
24 | "node-sass-glob-importer": "^3.0.2",
25 | "postcss-object-fit-images": "^1.1.2",
26 | "postcss-plugin-px2rem": "^0.8.1"
27 | },
28 | "devDependencies": {
29 | "sass": "^1.69.1",
30 | "sass-loader": "^13.3.2",
31 | "webpack": "^5.88.2"
32 | },
33 | "description": ""
34 | }
35 |
--------------------------------------------------------------------------------
/frontend/src/molecule/pagination/pagination.pug:
--------------------------------------------------------------------------------
1 | include /atom/debug/debug
2 |
3 | mixin pagination(paginationInfo)
4 | if paginationInfo && paginationInfo.totalHits && paginationInfo.totalHits > 0
5 | nav.d-flex.justify-content-center.wow.fadeIn
6 | ul.pagination.pg-blue
7 | if paginationInfo.previousPage
8 | li.page-item
9 | a.page-link(href=paginationInfo.previousPage.uRL, aria-label='Previous')
10 | span(aria-hidden='true') «
11 | span.sr-only Previous
12 | if paginationInfo.pageNavigation.length > 1
13 | each page in paginationInfo.pageNavigation
14 | if page.isSpacer
15 | li.page-item ...
16 | else
17 | if page.isActive
18 | li.page-item.active
19 | a.page-link(href=page.uRL)=page.page
20 | else
21 | li.page-item
22 | a.page-link(href=page.uRL)=page.page
23 | if paginationInfo.nextPage
24 | li.page-item
25 | a.page-link(href=paginationInfo.nextPage.uRL, aria-label='Next')
26 | span(aria-hidden='true') »
27 | span.sr-only Next
28 |
--------------------------------------------------------------------------------
/frontend/src/base/style/mdp-ecom-base/core/_global.sass:
--------------------------------------------------------------------------------
1 | // Globals
2 | // Shadows
3 | .z-depth-0
4 | box-shadow: none !important
5 |
6 | .z-depth-1
7 | box-shadow: $z-depth-1
8 |
9 | .z-depth-1-half
10 | box-shadow: $z-depth-1-half
11 |
12 | .z-depth-2
13 | box-shadow: $z-depth-2
14 |
15 | .z-depth-3
16 | box-shadow: $z-depth-3
17 |
18 | .z-depth-4
19 | box-shadow: $z-depth-4
20 |
21 | .z-depth-5
22 | box-shadow: $z-depth-5
23 |
24 | // Shadow on hover
25 | .hoverable
26 | box-shadow: none
27 | transition: $transition-hoverable
28 |
29 | &:hover
30 | box-shadow: $z-depth-2
31 | transition: $transition-hoverable
32 |
33 | // Disabled cursor
34 | .disabled,
35 | a:disabled
36 | pointer-events: none !important
37 |
38 | // Links
39 | a
40 | cursor: pointer
41 | text-decoration: none
42 | color: $link-color
43 | transition: $transition-basic
44 |
45 | &:hover
46 | transition: $transition-basic
47 | text-decoration: none
48 |
49 | &.disabled,
50 | &:disabled
51 | &:hover
52 | color: $link-color
53 |
54 | a:not([href]):not([tabindex]), a:not([href]):not([tabindex]):focus, a:not([href]):not([tabindex]):hover
55 | color: inherit
56 | text-decoration: none
57 |
--------------------------------------------------------------------------------
/translations/src/en-gb.checkout.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "id": "checkout.success_message1",
4 | "translation": "Your order has been received. Your order number is: {{.OrderId}}"
5 | },
6 |
7 | {
8 | "id": "checkout.success_message2",
9 | "translation": "An confirmation email will be send to {{.Email}}."
10 | },
11 |
12 | {
13 | "id": "checkout.cart_item_error_hint",
14 | "translation": "There are invalid items in your cart. Please check below and resolve the issue."
15 | },
16 |
17 | {
18 | "id": "checkout.back_to_cart",
19 | "translation": "Back to cart"
20 | },
21 |
22 | {
23 | "id": "checkout.no_items_in_cart",
24 | "translation": "No Items in your cart"
25 | },
26 |
27 | {
28 | "id":"checkout.legalConfirmation.termsAndConditions",
29 | "translation": "Check here to indicate that you have read and agree to the privacy policies and terms and conditions of the Heathrow Boutique."
30 | },
31 |
32 | {
33 | "id":"checkout.error.terms_and_conditions_required",
34 | "translation": "Please accept the terms and conditions."
35 | }
36 | ]
37 |
--------------------------------------------------------------------------------
/frontend/src/atom/price/price.pug:
--------------------------------------------------------------------------------
1 |
2 | mixin price(product)
3 | case product.type()
4 | when 'simple'
5 | - var baseData = product.baseData
6 | - var saleableProductData = product.saleableData
7 | when 'configurable'
8 | - var baseData = product.baseData
9 | - var saleableProductData = false
10 | when 'configurable_with_activevariant'
11 | - var baseData = product.activeVariant.baseData
12 | - var saleableProductData = product.activeVariant.saleableData
13 | default
14 | - throw 'No proper productType given'
15 |
16 | if saleableProductData
17 | - var priceInfo = saleableProductData.activePrice
18 | if priceInfo.isDiscounted
19 | span.mr-1
20 | del=commercePriceFormat(priceInfo.default)
21 | span=commercePriceFormat(priceInfo.discounted)
22 | else
23 | span=commercePriceFormat(priceInfo.default)
24 | else
25 | span
26 | p Select a Variant to see the price
27 |
28 | mixin teaserPrice(product)
29 | - var priceInfo = product.teaser.teaserPrice
30 | if priceInfo.isDiscounted
31 | span.mr-1
32 | del=commercePriceFormat(priceInfo.default)
33 | span=commercePriceFormat(priceInfo.discounted)
34 | else
35 | span=commercePriceFormat(priceInfo.default)
--------------------------------------------------------------------------------
/docs/docs.go:
--------------------------------------------------------------------------------
1 | // Package docs Code generated by swaggo/swag. DO NOT EDIT
2 | package docs
3 |
4 | import "github.com/swaggo/swag"
5 |
6 | const docTemplate = `{
7 | "schemes": {{ marshal .Schemes }},
8 | "swagger": "2.0",
9 | "info": {
10 | "description": "{{escape .Description}}",
11 | "title": "{{.Title}}",
12 | "contact": {
13 | "name": "Flamingo",
14 | "url": "https://gitter.im/i-love-flamingo/community#",
15 | "email": "flamingo@aoe.com"
16 | },
17 | "license": {
18 | "name": "MIT"
19 | },
20 | "version": "{{.Version}}"
21 | },
22 | "host": "{{.Host}}",
23 | "basePath": "{{.BasePath}}",
24 | "paths": {}
25 | }`
26 |
27 | // SwaggerInfo holds exported Swagger Info so clients can modify it
28 | var SwaggerInfo = &swag.Spec{
29 | Version: "1.0",
30 | Host: "",
31 | BasePath: "/en",
32 | Schemes: []string{},
33 | Title: "Flamingo Commerce Demo Shop",
34 | Description: "",
35 | InfoInstanceName: "swagger",
36 | SwaggerTemplate: docTemplate,
37 | LeftDelim: "{{",
38 | RightDelim: "}}",
39 | }
40 |
41 | func init() {
42 | swag.Register(SwaggerInfo.InstanceName(), SwaggerInfo)
43 | }
44 |
--------------------------------------------------------------------------------
/frontend/src/base/style/mdp-ecom-base/core/_masks.sass:
--------------------------------------------------------------------------------
1 | // Masks
2 | // General properties
3 | .view
4 | position: relative
5 | overflow: hidden
6 | cursor: default
7 |
8 | .mask
9 | position: absolute
10 | top: 0
11 | overflow: hidden
12 | width: 100%
13 | height: 100%
14 | background-attachment: fixed
15 |
16 | img, video
17 | position: relative
18 | display: block
19 |
20 | video
21 | &.video-intro
22 | z-index: -100
23 | top: 50%
24 | left: 50%
25 | transform: $intro-video-transform
26 | transition: $intro-video-transition opacity
27 | min-width: 100%
28 | min-height: 100%
29 | width: auto
30 | height: auto
31 |
32 | // Overlay
33 | .overlay
34 | .mask
35 | opacity: 0
36 | transition: $mask-overlay-transition
37 |
38 | &:hover
39 | opacity: 1
40 |
41 | // Zoom
42 | .zoom
43 | img, video
44 | transition: $mask-zoom-transition
45 |
46 | &:hover
47 | img, video
48 | transform: $mask-zoom-transform
49 |
50 | // Patterns
51 | $patterns: (1: "01", 2: "02", 3: "03", 4: "04", 5: "05", 6: "06", 7: "07", 8: "08", 9: "09")
52 |
53 | @each $no, $filename in $patterns
54 | .pattern-#{$no}
55 | background: url("#{$image-path}/overlays/#{$filename}.png")
56 |
--------------------------------------------------------------------------------
/translations/Readme.md:
--------------------------------------------------------------------------------
1 | # Translation structure:
2 |
3 | * src:
4 | * This is the folder where developer add the labels and a best guess for the translation.
5 | * Files should be splitted nicely (e.g. per module) - so that we can also reuse them over projects
6 |
7 | * merged:
8 | * This contains the "src/*.json" files merged to *.all.yaml and *.untranslated.yaml
9 | * The complete folder can be given to external translation
10 | * The files here are build on build time
11 | * Local you can run `./preparetranslations.sh` (requires *goi18n*)
12 |
13 |
14 | * translated:
15 | * This contains the files that came back from external translation. (They are loaded after "merged")
16 |
17 | # Troubleshooting
18 | * `./preparetranslations.sh: line 4: goi18n: command not found`
19 |
20 | __Solution__: Install *goi18n* by executing `go get -u github.com/nicksnyder/go-i18n/goi18n`
21 |
22 | * If `go get -u github.com/nicksnyder/go-i18n/goi18n` results in following error:
23 |
24 | `package github.com/nicksnyder/go-i18n/goi18n: directory "/Users/patrick.schaper/.virtualgo/flamingo/src/github.com/nicksnyder/go-i18n/goi18n" is not using a known version control system`
25 |
26 | __Solution__: `rm -rf PATH_TO/.virtualgo/flamingo/src/github.com/nicksnyder/go-i18n/` and retry installation of *goi18n*
27 |
28 |
--------------------------------------------------------------------------------
/frontend/src/base/style/mdp-ecom-base/free/_carousels.sass:
--------------------------------------------------------------------------------
1 | // Carousels
2 | .carousel
3 | .carousel-control-prev-icon,
4 | .carousel-control-next-icon
5 | width: $carousel-control-icon-width
6 | height: $carousel-control-icon-height
7 |
8 | .carousel-control-prev-icon
9 | background-image: $carousel-control-prev-icon
10 |
11 | .carousel-control-next-icon
12 | background-image: $carousel-control-next-icon
13 |
14 | .carousel-indicators
15 | li
16 | width: $carousel-indicators-width
17 | height: $carousel-indicators-height
18 | border-radius: $carousel-indicators-border-radius
19 | cursor: pointer
20 |
21 | .carousel-fade
22 | .carousel-item
23 | opacity: 0
24 | transition-duration: $carousel-transition-duration
25 | transition-property: opacity
26 |
27 | .carousel-item.active,
28 | .carousel-item-next.carousel-item-left,
29 | .carousel-item-prev.carousel-item-right
30 | opacity: 1
31 |
32 | .carousel-item-left,
33 | .carousel-item-right
34 | &.active
35 | opacity: 0
36 |
37 | .carousel-item-next,
38 | .carousel-item-prev,
39 | .carousel-item.active,
40 | .carousel-item-left.active,
41 | .carousel-item-prev.active
42 | transform: $carousel-item-transform
43 |
44 | @supports (transform-style: preserve-3d)
45 | transform: $carousel-item-transform-2
46 |
--------------------------------------------------------------------------------
/frontend/src/organism/productList/productList.pug:
--------------------------------------------------------------------------------
1 | include /molecule/productMedia/productMedia
2 | include /molecule/pagination/pagination
3 | include /atom/price/price
4 | include /atom/debug/debug
5 |
6 | mixin productList(products, paginationInfo)
7 | //+debug(productSearchResult)
8 | .row.wow.fadeIn.productList
9 | // Grid column
10 | each product in products
11 | //+debug(product)
12 | .col-lg-3.col-md-6.mb-4
13 | // Card
14 | .card.product-card
15 | // Card image
16 | .view.overlay
17 | +productMedia(product.baseData.getListMedia,"200x").product-image
18 | a(href=getProductUrl(product))
19 | .mask.rgba-white-slight
20 | // Card image
21 | // Card content
22 | .card-body.text-center
23 | // Category & Title
24 | a.grey-text(href=getProductUrl(product))
25 | h5=product.baseData.title
26 | h5
27 | strong
28 | a.dark-grey-text(href=getProductUrl(product))
29 | span.badge.badge-pill.danger-color NEW
30 | span.badge.badge-pill.primary-color=product.type()
31 | h4.font-weight-bold.blue-text
32 | +teaserPrice(product)
33 | +pagination(paginationInfo)
34 |
35 |
36 | mixin productListByProductSearchResult(productSearchResult)
37 | +productList(productSearchResult.products, productSearchResult.paginationInfo)
--------------------------------------------------------------------------------
/frontend/src/molecule/productTile/productTile.sass:
--------------------------------------------------------------------------------
1 | $productTileBorderRadius: 6px
2 |
3 | .productTile
4 | +hover
5 | &::before
6 | box-shadow: 1px 1px 7px 0 $colorBlackShadowLight2
7 |
8 | text-align: center
9 | position: relative
10 | display: flex
11 | justify-content: flex-start
12 | flex-direction: column
13 | flex-wrap: nowrap
14 | padding: 5px
15 |
16 | &::before
17 | content: ''
18 | position: absolute
19 | width: 100%
20 | height: 100%
21 | background-color: $colorWhite
22 | border-radius: $productTileBorderRadius
23 | transition: box-shadow .3s ease-out
24 | top: 0
25 | left: 0
26 |
27 | > *
28 | z-index: 1
29 |
30 | .productTileFigure
31 | margin-bottom: 5px
32 | position: relative
33 | display: block
34 | border-radius: $productTileBorderRadius
35 |
36 | &::before
37 | content: ''
38 | display: block
39 | position: relative
40 | padding-top: 100%
41 |
42 |
43 | .productTileImage
44 | position: absolute
45 | left: 0
46 | top: 0
47 | width: 100%
48 | height: 100%
49 | object-fit: contain
50 | border-radius: $productTileBorderRadius
51 |
52 | .productTileBrand
53 | margin-bottom: 5px
54 | font-size: 12px
55 | line-height: 22px
56 | flex-shrink: 0
57 | font-weight: bold
58 |
59 | .productTileTitle
60 | margin-bottom: 20px
61 | font-size: 14px
62 | line-height: 22px
63 | flex-shrink: 0
64 |
65 | .productTilePrice
66 | margin-top: auto
67 | margin-bottom: 5px
68 |
--------------------------------------------------------------------------------
/frontend/src/asset/img/lightbox/default-skin.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/frontend/src/page/category/category.pug:
--------------------------------------------------------------------------------
1 | extends /template/base/base
2 |
3 | include /organism/productList/productList
4 |
5 | block maincontent
6 | main.mt-5.p-4.dark-grey-text.category
7 | h2.mt-4.mb-4.h2.text-center=category.name
8 | .row
9 | nav.col-md-3.order-md-first
10 | //+debug(categoryTree)
11 | if categoryTree.subTrees
12 | button.d-block.d-md-none.btn.btn-primary.btn-block.mb-3(type="button" data-toggle="collapse" data-target="#filters") Subcategories ▾
13 | div.collapse.d-md-block(id="filters")
14 | ul.navbar-nav.mr-auto
15 | for treeNode in categoryTree.subTrees
16 | - var className= ""
17 | if treeNode.active
18 | - var className= "active"
19 | - var categoryUrl = url('category.view', {code: treeNode.code,name: treeNode.name})
20 | //- level 1
21 | li
22 | a(href=url("category.view",{code:treeNode.code, name:treeNode.name}) class=className)=treeNode.name
23 | if treeNode.hasChilds
24 | ul
25 | for subTreeNode in treeNode.subTrees
26 | - var className= ""
27 | if treeNode.active
28 | - var className= "active"
29 | //- level 2
30 | li
31 | - var categoryUrl = url('category.view', {code: subTreeNode.code,name: subTreeNode.name})
32 | a.level2-item(href=categoryUrl class=className)=subTreeNode.name
33 | div.col-md-9.order-md-last(id="")
34 | +productList(productSearchResult.products, productSearchResult.paginationInfo)
35 | //+debug(productSearchResult)
36 | //+debug(categoryTree)
--------------------------------------------------------------------------------
/graphql/schema/flamingo.me_flamingo-commerce_v3_category_interfaces_graphql-Service.graphql:
--------------------------------------------------------------------------------
1 | type Commerce_Category_Attributes {
2 | get(code: String!): Commerce_Category_Attribute
3 | has(code: String!): Boolean
4 | all: [Commerce_Category_Attribute!]
5 | }
6 |
7 | type Commerce_Category_Attribute {
8 | code: String!
9 | label: String!
10 | values: [Commerce_Category_AttributeValue!]
11 | }
12 |
13 | type Commerce_Category_AttributeValue {
14 | value: String!
15 | label: String!
16 | }
17 |
18 | interface Commerce_Category {
19 | code: String!
20 | name: String!
21 | path: String!
22 | active: Boolean!
23 | promoted: Boolean!
24 | attributes: Commerce_Category_Attributes!
25 | }
26 |
27 | type Commerce_CategoryData implements Commerce_Category {
28 | code: String!
29 | name: String!
30 | path: String!
31 | active: Boolean!
32 | promoted: Boolean!
33 | attributes: Commerce_Category_Attributes!
34 | }
35 |
36 | interface Commerce_Tree {
37 | code: String!
38 | name: String!
39 | path: String!
40 | active: Boolean!
41 | subTrees: [Commerce_Tree]
42 | hasChilds: Boolean!
43 | documentCount: Int!
44 | }
45 |
46 | type Commerce_CategoryTree implements Commerce_Tree{
47 | code: String!
48 | name: String!
49 | path: String!
50 | active: Boolean!
51 | subTrees: [Commerce_Tree]
52 | hasChilds: Boolean!
53 | documentCount: Int!
54 | }
55 |
56 | type Commerce_Category_SearchResult {
57 | category: Commerce_Category!
58 | productSearchResult: Commerce_Product_SearchResult!
59 | }
60 |
61 | extend type Query {
62 | Commerce_CategoryTree(activeCategoryCode: String!): Commerce_Tree!
63 | Commerce_Category(categoryCode: String!, categorySearchRequest: Commerce_Search_Request): Commerce_Category_SearchResult
64 | }
65 |
--------------------------------------------------------------------------------
/frontend/src/page/home/home.pug:
--------------------------------------------------------------------------------
1 | extends /template/base/base
2 |
3 | include /organism/productList/productList
4 |
5 | block precontent
6 | include /page/home/molecule/carousel/carousel
7 |
8 | block maincontent
9 | main
10 | .container
11 | // Sub-Navbar for findProducts (TODO)
12 | //nav.navbar.navbar-expand-lg.navbar-dark.mdb-color.lighten-3.mt-3.mb-5
13 | // Navbar brand
14 | span.navbar-brand Categories:
15 | // Collapse button
16 | button.navbar-toggler(type='button', data-toggle='collapse', data-target='#basicExampleNav', aria-controls='basicExampleNav', aria-expanded='false', aria-label='Toggle navigation')
17 | span.navbar-toggler-icon
18 | // Collapsible content
19 | #basicExampleNav.collapse.navbar-collapse
20 | // Links
21 | ul.navbar-nav.mr-auto
22 | li.nav-item.active
23 | a.nav-link(href='#')
24 | | All
25 | span.sr-only (current)
26 | li.nav-item
27 | a.nav-link(href='#') Shirts
28 | li.nav-item
29 | a.nav-link(href='#') Sport wears
30 | li.nav-item
31 | a.nav-link(href='#') Outwears
32 | // Links
33 | form.form-inline
34 | .md-form.my-0
35 | input.form-control.mr-sm-2(type='text', placeholder='Search', aria-label='Search')
36 | // Collapsible content
37 | // /.Navbar
38 | // Section: Products v.3
39 | section.text-center.mb-4
40 | // Grid row
41 | //+productListByProductSearchResult(findProducts("homepagewidget",{"query":"","pageSize": "10","sortDirection":"A","sortBy":'name'},{"categories":['laptops']}))
42 | +productListByProductSearchResult(findProducts("homepagewidget",{"query":"","pageSize": "8","sortDirection":"A","sortBy":'name'},{}))
--------------------------------------------------------------------------------
/frontend/src/template/base/molecule/footer/footer.pug:
--------------------------------------------------------------------------------
1 | footer.page-footer.text-center.font-small.mt-4.wow.fadeIn
2 | // /.Call to action
3 | hr.my-4
4 | // Social icons
5 | .pb-4
6 | a(href='https://twitter.com/aoepeople', target='_blank')
7 | i.fa.fa-twitter.mr-3
8 | a(href='https://www.youtube.com/watch?v=7MUISDJ5ZZ4', target='_blank')
9 | i.fa.fa-youtube.mr-3
10 | a(href='https://github.com/i-love-flamingo', target='_blank')
11 | i.fa.fa-github.mr-3
12 | // Social icons
13 | // Copyright
14 | .footer-copyright.py-3
15 | | © 2018 Copyright:
16 | a(href='https://mdbootstrap.com/bootstrap-tutorial/', target='_blank') Template based on MDBootstrap.com
17 | | © 2018 Copyright:
18 | a(href='https://flamingo.me/', target='_blank') Flamingo by AOE
19 | // /.Copyright
20 | // /.Footer
21 | // SCRIPTS
22 | // JQuery
23 | link(rel="stylesheet", href=asset("asset/css/bootstrap.min.css"))
24 |
25 |
26 | script(type='text/javascript', src=asset("asset/js/jquery-3.3.1.min.js"))
27 | // Bootstrap tooltips
28 | script(type='text/javascript', src=asset("asset/js/popper.min.js"))
29 | // Bootstrap core JavaScript
30 | script(type='text/javascript', src=asset("asset/js/bootstrap.min.js"))
31 | // MDB core JavaScript
32 | script(type='text/javascript', src=asset("asset/js/mdb.min.js"))
33 | // Initializations
34 | script(type='text/javascript').
35 | // Animations initialization
36 | new WOW().init();
37 | block js-application
38 | //script(src=asset("js/app.js"))
39 | script(src=asset("js/main.js"))
40 | //
41 | script(async src="https://www.googletagmanager.com/gtag/js?id=UA-129655449-1")
42 | script.
43 | window.dataLayer = window.dataLayer || [];
44 | function gtag() {
45 | dataLayer.push(arguments);
46 | }
47 | gtag('js', new Date());
48 |
49 | gtag('config', 'UA-129655449-1');
--------------------------------------------------------------------------------
/graphql/module.go:
--------------------------------------------------------------------------------
1 | // Code generated by flamingo.me/graphql, DO NOT EDIT.
2 | //go:build !graphql
3 | // +build !graphql
4 |
5 | package graphql
6 |
7 | import (
8 | "context"
9 | "encoding/json"
10 | "log"
11 | "reflect"
12 |
13 | "flamingo.me/dingo"
14 | "github.com/99designs/gqlgen/graphql"
15 | "github.com/spf13/cobra"
16 | )
17 |
18 | // Module is an autogenerated dingo Module to bind the root resolver
19 | type Module struct{}
20 |
21 | // Configure sets the graphql.ExecutableSchema binding via a provider, passing in the correct root resolver
22 | func (*Module) Configure(injector *dingo.Injector) {
23 | injector.Bind(new(graphql.ExecutableSchema)).ToProvider(func(root *rootResolver) graphql.ExecutableSchema {
24 | return NewExecutableSchema(Config{Resolvers: root, Directives: root.directives()})
25 | })
26 |
27 | injector.BindMulti(new(cobra.Command)).ToProvider(func(root *rootResolver) *cobra.Command {
28 | return &cobra.Command{
29 | Use: "gql calls a gql function like 'go run main.go gql User.Todos '{\"Name\":\"User a\"}' ",
30 | Run: func(cmd *cobra.Command, args []string) {
31 | if len(args) == 0 {
32 | for k := range direct(root) {
33 | log.Println(k)
34 | }
35 | return
36 | } else if len(args) == 1 {
37 | v := reflect.ValueOf(direct(root)[args[0]])
38 | log.Printf("%s", v.Type().String())
39 | return
40 | }
41 |
42 | v := reflect.ValueOf(direct(root)[args[0]])
43 | in := make([]reflect.Value, v.Type().NumIn()-1)
44 | for i := 1; i < v.Type().NumIn(); i++ {
45 | in[i-1] = reflect.New(v.Type().In(i))
46 | log.Println(json.Unmarshal([]byte(args[i]), in[i-1].Interface()))
47 | in[i-1] = in[i-1].Elem()
48 | }
49 | res := v.Call(append([]reflect.Value{reflect.ValueOf(context.Background())}, in...))
50 | for _, r := range res {
51 | v, _ := json.Marshal(r.Interface())
52 | log.Print(string(v))
53 | }
54 | },
55 | }
56 | })
57 | }
58 |
--------------------------------------------------------------------------------
/frontend/src/base/style/mdp-ecom-base/free/_pagination.sass:
--------------------------------------------------------------------------------
1 | // Pagination
2 | .pagination
3 | .page-item
4 | &.active
5 | .page-link
6 | box-shadow: $z-depth-1
7 | transition: $pagination-active-transition
8 | border-radius: $border-radius-base
9 | background-color: $primary-color
10 | color: $white-base
11 |
12 | &:hover
13 | background-color: $primary-color
14 |
15 | &.disabled
16 | .page-link
17 | color: $pagination-page-item-disabled-color
18 |
19 | .page-link
20 | transition: $pagination-page-link-transition
21 | outline: 0
22 | border: 0
23 | background-color: transparent
24 | font-size: $pagination-page-link-font-size
25 | color: $pagination-page-link-color
26 |
27 | &:hover
28 | transition: $pagination-page-link-transition
29 | border-radius: $border-radius-base
30 | background-color: $pagination-page-link-hover-bg-color
31 |
32 | &:focus
33 | background-color: transparent
34 |
35 | &.pagination-lg
36 | .page-item
37 | .page-link
38 | font-size: $pagination-page-link-font-size-lg
39 |
40 | &.pagination-sm
41 | .page-item
42 | .page-link
43 | font-size: $pagination-page-link-font-size-sm
44 |
45 | &.pagination-circle
46 | .page-item
47 | .page-link
48 | margin-left: $pagination-circle-margin-x
49 | margin-right: $pagination-circle-margin-x
50 | border-radius: $pagination-circle-border-radius
51 |
52 | &:hover
53 | border-radius: $pagination-circle-border-radius
54 |
55 | &.active
56 | .page-link
57 | border-radius: $pagination-circle-border-radius
58 |
59 | @each $name, $color in $pagination-colors
60 | &.pg-#{$name}
61 | .page-item
62 | &.active
63 | .page-link
64 | background-color: $color
65 |
66 | &:hover
67 | background-color: $color
68 |
--------------------------------------------------------------------------------
/frontend/src/page/search/products.pug:
--------------------------------------------------------------------------------
1 | extends /template/base/base
2 |
3 | include /organism/productList/productList
4 | include /atom/debug/debug
5 |
6 | mixin catTreeItems(facetItems, queryS)
7 | each facetItem in facetItems
8 | li
9 | -
10 | urlValues = {type: "products", q: queryS}
11 | urlValues["category"] = facetItem.value
12 |
13 | a(href=url('search.search', urlValues)) #{facetItem.label} (#{facetItem.count})
14 | if facetItem.items
15 | ul
16 | +catTreeItems(facetItem.items, queryS)
17 |
18 | block maincontent
19 | main.mt-5.p-4.dark-grey-text.category
20 | h2.mt-4.mb-4.h2.text-center Search result
21 | p.text-center #{searchMeta.numResults} hits for your search for
22 | i "#{searchMeta.query}"
23 | .row
24 | nav.col-md-3.order-md-first
25 | button.d-block.d-md-none.btn.btn-primary.btn-block.mb-3(type="button" data-toggle="collapse" data-target="#filters") Filters ▾
26 | div.collapse.d-md-block(id="filters")
27 | if searchResult["products"].facets["category"]
28 | h2=__("facet.header.category").setDefaultLabel("Category")
29 | ul
30 | +catTreeItems(searchResult["products"].facets["category"].items,searchMeta.query)
31 | each facet, facetKey in searchResult["products"].facets
32 | if facetKey == "category"
33 | else
34 | h2=__("facet.header."+facetKey).setDefaultLabel(capitalize(facetKey))
35 | if facet.items
36 | ul
37 | each facetItem in facet.items
38 | -
39 | addUrlParam = {}
40 | addUrlParam[facetKey] = facetItem.value
41 | li
42 | a(href=url('', addUrlParam)) #{capitalize(facetItem.label)} (#{facetItem.count})
43 |
44 | div.col-md-9.order-md-last(id="")
45 | +productList(searchResult["products"].hits, searchResult["products"].paginationInfo)
46 | //+debug(productSearchResult)
47 | //+debug(categoryTree)
--------------------------------------------------------------------------------
/frontend/src/organism/cart/cart.pug:
--------------------------------------------------------------------------------
1 | include /molecule/productMedia/productMedia
2 | include /atom/price/price
3 | include /atom/debug/debug
4 | include /molecule/productMedia/productMedia
5 |
6 | mixin cart(decoratedCart,cartValidationResult, showActions)
7 |
8 | if decoratedCart.cart.isEmpty
9 | h4=__("emptycart").setDefaultLabel("Your cart is empty")
10 | else
11 | if cartValidationResult
12 | if cartValidationResult.isValid === false
13 | .error
14 | if cartValidationResult.hasCommonError
15 | p(data-alert)= __(cartValidationResult.commonErrorMessageKey)
16 | else
17 | p(data-alert)= __('checkout.cart_item_error_hint').setDefaultLabel()
18 |
19 |
20 |
21 | each decoratedDelivery in decoratedCart.decoratedDeliveries
22 | if decoratedDelivery.delivery.hasItems
23 | h4(data-deliverycode=decoratedDelivery.delivery.deliveryInfo.code).d-flex.justify-content-between.align-items-center.mb-3
24 | span.text-muted=__(decoratedDelivery.delivery.deliveryInfo.code)
25 | ul.list-group.mb-3.z-depth-1
26 | each decoratedItem in decoratedDelivery.decoratedItems
27 | li.list-group-item.d-flex.justify-content-between.lh-condensed
28 | div
29 | h6.my-0.mb-1
30 | +productMedia(decoratedItem.product.getListMedia, '40x')(height="30px").mr-3
31 | a(href=getProductUrl(decoratedItem.product))=decoratedItem.item.productName
32 | small.text-muted=truncate(decoratedItem.product.baseData.shortDescription,80)
33 | if showActions
34 | small.text-muted
35 | a(href=url('cart.deleteItem', {id: decoratedItem.item.iD,deliveryCode:decoratedDelivery.delivery.deliveryInfo.code})) [delete]
36 | span.text-muted=commercePriceFormat(decoratedItem.item.rowPriceGrossWithDiscount)
37 | li.list-group-item.d-flex.justify-content-between
38 | span Sum:
39 | strong=commercePriceFormat(decoratedDelivery.delivery.subTotalGrossWithDiscounts)
40 | if !decoratedCart.cart.sumTotalTaxAmount.isZero
41 | div.text-right Included Tax:
42 | strong=commercePriceFormat(decoratedCart.cart.sumTotalTaxAmount)
43 | div.text-right Total:
44 | strong=commercePriceFormat(decoratedCart.cart.grandTotal)
--------------------------------------------------------------------------------
/graphql/schema/flamingo.me_flamingo-commerce_v3_customer_interfaces_graphql-Service.graphql:
--------------------------------------------------------------------------------
1 | type Commerce_Customer_Status_Result {
2 | isLoggedIn: Boolean!
3 | userID: String!
4 | }
5 |
6 | type Commerce_Customer_Result {
7 | id: String!
8 | "Customers personal data"
9 | personalData: Commerce_Customer_PersonData!
10 | "Get a specific address from the customer"
11 | getAddress(id: ID!): Commerce_Customer_Address
12 | "Addresses that the customer provided, can be used for billing / shipping"
13 | addresses: [Commerce_Customer_Address!]
14 | "The default shipping address of the customer, null if there is none"
15 | defaultShippingAddress: Commerce_Customer_Address
16 | "The default billing address of the customer, null if there is none"
17 | defaultBillingAddress: Commerce_Customer_Address
18 | }
19 |
20 | type Commerce_Customer_PersonData {
21 | gender: String!
22 | firstName: String!
23 | lastName: String!
24 | middleName: String!
25 | mainEmail: String!
26 | prefix: String!
27 | birthday: Date
28 | nationality: String!
29 | }
30 |
31 | type Commerce_Customer_Address {
32 | id: ID!
33 | additionalAddressLines: [String!]
34 | city: String!
35 | company: String!
36 | countryCode: String!
37 | "Flag if this address should be used as the default billing address"
38 | defaultBilling: Boolean!
39 | "Flag if this address should be used as the default shipping address"
40 | defaultShipping: Boolean!
41 | firstName: String!
42 | lastName: String!
43 | postCode: String!
44 | prefix: String!
45 | regionCode: String!
46 | street: String!
47 | streetNumber: String!
48 | state: String!
49 | telephone: String!
50 | email: String!
51 | }
52 |
53 | extend type Query {
54 | """
55 | Returns the logged in status for the current session
56 | """
57 | Commerce_Customer_Status: Commerce_Customer_Status_Result
58 | """
59 | Returns the logged in customer for the current session or an error if it is not logged in.
60 | If you don't want to handle the error, check with Commerce_Customer_Status first.
61 | """
62 | Commerce_Customer: Commerce_Customer_Result
63 | }
64 |
--------------------------------------------------------------------------------
/frontend/src/base/style/mdp-ecom-base/free/_navbars.sass:
--------------------------------------------------------------------------------
1 | // Navbars
2 | .navbar
3 | box-shadow: $z-depth-1
4 | font-weight: $navbar-font-weight
5 |
6 | form
7 | .md-form
8 | input
9 | margin: 0 $navbar-form-input-mr $navbar-form-input-mb $navbar-form-input-ml
10 |
11 | .breadcrumb
12 | margin: 0
13 | padding: $navbar-breadcrumb-padding-top 0 0 $navbar-breadcrumb-padding-left
14 | background-color: inherit
15 | font-size: $navbar-double-font-size
16 | font-weight: $navbar-font-weight
17 |
18 | .breadcrumb-item
19 | color: $white-base
20 |
21 | &.active
22 | color: $navbar-breadcrumb-color
23 |
24 | &:before
25 | color: $navbar-breadcrumb-color
26 |
27 | .navbar-toggler
28 | outline: 0
29 | border-width: 0
30 |
31 | .nav-flex-icons
32 | flex-direction: row
33 |
34 | .container
35 | @media (max-width: $medium-screen)
36 | width: 100%
37 |
38 | .navbar-toggler-right
39 | right: 0
40 |
41 | .nav-item
42 | .nav-link
43 | display: block
44 |
45 | &.disabled
46 | &:active
47 | pointer-events: none
48 |
49 | .fa
50 | padding-right: $navbar-flex-icons-padding-lg
51 | padding-left: $navbar-flex-icons-padding-lg
52 |
53 | @media (max-width: $medium-screen)
54 | padding-right: $navbar-flex-icons-padding-md
55 | padding-left: $navbar-flex-icons-padding-md
56 |
57 | .dropdown-menu
58 | position: absolute !important
59 | margin-top: 0
60 | z-index: 5
61 |
62 | a
63 | padding: $navbar-dropdown-menu-padding
64 | font-size: $navbar-dropdown-font-size
65 | font-weight: $navbar-font-weight
66 | color: $black !important
67 |
68 | &.navbar-light
69 | +make-navbar($navbar-light-disabled-color, $navbar-light-toggler-icon, $black, $navbar-light-hover-color, $navbar-light-bg-active-color)
70 |
71 | &.navbar-dark
72 | +make-navbar($navbar-dark-disabled-color, $navbar-dark-toggler-icon, $white, $navbar-dark-hover-color, $navbar-dark-bg-active-color)
73 |
74 | &.scrolling-navbar
75 | @media (min-width: $small-screen)
76 | transition: $navbar-scrolling-transition
77 | padding-top: $navbar-scrolling-padding
78 | padding-bottom: $navbar-scrolling-padding
79 |
80 | .navbar-nav > li
81 | transition-duration: $navbar-scrolling-transition-duration
82 |
83 | &.top-nav-collapse
84 | padding-top: $navbar-top-collapse-padding
85 | padding-bottom: $navbar-top-collapse-padding
86 |
--------------------------------------------------------------------------------
/frontend/src/template/base/base.pug:
--------------------------------------------------------------------------------
1 | if config('debug.mode')
2 | include /atom/debug/debug
3 | include /atom/console/console
4 |
5 | doctype html
6 | html(lang='en')
7 | block head
8 | include /template/base/molecule/head/head
9 | body
10 | // Navbar
11 | nav.navbar.fixed-top.navbar-expand-lg.navbar-light.white.scrolling-navbar
12 | .container
13 | // Brand
14 | a.navbar-brand.waves-effect(href='/')
15 | img.img-fluid(src=asset("asset/img/flamingo-logo-black.png") style="max-height:30px")
16 | strong.ml-2 demoshop
17 | // Collapse
18 | button.navbar-toggler(type='button', data-toggle='collapse', data-target='#navbarSupportedContent', aria-controls='navbarSupportedContent', aria-expanded='false', aria-label='Toggle navigation')
19 | span.navbar-toggler-icon
20 | // Links
21 | #navbarSupportedContent.collapse.navbar-collapse
22 | // Left
23 | include /template/base/molecule/categoryMenu/categoryMenu
24 | form(class="form-inline my-2 my-lg-0" action=url('search.search', {type: "products"}))
25 | if searchMeta
26 | input(class="form-control mr-sm-2" type="search" name="q" placeholder="Search" aria-label="Search" value=searchMeta.query)
27 | else
28 | input(class="form-control mr-sm-2" type="search" name="q" placeholder="Search" aria-label="Search")
29 | button(class="btn btn-dark btn-sm" type="submit") Search
30 | // Right
31 | ul.navbar-nav.nav-flex-icons
32 | li.nav-item
33 | a.nav-link.waves-effect(href=url('cart.view'))
34 | -
35 | var miniCart = getCart()
36 | var currentCount = miniCart.getCartTeaser.itemCount
37 | span.badge.red.z-depth-1.mr-1=currentCount
38 | i.fa.fa-shopping-cart
39 | span.clearfix.d-none.d-sm-inline-block Cart
40 | //li.nav-item
41 | a.nav-link.waves-effect(href='https://twitter.com/aoepeople', target='_blank')
42 | i.fa.fa-twitter
43 | //li.nav-item
44 | a.nav-link.border.border-light.rounded.waves-effect(href='https://github.com/i-love-flamingo', target='_blank')
45 | i.fa.fa-github.mr-2
46 | | GitHub
47 | // Navbar
48 | // Carousel Wrapper
49 | block precontent
50 | block maincontent
51 | main.mt-5.pt-4
52 | block content
53 |
54 | // Pagination
55 | // Main layout
56 | // Footer
57 | include /template/base/molecule/footer/footer
58 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | CONTEXT?=dev:testproducts
2 | REPLACE?=-replace flamingo.me/flamingo/v3=../flamingo -replace flamingo.me/flamingo-commerce/v3=../flamingo-commerce -replace flamingo.me/flamingo-commerce-adapter-standalone=../flamingo-commerce-adapter-standalone -replace flamingo.me/flamingo-commerce-adapter-magento2=../flamingo-commerce-adapter-magento2 -replace flamingo.me/form=../form
3 | DROPREPLACE?=-dropreplace flamingo.me/flamingo/v3 -dropreplace flamingo.me/flamingo-commerce/v3 -dropreplace flamingo.me/flamingo-commerce-adapter-standalone -dropreplace flamingo.me/flamingo-commerce-adapter-magento2 -dropreplace flamingo.me/form
4 |
5 | .PHONY: prepare-product-data download-product-data build serve serve-jaeger jaeger-docker local unlocal frontend frontend-build translation update dockerpublish
6 |
7 | prepare-product-data:
8 | cd resources && zip -r products.zip products
9 |
10 | download-product-data:
11 | cd resources && wget https://github.com/i-love-flamingo/commerce-demo-carotene/releases/download/productdata1/products.zip && unzip products.zip
12 |
13 | build:
14 | go build main.go
15 |
16 | serve:
17 | DEBUG=1 CONTEXT=$(CONTEXT) go run main.go serve
18 |
19 | serve-jaeger: translation
20 | DEBUG=1 CONTEXT=$(CONTEXT) go run main.go --flamingo-config 'opencensus.jaeger.enable: true' serve
21 |
22 | jaeger-docker:
23 | docker run -e COLLECTOR_ZIPKIN_HTTP_PORT=9411 -p 5775:5775/udp -p 6831:6831/udp -p 6832:6832/udp -p 5778:5778 -p 16686:16686 -p 14268:14268 -p 9411:9411 jaegertracing/all-in-one:latest
24 |
25 | frontend: frontend-build
26 | bash -c 'cd frontend && npm run dev'
27 |
28 | frontend-build:
29 | bash -c 'cd frontend && npm ci && npm run build'
30 |
31 | translation:
32 | ./preparetranslations.sh
33 |
34 | local:
35 | git config filter.gomod-commercedemo-flamingo.smudge 'go mod edit -fmt -print $(REPLACE) /dev/stdin'
36 | git config filter.gomod-commercedemo-flamingo.clean 'go mod edit -fmt -print $(DROPREPLACE) /dev/stdin'
37 | git config filter.gomod-commercedemo-flamingo.required true
38 | go mod edit -fmt $(REPLACE)
39 |
40 | unlocal:
41 | git config filter.gomod-commercedemo-flamingo.smudge ''
42 | git config filter.gomod-commercedemo-flamingo.clean ''
43 | git config filter.gomod-commercedemo-flamingo.required false
44 | go mod edit -fmt $(DROPREPLACE)
45 |
46 | update:
47 | go get -u flamingo.me/flamingo/v3 flamingo.me/flamingo-commerce/v3@v3
48 |
49 | dockerpublish:
50 | GOOS=linux go build -o flamingo-commerce-demo-carotene main.go
51 | docker build --no-cache -t iloveflamingo/flamingo-commerce-demo-carotene .
52 | docker push iloveflamingo/flamingo-commerce-demo-carotene:latest
53 |
54 | generate-graphql:
55 | go generate
--------------------------------------------------------------------------------
/translations/src/en-gb.cart.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "id": "delivery",
4 | "translation": "Home delivery"
5 | },
6 | {
7 | "id": "pickup_store",
8 | "translation": "Instore pickup"
9 | },
10 | {
11 | "id": "cart.group.title",
12 | "translation": "products"
13 | },
14 |
15 | {
16 | "id": "cart.column.quantity",
17 | "translation": "Quantity"
18 | },
19 |
20 | {
21 | "id": "cart.column.price",
22 | "translation": "Price"
23 | },
24 |
25 | {
26 | "id": "cart.column.sum",
27 | "translation": "Sum"
28 | },
29 |
30 | {
31 | "id": "cart.item.detail",
32 | "translation": "SKU: {{ .SKU }}"
33 | },
34 |
35 | {
36 | "id": "cart.item.remove",
37 | "translation": "remove item"
38 | },
39 |
40 | {
41 | "id": "cart.loyalty.label",
42 | "translation": "Heathrow Reward points"
43 | },
44 |
45 | {
46 | "id": "cart.total.label",
47 | "translation": "Total"
48 | },
49 |
50 | {
51 | "id": "cart.button.reserveAndCollect",
52 | "translation": "Reserve & Collect"
53 | },
54 |
55 | {
56 | "id": "cart.button.continueShopping",
57 | "translation": "Continue Shopping"
58 | },
59 |
60 | {
61 | "id": "miniCart.removeItem",
62 | "translation": "Remove {{.title}}"
63 | },
64 |
65 | {
66 | "id": "miniCart.hiddenProducts",
67 | "translation": "{{.qty}} more products"
68 | },
69 |
70 | {
71 | "id": "miniCart.hiddenProduct",
72 | "translation": "1 more product"
73 | },
74 |
75 | {
76 | "id": "miniCart.total",
77 | "translation": "Total: {{.total}}"
78 | },
79 |
80 | {
81 | "id": "miniCart.empty",
82 | "translation": "Your cart is empty"
83 | },
84 |
85 | {
86 | "id": "miniCart.buttonCartView",
87 | "translation": "Shopping Bag"
88 | },
89 |
90 | {
91 | "id": "miniCart.buttonReserveAndCollect",
92 | "translation": "Reserve & Collect"
93 | },
94 |
95 | {
96 | "id": "cart.reserveInfo.noPayment",
97 | "translation": "No payment is taken and you have no obligation to purchase your reserved shopping requests if you change your mind."
98 | },
99 |
100 | {
101 | "id": "cart.reserveInfo.collectedAtShop",
102 | "translation": "The items must be paid for and collected at the shop you have made the purchase from on your day of travel, prior to flying."
103 | },
104 |
105 | {
106 | "id": "cart.reserveInfo.individualStorePolicy",
107 | "translation": "Reservations will be confirmed in accordance with individual store policy, which our customer service team will verify to you."
108 | }
109 |
110 |
111 | ]
112 |
--------------------------------------------------------------------------------
/frontend/src/molecule/productTile/productTile.pug:
--------------------------------------------------------------------------------
1 | include /atom/price/price
2 | include /molecule/productMedia/productMedia
3 | include /molecule/productTile/productTileTruncate
4 | include /atom/debug/debug
5 |
6 | mixin productTile(productData)
7 | - var teaserData = productData.teaserData
8 |
9 | - var baseData = productData.baseData
10 | case productData.type
11 | when 'simple'
12 | - var productUrl = url('product.view', {marketplacecode: teaserData.marketPlaceCode, name: teaserData.shortTitle})
13 | when 'configurable'
14 | - var variantcode = teaserData.preSelectedVariantSku ? teaserData.preSelectedVariantSku : null
15 |
16 | if variantcode
17 | - var productUrl = url('product.view', {marketplacecode: teaserData.marketPlaceCode, variantcode: variantcode, name: teaserData.shortTitle})
18 | else
19 | - var productUrl = url('product.view', {marketplacecode: teaserData.marketPlaceCode, name: teaserData.shortTitle})
20 | default
21 | - throw 'unknown product type'
22 |
23 | if baseData
24 | // init brandLabel and set to brandName
25 | - var brandLabel = ""
26 | if (baseData.attributes.brandName)
27 | - var brandLabel = baseData.attributes.brandName.value
28 |
29 | //- Check for promo badge
30 | - var hasPromoBadge = false
31 | - var promoCode = null
32 | if baseData.attributes.campaignCodes && baseData.attributes.campaignCodes.values.length > 0
33 | - hasPromoBadge = true
34 | - promoCode = baseData.attributes.campaignCodes.values[0]
35 |
36 | if !hasPromoBadge && productData.type === 'configurable'
37 | if productData.variants && productData.variants.length > 0
38 | each variant, index in productData.variants
39 | if variant.baseData.attributes.campaignCodes && variant.baseData.attributes.campaignCodes.values.length > 0
40 | - hasPromoBadge = true
41 | // use first promo code of variants
42 | if !promoCode
43 | - promoCode = variant.baseData.attributes.campaignCodes.values[0]
44 |
45 | a.productTile(href=productUrl title=teaserData.shortTitle)&attributes(attributes)
46 | .productTileFigure
47 | - var inserted = false
48 | each mediaItem in teaserData.media
49 | if (!inserted && mediaItem.usage === 'list')
50 | - inserted = true
51 | +productMedia(mediaItem, '400x').productTileImage
52 | if hasPromoBadge
53 | +promoBadge()
54 | p.productTileBrand
55 | +productTileTruncate(brandLabel, 15)
56 | h5.productTileTitle
57 | +productTileTruncate(teaserData.shortTitle, 50)
58 |
59 | +price(productData, productData.type, true, promoCode).productTilePrice
60 |
--------------------------------------------------------------------------------
/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "flamingo.me/dingo"
5 | "flamingo.me/graphql"
6 |
7 | "flamingo.me/flamingo-commerce-adapter-standalone/commercesearch"
8 | "flamingo.me/flamingo-commerce-adapter-standalone/csvindexing"
9 | "flamingo.me/flamingo-commerce/v3/cart"
10 | "flamingo.me/flamingo-commerce/v3/category"
11 | "flamingo.me/flamingo-commerce/v3/checkout"
12 | "flamingo.me/flamingo-commerce/v3/customer"
13 | "flamingo.me/flamingo-commerce/v3/payment"
14 | "flamingo.me/flamingo-commerce/v3/product"
15 | "flamingo.me/flamingo/v3"
16 | "flamingo.me/flamingo/v3/core/healthcheck"
17 | "flamingo.me/flamingo/v3/core/locale"
18 | "flamingo.me/flamingo/v3/core/requestlogger"
19 | "flamingo.me/flamingo/v3/framework/config"
20 | flamingoFramework "flamingo.me/flamingo/v3/framework/flamingo"
21 | "flamingo.me/flamingo/v3/framework/opencensus"
22 | "flamingo.me/flamingo/v3/framework/prefixrouter"
23 | "flamingo.me/flamingo/v3/framework/systemendpoint"
24 | "flamingo.me/form"
25 | "flamingo.me/pugtemplate"
26 |
27 | "flamingo.me/swagger"
28 |
29 | projectGraphql "flamingo.me/commerce-demo-carotene/graphql"
30 | )
31 |
32 | //go:generate rm -f graphql/generated.go
33 | //go:generate go run -tags graphql main.go graphql
34 | //go:generate go run github.com/swaggo/swag/cmd/swag init --parseDependency=1 --generalInfo=main.go
35 |
36 | // main is our entry point
37 |
38 | // @title Flamingo Commerce Demo Shop
39 | // @version 1.0
40 | // @BasePath /en
41 | // @license.name MIT
42 | // @contact.name Flamingo
43 | // @contact.url https://gitter.im/i-love-flamingo/community#
44 | // @contact.email flamingo@aoe.com
45 | func main() {
46 |
47 | flamingo.App([]dingo.Module{
48 | //flamingo framework modules:
49 | new(requestlogger.Module), // requestlogger show request logs
50 | new(prefixrouter.Module),
51 | new(flamingoFramework.SessionModule),
52 |
53 | new(locale.Module),
54 | new(opencensus.Module),
55 | new(systemendpoint.Module),
56 | new(healthcheck.Module),
57 | new(projectGraphql.Module),
58 | //form module (required by commerce)
59 | new(form.Module),
60 | //flamingo-commerce modules
61 | new(product.Module),
62 | //new(price.Module),
63 | new(category.Module),
64 | new(cart.Module),
65 | new(customer.Module),
66 | new(payment.Module),
67 | new(checkout.Module),
68 | //flamingo-commerce-adpater-standalone modules:
69 | new(commercesearch.Module),
70 | new(commercesearch.CategoryModule),
71 | new(commercesearch.SearchModule),
72 | new(csvindexing.ProductModule),
73 | //new(emailplaceorder.Module),
74 | new(graphql.Module),
75 | new(pugtemplate.Module),
76 | new(swagger.Module),
77 | }, flamingo.ChildAreas(
78 | config.NewArea("csv", nil,
79 | config.NewArea("de", nil),
80 | ),
81 | ),
82 | )
83 | }
84 |
--------------------------------------------------------------------------------
/frontend/src/base/style/mdp-ecom-base/core/bootstrap/_functions.sass:
--------------------------------------------------------------------------------
1 | // Bootstrap functions
2 | //
3 | // Utility mixins and functions for evalutating source code across our variables, maps, and mixins.
4 |
5 | // Ascending
6 | // Used to evaluate Sass maps like our grid breakpoints.
7 | =_assert-ascending($map, $map-name)
8 | $prev-key: null
9 | $prev-num: null
10 |
11 | @each $key, $num in $map
12 | @if $prev-num == null
13 | // Do nothing
14 | @else if not comparable($prev-num, $num)
15 | @warn "Potentially invalid value for #{$map-name}: This map must be in ascending order, but key '#{$key}' has value #{$num} whose unit makes it incomparable to #{$prev-num}, the value of the previous key '#{$prev-key}' !"
16 | @else if $prev-num >= $num
17 | @warn "Invalid value for #{$map-name}: This map must be in ascending order, but key '#{$key}' has value #{$num} which isn't greater than #{$prev-num}, the value of the previous key '#{$prev-key}' !"
18 |
19 | $prev-key: $key
20 | $prev-num: $num
21 |
22 | // Starts at zero
23 | // Another grid mixin that ensures the min-width of the lowest breakpoint starts at 0.
24 | =_assert-starts-at-zero($map)
25 | $values: map-values($map)
26 | $first-value: nth($values, 1)
27 |
28 | @if $first-value != 0
29 | @warn "First breakpoint in `$grid-breakpoints` must start at 0, but starts at #{$first-value}."
30 |
31 | // Replace `$search` with `$replace` in `$string`
32 | // Used on our SVG icon backgrounds for custom forms.
33 | //
34 | // @author Hugo Giraudel
35 | // @param {String} $string - Initial string
36 | // @param {String} $search - Substring to replace
37 | // @param {String} $replace ('') - New value
38 | // @return {String} - Updated string
39 | @function str-replace($string, $search, $replace: "")
40 | $index: str-index($string, $search)
41 |
42 | @if $index
43 | @return str-slice($string, 1, $index - 1) + $replace + str-replace(str-slice($string, $index + str-length($search)), $search, $replace)
44 |
45 | @return $string
46 |
47 | // Color contrast
48 | @function color-yiq($color)
49 | $r: red($color)
50 | $g: green($color)
51 | $b: blue($color)
52 |
53 | $yiq: ($r * 299 + $g * 587 + $b * 114) / 1000
54 |
55 | @if $yiq >= $yiq-contrasted-threshold
56 | @return $yiq-text-dark
57 | @else
58 | @return $yiq-text-light
59 |
60 | // Retrieve color Sass maps
61 | @function color($key: "blue")
62 | @return map-get($colors, $key)
63 |
64 | @function theme-color($key: "primary")
65 | @return map-get($theme-colors, $key)
66 |
67 | @function gray($key: "100")
68 | @return map-get($grays, $key)
69 |
70 | // Request a theme color level
71 | @function theme-color-level($color-name: "primary", $level: 0)
72 | $color: theme-color($color-name)
73 | $color-base: if($level > 0, $black, $white)
74 | $level: abs($level)
75 |
76 | @return mix($color-base, $color, $level * $theme-color-interval)
77 |
--------------------------------------------------------------------------------
/frontend/src/page/checkout/review.pug:
--------------------------------------------------------------------------------
1 | extends /template/base/base
2 | include /organism/cart/cart
3 |
4 | block maincontent
5 | main.mt-5.pt-4
6 | div.container
7 | //+debug(decoratedCart.cart)
8 | h2.my-5.h2.text-center Checkout
9 | if errorInfos
10 | if errorInfos.hasError
11 | if errorInfos.hasPaymentError
12 | div.alert.alert-error(role="alert") Payment Error
13 | div.alert.alert-warning(role="alert")=__("checkout.error."+errorInfos.errorMessage)
14 | div.row
15 | div.col-md-8.mb-4
16 | h4.d-flex.justify-content-between.align-items-center.mb-3
17 | span.text-muted Review your data
18 | div.card
19 | .card-body
20 | h5.mt-1.mb-2
21 | span.text-muted Billing
22 | +renderAddress(decoratedCart.cart.billingAddress)
23 | each delivery in decoratedCart.cart.deliveries
24 | - var deliveryCode = delivery.deliveryInfo.code
25 | h5(data-deliverycode=delivery.deliveryInfo.code).mt-5.mb-2
26 | span.text-muted=__(delivery.deliveryInfo.code)
27 |
28 | if deliveryCode == "delivery"
29 | if delivery.deliveryInfo.deliveryLocation.useBillingAddress
30 | p
31 | strong same as billing
32 | else
33 | +renderAddress(delivery.deliveryInfo.deliveryLocation.address)
34 | h5.mt-5.mb-2
35 | span.text-muted Payment
36 | p Gateway: #{decoratedCart.cart.paymentSelection.gateway}
37 | each chargeSplit in decoratedCart.cart.paymentSelection.chargeSplits
38 | p #{commercePriceFormat(chargeSplit.charge.price)} with Method: #{chargeSplit.method}
39 | form(action=url("checkout.review"))
40 | div.custom-control.custom-checkbox.mt-3.mb-1
41 | input.custom-control-input(type="checkbox", id="termsAndConditions", name="termsAndConditions", value="1")
42 | label.custom-control-label(for="termsAndConditions") I accept terms and conditions
43 | input(type='hidden' name='proceed' value='1')
44 | button.btn.btn-primary.btn-lg.btn-block.waves-effect.waves-light(type="submit") Pay and place order
45 | div.col-md-4.mb-4
46 | if cartValidationResult
47 | if cartValidationResult.hasCommonError
48 | div.alert.alert-warning(role="alert")=cartValidationResult.commonErrorMessageKey
49 | each itemResult in cartValidationResult.itemResults
50 | div.alert.alert-warning(role="alert")=itemResult.errorMessageKey
51 | +cart(decoratedCart,cartValidationResult,false)
52 |
53 |
54 | mixin renderAddress(address)
55 | p #{address.firstname} #{address.lastname}
56 | p #{address.email}
57 | p #{address.street} #{address.streetNr}
58 | p #{address.postCode} #{address.city}
--------------------------------------------------------------------------------
/frontend/src/base/style/mdp-ecom-base/free/_buttons.sass:
--------------------------------------------------------------------------------
1 | // Buttons
2 | .btn
3 | box-shadow: $z-depth-1
4 |
5 | +button-size($btn-padding-y-basic, $btn-padding-x-basic, $btn-font-size-basic)
6 |
7 | transition: $btn-transition
8 | margin: $btn-margin-basic
9 | border: 0
10 | border-radius: $border-radius-base
11 | cursor: pointer
12 | text-transform: uppercase
13 | white-space: normal
14 | word-wrap: break-word
15 | color: $btn-color-basic
16 |
17 | &:hover,
18 | &:active,
19 | &:focus
20 | box-shadow: $z-depth-1-half
21 | outline: 0
22 |
23 | &:not([disabled]):not(.disabled):active,
24 | &:not([disabled]):not(.disabled).active
25 | box-shadow: $z-depth-1-half
26 |
27 | .fa
28 | position: relative
29 | font-size: $btn-icon-basic
30 |
31 | &.right
32 | margin-left: $btn-icon-margin
33 |
34 | &.left
35 | margin-right: $btn-icon-margin
36 |
37 | &.btn-lg
38 | +button-size($btn-padding-y-large, $btn-padding-x-large, $btn-font-size-large)
39 |
40 | .fa
41 | font-size: $btn-icon-large
42 |
43 | &.btn-md
44 | +button-size($btn-padding-y-medium, $btn-padding-x-medium, $btn-font-size-medium)
45 |
46 | .fa
47 | font-size: $btn-icon-medium
48 |
49 | &.btn-sm
50 | +button-size($btn-padding-y-small, $btn-padding-x-small, $btn-font-size-small)
51 |
52 | .fa
53 | font-size: $btn-icon-small
54 |
55 | &.btn-tb
56 | padding: $btn-tb-padding-y $btn-tb-padding-x
57 |
58 | &.disabled,
59 | &:disabled
60 | &:active,
61 | &:focus,
62 | &:hover
63 | box-shadow: $z-depth-1
64 |
65 | &.btn-block
66 | margin: inherit
67 |
68 | &.btn-link
69 | @extend .black-text
70 |
71 | box-shadow: none
72 | background-color: transparent
73 |
74 | &:active,
75 | &:focus,
76 | &:hover
77 | box-shadow: none !important
78 | background-color: transparent
79 |
80 | &[class*="btn-outline-"]
81 | padding-top: $btn-outline-padding-y-basic
82 | padding-bottom: $btn-outline-padding-y-basic
83 |
84 | &.btn-lg
85 | padding-top: $btn-outline-padding-y-large
86 | padding-bottom: $btn-outline-padding-y-large
87 |
88 | &.btn-md
89 | padding-top: $btn-outline-padding-y-medium
90 | padding-bottom: $btn-outline-padding-y-medium
91 |
92 | &.btn-sm
93 | padding-top: $btn-outline-padding-y-small
94 | padding-bottom: $btn-outline-padding-y-small
95 |
96 | .btn-group
97 | .btn
98 | margin: 0
99 |
100 | // Overwrite default button icon size
101 | .btn
102 | .fa-lg
103 | font-size: 1.33333333em !important
104 |
105 | .fa-2x
106 | font-size: 2em !important
107 |
108 | .fa-3x
109 | font-size: 3em !important
110 |
111 | .fa-4x
112 | font-size: 4em !important
113 |
114 | .fa-5x
115 | font-size: 5em !important
116 |
117 | @each $btn_name, $color_value in $mdb-colors
118 | +make-button($btn_name, $color_value)
119 | +make-outline-button($btn_name, $color_value)
120 |
--------------------------------------------------------------------------------
/translations/merged/de-de.all.yaml:
--------------------------------------------------------------------------------
1 | cart.button.continueShopping:
2 | other: ""
3 | cart.button.reserveAndCollect:
4 | other: ""
5 | cart.column.price:
6 | other: ""
7 | cart.column.quantity:
8 | other: ""
9 | cart.column.sum:
10 | other: ""
11 | cart.group.title:
12 | other: ""
13 | cart.item.detail:
14 | other: ""
15 | cart.item.remove:
16 | other: ""
17 | cart.loyalty.label:
18 | other: ""
19 | cart.reserveInfo.collectedAtShop:
20 | other: ""
21 | cart.reserveInfo.individualStorePolicy:
22 | other: ""
23 | cart.reserveInfo.noPayment:
24 | other: ""
25 | cart.total.label:
26 | other: ""
27 | checkout.back_to_cart:
28 | other: ""
29 | checkout.cart_item_error_hint:
30 | other: ""
31 | checkout.error.terms_and_conditions_required:
32 | other: ""
33 | checkout.legalConfirmation.termsAndConditions:
34 | other: ""
35 | checkout.no_items_in_cart:
36 | other: ""
37 | checkout.success_message1:
38 | other: ""
39 | checkout.success_message2:
40 | other: ""
41 | delivery:
42 | other: ""
43 | error.404.headline:
44 | other: ""
45 | error.503.headline:
46 | other: ""
47 | error.common.headline:
48 | other: ""
49 | error.homeButton:
50 | other: ""
51 | facet.header.brandCode:
52 | other: ""
53 | header.welcome.subtitle:
54 | other: Standart demo shop mit carotene templates
55 | miniCart.buttonCartView:
56 | other: ""
57 | miniCart.buttonReserveAndCollect:
58 | other: ""
59 | miniCart.empty:
60 | other: ""
61 | miniCart.hiddenProduct:
62 | other: ""
63 | miniCart.hiddenProducts:
64 | other: ""
65 | miniCart.removeItem:
66 | other: ""
67 | miniCart.total:
68 | other: ""
69 | pickup_store:
70 | other: ""
71 | product.attribute.__group_packageSizes:
72 | other: ""
73 | product.attribute.baseColor:
74 | other: ""
75 | product.attribute.manufacturerColor:
76 | other: ""
77 | product.attribute.washingInstructions:
78 | other: ""
79 | search.footer.callNow:
80 | other: ""
81 | search.footer.description:
82 | other: ""
83 | search.footer.headline:
84 | other: ""
85 | search.found.brands:
86 | other: ""
87 | search.found.other:
88 | other: ""
89 | search.found.products:
90 | other: ""
91 | search.live.brands:
92 | other: ""
93 | search.live.contentPages:
94 | other: ""
95 | search.live.inRetailers:
96 | other: ""
97 | search.live.input.aria:
98 | other: ""
99 | search.live.input.placeholder:
100 | other: ""
101 | search.live.label:
102 | other: ""
103 | search.live.noResults:
104 | other: ""
105 | search.live.popular:
106 | other: ""
107 | search.live.products:
108 | other: ""
109 | search.live.reset:
110 | other: ""
111 | search.live.results:
112 | other: ""
113 | search.live.retailers:
114 | other: ""
115 | search.live.showAll:
116 | other: ""
117 | search.live.submit.aria:
118 | other: ""
119 | search.live.totalResults:
120 | other: ""
121 | search.noresult.titleWithQuery:
122 | other: ""
123 | search.noresult.widgetHeadline:
124 | other: ""
125 | search.result.title:
126 | other: ""
127 | search.result.titleWithQuery:
128 | other: ""
129 | search.suggestion.title:
130 | other: ""
131 | searchNoResultsHeader.buttonLabel:
132 | other: ""
133 | searchNoResultsHeader.text:
134 | other: ""
135 | searchNoResultsHeader.title:
136 | other: ""
137 |
--------------------------------------------------------------------------------
/config/config.yml:
--------------------------------------------------------------------------------
1 | # Flamingo core related configurations:
2 | flamingo:
3 | web:
4 | filter:
5 | cachestrategy:
6 | default:
7 | # disable http caching by default
8 | revalidateEachTime: true
9 | isReusable: false
10 | debug:
11 | mode: false
12 | session:
13 | backend: memory # in prod you will use something like redis
14 | zap:
15 | loglevel: Warn
16 | prefixrouter:
17 | rootRedirectHandler:
18 | enabled: true
19 | redirectTarget: "/en/"
20 | opencensus:
21 | tracing:
22 | sample:
23 | blacklist:
24 | - "/image"
25 | - "/static"
26 |
27 | core:
28 | oauth:
29 | server: 'https://accounts.google.com'
30 | secret: "%%ENV:OAUTH_SECRET%%"
31 | clientid: flamingo
32 | myhost: '%%ENV:FLAMINGO_HOSTNAME%%'
33 | disableOfflineToken: true
34 | mapping.idToken:
35 | groups: "UserType"
36 | locale:
37 | locale: en-gb
38 | translationFiles:
39 | - translations/merged/en-gb.all.yaml
40 | accounting:
41 | default:
42 | thousand: ','
43 | decimal: '.'
44 | formatZero: '%s -.-'
45 | format: "%s %v"
46 | EUR:
47 | thousand: '.'
48 | decimal: ','
49 | formatZero: '-,- %s'
50 | format: "%v %s"
51 | numbers:
52 | decimal: '.'
53 | thousand: ','
54 | precision: 1
55 | date:
56 | dateFormat: 02 Jan 2006
57 | timeFormat: 15:04
58 | dateTimeFormat: 02 Jan 2006 15:04:05
59 | location: Europe/London
60 |
61 | # By convention "template" is the namespace of configs just used in the template
62 | template:
63 | defaultTitle: "Flamingo Commerce Demo"
64 | product:
65 | descriptionAttributes:
66 | - size
67 | - colour
68 | - clothing_size
69 |
70 | # Configs for flamingo-commerce modules
71 | commerce:
72 | pagination:
73 | defaultPageSize: 8
74 | showAroundActivePageAmount: 2
75 | cart:
76 | defaultCartAdapter:
77 | enabled: true
78 | defaultTaxRate: 19
79 | placeOrderLogger:
80 | enabled: true
81 | useFlamingoLog: true
82 | logAsFile: true
83 | logDirectory: "./orders/"
84 | defaultDeliveryCode: delivery
85 | enableCartCache: false
86 | checkout:
87 | showEmptyCartPageIfNoItems: true
88 | payment:
89 | enableOfflinePaymentGateway: true
90 | customer:
91 | useNilCustomerAdapter: true
92 | category:
93 | useCategoryFixedAdapter: false
94 |
95 | graphql:
96 | introspectionEnabled: true # should be turned off in prod env
97 |
98 |
99 | flamingoCommerceAdapterStandalone:
100 | csvindexing:
101 | products:
102 | file:
103 | path: "resources/products/products_en.csv"
104 | delimiter: ","
105 | categories:
106 | file:
107 | path: "resources/products/categories.csv"
108 | delimiter: ","
109 | locale: "en_GB"
110 | currency: "GBP"
111 | commercesearch:
112 | enableIndexing: true
113 | repositoryAdapter: bleve
114 | bleveAdapter:
115 | enableCategoryFacet: true
116 | facetConfig:
117 | - attributeCode: brandCode
118 | amount: 10
119 | emailplaceorder:
120 | emailAddress: "flamingo@flamingo.me"
121 | fromMail: "flamingo@flamingo.me"
122 | fromName: "Flamingo Webstore"
123 |
--------------------------------------------------------------------------------
/translations/src/en-gb.search.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "id":"facet.header.brandCode",
4 | "translation":"Brand"
5 | },
6 | {
7 | "id":"search.result.titleWithQuery",
8 | "translation":"Search results for \"{{ .query }}\""
9 | },
10 | {
11 | "id":"search.result.title",
12 | "translation":"Search results"
13 | },
14 | {
15 | "id":"search.noresult.titleWithQuery",
16 | "translation":"No results for \"{{ .query }}\""
17 | },
18 | {
19 | "id":"search.noresult.widgetHeadline",
20 | "translation":"Trending Results"
21 | },
22 | {
23 | "id":"search.suggestion.title",
24 | "translation":"Here are some results for \"{{ .query }}\""
25 | },
26 | {
27 | "id":"search.found.brands",
28 | "translation":"Found in Brands"
29 | },
30 | {
31 | "id":"search.found.products",
32 | "translation":"Found in Products ({{ .numResults }})"
33 | },
34 | {
35 | "id":"search.found.other",
36 | "translation":"Other results (%s)"
37 | },
38 | {
39 | "id":"search.footer.headline",
40 | "translation":"Can’t see what you want?"
41 | },
42 | {
43 | "id":"search.footer.description",
44 | "translation":"Our Shopping Services team are available to answer any questions that you have about brands, products or services at Heathrow."
45 | },
46 | {
47 | "id":"search.footer.callNow",
48 | "translation":"Call now +44 (0)800 678 5324"
49 | },
50 | {
51 | "id":"searchNoResultsHeader.title",
52 | "translation":"We couldn't find any results
that match your search"
53 | },
54 | {
55 | "id":"searchNoResultsHeader.text",
56 | "translation":"Please check for misspellings or broaden your search by using fewer keywords.
Alternatively, browse our products by selecting a category from the menu."
57 | },
58 | {
59 | "id":"searchNoResultsHeader.buttonLabel",
60 | "translation":"Search again"
61 | },
62 | {
63 | "id": "search.live.label",
64 | "translation": "Search"
65 | },
66 | {
67 | "id": "search.live.input.placeholder",
68 | "translation": "Search"
69 | },
70 | {
71 | "id": "search.live.input.aria",
72 | "translation": "Search website"
73 | },
74 | {
75 | "id": "search.live.submit.aria",
76 | "translation": "Submit search"
77 | },
78 | {
79 | "id": "search.live.showAll",
80 | "translation": "Show all results"
81 | },
82 | {
83 | "id": "search.live.popular",
84 | "translation": "Popular searches"
85 | },
86 | {
87 | "id": "search.live.products",
88 | "translation": "Found products"
89 | },
90 | {
91 | "id": "search.live.results",
92 | "translation": "Search results"
93 | },
94 | {
95 | "id": "search.live.brands",
96 | "translation": "Brands"
97 | },
98 | {
99 | "id": "search.live.retailers",
100 | "translation": "Retailers"
101 | },
102 | {
103 | "id": "search.live.contentPages",
104 | "translation": "Content pages"
105 | },
106 | {
107 | "id": "search.live.inRetailers",
108 | "translation": "in retailers"
109 | },
110 | {
111 | "id": "search.live.reset",
112 | "translation": "Reset search"
113 | },
114 | {
115 | "id": "search.live.noResults",
116 | "translation": "Sorry, there are no results matching your query."
117 | },
118 | {
119 | "id": "search.live.totalResults",
120 | "translation": "Total results"
121 | }
122 | ]
123 |
--------------------------------------------------------------------------------
/frontend/src/base/style/mdp-ecom-base/core/_waves.sass:
--------------------------------------------------------------------------------
1 | /*!
2 | * Waves v0.7.5
3 | * http://fian.my.id/Waves
4 | *
5 | * Copyright 2014-2016 Alfiana E. Sibuea and other contributors
6 | * Released under the MIT license
7 | * https://github.com/fians/Waves/blob/master/LICENSE
8 |
9 | =waves-transition($transition)
10 | transition: $transition
11 |
12 | =waves-transform($string)
13 | transform: $string
14 |
15 | =waves-box-shadow($shadow)
16 | box-shadow: $shadow
17 |
18 | .waves-effect
19 | position: relative
20 | cursor: pointer
21 | overflow: hidden
22 | user-select: none
23 | -webkit-tap-highlight-color: transparent
24 | z-index: 1
25 |
26 | .waves-ripple
27 | position: absolute
28 | border-radius: 50%
29 | width: 100px
30 | height: 100px
31 | margin-top: -50px
32 | margin-left: -50px
33 | opacity: 0
34 | background: rgba(0, 0, 0, 0.2)
35 |
36 | $gradient: rgba(0, 0, 0, 0.2) 0, rgba(0, 0, 0, 0.3) 40%, rgba(0, 0, 0, 0.4) 50%, rgba(0, 0, 0, 0.5) 60%, rgba(255, 255, 255, 0) 70%
37 |
38 | background: -webkit-radial-gradient($gradient)
39 | background: -o-radial-gradient($gradient)
40 | background: -moz-radial-gradient($gradient)
41 | background: radial-gradient($gradient)
42 |
43 | +waves-transition(all 0.5s ease-out)
44 |
45 | transition-property: transform, opacity
46 |
47 | +waves-transform(scale(0) translate(0, 0))
48 |
49 | pointer-events: none
50 |
51 | &.waves-light .waves-ripple
52 | background: rgba(255, 255, 255, 0.4)
53 |
54 | $gradient: rgba(255, 255, 255, 0.2) 0, rgba(255, 255, 255, 0.3) 40%, rgba(255, 255, 255, 0.4) 50%, rgba(255, 255, 255, 0.5) 60%, rgba(255, 255, 255, 0) 70%
55 |
56 | background: radial-gradient($gradient)
57 |
58 | &.waves-classic .waves-ripple
59 | background: rgba(0, 0, 0, 0.2)
60 |
61 | &.waves-classic.waves-light .waves-ripple
62 | background: rgba(255, 255, 255, 0.4)
63 |
64 | .waves-notransition
65 | +waves-transition(none #{"!important"})
66 |
67 | .waves-button,
68 | .waves-circle
69 | +waves-transform(translateZ(0))
70 |
71 | -webkit-mask-image: -webkit-radial-gradient(circle, white 100%, black 100%)
72 |
73 | .waves-button,
74 | .waves-button:hover,
75 | .waves-button:visited,
76 | .waves-button-input
77 | white-space: nowrap
78 | vertical-align: middle
79 | cursor: pointer
80 | border: none
81 | outline: none
82 | color: inherit
83 | background-color: rgba(0, 0, 0, 0)
84 | font-size: 1em
85 | line-height: 1em
86 | text-align: center
87 | text-decoration: none
88 | z-index: 1
89 |
90 | .waves-button
91 | padding: 0.85em 1.1em
92 | border-radius: 0.2em
93 |
94 | .waves-button-input
95 | margin: 0
96 | padding: 0.85em 1.1em
97 |
98 | .waves-input-wrapper
99 | border-radius: 0.2em
100 | vertical-align: middle
101 | display: inline-block
102 |
103 | &.waves-button
104 | padding: 0
105 |
106 | .waves-button-input
107 | position: relative
108 | top: 0
109 | left: 0
110 | z-index: 1
111 |
112 | .waves-circle
113 | text-align: center
114 | width: 2.5em
115 | height: 2.5em
116 | line-height: 2.5em
117 | border-radius: 50%
118 |
119 | .waves-float
120 | -webkit-mask-image: none
121 |
122 | +waves-box-shadow(0px 1px 1.5px 1px rgba(0, 0, 0, 0.12))
123 | +waves-transition(all 300ms)
124 |
125 | &:active
126 | +waves-box-shadow(0px 8px 20px 1px rgba(0, 0, 0, 0.3))
127 |
128 | .waves-block
129 | display: block
130 |
131 | a
132 | &.waves-effect,
133 | &.waves-light
134 | display: inline-block
135 |
--------------------------------------------------------------------------------
/frontend/src/atom/price/price.sass:
--------------------------------------------------------------------------------
1 | $priceStrikeColor: $colorMonotoneMid1
2 | $priceTaxAndDutyFreeColor: $colorMonotoneMid2
3 | $priceDiscountedPromoColor: $colorPrimaryRegular
4 | $priceMobileCenterBorderColor: $colorMonotoneLight
5 | $priceAdditionalBreakpoint: 375px
6 |
7 | .price
8 | display: flex
9 | justify-content: center
10 | flex-wrap: wrap
11 |
12 | &.priceHasPromoDiscountContainer:not(.priceTypeTileView)
13 | justify-content: flex-start
14 |
15 | &.priceTypeTileView
16 | display: flex
17 | justify-content: center
18 |
19 | +respondFrom(s)
20 | display: block
21 |
22 |
23 | .priceRegular
24 | font-size: 18px
25 |
26 | +respondFrom(s)
27 | padding-bottom: 15px
28 | font-size: 22px
29 |
30 | .priceTypeTileView &
31 | font-size: 14px
32 | line-height: 22px
33 | padding: 0 6px
34 |
35 | .priceShowDiscounted &
36 | color: $priceStrikeColor
37 |
38 | .priceHasPromoDiscountContainer:not(.priceTypeTileView) &
39 | border-left: 1px solid $priceMobileCenterBorderColor
40 | padding-left: 16px
41 |
42 | +respondFrom($priceAdditionalBreakpoint)
43 | padding-left: 30px
44 |
45 | +respondFrom(s)
46 | border-left: 0
47 | padding-left: 0
48 |
49 |
50 | .priceTaxAndDutyFree
51 | color: $priceTaxAndDutyFreeColor
52 | letter-spacing: .2px
53 | font-size: 14px
54 | line-height: 18px
55 | width: 100%
56 | margin-top: 15px
57 |
58 | +respondFrom(s)
59 | font-size: 16px
60 | line-height: 24px
61 |
62 |
63 | .pricePromoDiscount
64 | width: 50%
65 | border-right: 1px solid $priceMobileCenterBorderColor
66 | padding-right: 16px
67 | display: flex
68 | justify-content: flex-end
69 |
70 | .priceTypeTileView &
71 | width: auto
72 | border-right: 0
73 | display: block
74 | padding-right: 0
75 | margin-bottom: 0
76 |
77 | +respondFrom($priceAdditionalBreakpoint)
78 | padding-right: 30px
79 |
80 | +respondFrom(s)
81 | width: auto
82 | border-right: 0
83 | padding: 0
84 | display: block
85 | margin-bottom: 30px
86 |
87 | .pricePromoDiscountInner
88 | text-align: center
89 |
90 | +respondFrom(s)
91 | text-align: left
92 |
93 | .pricePromoDiscountLabel,
94 | .priceLabel
95 | +caps
96 | line-height: 16px
97 | padding-bottom: 2px
98 | font-size: 12px
99 | text-decoration: none
100 |
101 | +respondFrom(s)
102 | padding-bottom: 10px
103 |
104 | .pricePromoDiscountLabel
105 | color: $priceDiscountedPromoColor
106 |
107 | .pricePromo,
108 | .priceDiscounted
109 | color: $priceDiscountedPromoColor
110 | font-size: 18px
111 | font-weight: bold
112 | display: block
113 |
114 | +respondFrom(s)
115 | font-size: 22px
116 |
117 | .priceTypeTileView &
118 | font-size: 14px
119 | line-height: 22px
120 | padding: 0 6px
121 |
122 | .pricePromoComponent
123 | display: block
124 |
125 | .priceTypeTileView &
126 | display: inline
127 |
128 | .pricePromoComponentSecondary
129 | margin-top: 5px
130 | font-weight: normal
131 | font-size: 14px
132 |
133 | +respondFrom(s)
134 | margin-top: 10px
135 | font-size: 16px
136 |
137 | .priceTypeTileView &
138 | font-weight: inherit
139 | font-size: inherit
140 |
141 |
142 | .priceValue
143 | .priceShowDiscounted &
144 | text-decoration: line-through
145 |
146 |
147 | .priceTermsConditionLink
148 | display: inline-block
149 | margin-top: 5px
150 | color: $priceDiscountedPromoColor
151 | text-decoration: underline
152 | font-size: 14px
153 |
154 | +respondFrom(s)
155 | margin-top: 10px
156 | font-size: 16px
157 |
--------------------------------------------------------------------------------
/frontend/src/base/style/mdp-ecom-base/core/_typography.sass:
--------------------------------------------------------------------------------
1 | // Typography
2 | // ROBOTO FONT
3 | @font-face
4 | font-family: "Roboto"
5 | src: local(Roboto Thin), url("#{$roboto-font-path}Roboto-Thin.eot")
6 | src: url("#{$roboto-font-path}Roboto-Thin.eot?#iefix") format("embedded-opentype"), url("#{$roboto-font-path}Roboto-Thin.woff2") format("woff2"), url("#{$roboto-font-path}Roboto-Thin.woff") format("woff"), url("#{$roboto-font-path}Roboto-Thin.ttf") format("truetype")
7 | font-weight: 200
8 |
9 | @font-face
10 | font-family: "Roboto"
11 | src: local(Roboto Light), url("#{$roboto-font-path}Roboto-Light.eot")
12 | src: url("#{$roboto-font-path}Roboto-Light.eot?#iefix") format("embedded-opentype"), url("#{$roboto-font-path}Roboto-Light.woff2") format("woff2"), url("#{$roboto-font-path}Roboto-Light.woff") format("woff"), url("#{$roboto-font-path}Roboto-Light.ttf") format("truetype")
13 | font-weight: 300
14 |
15 | @font-face
16 | font-family: "Roboto"
17 | src: local(Roboto Regular), url("#{$roboto-font-path}Roboto-Regular.eot")
18 | src: url("#{$roboto-font-path}Roboto-Regular.eot?#iefix") format("embedded-opentype"), url("#{$roboto-font-path}Roboto-Regular.woff2") format("woff2"), url("#{$roboto-font-path}Roboto-Regular.woff") format("woff"), url("#{$roboto-font-path}Roboto-Regular.ttf") format("truetype")
19 | font-weight: 400
20 |
21 | @font-face
22 | font-family: "Roboto"
23 | src: url("#{$roboto-font-path}Roboto-Medium.eot")
24 | src: url("#{$roboto-font-path}Roboto-Medium.eot?#iefix") format("embedded-opentype"), url("#{$roboto-font-path}Roboto-Medium.woff2") format("woff2"), url("#{$roboto-font-path}Roboto-Medium.woff") format("woff"), url("#{$roboto-font-path}Roboto-Medium.ttf") format("truetype")
25 | font-weight: 500
26 |
27 | @font-face
28 | font-family: "Roboto"
29 | src: url("#{$roboto-font-path}Roboto-Bold.eot")
30 | src: url("#{$roboto-font-path}Roboto-Bold.eot?#iefix") format("embedded-opentype"), url("#{$roboto-font-path}Roboto-Bold.woff2") format("woff2"), url("#{$roboto-font-path}Roboto-Bold.woff") format("woff"), url("#{$roboto-font-path}Roboto-Bold.ttf") format("truetype")
31 | font-weight: 700
32 |
33 | body
34 | font-family: "Roboto", sans-serif
35 | font-weight: 300
36 |
37 | h1, h2, h3, h4, h5, h6
38 | font-weight: 300
39 |
40 | // Responsive headings
41 | @each $key, $val in $grid-breakpoints
42 | +media-breakpoint-up($key)
43 | $y: map-get($responsive-headings, $key)
44 |
45 | @each $name, $value in $y
46 | .#{$name}-responsive
47 | font-size: $value
48 |
49 | // Divider
50 | .divider-new
51 | flex-direction: row
52 | justify-content: center
53 | align-items: center
54 | display: flex
55 | margin-top: $divider-margin-y
56 | margin-bottom: $divider-margin-y
57 |
58 | > h1, h2, h3, h4, h5, h6
59 | margin-bottom: 0
60 |
61 | &:before,
62 | &:after
63 | content: ""
64 | height: 1.5px
65 | flex: 1
66 | height: $divider-height
67 | background: #c6c6c6
68 |
69 | &:before
70 | margin: 0 $divider-margin-x 0 0
71 |
72 | &:after
73 | margin: 0 0 0 $divider-margin-x
74 |
75 | // Blockquote
76 | .blockquote
77 | padding: $blockquote-padding-y $blockquote-padding-x
78 | border-left: .25rem solid #eceeef
79 |
80 | .bq-title
81 | margin-bottom: 0
82 | font-size: $font-size-large
83 | font-weight: 400
84 |
85 | p
86 | padding: $blockquote-p-padding-t 0 $blockquote-p-padding-b $blockquote-p-padding-l
87 | font-size: $blockquote-p-font-size
88 |
89 | @each $name, $color in $basic
90 | .bq-#{$name}
91 | border-left: 3px solid $color !important
92 |
93 | .bq-title
94 | color: $color !important
95 |
96 | @each $name, $color in $basic-mdb-colors
97 | +text-emphasis-variant(".text-#{$name}", $color)
98 |
99 | .font-small
100 | font-size: $font-small
101 |
--------------------------------------------------------------------------------
/Readme.md:
--------------------------------------------------------------------------------
1 | # Official Commerce Flamingo Demo
2 |
3 | Watch online: https://demoshop.flamingo.me/en/
4 |
5 | Or try the powerful Flamingo-Commerce graphql console: https://demoshop.flamingo.me/en/graphql-console
6 |
7 | ## What's inside:
8 |
9 | The demo shop comes with:
10 |
11 | * Using the Flamingo Commerce Standalone Adapter: Products and Categories are indexed from a plain CSV file into an embedded indexed search (bleve). Once an order is placed Flamingo logs the order and sends an E-Mail.
12 |
13 | * The multi context feature of Flamingo is used to have 2 different locales (de and en)
14 |
15 | * An example template using pug and Flamingo Carotene is used.
16 |
17 |
18 | ## Getting Started
19 |
20 | ### Preconditions
21 |
22 | This demo uses Flamingo Carotene, so you should have `npm` installed. (https://www.npmjs.com/get-npm)
23 | Also you need Go installed. (https://golang.org/)
24 |
25 | ### Run the demo shop
26 |
27 | #### Try out with docker:
28 |
29 | ```
30 | docker run --rm -p 3210:3210 iloveflamingo/flamingo-commerce-demo-carotene:latest
31 | ```
32 | Now open http://localhost:3210/
33 |
34 | #### Try the GraphQL API
35 | open http://localhost:3210/en/graphql-console/
36 |
37 | #### Run local from source code:
38 | ```
39 | # clone the repo:
40 | git clone https://github.com/i-love-flamingo/commerce-demo-carotene.git
41 | cd commerce-demo-carotene
42 |
43 | # Download the test catalog - you only need to do it once - it includes products.csv and images:
44 | make download-product-data
45 |
46 | # Prepare translation files:
47 | make translation
48 |
49 | # Build the flamingo-carotene bases templates:
50 | make frontend-build
51 |
52 | # Run flamingo with flamingo-commerce
53 | make serve
54 |
55 | ```
56 |
57 | Now open http://localhost:3210/
58 |
59 | ## About the Demo Frontend - Template
60 | The demo comes with a simple demo template in "frontend/src" that is using carotene-cli
61 |
62 | The template is based on: https://github.com/mdbootstrap/Ecommerce-Template-Bootstrap
63 |
64 | The following things have been changed:
65 | - Markup was transformed to pug and split according to atomic design
66 | - SASS is used instead of scss (`docker run -it -v "$(pwd)":/workdir unibeautify/sass-convert -R . --from scss --to sass`)
67 |
68 | You can start watch mode with rebuilding the frontend after changes with this command:
69 | ```
70 | make frontend
71 | ```
72 | ### License MDBootstrap
73 |
74 | Copyright (c) 2017 MDBootstrap.com
75 |
76 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
77 |
78 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
79 |
80 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
81 |
82 |
83 | ## Production ready?
84 |
85 | This demo project is **not** production ready - at least the following things need to be considered:
86 |
87 | * The template is not optimized and just for demo reasons, in a production template we would probably not use this bootstrap, material design demo as a start. Rather we would start a clean template based on the screen design.
88 | * The Secondary Adapters used in the demo are not full featured.
89 |
--------------------------------------------------------------------------------
/frontend/src/page/home/molecule/carousel/carousel.pug:
--------------------------------------------------------------------------------
1 | #carousel-example-1z.carousel.slide.carousel-fade.pt-4(data-ride='carousel')
2 | // Indicators
3 | ol.carousel-indicators
4 | li.active(data-target='#carousel-example-1z', data-slide-to='0')
5 | li(data-target='#carousel-example-1z', data-slide-to='1')
6 | //- li(data-target='#carousel-example-1z', data-slide-to='2')
7 | // /.Indicators
8 | // Slides
9 | .carousel-inner(role='listbox')
10 | // First slide
11 | .carousel-item.active
12 | // https://pixabay.com/de/flamingo-valentin-herz-valentinstag-600205/
13 | - var imageStyle = "background-image: url('"+asset("asset/img/visuals/flamingo-scetch.jpg")+"'); background-repeat: no-repeat; background-size: cover;"
14 | .view(style=imageStyle)
15 | // Mask & flexbox options
16 | .mask.d-flex.justify-content-center.align-items-center
17 | // Content
18 | .text-center.black-text.mx-5.wow.fadeIn
19 | h1.mb-4
20 | strong Flamingo commerce
21 | //p Blazing fast modern eCommerce frontend framework ideally for your microservice architecture.
22 | p.mb-4.d-none.d-md-block= __("header.welcome.subtitle")
23 | a.btn.btn-dark.btn-lg(target='_blank', href='https://flamingo.me/')
24 | | Learn more
25 | i.fa.fa-graduation-cap.ml-2
26 | // Content
27 | // Mask & flexbox options
28 | // /First slide
29 | // Second slide
30 | //- .carousel-item
31 | // https://pixabay.com/de/digitale-kunst-digital-art-flamingo-3054735/
32 | - var imageStyle = "background-image: url('"+asset("asset/img/visuals/digital-art-3054735_1280.jpg")+"'); background-repeat: no-repeat; background-size: cover;"
33 | .view(style=imageStyle)
34 | // Mask & flexbox options
35 | .mask.d-flex.justify-content-center.align-items-center
36 | // Content
37 | .text-center.white-text.mx-5.wow.fadeIn
38 | h1.mb-4
39 | strong Flamingo eCommerce
40 | p
41 | strong The head for our eCommerce architecture
42 | p.mb-4.d-none.d-md-block
43 | strong
44 | | Blazing fast modern eCommerce frontend framework ideally for your microservice architecture.
45 | a.btn.btn-outline-white.btn-lg(target='_blank', href='https://flamingo.me/')
46 | | Read more
47 | i.fa.fa-graduation-cap.ml-2
48 | // Content
49 | // Mask & flexbox options
50 | // /Second slide
51 | // Third slide
52 | .carousel-item
53 | - var imageStyle = "background-image: url('"+asset("asset/img/visuals/digital-art-3054735_1280.jpg")+"'); background-repeat: no-repeat; background-size: cover;"
54 | .view(style=imageStyle)
55 | // Mask & flexbox options
56 | .mask.rgba-black-strong.d-flex.justify-content-center.align-items-center
57 | // Content
58 | .white-text.mx-5.wow.fadeIn
59 | h1.mb-4
60 | strong Highlights
61 | p.mb-4.d-none.d-md-block
62 | ul
63 | li golang powered high performance rendering
64 | li build with developer happiness in mind.
65 | li ports and adapters - easy to connect to microservices
66 | li flexible commerce domain models
67 | // Content
68 | // Mask & flexbox options
69 | // /Third slide
70 | // /.Slides
71 | // Controls
72 | a.carousel-control-prev(href='#carousel-example-1z', role='button', data-slide='prev')
73 | span.carousel-control-prev-icon(aria-hidden='true')
74 | span.sr-only Previous
75 | a.carousel-control-next(href='#carousel-example-1z', role='button', data-slide='next')
76 | span.carousel-control-next-icon(aria-hidden='true')
77 | span.sr-only Next
78 | // /.Controls
79 | // /.Carousel Wrapper
80 | // Main layout
81 |
--------------------------------------------------------------------------------
/graphql/schema/flamingo.me_flamingo-commerce_v3_search_interfaces_graphql-Service.graphql:
--------------------------------------------------------------------------------
1 | input Commerce_Search_KeyValueFilter {
2 | k: String!
3 | v: [String!]
4 | }
5 |
6 | input Commerce_Search_Request {
7 | pageSize: Int
8 | page: Int
9 | sortBy: String
10 | keyValueFilters: [Commerce_Search_KeyValueFilter!]
11 | query: String
12 | }
13 |
14 | #input Commerce_Search_LiveSearchRequest {
15 | # query: String
16 | #}
17 |
18 | type Commerce_Search_Meta {
19 | query: String!
20 | originalQuery: String!
21 | page: Int!
22 | numPages: Int!
23 | numResults: Int!
24 | sortOptions: [Commerce_Search_SortOption!]
25 | }
26 |
27 | type Commerce_Search_SortOption {
28 | label: String!
29 | field: String!
30 | selected: Boolean!
31 | }
32 |
33 | interface Commerce_Search_Facet {
34 | name: String!
35 | label: String!
36 | position: Int!
37 | items: [Commerce_Search_FacetItem!]!
38 | hasSelectedItem: Boolean!
39 | }
40 |
41 | interface Commerce_Search_FacetItem {
42 | label: String!
43 | value: String!
44 | selected: Boolean!
45 | count: Int!
46 | }
47 |
48 | type Commerce_Search_ListFacet implements Commerce_Search_Facet {
49 | name: String!
50 | label: String!
51 | position: Int!
52 | items: [Commerce_Search_ListFacetItem!]!
53 | hasSelectedItem: Boolean!
54 | }
55 |
56 | type Commerce_Search_ListFacetItem implements Commerce_Search_FacetItem {
57 | label: String!
58 | value: String!
59 | selected: Boolean!
60 | count: Int!
61 | }
62 |
63 | type Commerce_Search_TreeFacet implements Commerce_Search_Facet {
64 | name: String!
65 | label: String!
66 | position: Int!
67 | items: [Commerce_Search_TreeFacetItem!]!
68 | hasSelectedItem: Boolean!
69 | }
70 |
71 | type Commerce_Search_TreeFacetItem implements Commerce_Search_FacetItem {
72 | label: String!
73 | value: String!
74 | selected: Boolean!
75 | count: Int!
76 | active: Boolean!
77 | items: [Commerce_Search_TreeFacetItem!]
78 | }
79 |
80 | type Commerce_Search_RangeFacet implements Commerce_Search_Facet {
81 | name: String!
82 | label: String!
83 | position: Int!
84 | items: [Commerce_Search_RangeFacetItem!]!
85 | hasSelectedItem: Boolean!
86 | }
87 |
88 | type Commerce_Search_RangeFacetItem implements Commerce_Search_FacetItem {
89 | label: String!
90 | value: String!
91 | selected: Boolean!
92 | count: Int!
93 | min: Int!
94 | max: Int!
95 | selectedMin: Int!
96 | selectedMax: Int!
97 | }
98 |
99 | type Commerce_Search_Suggestion {
100 | text: String!
101 | highlight: String!
102 | }
103 |
104 | type Commerce_Search_Action {
105 | type: String!
106 | content: String!
107 | }
108 |
109 | type Commerce_Search_Promotion {
110 | title: String!
111 | content: String!
112 | url: String!
113 | media: Commerce_Search_PromotionMedia
114 | }
115 |
116 | type Commerce_Search_PromotionMedia {
117 | type: String!
118 | mimeType: String!
119 | usage: String!
120 | title: String!
121 | reference: String!
122 | }
123 |
124 | #type Commerce_Search_Result {
125 | # hits: []Commerce_Search_Document / Or maybe we dont need hits and the modules need to add a edge to this object... we will see
126 | # searchMeta: Commerce_Search_Meta!
127 | # Facets: domain.FacetCollection
128 | # suggestions: [Commerce_Search_Suggestion]
129 | #}
130 |
131 |
132 | #extend type Query {
133 | # Commerce_Search(searchRequest: Commerce_Search_Request): Commerce_Search_Result
134 | # Commerce_Search_LiveSearch(searchRequest: Commerce_Search_LiveSearchRequest): Commerce_Search_ResultCommerce_Search_LiveSearchRequest!
135 | #}
136 |
--------------------------------------------------------------------------------
/frontend/src/base/style/mdp-ecom-base/free/_forms.sass:
--------------------------------------------------------------------------------
1 | // Forms basic
2 | // Input + label wrapper styles
3 | .md-form
4 | // Text inputs
5 | input[type=text],
6 | input[type=password],
7 | input[type=email],
8 | input[type=url],
9 | input[type=time],
10 | input[type=date],
11 | input[type=datetime-local],
12 | input[type=tel],
13 | input[type=number],
14 | input[type=search-md],
15 | input[type=search],
16 | textarea.md-textarea
17 | // General Styles
18 | transition: $input-transition
19 | outline: none
20 | box-shadow: none
21 | border: none
22 | border-bottom: 1px solid $input-border-color
23 | border-radius: 0
24 | box-sizing: content-box
25 | background-color: transparent
26 |
27 | // Focused input style
28 | &:focus:not([readonly])
29 | box-shadow: 0 1px 0 0 $input-md-focus-color
30 | border-bottom: 1px solid $input-md-focus-color
31 |
32 | // Focused label style
33 | + label
34 | color: $input-md-focus-color
35 |
36 | // Form message shared styles
37 | + label:after
38 | content: ""
39 | position: absolute
40 | top: $input-label-after-top
41 | display: block
42 | opacity: 0
43 | transition: $input-label-after-transition
44 |
45 | // Valid input style
46 | &.valid, &:focus.valid
47 | border-bottom: 1px solid $input-success-color
48 | box-shadow: 0 1px 0 0 $input-success-color
49 |
50 | &.valid + label:after, &:focus.valid + label:after
51 | content: attr(data-success)
52 | color: $input-success-color
53 | opacity: 1
54 |
55 | // Invalid input style
56 | &.invalid, &:focus.invalid
57 | border-bottom: 1px solid $input-error-color
58 | box-shadow: 0 1px 0 0 $input-error-color
59 |
60 | &.invalid + label:after, &:focus.invalid + label:after
61 | content: attr(data-error)
62 | color: $input-error-color
63 | opacity: 1
64 |
65 | .was-validated
66 | input[type=text]
67 | &:valid
68 | + label
69 | color: $input-success-color !important
70 |
71 | &:invalid
72 | + label
73 | color: $input-error-color !important
74 |
75 | .form-control
76 | &:valid:focus
77 | box-shadow: 0 1px 0 0 $input-success-color !important
78 |
79 | &:valid
80 | border-color: $input-success-color !important
81 |
82 | &:invalid:focus
83 | box-shadow: 0 1px 0 0 $input-error-color !important
84 |
85 | &:invalid
86 | border-color: $input-error-color !important
87 |
88 | // Input with label
89 | .form-control
90 | margin: 0 0 $input-form-control-margin-bottom 0
91 | border-radius: 0
92 | padding: $input-form-control-padding-top 0 $input-form-control-padding-bottom 0
93 | background-image: none
94 | background-color: transparent
95 |
96 | &:focus
97 | box-shadow: none
98 | background: transparent
99 |
100 | &:disabled,
101 | &[readonly]
102 | border-bottom: 1px solid $grey-lighten-1
103 | background-color: transparent
104 |
105 | +make-input($input-label-font-size, $input-label-active-font-size, $input-prefix-top, $input-prefix-font-size, $input-prefix-margin-left, $input-prefix-width, $input-form-text-ml)
106 |
107 | position: relative
108 | margin-top: $input-md-form-margin-top
109 | margin-bottom: $input-md-form-margin-bottom
110 |
111 | label
112 | position: absolute
113 | top: $input-label-top
114 | left: 0
115 | transition: $input-label-transition
116 | cursor: text
117 | color: $input-label-color
118 |
119 | &.active
120 | transform: $input-label-active-transform
121 |
122 | .prefix
123 | position: absolute
124 | transition: $input-prefix-transition
125 |
126 | &.active
127 | color: $input-md-focus-color
128 |
129 | &.form-lg
130 | +make-input($input-label-font-size-lg, $input-label-active-font-size-lg, $input-prefix-top-lg, $input-prefix-font-size-lg, $input-prefix-margin-left-lg, $input-prefix-width-lg, $input-form-text-ml-lg)
131 |
132 | &.form-sm
133 | +make-input($input-label-font-size-sm, $input-label-active-font-size-sm, $input-prefix-top-sm, $input-prefix-font-size-sm, $input-prefix-margin-left-sm, $input-prefix-width-sm, $input-form-text-ml-sm)
134 |
135 | // Textarea
136 | textarea
137 | &.md-textarea
138 | overflow-y: hidden
139 | padding: $textarea-padding 0
140 | resize: none
141 |
142 | &.md-textarea-auto
143 | padding: 0
144 | padding-top: $textarea-padding
145 |
--------------------------------------------------------------------------------
/frontend/src/page/product/product.pug:
--------------------------------------------------------------------------------
1 | extends /template/base/base
2 |
3 | include /atom/price/price
4 | include /molecule/productMedia/productMedia
5 | include /atom/dropdown/dropdown
6 | include /organism/productList/productList
7 |
8 | block maincontent
9 | //- Detect the baseData of the product depending on its context
10 | - var baseData = product.baseData
11 |
12 | //+debug(baseData)
13 | //+debug(product.saleableData)
14 | main.mt-5.pt-4
15 | .container.dark-grey-text.mt-5
16 | // Grid row
17 | .row.wow.fadeIn
18 | // Grid column
19 | .col-md-6.mb-4
20 | each mediaItem in baseData.media
21 | if mediaItem.usage === 'detail' || mediaItem.usage === 'gallery'
22 | +productMedia(mediaItem, '700x').media.img-fluid
23 | // Grid column
24 | // Grid column
25 | .col-md-6.mb-4
26 | // Content
27 | .p-4
28 | .mb-3
29 | - var i = 1
30 | each categoryTeaser in product.baseData.categories
31 | - var i = i + 1
32 | if i<4
33 | a(href='')
34 | span.badge.purple.mr-1=categoryTeaser.name
35 |
36 | p.lead
37 | +price(product)
38 | p.lead.font-weight-bold=baseData.title
39 | p !{baseData.description}
40 | if product.baseData.hasAttribute("colour")
41 | p Colour: #{product.baseData.attribute("colour").value}
42 |
43 | if product.type() == "configurable" || product.type() == "configurable_with_activevariant"
44 | .row.p-3
45 | span.col-small=__("select_variant").setDefaultLabel("select a variant:")
46 | .col
47 | +dropdown()(name="variant-selector" id="variant-selector" data-qa="productVariants")
48 | each variant in product.variants
49 | - var configurableActiveVariant = product.getConfigurableWithActiveVariant(variant.baseData.marketPlaceCode)
50 | - var configurableActiveVariantUrl = getProductUrl(configurableActiveVariant)
51 | - var selected = false
52 | if product.type() == "configurable_with_activevariant"
53 | if product.activeVariant.baseData.marketPlaceCode == variant.baseData.marketPlaceCode
54 | - var selected = true
55 | if selected
56 | option(value=variant.baseData.marketPlaceCode data-url=configurableActiveVariantUrl selected="selected")= variant.baseData.title
57 | else
58 | option(value=variant.baseData.marketPlaceCode data-url=configurableActiveVariantUrl)= variant.baseData.title
59 |
60 | if product.isSaleable
61 | form.d-flex.justify-content-left(action=url('cart.add',{marketplaceCode:baseData.marketPlaceCode}))
62 | // Default input
63 | input.form-control(type='number', value='1', aria-label='Search', style='width: 100px', name="qty")
64 | button.btn.btn-primary.btn-md.my-0.p(type='submit')
65 | | Add for home delivery
66 | i.fa.fa-shopping-cart.ml-1
67 | button.btn.btn-primary.btn-md.my-0.p(type='submit', name="deliveryCode", value="pickup_store")
68 | | Add for pickup
69 | i.fa.fa-shopping-cart.ml-1
70 | else
71 | p=__("not saleable")
72 | // Content
73 | // Grid column
74 | // Grid row
75 | hr
76 | // Grid row
77 | .row.d-flex.justify-content-center.wow.fadeIn
78 | // Grid column
79 | .col-md-6.text-center
80 | h4.my-4.h4=__("Additional information")
81 | - var attributeKeysForDisplay = config('template.product.descriptionAttributes')
82 | each attributeKey in attributeKeysForDisplay
83 | if baseData.hasAttribute(attributeKey) && baseData.attributes[attributeKey].value !== ''
84 | dt.productDetailsAttribute
85 | strong= __('attribute.' + attributeKey, attributeKey) + ':'
86 | dd.productDetailsAttributeData
87 | - var formattedValue = stripTags(baseData.attributes[attributeKey].value)
88 | = __('attribute.' + attributeKey + '.value.' + baseData.attributes[attributeKey].value, formattedValue)
89 | // Grid column
90 | // Grid row
91 | // Grid row
92 | .row.wow.fadeIn
93 | h4.my-4.h4=__("Other products")
94 | - var filterByCategory = "headphone_accessories"
95 | if baseData.mainCategory.code != ""
96 | - var filterByCategory = baseData.mainCategory.code
97 | +productListByProductSearchResult(findProducts("homepagewidget",{"query":"","pageSize": "4","sortDirection":"A","sortBy":'random'},{"categories":[filterByCategory]}))
--------------------------------------------------------------------------------
/translations/merged/de-de.untranslated.yaml:
--------------------------------------------------------------------------------
1 | cart.button.continueShopping:
2 | other: Continue Shopping
3 | cart.button.reserveAndCollect:
4 | other: Reserve & Collect
5 | cart.column.price:
6 | other: Price
7 | cart.column.quantity:
8 | other: Quantity
9 | cart.column.sum:
10 | other: Sum
11 | cart.group.title:
12 | other: products
13 | cart.item.detail:
14 | other: 'SKU: {{ .SKU }}'
15 | cart.item.remove:
16 | other: remove item
17 | cart.loyalty.label:
18 | other: Heathrow Reward points
19 | cart.reserveInfo.collectedAtShop:
20 | other: The items must be paid for and collected at the shop you have made the purchase from on your day of travel, prior to flying.
21 | cart.reserveInfo.individualStorePolicy:
22 | other: Reservations will be confirmed in accordance with individual store policy, which our customer service team will verify to you.
23 | cart.reserveInfo.noPayment:
24 | other: No payment is taken and you have no obligation to purchase your reserved shopping requests if you change your mind.
25 | cart.total.label:
26 | other: Total
27 | checkout.back_to_cart:
28 | other: Back to cart
29 | checkout.cart_item_error_hint:
30 | other: There are invalid items in your cart. Please check below and resolve the issue.
31 | checkout.error.terms_and_conditions_required:
32 | other: Please accept the terms and conditions.
33 | checkout.legalConfirmation.termsAndConditions:
34 | other: Check here to indicate that you have read and agree to the privacy policies and terms and conditions of the Heathrow Boutique.
35 | checkout.no_items_in_cart:
36 | other: No Items in your cart
37 | checkout.success_message1:
38 | other: 'Your order has been received. Your order number is: {{.OrderId}}'
39 | checkout.success_message2:
40 | other: An confirmation email will be send to {{.Email}}.
41 | delivery:
42 | other: Home delivery
43 | error.404.headline:
44 | other: Error 404
45 | error.503.headline:
46 | other: Error 503
47 | error.common.headline:
48 | other: Error occured
49 | error.homeButton:
50 | other: Back to home
51 | facet.header.brandCode:
52 | other: Brand
53 | miniCart.buttonCartView:
54 | other: Shopping Bag
55 | miniCart.buttonReserveAndCollect:
56 | other: Reserve & Collect
57 | miniCart.empty:
58 | other: Your cart is empty
59 | miniCart.hiddenProduct:
60 | other: 1 more product
61 | miniCart.hiddenProducts:
62 | other: '{{.qty}} more products'
63 | miniCart.removeItem:
64 | other: Remove {{.title}}
65 | miniCart.total:
66 | other: 'Total: {{.total}}'
67 | pickup_store:
68 | other: Instore pickup
69 | product.attribute.__group_packageSizes:
70 | other: Package size
71 | product.attribute.baseColor:
72 | other: Base color
73 | product.attribute.manufacturerColor:
74 | other: Manufacturer color
75 | product.attribute.washingInstructions:
76 | other: Washing Instruction
77 | search.footer.callNow:
78 | other: Call now +44 (0)800 678 5324
79 | search.footer.description:
80 | other: Our Shopping Services team are available to answer any questions that you have about brands, products or services at Heathrow.
81 | search.footer.headline:
82 | other: Can’t see what you want?
83 | search.found.brands:
84 | other: Found in Brands
85 | search.found.other:
86 | other: Other results (%s)
87 | search.found.products:
88 | other: Found in Products ({{ .numResults }})
89 | search.live.brands:
90 | other: Brands
91 | search.live.contentPages:
92 | other: Content pages
93 | search.live.inRetailers:
94 | other: in retailers
95 | search.live.input.aria:
96 | other: Search website
97 | search.live.input.placeholder:
98 | other: Search
99 | search.live.label:
100 | other: Search
101 | search.live.noResults:
102 | other: Sorry, there are no results matching your query.
103 | search.live.popular:
104 | other: Popular searches
105 | search.live.products:
106 | other: Found products
107 | search.live.reset:
108 | other: Reset search
109 | search.live.results:
110 | other: Search results
111 | search.live.retailers:
112 | other: Retailers
113 | search.live.showAll:
114 | other: Show all results
115 | search.live.submit.aria:
116 | other: Submit search
117 | search.live.totalResults:
118 | other: Total results
119 | search.noresult.titleWithQuery:
120 | other: No results for "{{ .query }}"
121 | search.noresult.widgetHeadline:
122 | other: Trending Results
123 | search.result.title:
124 | other: Search results
125 | search.result.titleWithQuery:
126 | other: Search results for "{{ .query }}"
127 | search.suggestion.title:
128 | other: Here are some results for "{{ .query }}"
129 | searchNoResultsHeader.buttonLabel:
130 | other: Search again
131 | searchNoResultsHeader.text:
132 | other: Please check for misspellings or broaden your search by using fewer keywords.
Alternatively, browse our products by selecting a category from the menu.
133 | searchNoResultsHeader.title:
134 | other: We couldn't find any results
that match your search
135 |
--------------------------------------------------------------------------------
/translations/merged/en-gb.all.yaml:
--------------------------------------------------------------------------------
1 | cart.button.continueShopping:
2 | other: Continue Shopping
3 | cart.button.reserveAndCollect:
4 | other: Reserve & Collect
5 | cart.column.price:
6 | other: Price
7 | cart.column.quantity:
8 | other: Quantity
9 | cart.column.sum:
10 | other: Sum
11 | cart.group.title:
12 | other: products
13 | cart.item.detail:
14 | other: 'SKU: {{ .SKU }}'
15 | cart.item.remove:
16 | other: remove item
17 | cart.loyalty.label:
18 | other: Heathrow Reward points
19 | cart.reserveInfo.collectedAtShop:
20 | other: The items must be paid for and collected at the shop you have made the purchase from on your day of travel, prior to flying.
21 | cart.reserveInfo.individualStorePolicy:
22 | other: Reservations will be confirmed in accordance with individual store policy, which our customer service team will verify to you.
23 | cart.reserveInfo.noPayment:
24 | other: No payment is taken and you have no obligation to purchase your reserved shopping requests if you change your mind.
25 | cart.total.label:
26 | other: Total
27 | checkout.back_to_cart:
28 | other: Back to cart
29 | checkout.cart_item_error_hint:
30 | other: There are invalid items in your cart. Please check below and resolve the issue.
31 | checkout.error.terms_and_conditions_required:
32 | other: Please accept the terms and conditions.
33 | checkout.legalConfirmation.termsAndConditions:
34 | other: Check here to indicate that you have read and agree to the privacy policies and terms and conditions of the Heathrow Boutique.
35 | checkout.no_items_in_cart:
36 | other: No Items in your cart
37 | checkout.success_message1:
38 | other: 'Your order has been received. Your order number is: {{.OrderId}}'
39 | checkout.success_message2:
40 | other: An confirmation email will be send to {{.Email}}.
41 | delivery:
42 | other: Home delivery
43 | error.404.headline:
44 | other: Error 404
45 | error.503.headline:
46 | other: Error 503
47 | error.common.headline:
48 | other: Error occured
49 | error.homeButton:
50 | other: Back to home
51 | facet.header.brandCode:
52 | other: Brand
53 | header.welcome.subtitle:
54 | other: Standard demo shop with carotene templates
55 | miniCart.buttonCartView:
56 | other: Shopping Bag
57 | miniCart.buttonReserveAndCollect:
58 | other: Reserve & Collect
59 | miniCart.empty:
60 | other: Your cart is empty
61 | miniCart.hiddenProduct:
62 | other: 1 more product
63 | miniCart.hiddenProducts:
64 | other: '{{.qty}} more products'
65 | miniCart.removeItem:
66 | other: Remove {{.title}}
67 | miniCart.total:
68 | other: 'Total: {{.total}}'
69 | pickup_store:
70 | other: Instore pickup
71 | product.attribute.__group_packageSizes:
72 | other: Package size
73 | product.attribute.baseColor:
74 | other: Base color
75 | product.attribute.manufacturerColor:
76 | other: Manufacturer color
77 | product.attribute.washingInstructions:
78 | other: Washing Instruction
79 | search.footer.callNow:
80 | other: Call now +44 (0)800 678 5324
81 | search.footer.description:
82 | other: Our Shopping Services team are available to answer any questions that you have about brands, products or services at Heathrow.
83 | search.footer.headline:
84 | other: Can’t see what you want?
85 | search.found.brands:
86 | other: Found in Brands
87 | search.found.other:
88 | other: Other results (%s)
89 | search.found.products:
90 | other: Found in Products ({{ .numResults }})
91 | search.live.brands:
92 | other: Brands
93 | search.live.contentPages:
94 | other: Content pages
95 | search.live.inRetailers:
96 | other: in retailers
97 | search.live.input.aria:
98 | other: Search website
99 | search.live.input.placeholder:
100 | other: Search
101 | search.live.label:
102 | other: Search
103 | search.live.noResults:
104 | other: Sorry, there are no results matching your query.
105 | search.live.popular:
106 | other: Popular searches
107 | search.live.products:
108 | other: Found products
109 | search.live.reset:
110 | other: Reset search
111 | search.live.results:
112 | other: Search results
113 | search.live.retailers:
114 | other: Retailers
115 | search.live.showAll:
116 | other: Show all results
117 | search.live.submit.aria:
118 | other: Submit search
119 | search.live.totalResults:
120 | other: Total results
121 | search.noresult.titleWithQuery:
122 | other: No results for "{{ .query }}"
123 | search.noresult.widgetHeadline:
124 | other: Trending Results
125 | search.result.title:
126 | other: Search results
127 | search.result.titleWithQuery:
128 | other: Search results for "{{ .query }}"
129 | search.suggestion.title:
130 | other: Here are some results for "{{ .query }}"
131 | searchNoResultsHeader.buttonLabel:
132 | other: Search again
133 | searchNoResultsHeader.text:
134 | other: Please check for misspellings or broaden your search by using fewer keywords.
Alternatively, browse our products by selecting a category from the menu.
135 | searchNoResultsHeader.title:
136 | other: We couldn't find any results
that match your search
137 |
--------------------------------------------------------------------------------
/frontend/src/base/style/mdp-ecom-base/free/_animations-basic.sass:
--------------------------------------------------------------------------------
1 | /*!
2 | * animate.css -http://daneden.me/animate
3 | * Version - 3.6.0
4 | * Licensed under the MIT license - http://opensource.org/licenses/MIT
5 | *
6 | * Copyright (c) 2018 Daniel Eden
7 |
8 | .animated
9 | -webkit-animation-duration: 1s
10 | animation-duration: 1s
11 | -webkit-animation-fill-mode: both
12 | animation-fill-mode: both
13 |
14 | .animated.infinite
15 | -webkit-animation-iteration-count: infinite
16 | animation-iteration-count: infinite
17 |
18 | @-webkit-keyframes fadeIn
19 | from
20 | opacity: 0
21 |
22 | to
23 | opacity: 1
24 |
25 | @keyframes fadeIn
26 | from
27 | opacity: 0
28 |
29 | to
30 | opacity: 1
31 |
32 | .fadeIn
33 | -webkit-animation-name: fadeIn
34 | animation-name: fadeIn
35 |
36 | @-webkit-keyframes fadeInDown
37 | from
38 | opacity: 0
39 | -webkit-transform: translate3d(0, -100%, 0)
40 | transform: translate3d(0, -100%, 0)
41 |
42 | to
43 | opacity: 1
44 | -webkit-transform: translate3d(0, 0, 0)
45 | transform: translate3d(0, 0, 0)
46 |
47 | @keyframes fadeInDown
48 | from
49 | opacity: 0
50 | -webkit-transform: translate3d(0, -100%, 0)
51 | transform: translate3d(0, -100%, 0)
52 |
53 | to
54 | opacity: 1
55 | -webkit-transform: translate3d(0, 0, 0)
56 | transform: translate3d(0, 0, 0)
57 |
58 | .fadeInDown
59 | -webkit-animation-name: fadeInDown
60 | animation-name: fadeInDown
61 |
62 | @-webkit-keyframes fadeInLeft
63 | from
64 | opacity: 0
65 | -webkit-transform: translate3d(-100%, 0, 0)
66 | transform: translate3d(-100%, 0, 0)
67 |
68 | to
69 | opacity: 1
70 | -webkit-transform: translate3d(0, 0, 0)
71 | transform: translate3d(0, 0, 0)
72 |
73 | @keyframes fadeInLeft
74 | from
75 | opacity: 0
76 | -webkit-transform: translate3d(-100%, 0, 0)
77 | transform: translate3d(-100%, 0, 0)
78 |
79 | to
80 | opacity: 1
81 | -webkit-transform: translate3d(0, 0, 0)
82 | transform: translate3d(0, 0, 0)
83 |
84 | .fadeInLeft
85 | -webkit-animation-name: fadeInLeft
86 | animation-name: fadeInLeft
87 |
88 | @-webkit-keyframes fadeInRight
89 | from
90 | opacity: 0
91 | -webkit-transform: translate3d(100%, 0, 0)
92 | transform: translate3d(100%, 0, 0)
93 |
94 | to
95 | opacity: 1
96 | -webkit-transform: translate3d(0, 0, 0)
97 | transform: translate3d(0, 0, 0)
98 |
99 | @keyframes fadeInRight
100 | from
101 | opacity: 0
102 | -webkit-transform: translate3d(100%, 0, 0)
103 | transform: translate3d(100%, 0, 0)
104 |
105 | to
106 | opacity: 1
107 | -webkit-transform: translate3d(0, 0, 0)
108 | transform: translate3d(0, 0, 0)
109 |
110 | .fadeInRight
111 | -webkit-animation-name: fadeInRight
112 | animation-name: fadeInRight
113 |
114 | @-webkit-keyframes fadeInUp
115 | from
116 | opacity: 0
117 | -webkit-transform: translate3d(0, 100%, 0)
118 | transform: translate3d(0, 100%, 0)
119 |
120 | to
121 | opacity: 1
122 | -webkit-transform: translate3d(0, 0, 0)
123 | transform: translate3d(0, 0, 0)
124 |
125 | @keyframes fadeInUp
126 | from
127 | opacity: 0
128 | -webkit-transform: translate3d(0, 100%, 0)
129 | transform: translate3d(0, 100%, 0)
130 |
131 | to
132 | opacity: 1
133 | -webkit-transform: translate3d(0, 0, 0)
134 | transform: translate3d(0, 0, 0)
135 |
136 | .fadeInUp
137 | -webkit-animation-name: fadeInUp
138 | animation-name: fadeInUp
139 |
140 | @-webkit-keyframes fadeOut
141 | from
142 | opacity: 1
143 |
144 | to
145 | opacity: 0
146 |
147 | @keyframes fadeOut
148 | from
149 | opacity: 1
150 |
151 | to
152 | opacity: 0
153 |
154 | .fadeOut
155 | -webkit-animation-name: fadeOut
156 | animation-name: fadeOut
157 |
158 | @-webkit-keyframes fadeOutDown
159 | from
160 | opacity: 1
161 |
162 | to
163 | opacity: 0
164 | -webkit-transform: translate3d(0, 100%, 0)
165 | transform: translate3d(0, 100%, 0)
166 |
167 | @keyframes fadeOutDown
168 | from
169 | opacity: 1
170 |
171 | to
172 | opacity: 0
173 | -webkit-transform: translate3d(0, 100%, 0)
174 | transform: translate3d(0, 100%, 0)
175 |
176 | .fadeOutDown
177 | -webkit-animation-name: fadeOutDown
178 | animation-name: fadeOutDown
179 |
180 | @keyframes fadeOutLeft
181 | from
182 | opacity: 1
183 |
184 | to
185 | opacity: 0
186 | -webkit-transform: translate3d(-100%, 0, 0)
187 | transform: translate3d(-100%, 0, 0)
188 |
189 | .fadeOutLeft
190 | -webkit-animation-name: fadeOutLeft
191 | animation-name: fadeOutLeft
192 |
193 | @-webkit-keyframes fadeOutRight
194 | from
195 | opacity: 1
196 |
197 | to
198 | opacity: 0
199 | -webkit-transform: translate3d(100%, 0, 0)
200 | transform: translate3d(100%, 0, 0)
201 |
202 | @keyframes fadeOutRight
203 | from
204 | opacity: 1
205 |
206 | to
207 | opacity: 0
208 | -webkit-transform: translate3d(100%, 0, 0)
209 | transform: translate3d(100%, 0, 0)
210 |
211 | .fadeOutRight
212 | -webkit-animation-name: fadeOutRight
213 | animation-name: fadeOutRight
214 |
215 | @-webkit-keyframes fadeOutUp
216 | from
217 | opacity: 1
218 |
219 | to
220 | opacity: 0
221 | -webkit-transform: translate3d(0, -100%, 0)
222 | transform: translate3d(0, -100%, 0)
223 |
224 | @keyframes fadeOutUp
225 | from
226 | opacity: 1
227 |
228 | to
229 | opacity: 0
230 | -webkit-transform: translate3d(0, -100%, 0)
231 | transform: translate3d(0, -100%, 0)
232 |
233 | .fadeOutUp
234 | -webkit-animation-name: fadeOutUp
235 | animation-name: fadeOutUp
236 |
--------------------------------------------------------------------------------
/graphql/schema/flamingo.me_flamingo-commerce_v3_checkout_interfaces_graphql-Service.graphql:
--------------------------------------------------------------------------------
1 | type Commerce_Checkout_StartPlaceOrder_Result {
2 | uuid: String!
3 | }
4 | # Commerce_Checkout_PlaceOrderContext represents the result of the current (running) place order mutation
5 | type Commerce_Checkout_PlaceOrderContext {
6 | # The Cart that is going to be placed
7 | cart: Commerce_Cart_DecoratedCart
8 | # The placed order in case order is already placed
9 | orderInfos: Commerce_Checkout_PlacedOrderInfos
10 | # State depending on the state of payment and place order - state may contain additional infos
11 | state: Commerce_Checkout_PlaceOrderState_State!
12 | # A unique id for the process
13 | uuid: String!
14 | }
15 |
16 |
17 | # Commerce_Checkout_PlacedOrderInfos - infos about the placed orders - typically shown on a suceess page
18 | type Commerce_Checkout_PlacedOrderInfos {
19 | paymentInfos: [Commerce_Checkout_PlaceOrderPaymentInfo!]
20 | placedOrderInfos: [Commerce_Cart_PlacedOrderInfo!]
21 | email: String!
22 | }
23 |
24 | type Commerce_Checkout_PlaceOrderPaymentInfo {
25 | gateway: String!
26 | paymentProvider: String!
27 | method: String!
28 | amount: Commerce_Price!
29 | title: String!
30 | }
31 |
32 |
33 | interface Commerce_Checkout_PlaceOrderState_State {
34 | name: String!
35 | }
36 |
37 | type Commerce_Checkout_PlaceOrderState_State_Wait implements Commerce_Checkout_PlaceOrderState_State {
38 | name: String!
39 | }
40 |
41 | type Commerce_Checkout_PlaceOrderState_State_WaitForCustomer implements Commerce_Checkout_PlaceOrderState_State {
42 | name: String!
43 | }
44 |
45 | type Commerce_Checkout_PlaceOrderState_State_Success implements Commerce_Checkout_PlaceOrderState_State {
46 | name: String!
47 | }
48 |
49 | type Commerce_Checkout_PlaceOrderState_State_Failed implements Commerce_Checkout_PlaceOrderState_State {
50 | name: String!
51 | reason: Commerce_Checkout_PlaceOrderState_State_FailedReason!
52 | }
53 |
54 | type Commerce_Checkout_PlaceOrderState_State_ShowIframe implements Commerce_Checkout_PlaceOrderState_State {
55 | name: String!
56 | URL: String!
57 | }
58 |
59 | type Commerce_Checkout_PlaceOrderState_State_ShowHTML implements Commerce_Checkout_PlaceOrderState_State {
60 | name: String!
61 | HTML: String!
62 | }
63 |
64 | type Commerce_Checkout_PlaceOrderState_State_Redirect implements Commerce_Checkout_PlaceOrderState_State {
65 | name: String!
66 | URL: String!
67 | }
68 |
69 | type Commerce_Checkout_PlaceOrderState_State_TriggerClientSDK implements Commerce_Checkout_PlaceOrderState_State {
70 | name: String!
71 | URL: String!
72 | data: String!
73 | }
74 |
75 | type Commerce_Checkout_PlaceOrderState_State_ShowWalletPayment implements Commerce_Checkout_PlaceOrderState_State {
76 | name: String!
77 | "Wallet payment method that was chosen previously"
78 | paymentMethod: String!
79 | "Information needed to create a payment using the PaymentRequest API"
80 | paymentRequestAPI: Commerce_Checkout_PlaceOrderState_PaymentRequestAPI!
81 | }
82 |
83 | type Commerce_Checkout_PlaceOrderState_PaymentRequestAPI {
84 | "Contains the JSON encoded method data for the PaymentRequest API"
85 | methodData: String!
86 | "Contains the JSON encoded details for the PaymentRequest API"
87 | details: String!
88 | "Contains the JSON encoded options for the PaymentRequest API"
89 | options: String!
90 | "Optional endpoint used for obtaining a merchant session, not set if the wallet payment doesn't require a merchant validation"
91 | merchantValidationURL: String
92 | "Endpoint to sent completed payment to"
93 | completeURL: String!
94 | }
95 |
96 | type Commerce_Checkout_PlaceOrderState_State_PostRedirect implements Commerce_Checkout_PlaceOrderState_State {
97 | name: String!
98 | URL: String!
99 | Parameters: [Commerce_Checkout_PlaceOrderState_Form_Parameter!]
100 | }
101 |
102 | interface Commerce_Checkout_PlaceOrderState_State_FailedReason {
103 | reason: String
104 | }
105 |
106 |
107 | type Commerce_Checkout_PlaceOrderState_State_FailedReason_Error implements Commerce_Checkout_PlaceOrderState_State_FailedReason {
108 | reason: String
109 | }
110 |
111 | type Commerce_Checkout_PlaceOrderState_State_FailedReason_PaymentError implements Commerce_Checkout_PlaceOrderState_State_FailedReason {
112 | reason: String
113 | }
114 |
115 | type Commerce_Checkout_PlaceOrderState_State_FailedReason_CanceledByCustomer implements Commerce_Checkout_PlaceOrderState_State_FailedReason {
116 | reason: String
117 | }
118 |
119 | type Commerce_Checkout_PlaceOrderState_State_FailedReason_PaymentCanceledByCustomer implements Commerce_Checkout_PlaceOrderState_State_FailedReason {
120 | reason: String
121 | }
122 |
123 | type Commerce_Checkout_PlaceOrderState_State_FailedReason_CartValidationError implements Commerce_Checkout_PlaceOrderState_State_FailedReason {
124 | reason: String
125 | validationResult: Commerce_Cart_ValidationResult!
126 | }
127 |
128 | type Commerce_Checkout_PlaceOrderState_Form_Parameter {
129 | key: String!
130 | value: [String!]
131 | }
132 |
133 | extend type Query {
134 | # Is there a active place order process
135 | Commerce_Checkout_ActivePlaceOrder: Boolean!
136 | Commerce_Checkout_CurrentContext: Commerce_Checkout_PlaceOrderContext!
137 | }
138 |
139 | extend type Mutation {
140 | # Starts a new process and will replace existing ones
141 | Commerce_Checkout_StartPlaceOrder(returnUrl: String!): Commerce_Checkout_StartPlaceOrder_Result!
142 | # Cancels to current running place order process, possible if state is not final
143 | Commerce_Checkout_CancelPlaceOrder: Boolean!
144 | # Clears the last stored place order process
145 | Commerce_Checkout_ClearPlaceOrder: Boolean!
146 | # Gets the last stored place order state and ensures that the state machine proceeds, non blocking
147 | Commerce_Checkout_RefreshPlaceOrder: Commerce_Checkout_PlaceOrderContext!
148 | # Gets the most recent place order state by waiting for the state machine to proceed, therefore blocking
149 | Commerce_Checkout_RefreshPlaceOrderBlocking: Commerce_Checkout_PlaceOrderContext!
150 | }
151 |
--------------------------------------------------------------------------------
/go.mod:
--------------------------------------------------------------------------------
1 | module flamingo.me/commerce-demo-carotene
2 |
3 | go 1.21
4 |
5 | toolchain go1.21.7
6 |
7 | require (
8 | flamingo.me/dingo v0.2.10
9 | flamingo.me/flamingo-commerce-adapter-standalone v0.0.5-beta
10 | flamingo.me/flamingo-commerce/v3 v3.9.0
11 | flamingo.me/flamingo/v3 v3.8.0
12 | flamingo.me/form v1.1.2
13 | flamingo.me/graphql v1.11.1
14 | flamingo.me/pugtemplate v1.3.1
15 | flamingo.me/swagger v0.0.0-20200904191647-041b9dd247c7
16 | github.com/99designs/gqlgen v0.17.43
17 | github.com/spf13/cobra v1.8.0
18 | github.com/swaggo/swag v1.16.3
19 | github.com/vektah/gqlparser/v2 v2.5.11
20 | )
21 |
22 | require (
23 | contrib.go.opencensus.io/exporter/jaeger v0.2.1 // indirect
24 | contrib.go.opencensus.io/exporter/prometheus v0.4.2 // indirect
25 | contrib.go.opencensus.io/exporter/zipkin v0.1.2 // indirect
26 | cuelang.org/go v0.0.15 // indirect
27 | github.com/KyleBanks/depth v1.2.1 // indirect
28 | github.com/RoaringBitmap/roaring v0.4.23 // indirect
29 | github.com/agnivade/levenshtein v1.1.1 // indirect
30 | github.com/beorn7/perks v1.0.1 // indirect
31 | github.com/blevesearch/bleve v1.0.12 // indirect
32 | github.com/blevesearch/go-porterstemmer v1.0.3 // indirect
33 | github.com/blevesearch/mmap-go v1.0.2 // indirect
34 | github.com/blevesearch/segment v0.9.0 // indirect
35 | github.com/blevesearch/snowballstem v0.9.0 // indirect
36 | github.com/blevesearch/zap/v11 v11.0.12 // indirect
37 | github.com/blevesearch/zap/v12 v12.0.12 // indirect
38 | github.com/blevesearch/zap/v13 v13.0.4 // indirect
39 | github.com/blevesearch/zap/v14 v14.0.3 // indirect
40 | github.com/blevesearch/zap/v15 v15.0.1 // indirect
41 | github.com/cespare/xxhash/v2 v2.2.0 // indirect
42 | github.com/cockroachdb/apd v1.1.0 // indirect
43 | github.com/cockroachdb/apd/v2 v2.0.1 // indirect
44 | github.com/couchbase/vellum v1.0.2 // indirect
45 | github.com/davecgh/go-spew v1.1.1 // indirect
46 | github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
47 | github.com/disintegration/imaging v1.6.2 // indirect
48 | github.com/etgryphon/stringUp v0.0.0-20121020160746-31534ccd8cac // indirect
49 | github.com/gabriel-vasile/mimetype v1.4.2 // indirect
50 | github.com/ghodss/yaml v1.0.0 // indirect
51 | github.com/glycerine/go-unsnap-stream v0.0.0-20181221182339-f9677308dec2 // indirect
52 | github.com/go-kit/log v0.2.1 // indirect
53 | github.com/go-logfmt/logfmt v0.5.1 // indirect
54 | github.com/go-openapi/jsonpointer v0.19.5 // indirect
55 | github.com/go-openapi/jsonreference v0.20.0 // indirect
56 | github.com/go-openapi/spec v0.20.4 // indirect
57 | github.com/go-openapi/swag v0.19.15 // indirect
58 | github.com/go-playground/form v3.1.4+incompatible // indirect
59 | github.com/go-playground/form/v4 v4.2.1 // indirect
60 | github.com/go-playground/locales v0.14.1 // indirect
61 | github.com/go-playground/universal-translator v0.18.1 // indirect
62 | github.com/go-playground/validator/v10 v10.17.0 // indirect
63 | github.com/go-redsync/redsync/v4 v4.11.0 // indirect
64 | github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect
65 | github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
66 | github.com/golang/protobuf v1.5.3 // indirect
67 | github.com/golang/snappy v0.0.4 // indirect
68 | github.com/gomodule/redigo v2.0.0+incompatible // indirect
69 | github.com/google/go-cmp v0.6.0 // indirect
70 | github.com/google/uuid v1.6.0 // indirect
71 | github.com/gorilla/securecookie v1.1.2 // indirect
72 | github.com/gorilla/sessions v1.2.2 // indirect
73 | github.com/gorilla/websocket v1.5.0 // indirect
74 | github.com/hashicorp/errwrap v1.1.0 // indirect
75 | github.com/hashicorp/go-multierror v1.1.1 // indirect
76 | github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
77 | github.com/inconshreveable/mousetrap v1.1.0 // indirect
78 | github.com/josharian/intern v1.0.0 // indirect
79 | github.com/kr/pretty v0.3.1 // indirect
80 | github.com/leebenson/conform v1.2.2 // indirect
81 | github.com/leekchan/accounting v0.3.1 // indirect
82 | github.com/leodido/go-urn v1.2.4 // indirect
83 | github.com/mailru/easyjson v0.7.6 // indirect
84 | github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
85 | github.com/mitchellh/mapstructure v1.5.0 // indirect
86 | github.com/mpvl/unique v0.0.0-20150818121801-cbe035fff7de // indirect
87 | github.com/mschoch/smat v0.2.0 // indirect
88 | github.com/nicksnyder/go-i18n v0.0.0-20180814031359-04f547cc50da // indirect
89 | github.com/openzipkin/zipkin-go v0.4.2 // indirect
90 | github.com/pelletier/go-toml v1.9.5 // indirect
91 | github.com/philhofer/fwd v1.0.0 // indirect
92 | github.com/pkg/errors v0.9.1 // indirect
93 | github.com/pmezard/go-difflib v1.0.0 // indirect
94 | github.com/prometheus/client_golang v1.14.0 // indirect
95 | github.com/prometheus/client_model v0.4.0 // indirect
96 | github.com/prometheus/common v0.37.0 // indirect
97 | github.com/prometheus/procfs v0.8.0 // indirect
98 | github.com/prometheus/statsd_exporter v0.22.7 // indirect
99 | github.com/rbcervilla/redisstore/v9 v9.0.0 // indirect
100 | github.com/redis/go-redis/v9 v9.4.0 // indirect
101 | github.com/rogpeppe/go-internal v1.10.0 // indirect
102 | github.com/shopspring/decimal v1.2.0 // indirect
103 | github.com/sosodev/duration v1.1.0 // indirect
104 | github.com/spf13/pflag v1.0.5 // indirect
105 | github.com/steveyen/gtreap v0.1.0 // indirect
106 | github.com/stretchr/objx v0.5.0 // indirect
107 | github.com/stretchr/testify v1.8.4 // indirect
108 | github.com/tinylib/msgp v1.1.0 // indirect
109 | github.com/uber/jaeger-client-go v2.25.0+incompatible // indirect
110 | github.com/willf/bitset v1.1.11 // indirect
111 | github.com/zemirco/memorystore v0.0.0-20160308183530-ecd57e5134f6 // indirect
112 | go.etcd.io/bbolt v1.3.7 // indirect
113 | go.opencensus.io v0.24.0 // indirect
114 | go.uber.org/automaxprocs v1.5.3 // indirect
115 | go.uber.org/multierr v1.10.0 // indirect
116 | go.uber.org/zap v1.26.0 // indirect
117 | golang.org/x/crypto v0.19.0 // indirect
118 | golang.org/x/image v0.0.0-20220302094943-723b81ca9867 // indirect
119 | golang.org/x/mod v0.15.0 // indirect
120 | golang.org/x/net v0.21.0 // indirect
121 | golang.org/x/sync v0.6.0 // indirect
122 | golang.org/x/sys v0.17.0 // indirect
123 | golang.org/x/text v0.14.0 // indirect
124 | golang.org/x/tools v0.13.0 // indirect
125 | golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect
126 | google.golang.org/api v0.126.0 // indirect
127 | google.golang.org/protobuf v1.31.0 // indirect
128 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
129 | gopkg.in/yaml.v2 v2.4.0 // indirect
130 | gopkg.in/yaml.v3 v3.0.1 // indirect
131 | )
132 |
--------------------------------------------------------------------------------
/frontend/src/base/style/mdp-ecom-base/free/_modals.sass:
--------------------------------------------------------------------------------
1 | // Modals
2 | // Styles for body
3 | body
4 | &.modal-open
5 | overflow: auto
6 | padding-right: 0 !important
7 |
8 | &.scrollable
9 | overflow-y: auto
10 |
11 | // *** ENHANCED BOOTSTRAP MODALS ***///
12 | // General styles
13 | .modal-dialog
14 | .modal-content
15 | box-shadow: $z-depth-1-half
16 | border: 0
17 | border-radius: $border-radius-base
18 |
19 | .modal-header
20 | border-top-left-radius: $border-radius-base
21 | border-top-right-radius: $border-radius-base
22 |
23 | // Cascading modals
24 | &.cascading-modal
25 | margin-top: 10%
26 |
27 | .close
28 | opacity: 1
29 | text-shadow: none
30 | color: $white-base
31 | outline: 0
32 |
33 | // Cascading header
34 | .modal-header
35 | box-shadow: $z-depth-1-half
36 | margin: $cascading-modal-margin-top $cascading-modal-margin-right $cascading-modal-margin-bottom $cascading-modal-margin-left
37 | border: none
38 | border-radius: $border-radius-base
39 | padding: $cascading-modal-padding
40 | text-align: center
41 |
42 | .close
43 | margin-right: $cascading-modal-close-margin-right
44 |
45 | .title
46 | margin-bottom: 0
47 | width: 100%
48 | font-size: $cascading-modal-font-size
49 |
50 | .fa
51 | margin-right: $cascading-modal-fa-margin-right
52 |
53 | .social-buttons
54 | margin-top: $cascading-modal-social-margin-top
55 |
56 | a
57 | font-size: $cascading-modal-a-font-size
58 |
59 | // Cascading tabs nav
60 | .modal-c-tabs
61 | .nav-tabs
62 | box-shadow: $z-depth-1
63 | margin: $cascading-modal-tabs-margin-top $cascading-modal-tabs-margin-x 0 $cascading-modal-tabs-margin-x
64 |
65 | .tab-content
66 | padding: $cascading-modal-tabs-padding-top 0 0 0
67 |
68 | .nav-tabs
69 | display: flex
70 |
71 | li
72 | flex: 1
73 |
74 | a
75 | text-align: center
76 |
77 | // Footer customization
78 | .modal-body,
79 | .modal-footer
80 | padding-left: $modal-body-padding-left
81 | padding-right: $modal-body-padding-right
82 | color: $grey-darken-2
83 |
84 | .additional-option
85 | margin-top: $modal-body-margin-top
86 | text-align: center
87 |
88 | // Cascading avatar
89 | &.modal-avatar
90 | margin-top: $modal-avatar-margin-top
91 |
92 | .modal-header
93 | box-shadow: none
94 |
95 | @extend .img-fluid
96 |
97 | margin: $modal-avatar-header-margin-top 0 $modal-avatar-header-margin-bottom
98 |
99 | img
100 | width: $modal-avatar-img-width
101 | box-shadow: $z-depth-2
102 | margin-left: auto
103 | margin-right: auto
104 |
105 | // Modal notify
106 | &.modal-notify
107 | .heading
108 | margin: 0
109 | padding: $modal-notify-heading-padding
110 | font-size: $modal-notify-font-size
111 | color: $white-base
112 |
113 | .modal-header
114 | box-shadow: $z-depth-1
115 | border: 0
116 |
117 | .close
118 | opacity: 1
119 |
120 | .modal-body
121 | padding: $modal-notify-body-padding
122 | color: $grey-darken-2
123 |
124 | @each $name, $color in $basic
125 | &.modal-#{$name}
126 | .modal-header
127 | background-color: $color
128 |
129 | .fa
130 | color: $color
131 |
132 | .badge
133 | background-color: $color
134 |
135 | // Position & Size
136 | .modal
137 | padding-right: 0 !important
138 |
139 | .modal-dialog
140 | @media (min-width: 768px)
141 | &.modal-top
142 | top: 0
143 |
144 | &.modal-left
145 | left: 0
146 |
147 | &.modal-right
148 | right: 0
149 |
150 | &.modal-bottom
151 | bottom: 0
152 |
153 | &.modal-top-left
154 | top: $modal-distance
155 | left: $modal-distance
156 |
157 | &.modal-top-right
158 | top: $modal-distance
159 | right: $modal-distance
160 |
161 | &.modal-bottom-left
162 | bottom: $modal-distance
163 | left: $modal-distance
164 |
165 | &.modal-bottom-right
166 | bottom: $modal-distance
167 | right: $modal-distance
168 |
169 | &.fade
170 | &.top:not(.show) .modal-dialog
171 | transform: $modal-fade-top-transform
172 |
173 | &.left:not(.show) .modal-dialog
174 | transform: $modal-fade-left-transform
175 |
176 | &.right:not(.show) .modal-dialog
177 | transform: $modal-fade-right-transform
178 |
179 | &.bottom:not(.show) .modal-dialog
180 | transform: $modal-fade-bottom-transform
181 |
182 | @media (min-width: $medium-screen)
183 | &.modal-scrolling
184 | position: relative
185 |
186 | .modal-dialog
187 | position: fixed
188 | z-index: 1050
189 |
190 | &.modal-content-clickable
191 | top: auto
192 | bottom: auto
193 |
194 | .modal-dialog
195 | position: fixed
196 |
197 | .modal-fluid
198 | width: 100%
199 | max-width: 100%
200 |
201 | .modal-content
202 | width: 100%
203 |
204 | .modal-frame
205 | position: absolute
206 | margin: 0
207 | width: 100%
208 | max-width: 100%
209 |
210 | &.modal-bottom
211 | bottom: 0
212 |
213 | .modal-full-height
214 | position: absolute
215 | display: flex
216 | margin: 0
217 | width: $modal-width
218 | height: 100%
219 | top: 0
220 | right: 0
221 |
222 | &.modal-top,
223 | &.modal-bottom
224 | display: block
225 | width: 100%
226 | max-width: 100%
227 | height: auto
228 |
229 | &.modal-top
230 | bottom: auto
231 |
232 | &.modal-bottom
233 | top: auto
234 |
235 | .modal-content
236 | width: 100%
237 |
238 | &.modal-lg
239 | width: 90%
240 | max-width: 90%
241 |
242 | @media (min-width: $medium-screen)
243 | width: $modal-full-height-medium-screen
244 | max-width: $modal-full-height-medium-screen
245 |
246 | @media (min-width: $large-screen)
247 | width: $modal-full-height-large-screen
248 | max-width: $modal-full-height-large-screen
249 |
250 | .modal-side
251 | position: absolute
252 | bottom: $modal-distance
253 | right: $modal-distance
254 | margin: 0
255 | width: $modal-width
256 |
257 | .nav-tabs
258 | border-radius: $md-card-border-radius
259 |
260 | .nav-item
261 | .nav-link
262 | border-radius: $md-card-border-radius
263 | background-color: inherit
264 | color: $white-base
265 |
--------------------------------------------------------------------------------
/frontend/src/page/checkout/organism/checkoutform.pug:
--------------------------------------------------------------------------------
1 | form(method="post")
2 | h4.d-flex.justify-content-between.align-items-center.mb-3
3 | span.text-muted Billing Address #{form.hasGeneralErrors}
4 |
5 | if form.hasAnyGeneralErrors
6 | each error in form.getAllGeneralErrors
7 | div.alert.alert-error(role="alert", data-error=error.messageKey)=error.defaultLabel
8 | div.card
9 | - var billingForm = form.billingAddressForm
10 | .card-body
11 | div.row
12 | div.col-md-6.mb-2
13 | div.md-form
14 | +inputField("billingAddress","firstname","First Name", billingForm, billingForm.data.firstname)
15 | +fieldError("firstname",billingForm)
16 | div.col-md-6.mb-2
17 | div.md-form
18 | +inputField("billingAddress","lastname","Last Name", billingForm,billingForm.data.lastname)
19 | +fieldError("lastname",billingForm)
20 | div.row
21 | div.col-md-10.mb-2
22 | div.md-form
23 | +inputField("billingAddress","street","Street", billingForm,billingForm.data.street)
24 | +fieldError("street",billingForm)
25 | div.col-md-2.mb-2
26 | div.md-form
27 | +inputField("billingAddress","streetNr","Nr", billingForm,billingForm.data.streetNr)
28 | +fieldError("streetNr",billingForm)
29 | div.row
30 | div.col-md-4.mb-2
31 | div.md-form
32 | +inputField("billingAddress","postCode","Post code", billingForm,billingForm.data.postCode)
33 | +fieldError("postCode",billingForm)
34 | div.col-md-8.mb-2
35 | div.md-form
36 | +inputField("billingAddress","city","City", billingForm,billingForm.data.city)
37 | +fieldError("city",billingForm)
38 | div.md-form.mb-5
39 | +inputField("billingAddress","email","E-Mail", billingForm,billingForm.data.email)
40 | +fieldError("email",billingForm)
41 |
42 |
43 | each delivery in decoratedCart.cart.deliveries
44 | - var deliveryCode = delivery.deliveryInfo.code
45 | - var deliveryForm = form.deliveryForms[deliveryCode]
46 | - var formFieldNameSpace = "deliveries."+deliveryCode
47 | h4(data-deliverycode=delivery.deliveryInfo.code).d-flex.justify-content-between.align-items-center.m-3
48 | span.text-muted=__(delivery.deliveryInfo.code)
49 |
50 | if deliveryCode == "delivery"
51 | div.card(class=deliveryCode)
52 | .card-body
53 | div.custom-control.custom-checkbox
54 | if deliveryForm.data.useBillingAddress == true
55 | input.custom-control-input(name=formFieldNameSpace+".useBillingAddress", type="checkbox", id="useBillingAddress", checked="checked")
56 | else
57 | input.custom-control-input(name=formFieldNameSpace+".useBillingAddress", type="checkbox", id="useBillingAddress")
58 | label.custom-control-label(for="useBillingAddress") Use billing address as shipping address
59 | div(id="useBillingAddressToggle", class="collapse show")
60 | div.row
61 | div.col-md-6.mb-2
62 | div.md-form
63 | +inputField(formFieldNameSpace,"deliveryAddress.firstname","First Name", deliveryForm,deliveryForm.data.deliveryAddress.firstname)
64 | +fieldError("deliveryAddress.firstname",deliveryForm)
65 | div.col-md-6.mb-2
66 | div.md-form
67 | +inputField(formFieldNameSpace,"deliveryAddress.lastname","Last Name", deliveryForm, deliveryForm.data.deliveryAddress.lastname)
68 | +fieldError("deliveryAddress.lastname",deliveryForm)
69 | div.row
70 | div.col-md-10.mb-2
71 | div.md-form
72 | +inputField(formFieldNameSpace,"deliveryAddress.street","Street", deliveryForm,deliveryForm.data.deliveryAddress.street)
73 | +fieldError("deliveryAddress.street",deliveryForm)
74 | div.col-md-2.mb-2
75 | div.md-form
76 | +inputField(formFieldNameSpace,"deliveryAddress.streetNr","Nr", deliveryForm,deliveryForm.data.deliveryAddress.streetNr)
77 | +fieldError("deliveryAddress.streetNr",deliveryForm)
78 | div.row
79 | div.col-md-4.mb-2
80 | div.md-form
81 | +inputField(formFieldNameSpace,"deliveryAddress.postCode","Post code", deliveryForm,deliveryForm.data.deliveryAddress.postCode)
82 | +fieldError("deliveryAddress.postCode",deliveryForm)
83 | div.col-md-8.mb-2
84 | div.md-form
85 | +inputField(formFieldNameSpace,"deliveryAddress.city","City", billingForm,deliveryForm.data.deliveryAddress.city)
86 | +fieldError("deliveryAddress.city",deliveryForm)
87 | div.md-form.mb-5
88 | +inputField(formFieldNameSpace,"deliveryAddress.email","E-Mail", billingForm,deliveryForm.data.deliveryAddress.email)
89 | +fieldError("deliveryAddress.email",deliveryForm)
90 | hr.mb-4
91 |
92 | if deliveryCode == "pickup_store"
93 | div.card
94 | .card-body
95 | p You can pick your products directly in the store.
96 | input(name=formFieldNameSpace + ".useBillingAddress", type="hidden", value="1")
97 | hr.mb-4
98 | h4(data-deliverycode=decoratedDelivery.delivery.deliveryInfo.code).d-flex.justify-content-between.align-items-center.m-3
99 | span.text-muted Payment
100 | div.card
101 | .card-body
102 | each methods, gateway in availablePayments
103 | div.d-block.my-3
104 | h5=gateway
105 | input(type="hidden", name="payment.gateway", value=gateway)
106 | +fieldError("method", form.simplePaymentForm)
107 | each method in methods
108 | .custom-control.custom-radio
109 | if form.simplePaymentForm.data.method == method.code
110 | input.custom-control-input(id=method.code, name="payment.method", value=method.code, type="radio", checked="checked", required="1")
111 | else
112 | input.custom-control-input(id=method.code, name="payment.method", value=method.code, type="radio", required="1")
113 | label.custom-control-label(for=method.code)=method.title
114 | button.btn.btn-primary.btn-lg.btn-block.waves-effect.waves-light.mt-2(type="submit") Continue to review
115 |
116 |
117 | mixin inputField(formNameSpace, fieldNameInForm, label, form, currentValue)
118 | - var nameSpacedFieldName = formNameSpace+"."+fieldNameInForm
119 | if form.hasErrorForField(fieldNameInForm)
120 | input(type="text", id=nameSpacedFieldName, name=nameSpacedFieldName, class="form-control is-invalid", value=currentValue)
121 | label(for=nameSpacedFieldName)=label
122 | else
123 | input(type="text", id=nameSpacedFieldName, name=nameSpacedFieldName, class="form-control", value=currentValue)
124 | label(for=nameSpacedFieldName)=label
125 |
126 |
127 | mixin fieldError(fieldNameInForm, form)
128 | if form.hasErrorForField(fieldNameInForm)
129 | div.invalid-feedback
130 | each fieldError in form.getErrorsForField(fieldNameInForm)
131 | span=fieldError.defaultLabel
132 |
--------------------------------------------------------------------------------
/frontend/src/base/style/mdp-ecom-base/core/_mixins.sass:
--------------------------------------------------------------------------------
1 | // Mixins
2 | // Bootstrap Mixins
3 | @function breakpoint-next($name, $breakpoints: $grid-breakpoints, $breakpoint-names: map-keys($breakpoints))
4 | $n: index($breakpoint-names, $name)
5 |
6 | @return if($n < length($breakpoint-names), nth($breakpoint-names, $n + 1), null)
7 |
8 | @function breakpoint-min($name, $breakpoints: $grid-breakpoints)
9 | $min: map-get($breakpoints, $name)
10 |
11 | @return if($min != 0, $min, null)
12 |
13 | @function breakpoint-max($name, $breakpoints: $grid-breakpoints)
14 | $next: breakpoint-next($name, $breakpoints)
15 |
16 | @return if($next, breakpoint-min($next, $breakpoints) - 0.02px, null)
17 |
18 | // Media of at least the minimum breakpoint width. No query for the smallest breakpoint.
19 | // Makes the @content apply to the given breakpoint and wider.
20 | =media-breakpoint-up($name, $breakpoints: $grid-breakpoints)
21 | $min: breakpoint-min($name, $breakpoints)
22 |
23 | @if $min
24 | @media (min-width: $min)
25 | @content
26 | @else
27 | @content
28 |
29 | // Media of at most the maximum breakpoint width. No query for the largest breakpoint.
30 | // Makes the @content apply to the given breakpoint and narrower.
31 | =media-breakpoint-down($name, $breakpoints: $grid-breakpoints)
32 | $max: breakpoint-max($name, $breakpoints)
33 |
34 | @if $max
35 | @media (max-width: $max)
36 | @content
37 | @else
38 | @content
39 |
40 | // Media that spans multiple breakpoint widths.
41 | // Makes the @content apply between the min and max breakpoints
42 | =media-breakpoint-between($lower, $upper, $breakpoints: $grid-breakpoints)
43 | $min: breakpoint-min($lower, $breakpoints)
44 | $max: breakpoint-max($upper, $breakpoints)
45 |
46 | @if $min != null and $max != null
47 | @media (min-width: $min) and (max-width: $max)
48 | @content
49 | @else if $max == null
50 | +media-breakpoint-up($lower, $breakpoints)
51 | @content
52 | @else if $min == null
53 | +media-breakpoint-down($upper, $breakpoints)
54 | @content
55 |
56 | // Media between the breakpoint's minimum and maximum widths.
57 | // No minimum for the smallest breakpoint, and no maximum for the largest one.
58 | // Makes the @content apply only to the given breakpoint, not viewports any wider or narrower.
59 | =media-breakpoint-only($name, $breakpoints: $grid-breakpoints)
60 | $min: breakpoint-min($name, $breakpoints)
61 | $max: breakpoint-max($name, $breakpoints)
62 |
63 | @if $min != null and $max != null
64 | @media (min-width: $min) and (max-width: $max)
65 | @content
66 | @else if $max == null
67 | +media-breakpoint-up($name, $breakpoints)
68 | @content
69 | @else if $min == null
70 | +media-breakpoint-down($name, $breakpoints)
71 | @content
72 |
73 | @function breakpoint-infix($name, $breakpoints: $grid-breakpoints)
74 | @return if(breakpoint-min($name, $breakpoints) == null, "", "-#{$name}")
75 |
76 | =hover-focus
77 | &:hover,
78 | &:focus
79 | @content
80 |
81 | // Background color
82 | =bg-variant($parent, $color)
83 | #{$parent}
84 | background-color: $color !important
85 |
86 | a#{$parent},
87 | button#{$parent}
88 | +hover-focus
89 | background-color: darken($color, 10%) !important
90 |
91 | // Typography
92 | =text-emphasis-variant($parent, $color)
93 | #{$parent}
94 | color: $color !important
95 |
96 | a#{$parent}
97 | +hover-focus
98 | color: darken($color, 10%) !important
99 |
100 | // Placeholder
101 | =placeholder
102 | &::placeholder
103 | @content
104 |
105 | // MDB Mixins
106 | // Set the color of the button and badge
107 | @function set-notification-text-color($color)
108 | @if lightness($color) > 80
109 | @return $black-base
110 |
111 | // Lighter backgorund, return dark color
112 | @else
113 | @return $white-base
114 |
115 | // Darker background, return light color
116 |
117 | // Make button
118 | =make-button($name, $color)
119 | .btn-#{$name}
120 | background-color: $color !important
121 | color: set-notification-text-color($color) !important
122 |
123 | &:hover
124 | background-color: lighten($color, 5%)
125 |
126 | &:focus,
127 | &.focus
128 | box-shadow: $z-depth-1-half
129 |
130 | &:focus,
131 | &:active,
132 | &.active
133 | background-color: darken($color, 20%)
134 |
135 | &.dropdown-toggle
136 | background-color: $color !important
137 |
138 | &:hover,
139 | &:focus
140 | background-color: lighten($color, 5%) !important
141 |
142 | &:not([disabled]):not(.disabled):active,
143 | &:not([disabled]):not(.disabled).active,
144 | .show > &.dropdown-toggle
145 | box-shadow: $z-depth-1-half
146 | background-color: darken($color, 20%) !important
147 |
148 | &:not([disabled]):not(.disabled):active:focus,
149 | &:not([disabled]):not(.disabled).active:focus,
150 | .show > &.dropdown-toggle:focus
151 | box-shadow: $z-depth-1-half
152 |
153 | .#{$name}-ic
154 | color: $color !important
155 |
156 | &:hover,
157 | &:focus
158 | color: $color
159 |
160 | // Make outline button
161 | =make-outline-button($name, $color)
162 | .btn-outline-#{$name}
163 | border: 2px solid $color !important
164 | background-color: transparent !important
165 | color: $color !important
166 |
167 | &:hover,
168 | &:focus,
169 | &:active,
170 | &:active:focus,
171 | &.active
172 | border-color: $color !important
173 | background-color: transparent !important
174 | color: $color !important
175 |
176 | &:not([disabled]):not(.disabled):active,
177 | &:not([disabled]):not(.disabled).active,
178 | .show > &.dropdown-toggle
179 | box-shadow: $z-depth-1-half
180 | background-color: transparent !important
181 | border-color: $color !important
182 |
183 | &:not([disabled]):not(.disabled):active:focus,
184 | &:not([disabled]):not(.disabled).active:focus,
185 | .show > &.dropdown-toggle:focus
186 | box-shadow: $z-depth-1-half
187 |
188 | // Make gradient
189 | =make-gradient($name, $value)
190 | .#{$name}-gradient
191 | background: linear-gradient(40deg, map-get($value, start), map-get($value, end)) !important
192 |
193 | // Make gradient button
194 | =make-gradient-button($name, $value)
195 | .btn
196 | &.#{$name}-gradient
197 | transition: .5s ease
198 | color: $white-base
199 |
200 | &:hover,
201 | &:focus,
202 | &:active,
203 | &:active:focus &.active
204 | background: linear-gradient(40deg, lighten(map-get($value, start), 5%), lighten(map-get($value, end), 5%))
205 |
206 | // Button size
207 | =button-size($padding-y, $padding-x, $font-size)
208 | padding: $padding-y $padding-x
209 | font-size: $font-size
210 |
211 | =make-badge($name, $color)
212 | .badge-#{$name}
213 | background-color: $color !important
214 | color: set-notification-text-color($color) !important
215 |
216 | // Make input
217 | =make-input($label-font-size, $label-active-font-size, $top, $prefix-font-size, $margin-left, $width, $margin-left-2)
218 | label
219 | font-size: $label-font-size
220 |
221 | &.active
222 | font-size: $label-active-font-size
223 |
224 | .prefix
225 | top: $top
226 | font-size: $prefix-font-size
227 |
228 | ~ input, ~ textarea
229 | margin-left: $margin-left
230 | width: $width
231 |
232 | ~ label
233 | margin-left: $margin-left
234 |
235 | ~ .form-text
236 | margin-left: $margin-left-2
237 |
238 | // Make navbar
239 | =make-navbar($color-0, $background-image, $color, $color-2, $color-3)
240 | .navbar-nav
241 | .nav-item
242 | .nav-link
243 | &.disbled
244 | color: $color-0
245 |
246 | &:hover
247 | color: $color-0
248 |
249 | .navbar-toggler-icon
250 | background-image: $background-image
251 | cursor: pointer
252 |
253 | .breadcrumb,
254 | .navbar-nav
255 | .nav-item
256 | .nav-link
257 | color: $color
258 | transition: $navbar-nav-transition
259 |
260 | &:hover
261 | color: $color-2
262 |
263 | &.active > .nav-link
264 | background-color: $color-3
265 |
266 | &:hover
267 | color: $color
268 |
269 | .navbar-toggler
270 | color: $color
271 |
272 | form
273 | .md-form
274 | input
275 | border-bottom: 1px solid $color
276 |
277 | &:focus:not([readonly])
278 | border-color: $input-md-focus-color
279 |
280 | .form-control
281 | color: $color
282 |
283 | +placeholder
284 | color: $color
285 | font-weight: $navbar-font-weight
286 |
287 | // Make floating button
288 | =make-btn-floating($width, $height, $font-size, $line-height)
289 | width: $width
290 | height: $height
291 |
292 | i
293 | font-size: $font-size
294 | line-height: $line-height
295 |
296 | // Keyframes
297 | =keyframes($animation-name)
298 | @keyframes #{$animation-name}
299 | @content
300 |
--------------------------------------------------------------------------------
/graphql/schema/flamingo.me_flamingo-commerce_v3_product_interfaces_graphql-Service.graphql:
--------------------------------------------------------------------------------
1 | interface Commerce_Product {
2 | type: String!
3 | marketPlaceCode: String!
4 | identifier: String!
5 | media: Commerce_Product_Media!,
6 | price: Commerce_Product_PriceInfo!,
7 | availablePrices: [Commerce_Product_PriceInfo!],
8 | title: String!
9 | categories: Commerce_Product_Categories!
10 | description: String!
11 | shortDescription: String!
12 | meta: Commerce_Product_Meta!
13 | loyalty: Commerce_Product_Loyalty!
14 | attributes: Commerce_Product_Attributes!
15 | badges: Commerce_Product_Badges!
16 | }
17 |
18 | """
19 | A simple product, that has no variable attributes and therefore no relation to other products
20 | """
21 | type Commerce_Product_SimpleProduct implements Commerce_Product {
22 | type: String!
23 | marketPlaceCode: String!
24 | identifier: String!
25 | media: Commerce_Product_Media!,
26 | price: Commerce_Product_PriceInfo!,
27 | availablePrices: [Commerce_Product_PriceInfo!],
28 | title: String!
29 | categories: Commerce_Product_Categories!
30 | description: String!
31 | shortDescription: String!
32 | meta: Commerce_Product_Meta!
33 | loyalty: Commerce_Product_Loyalty!
34 | attributes: Commerce_Product_Attributes!
35 | badges: Commerce_Product_Badges!
36 | }
37 |
38 | """
39 | A configurable product defines the possible variations of a product. It only contains
40 | information about product variants but has no active variant itself.
41 | """
42 | type Commerce_Product_ConfigurableProduct implements Commerce_Product {
43 | type: String!
44 | marketPlaceCode: String!
45 | identifier: String!
46 | media: Commerce_Product_Media!,
47 | price: Commerce_Product_PriceInfo!,
48 | availablePrices: [Commerce_Product_PriceInfo!],
49 | title: String!
50 | categories: Commerce_Product_Categories!
51 | description: String!
52 | shortDescription: String!
53 | meta: Commerce_Product_Meta!
54 | loyalty: Commerce_Product_Loyalty!
55 | attributes: Commerce_Product_Attributes!
56 | """
57 | Contains all possible combinations of variation attributes that point to a variant,
58 | as well as all possible variations to render in the frontend.
59 | """
60 | variantSelection: Commerce_Product_VariantSelection!
61 | badges: Commerce_Product_Badges!
62 | }
63 |
64 | type Commerce_Product_VariantSelection {
65 | variants: [Commerce_Product_VariantSelection_Match!]!
66 | attributes: [Commerce_Product_VariantSelection_Attribute!]!
67 | }
68 |
69 | type Commerce_Product_VariantSelection_Attribute {
70 | label: String!
71 | code: String!
72 | options: [Commerce_Product_VariantSelection_Attribute_Option!]!
73 | }
74 |
75 | type Commerce_Product_VariantSelection_Attribute_Option {
76 | label: String!
77 | unitCode: String
78 | otherAttributesRestrictions: [Commerce_Product_VariantSelection_Option_OtherAttributesRestriction!]!
79 | }
80 |
81 | type Commerce_Product_VariantSelection_Option_OtherAttributesRestriction {
82 | code: String!
83 | availableOptions: [String!]!
84 | }
85 |
86 | type Commerce_Product_VariantSelection_Match {
87 | attributes: [Commerce_Product_VariantSelection_Match_Attributes!]
88 | variant: Commerce_Product_VariantSelection_Match_Variant!
89 | }
90 |
91 | type Commerce_Product_VariantSelection_Match_Attributes {
92 | key: String!
93 | value: String!
94 | }
95 |
96 | type Commerce_Product_VariantSelection_Match_Variant {
97 | marketplaceCode: String!
98 | }
99 |
100 | """
101 | An active variant is one of many concrete variants that a configurable provides. All data relates to one active variant
102 | and not the the configurable. It also contains information about it´s siblings (other variants on the same configurable)
103 | """
104 | type Commerce_Product_ActiveVariantProduct implements Commerce_Product {
105 | type: String!
106 | "The marketPlaceCode of the 'configurable' product. See also 'variantMarketPlaceCode' for the variant marketPlaceCode"
107 | marketPlaceCode: String!
108 | identifier: String!
109 | media: Commerce_Product_Media!,
110 | price: Commerce_Product_PriceInfo!,
111 | availablePrices: [Commerce_Product_PriceInfo!],
112 | title: String!
113 | categories: Commerce_Product_Categories!
114 | description: String!
115 | shortDescription: String!
116 | meta: Commerce_Product_Meta!
117 | loyalty: Commerce_Product_Loyalty!
118 | attributes: Commerce_Product_Attributes!
119 | "The marketPlaceCode of the actual variant"
120 | variantMarketPlaceCode: String!
121 | "Contains information about other available product variations"
122 | variationSelections: [Commerce_Product_VariationSelection!]
123 | "Convenience property to access the active variant labels easily"
124 | activeVariationSelections: [Commerce_Product_ActiveVariationSelection!]
125 | badges: Commerce_Product_Badges!
126 | }
127 |
128 | """
129 | A bundle product, that consists of basic products.
130 | """
131 | type Commerce_Product_BundleProduct implements Commerce_Product {
132 | type: String!
133 | marketPlaceCode: String!
134 | identifier: String!
135 | media: Commerce_Product_Media!,
136 | price: Commerce_Product_PriceInfo!,
137 | availablePrices: [Commerce_Product_PriceInfo!],
138 | title: String!
139 | categories: Commerce_Product_Categories!
140 | description: String!
141 | shortDescription: String!
142 | meta: Commerce_Product_Meta!
143 | loyalty: Commerce_Product_Loyalty!
144 | attributes: Commerce_Product_Attributes!
145 | badges: Commerce_Product_Badges!
146 | choices: [Commerce_Product_Choice!]
147 | }
148 |
149 |
150 | "A group of attributes. E.g. 'size'"
151 | type Commerce_Product_VariationSelection {
152 | code: String!
153 | label: String!
154 | "All possible variations for that attribute. E.g. 'M', 'L', 'XL'"
155 | options: [Commerce_Product_VariationSelection_Option]
156 | }
157 |
158 | "Easy-to-access property to display attribute information about an active variant"
159 | type Commerce_Product_ActiveVariationSelection {
160 | code: String!
161 | label: String!
162 | value: String!
163 | unitCode: String!
164 | }
165 |
166 | "An option for a group of attributes"
167 | type Commerce_Product_VariationSelection_Option {
168 | label: String!
169 | unitCode: String!
170 | state: Commerce_Product_VariationSelection_OptionState!
171 | """
172 | Contains information about a product that matches this option.
173 | Depending on if there is an active variant or not, it tries to include the variant,
174 | that best matches the current option.
175 | """
176 | variant: Commerce_Product_VariationSelection_OptionVariant!,
177 | }
178 |
179 | "Information about the underlying variant"
180 | type Commerce_Product_VariationSelection_OptionVariant {
181 | marketPlaceCode: String!
182 | }
183 |
184 | "The state of an option related to the currently active variant"
185 | enum Commerce_Product_VariationSelection_OptionState {
186 | "The currently active variant has this exact attribute + all other active variant attributes"
187 | ACTIVE
188 | "A variant (other than the active variant) exists, that matches this exact attribute + all other active variant attributes"
189 | MATCH
190 | "No variant exists, that matches this exact attribute + all other active variant attributes."
191 | NO_MATCH
192 | }
193 |
194 | "Wrapper that includes main category and all categories"
195 | type Commerce_Product_Categories {
196 | main: Commerce_Product_CategoryTeaser!
197 | all: [Commerce_Product_CategoryTeaser!]
198 | }
199 |
200 | "Meta information about the product"
201 | type Commerce_Product_Meta {
202 | keywords: [String!]
203 | }
204 |
205 | "Loyalty information about this product"
206 | type Commerce_Product_Loyalty {
207 | price: Commerce_Product_Loyalty_PriceInfo
208 | earning: Commerce_Product_Loyalty_EarningInfo
209 | }
210 |
211 | type Commerce_Product_Loyalty_PriceInfo {
212 | type: String!
213 | default: Commerce_Price!
214 | isDiscounted: Boolean!
215 | discounted: Commerce_Price!
216 | discountText: String!
217 | minPointsToSpent: Float!
218 | maxPointsToSpent: Float!
219 | context: Commerce_Product_PriceContext!
220 | }
221 |
222 | "Shows the type and the points earned"
223 | type Commerce_Product_Loyalty_EarningInfo {
224 | "The type of the LoyaltyEarningInfo, e.g. MilesAndMore"
225 | type: String!
226 | "The value of the LoyaltyEarningInfo, currency can be e.g. points or miles"
227 | default: Commerce_Price!
228 | }
229 |
230 | type Commerce_Product_PriceContext {
231 | customerGroup: String!
232 | deliveryCode: String!
233 | channelCode: String!
234 | locale: String!
235 | }
236 |
237 | type Commerce_Product_Media {
238 | all: [Commerce_Product_MediaItem!]
239 | getMedia(usage: String!): Commerce_Product_MediaItem!
240 | }
241 |
242 | type Commerce_Product_MediaItem {
243 | type: String!
244 | mimeType: String!
245 | usage: String!
246 | title: String!
247 | reference: String!
248 | }
249 |
250 | type Commerce_Product_Attributes {
251 | attributeKeys: [String!]
252 | attributes: [Commerce_Product_Attribute!]
253 | hasAttribute(key: String!): Boolean
254 | getAttribute(key: String!): Commerce_Product_Attribute
255 | getAttributesByKey(keys: [String!]): [Commerce_Product_Attribute!]
256 | }
257 |
258 | type Commerce_Product_Attribute {
259 | "Code of the attribute e.g. `productWeight`"
260 | code: String!
261 | "Human-readable code e.g. `The Product Weight`"
262 | codeLabel: String!
263 | "Human-readable label of a single value"
264 | label: String!
265 | "Value of the selected attribute"
266 | value: String!
267 | "Unit of the attribute e.g. `kg`"
268 | unitCode: String!
269 | "Values of a multi value attribute"
270 | values: [String!]
271 | "Human-readable labels of a multi value attribute"
272 | labels: [String!]
273 | }
274 |
275 | type Commerce_Product_CategoryTeaser {
276 | code: String!
277 | path: String!
278 | name: String!
279 | parent: Commerce_Product_CategoryTeaser
280 | }
281 |
282 | type Commerce_Product_PriceInfo {
283 | default: Commerce_Price!
284 | discounted: Commerce_Price!
285 | discountText: String!
286 | activeBase: Commerce_Price!
287 | activeBaseAmount: Float!
288 | activeBaseUnit: String!
289 | isDiscounted: Boolean!
290 | campaignRules: [String!]
291 | denyMoreDiscounts: Boolean!
292 | context: Commerce_Product_PriceContext!
293 | taxClass: String!
294 | }
295 |
296 |
297 | type Commerce_Product_SearchResult {
298 | products: [Commerce_Product!]
299 | facets: [Commerce_Search_Facet!]!
300 | suggestions: [Commerce_Search_Suggestion!]
301 | searchMeta: Commerce_Search_Meta!
302 | hasSelectedFacet: Boolean!
303 | promotion: Commerce_Search_Promotion
304 | actions: [Commerce_Search_Action!]
305 | }
306 |
307 | type Commerce_Product_Badges {
308 | all: [Commerce_Product_Badge!]
309 | first: Commerce_Product_Badge
310 | }
311 |
312 | type Commerce_Product_Badge {
313 | code: String!
314 | label: String!
315 | }
316 |
317 | type Commerce_Product_Choice {
318 | identifier: String!
319 | required: Boolean!
320 | label: String!
321 | options: [Commerce_Product_Option!]
322 | active: Commerce_Product @deprecated(reason: "use activeOption instead")
323 | activeOption: Commerce_Product_Option
324 | }
325 |
326 | type Commerce_Product_Option {
327 | product: Commerce_Product!
328 | qty: Int!
329 | }
330 |
331 | input Commerce_Product_ChoiceConfigurationInput {
332 | identifier: String!
333 | marketplaceCode: String!
334 | variantMarketplaceCode: String
335 | qty: Int!
336 | }
337 |
338 | extend type Query {
339 | Commerce_Product(marketPlaceCode: String!, variantMarketPlaceCode: String, bundleConfiguration: [Commerce_Product_ChoiceConfigurationInput!]): Commerce_Product
340 | Commerce_Product_Search(searchRequest: Commerce_Search_Request!): Commerce_Product_SearchResult!
341 | }
342 |
--------------------------------------------------------------------------------
/frontend/src/base/style/mdp-ecom-base/core/_variables.sass:
--------------------------------------------------------------------------------
1 | // Variables
2 | // Fonts
3 | $roboto-font-path: "asset/font/roboto/" !default
4 |
5 | $font-size-large: 1.5rem !default
6 | $font-bold: 500 !default
7 | $font-small: 0.9rem !default
8 |
9 | $line-height-small: 1 !default
10 | $line-height-extra-large: 2.5 !default
11 |
12 | // Reponsive Headings
13 | $responsive-headings: () !default
14 | $responsive-headings: map-merge(("xs": ("h1": 150%, "h2": 145%, "h3": 135%, "h4": 135%, "h5": 135%), "sm": ("h1": 170%, "h2": 140%, "h3": 125%, "h4": 125%, "h5": 125%), "md": ("h1": 200%, "h2": 170%, "h3": 140%, "h4": 125%, "h5": 125%), "lg": ("h1": 200%, "h2": 170%, "h3": 140%, "h4": 125%, "h5": 125%), "xl": ("h1": 250%, "h2": 200%, "h3": 170%, "h4": 140%, "h5": 125%)), $responsive-headings)
15 |
16 | // Blockquote
17 | $blockquote-padding-y: 0.5rem !default
18 | $blockquote-padding-x: 1rem !default
19 | $blockquote-p-padding-t: $blockquote-padding-x !default
20 | $blockquote-p-padding-b: $blockquote-padding-x !default
21 | $blockquote-p-padding-l: 2rem !default
22 | $blockquote-p-font-size: 1.1rem !default
23 |
24 | // Shadows
25 | $z-depth-1: 0 2px 5px 0 rgba(0, 0, 0, 0.16), 0 2px 10px 0 rgba(0, 0, 0, 0.12) !default
26 | $z-depth-1-half: 0 5px 11px 0 rgba(0, 0, 0, 0.18), 0 4px 15px 0 rgba(0, 0, 0, 0.15) !default
27 | $z-depth-2: 0 8px 17px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19) !default
28 | $z-depth-3: 0 12px 15px 0 rgba(0, 0, 0, 0.24), 0 17px 50px 0 rgba(0, 0, 0, 0.19) !default
29 | $z-depth-4: 0 16px 28px 0 rgba(0, 0, 0, 0.22), 0 25px 55px 0 rgba(0, 0, 0, 0.21) !default
30 | $z-depth-5: 0 27px 24px 0 rgba(0, 0, 0, 0.2), 0 40px 77px 0 rgba(0, 0, 0, 0.22) !default
31 |
32 | // Transitions
33 | $transition-basic: all 0.2s ease-in-out !default
34 | $transition-hoverable: all 0.55s ease-in-out !default
35 |
36 | // Border radius
37 | $border-radius-base: 0.125rem !default
38 | $border-radius-circle: 50% !default
39 |
40 | // Buttons
41 | $btn-color-basic: $white-base !default
42 | $btn-margin-basic: 0.375rem !default
43 | $btn-padding-y-basic: 0.84rem !default
44 | $btn-padding-x-basic: 2.14rem !default
45 | $btn-font-size-basic: 0.81rem !default
46 |
47 | $btn-padding-y-large: 1rem !default
48 | $btn-padding-x-large: 2.4rem !default
49 | $btn-font-size-large: 0.94rem !default
50 |
51 | $btn-padding-y-medium: 0.7rem !default
52 | $btn-padding-x-medium: 1.6rem !default
53 | $btn-font-size-medium: 0.7rem !default
54 |
55 | $btn-padding-y-small: 0.5rem !default
56 | $btn-padding-x-small: 1.6rem !default
57 | $btn-font-size-small: 0.64rem !default
58 |
59 | $btn-outline-padding-y-basic: 0.7rem !default
60 | $btn-outline-padding-y-large: 0.88rem !default
61 | $btn-outline-padding-y-medium: 0.58rem !default
62 | $btn-outline-padding-y-small: 0.38rem !default
63 |
64 | $btn-tb-padding-y: 0.3rem !default
65 | $btn-tb-padding-x: 1rem !default
66 |
67 | $btn-transition: $transition-basic !default
68 |
69 | $btn-icon-basic: 0.9rem !default
70 | $btn-icon-large: 1rem !default
71 | $btn-icon-medium: 0.8rem !default
72 | $btn-icon-small: 0.7rem !default
73 | $btn-icon-margin: 0.3rem !default
74 |
75 | /*** Global **
76 | // Media Query Ranges
77 | $small-screen-up: 601px !default
78 | $medium-screen-up: 993px !default
79 | $large-screen-up: 1201px !default
80 | $small-screen: 600px !default
81 | $medium-screen: 992px !default
82 | $large-screen: 1200px !default
83 | $sidenav-breakpoint: 1440px !default
84 |
85 | $medium-and-up: "only screen and (min-width : #{$small-screen-up})" !default
86 | $large-and-up: "only screen and (min-width : #{$medium-screen-up})" !default
87 | $small-and-down: "only screen and (max-width : #{$small-screen})" !default
88 | $medium-and-down: "only screen and (max-width : #{$medium-screen})" !default
89 | $medium-only: "only screen and (min-width : #{$small-screen-up}) and (max-width : #{$medium-screen})" !default
90 | $hide-sidenav: "only screen and (max-width : #{$sidenav-breakpoint})" !default
91 |
92 | // Link color
93 | $link-color: #0275d8 !default
94 |
95 | // Dividers colors
96 | $hr-light: $white-base !default
97 | $hr-dark: #666 !default
98 | $flex-center-ul-mb: 1rem !default
99 |
100 | // Divider
101 | $divider-margin-y: 2.8rem !default
102 | $divider-margin-x: 0.5rem !default
103 | $divider-height: 2px !default
104 |
105 | // Masks
106 | $mask-overlay-transition: all 0.4s ease-in-out !default
107 | $mask-zoom-transition: all 0.2s linear !default
108 | $mask-zoom-transform: scale(1.1) !default
109 | $intro-video-transform: translateX(-50%) translateY(-50%) !default
110 | $intro-video-transition: 1s !default
111 |
112 | // Cards
113 | $md-card-border-radius: 0.25rem !default
114 | $md-card-link-transition: 0.2s ease-in-out !default
115 | $md-card-font-size: 0.9rem !default
116 | $md-card-text-color: #747373 !default
117 |
118 | // Images
119 | $image-path: "asset/img/" !default
120 | $avatar-img-max-width: 100px !default
121 |
122 | // Carousels
123 | $carousel-control-icon-width: 2.25rem !default
124 | $carousel-control-icon-height: $carousel-control-icon-width !default
125 | $carousel-control-prev-icon: url(#{$image-path}/svg/arrow_left.svg) !default
126 | $carousel-control-next-icon: url(#{$image-path}/svg/arrow_right.svg) !default
127 | $carousel-indicators-width: 0.625rem !default
128 | $carousel-indicators-height: $carousel-indicators-width !default
129 | $carousel-indicators-border-radius: $border-radius-circle !default
130 | $carousel-transition-duration: 0.6s !default
131 | $carousel-item-transform: translateX(0) !default
132 | $carousel-item-transform-2: translate3d(0, 0, 0) !default
133 |
134 | // Badges
135 | $badge-pill-padding-x: 0.6rem !default
136 | $badge-pill-border-radius: 10rem !default
137 |
138 | // Footers
139 | $footer-copyright-color: rgba($white-base, 0.6) !default
140 | $footer-copyright-bg-color: rgba($black-base, 0.2) !default
141 | $footer-font-size: 0.9rem !default
142 |
143 | // Forms
144 | $input-bg-color: $white-base !default
145 | $label-font-size: 0.8rem !default
146 | $input-transition: all 0.3s !default
147 | $input-disabled-color: rgba(0, 0, 0, 0.46) !default
148 | $input-md-focus-color: $primary-color !default
149 | $input-error-color: $error-color !default
150 | $input-success-color: $success-color !default
151 | $input-label-after-top: 65px !default
152 | $input-label-after-transition: 0.2s opacity ease-out, 0.2s color ease-out !default
153 | $input-border-color: #ced4da !default
154 |
155 | $input-label-transition: 0.2s ease-out !default
156 | $input-label-color: #757575 !default
157 | $input-label-top: 0.65rem !default
158 | $input-label-active-transform: translateY(-140%) !default
159 | $input-prefix-transition: color 0.2s !default
160 |
161 | $input-md-form-margin-top: 1.5rem !default
162 | $input-md-form-margin-bottom: $input-md-form-margin-top !default
163 | $input-label-font-size: 1rem !default
164 | $input-label-active-font-size: 0.8rem !default
165 | $input-prefix-top: 0.25rem !default
166 | $input-prefix-font-size: 1.75rem !default
167 | $input-prefix-margin-left: 2.5rem !default
168 | $input-prefix-width: calc(100% - 2.5rem) !default
169 | $input-group-addon-font-size: 1.4rem !default
170 | $input-form-text-ml: 2.6rem !default
171 |
172 | $input-label-font-size-lg: 1.25rem !default
173 | $input-label-active-font-size-lg: 0.95rem !default
174 | $input-prefix-top-lg: 0.4rem !default
175 | $input-prefix-font-size-lg: 2rem !default
176 | $input-prefix-margin-left-lg: 3rem !default
177 | $input-prefix-width-lg: calc(100% - 3rem) !default
178 | $input-group-addon-font-size-lg: 1.65rem !default
179 | $input-form-text-ml-lg: 3.1rem !default
180 |
181 | $input-label-font-size-sm: 0.875rem !default
182 | $input-label-active-font-size-sm: 0.75rem !default
183 | $input-prefix-top-sm: 0.35rem !default
184 | $input-prefix-font-size-sm: 1.5rem !default
185 | $input-prefix-margin-left-sm: 2rem !default
186 | $input-prefix-width-sm: calc(100% - 2rem) !default
187 | $input-group-addon-font-size-sm: 1.15rem !default
188 | $input-form-text-ml-sm: 2rem !default
189 |
190 | $textarea-padding: 1.5rem !default
191 |
192 | $input-form-control-margin-bottom: 0.5rem !default
193 | $input-form-control-padding-top: 0.3rem !default
194 | $input-form-control-padding-bottom: 0.55rem !default
195 | $input-disabled-solid-color: #BDBDBD !default
196 |
197 | // Input group
198 | $input-group-text-bgc: #e0e0e0 !default
199 | $input-group-form-control-px: 0.75rem !default
200 | $input-group-form-control-py: 0.375rem !default
201 |
202 | // List group
203 | $list-group-padding: 0 10px 10px 0 !default
204 | $list-group-transition: 0.5s !default
205 |
206 | // Modals
207 | $modal-distance: 10px !default
208 | $modal-width: 400px !default
209 | $modal-full-height-medium-screen: 800px !default
210 | $modal-full-height-large-screen: 1000px !default
211 | $modal-fade-top-transform: translate3d(0, -25%, 0) !default
212 | $modal-fade-bottom-transform: translate3d(0, 25%, 0) !default
213 | $modal-fade-right-transform: translate3d(25%, 0, 0) !default
214 | $modal-fade-left-transform: translate3d(-25%, 0, 0) !default
215 | $modal-notify-body-padding: 1.5rem !default
216 | $modal-notify-heading-padding: 0.3rem !default
217 | $modal-notify-font-size: 1.15rem !default
218 | $modal-avatar-margin-top: 6rem !default
219 | $modal-avatar-header-margin-top: -6rem !default
220 | $modal-avatar-header-margin-bottom: -1rem !default
221 | $modal-avatar-img-width: 130px !default
222 | $modal-body-padding-right: 2rem !default
223 | $modal-body-padding-left: $modal-body-padding-right !default
224 | $modal-body-margin-top: 1rem !default
225 | $cascading-modal-margin-top: -2rem !default
226 | $cascading-modal-margin-right: 1rem !default
227 | $cascading-modal-margin-bottom: $cascading-modal-margin-right !default
228 | $cascading-modal-margin-left: $cascading-modal-margin-right !default
229 | $cascading-modal-padding: 1.5rem !default
230 | $cascading-modal-close-margin-right: $cascading-modal-margin-right !default
231 | $cascading-modal-font-size: 1.25rem !default
232 | $cascading-modal-fa-margin-right: 9px !default
233 | $cascading-modal-social-margin-top: $cascading-modal-padding !default
234 | $cascading-modal-a-font-size: 1rem !default
235 | $cascading-modal-tabs-margin-x: 1rem !default
236 | $cascading-modal-tabs-margin-top: -1.5rem !default
237 | $cascading-modal-tabs-padding-top: 1.7rem !default
238 |
239 | // Miscellaneous
240 | $edge-header-height: 278px !default
241 | $edge-header-background-color: #ccc !default
242 | $edge-header-margin-top: -100px !default
243 |
244 | // Navbars
245 | $navbar-font-weight: 300 !default
246 | $navbar-double-font-size: 15px !default
247 |
248 | $navbar-light-toggler-icon: url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 32 32' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba(0, 0, 0, 0.9)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 8h24M4 16h24M4 24h24'/%3E%3C/svg%3E") !default
249 | $navbar-light-bg-active-color: rgba($black-base, 0.1) !default
250 | $navbar-light-hover-color: rgba($black-base, 0.75) !default
251 | $navbar-light-disabled-color: rgba(0, 0, 0, 0.5) !default
252 |
253 | $navbar-dark-toggler-icon: url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 32 32' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba(255, 255, 255, 0.9)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 8h24M4 16h24M4 24h24'/%3E%3C/svg%3E") !default
254 | $navbar-dark-bg-active-color: rgba($white-base, 0.1) !default
255 | $navbar-dark-hover-color: rgba($white-base, 0.75) !default
256 | $navbar-dark-disabled-color: rgba(255, 255, 255, 0.5) !default
257 |
258 | $navbar-scrolling-transition: background 0.5s ease-in-out, padding 0.5s ease-in-out !default
259 | $navbar-scrolling-transition-duration: 1s !default
260 | $navbar-scrolling-padding: 12px !default
261 | $navbar-top-collapse-padding: 5px !default
262 | $navbar-nav-transition: 0.35s !default
263 | $navbar-dropdown-font-size: 0.9375rem !default
264 | $navbar-dropdown-menu-padding: 10px !default
265 | $navbar-flex-icons-padding-md: 6px !default
266 | $navbar-flex-icons-padding-lg: 3px !default
267 | $navbar-form-input-mr: 5px !default
268 | $navbar-form-input-mb: 1px !default
269 | $navbar-form-input-ml: 8px !default
270 | $navbar-form-input-height: 1rem !default
271 | $navbar-breadcrumb-padding-top: 0.3rem !default
272 | $navbar-breadcrumb-padding-left: 1rem !default
273 | $navbar-breadcrumb-color: rgba(255, 255, 255, 0.65) !default
274 |
275 | // Pagination
276 | $pagination-active-transition: all 0.2s linear !default
277 | $pagination-page-link-transition: all 0.3s linear !default
278 | $pagination-page-link-font-size: 0.9rem !default
279 | $pagination-page-link-font-size-lg: 1rem !default
280 | $pagination-page-link-font-size-sm: 0.8rem !default
281 | $pagination-page-item-disabled-color: #868e96 !default
282 | $pagination-page-link-color: #212529 !default
283 | $pagination-page-link-hover-bg-color: #eee !default
284 | $pagination-circle-margin-x: 2px !default
285 | $pagination-circle-border-radius: $border-radius-circle !default
286 |
287 | // Tables
288 | $table-th-font-size: 0.9rem !default
289 | $table-td-font-size: $table-th-font-size !default
290 | $table-th-padding-top: 1.1rem !default
291 | $table-td-padding-bottom: 1rem !default
292 | $table-a-color: #212529 !default
293 | $table-hover-transition: 0.5s !default
294 | $table-hover-background-color: rgba(0, 0, 0, 0.075) !default
295 | $table-sm-padding-y: 0.6rem !default
296 | $table-inverse-color-border: $white-base !default
297 | $product-table-img-max-height: 150px !default
298 | $product-table-img-min-width: 50px !default
299 |
--------------------------------------------------------------------------------