├── README.md
├── theme
├── assets
│ ├── css
│ │ ├── custom.scss
│ │ ├── page.scss
│ │ └── cart.scss
│ ├── images
│ │ ├── logo.png
│ │ ├── slide7.jpg
│ │ ├── slide8.jpg
│ │ ├── slide9.jpg
│ │ ├── icons
│ │ │ ├── icon-128.png
│ │ │ ├── icon-16.png
│ │ │ ├── icon-256.png
│ │ │ ├── icon-32.png
│ │ │ └── icon-512.png
│ │ ├── arrow_down.svg
│ │ ├── arrow_right.svg
│ │ ├── search.svg
│ │ ├── payment
│ │ │ ├── diners.svg
│ │ │ └── visa.svg
│ │ ├── close.svg
│ │ ├── arrow_back.svg
│ │ ├── thin_arrow_right.svg
│ │ └── success.svg
│ └── manifest.json
├── src
│ ├── lib
│ │ ├── api.js
│ │ └── settings.js
│ ├── components
│ │ ├── pageList
│ │ │ ├── list.js
│ │ │ ├── item.js
│ │ │ └── index.js
│ │ ├── productList
│ │ │ ├── itemTags.js
│ │ │ ├── itemImage.js
│ │ │ └── loadMore.js
│ │ ├── productDetails
│ │ │ ├── tags.js
│ │ │ ├── breadcrumbs.js
│ │ │ ├── attributes.js
│ │ │ └── relatedProducts.js
│ │ ├── categoryBreadcrumbs.js
│ │ ├── sort.js
│ │ ├── cartIndicator.js
│ │ ├── head
│ │ │ └── cartIndicator.js
│ │ └── header
│ │ │ └── cartIndicator.js
│ ├── containers
│ │ ├── notfound.js
│ │ ├── shared.js
│ │ └── checkout.js
│ └── index.js
└── package.json
├── logs
└── README.md
├── public
├── content
│ └── README.md
├── admin-assets
│ ├── images
│ │ ├── shortcut.png
│ │ └── apps
│ │ │ ├── facebook.png
│ │ │ ├── jivosite.png
│ │ │ ├── messenger.png
│ │ │ ├── google_analytics.png
│ │ │ ├── site_verification.png
│ │ │ └── facebook-customer-chat-plugin.png
│ ├── tinymce
│ │ ├── plugins
│ │ │ ├── example_dependency
│ │ │ │ └── plugin.min.js
│ │ │ ├── media
│ │ │ │ └── moxieplayer.swf
│ │ │ ├── emoticons
│ │ │ │ ├── img
│ │ │ │ │ ├── smiley-cool.gif
│ │ │ │ │ ├── smiley-cry.gif
│ │ │ │ │ ├── smiley-kiss.gif
│ │ │ │ │ ├── smiley-wink.gif
│ │ │ │ │ ├── smiley-yell.gif
│ │ │ │ │ ├── smiley-frown.gif
│ │ │ │ │ ├── smiley-sealed.gif
│ │ │ │ │ ├── smiley-smile.gif
│ │ │ │ │ ├── smiley-innocent.gif
│ │ │ │ │ ├── smiley-laughing.gif
│ │ │ │ │ ├── smiley-surprised.gif
│ │ │ │ │ ├── smiley-undecided.gif
│ │ │ │ │ ├── smiley-embarassed.gif
│ │ │ │ │ ├── smiley-money-mouth.gif
│ │ │ │ │ ├── smiley-tongue-out.gif
│ │ │ │ │ └── smiley-foot-in-mouth.gif
│ │ │ │ └── plugin.min.js
│ │ │ ├── example
│ │ │ │ ├── dialog.html
│ │ │ │ └── plugin.min.js
│ │ │ ├── print
│ │ │ │ └── plugin.min.js
│ │ │ ├── hr
│ │ │ │ └── plugin.min.js
│ │ │ ├── anchor
│ │ │ │ └── plugin.min.js
│ │ │ ├── nonbreaking
│ │ │ │ └── plugin.min.js
│ │ │ ├── code
│ │ │ │ └── plugin.min.js
│ │ │ ├── directionality
│ │ │ │ └── plugin.min.js
│ │ │ ├── wordcount
│ │ │ │ └── plugin.min.js
│ │ │ ├── contextmenu
│ │ │ │ └── plugin.min.js
│ │ │ ├── noneditable
│ │ │ │ └── plugin.min.js
│ │ │ ├── save
│ │ │ │ └── plugin.min.js
│ │ │ ├── visualblocks
│ │ │ │ └── plugin.min.js
│ │ │ ├── colorpicker
│ │ │ │ └── plugin.min.js
│ │ │ ├── pagebreak
│ │ │ │ └── plugin.min.js
│ │ │ ├── visualchars
│ │ │ │ └── plugin.min.js
│ │ │ ├── tabfocus
│ │ │ │ └── plugin.min.js
│ │ │ └── advlist
│ │ │ │ └── plugin.min.js
│ │ ├── skins
│ │ │ └── lightgray
│ │ │ │ ├── img
│ │ │ │ ├── anchor.gif
│ │ │ │ ├── loader.gif
│ │ │ │ ├── object.gif
│ │ │ │ └── trans.gif
│ │ │ │ └── fonts
│ │ │ │ ├── tinymce.eot
│ │ │ │ ├── tinymce.ttf
│ │ │ │ ├── tinymce.woff
│ │ │ │ ├── tinymce-small.eot
│ │ │ │ ├── tinymce-small.ttf
│ │ │ │ └── tinymce-small.woff
│ │ └── langs
│ │ │ └── readme.md
│ └── manifest.json
├── robots.template
└── sw.js
├── src
├── admin
│ └── client
│ │ ├── lib
│ │ ├── text.js
│ │ ├── settings.js
│ │ ├── data.js
│ │ ├── api.js
│ │ └── events.js
│ │ ├── modules
│ │ ├── shared
│ │ │ ├── tinymce
│ │ │ │ ├── index.js
│ │ │ │ └── helpers
│ │ │ │ │ ├── ucFirst.js
│ │ │ │ │ └── uuid.js
│ │ │ ├── imageUpload
│ │ │ │ └── style.css
│ │ │ ├── imageUploadMultiple
│ │ │ │ ├── item.js
│ │ │ │ └── style.css
│ │ │ └── form
│ │ │ │ └── index.js
│ │ ├── products
│ │ │ ├── listFilter
│ │ │ │ ├── components
│ │ │ │ │ └── style.css
│ │ │ │ └── index.js
│ │ │ ├── edit
│ │ │ │ ├── inventory
│ │ │ │ │ ├── components
│ │ │ │ │ │ └── style.css
│ │ │ │ │ └── index.js
│ │ │ │ ├── general
│ │ │ │ │ ├── components
│ │ │ │ │ │ └── style.css
│ │ │ │ │ └── index.js
│ │ │ │ ├── attributes
│ │ │ │ │ ├── components
│ │ │ │ │ │ └── style.css
│ │ │ │ │ └── index.js
│ │ │ │ ├── additional
│ │ │ │ │ └── index.js
│ │ │ │ ├── images
│ │ │ │ │ └── components
│ │ │ │ │ │ └── images.js
│ │ │ │ ├── option
│ │ │ │ │ └── components
│ │ │ │ │ │ └── style.css
│ │ │ │ └── variants
│ │ │ │ │ └── components
│ │ │ │ │ └── style.css
│ │ │ ├── listHead
│ │ │ │ ├── components
│ │ │ │ │ └── search.js
│ │ │ │ └── index.js
│ │ │ ├── editHead
│ │ │ │ └── index.js
│ │ │ └── list
│ │ │ │ └── components
│ │ │ │ ├── head.js
│ │ │ │ └── style.css
│ │ ├── orders
│ │ │ ├── listFilter
│ │ │ │ └── components
│ │ │ │ │ └── style.css
│ │ │ ├── list
│ │ │ │ ├── components
│ │ │ │ │ ├── style.css
│ │ │ │ │ └── head.js
│ │ │ │ └── index.js
│ │ │ ├── listHead
│ │ │ │ ├── components
│ │ │ │ │ └── search.js
│ │ │ │ └── index.js
│ │ │ └── editHead
│ │ │ │ └── index.js
│ │ ├── customers
│ │ │ ├── filter
│ │ │ │ ├── components
│ │ │ │ │ └── style.css
│ │ │ │ └── index.js
│ │ │ ├── list
│ │ │ │ ├── components
│ │ │ │ │ ├── style.css
│ │ │ │ │ └── head.js
│ │ │ │ └── index.js
│ │ │ ├── listHead
│ │ │ │ ├── components
│ │ │ │ │ └── search.js
│ │ │ │ └── index.js
│ │ │ └── actionTypes.js
│ │ ├── settings
│ │ │ ├── paymentGateway
│ │ │ │ ├── components
│ │ │ │ │ └── style.css
│ │ │ │ ├── availablePaymentGateways.js
│ │ │ │ └── index.js
│ │ │ ├── smtp
│ │ │ │ ├── components
│ │ │ │ │ └── style.css
│ │ │ │ └── index.js
│ │ │ ├── paymentsEdit
│ │ │ │ ├── components
│ │ │ │ │ └── style.css
│ │ │ │ └── head.js
│ │ │ ├── shippingEdit
│ │ │ │ ├── components
│ │ │ │ │ └── style.css
│ │ │ │ └── head.js
│ │ │ ├── tokens
│ │ │ │ ├── edit
│ │ │ │ │ ├── components
│ │ │ │ │ │ └── style.css
│ │ │ │ │ └── index.js
│ │ │ │ └── list
│ │ │ │ │ ├── head.js
│ │ │ │ │ ├── index.js
│ │ │ │ │ └── components
│ │ │ │ │ └── headButtons.js
│ │ │ ├── theme
│ │ │ │ ├── components
│ │ │ │ │ └── style.css
│ │ │ │ └── index.js
│ │ │ ├── general
│ │ │ │ ├── components
│ │ │ │ │ └── style.css
│ │ │ │ └── index.js
│ │ │ ├── checkoutFields
│ │ │ │ ├── components
│ │ │ │ │ └── style.css
│ │ │ │ └── index.js
│ │ │ ├── emailTemplates
│ │ │ │ ├── components
│ │ │ │ │ └── style.css
│ │ │ │ └── index.js
│ │ │ ├── payments
│ │ │ │ ├── head.js
│ │ │ │ ├── index.js
│ │ │ │ └── components
│ │ │ │ │ └── headButtons.js
│ │ │ ├── shipping
│ │ │ │ ├── head.js
│ │ │ │ ├── index.js
│ │ │ │ └── components
│ │ │ │ │ └── headButtons.js
│ │ │ ├── email
│ │ │ │ └── index.js
│ │ │ ├── checkout
│ │ │ │ └── index.js
│ │ │ ├── generalLogo
│ │ │ │ ├── index.js
│ │ │ │ └── components
│ │ │ │ │ └── form.js
│ │ │ └── themeSettings
│ │ │ │ ├── components
│ │ │ │ ├── style.css
│ │ │ │ └── imageEditor.js
│ │ │ │ └── index.js
│ │ ├── pages
│ │ │ ├── edit
│ │ │ │ ├── components
│ │ │ │ │ └── style.css
│ │ │ │ ├── head.js
│ │ │ │ └── index.js
│ │ │ ├── actionTypes.js
│ │ │ ├── list
│ │ │ │ ├── head.js
│ │ │ │ ├── index.js
│ │ │ │ └── components
│ │ │ │ │ └── headButtons.js
│ │ │ └── reducer.js
│ │ ├── files
│ │ │ ├── actionTypes.js
│ │ │ ├── list
│ │ │ │ ├── components
│ │ │ │ │ ├── headButtons.js
│ │ │ │ │ ├── fileUploader
│ │ │ │ │ │ └── style.css
│ │ │ │ │ └── style.css
│ │ │ │ ├── head.js
│ │ │ │ └── index.js
│ │ │ ├── reducer.js
│ │ │ └── actions.js
│ │ ├── customerGroups
│ │ │ ├── edit
│ │ │ │ ├── components
│ │ │ │ │ └── style.css
│ │ │ │ └── index.js
│ │ │ ├── select
│ │ │ │ └── index.js
│ │ │ ├── actionTypes.js
│ │ │ ├── list
│ │ │ │ └── index.js
│ │ │ └── head
│ │ │ │ └── index.js
│ │ ├── orderStatuses
│ │ │ ├── edit
│ │ │ │ ├── components
│ │ │ │ │ └── style.css
│ │ │ │ └── index.js
│ │ │ ├── select
│ │ │ │ └── index.js
│ │ │ ├── actionTypes.js
│ │ │ ├── list
│ │ │ │ └── index.js
│ │ │ └── head
│ │ │ │ └── index.js
│ │ ├── productCategories
│ │ │ ├── edit
│ │ │ │ ├── components
│ │ │ │ │ └── style.css
│ │ │ │ └── index.js
│ │ │ ├── select
│ │ │ │ └── index.js
│ │ │ ├── list
│ │ │ │ └── index.js
│ │ │ ├── actionTypes.js
│ │ │ └── head
│ │ │ │ └── index.js
│ │ ├── apps
│ │ │ ├── services
│ │ │ │ ├── components
│ │ │ │ │ ├── appItem.js
│ │ │ │ │ ├── style.css
│ │ │ │ │ └── serviceItem.js
│ │ │ │ └── index.js
│ │ │ ├── head
│ │ │ │ ├── index.js
│ │ │ │ └── components
│ │ │ │ │ └── buttons.js
│ │ │ ├── account
│ │ │ │ ├── components
│ │ │ │ │ ├── style.css
│ │ │ │ │ └── details.js
│ │ │ │ └── index.js
│ │ │ ├── actionTypes.js
│ │ │ ├── appDetails
│ │ │ │ └── index.js
│ │ │ ├── serviceDetails
│ │ │ │ └── components
│ │ │ │ │ └── logs.js
│ │ │ └── reducer.js
│ │ └── head
│ │ │ └── index.js
│ │ ├── routes
│ │ ├── orders
│ │ │ ├── edit.js
│ │ │ ├── statuses
│ │ │ │ └── index.js
│ │ │ └── index.js
│ │ ├── customers
│ │ │ ├── edit.js
│ │ │ ├── index.js
│ │ │ └── groups
│ │ │ │ └── index.js
│ │ ├── home.js
│ │ ├── logout.js
│ │ ├── notFound.js
│ │ ├── files.js
│ │ ├── pages
│ │ │ ├── index.js
│ │ │ └── edit.js
│ │ ├── products
│ │ │ ├── categories
│ │ │ │ └── index.js
│ │ │ ├── index.js
│ │ │ └── edit.js
│ │ └── apps
│ │ │ └── index.js
│ │ ├── apps
│ │ └── index.js
│ │ ├── rootReducer.js
│ │ └── index.js
├── store
│ ├── client
│ │ ├── settings.js
│ │ ├── api.js
│ │ └── index.js
│ ├── server
│ │ ├── settings.js
│ │ ├── readIndexHtml.js
│ │ ├── api.js
│ │ ├── themeLocales.js
│ │ ├── robotsRendering.js
│ │ └── sitemapRendering.js
│ └── shared
│ │ ├── text.js
│ │ ├── pageTypes.js
│ │ ├── containers
│ │ ├── index.js
│ │ ├── page.js
│ │ ├── search.js
│ │ ├── shared.js
│ │ ├── category.js
│ │ ├── notfound.js
│ │ ├── product.js
│ │ ├── checkoutSuccess.js
│ │ └── checkout.js
│ │ └── components
│ │ ├── checkoutForm
│ │ └── index.js
│ │ └── stepPayment
│ │ └── index.js
└── api
│ └── server
│ ├── lib
│ ├── settings.js
│ ├── mongo.js
│ ├── events.js
│ └── utils.js
│ ├── services
│ ├── data.js
│ ├── orders
│ │ ├── paymentMethodsLight.js
│ │ └── shippingMethodsLight.js
│ ├── apps
│ │ └── settings.js
│ └── settings
│ │ └── paymentGateways.js
│ ├── routes
│ ├── notifications.js
│ ├── sitemap.js
│ ├── paymentGateways.js
│ ├── apps.js
│ └── files.js
│ └── controllers
│ ├── notifications.js
│ ├── data.js
│ ├── sitemap.js
│ ├── paymentGateways.js
│ ├── apps.js
│ └── files.js
├── .DS_Store
├── .gitattributes
├── config
├── store.js
└── admin.js
├── scripts
├── theme-export.sh
└── theme-install.sh
├── docs
├── README.md
└── structure.md
├── process.json
├── locales
└── store
│ ├── zh_CN.json
│ ├── en.json
│ ├── uk.json
│ └── ru.json
└── LICENSE
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/theme/assets/css/custom.scss:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/logs/README.md:
--------------------------------------------------------------------------------
1 | Folder must exists
2 |
--------------------------------------------------------------------------------
/public/content/README.md:
--------------------------------------------------------------------------------
1 | Folder must exists
2 |
--------------------------------------------------------------------------------
/src/admin/client/lib/text.js:
--------------------------------------------------------------------------------
1 | module.exports = APPLICATION_TEXT;
2 |
--------------------------------------------------------------------------------
/src/admin/client/lib/settings.js:
--------------------------------------------------------------------------------
1 | module.exports = APPLICATION_CONFIG;
2 |
--------------------------------------------------------------------------------
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webdevstar/React-Ecommerce/HEAD/.DS_Store
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
--------------------------------------------------------------------------------
/src/admin/client/modules/shared/tinymce/index.js:
--------------------------------------------------------------------------------
1 | module.exports = require('./components/TinyMCE');
2 |
--------------------------------------------------------------------------------
/src/admin/client/modules/products/listFilter/components/style.css:
--------------------------------------------------------------------------------
1 | .filter {
2 | padding: 0 16px;
3 | }
4 |
--------------------------------------------------------------------------------
/src/store/client/settings.js:
--------------------------------------------------------------------------------
1 | import settings from '../../../config/store'
2 | export default settings
3 |
--------------------------------------------------------------------------------
/src/store/server/settings.js:
--------------------------------------------------------------------------------
1 | import settings from '../../../config/server'
2 | export default settings
3 |
--------------------------------------------------------------------------------
/theme/assets/images/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webdevstar/React-Ecommerce/HEAD/theme/assets/images/logo.png
--------------------------------------------------------------------------------
/src/api/server/lib/settings.js:
--------------------------------------------------------------------------------
1 | const settings = require('../../../../config/server');
2 | module.exports = settings;
3 |
--------------------------------------------------------------------------------
/theme/assets/images/slide7.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webdevstar/React-Ecommerce/HEAD/theme/assets/images/slide7.jpg
--------------------------------------------------------------------------------
/theme/assets/images/slide8.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webdevstar/React-Ecommerce/HEAD/theme/assets/images/slide8.jpg
--------------------------------------------------------------------------------
/theme/assets/images/slide9.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webdevstar/React-Ecommerce/HEAD/theme/assets/images/slide9.jpg
--------------------------------------------------------------------------------
/src/admin/client/modules/orders/listFilter/components/style.css:
--------------------------------------------------------------------------------
1 | .filter {
2 | padding: 0 16px;
3 | }
4 |
5 | .select {}
6 |
--------------------------------------------------------------------------------
/theme/assets/images/icons/icon-128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webdevstar/React-Ecommerce/HEAD/theme/assets/images/icons/icon-128.png
--------------------------------------------------------------------------------
/theme/assets/images/icons/icon-16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webdevstar/React-Ecommerce/HEAD/theme/assets/images/icons/icon-16.png
--------------------------------------------------------------------------------
/theme/assets/images/icons/icon-256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webdevstar/React-Ecommerce/HEAD/theme/assets/images/icons/icon-256.png
--------------------------------------------------------------------------------
/theme/assets/images/icons/icon-32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webdevstar/React-Ecommerce/HEAD/theme/assets/images/icons/icon-32.png
--------------------------------------------------------------------------------
/theme/assets/images/icons/icon-512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webdevstar/React-Ecommerce/HEAD/theme/assets/images/icons/icon-512.png
--------------------------------------------------------------------------------
/public/admin-assets/images/shortcut.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webdevstar/React-Ecommerce/HEAD/public/admin-assets/images/shortcut.png
--------------------------------------------------------------------------------
/public/admin-assets/tinymce/plugins/example_dependency/plugin.min.js:
--------------------------------------------------------------------------------
1 | tinymce.PluginManager.add("example_dependency",function(){},["example"]);
--------------------------------------------------------------------------------
/public/admin-assets/images/apps/facebook.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webdevstar/React-Ecommerce/HEAD/public/admin-assets/images/apps/facebook.png
--------------------------------------------------------------------------------
/public/admin-assets/images/apps/jivosite.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webdevstar/React-Ecommerce/HEAD/public/admin-assets/images/apps/jivosite.png
--------------------------------------------------------------------------------
/public/admin-assets/images/apps/messenger.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webdevstar/React-Ecommerce/HEAD/public/admin-assets/images/apps/messenger.png
--------------------------------------------------------------------------------
/src/admin/client/modules/customers/filter/components/style.css:
--------------------------------------------------------------------------------
1 | .filter {
2 | padding: 0 16px;
3 | }
4 |
5 | .toggle {
6 | margin-bottom: 16px;
7 | }
8 |
--------------------------------------------------------------------------------
/src/admin/client/routes/orders/edit.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import OrderDetails from 'modules/orders/edit';
3 |
4 | export default OrderDetails;
5 |
--------------------------------------------------------------------------------
/src/admin/client/modules/shared/tinymce/helpers/ucFirst.js:
--------------------------------------------------------------------------------
1 | export default function ucFirst(str) {
2 | return str[0].toUpperCase() + str.substring(1);
3 | }
4 |
--------------------------------------------------------------------------------
/src/admin/client/modules/shared/tinymce/helpers/uuid.js:
--------------------------------------------------------------------------------
1 | let count = 0;
2 | module.exports = function uuid() {
3 | return 'react-tinymce-' + count++;
4 | };
5 |
--------------------------------------------------------------------------------
/public/admin-assets/images/apps/google_analytics.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webdevstar/React-Ecommerce/HEAD/public/admin-assets/images/apps/google_analytics.png
--------------------------------------------------------------------------------
/public/admin-assets/images/apps/site_verification.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webdevstar/React-Ecommerce/HEAD/public/admin-assets/images/apps/site_verification.png
--------------------------------------------------------------------------------
/src/admin/client/routes/customers/edit.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import CustomerDetails from 'modules/customers/edit';
3 |
4 | export default CustomerDetails;
5 |
--------------------------------------------------------------------------------
/src/store/shared/text.js:
--------------------------------------------------------------------------------
1 | import clientSettings from '../client/settings'
2 | module.exports = require('../../../locales/store/' + clientSettings.language + '.json');
3 |
--------------------------------------------------------------------------------
/public/admin-assets/tinymce/plugins/media/moxieplayer.swf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webdevstar/React-Ecommerce/HEAD/public/admin-assets/tinymce/plugins/media/moxieplayer.swf
--------------------------------------------------------------------------------
/public/admin-assets/tinymce/skins/lightgray/img/anchor.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webdevstar/React-Ecommerce/HEAD/public/admin-assets/tinymce/skins/lightgray/img/anchor.gif
--------------------------------------------------------------------------------
/public/admin-assets/tinymce/skins/lightgray/img/loader.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webdevstar/React-Ecommerce/HEAD/public/admin-assets/tinymce/skins/lightgray/img/loader.gif
--------------------------------------------------------------------------------
/public/admin-assets/tinymce/skins/lightgray/img/object.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webdevstar/React-Ecommerce/HEAD/public/admin-assets/tinymce/skins/lightgray/img/object.gif
--------------------------------------------------------------------------------
/public/admin-assets/tinymce/skins/lightgray/img/trans.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webdevstar/React-Ecommerce/HEAD/public/admin-assets/tinymce/skins/lightgray/img/trans.gif
--------------------------------------------------------------------------------
/config/store.js:
--------------------------------------------------------------------------------
1 | // config used by store client side only
2 | module.exports = {
3 | // store UI language
4 | language: 'en',
5 | ajaxBaseUrl: 'http://localhost:3001/ajax'
6 | }
7 |
--------------------------------------------------------------------------------
/public/admin-assets/tinymce/skins/lightgray/fonts/tinymce.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webdevstar/React-Ecommerce/HEAD/public/admin-assets/tinymce/skins/lightgray/fonts/tinymce.eot
--------------------------------------------------------------------------------
/public/admin-assets/tinymce/skins/lightgray/fonts/tinymce.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webdevstar/React-Ecommerce/HEAD/public/admin-assets/tinymce/skins/lightgray/fonts/tinymce.ttf
--------------------------------------------------------------------------------
/public/admin-assets/tinymce/skins/lightgray/fonts/tinymce.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webdevstar/React-Ecommerce/HEAD/public/admin-assets/tinymce/skins/lightgray/fonts/tinymce.woff
--------------------------------------------------------------------------------
/public/admin-assets/images/apps/facebook-customer-chat-plugin.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webdevstar/React-Ecommerce/HEAD/public/admin-assets/images/apps/facebook-customer-chat-plugin.png
--------------------------------------------------------------------------------
/public/admin-assets/tinymce/plugins/emoticons/img/smiley-cool.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webdevstar/React-Ecommerce/HEAD/public/admin-assets/tinymce/plugins/emoticons/img/smiley-cool.gif
--------------------------------------------------------------------------------
/public/admin-assets/tinymce/plugins/emoticons/img/smiley-cry.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webdevstar/React-Ecommerce/HEAD/public/admin-assets/tinymce/plugins/emoticons/img/smiley-cry.gif
--------------------------------------------------------------------------------
/public/admin-assets/tinymce/plugins/emoticons/img/smiley-kiss.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webdevstar/React-Ecommerce/HEAD/public/admin-assets/tinymce/plugins/emoticons/img/smiley-kiss.gif
--------------------------------------------------------------------------------
/public/admin-assets/tinymce/plugins/emoticons/img/smiley-wink.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webdevstar/React-Ecommerce/HEAD/public/admin-assets/tinymce/plugins/emoticons/img/smiley-wink.gif
--------------------------------------------------------------------------------
/public/admin-assets/tinymce/plugins/emoticons/img/smiley-yell.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webdevstar/React-Ecommerce/HEAD/public/admin-assets/tinymce/plugins/emoticons/img/smiley-yell.gif
--------------------------------------------------------------------------------
/src/admin/client/lib/data.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | countries: APPLICATION_DATA_COUNTRIES,
3 | currencies: APPLICATION_DATA_CURRENCIES,
4 | timezones: APPLICATION_DATA_TIMEZONES
5 | }
6 |
--------------------------------------------------------------------------------
/src/admin/client/modules/settings/paymentGateway/components/style.css:
--------------------------------------------------------------------------------
1 | .buttons{
2 | text-align: right;
3 | margin-top: 20px;
4 | }
5 |
6 | .error {
7 | color: rgb(244, 67, 54);
8 | }
9 |
--------------------------------------------------------------------------------
/public/admin-assets/tinymce/plugins/emoticons/img/smiley-frown.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webdevstar/React-Ecommerce/HEAD/public/admin-assets/tinymce/plugins/emoticons/img/smiley-frown.gif
--------------------------------------------------------------------------------
/public/admin-assets/tinymce/plugins/emoticons/img/smiley-sealed.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webdevstar/React-Ecommerce/HEAD/public/admin-assets/tinymce/plugins/emoticons/img/smiley-sealed.gif
--------------------------------------------------------------------------------
/public/admin-assets/tinymce/plugins/emoticons/img/smiley-smile.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webdevstar/React-Ecommerce/HEAD/public/admin-assets/tinymce/plugins/emoticons/img/smiley-smile.gif
--------------------------------------------------------------------------------
/public/admin-assets/tinymce/skins/lightgray/fonts/tinymce-small.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webdevstar/React-Ecommerce/HEAD/public/admin-assets/tinymce/skins/lightgray/fonts/tinymce-small.eot
--------------------------------------------------------------------------------
/public/admin-assets/tinymce/skins/lightgray/fonts/tinymce-small.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webdevstar/React-Ecommerce/HEAD/public/admin-assets/tinymce/skins/lightgray/fonts/tinymce-small.ttf
--------------------------------------------------------------------------------
/public/admin-assets/tinymce/skins/lightgray/fonts/tinymce-small.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webdevstar/React-Ecommerce/HEAD/public/admin-assets/tinymce/skins/lightgray/fonts/tinymce-small.woff
--------------------------------------------------------------------------------
/public/admin-assets/tinymce/plugins/emoticons/img/smiley-innocent.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webdevstar/React-Ecommerce/HEAD/public/admin-assets/tinymce/plugins/emoticons/img/smiley-innocent.gif
--------------------------------------------------------------------------------
/public/admin-assets/tinymce/plugins/emoticons/img/smiley-laughing.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webdevstar/React-Ecommerce/HEAD/public/admin-assets/tinymce/plugins/emoticons/img/smiley-laughing.gif
--------------------------------------------------------------------------------
/public/admin-assets/tinymce/plugins/emoticons/img/smiley-surprised.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webdevstar/React-Ecommerce/HEAD/public/admin-assets/tinymce/plugins/emoticons/img/smiley-surprised.gif
--------------------------------------------------------------------------------
/public/admin-assets/tinymce/plugins/emoticons/img/smiley-undecided.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webdevstar/React-Ecommerce/HEAD/public/admin-assets/tinymce/plugins/emoticons/img/smiley-undecided.gif
--------------------------------------------------------------------------------
/public/admin-assets/tinymce/langs/readme.md:
--------------------------------------------------------------------------------
1 | This is where language files should be placed.
2 |
3 | Please DO NOT translate these directly use this service: https://www.transifex.com/projects/p/tinymce/
4 |
--------------------------------------------------------------------------------
/public/admin-assets/tinymce/plugins/emoticons/img/smiley-embarassed.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webdevstar/React-Ecommerce/HEAD/public/admin-assets/tinymce/plugins/emoticons/img/smiley-embarassed.gif
--------------------------------------------------------------------------------
/public/admin-assets/tinymce/plugins/emoticons/img/smiley-money-mouth.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webdevstar/React-Ecommerce/HEAD/public/admin-assets/tinymce/plugins/emoticons/img/smiley-money-mouth.gif
--------------------------------------------------------------------------------
/public/admin-assets/tinymce/plugins/emoticons/img/smiley-tongue-out.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webdevstar/React-Ecommerce/HEAD/public/admin-assets/tinymce/plugins/emoticons/img/smiley-tongue-out.gif
--------------------------------------------------------------------------------
/public/admin-assets/tinymce/plugins/emoticons/img/smiley-foot-in-mouth.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webdevstar/React-Ecommerce/HEAD/public/admin-assets/tinymce/plugins/emoticons/img/smiley-foot-in-mouth.gif
--------------------------------------------------------------------------------
/src/admin/client/modules/pages/edit/components/style.css:
--------------------------------------------------------------------------------
1 | .button {
2 | margin-left: 12px;
3 | }
4 |
5 | .innerBox {
6 | padding: 30px;
7 | }
8 |
9 | .error {
10 | color: rgb(244, 67, 54);
11 | }
12 |
--------------------------------------------------------------------------------
/config/admin.js:
--------------------------------------------------------------------------------
1 | // config used by dashboard client side only
2 | module.exports = {
3 | // dashboard UI language
4 | language: 'en',
5 | apiBaseUrl: 'http://localhost:3001/api/v1',
6 | developerMode: true
7 | }
8 |
--------------------------------------------------------------------------------
/src/admin/client/modules/settings/smtp/components/style.css:
--------------------------------------------------------------------------------
1 | .button {
2 | margin-left: 12px;
3 | }
4 |
5 | .innerBox {
6 | padding: 30px;
7 | }
8 |
9 | .error {
10 | color: rgb(244, 67, 54);
11 | }
12 |
--------------------------------------------------------------------------------
/src/admin/client/modules/settings/paymentsEdit/components/style.css:
--------------------------------------------------------------------------------
1 | .button {
2 | margin-left: 12px;
3 | }
4 |
5 | .innerBox {
6 | padding: 30px;
7 | }
8 |
9 | .error {
10 | color: rgb(244, 67, 54);
11 | }
12 |
--------------------------------------------------------------------------------
/src/admin/client/modules/settings/shippingEdit/components/style.css:
--------------------------------------------------------------------------------
1 | .button {
2 | margin-left: 12px;
3 | }
4 |
5 | .innerBox {
6 | padding: 30px;
7 | }
8 |
9 | .error {
10 | color: rgb(244, 67, 54);
11 | }
12 |
--------------------------------------------------------------------------------
/src/admin/client/modules/settings/tokens/edit/components/style.css:
--------------------------------------------------------------------------------
1 | .button {
2 | margin-left: 12px;
3 | }
4 |
5 | .innerBox {
6 | padding: 30px;
7 | }
8 |
9 | .error {
10 | color: rgb(244, 67, 54);
11 | }
12 |
--------------------------------------------------------------------------------
/src/admin/client/modules/products/edit/inventory/components/style.css:
--------------------------------------------------------------------------------
1 | .button {
2 | margin-left: 12px;
3 | }
4 |
5 | .innerBox {
6 | padding: 30px;
7 | }
8 |
9 | .error {
10 | color: rgb(244, 67, 54);
11 | }
12 |
--------------------------------------------------------------------------------
/src/store/shared/pageTypes.js:
--------------------------------------------------------------------------------
1 | export const PAGE = 'page'
2 | export const PRODUCT_CATEGORY = 'product-category'
3 | export const PRODUCT = 'product'
4 | export const RESERVED = 'reserved'
5 | export const SEARCH = 'search'
6 |
--------------------------------------------------------------------------------
/src/admin/client/modules/pages/actionTypes.js:
--------------------------------------------------------------------------------
1 | export const PAGES_REQUEST = 'PAGES_REQUEST'
2 | export const PAGES_RECEIVE = 'PAGES_RECEIVE'
3 |
4 | export const PAGE_REQUEST = 'PAGE_REQUEST'
5 | export const PAGE_RECEIVE = 'PAGE_RECEIVE'
6 |
--------------------------------------------------------------------------------
/src/admin/client/modules/products/edit/general/components/style.css:
--------------------------------------------------------------------------------
1 | .button {
2 | margin-left: 12px;
3 | }
4 |
5 | .innerBox {
6 | padding: 30px 30px 50px 30px;
7 | }
8 |
9 | .error {
10 | color: rgb(244, 67, 54);
11 | }
12 |
--------------------------------------------------------------------------------
/src/store/client/api.js:
--------------------------------------------------------------------------------
1 | import CezerinClient from 'cezerin-client'
2 | import clientSettings from './settings'
3 |
4 | const api = new CezerinClient({
5 | ajaxBaseUrl: clientSettings.ajaxBaseUrl || '/ajax'
6 | });
7 |
8 | export default api;
9 |
--------------------------------------------------------------------------------
/theme/src/lib/api.js:
--------------------------------------------------------------------------------
1 | import CezerinClient from 'cezerin-client'
2 | import clientSettings from '../../../config/store'
3 |
4 | const api = new CezerinClient({
5 | ajaxBaseUrl: clientSettings.ajaxBaseUrl || '/ajax'
6 | });
7 |
8 | export default api;
9 |
--------------------------------------------------------------------------------
/src/admin/client/modules/files/actionTypes.js:
--------------------------------------------------------------------------------
1 | export const FILES_REQUEST = 'FILES_REQUEST'
2 | export const FILES_RECEIVE = 'FILES_RECEIVE'
3 |
4 | export const FILES_UPLOAD_START = 'FILES_UPLOAD_START'
5 | export const FILES_UPLOAD_END = 'FILES_UPLOAD_END'
6 |
--------------------------------------------------------------------------------
/theme/assets/images/arrow_down.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/theme/assets/images/arrow_right.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/admin/client/routes/home.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | export default() => (
4 |
10 | )
11 |
--------------------------------------------------------------------------------
/public/admin-assets/tinymce/plugins/example/dialog.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Custom dialog
5 | Input some text:
6 |
7 |
8 |
--------------------------------------------------------------------------------
/src/admin/client/routes/logout.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import * as auth from 'lib/auth'
3 |
4 | export default class Logout extends React.Component {
5 | componentWillMount() {
6 | auth.removeToken();
7 | }
8 |
9 | render() {
10 | return null;
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/store/server/readIndexHtml.js:
--------------------------------------------------------------------------------
1 | import fs from 'fs'
2 | import path from 'path'
3 |
4 | const FILE_PATH = path.resolve('theme/assets/index.html');
5 | export let indexHtml = null;
6 |
7 | fs.readFile(FILE_PATH, 'utf8', (err, data) => {
8 | indexHtml = err ? err : data;
9 | });
10 |
--------------------------------------------------------------------------------
/src/admin/client/modules/settings/paymentGateway/availablePaymentGateways.js:
--------------------------------------------------------------------------------
1 | export const AVAILABLE_PAYMENT_GATEWAYS = [
2 | {
3 | 'key': 'paypal-checkout',
4 | 'name': 'PayPal Express Checkout'
5 | },
6 | {
7 | 'key': 'liqpay',
8 | 'name': 'LiqPay'
9 | }
10 | ];
11 |
--------------------------------------------------------------------------------
/src/admin/client/routes/notFound.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import messages from 'lib/text'
3 |
4 | export default() => (
5 |
6 |
404
7 |
{messages.pageNotFound}
8 |
9 | )
10 |
--------------------------------------------------------------------------------
/src/admin/client/routes/files.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import List from 'modules/files/list';
3 |
4 | export default () => (
5 |
10 | )
11 |
--------------------------------------------------------------------------------
/src/admin/client/routes/pages/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import List from 'modules/pages/list';
3 |
4 | export default () => (
5 |
10 | )
11 |
--------------------------------------------------------------------------------
/public/admin-assets/tinymce/plugins/print/plugin.min.js:
--------------------------------------------------------------------------------
1 | tinymce.PluginManager.add("print",function(a){a.addCommand("mcePrint",function(){a.getWin().print()}),a.addButton("print",{title:"Print",cmd:"mcePrint"}),a.addShortcut("Meta+P","","mcePrint"),a.addMenuItem("print",{text:"Print",cmd:"mcePrint",icon:"print",shortcut:"Meta+P",context:"file"})});
--------------------------------------------------------------------------------
/src/admin/client/modules/files/list/components/headButtons.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { Link } from 'react-router-dom'
3 | import messages from 'lib/text'
4 | import FontIcon from 'material-ui/FontIcon'
5 | import IconButton from 'material-ui/IconButton'
6 |
7 | const Buttons = () => null;
8 |
9 | export default Buttons;
10 |
--------------------------------------------------------------------------------
/public/robots.template:
--------------------------------------------------------------------------------
1 | User-agent: *
2 | Disallow: /api
3 | Disallow: /admin
4 | Disallow: /cart
5 | Disallow: /checkout
6 | Disallow: /checkout-success
7 | Disallow: /register
8 | Disallow: /login
9 | Disallow: /logout
10 | Disallow: /account
11 | Disallow: /settings
12 | Disallow: /search
13 | Sitemap: {domain}/sitemap.xml
14 | Host: {domain}
15 |
--------------------------------------------------------------------------------
/src/admin/client/modules/customerGroups/edit/components/style.css:
--------------------------------------------------------------------------------
1 | .shortBox {
2 | max-width: 300px;
3 | }
4 |
5 | .button {
6 | margin-left: 12px;
7 | }
8 |
9 | .toggle {
10 | margin-top: 12px;
11 | margin-bottom: 22px;
12 | }
13 |
14 | .innerBox {
15 | padding: 30px;
16 | }
17 |
18 | .error {
19 | color: rgb(244, 67, 54);
20 | }
21 |
--------------------------------------------------------------------------------
/src/admin/client/modules/orderStatuses/edit/components/style.css:
--------------------------------------------------------------------------------
1 | .shortBox {
2 | max-width: 300px;
3 | }
4 |
5 | .button {
6 | margin-left: 12px;
7 | }
8 |
9 | .toggle {
10 | margin-top: 12px;
11 | margin-bottom: 22px;
12 | }
13 |
14 | .innerBox {
15 | padding: 30px;
16 | }
17 |
18 | .error {
19 | color: rgb(244, 67, 54);
20 | }
21 |
--------------------------------------------------------------------------------
/src/store/shared/containers/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import {connect} from 'react-redux'
3 | import {withRouter} from 'react-router'
4 | import {mapStateToProps, mapDispatchToProps} from '../containerProps'
5 | import {IndexContainer} from 'theme'
6 |
7 | export default withRouter(connect(mapStateToProps, mapDispatchToProps)(IndexContainer));
8 |
--------------------------------------------------------------------------------
/src/store/shared/containers/page.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import {connect} from 'react-redux'
3 | import {withRouter} from 'react-router'
4 | import {mapStateToProps, mapDispatchToProps} from '../containerProps'
5 | import {PageContainer} from 'theme'
6 |
7 | export default withRouter(connect(mapStateToProps, mapDispatchToProps)(PageContainer));
8 |
--------------------------------------------------------------------------------
/src/admin/client/modules/productCategories/edit/components/style.css:
--------------------------------------------------------------------------------
1 | .shortBox {
2 | max-width: 300px;
3 | }
4 |
5 | .button {
6 | margin-left: 12px;
7 | }
8 |
9 | .toggle {
10 | margin-top: 12px;
11 | margin-bottom: 22px;
12 | }
13 |
14 | .innerBox {
15 | padding: 30px;
16 | }
17 |
18 | .error {
19 | color: rgb(244, 67, 54);
20 | }
21 |
--------------------------------------------------------------------------------
/src/admin/client/modules/settings/theme/components/style.css:
--------------------------------------------------------------------------------
1 | .button {
2 | margin-left: 12px;
3 | }
4 |
5 | .toggle {
6 | margin-top: 12px;
7 | margin-bottom: 22px;
8 | }
9 |
10 | .innerBox {
11 | padding: 30px;
12 | }
13 |
14 | .childrenBox {
15 | padding: 0 30px 30px 30px;
16 | }
17 |
18 | .error {
19 | color: rgb(244, 67, 54);
20 | }
21 |
--------------------------------------------------------------------------------
/src/store/shared/containers/search.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import {connect} from 'react-redux'
3 | import {withRouter} from 'react-router'
4 | import {mapStateToProps, mapDispatchToProps} from '../containerProps'
5 | import {SearchContainer} from 'theme'
6 |
7 | export default withRouter(connect(mapStateToProps, mapDispatchToProps)(SearchContainer));
8 |
--------------------------------------------------------------------------------
/src/store/shared/containers/shared.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import {connect} from 'react-redux'
3 | import {withRouter} from 'react-router'
4 | import {mapStateToProps, mapDispatchToProps} from '../containerProps'
5 | import {SharedContainer} from 'theme'
6 |
7 | export default withRouter(connect(mapStateToProps, mapDispatchToProps)(SharedContainer));
8 |
--------------------------------------------------------------------------------
/src/admin/client/modules/settings/general/components/style.css:
--------------------------------------------------------------------------------
1 | .button {
2 | margin-left: 12px;
3 | }
4 |
5 | .toggle {
6 | margin-top: 12px;
7 | margin-bottom: 22px;
8 | }
9 |
10 | .innerBox {
11 | padding: 30px;
12 | }
13 |
14 | .childrenBox {
15 | padding: 0 30px 30px 30px;
16 | }
17 |
18 | .error {
19 | color: rgb(244, 67, 54);
20 | }
21 |
--------------------------------------------------------------------------------
/src/store/shared/containers/category.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import {connect} from 'react-redux'
3 | import {withRouter} from 'react-router'
4 | import {mapStateToProps, mapDispatchToProps} from '../containerProps'
5 | import {CategoryContainer} from 'theme'
6 |
7 | export default withRouter(connect(mapStateToProps, mapDispatchToProps)(CategoryContainer));
8 |
--------------------------------------------------------------------------------
/src/store/shared/containers/notfound.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import {connect} from 'react-redux'
3 | import {withRouter} from 'react-router'
4 | import {mapStateToProps, mapDispatchToProps} from '../containerProps'
5 | import {NotFoundContainer} from 'theme'
6 |
7 | export default withRouter(connect(mapStateToProps, mapDispatchToProps)(NotFoundContainer));
8 |
--------------------------------------------------------------------------------
/src/store/shared/containers/product.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import {connect} from 'react-redux'
3 | import {withRouter} from 'react-router'
4 | import {mapStateToProps, mapDispatchToProps} from '../containerProps'
5 | import {ProductContainer} from 'theme'
6 |
7 | export default withRouter(connect(mapStateToProps, mapDispatchToProps)(ProductContainer));
8 |
--------------------------------------------------------------------------------
/public/admin-assets/tinymce/plugins/hr/plugin.min.js:
--------------------------------------------------------------------------------
1 | tinymce.PluginManager.add("hr",function(a){a.addCommand("InsertHorizontalRule",function(){a.execCommand("mceInsertContent",!1,"
")}),a.addButton("hr",{icon:"hr",tooltip:"Horizontal line",cmd:"InsertHorizontalRule"}),a.addMenuItem("hr",{icon:"hr",text:"Horizontal line",cmd:"InsertHorizontalRule",context:"insert"})});
--------------------------------------------------------------------------------
/src/admin/client/modules/apps/services/components/appItem.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import Item from './item'
3 |
4 | const ServiceItem = ({ app }) => {
5 | return (
6 |
11 | )
12 | }
13 |
14 | export default ServiceItem;
15 |
--------------------------------------------------------------------------------
/src/admin/client/modules/settings/checkoutFields/components/style.css:
--------------------------------------------------------------------------------
1 | .button {
2 | margin-left: 12px;
3 | }
4 |
5 | .toggle {
6 | margin-top: 12px;
7 | margin-bottom: 22px;
8 | }
9 |
10 | .innerBox {
11 | padding: 30px;
12 | }
13 |
14 | .childrenBox {
15 | padding: 0 30px 30px 30px;
16 | }
17 |
18 | .error {
19 | color: rgb(244, 67, 54);
20 | }
21 |
--------------------------------------------------------------------------------
/src/admin/client/modules/settings/emailTemplates/components/style.css:
--------------------------------------------------------------------------------
1 | .button {
2 | margin-left: 12px;
3 | }
4 |
5 | .toggle {
6 | margin-top: 12px;
7 | margin-bottom: 22px;
8 | }
9 |
10 | .innerBox {
11 | padding: 30px;
12 | }
13 |
14 | .childrenBox {
15 | padding: 0 30px 30px 30px;
16 | }
17 |
18 | .error {
19 | color: rgb(244, 67, 54);
20 | }
21 |
--------------------------------------------------------------------------------
/src/store/shared/containers/checkoutSuccess.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import {connect} from 'react-redux'
3 | import {withRouter} from 'react-router'
4 | import {mapStateToProps, mapDispatchToProps} from '../containerProps'
5 | import {CheckoutSuccessContainer} from 'theme'
6 |
7 | export default withRouter(connect(mapStateToProps, mapDispatchToProps)(CheckoutSuccessContainer));
8 |
--------------------------------------------------------------------------------
/src/admin/client/modules/apps/services/components/style.css:
--------------------------------------------------------------------------------
1 | .servicesCover {
2 | width: 280px;
3 | height: 160px;
4 | background-size: cover;
5 | background-position: center;
6 | border-radius: 2px 2px 0 0;
7 | }
8 |
9 | .more {
10 | padding: 40px 0;
11 | text-align: center;
12 | }
13 |
14 | .card:hover {
15 | box-shadow: 0 2px 2px 0 rgba(0,0,0,0.2), 0 6px 10px 0 rgba(0,0,0,0.3) !important;
16 | }
17 |
--------------------------------------------------------------------------------
/src/admin/client/apps/index.js:
--------------------------------------------------------------------------------
1 | import * as GoogleAnalyticsApp from './google-analytics'
2 | import * as SiteVerificationApp from './site-verification'
3 | import * as JivositeApp from './jivosite'
4 | import * as FacebookSDKApp from './facebook-sdk'
5 | import * as FacebookCustomerChatApp from './facebook-customer-chat'
6 |
7 | export default [GoogleAnalyticsApp, SiteVerificationApp, JivositeApp, FacebookSDKApp, FacebookCustomerChatApp];
8 |
--------------------------------------------------------------------------------
/src/admin/client/modules/files/list/head.js:
--------------------------------------------------------------------------------
1 | import { connect } from 'react-redux'
2 | import { withRouter } from 'react-router'
3 | import Buttons from './components/headButtons'
4 |
5 | const mapStateToProps = (state, ownProps) => {
6 | return {}
7 | }
8 |
9 | const mapDispatchToProps = (dispatch, ownProps) => {
10 | return {}
11 | }
12 |
13 | export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Buttons));
14 |
--------------------------------------------------------------------------------
/src/admin/client/modules/pages/list/head.js:
--------------------------------------------------------------------------------
1 | import { connect } from 'react-redux'
2 | import { withRouter } from 'react-router'
3 | import Buttons from './components/headButtons'
4 |
5 | const mapStateToProps = (state, ownProps) => {
6 | return {}
7 | }
8 |
9 | const mapDispatchToProps = (dispatch, ownProps) => {
10 | return {}
11 | }
12 |
13 | export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Buttons));
14 |
--------------------------------------------------------------------------------
/public/sw.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | importScripts('/sw-toolbox.js');
3 | toolbox.router.get('/images/*', toolbox.cacheFirst);
4 | toolbox.router.get('/assets/*', toolbox.cacheFirst);
5 | toolbox.router.get('/admin-assets/*', toolbox.cacheFirst);
6 | toolbox.router.get('/api/*', toolbox.networkOnly);
7 | toolbox.router.get('/ajax/payment_form_settings', toolbox.networkOnly);
8 | toolbox.router.get('/*', toolbox.networkFirst, { networkTimeoutSeconds: 5});
9 |
--------------------------------------------------------------------------------
/src/admin/client/modules/settings/payments/head.js:
--------------------------------------------------------------------------------
1 | import { connect } from 'react-redux'
2 | import { withRouter } from 'react-router'
3 | import Buttons from './components/headButtons'
4 |
5 | const mapStateToProps = (state, ownProps) => {
6 | return {}
7 | }
8 |
9 | const mapDispatchToProps = (dispatch, ownProps) => {
10 | return {}
11 | }
12 |
13 | export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Buttons));
14 |
--------------------------------------------------------------------------------
/src/admin/client/modules/settings/shipping/head.js:
--------------------------------------------------------------------------------
1 | import { connect } from 'react-redux'
2 | import { withRouter } from 'react-router'
3 | import Buttons from './components/headButtons'
4 |
5 | const mapStateToProps = (state, ownProps) => {
6 | return {}
7 | }
8 |
9 | const mapDispatchToProps = (dispatch, ownProps) => {
10 | return {}
11 | }
12 |
13 | export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Buttons));
14 |
--------------------------------------------------------------------------------
/src/admin/client/modules/settings/tokens/list/head.js:
--------------------------------------------------------------------------------
1 | import { connect } from 'react-redux'
2 | import { withRouter } from 'react-router'
3 | import Buttons from './components/headButtons'
4 |
5 | const mapStateToProps = (state, ownProps) => {
6 | return {}
7 | }
8 |
9 | const mapDispatchToProps = (dispatch, ownProps) => {
10 | return {}
11 | }
12 |
13 | export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Buttons));
14 |
--------------------------------------------------------------------------------
/src/admin/client/modules/apps/head/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { connect } from 'react-redux'
3 | import { withRouter } from 'react-router'
4 | import Buttons from './components/buttons'
5 |
6 | const mapStateToProps = (state, ownProps) => {
7 | return {}
8 | }
9 |
10 | const mapDispatchToProps = (dispatch, ownProps) => {
11 | return {}
12 | }
13 |
14 | export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Buttons));
15 |
--------------------------------------------------------------------------------
/src/admin/client/routes/pages/edit.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { Route } from 'react-router-dom'
3 | import PageEdit from 'modules/pages/edit'
4 |
5 | const ProductDetails = (props) => {
6 | return (
7 |
12 | )
13 | }
14 |
15 | export default ProductDetails;
16 |
--------------------------------------------------------------------------------
/src/admin/client/modules/apps/account/components/style.css:
--------------------------------------------------------------------------------
1 | .button {
2 | margin-left: 12px;
3 | }
4 |
5 | .toggle {
6 | margin-top: 12px;
7 | margin-bottom: 22px;
8 | }
9 |
10 | .innerBox {
11 | padding: 30px;
12 | }
13 |
14 | .childrenBox {
15 | padding: 0 30px 30px 30px;
16 | }
17 |
18 | .error {
19 | color: rgb(244, 67, 54);
20 | }
21 |
22 | .detailsContainer {
23 | display: flex;
24 | flex-direction: column;
25 | align-items: center;
26 | }
27 |
--------------------------------------------------------------------------------
/src/admin/client/modules/apps/services/components/serviceItem.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import Item from './item'
3 |
4 | const ServiceItem = ({ service }) => {
5 | return (
6 |
13 | )
14 | }
15 |
16 | export default ServiceItem;
17 |
--------------------------------------------------------------------------------
/theme/src/components/pageList/list.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { themeSettings, text } from '../../lib/settings'
3 | import PageListItem from './item'
4 |
5 | const PageList = ({pages}) => {
6 | const items = pages ? pages.map((page, index) => (
7 |
8 | )) : null;
9 |
10 | return (
11 |
12 | {items}
13 |
14 | )
15 | }
16 |
17 | export default PageList
18 |
--------------------------------------------------------------------------------
/public/admin-assets/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Cezerin",
3 | "short_name": "Cezerin",
4 | "start_url": "/admin",
5 | "display": "standalone",
6 | "background_color": "#F9F9F9",
7 | "theme_color": "#1976D2",
8 | "icons": [{
9 | "src": "/admin-assets/images/shortcut.png",
10 | "sizes": "96x96",
11 | "type": "image/png"
12 | },{
13 | "src": "/admin-assets/images/shortcut.png",
14 | "sizes": "192x192",
15 | "type": "image/png"
16 | }]
17 | }
18 |
--------------------------------------------------------------------------------
/src/admin/client/modules/customers/list/components/style.css:
--------------------------------------------------------------------------------
1 | .customerName {
2 | text-decoration: none;
3 | font-weight: 400;
4 | color: rgb(0,142,180);
5 | }
6 |
7 | .customerName small {
8 | color: rgba(0, 0, 0, 0.4);
9 | }
10 |
11 | .location {
12 | color: rgba(0, 0, 0, 0.4);
13 | }
14 |
15 | .price {
16 | word-break: break-all;
17 | text-align: right;
18 | margin-right: 10px;
19 | }
20 |
21 | .more {
22 | padding: 40px 0;
23 | text-align: center;
24 | }
25 |
--------------------------------------------------------------------------------
/src/admin/client/modules/pages/reducer.js:
--------------------------------------------------------------------------------
1 | import * as t from './actionTypes'
2 |
3 | const initialState = {
4 | pages: [],
5 | pageEdit: null
6 | };
7 |
8 | export default(state = initialState, action) => {
9 | switch (action.type) {
10 | case t.PAGES_RECEIVE:
11 | return Object.assign({}, state, {pages: action.pages})
12 | case t.PAGE_RECEIVE:
13 | return Object.assign({}, state, {pageEdit: action.pageEdit})
14 | default:
15 | return state
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/admin/client/modules/orders/list/components/style.css:
--------------------------------------------------------------------------------
1 | .number {
2 | text-decoration: none;
3 | font-weight: 400;
4 | color: rgb(0,142,180);
5 | }
6 |
7 | .small {
8 | color: rgba(0, 0, 0, 0.4);
9 | }
10 |
11 | .price {
12 | word-break: break-all;
13 | text-align: right;
14 | }
15 |
16 | .shipping {
17 | font-size: 14px;
18 | }
19 |
20 | .status {
21 | text-align: right;
22 | font-size: 14px;
23 | }
24 |
25 | .more {
26 | padding: 40px 0;
27 | text-align: center;
28 | }
29 |
--------------------------------------------------------------------------------
/src/admin/client/modules/pages/list/index.js:
--------------------------------------------------------------------------------
1 | import { connect } from 'react-redux'
2 | import { fetchPages } from '../actions'
3 | import Form from './components/form'
4 |
5 | const mapStateToProps = (state) => {
6 | return {
7 | pages: state.pages.pages
8 | }
9 | }
10 |
11 | const mapDispatchToProps = (dispatch) => {
12 | return {
13 | onLoad: () => {
14 | dispatch(fetchPages())
15 | }
16 | }
17 | }
18 |
19 | export default connect(mapStateToProps, mapDispatchToProps)(Form);
20 |
--------------------------------------------------------------------------------
/src/store/server/api.js:
--------------------------------------------------------------------------------
1 | import jwt from 'jsonwebtoken'
2 | import CezerinClient from 'cezerin-client'
3 | import serverSettings from './settings'
4 |
5 | const TOKEN_PAYLOAD = {email: 'store', scopes: ['admin']};
6 | const STORE_ACCESS_TOKEN = jwt.sign(TOKEN_PAYLOAD, serverSettings.jwtSecretKey);
7 |
8 | const api = new CezerinClient({
9 | apiBaseUrl: serverSettings.apiBaseUrl,
10 | ajaxBaseUrl: serverSettings.ajaxBaseUrl,
11 | apiToken: STORE_ACCESS_TOKEN
12 | });
13 |
14 | export default api;
15 |
--------------------------------------------------------------------------------
/theme/src/components/productList/itemTags.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { themeSettings, text } from '../../lib/settings'
3 | import * as helper from '../../lib/helper'
4 |
5 | const ItemTags = ({ tags }) => {
6 | if(tags && tags.length > 0){
7 | return
8 | {tags.map((tag, index) => (
9 | {tag}
10 | ))}
11 |
12 | } else {
13 | return null;
14 | }
15 | }
16 |
17 | export default ItemTags
18 |
--------------------------------------------------------------------------------
/src/admin/client/modules/settings/tokens/list/index.js:
--------------------------------------------------------------------------------
1 | import { connect } from 'react-redux'
2 | import { fetchTokens } from '../../actions'
3 | import Form from './components/form'
4 |
5 | const mapStateToProps = (state) => {
6 | return {
7 | tokens: state.settings.tokens
8 | }
9 | }
10 |
11 | const mapDispatchToProps = (dispatch) => {
12 | return {
13 | onLoad: () => {
14 | dispatch(fetchTokens())
15 | }
16 | }
17 | }
18 |
19 | export default connect(mapStateToProps, mapDispatchToProps)(Form);
20 |
--------------------------------------------------------------------------------
/src/api/server/services/data.js:
--------------------------------------------------------------------------------
1 | // 'use strict';
2 | //
3 | // const fs = require('fs')
4 | // const path = require('path')
5 | // const countriesArray = require('../../../../data/countries.json');
6 | // const currenciesArray = require('../../../../data/currencies.json');
7 | //
8 | // class DataService {
9 | // getCountries() {
10 | // return countriesArray;
11 | // }
12 | //
13 | // getCurrencies() {
14 | // return currenciesArray;
15 | // }
16 | // }
17 | //
18 | // module.exports = new DataService();
19 |
--------------------------------------------------------------------------------
/theme/src/components/productDetails/tags.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import * as helper from '../../lib/helper'
3 | import { themeSettings, text } from '../../lib/settings'
4 |
5 | const Tags = ({ tags }) => {
6 | if(tags && tags.length > 0){
7 | return (
8 |
9 | {tags.map((tag, index) => (
10 | {tag}
11 | ))}
12 |
13 | )
14 | } else {
15 | return null;
16 | }
17 | }
18 |
19 | export default Tags;
20 |
--------------------------------------------------------------------------------
/src/admin/client/routes/orders/statuses/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import Edit from 'modules/orderStatuses/edit';
3 | import List from 'modules/orderStatuses/list';
4 |
5 | export default () => (
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | )
15 |
--------------------------------------------------------------------------------
/src/admin/client/modules/customerGroups/select/index.js:
--------------------------------------------------------------------------------
1 | import { connect } from 'react-redux'
2 | import { fetchGroupsIfNeeded } from '../actions'
3 | import List from '../components/list'
4 |
5 | const mapStateToProps = (state) => {
6 | return {
7 | items: state.customerGroups.items
8 | }
9 | }
10 |
11 | const mapDispatchToProps = (dispatch) => {
12 | return {
13 | onLoad: () => {
14 | dispatch(fetchGroupsIfNeeded());
15 | }
16 | }
17 | }
18 |
19 | export default connect(mapStateToProps, mapDispatchToProps)(List);
20 |
--------------------------------------------------------------------------------
/src/admin/client/modules/settings/email/index.js:
--------------------------------------------------------------------------------
1 | import { connect } from 'react-redux'
2 | import { fetchEmailSettings } from '../actions'
3 | import Form from './components/form'
4 |
5 | const mapStateToProps = (state) => {
6 | return {
7 | emailSettings: state.settings.emailSettings
8 | }
9 | }
10 |
11 | const mapDispatchToProps = (dispatch) => {
12 | return {
13 | onLoad: () => {
14 | dispatch(fetchEmailSettings())
15 | }
16 | }
17 | }
18 |
19 | export default connect(mapStateToProps, mapDispatchToProps)(Form);
20 |
--------------------------------------------------------------------------------
/src/admin/client/modules/orderStatuses/select/index.js:
--------------------------------------------------------------------------------
1 | import { connect } from 'react-redux'
2 | import { fetchStatusesIfNeeded } from '../actions'
3 | import List from '../components/list'
4 |
5 | const mapStateToProps = (state) => {
6 | return {
7 | items: state.orderStatuses.items
8 | }
9 | }
10 |
11 | const mapDispatchToProps = (dispatch) => {
12 | return {
13 | onLoad: () => {
14 | dispatch(fetchStatusesIfNeeded());
15 | }
16 | }
17 | }
18 |
19 | export default connect(mapStateToProps, mapDispatchToProps)(List);
20 |
--------------------------------------------------------------------------------
/src/admin/client/modules/settings/checkout/index.js:
--------------------------------------------------------------------------------
1 | import { connect } from 'react-redux'
2 | import { fetchCheckoutFields } from '../actions'
3 | import Form from './components/form'
4 |
5 | const mapStateToProps = (state) => {
6 | return {
7 | checkoutFields: state.settings.checkoutFields
8 | }
9 | }
10 |
11 | const mapDispatchToProps = (dispatch) => {
12 | return {
13 | onLoad: () => {
14 | dispatch(fetchCheckoutFields())
15 | }
16 | }
17 | }
18 |
19 | export default connect(mapStateToProps, mapDispatchToProps)(Form);
20 |
--------------------------------------------------------------------------------
/src/admin/client/modules/settings/payments/index.js:
--------------------------------------------------------------------------------
1 | import { connect } from 'react-redux'
2 | import { fetchPaymentMethods } from '../actions'
3 | import Form from './components/form'
4 |
5 | const mapStateToProps = (state) => {
6 | return {
7 | paymentMethods: state.settings.paymentMethods
8 | }
9 | }
10 |
11 | const mapDispatchToProps = (dispatch) => {
12 | return {
13 | onLoad: () => {
14 | dispatch(fetchPaymentMethods())
15 | }
16 | }
17 | }
18 |
19 | export default connect(mapStateToProps, mapDispatchToProps)(Form);
20 |
--------------------------------------------------------------------------------
/src/admin/client/modules/settings/shipping/index.js:
--------------------------------------------------------------------------------
1 | import { connect } from 'react-redux'
2 | import { fetchShippingMethods } from '../actions'
3 | import Form from './components/form'
4 |
5 | const mapStateToProps = (state) => {
6 | return {
7 | shippingMethods: state.settings.shippingMethods
8 | }
9 | }
10 |
11 | const mapDispatchToProps = (dispatch) => {
12 | return {
13 | onLoad: () => {
14 | dispatch(fetchShippingMethods())
15 | }
16 | }
17 | }
18 |
19 | export default connect(mapStateToProps, mapDispatchToProps)(Form);
20 |
--------------------------------------------------------------------------------
/src/store/shared/containers/checkout.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import {connect} from 'react-redux'
3 | import {withRouter} from 'react-router'
4 | import {mapStateToProps, mapDispatchToProps} from '../containerProps'
5 | import {CheckoutContainer} from 'theme'
6 | import CheckoutForm from '../components/checkoutForm'
7 |
8 | const ConnectedCheckoutContainer = withRouter(connect(mapStateToProps, mapDispatchToProps)(CheckoutContainer));
9 |
10 | export default() => {
11 | return } />
12 | }
13 |
--------------------------------------------------------------------------------
/src/admin/client/routes/customers/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import CustomersList from 'modules/customers/list';
3 | import Groups from 'modules/customerGroups/list';
4 |
5 | export default () => (
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | )
15 |
--------------------------------------------------------------------------------
/src/admin/client/routes/customers/groups/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import GroupEdit from 'modules/customerGroups/edit';
3 | import Groups from 'modules/customerGroups/list';
4 |
5 | export default () => (
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | )
15 |
--------------------------------------------------------------------------------
/scripts/theme-export.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | set -e
3 |
4 | # first argument is *.zip file name
5 | fileName="theme.zip"
6 |
7 | # 1. change fileName if arg passed
8 | if [ $# -ne 0 ]; then
9 | fileName=$1
10 | fi
11 |
12 | # 2. delete zip if exists
13 | if [ -f "public/content/$fileName" ]; then
14 | rm public/content/$fileName
15 | fi
16 |
17 | # 3. zip current theme
18 | cd theme
19 | zip -rq9 ../public/content/$fileName . -x node_modules\* dist\* assets/index.html assets/js/bundle-\* assets/css/bundle-\*
20 |
21 | # 4. show success message
22 | echo success
23 |
--------------------------------------------------------------------------------
/src/api/server/routes/notifications.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const PaymentGateways = require('../paymentGateways');
4 |
5 | class NotificationsRoute {
6 | constructor(router) {
7 | this.router = router;
8 | this.registerRoutes();
9 | }
10 |
11 | registerRoutes() {
12 | this.router.post('/v1/notifications/:gateway', this.paymentNotification.bind(this));
13 | }
14 |
15 | paymentNotification(req, res, next) {
16 | PaymentGateways.paymentNotification(req, res, req.params.gateway);
17 | }
18 | }
19 |
20 | module.exports = NotificationsRoute;
21 |
--------------------------------------------------------------------------------
/src/admin/client/routes/products/categories/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import CategoryEdit from 'modules/productCategories/edit';
3 | import Categories from 'modules/productCategories/list';
4 |
5 | export default () => (
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | )
15 |
--------------------------------------------------------------------------------
/src/api/server/controllers/notifications.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const PaymentGateways = require('../paymentGateways');
4 |
5 | class NotificationsController {
6 | constructor(router) {
7 | this.router = router;
8 | this.registerRoutes();
9 | }
10 |
11 | registerRoutes() {
12 | this.router.post('/v1/notifications/:gateway', this.paymentNotification.bind(this));
13 | }
14 |
15 | paymentNotification(req, res, next) {
16 | PaymentGateways.paymentNotification(req, res, req.params.gateway);
17 | }
18 | }
19 |
20 | module.exports = NotificationsController;
21 |
--------------------------------------------------------------------------------
/src/admin/client/lib/api.js:
--------------------------------------------------------------------------------
1 | import CezerinClient from 'cezerin-client'
2 | import settings from 'lib/settings'
3 |
4 | let api = null;
5 | let dashboardToken = localStorage.getItem('dashboard_token');
6 | let webstoreToken = localStorage.getItem('webstore_token');
7 |
8 | const DEVELOPER_MODE = settings.developerMode === true;
9 |
10 | if(dashboardToken || DEVELOPER_MODE === true) {
11 | api = new CezerinClient({
12 | apiBaseUrl: settings.apiBaseUrl || '/api/v1',
13 | apiToken: dashboardToken,
14 | webstoreToken: webstoreToken
15 | });
16 | }
17 |
18 | export default api;
19 |
--------------------------------------------------------------------------------
/src/admin/client/modules/productCategories/select/index.js:
--------------------------------------------------------------------------------
1 | import { connect } from 'react-redux'
2 | import { selectCategory, fetchCategoriesIfNeeded, createCategory } from '../actions'
3 | import List from '../components/list'
4 |
5 | const mapStateToProps = (state) => {
6 | return {
7 | items: state.productCategories.items
8 | }
9 | }
10 |
11 | const mapDispatchToProps = (dispatch) => {
12 | return {
13 | onLoad: () => {
14 | dispatch(fetchCategoriesIfNeeded());
15 | }
16 | }
17 | }
18 |
19 | export default connect(mapStateToProps, mapDispatchToProps)(List);
20 |
--------------------------------------------------------------------------------
/theme/src/lib/settings.js:
--------------------------------------------------------------------------------
1 | export let themeSettings = {};
2 | export let text = {};
3 |
4 | // Client - from Redux state
5 | if(typeof window !== 'undefined'){
6 | const appText = window.__APP_TEXT__;
7 | const appState = window.__APP_STATE__;
8 |
9 | if(appState.app.themeSettings){
10 | themeSettings = appState.app.themeSettings;
11 | }
12 |
13 | if(appText){
14 | text = appText;
15 | }
16 | }
17 |
18 | // Server - from render page method
19 | export const updateThemeSettings = options => {
20 | themeSettings = options.settings;
21 | text = options.text;
22 | }
23 |
--------------------------------------------------------------------------------
/src/store/shared/components/checkoutForm/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import {connect} from 'react-redux'
3 | import {withRouter} from 'react-router'
4 | import Form from './form'
5 |
6 | const mapStateToProps = (state, ownProps) => {
7 | return {
8 | cart: state.app.cart,
9 | settings: state.app.settings,
10 | themeSettings: state.app.themeSettings
11 | }
12 | }
13 |
14 | const mapDispatchToProps = (dispatch, ownProps) => {
15 | return {
16 | onLoad: () => {}
17 | }
18 | }
19 |
20 | export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Form));
21 |
--------------------------------------------------------------------------------
/src/api/server/services/orders/paymentMethodsLight.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var mongo = require('../../lib/mongo');
4 |
5 | class PaymentMethodsLightService {
6 | constructor() {}
7 |
8 | getMethods(filter = {}) {
9 | return mongo.db.collection('paymentMethods').find(filter).toArray().then(items => items.map(item => this.changeProperties(item)))
10 | }
11 |
12 | changeProperties(item) {
13 | if (item) {
14 | item.id = item._id.toString();
15 | delete item._id;
16 | }
17 | return item;
18 | }
19 | }
20 |
21 | module.exports = new PaymentMethodsLightService();
22 |
--------------------------------------------------------------------------------
/theme/assets/images/search.svg:
--------------------------------------------------------------------------------
1 |
2 |
7 |
--------------------------------------------------------------------------------
/docs/README.md:
--------------------------------------------------------------------------------
1 | ## Documentation
2 |
3 | ### General
4 | * [Getting Started](./getting-started.md)
5 | * [Developer Install Guide](./developer.md)
6 | * [Application Structure](./structure.md)
7 | * [Initialize MongoDB](.initialize-mongodb.md)
8 | * Theme customization
9 | * [API](https://apidocs.cezerin.com)
10 | * [API Client](https://github.com/cezerin/client)
11 | * Localization
12 | * Payment Gateway
13 | * Web Service
14 |
15 | ### Questions
16 |
17 | * How to change language
18 |
19 | ### Recipes
20 |
21 | * How to Integrate Disqus
22 |
23 |
--------------------------------------------------------------------------------
/src/admin/client/routes/orders/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import OrdersList from 'modules/orders/list';
3 | import OrdersFilter from 'modules/orders/listFilter';
4 | import Statuses from 'modules/orderStatuses/list';
5 |
6 | export default () => (
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | )
17 |
--------------------------------------------------------------------------------
/src/admin/client/modules/pages/list/components/headButtons.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { Link } from 'react-router-dom'
3 | import messages from 'lib/text'
4 | import FontIcon from 'material-ui/FontIcon'
5 | import IconButton from 'material-ui/IconButton'
6 |
7 | const Buttons = () => (
8 |
9 |
10 |
11 | add
12 |
13 |
14 |
15 | )
16 |
17 | export default Buttons;
18 |
--------------------------------------------------------------------------------
/src/admin/client/modules/customerGroups/actionTypes.js:
--------------------------------------------------------------------------------
1 | export const GROUPS_REQUEST = 'GROUPS_REQUEST'
2 | export const GROUPS_RECEIVE = 'GROUPS_RECEIVE'
3 | export const GROUPS_FAILURE = 'GROUPS_FAILURE'
4 |
5 | export const GROUPS_SELECT = 'GROUPS_SELECT'
6 | export const GROUPS_DESELECT = 'GROUPS_DESELECT'
7 |
8 | export const GROUP_UPDATE_REQUEST = 'GROUP_UPDATE_REQUEST'
9 | export const GROUP_UPDATE_SUCCESS = 'GROUP_UPDATE_SUCCESS'
10 | export const GROUP_UPDATE_FAILURE = 'GROUP_UPDATE_FAILURE'
11 |
12 | export const GROUP_CREATE_SUCCESS = 'GROUP_CREATE_SUCCESS'
13 | export const GROUP_DELETE_SUCCESS = 'GROUP_DELETE_SUCCESS'
14 |
--------------------------------------------------------------------------------
/src/admin/client/modules/settings/general/index.js:
--------------------------------------------------------------------------------
1 | import { connect } from 'react-redux'
2 | import { fetchSettings, updateSettings } from '../actions'
3 | import Form from './components/form'
4 |
5 | const mapStateToProps = (state) => {
6 | return {
7 | initialValues: state.settings.settings
8 | }
9 | }
10 |
11 | const mapDispatchToProps = (dispatch) => {
12 | return {
13 | onLoad: () => {
14 | dispatch(fetchSettings())
15 | },
16 | onSubmit: (values) => {
17 | dispatch(updateSettings(values));
18 | }
19 | }
20 | }
21 |
22 | export default connect(mapStateToProps, mapDispatchToProps)(Form);
23 |
--------------------------------------------------------------------------------
/src/admin/client/modules/files/reducer.js:
--------------------------------------------------------------------------------
1 | import * as t from './actionTypes'
2 |
3 | const initialState = {
4 | files: [],
5 | uploading: false
6 | };
7 |
8 | export default(state = initialState, action) => {
9 | switch (action.type) {
10 | case t.FILES_RECEIVE:
11 | return Object.assign({}, state, {files: action.files})
12 | case t.FILES_UPLOAD_START:
13 | return Object.assign({}, state, {
14 | uploading: true
15 | })
16 | case t.FILES_UPLOAD_END:
17 | return Object.assign({}, state, {
18 | uploading: false
19 | })
20 | default:
21 | return state
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/api/server/lib/mongo.js:
--------------------------------------------------------------------------------
1 | const settings = require('./settings');
2 | const winston = require('winston');
3 | const mongo = require('mongodb').MongoClient;
4 | const mongodbConnection = settings.mongodbServerUrl;
5 |
6 | const CONNECT_OPTIONS = {
7 | reconnectTries: 3600,
8 | reconnectInterval: 1000
9 | }
10 |
11 | // Initialize connection once
12 | mongo.connect(mongodbConnection, CONNECT_OPTIONS, (err, database) => {
13 | if(err){
14 | winston.error('Failed connecting to MongoDB', err.message);
15 | } else {
16 | module.exports.db = database;
17 | winston.info('Successfully connected to MongoDB')
18 | }
19 | });
20 |
--------------------------------------------------------------------------------
/theme/src/containers/notfound.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { themeSettings, text } from '../lib/settings'
3 | import MetaTags from '../components/metaTags'
4 | const Fragment = React.Fragment;
5 |
6 | const NotFoundContainer = (props) => (
7 |
8 |
11 |
12 |
13 |
14 |
{text.title404}
15 | {text.text404}
16 |
17 |
18 |
19 |
20 | )
21 |
22 | export default NotFoundContainer
23 |
--------------------------------------------------------------------------------
/src/admin/client/modules/settings/tokens/list/components/headButtons.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { Link } from 'react-router-dom'
3 | import messages from 'lib/text'
4 | import FontIcon from 'material-ui/FontIcon'
5 | import IconButton from 'material-ui/IconButton'
6 |
7 | const Buttons = () => (
8 |
9 |
10 |
11 | add
12 |
13 |
14 |
15 | )
16 |
17 | export default Buttons;
18 |
--------------------------------------------------------------------------------
/src/admin/client/routes/products/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import ProductsList from 'modules/products/list';
3 | import ProductsFilter from 'modules/products/listFilter';
4 | import Categories from 'modules/productCategories/list';
5 |
6 | export default () => (
7 |
16 | )
17 |
--------------------------------------------------------------------------------
/public/admin-assets/tinymce/plugins/anchor/plugin.min.js:
--------------------------------------------------------------------------------
1 | tinymce.PluginManager.add("anchor",function(a){function b(){var b=a.selection.getNode(),c="",d="A"==b.tagName&&""===a.dom.getAttrib(b,"href");d&&(c=b.name||b.id||""),a.windowManager.open({title:"Anchor",body:{type:"textbox",name:"name",size:40,label:"Name",value:c},onsubmit:function(c){var e=c.data.name;d?b.id=e:(a.selection.collapse(!0),a.execCommand("mceInsertContent",!1,a.dom.createHTML("a",{id:e})))}})}a.addCommand("mceAnchor",b),a.addButton("anchor",{icon:"anchor",tooltip:"Anchor",onclick:b,stateSelector:"a:not([href])"}),a.addMenuItem("anchor",{icon:"anchor",text:"Anchor",context:"insert",onclick:b})});
--------------------------------------------------------------------------------
/src/admin/client/modules/pages/edit/head.js:
--------------------------------------------------------------------------------
1 | import { connect } from 'react-redux'
2 | import { withRouter } from 'react-router'
3 | import { deletePage } from '../actions'
4 | import Buttons from './components/headButtons'
5 |
6 | const mapStateToProps = (state, ownProps) => {
7 | return {
8 | page: state.pages.pageEdit
9 | }
10 | }
11 |
12 | const mapDispatchToProps = (dispatch, ownProps) => {
13 | return {
14 | onDelete: (id) => {
15 | dispatch(deletePage(id));
16 | ownProps.history.push('/admin/pages');
17 | }
18 | }
19 | }
20 |
21 | export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Buttons));
22 |
--------------------------------------------------------------------------------
/src/admin/client/modules/settings/payments/components/headButtons.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { Link } from 'react-router-dom'
3 | import messages from 'lib/text'
4 | import FontIcon from 'material-ui/FontIcon'
5 | import IconButton from 'material-ui/IconButton'
6 |
7 | const Buttons = () => (
8 |
9 |
10 |
11 | add
12 |
13 |
14 |
15 | )
16 |
17 | export default Buttons;
18 |
--------------------------------------------------------------------------------
/src/admin/client/modules/settings/shipping/components/headButtons.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { Link } from 'react-router-dom'
3 | import messages from 'lib/text'
4 | import FontIcon from 'material-ui/FontIcon'
5 | import IconButton from 'material-ui/IconButton'
6 |
7 | const Buttons = () => (
8 |
9 |
10 |
11 | add
12 |
13 |
14 |
15 | )
16 |
17 | export default Buttons;
18 |
--------------------------------------------------------------------------------
/src/admin/client/modules/settings/smtp/index.js:
--------------------------------------------------------------------------------
1 | import { connect } from 'react-redux'
2 | import { fetchEmailSettings, updateEmailSettings } from '../actions'
3 | import Form from './components/form'
4 |
5 | const mapStateToProps = (state) => {
6 | return {
7 | initialValues: state.settings.emailSettings
8 | }
9 | }
10 |
11 | const mapDispatchToProps = (dispatch) => {
12 | return {
13 | onLoad: () => {
14 | dispatch(fetchEmailSettings())
15 | },
16 | onSubmit: (values) => {
17 | dispatch(updateEmailSettings(values));
18 | }
19 | }
20 | }
21 |
22 | export default connect(mapStateToProps, mapDispatchToProps)(Form);
23 |
--------------------------------------------------------------------------------
/src/store/server/themeLocales.js:
--------------------------------------------------------------------------------
1 | import fs from 'fs'
2 | import path from 'path'
3 |
4 | const THEME_LOCALES_PATH = 'theme/locales/';
5 | let text = null;
6 |
7 | export const getText = (locale) => {
8 | if(text) {
9 | return Promise.resolve(text);
10 | } else {
11 | const filePath = path.resolve(THEME_LOCALES_PATH + locale + '.json');
12 | return new Promise((resolve, reject) => {
13 | fs.readFile(filePath, 'utf8', (err, data) => {
14 | if(err){
15 | reject(err)
16 | } else {
17 | text = JSON.parse(data);
18 | resolve(text);
19 | }
20 | });
21 | });
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/admin/client/modules/orderStatuses/actionTypes.js:
--------------------------------------------------------------------------------
1 | export const STATUSES_REQUEST = 'STATUSES_REQUEST'
2 | export const STATUSES_RECEIVE = 'STATUSES_RECEIVE'
3 | export const STATUSES_FAILURE = 'STATUSES_FAILURE'
4 |
5 | export const STATUSES_SELECT = 'STATUSES_SELECT'
6 | export const STATUSES_DESELECT = 'STATUSES_DESELECT'
7 |
8 | export const STATUS_UPDATE_REQUEST = 'STATUS_UPDATE_REQUEST'
9 | export const STATUS_UPDATE_SUCCESS = 'STATUS_UPDATE_SUCCESS'
10 | export const STATUS_UPDATE_FAILURE = 'STATUS_UPDATE_FAILURE'
11 |
12 | export const STATUS_CREATE_SUCCESS = 'STATUS_CREATE_SUCCESS'
13 | export const STATUS_DELETE_SUCCESS = 'STATUS_DELETE_SUCCESS'
14 |
--------------------------------------------------------------------------------
/scripts/theme-install.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | set -e
3 |
4 | # first argument is *.zip file name
5 | fileName=$1
6 |
7 | if [ $# -eq 0 ]; then
8 | echo "No arguments supplied"
9 | exit 1
10 | fi
11 |
12 | # 1. check file exists
13 | if [ ! -f "public/content/$fileName" ]; then
14 | echo "File not found!"
15 | exit 1
16 | fi
17 |
18 | # 3. remove all the contents of theme folder
19 | rm -rf theme/*
20 |
21 | # 4. unzip to current theme
22 | unzip -q "public/content/$fileName" -d "theme"
23 |
24 | # 5. build theme
25 | npm run theme:build:prod
26 |
27 | # 6. show success message
28 | echo -e '\e[1;92m'Theme $fileName successfully installed'\e[0m'
29 |
--------------------------------------------------------------------------------
/src/admin/client/modules/products/listHead/components/search.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import messages from 'lib/text'
3 | import TextField from 'material-ui/TextField';
4 |
5 | export default ({ value, setSearch }) => {
6 | return (
7 |
16 | )
17 | }
18 |
--------------------------------------------------------------------------------
/src/admin/client/routes/products/edit.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { Route } from 'react-router-dom'
3 | import ProductEdit from 'modules/products/edit'
4 | import ProductOption from 'modules/products/edit/option'
5 |
6 | const ProductDetails = (props) => {
7 | return (
8 |
14 | )
15 | }
16 |
17 | export default ProductDetails;
18 |
--------------------------------------------------------------------------------
/theme/assets/css/page.scss:
--------------------------------------------------------------------------------
1 | .page-list {
2 | margin: 40px 0 0 0;
3 | }
4 | .page-item {
5 | margin: 0 0 30px 0;
6 | border-bottom: 1px solid #e5e5e5;
7 | }
8 | .page-item h2 {
9 | font-size: 1.5rem;
10 | margin: 0 0 10px 0;
11 | }
12 | .page-item h2 a:hover {
13 | text-decoration: underline;
14 | }
15 | .page-item .date {
16 | font-size: small;
17 | color: #aaa;
18 | margin: 0 0 10px 0;
19 | }
20 | .page-item .description {
21 | margin: 0 0 10px 0;
22 | }
23 | .page-item div:last-of-type {
24 | margin: 0 0 40px 0;
25 | }
26 | .page-list div:last-of-type {
27 | border-bottom: none;
28 | }
29 | .page-content a {
30 | text-decoration: underline;
31 | }
32 |
--------------------------------------------------------------------------------
/src/admin/client/modules/orders/listHead/components/search.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import messages from 'lib/text'
3 | import TextField from 'material-ui/TextField';
4 |
5 | export default ({ value, setSearch }) => {
6 | return (
7 | { setSearch(v); }}
10 | hintText={messages.orders_search}
11 | underlineShow={false}
12 | style={{ float: 'left', marginRight: 10 }}
13 | hintStyle={{ color: 'rgba(255,255,255,0.4)', textIndent: '16px' }}
14 | inputStyle={{ color:'#fff', backgroundColor: 'rgba(255,255,255,0.2)', borderRadius: '4px', textIndent: '16px' }}
15 | />
16 | )
17 | }
18 |
--------------------------------------------------------------------------------
/src/store/server/robotsRendering.js:
--------------------------------------------------------------------------------
1 | import fs from 'fs'
2 | import path from 'path'
3 | import api from './api'
4 |
5 | const ROBOTS_TEMPLATE_PATH = 'public/robots.template';
6 |
7 | const robotsRendering = (req, res) => {
8 | api.settings.retrieve().then(settingsResponse => {
9 | fs.readFile(path.resolve(ROBOTS_TEMPLATE_PATH), 'utf8', (err, data) => {
10 | if(err) {
11 | res.status(500).end();
12 | } else {
13 | const robots = data.replace(/{domain}/g, settingsResponse.json.domain)
14 | res.header('Content-Type', 'text/plain');
15 | res.send(robots);
16 | }
17 | });
18 | })
19 | }
20 |
21 | export default robotsRendering;
22 |
--------------------------------------------------------------------------------
/theme/src/components/productDetails/breadcrumbs.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { NavLink } from 'react-router-dom'
3 | import { themeSettings, text } from '../../lib/settings'
4 | import * as helper from '../../lib/helper'
5 |
6 | const ProductBreadcrumbs = ({ product, categories }) => {
7 | const items = helper.getProductBreadcrumbs(product, categories);
8 | return (
9 |
17 | )
18 | }
19 |
20 | export default ProductBreadcrumbs;
21 |
--------------------------------------------------------------------------------
/public/admin-assets/tinymce/plugins/example/plugin.min.js:
--------------------------------------------------------------------------------
1 | tinymce.PluginManager.add("example",function(a,b){a.addButton("example",{text:"My button",icon:!1,onclick:function(){a.windowManager.open({title:"Example plugin",body:[{type:"textbox",name:"title",label:"Title"}],onsubmit:function(b){a.insertContent("Title: "+b.data.title)}})}}),a.addMenuItem("example",{text:"Example plugin",context:"tools",onclick:function(){a.windowManager.open({title:"TinyMCE site",url:b+"/dialog.html",width:600,height:400,buttons:[{text:"Insert",onclick:function(){var b=a.windowManager.getWindows()[0];a.insertContent(b.getContentWindow().document.getElementById("content").value),b.close()}},{text:"Close",onclick:"close"}]})}})});
--------------------------------------------------------------------------------
/public/admin-assets/tinymce/plugins/nonbreaking/plugin.min.js:
--------------------------------------------------------------------------------
1 | tinymce.PluginManager.add("nonbreaking",function(a){var b=a.getParam("nonbreaking_force_tab");if(a.addCommand("mceNonBreaking",function(){a.insertContent(a.plugins.visualchars&&a.plugins.visualchars.state?' ':" "),a.dom.setAttrib(a.dom.select("span.mce-nbsp"),"data-mce-bogus","1")}),a.addButton("nonbreaking",{title:"Nonbreaking space",cmd:"mceNonBreaking"}),a.addMenuItem("nonbreaking",{text:"Nonbreaking space",cmd:"mceNonBreaking",context:"insert"}),b){var c=+b>1?+b:3;a.on("keydown",function(b){if(9==b.keyCode){if(b.shiftKey)return;b.preventDefault();for(var d=0;c>d;d++)a.execCommand("mceNonBreaking")}})}});
--------------------------------------------------------------------------------
/src/admin/client/modules/customers/listHead/components/search.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import messages from 'lib/text'
3 | import TextField from 'material-ui/TextField';
4 |
5 | export default ({ value, setSearch }) => {
6 | return (
7 | { setSearch(v); }}
10 | hintText={messages.customers_search}
11 | underlineShow={false}
12 | style={{ float: 'left', marginRight: 10 }}
13 | hintStyle={{ color: 'rgba(255,255,255,0.4)', textIndent: '16px' }}
14 | inputStyle={{ color:'#fff', backgroundColor: 'rgba(255,255,255,0.2)', borderRadius: '4px', textIndent: '16px' }}
15 | />
16 | )
17 | }
18 |
--------------------------------------------------------------------------------
/src/api/server/controllers/data.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var DataService = require('../services/data');
4 |
5 | class DataController {
6 | constructor(router) {
7 | this.router = router;
8 | this.registerRoutes();
9 | }
10 |
11 | registerRoutes() {
12 | // this.router.get('/countries', this.getCountries.bind(this));
13 | // this.router.get('/currencies', this.getCurrencies.bind(this));
14 | }
15 |
16 | // getCountries(req, res, next) {
17 | // res.send(DataService.getCountries())
18 | // }
19 | //
20 | // getCurrencies(req, res, next) {
21 | // res.send(DataService.getCurrencies())
22 | // }
23 | }
24 |
25 | module.exports = DataController;
26 |
--------------------------------------------------------------------------------
/theme/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "theme",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "dist/index.js",
6 | "scripts": {
7 | "build": "babel src -d dist --quiet"
8 | },
9 | "author": "",
10 | "license": "MIT",
11 | "dependencies": {
12 | "babel-cli": "^6.26.0",
13 | "babel-core": "^6.26.0",
14 | "babel-loader": "^7.1.2",
15 | "babel-plugin-transform-class-properties": "^6.24.1",
16 | "babel-preset-latest": "^6.24.1",
17 | "babel-preset-react": "^6.24.1",
18 | "bulma": "^0.6.1",
19 | "rc-slider": "^8.4.1",
20 | "react-image-gallery": "^0.8.6",
21 | "react-image-lightbox": "^4.3.0",
22 | "react-lazyload": "^2.3.0"
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/admin/client/modules/products/editHead/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { connect } from 'react-redux'
3 | import { withRouter } from 'react-router'
4 | import { deleteCurrentProduct } from '../actions'
5 | import Buttons from './components/buttons'
6 |
7 | const mapStateToProps = (state, ownProps) => {
8 | return {
9 | product: state.products.editProduct
10 | }
11 | }
12 |
13 | const mapDispatchToProps = (dispatch, ownProps) => {
14 | return {
15 | onDelete: () => {
16 | dispatch(deleteCurrentProduct());
17 | ownProps.history.push('/admin/products');
18 | }
19 | }
20 | }
21 |
22 | export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Buttons));
23 |
--------------------------------------------------------------------------------
/src/admin/client/modules/settings/generalLogo/index.js:
--------------------------------------------------------------------------------
1 | import { connect } from 'react-redux'
2 | import { fetchSettings, deleteLogo, uploadLogo } from '../actions'
3 | import Form from './components/form'
4 |
5 | const mapStateToProps = (state) => {
6 | return {
7 | settings: state.settings.settings
8 | }
9 | }
10 |
11 | const mapDispatchToProps = (dispatch) => {
12 | return {
13 | onLoad: () => {
14 | dispatch(fetchSettings())
15 | },
16 | onImageDelete: () => {
17 | dispatch(deleteLogo());
18 | },
19 | onImageUpload: (form) => {
20 | dispatch(uploadLogo(form));
21 | }
22 | }
23 | }
24 |
25 | export default connect(mapStateToProps, mapDispatchToProps)(Form);
26 |
--------------------------------------------------------------------------------
/src/admin/client/modules/settings/paymentsEdit/head.js:
--------------------------------------------------------------------------------
1 | import { connect } from 'react-redux'
2 | import { withRouter } from 'react-router'
3 | import { deletePaymentMethod } from '../actions'
4 | import Buttons from './components/headButtons'
5 |
6 | const mapStateToProps = (state, ownProps) => {
7 | return {
8 | paymentMethod: state.settings.paymentMethodEdit
9 | }
10 | }
11 |
12 | const mapDispatchToProps = (dispatch, ownProps) => {
13 | return {
14 | onDelete: (id) => {
15 | dispatch(deletePaymentMethod(id));
16 | ownProps.history.push('/admin/settings/payments');
17 | }
18 | }
19 | }
20 |
21 | export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Buttons));
22 |
--------------------------------------------------------------------------------
/src/admin/client/modules/settings/themeSettings/components/style.css:
--------------------------------------------------------------------------------
1 | .button {
2 | margin-left: 12px;
3 | }
4 |
5 | .innerBox {
6 | padding: 30px;
7 | }
8 |
9 | .arrayInnerBox {
10 | padding: 0 30px 20px 30px;
11 | }
12 |
13 | .arrayTitle{
14 | margin: 40px 0 0 0;
15 | display: flex;
16 | align-items: center;
17 | }
18 |
19 | .arrayItemHead {
20 | padding: 4px;
21 | }
22 |
23 | .colorInput {
24 | padding-top: 16px;
25 | padding-bottom: 16px;
26 | }
27 |
28 | .colorInput label {
29 | margin-right: 20px;
30 | }
31 |
32 | .sectionTitle {
33 | font-size: 24px;
34 | font-weight: 400;
35 | margin: 40px -30px 0px -30px;
36 | padding: 15px 30px;
37 | background-color: #f1f1f1;
38 | }
39 |
--------------------------------------------------------------------------------
/src/admin/client/modules/settings/shippingEdit/head.js:
--------------------------------------------------------------------------------
1 | import { connect } from 'react-redux'
2 | import { withRouter } from 'react-router'
3 | import { deleteShippingMethod } from '../actions'
4 | import Buttons from './components/headButtons'
5 |
6 | const mapStateToProps = (state, ownProps) => {
7 | return {
8 | shippingMethod: state.settings.shippingMethodEdit
9 | }
10 | }
11 |
12 | const mapDispatchToProps = (dispatch, ownProps) => {
13 | return {
14 | onDelete: (id) => {
15 | dispatch(deleteShippingMethod(id));
16 | ownProps.history.push('/admin/settings/shipping');
17 | }
18 | }
19 | }
20 |
21 | export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Buttons));
22 |
--------------------------------------------------------------------------------
/src/admin/client/modules/files/list/components/fileUploader/style.css:
--------------------------------------------------------------------------------
1 | .dropzone {
2 | margin: 20px;
3 | opacity: 1;
4 | transition: opacity .2s ease-in-out;
5 | }
6 | .uploading {
7 | opacity: 0;
8 | }
9 | .dropzoneEmpty {
10 | color: #a1a1a1;
11 | font-size: 16px;
12 | border: 2px dashed rgba(0,0,0,0.1);
13 | padding: 80px 0;
14 | text-align: center;
15 | }
16 | .dropzoneActive {
17 | background-color: rgba(18,179,117, 0.4);
18 | }
19 | .dropzoneReject {
20 | background-color: rgba(244,67,54,0.8);
21 | }
22 | .dropzoneReject .list,
23 | .dropzoneActive .list {
24 | opacity: 0.3
25 | }
26 | .dropzoneActive .button {
27 | opacity: 0;
28 | }
29 | .button {
30 | margin-left: 10px !important;
31 | }
32 |
--------------------------------------------------------------------------------
/src/admin/client/modules/settings/themeSettings/index.js:
--------------------------------------------------------------------------------
1 | import { connect } from 'react-redux'
2 | import { fetchThemeSettings, updateThemeSettings } from '../actions'
3 | import Form from './components/form'
4 |
5 | const mapStateToProps = (state) => {
6 | return {
7 | initialValues: state.settings.themeSettings,
8 | settingsSchema: state.settings.themeSettingsSchema
9 | }
10 | }
11 |
12 | const mapDispatchToProps = (dispatch) => {
13 | return {
14 | onLoad: () => {
15 | dispatch(fetchThemeSettings())
16 | },
17 | onSubmit: (values) => {
18 | dispatch(updateThemeSettings(values));
19 | }
20 | }
21 | }
22 |
23 | export default connect(mapStateToProps, mapDispatchToProps)(Form);
24 |
--------------------------------------------------------------------------------
/src/store/shared/components/stepPayment/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import {connect} from 'react-redux'
3 | import {withRouter} from 'react-router'
4 | import {checkout} from '../../actions'
5 | import Form from './form'
6 |
7 | const mapStateToProps = (state, ownProps) => {
8 | return {
9 | cart: state.app.cart,
10 | settings: state.app.settings,
11 | processingCheckout: state.app.processingCheckout
12 | }
13 | }
14 |
15 | const mapDispatchToProps = (dispatch, ownProps) => {
16 | return {
17 | finishCheckout: () => {
18 | dispatch(checkout(null, ownProps.history));
19 | }
20 | }
21 | }
22 |
23 | export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Form));
24 |
--------------------------------------------------------------------------------
/theme/src/components/pageList/item.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { NavLink } from 'react-router-dom'
3 | import { themeSettings, text } from '../../lib/settings'
4 |
5 | const pad = number => number < 10 ? ('0' + number) : number;
6 | const formatDate = date => `${pad(date.getDate())}.${pad(date.getMonth() + 1)}.${date.getFullYear()}`;
7 |
8 | const PageListItem = ({page}) => (
9 |
10 |
{page.meta_title}
11 |
12 | {formatDate(new Date(page.date_created))}
13 |
14 |
15 | {page.meta_description}
16 |
17 |
18 | )
19 |
20 | export default PageListItem
21 |
--------------------------------------------------------------------------------
/src/admin/client/modules/products/edit/attributes/components/style.css:
--------------------------------------------------------------------------------
1 | .button {
2 | margin-left: 12px;
3 | }
4 |
5 | .innerBox {
6 | padding: 30px;
7 | }
8 |
9 | .childrenBox {
10 | padding: 0 30px 30px 30px;
11 | }
12 |
13 | .error {
14 | color: rgb(244, 67, 54);
15 | }
16 |
17 | .head {
18 | background-color: rgba(0, 0, 0, 0.05);
19 | color: #a1a1a1;
20 | padding: 18px 0 18px 30px !important;
21 | }
22 |
23 | .input {
24 | width: 100%;
25 | margin: 0;
26 | padding: 0;
27 | border: none;
28 | outline: none;
29 | background-color: transparent;
30 | font-size: 15px;
31 | height: 60px;
32 | text-indent: 30px;
33 | }
34 |
35 | .input:hover,
36 | .input:focus {
37 | background-color: rgba(0, 0, 0, 0.05);
38 | }
39 |
--------------------------------------------------------------------------------
/src/admin/client/modules/products/edit/attributes/index.js:
--------------------------------------------------------------------------------
1 | import { connect } from 'react-redux'
2 | import { withRouter } from 'react-router'
3 | import { updateProduct } from '../../actions'
4 | import ProductAttributesForm from './components/form'
5 |
6 | const mapStateToProps = (state, ownProps) => {
7 | return {
8 | initialValues: state.products.editProduct
9 | }
10 | }
11 |
12 | const mapDispatchToProps = (dispatch, ownProps) => {
13 | return {
14 | onSubmit: (values) => {
15 | dispatch(updateProduct({
16 | id: values.id,
17 | attributes: values.attributes
18 | }));
19 | }
20 | }
21 | }
22 |
23 | export default withRouter(connect(mapStateToProps, mapDispatchToProps)(ProductAttributesForm));
24 |
--------------------------------------------------------------------------------
/theme/src/containers/shared.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { themeSettings, text } from '../lib/settings'
3 | import Header from '../components/header'
4 | import Footer from '../components/footer'
5 | const Fragment = React.Fragment;
6 |
7 | const SharedContainer = (props) => {
8 | const {currentPage, settings} = props.state;
9 | let hideFooter = (currentPage.path === '/checkout-success' || currentPage.path === '/checkout') && themeSettings.hide_footer_on_checkout === true;
10 |
11 | return (
12 |
13 |
14 | {props.children}
15 | {!hideFooter &&
16 |
17 | }
18 |
19 | )
20 | }
21 |
22 | export default SharedContainer
23 |
--------------------------------------------------------------------------------
/public/admin-assets/tinymce/plugins/code/plugin.min.js:
--------------------------------------------------------------------------------
1 | tinymce.PluginManager.add("code",function(a){function b(){var b=a.windowManager.open({title:"Source code",body:{type:"textbox",name:"code",multiline:!0,minWidth:a.getParam("code_dialog_width",600),minHeight:a.getParam("code_dialog_height",Math.min(tinymce.DOM.getViewPort().h-200,500)),spellcheck:!1,style:"direction: ltr; text-align: left"},onSubmit:function(b){a.focus(),a.undoManager.transact(function(){a.setContent(b.data.code)}),a.selection.setCursorLocation(),a.nodeChanged()}});b.find("#code").value(a.getContent({source_view:!0}))}a.addCommand("mceCodeEditor",b),a.addButton("code",{icon:"code",tooltip:"Source code",onclick:b}),a.addMenuItem("code",{icon:"code",text:"Source code",context:"tools",onclick:b})});
--------------------------------------------------------------------------------
/src/admin/client/modules/settings/emailTemplates/index.js:
--------------------------------------------------------------------------------
1 | import { connect } from 'react-redux'
2 | import { fetchEmailTemplate, updateEmailTemplate } from '../actions'
3 | import Form from './components/form'
4 |
5 | const mapStateToProps = (state, ownProps) => {
6 | return {
7 | initialValues: state.settings.emailTemplate
8 | }
9 | }
10 |
11 | const mapDispatchToProps = (dispatch, ownProps) => {
12 | return {
13 | onLoad: () => {
14 | const {templateName} = ownProps.match.params;
15 | dispatch(fetchEmailTemplate(templateName))
16 | },
17 | onSubmit: (values) => {
18 | dispatch(updateEmailTemplate(values));
19 | }
20 | }
21 | }
22 |
23 | export default connect(mapStateToProps, mapDispatchToProps)(Form);
24 |
--------------------------------------------------------------------------------
/theme/src/components/productList/itemImage.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { themeSettings, text } from '../../lib/settings'
3 | import * as helper from '../../lib/helper'
4 | import LazyLoad from 'react-lazyload'
5 |
6 | const ItemImage = ({ images, alt, title, height }) => {
7 | if(images && images.length > 0) {
8 | const imageUrl = helper.getThumbnailUrl(images[0].url, themeSettings.listThumbnailWidth);
9 |
10 | return (
11 |
12 |
13 |
14 | )
15 | } else {
16 | return (
17 |
18 | )
19 | }
20 | }
21 |
22 | export default ItemImage
23 |
--------------------------------------------------------------------------------
/public/admin-assets/tinymce/plugins/directionality/plugin.min.js:
--------------------------------------------------------------------------------
1 | tinymce.PluginManager.add("directionality",function(a){function b(b){var c,d=a.dom,e=a.selection.getSelectedBlocks();e.length&&(c=d.getAttrib(e[0],"dir"),tinymce.each(e,function(a){d.getParent(a.parentNode,"*[dir='"+b+"']",d.getRoot())||(c!=b?d.setAttrib(a,"dir",b):d.setAttrib(a,"dir",null))}),a.nodeChanged())}function c(a){var b=[];return tinymce.each("h1 h2 h3 h4 h5 h6 div p".split(" "),function(c){b.push(c+"[dir="+a+"]")}),b.join(",")}a.addCommand("mceDirectionLTR",function(){b("ltr")}),a.addCommand("mceDirectionRTL",function(){b("rtl")}),a.addButton("ltr",{title:"Left to right",cmd:"mceDirectionLTR",stateSelector:c("ltr")}),a.addButton("rtl",{title:"Right to left",cmd:"mceDirectionRTL",stateSelector:c("rtl")})});
--------------------------------------------------------------------------------
/src/admin/client/modules/apps/services/index.js:
--------------------------------------------------------------------------------
1 | import { connect } from 'react-redux'
2 | import { withRouter } from 'react-router'
3 | import { fetchServices } from '../actions'
4 | import * as webstoreAuth from 'lib/webstoreAuth'
5 | import List from './components/list'
6 |
7 | const mapStateToProps = (state, ownProps) => {
8 | const webstoreAuthorized = webstoreAuth.isCurrentTokenValid();
9 | return {
10 | services: state.apps.services,
11 | webstoreAuthorized: webstoreAuthorized
12 | }
13 | }
14 |
15 | const mapDispatchToProps = (dispatch, ownProps) => {
16 | return {
17 | fetchData: () => {
18 | dispatch(fetchServices());
19 | }
20 | }
21 | }
22 |
23 | export default withRouter(connect(mapStateToProps, mapDispatchToProps)(List));
24 |
--------------------------------------------------------------------------------
/theme/assets/images/payment/diners.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/api/server/services/apps/settings.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var mongo = require('../../lib/mongo');
4 | var parse = require('../../lib/parse');
5 |
6 | class AppSettingsService {
7 | constructor() {}
8 |
9 | getSettings(appKey) {
10 | return mongo.db.collection('appSettings').findOne({key: appKey}, { _id: 0, key: 0 });
11 | }
12 |
13 | updateSettings(appKey, data) {
14 | if (Object.keys(data).length === 0) {
15 | return new Error('Required fields are missing');
16 | }
17 |
18 | delete data.key;
19 |
20 | return mongo.db.collection('appSettings').updateOne({key: appKey}, {
21 | $set: data
22 | }, {upsert: true}).then(res => this.getSettings(appKey));
23 | }
24 | }
25 |
26 | module.exports = new AppSettingsService();
27 |
--------------------------------------------------------------------------------
/src/admin/client/modules/settings/paymentGateway/index.js:
--------------------------------------------------------------------------------
1 | import { connect } from 'react-redux'
2 | import { fetchPaymentGateway, updatePaymentGateway } from '../actions'
3 | import Form from './components/form'
4 |
5 | const mapStateToProps = (state, ownProps) => {
6 | return {
7 | gateway: ownProps.gateway,
8 | initialValues: state.settings.paymentGatewayEdit
9 | }
10 | }
11 |
12 | const mapDispatchToProps = (dispatch, ownProps) => {
13 | return {
14 | onLoad: (gateway) => {
15 | dispatch(fetchPaymentGateway(gateway || ownProps.gateway));
16 | },
17 | onSubmit: (data) => {
18 | dispatch(updatePaymentGateway(ownProps.gateway, data));
19 | }
20 | }
21 | }
22 |
23 | export default connect(mapStateToProps, mapDispatchToProps)(Form);
24 |
--------------------------------------------------------------------------------
/src/admin/client/modules/files/list/index.js:
--------------------------------------------------------------------------------
1 | import { connect } from 'react-redux'
2 | import { fetchFiles, uploadFiles, deleteFile } from '../actions'
3 | import Form from './components/form'
4 |
5 | const mapStateToProps = (state) => {
6 | return {
7 | files: state.files.files,
8 | uploading: state.files.uploading,
9 | settings: state.settings.settings
10 | }
11 | }
12 |
13 | const mapDispatchToProps = (dispatch) => {
14 | return {
15 | onLoad: () => {
16 | dispatch(fetchFiles())
17 | },
18 | onDelete: (fileName) => {
19 | dispatch(deleteFile(fileName));
20 | },
21 | onUpload: (form) => {
22 | dispatch(uploadFiles(form));
23 | }
24 | }
25 | }
26 |
27 | export default connect(mapStateToProps, mapDispatchToProps)(Form);
28 |
--------------------------------------------------------------------------------
/src/admin/client/modules/apps/actionTypes.js:
--------------------------------------------------------------------------------
1 | export const ACCOUNT_REQUEST = 'ACCOUNT_REQUEST'
2 | export const ACCOUNT_RECEIVE = 'ACCOUNT_RECEIVE'
3 |
4 | export const SERVICES_REQUEST = 'SERVICES_REQUEST'
5 | export const SERVICES_RECEIVE = 'SERVICES_RECEIVE'
6 |
7 | export const SERVICE_REQUEST = 'SERVICE_REQUEST'
8 | export const SERVICE_RECEIVE = 'SERVICE_RECEIVE'
9 |
10 | export const SERVICE_ENABLE_REQUEST = 'SERVICE_ENABLE_REQUEST'
11 | export const SERVICE_ENABLE_RECEIVE = 'SERVICE_ENABLE_RECEIVE'
12 |
13 | export const SERVICE_SETTINGS_REQUEST = 'SERVICE_SETTINGS_REQUEST'
14 | export const SERVICE_SETTINGS_RECEIVE = 'SERVICE_SETTINGS_RECEIVE'
15 |
16 | export const SERVICE_LOGS_REQUEST = 'SERVICE_LOGS_REQUEST'
17 | export const SERVICE_LOGS_RECEIVE = 'SERVICE_LOGS_RECEIVE'
18 |
--------------------------------------------------------------------------------
/src/admin/client/modules/customerGroups/list/index.js:
--------------------------------------------------------------------------------
1 | import { connect } from 'react-redux'
2 | import { selectGroup, fetchGroupsIfNeeded } from '../actions'
3 | import { fetchCustomers } from '../../customers/actions'
4 | import List from '../components/list'
5 |
6 | const mapStateToProps = (state) => {
7 | return {
8 | items: state.customerGroups.items,
9 | selectedId: state.customerGroups.selectedId
10 | }
11 | }
12 |
13 | const mapDispatchToProps = (dispatch) => {
14 | return {
15 | onLoad: () => {
16 | dispatch(fetchGroupsIfNeeded());
17 | },
18 | onSelect: (groupId) => {
19 | dispatch(selectGroup(groupId));
20 | dispatch(fetchCustomers());
21 | }
22 | }
23 | }
24 |
25 | export default connect(mapStateToProps, mapDispatchToProps)(List);
26 |
--------------------------------------------------------------------------------
/src/admin/client/modules/orderStatuses/list/index.js:
--------------------------------------------------------------------------------
1 | import { connect } from 'react-redux'
2 | import { selectStatus, fetchStatusesIfNeeded } from '../actions'
3 | import { fetchOrders } from '../../orders/actions'
4 | import List from '../components/list'
5 |
6 | const mapStateToProps = (state) => {
7 | return {
8 | items: state.orderStatuses.items,
9 | selectedId: state.orderStatuses.selectedId
10 | }
11 | }
12 |
13 | const mapDispatchToProps = (dispatch) => {
14 | return {
15 | onLoad: () => {
16 | dispatch(fetchStatusesIfNeeded());
17 | },
18 | onSelect: (statusId) => {
19 | dispatch(selectStatus(statusId));
20 | dispatch(fetchOrders());
21 | }
22 | }
23 | }
24 |
25 | export default connect(mapStateToProps, mapDispatchToProps)(List);
26 |
--------------------------------------------------------------------------------
/src/store/client/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import ReactDOM from 'react-dom'
3 | import {createStore, applyMiddleware} from 'redux'
4 | import {Provider} from 'react-redux'
5 | import thunkMiddleware from 'redux-thunk'
6 | import { BrowserRouter } from 'react-router-dom'
7 | import reducers from '../shared/reducers'
8 | import * as analytics from '../shared/analytics'
9 | import App from '../shared/app'
10 |
11 | const initialState = window.__APP_STATE__;
12 | const store = createStore(reducers, initialState, applyMiddleware(thunkMiddleware));
13 |
14 | ReactDOM.hydrate(
15 |
16 |
17 |
18 |
19 | ,
20 | document.getElementById('app'))
21 |
22 | analytics.onPageLoad({ state: initialState });
23 |
--------------------------------------------------------------------------------
/src/admin/client/modules/customerGroups/head/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { connect } from 'react-redux'
3 | import { reset } from 'redux-form';
4 | import { deleteGroup, deselectGroup } from '../actions'
5 | import Buttons from './components/buttons'
6 |
7 | const mapStateToProps = (state) => {
8 | return {
9 | selected: state.customerGroups.items.find(item => item.id === state.customerGroups.selectedId)
10 | }
11 | }
12 |
13 | const mapDispatchToProps = (dispatch) => {
14 | return {
15 | onDelete: (id) => {
16 | dispatch(deleteGroup(id));
17 | dispatch(reset('FormCustomerGroup'));
18 | },
19 | onCreate: () => {
20 | dispatch(deselectGroup())
21 | }
22 | }
23 | }
24 |
25 | export default connect(mapStateToProps, mapDispatchToProps)(Buttons);
26 |
--------------------------------------------------------------------------------
/src/admin/client/modules/orderStatuses/head/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { connect } from 'react-redux'
3 | import { reset } from 'redux-form';
4 | import { deleteStatus, deselectStatus } from '../actions'
5 | import Buttons from './components/buttons'
6 |
7 | const mapStateToProps = (state) => {
8 | return {
9 | selected: state.orderStatuses.items.find(item => item.id === state.orderStatuses.selectedId)
10 | }
11 | }
12 |
13 | const mapDispatchToProps = (dispatch) => {
14 | return {
15 | onDelete: (id) => {
16 | dispatch(deleteStatus(id));
17 | dispatch(reset('FormOrderStatus'));
18 | },
19 | onCreate: () => {
20 | dispatch(deselectStatus())
21 | }
22 | }
23 | }
24 |
25 | export default connect(mapStateToProps, mapDispatchToProps)(Buttons);
26 |
--------------------------------------------------------------------------------
/src/admin/client/modules/settings/checkoutFields/index.js:
--------------------------------------------------------------------------------
1 | import { connect } from 'react-redux'
2 | import { fetchCheckoutField, updateCheckoutField } from '../actions'
3 | import Form from './components/form'
4 |
5 | const mapStateToProps = (state, ownProps) => {
6 | return {
7 | initialValues: state.settings.checkoutField
8 | }
9 | }
10 |
11 | const mapDispatchToProps = (dispatch, ownProps) => {
12 | return {
13 | onLoad: () => {
14 | const {fieldName} = ownProps.match.params;
15 | dispatch(fetchCheckoutField(fieldName))
16 | },
17 | onSubmit: (values) => {
18 | dispatch(updateCheckoutField(values));
19 | ownProps.history.push('/admin/settings/checkout');
20 | }
21 | }
22 | }
23 |
24 | export default connect(mapStateToProps, mapDispatchToProps)(Form);
25 |
--------------------------------------------------------------------------------
/src/admin/client/modules/shared/imageUpload/style.css:
--------------------------------------------------------------------------------
1 | .preview {
2 | height: 220px;
3 | width: 200px;
4 | }
5 |
6 | .preview img {
7 | max-width: 100%;
8 | max-height: 100%;
9 | }
10 |
11 | .footer {
12 | background-color: rgba(0,0,0,0.05);
13 | }
14 |
15 | .dropzone {
16 | cursor: pointer;
17 | }
18 | .dropText {
19 | color: #a1a1a1;
20 | font-size: 14px;
21 | }
22 | .dropzoneActive {
23 | background-color: rgba(18,179,117, 0.4);
24 | }
25 | .dropzoneReject {
26 | background-color: rgba(244,67,54,0.8);
27 | }
28 | .dropzoneReject .preview img,
29 | .dropzoneActive .preview img {
30 | opacity: 0.3
31 | }
32 |
33 | .noImage {
34 | display: flex;
35 | height: 100%;
36 | text-align: center;
37 | align-items: center;
38 | justify-content: center;
39 | flex-direction: column;
40 | }
41 |
--------------------------------------------------------------------------------
/theme/assets/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "The Shop",
3 | "short_name": "The Shop",
4 | "start_url": "/",
5 | "display": "standalone",
6 | "background_color": "#F9F9F9",
7 | "theme_color": "#f5f5f5",
8 | "icons": [{
9 | "src": "/assets/images/icons/icon-16.png",
10 | "sizes": "16x16",
11 | "type": "image/png"
12 | },{
13 | "src": "/assets/images/icons/icon-32.png",
14 | "sizes": "32x32",
15 | "type": "image/png"
16 | },{
17 | "src": "/assets/images/icons/icon-128.png",
18 | "sizes": "128x128",
19 | "type": "image/png"
20 | },{
21 | "src": "/assets/images/icons/icon-256.png",
22 | "sizes": "256x256",
23 | "type": "image/png"
24 | },{
25 | "src": "/assets/images/icons/icon-512.png",
26 | "sizes": "512x512",
27 | "type": "image/png"
28 | }]
29 | }
30 |
--------------------------------------------------------------------------------
/theme/src/components/categoryBreadcrumbs.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { NavLink } from 'react-router-dom'
3 | import { themeSettings, text } from '../lib/settings'
4 | import * as helper from '../lib/helper'
5 |
6 | const CategoryBreadcrumbs = ({ currentCategory, categories }) => {
7 | const items = helper.getCategoryBreadcrumbs(currentCategory.id, categories);
8 | return (
9 |
20 | )
21 | }
22 |
23 | export default CategoryBreadcrumbs;
24 |
--------------------------------------------------------------------------------
/process.json:
--------------------------------------------------------------------------------
1 | {
2 | "apps": [{
3 | "name": "api",
4 | "script": "./src/api/server/index.js",
5 | "watch": ["./config/server.js", "./src/api/server/"],
6 | "instances": "1",
7 | "exec_mode": "fork",
8 | "env": {
9 | "NODE_ENV": "production"
10 | },
11 | "watch_options": {
12 | "persistent": true,
13 | "ignoreInitial": false
14 | }
15 | }, {
16 | "name": "store",
17 | "script": "./dist/store/server/index.js",
18 | "watch": ["./config/server.js", "./public/admin/index.html", "./dist/store/", "./theme/dist/", "./theme/assets/index.html"],
19 | "instances": "1",
20 | "exec_mode": "fork",
21 | "env": {
22 | "NODE_ENV": "production"
23 | },
24 | "watch_options": {
25 | "persistent": true,
26 | "ignoreInitial": false
27 | }
28 | }]
29 | }
30 |
--------------------------------------------------------------------------------
/src/admin/client/modules/products/edit/additional/index.js:
--------------------------------------------------------------------------------
1 | import { connect } from 'react-redux'
2 | import { withRouter } from 'react-router'
3 | import { updateProduct } from '../../actions'
4 | import ProductAdditionalForm from './components/form'
5 |
6 | const mapStateToProps = (state, ownProps) => {
7 | return {
8 | initialValues: state.products.editProduct,
9 | settings: state.settings.settings
10 | }
11 | }
12 |
13 | const mapDispatchToProps = (dispatch, ownProps) => {
14 | return {
15 | onSubmit: (values) => {
16 | dispatch(updateProduct({
17 | id: values.id,
18 | tags: values.tags,
19 | related_product_ids: values.related_product_ids
20 | }));
21 | }
22 | }
23 | }
24 |
25 | export default withRouter(connect(mapStateToProps, mapDispatchToProps)(ProductAdditionalForm));
26 |
--------------------------------------------------------------------------------
/src/admin/client/modules/shared/imageUploadMultiple/item.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import messages from 'lib/text'
3 | import style from './style.css'
4 |
5 | import Paper from 'material-ui/Paper';
6 | import FontIcon from 'material-ui/FontIcon';
7 | import IconButton from 'material-ui/IconButton';
8 |
9 | const GalleryItem = ({ url, alt, id, onDelete }) => (
10 |
11 |
12 |

13 |
14 |
15 | { onDelete(id) }}>
16 | delete
17 |
18 |
19 |
20 | )
21 |
22 | export default GalleryItem;
23 |
--------------------------------------------------------------------------------
/theme/assets/images/close.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
38 |
--------------------------------------------------------------------------------
/theme/src/index.js:
--------------------------------------------------------------------------------
1 | export {updateThemeSettings} from './lib/settings'
2 | export {default as SharedContainer} from './containers/shared'
3 | export {default as IndexContainer} from './containers/index'
4 | export {default as CategoryContainer} from './containers/category'
5 | export {default as ProductContainer} from './containers/product'
6 | export {default as NotFoundContainer} from './containers/notfound'
7 | export {default as PageContainer} from './containers/page'
8 | export {default as CheckoutContainer} from './containers/checkout'
9 | export {default as CheckoutSuccessContainer} from './containers/checkoutSuccess'
10 | export {default as SearchContainer} from './containers/search'
11 |
12 | // combine all css files into one with webpack. Hack to deal with server side rendering.
13 | if(typeof window !== 'undefined'){
14 | require('../assets/css/theme.scss');
15 | }
16 |
--------------------------------------------------------------------------------
/locales/store/zh_CN.json:
--------------------------------------------------------------------------------
1 | {
2 | "loading": "加载中...",
3 | "optional": "可选",
4 | "shippingTo": "送货至",
5 | "shippingMethods": "运送选项",
6 | "shippingMethod": "运送方式",
7 | "paymentMethods": "付款选项",
8 | "paymentMethod": "付款方式",
9 | "shippingAddress": "送货地址",
10 | "billingAddress": "账单地址",
11 | "orderSubmit": "下单",
12 | "emptyCheckout": "你的购物车是空的",
13 | "email": "电子邮件",
14 | "mobile": "手机",
15 | "country": "国家",
16 | "state": "省/自治区",
17 | "city": "城市",
18 | "fullName": "全名",
19 | "address1": "地址栏 1",
20 | "address2": "地址栏 2",
21 | "postal_code": "邮政编码",
22 | "phone": "电话",
23 | "company": "公司",
24 | "comments": "评论",
25 | "required": "此字段需要填写",
26 | "emailInvalid": "请输入一个有效的电子邮件地址。",
27 | "sameAsShipping": "同送货地址",
28 | "edit": "编辑",
29 | "next": "下一步",
30 | "customerDetails": "客户详情",
31 | "shipping": "运送",
32 | "payment": "付款"
33 | }
34 |
--------------------------------------------------------------------------------
/src/admin/client/modules/customers/listHead/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { connect } from 'react-redux'
3 | import { fetchCustomers, deleteCustomers, setGroup, setFilterSearch } from '../actions'
4 | import Buttons from './components/buttons'
5 |
6 | const mapStateToProps = (state) => {
7 | return {
8 | search: state.customers.search,
9 | selectedCount: state.customers.selected.length
10 | }
11 | }
12 |
13 | const mapDispatchToProps = (dispatch) => {
14 | return {
15 | setSearch: (value) => {
16 | dispatch(setFilterSearch(value));
17 | dispatch(fetchCustomers());
18 | },
19 | onDelete: () => {
20 | dispatch(deleteCustomers());
21 | },
22 | onSetGroup: (group_id) => {
23 | dispatch(setGroup(group_id));
24 | }
25 | }
26 | }
27 |
28 | export default connect(mapStateToProps, mapDispatchToProps)(Buttons);
29 |
--------------------------------------------------------------------------------
/src/admin/client/modules/productCategories/list/index.js:
--------------------------------------------------------------------------------
1 | import { connect } from 'react-redux'
2 | import { selectCategory, fetchCategoriesIfNeeded } from '../actions'
3 | import { fetchProducts } from '../../products/actions'
4 | import List from '../components/list'
5 |
6 | const mapStateToProps = (state) => {
7 | return {
8 | items: state.productCategories.items,
9 | selectedId: state.productCategories.selectedId
10 | }
11 | }
12 |
13 | const mapDispatchToProps = (dispatch) => {
14 | return {
15 | onLoad: () => {
16 | dispatch(fetchCategoriesIfNeeded());
17 | },
18 | onSelect: (categoryId) => {
19 | dispatch(selectCategory(categoryId));
20 | dispatch(fetchProducts());
21 | },
22 | onCreate: () => {
23 | dispatch(createCategory())
24 | }
25 | }
26 | }
27 |
28 | export default connect(mapStateToProps, mapDispatchToProps)(List);
29 |
--------------------------------------------------------------------------------
/src/admin/client/modules/products/edit/images/components/images.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import Gallery from 'modules/shared/imageUploadMultiple'
3 | import Paper from 'material-ui/Paper';
4 |
5 | export default class ProductImages extends React.Component {
6 | constructor(props) {
7 | super(props);
8 | }
9 |
10 | componentDidMount() {
11 | this.props.fetchData();
12 | }
13 |
14 | render() {
15 | let {productId, images, onImageDelete, onImageSort, onImageUpload, uploadingImages} = this.props;
16 | return (
17 |
18 |
19 |
20 |
21 |
22 | )
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/admin/client/modules/settings/theme/index.js:
--------------------------------------------------------------------------------
1 | import { connect } from 'react-redux'
2 | import { exportRequest, exportReceive, installRequest, installReceive } from '../actions'
3 | import Form from './components/form'
4 |
5 | const mapStateToProps = (state) => {
6 | return {
7 | exportInProcess: state.settings.exportInProcess,
8 | installInProcess: state.settings.installInProcess
9 | }
10 | }
11 |
12 | const mapDispatchToProps = (dispatch) => {
13 | return {
14 | exportRequest: () => {
15 | dispatch(exportRequest());
16 | },
17 | exportReceive: () => {
18 | dispatch(exportReceive());
19 | },
20 | installRequest: () => {
21 | dispatch(installRequest());
22 | },
23 | installReceive: () => {
24 | dispatch(installReceive())
25 | }
26 | }
27 | }
28 |
29 | export default connect(mapStateToProps, mapDispatchToProps)(Form);
30 |
--------------------------------------------------------------------------------
/src/admin/client/modules/products/edit/general/index.js:
--------------------------------------------------------------------------------
1 | import { connect } from 'react-redux'
2 | import { withRouter } from 'react-router'
3 | import { updateProduct } from '../../actions'
4 | import ProductGeneralForm from './components/form'
5 |
6 | const mapStateToProps = (state, ownProps) => {
7 | return {
8 | initialValues: state.products.editProduct
9 | }
10 | }
11 |
12 | const mapDispatchToProps = (dispatch, ownProps) => {
13 | return {
14 | onSubmit: (values) => {
15 | dispatch(updateProduct({
16 | id: values.id,
17 | name: values.name,
18 | slug: values.slug,
19 | meta_title: values.meta_title,
20 | meta_description: values.meta_description,
21 | description: values.description
22 | }));
23 | }
24 | }
25 | }
26 |
27 | export default withRouter(connect(mapStateToProps, mapDispatchToProps)(ProductGeneralForm));
28 |
--------------------------------------------------------------------------------
/src/admin/client/modules/settings/generalLogo/components/form.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import ImageUpload from 'modules/shared/imageUpload'
3 | import Paper from 'material-ui/Paper';
4 |
5 | export default class GeneralLogoSettingsForm extends React.Component {
6 | componentDidMount() {
7 | this.props.onLoad();
8 | }
9 |
10 | render() {
11 | const { onImageUpload, onImageDelete, settings } = this.props;
12 | let imageUrl = settings && settings.logo ? settings.logo : '';
13 |
14 | return (
15 |
16 |
17 |
23 |
24 |
25 | )
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/admin/client/modules/apps/appDetails/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import AppDescription from './description'
3 | import style from './style.css'
4 | import Paper from 'material-ui/Paper'
5 | import apps from 'src/apps'
6 |
7 | const AppDetails = ({ match }) => {
8 | const { appKey } = match.params;
9 | const app = apps.find(a => a.Description.key === appKey);
10 | const AppModule = app.App;
11 | const appDescription = app.Description;
12 |
13 | return (
14 |
24 | )
25 | }
26 |
27 | export default AppDetails;
28 |
--------------------------------------------------------------------------------
/theme/src/components/pageList/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import api from '../../lib/api'
3 | import PageList from './list'
4 |
5 | export default class CustomPageList extends React.Component {
6 | constructor(props) {
7 | super(props);
8 | this.state = {
9 | pages: []
10 | }
11 | }
12 |
13 | componentDidMount() {
14 | this.fetchData(this.props);
15 | }
16 |
17 | componentWillReceiveProps(nextProps) {
18 | this.fetchData(nextProps);
19 | }
20 |
21 | fetchData = ({ tags, sort }) => {
22 | const filter = {
23 | tags: tags,
24 | sort: sort
25 | };
26 |
27 | api.ajax.pages.list(filter).then(({status, json}) => {
28 | this.setState({
29 | pages: json
30 | })
31 | });
32 | }
33 |
34 | render() {
35 | const { pages } = this.state;
36 | return (
37 |
38 | )
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/theme/src/components/sort.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { themeSettings, text } from '../lib/settings'
3 |
4 | const Sort = ({ defaultSort, currentSort, setSort }) => {
5 | return (
6 |
7 |
{text.sort}:
8 |
9 |
10 |
16 |
17 |
18 |
19 | )
20 | }
21 |
22 | export default Sort
23 |
--------------------------------------------------------------------------------
/src/admin/client/rootReducer.js:
--------------------------------------------------------------------------------
1 | import { combineReducers } from 'redux';
2 | import { reducer as formReducer } from 'redux-form'
3 |
4 | import productCategories from 'modules/productCategories/reducer';
5 | import products from 'modules/products/reducer';
6 | import customerGroups from 'modules/customerGroups/reducer';
7 | import customers from 'modules/customers/reducer';
8 | import orders from 'modules/orders/reducer';
9 | import orderStatuses from 'modules/orderStatuses/reducer';
10 | import pages from 'modules/pages/reducer';
11 | import settings from 'modules/settings/reducer';
12 | import apps from 'modules/apps/reducer';
13 | import files from 'modules/files/reducer';
14 |
15 | export default combineReducers({
16 | form: formReducer,
17 | productCategories,
18 | products,
19 | settings,
20 | customerGroups,
21 | customers,
22 | orders,
23 | orderStatuses,
24 | pages,
25 | apps,
26 | files
27 | });
28 |
--------------------------------------------------------------------------------
/src/admin/client/routes/apps/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { Switch, Route, NavLink } from 'react-router-dom'
3 | import * as auth from 'lib/webstoreAuth'
4 | import NotFound from 'routes/notFound'
5 | import Login from 'routes/apps/login'
6 | import Account from 'modules/apps/account'
7 | import Services from 'modules/apps/services'
8 | import ServiceDetails from 'modules/apps/serviceDetails'
9 | import AppDetails from 'modules/apps/appDetails'
10 |
11 | export default() => (
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 | )
21 |
--------------------------------------------------------------------------------
/public/admin-assets/tinymce/plugins/emoticons/plugin.min.js:
--------------------------------------------------------------------------------
1 | tinymce.PluginManager.add("emoticons",function(a,b){function c(){var a;return a='',tinymce.each(d,function(c){a+="",tinymce.each(c,function(c){var d=b+"/img/smiley-"+c+".gif";a+=' | '}),a+="
"}),a+="
"}var d=[["cool","cry","embarassed","foot-in-mouth"],["frown","innocent","kiss","laughing"],["money-mouth","sealed","smile","surprised"],["tongue-out","undecided","wink","yell"]];a.addButton("emoticons",{type:"panelbutton",panel:{role:"application",autohide:!0,html:c,onclick:function(b){var c=a.dom.getParent(b.target,"a");c&&(a.insertContent('
'),this.hide())}},tooltip:"Emoticons"})});
--------------------------------------------------------------------------------
/src/admin/client/modules/apps/head/components/buttons.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { Link } from 'react-router-dom'
3 | import messages from 'lib/text'
4 |
5 | import FontIcon from 'material-ui/FontIcon';
6 | import IconMenu from 'material-ui/IconMenu';
7 | import IconButton from 'material-ui/IconButton';
8 | import MenuItem from 'material-ui/MenuItem';
9 |
10 | const WebStoreMenu = () => {
11 | return (
12 |
15 | more_vert
16 |
17 | }
18 | targetOrigin={{horizontal: 'right', vertical: 'top'}}
19 | anchorOrigin={{horizontal: 'right', vertical: 'top'}}
20 | >
21 | } primaryText={messages.account} />
22 |
23 | )
24 | }
25 |
26 | export default WebStoreMenu;
27 |
--------------------------------------------------------------------------------
/src/admin/client/modules/files/list/components/style.css:
--------------------------------------------------------------------------------
1 | .item {
2 | font-size: 14px;
3 | padding: 4px 10px;
4 | border-bottom: 1px solid rgb(224, 224, 224);
5 | }
6 |
7 | .item:last-of-type {
8 | border-bottom: none;
9 | }
10 |
11 | .item:hover{
12 | background-color: rgba(0, 0, 0, 0.05);
13 | }
14 |
15 | .name a {
16 | color: rgb(0,142,180);
17 | text-decoration: none;
18 | overflow: hidden;
19 | text-overflow: ellipsis;
20 | white-space: nowrap;
21 | display: block;
22 | }
23 |
24 | .name a:hover {
25 | text-decoration: underline;
26 | }
27 |
28 | .date, .size {
29 | color: rgba(0, 0, 0, 0.54);
30 | text-align: right;
31 | }
32 |
33 | .more {
34 | text-align: right;
35 | }
36 |
37 | .head {
38 | color: rgba(0, 0, 0, 0.54);
39 | font-size: 14px;
40 | font-weight: 500;
41 | padding: 16px 16px 0 26px;
42 | text-align: right;
43 | }
44 |
45 | .head div:first-of-type {
46 | text-align: left;
47 | }
48 |
--------------------------------------------------------------------------------
/src/admin/client/modules/orders/listHead/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { connect } from 'react-redux'
3 | import { withRouter } from 'react-router'
4 | import { fetchOrders, setFilter, deleteOrders, createOrder } from '../actions'
5 | import Buttons from './components/buttons'
6 |
7 | const mapStateToProps = (state, ownProps) => {
8 | return {
9 | search: state.orders.filter.search,
10 | selectedCount: state.orders.selected.length
11 | }
12 | }
13 |
14 | const mapDispatchToProps = (dispatch, ownProps) => {
15 | return {
16 | setSearch: (value) => {
17 | dispatch(setFilter({ search: value }));
18 | dispatch(fetchOrders());
19 | },
20 | onDelete: () => {
21 | dispatch(deleteOrders());
22 | },
23 | onCreate: () => {
24 | dispatch(createOrder(ownProps.history))
25 | }
26 | }
27 | }
28 |
29 | export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Buttons));
30 |
--------------------------------------------------------------------------------
/src/api/server/services/orders/shippingMethodsLight.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var mongo = require('../../lib/mongo');
4 | var ObjectID = require('mongodb').ObjectID;
5 |
6 | class ShippingMethodsLightService {
7 | constructor() {}
8 |
9 | getMethods(filter = {}) {
10 | return mongo.db.collection('shippingMethods').find(filter).toArray().then(items => items.map(item => this.changeProperties(item)));
11 | }
12 |
13 | getMethodPrice(id) {
14 | let filter = {};
15 | if (id) {
16 | filter._id = new ObjectID(id);
17 | }
18 |
19 | return this.getMethods(filter).then(methods => {
20 | return methods.length > 0
21 | ? methods[0].price || 0
22 | : 0
23 | })
24 | }
25 |
26 | changeProperties(item) {
27 | if (item) {
28 | item.id = item._id.toString();
29 | delete item._id;
30 | }
31 | return item;
32 | }
33 | }
34 |
35 | module.exports = new ShippingMethodsLightService();
36 |
--------------------------------------------------------------------------------
/public/admin-assets/tinymce/plugins/wordcount/plugin.min.js:
--------------------------------------------------------------------------------
1 | tinymce.PluginManager.add("wordcount",function(a){function b(){a.theme.panel.find("#wordcount").text(["Words: {0}",e.getCount()])}var c,d,e=this;c=a.getParam("wordcount_countregex",/[\w\u2019\x27\-\u00C0-\u1FFF]+/g),d=a.getParam("wordcount_cleanregex",/[0-9.(),;:!?%#$?\x27\x22_+=\\\/\-]*/g),a.on("init",function(){var c=a.theme.panel&&a.theme.panel.find("#statusbar")[0];c&&tinymce.util.Delay.setEditorTimeout(a,function(){c.insert({type:"label",name:"wordcount",text:["Words: {0}",e.getCount()],classes:"wordcount",disabled:a.settings.readonly},0),a.on("setcontent beforeaddundo",b),a.on("keyup",function(a){32==a.keyCode&&b()})},0)}),e.getCount=function(){var b=a.getContent({format:"raw"}),e=0;if(b){b=b.replace(/\.\.\./g," "),b=b.replace(/<.[^<>]*?>/g," ").replace(/ | /gi," "),b=b.replace(/(\w+)(?[a-z0-9]+;)+(\w+)/i,"$1$3").replace(/&.+?;/g," "),b=b.replace(d,"");var f=b.match(c);f&&(e=f.length)}return e}});
--------------------------------------------------------------------------------
/theme/src/components/productDetails/attributes.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { themeSettings, text } from '../../lib/settings'
3 |
4 | const Attribute = ({ name, value }) => (
5 |
6 |
7 | {name}:
8 |
9 |
10 | {value}
11 |
12 |
13 | )
14 |
15 | const Attributes = ({ attributes }) => {
16 | if(attributes && attributes.length > 0) {
17 | const items = attributes.map((attribute, index) => (
18 |
19 | ))
20 |
21 | return (
22 |
23 |
{text.attributes}
24 | {items}
25 |
26 | )
27 | } else {
28 | return null;
29 | }
30 | }
31 | export default Attributes;
32 |
--------------------------------------------------------------------------------
/src/admin/client/modules/customers/list/components/head.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import Subheader from 'material-ui/Subheader';
3 | import Checkbox from 'material-ui/Checkbox';
4 | import messages from 'lib/text'
5 |
6 | export default ({ onSelectAll }) => (
7 |
8 |
9 |
10 | { onSelectAll(isInputChecked); }} />
11 |
12 |
13 | {messages.customers_name}
14 |
15 |
16 | {messages.customers_location}
17 |
18 |
19 | {messages.customers_orders}
20 |
21 |
22 | {messages.customers_totalSpent}
23 |
24 |
25 |
26 | )
27 |
--------------------------------------------------------------------------------
/theme/assets/images/arrow_back.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
41 |
--------------------------------------------------------------------------------
/src/api/server/routes/sitemap.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const security = require('../lib/security');
4 | var SitemapService = require('../services/sitemap');
5 |
6 | class SitemapRoute {
7 | constructor(router) {
8 | this.router = router;
9 | this.registerRoutes();
10 | }
11 |
12 | registerRoutes() {
13 | this.router.get('/v1/sitemap', security.checkUserScope.bind(this, security.scope.READ_SITEMAP), this.getPaths.bind(this));
14 | }
15 |
16 | getPaths(req, res, next) {
17 | if (req.query.path) {
18 | SitemapService.getSinglePath(req.query.path, req.query.enabled).then((data) => {
19 | if (data) {
20 | res.send(data)
21 | } else {
22 | res.status(404).end()
23 | }
24 | }).catch(next);
25 | } else {
26 | SitemapService.getPaths(req.query.enabled).then((data) => {
27 | res.send(data)
28 | }).catch(next);
29 | }
30 | }
31 | }
32 |
33 | module.exports = SitemapRoute;
34 |
--------------------------------------------------------------------------------
/src/api/server/controllers/sitemap.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const security = require('../lib/security');
4 | var SitemapService = require('../services/sitemap');
5 |
6 | class SitemapController {
7 | constructor(router) {
8 | this.router = router;
9 | this.registerRoutes();
10 | }
11 |
12 | registerRoutes() {
13 | this.router.get('/v1/sitemap', security.checkUserScope.bind(this, security.scope.READ_SITEMAP), this.getPaths.bind(this));
14 | }
15 |
16 | getPaths(req, res, next) {
17 | if (req.query.path) {
18 | SitemapService.getSinglePath(req.query.path, req.query.enabled).then((data) => {
19 | if (data) {
20 | res.send(data)
21 | } else {
22 | res.status(404).end()
23 | }
24 | }).catch(next);
25 | } else {
26 | SitemapService.getPaths(req.query.enabled).then((data) => {
27 | res.send(data)
28 | }).catch(next);
29 | }
30 | }
31 | }
32 |
33 | module.exports = SitemapController;
34 |
--------------------------------------------------------------------------------
/src/api/server/services/settings/paymentGateways.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var mongo = require('../../lib/mongo');
4 |
5 | class PaymentGatewaysService {
6 | constructor() {}
7 |
8 | getGateway(gatewayName) {
9 | return mongo.db.collection('paymentGateways').findOne({name: gatewayName}).then(data => {
10 | return this.changeProperties(data);
11 | });
12 | }
13 |
14 | updateGateway(gatewayName, data) {
15 | if (Object.keys(data).length === 0) {
16 | return this.getGateway(gatewayName);
17 | } else {
18 | return mongo.db.collection('paymentGateways')
19 | .updateOne(
20 | { name: gatewayName },
21 | { $set: data },
22 | { upsert: true })
23 | .then(res => this.getGateway(gatewayName));
24 | }
25 | }
26 |
27 | changeProperties(data) {
28 | if (data) {
29 | delete data._id;
30 | delete data.name;
31 | }
32 | return data;
33 | }
34 | }
35 |
36 | module.exports = new PaymentGatewaysService();
37 |
--------------------------------------------------------------------------------
/theme/assets/images/thin_arrow_right.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
38 |
--------------------------------------------------------------------------------
/src/admin/client/modules/productCategories/actionTypes.js:
--------------------------------------------------------------------------------
1 | export const CATEGORIES_REQUEST = 'CATEGORIES_REQUEST'
2 | export const CATEGORIES_RECEIVE = 'CATEGORIES_RECEIVE'
3 | export const CATEGORIES_FAILURE = 'CATEGORIES_FAILURE'
4 |
5 | export const CATEGORIES_SELECT = 'CATEGORIES_SELECT'
6 | export const CATEGORIES_DESELECT = 'CATEGORIES_DESELECT'
7 |
8 | export const CATEGORY_UPDATE_REQUEST = 'CATEGORY_UPDATE_REQUEST'
9 | export const CATEGORY_UPDATE_SUCCESS = 'CATEGORY_UPDATE_SUCCESS'
10 | export const CATEGORY_UPDATE_FAILURE = 'CATEGORY_UPDATE_FAILURE'
11 |
12 | export const CATEGORY_CREATE_SUCCESS = 'CATEGORY_CREATE_SUCCESS'
13 | export const CATEGORY_DELETE_SUCCESS = 'CATEGORY_DELETE_SUCCESS'
14 | export const CATEGORY_MOVE_UPDOWN_SUCCESS = 'CATEGORY_MOVE_UPDOWN_SUCCESS'
15 | export const CATEGORY_REPLACE_SUCCESS = 'CATEGORY_REPLACE_SUCCESS'
16 |
17 | export const CATEGORY_IMAGE_UPLOAD_START = 'CATEGORY_IMAGE_UPLOAD_START'
18 | export const CATEGORY_IMAGE_UPLOAD_END = 'CATEGORY_IMAGE_UPLOAD_END'
19 |
--------------------------------------------------------------------------------
/src/admin/client/modules/products/listFilter/index.js:
--------------------------------------------------------------------------------
1 | import { connect } from 'react-redux'
2 | import { fetchProducts, setFilter } from '../actions'
3 | import Filter from './components/filter'
4 |
5 | const mapStateToProps = (state) => {
6 | return {
7 | filter: state.products.filter
8 | }
9 | }
10 |
11 | const mapDispatchToProps = (dispatch) => {
12 | return {
13 | setEnabled: (value) => {
14 | dispatch(setFilter({ enabled: value }));
15 | dispatch(fetchProducts());
16 | },
17 | setDiscontinued: (value) => {
18 | dispatch(setFilter({ discontinued: value }));
19 | dispatch(fetchProducts());
20 | },
21 | setOnSale: (value) => {
22 | dispatch(setFilter({ onSale: value }));
23 | dispatch(fetchProducts());
24 | },
25 | setStock: (value) => {
26 | dispatch(setFilter({ stockStatus: value }));
27 | dispatch(fetchProducts());
28 | }
29 | }
30 | }
31 |
32 | export default connect(mapStateToProps, mapDispatchToProps)(Filter);
33 |
--------------------------------------------------------------------------------
/src/admin/client/modules/products/edit/option/components/style.css:
--------------------------------------------------------------------------------
1 | .button {
2 | margin-left: 12px;
3 | }
4 |
5 | .innerBox {
6 | padding: 30px;
7 | }
8 |
9 | .error {
10 | color: rgb(244, 67, 54);
11 | }
12 |
13 | .shortControl {
14 | max-width: 300px;
15 | margin: 15px 0;
16 | }
17 |
18 | .grid {}
19 |
20 | .gridRow {
21 | display: flex;
22 | flex-flow: row wrap;
23 | width: 100%;
24 | align-items: center;
25 | justify-content: space-around;
26 | align-items: center;
27 | border-top: 1px solid rgb(224, 224, 224);
28 | }
29 |
30 | .gridRow:hover {
31 | background-color: rgba(0, 0, 0, 0.03);
32 | }
33 |
34 | .gridColInput {
35 | padding-left: 30px;
36 | flex: 8 1;
37 | }
38 | .gridColButton {
39 | padding-right: 30px;
40 | text-align: right;
41 | flex: 1 1;
42 | }
43 |
44 | .textInput {
45 | width: 100%;
46 | margin: 0;
47 | padding: 0;
48 | border: none;
49 | outline: none;
50 | background-color: transparent;
51 | font-size: 15px;
52 | height: 60px;
53 | }
54 |
--------------------------------------------------------------------------------
/src/store/server/sitemapRendering.js:
--------------------------------------------------------------------------------
1 | import fs from 'fs'
2 | import sm from 'sitemap'
3 | import api from './api'
4 |
5 | const SITEMAP_EXCLUDE_PATH = ['/', '/checkout', '/checkout-success', '/account', '/cart', '/login', '/logout', '/register'];
6 |
7 | const sitemapRendering = (req, res) => {
8 | Promise.all([
9 | api.sitemap.list({ enabled: true }),
10 | api.settings.retrieve()
11 | ]).then(([sitemapResponse, settingsResponse]) => {
12 | const urls = sitemapResponse.json.filter(item => item.type !== 'reserved' && item.type !== 'search' && !SITEMAP_EXCLUDE_PATH.includes(item.path)).map(item => item.path)
13 | const sitemap = sm.createSitemap ({
14 | hostname: settingsResponse.json.domain,
15 | urls: urls
16 | });
17 | sitemap.toXML((err, xml) => {
18 | if (err) {
19 | res.status(500).end();
20 | }
21 | res.header('Content-Type', 'application/xml');
22 | res.send(xml);
23 | });
24 | })
25 | }
26 |
27 | export default sitemapRendering;
28 |
--------------------------------------------------------------------------------
/theme/assets/images/success.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
11 |
--------------------------------------------------------------------------------
/src/admin/client/modules/apps/account/index.js:
--------------------------------------------------------------------------------
1 | import { connect } from 'react-redux'
2 | import { fetchAccount, updateAccount, updateDeveloperAccount } from '../actions'
3 | import Details from './components/details'
4 | import * as webstoreAuth from 'lib/webstoreAuth'
5 |
6 | const mapStateToProps = (state, ownProps) => {
7 | return {
8 | account: state.apps.account
9 | }
10 | }
11 |
12 | const mapDispatchToProps = (dispatch, ownProps) => {
13 | return {
14 | fetchData: () => {
15 | const webstoreAuthorized = webstoreAuth.isCurrentTokenValid();
16 | if(webstoreAuthorized){
17 | dispatch(fetchAccount())
18 | } else {
19 | ownProps.history.push('/admin/apps/login');
20 | }
21 | },
22 | onAccountSubmit: (values) => {
23 | dispatch(updateAccount(values));
24 | },
25 | onDeveloperSubmit: (values) => {
26 | dispatch(updateDeveloperAccount(values));
27 | }
28 | }
29 | }
30 |
31 | export default connect(mapStateToProps, mapDispatchToProps)(Details);
32 |
--------------------------------------------------------------------------------
/src/admin/client/modules/orders/list/components/head.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import Subheader from 'material-ui/Subheader';
3 | import Checkbox from 'material-ui/Checkbox';
4 | import messages from 'lib/text'
5 |
6 | export default ({ onSelectAll }) => (
7 |
8 |
9 |
10 | { onSelectAll(isInputChecked); }} />
11 |
12 |
13 |
14 |
15 | {messages.order}
16 |
17 |
18 | {messages.orders_shippingTo}
19 |
20 |
21 | {messages.orders_total}
22 |
23 |
24 | {messages.orders_status}
25 |
26 |
27 |
28 | )
29 |
--------------------------------------------------------------------------------
/public/admin-assets/tinymce/plugins/contextmenu/plugin.min.js:
--------------------------------------------------------------------------------
1 | tinymce.PluginManager.add("contextmenu",function(a){var b,c=a.settings.contextmenu_never_use_native,d=function(a){return a.ctrlKey&&!c},e=function(){return tinymce.Env.mac&&tinymce.Env.webkit};a.on("mousedown",function(b){e()&&2===b.button&&!d(b)&&a.selection.isCollapsed()&&a.once("contextmenu",function(b){a.selection.placeCaretAt(b.clientX,b.clientY)})}),a.on("contextmenu",function(c){var e;if(!d(c)){if(c.preventDefault(),e=a.settings.contextmenu||"link image inserttable | cell row column deletetable",b)b.show();else{var f=[];tinymce.each(e.split(/[ ,]/),function(b){var c=a.menuItems[b];"|"==b&&(c={text:b}),c&&(c.shortcut="",f.push(c))});for(var g=0;g {
7 | return {
8 | statusId: state.orderStatuses.selectedId,
9 | items: state.orderStatuses.items,
10 | initialValues: state.orderStatuses.items.find((item) => (item.id === state.orderStatuses.selectedId)),
11 | isSaving: state.orderStatuses.isSaving
12 | }
13 | }
14 |
15 | const mapDispatchToProps = (dispatch) => {
16 | return {
17 | onSubmit: (values) => {
18 | if(values.id) {
19 | dispatch(updateStatus(values));
20 | } else {
21 | dispatch(createStatus(values));
22 | }
23 | },
24 | onCancel: () => {
25 | dispatch(deselectStatus());
26 | dispatch(reset('FormOrderStatus'));
27 | }
28 | }
29 | }
30 |
31 | export default connect(mapStateToProps, mapDispatchToProps)(Form);
32 |
--------------------------------------------------------------------------------
/src/admin/client/modules/customerGroups/edit/index.js:
--------------------------------------------------------------------------------
1 | import { connect } from 'react-redux'
2 | import { reset } from 'redux-form';
3 | import { updateGroup, createGroup, deselectGroup } from '../actions'
4 | import Form from './components/form'
5 |
6 | const mapStateToProps = (state) => {
7 | return {
8 | groupId: state.customerGroups.selectedId,
9 | items: state.customerGroups.items,
10 | initialValues: state.customerGroups.items.find((item) => (item.id === state.customerGroups.selectedId)),
11 | isSaving: state.customerGroups.isSaving
12 | }
13 | }
14 |
15 | const mapDispatchToProps = (dispatch) => {
16 | return {
17 | onSubmit: (values) => {
18 | if(values.id) {
19 | dispatch(updateGroup(values));
20 | } else {
21 | dispatch(createGroup(values));
22 | }
23 | },
24 | onCancel: () => {
25 | dispatch(deselectGroup());
26 | dispatch(reset('FormCustomerGroup'));
27 | }
28 | }
29 | }
30 |
31 | export default connect(mapStateToProps, mapDispatchToProps)(Form);
32 |
--------------------------------------------------------------------------------
/src/admin/client/modules/customers/actionTypes.js:
--------------------------------------------------------------------------------
1 | export const CUSTOMERS_REQUEST = 'CUSTOMERS_REQUEST'
2 | export const CUSTOMERS_RECEIVE = 'CUSTOMERS_RECEIVE'
3 | export const CUSTOMERS_FAILURE = 'CUSTOMERS_FAILURE'
4 |
5 | export const CUSTOMERS_DETAIL_REQUEST = 'CUSTOMERS_DETAIL_REQUEST'
6 | export const CUSTOMERS_DETAIL_RECEIVE = 'CUSTOMERS_DETAIL_RECEIVE'
7 | export const CUSTOMERS_DETAIL_FAILURE = 'CUSTOMERS_DETAIL_FAILURE'
8 |
9 | export const CUSTOMERS_MORE_REQUEST = 'CUSTOMERS_MORE_REQUEST'
10 | export const CUSTOMERS_MORE_RECEIVE = 'CUSTOMERS_MORE_RECEIVE'
11 |
12 | export const CUSTOMERS_FILTER_SET_SEARCH = 'CUSTOMERS_FILTER_SET_SEARCH'
13 |
14 | export const CUSTOMERS_SELECT = 'CUSTOMERS_SELECT'
15 | export const CUSTOMERS_DESELECT = 'CUSTOMERS_DESELECT'
16 | export const CUSTOMERS_SELECT_ALL = 'CUSTOMERS_SELECT_ALL'
17 | export const CUSTOMERS_DESELECT_ALL = 'CUSTOMERS_DESELECT_ALL'
18 |
19 | export const CUSTOMER_DELETE_SUCCESS = 'CUSTOMER_DELETE_SUCCESS'
20 | export const CUSTOMER_SET_GROUP_SUCCESS = 'CUSTOMER_SET_GROUP_SUCCESS'
21 |
--------------------------------------------------------------------------------
/src/admin/client/index.js:
--------------------------------------------------------------------------------
1 | import '../../../public/admin-assets/css/flexboxgrid.min.css'
2 | import '../../../public/admin-assets/css/style.css'
3 |
4 | import React from 'react'
5 | import ReactDOM from 'react-dom'
6 | import {createStore, applyMiddleware} from 'redux'
7 | import {Provider} from 'react-redux'
8 | import thunkMiddleware from 'redux-thunk'
9 |
10 | import {fetchSettings} from 'modules/settings/actions'
11 | import settings from 'lib/settings'
12 | import * as auth from 'lib/auth'
13 | import {listenEvents} from 'lib/events'
14 | import reducers from './rootReducer'
15 | import App from './app'
16 |
17 | const DEVELOPER_MODE = settings.developerMode === true;
18 | if(DEVELOPER_MODE === false){
19 | auth.validateCurrentToken();
20 | }
21 |
22 | const store = createStore(reducers, applyMiddleware(thunkMiddleware));
23 | store.dispatch(fetchSettings());
24 |
25 | if (!!window.EventSource) {
26 | listenEvents(store);
27 | }
28 |
29 | ReactDOM.render(
30 |
31 |
32 | ,
33 | document.getElementById('app'));
34 |
--------------------------------------------------------------------------------
/src/admin/client/modules/apps/account/components/details.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import messages from 'lib/text'
3 | import style from './style.css'
4 | import Account from './account'
5 | import Developer from './developer'
6 |
7 | export default class WebStoreAccountDetails extends React.Component {
8 | constructor(props) {
9 | super(props)
10 | }
11 |
12 | componentDidMount() {
13 | this.props.fetchData();
14 | }
15 |
16 | render() {
17 | const { account, onAccountSubmit, onDeveloperSubmit } = this.props;
18 | const developerData = account ? account.developer : null;
19 |
20 | if(account){
21 | return (
22 |
23 |
24 | {account && account.is_developer === true &&
25 |
26 | }
27 |
28 | )
29 | } else {
30 | return null;
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/admin/client/modules/products/listHead/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { connect } from 'react-redux'
3 | import { withRouter } from 'react-router'
4 | import { fetchProducts, deleteProducts, setCategory, setFilter, createProduct } from '../actions'
5 | import Buttons from './components/buttons'
6 |
7 | const mapStateToProps = (state, ownProps) => {
8 | return {
9 | search: state.products.filter.search,
10 | selectedCount: state.products.selected.length
11 | }
12 | }
13 |
14 | const mapDispatchToProps = (dispatch, ownProps) => {
15 | return {
16 | setSearch: (event, value) => {
17 | dispatch(setFilter({ search: value }));
18 | dispatch(fetchProducts());
19 | },
20 | onDelete: () => {
21 | dispatch(deleteProducts());
22 | },
23 | onMoveTo: (category_id) => {
24 | dispatch(setCategory(category_id));
25 | },
26 | onCreate: () => {
27 | dispatch(createProduct(ownProps.history))
28 | }
29 | }
30 | }
31 |
32 | export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Buttons));
33 |
--------------------------------------------------------------------------------
/src/admin/client/modules/shared/imageUploadMultiple/style.css:
--------------------------------------------------------------------------------
1 | .preview {
2 | position: relative;
3 | height: 220px;
4 | width: 200px;
5 | cursor: move;
6 | }
7 |
8 | .preview img {
9 | max-width: 100%;
10 | max-height: 100%;
11 | }
12 |
13 | .footer {
14 | background-color: rgba(0,0,0,0.05);
15 | }
16 |
17 | .dropzone {}
18 | .dropzoneEmpty {
19 | color: #a1a1a1;
20 | font-size: 16px;
21 | border: 2px dashed rgba(0,0,0,0.1);
22 | padding: 80px;
23 | margin: 20px 20px 0 20px;
24 | background-color: rgb(255,255,255);
25 | }
26 | .dropzoneActive {
27 | background-color: rgba(18,179,117, 0.4);
28 | }
29 | .dropzoneReject {
30 | background-color: rgba(244,67,54,0.8);
31 | }
32 | .dropzoneReject .list,
33 | .dropzoneActive .list {
34 | opacity: 0.3
35 | }
36 | .gallery {
37 | overflow: auto;
38 | }
39 |
40 | .list {
41 | margin: 10px 10px 0 10px;
42 | padding: 0;
43 | display: flex;
44 | flex-wrap: nowrap;
45 | list-style: none;
46 | }
47 |
48 | .item {
49 | margin: 10px 0px 10px 10px;
50 | padding: 0;
51 | list-style: none;
52 | }
53 |
--------------------------------------------------------------------------------
/src/api/server/routes/paymentGateways.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const security = require('../lib/security');
4 | var PaymentGatewaysService = require('../services/settings/paymentGateways');
5 |
6 | class PaymentGatewaysRoute {
7 | constructor(router) {
8 | this.router = router;
9 | this.registerRoutes();
10 | }
11 |
12 | registerRoutes() {
13 | this.router.get('/v1/payment_gateways/:name', security.checkUserScope.bind(this, security.scope.READ_PAYMENT_METHODS), this.getGateway.bind(this));
14 | this.router.put('/v1/payment_gateways/:name', security.checkUserScope.bind(this, security.scope.WRITE_PAYMENT_METHODS), this.updateGateway.bind(this));
15 | }
16 |
17 | getGateway(req, res, next) {
18 | PaymentGatewaysService.getGateway(req.params.name).then(data => {
19 | res.send(data)
20 | }).catch(next);
21 | }
22 |
23 | updateGateway(req, res, next) {
24 | PaymentGatewaysService.updateGateway(req.params.name, req.body).then(data => {
25 | res.send(data);
26 | }).catch(next);
27 | }
28 | }
29 |
30 | module.exports = PaymentGatewaysRoute;
31 |
--------------------------------------------------------------------------------
/src/api/server/controllers/paymentGateways.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const security = require('../lib/security');
4 | var PaymentGatewaysService = require('../services/settings/paymentGateways');
5 |
6 | class PaymentGatewaysController {
7 | constructor(router) {
8 | this.router = router;
9 | this.registerRoutes();
10 | }
11 |
12 | registerRoutes() {
13 | this.router.get('/v1/payment_gateways/:name', security.checkUserScope.bind(this, security.scope.READ_PAYMENT_METHODS), this.getGateway.bind(this));
14 | this.router.put('/v1/payment_gateways/:name', security.checkUserScope.bind(this, security.scope.WRITE_PAYMENT_METHODS), this.updateGateway.bind(this));
15 | }
16 |
17 | getGateway(req, res, next) {
18 | PaymentGatewaysService.getGateway(req.params.name).then(data => {
19 | res.send(data)
20 | }).catch(next);
21 | }
22 |
23 | updateGateway(req, res, next) {
24 | PaymentGatewaysService.updateGateway(req.params.name, req.body).then(data => {
25 | res.send(data);
26 | }).catch(next);
27 | }
28 | }
29 |
30 | module.exports = PaymentGatewaysController;
31 |
--------------------------------------------------------------------------------
/src/admin/client/modules/pages/edit/index.js:
--------------------------------------------------------------------------------
1 | import { connect } from 'react-redux'
2 | import { fetchPage, updatePage, createPage, receivePage } from '../actions'
3 | import Form from './components/form'
4 |
5 | const mapStateToProps = (state, ownProps) => {
6 | const {pageId} = ownProps.match.params;
7 | return {
8 | pageId: pageId,
9 | initialValues: state.pages.pageEdit
10 | }
11 | }
12 |
13 | const mapDispatchToProps = (dispatch, ownProps) => {
14 | return {
15 | onLoad: () => {
16 | const {pageId} = ownProps.match.params;
17 | if(pageId) {
18 | dispatch(fetchPage(pageId))
19 | } else {
20 | dispatch(receivePage({ enabled: true }));
21 | }
22 | },
23 | onSubmit: (page) => {
24 | if(page.id) {
25 | dispatch(updatePage(page));
26 | } else {
27 | dispatch(createPage(page));
28 | ownProps.history.push('/admin/pages');
29 | }
30 | },
31 | eraseData: () => {
32 | dispatch(receivePage(null));
33 | }
34 | }
35 | }
36 |
37 | export default connect(mapStateToProps, mapDispatchToProps)(Form);
38 |
--------------------------------------------------------------------------------
/src/api/server/routes/apps.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const security = require('../lib/security');
4 | const AppSettingsService = require('../services/apps/settings');
5 |
6 | class AppsRoute {
7 | constructor(router) {
8 | this.router = router;
9 | this.registerRoutes();
10 | }
11 |
12 | registerRoutes() {
13 | this.router.get('/v1/apps/:key/settings', security.checkUserScope.bind(this, security.scope.READ_SETTINGS), this.getSettings.bind(this));
14 | this.router.put('/v1/apps/:key/settings', security.checkUserScope.bind(this, security.scope.WRITE_SETTINGS), this.updateSettings.bind(this));
15 | }
16 |
17 | getSettings(req, res, next) {
18 | AppSettingsService.getSettings(req.params.key).then(data => {
19 | res.send(data)
20 | }).catch(next);
21 | }
22 |
23 | updateSettings(req, res, next) {
24 | AppSettingsService.updateSettings(req.params.key, req.body).then(data => {
25 | if (data) {
26 | res.send(data)
27 | } else {
28 | res.status(404).end()
29 | }
30 | }).catch(next);
31 | }
32 | }
33 |
34 | module.exports = AppsRoute;
35 |
--------------------------------------------------------------------------------
/theme/src/components/productList/loadMore.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { themeSettings, text } from '../../lib/settings'
3 |
4 | const LoadMore = ({ loadMoreProducts, hasMore, loading, className }) => {
5 | if(hasMore){
6 | className = className || 'button is-fullwidth is-dark';
7 |
8 | let buttonStyle = {};
9 | if(themeSettings.button_loadmore_bg && themeSettings.button_loadmore_bg.length > 0){
10 | buttonStyle.backgroundColor = themeSettings.button_loadmore_bg;
11 | }
12 | if(themeSettings.button_loadmore_color && themeSettings.button_loadmore_color.length > 0){
13 | buttonStyle.color = themeSettings.button_loadmore_color;
14 | }
15 |
16 | const loadMoreText = themeSettings.button_loadmore_text && themeSettings.button_loadmore_text.length > 0 ? themeSettings.button_loadmore_text : text.loadMore;
17 |
18 | return (
19 |
20 | )
21 | } else {
22 | return null;
23 | }
24 | }
25 |
26 | export default LoadMore
27 |
--------------------------------------------------------------------------------
/src/admin/client/modules/products/list/components/head.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import Subheader from 'material-ui/Subheader';
3 | import messages from 'lib/text'
4 |
5 | const Head = ({ onSelectAll }) => (
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | {messages.products_name}
15 |
16 |
17 |
18 |
19 | {messages.products_sku}
20 |
21 |
22 | {messages.products_stock}
23 |
24 |
25 | {messages.products_price}
26 |
27 |
28 |
29 | )
30 |
31 | export default Head
32 |
--------------------------------------------------------------------------------
/src/admin/client/lib/events.js:
--------------------------------------------------------------------------------
1 | import {fetchSettings, installReceive} from 'modules/settings/actions'
2 | import {fetchOrders} from 'modules/orders/actions'
3 |
4 | const THEME_INSTALLED = 'theme-installed';
5 | const ORDER_RECEIVED = 'order-received';
6 | const ORDER_CHANGED = 'order-changed';
7 |
8 | const messageReceived = (message, store) => {
9 | switch(message.type){
10 | case THEME_INSTALLED:
11 | store.dispatch(installReceive());
12 | break;
13 | case ORDER_RECEIVED:
14 | store.dispatch(fetchOrders());
15 | break;
16 | default:
17 | break;
18 | }
19 | }
20 |
21 | export const listenEvents = (store) => {
22 | const eventsUrl = '/api/dashboard/events?token=' + localStorage.getItem('dashboard_token');
23 | const serverEvents = new EventSource(eventsUrl);
24 |
25 | serverEvents.onmessage = (e) => {
26 | if(e.origin === location.origin && e.isTrusted === true){
27 | const message = JSON.parse(e.data);
28 | messageReceived(message, store);
29 | } else {
30 | console.log('Received message from server: ' + e.origin);
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/locales/store/en.json:
--------------------------------------------------------------------------------
1 | {
2 | "loading": "Loading...",
3 | "optional": "optional",
4 | "shippingTo": "Shipping To",
5 | "shippingMethods": "Shipping options",
6 | "shippingMethod": "Shipping method",
7 | "paymentMethods": "Payment options",
8 | "paymentMethod": "Payment method",
9 | "shippingAddress": "Shipping Address",
10 | "billingAddress": "Billing Address",
11 | "orderSubmit": "Place Order",
12 | "emptyCheckout": "Your cart is empty",
13 | "email": "Email",
14 | "mobile": "Mobile",
15 | "country": "Country",
16 | "state": "State/Province",
17 | "city": "City",
18 | "fullName": "Full name",
19 | "address1": "Address line 1",
20 | "address2": "Address line 2",
21 | "postal_code": "Postal code",
22 | "phone": "Phone",
23 | "company": "Company",
24 | "comments": "Comments",
25 | "required": "This field is required.",
26 | "emailInvalid": "Please enter a valid email address.",
27 | "sameAsShipping": "Same as shipping address",
28 | "edit": "Edit",
29 | "next": "Next",
30 | "customerDetails": "Customer Details",
31 | "shipping": "Shipping",
32 | "payment": "Payment"
33 | }
34 |
--------------------------------------------------------------------------------
/src/api/server/controllers/apps.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const security = require('../lib/security');
4 | const AppSettingsService = require('../services/apps/settings');
5 |
6 | class AppsController {
7 | constructor(router) {
8 | this.router = router;
9 | this.registerRoutes();
10 | }
11 |
12 | registerRoutes() {
13 | this.router.get('/v1/apps/:key/settings', security.checkUserScope.bind(this, security.scope.READ_SETTINGS), this.getSettings.bind(this));
14 | this.router.put('/v1/apps/:key/settings', security.checkUserScope.bind(this, security.scope.WRITE_SETTINGS), this.updateSettings.bind(this));
15 | }
16 |
17 | getSettings(req, res, next) {
18 | AppSettingsService.getSettings(req.params.key).then(data => {
19 | res.send(data)
20 | }).catch(next);
21 | }
22 |
23 | updateSettings(req, res, next) {
24 | AppSettingsService.updateSettings(req.params.key, req.body).then(data => {
25 | if (data) {
26 | res.send(data)
27 | } else {
28 | res.status(404).end()
29 | }
30 | }).catch(next);
31 | }
32 | }
33 |
34 | module.exports = AppsController;
35 |
--------------------------------------------------------------------------------
/src/admin/client/modules/apps/serviceDetails/components/logs.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import {Link} from 'react-router-dom'
3 | import moment from 'moment'
4 |
5 | import messages from 'lib/text'
6 | import api from 'lib/api'
7 | import style from './style.css'
8 | import Paper from 'material-ui/Paper';
9 |
10 | const ServiceLogs = ({ logs }) => {
11 | const list = logs.map((action, index) => {
12 | const date = moment(action.date);
13 | const dateFormated = date.fromNow();
14 | return (
15 |
16 |
{action.message}
17 |
{dateFormated}
18 |
19 | )
20 | });
21 |
22 | return (
23 |
24 |
{messages.serviceLogs}
25 |
26 |
27 | {list}
28 |
29 |
30 |
31 | )
32 | }
33 |
34 | export default ServiceLogs;
35 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 |
2 | MIT License
3 |
4 | Copyright (c) 2016 cezerin
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
23 |
--------------------------------------------------------------------------------
/public/admin-assets/tinymce/plugins/noneditable/plugin.min.js:
--------------------------------------------------------------------------------
1 | tinymce.PluginManager.add("noneditable",function(a){function b(a){return function(b){return-1!==(" "+b.attr("class")+" ").indexOf(a)}}function c(b){function c(b){var c=arguments,d=c[c.length-2];return d>0&&'"'==g.charAt(d-1)?b:''+a.dom.encode("string"==typeof c[1]?c[1]:c[0])+""}var d=f.length,g=b.content,h=tinymce.trim(e);if("raw"!=b.format){for(;d--;)g=g.replace(f[d],c);b.content=g}}var d,e,f,g="contenteditable";d=" "+tinymce.trim(a.getParam("noneditable_editable_class","mceEditable"))+" ",e=" "+tinymce.trim(a.getParam("noneditable_noneditable_class","mceNonEditable"))+" ";var h=b(d),i=b(e);f=a.getParam("noneditable_regexp"),f&&!f.length&&(f=[f]),a.on("PreInit",function(){f&&a.on("BeforeSetContent",c),a.parser.addAttributeFilter("class",function(a){for(var b,c=a.length;c--;)b=a[c],h(b)?b.attr(g,"true"):i(b)&&b.attr(g,"false")}),a.serializer.addAttributeFilter(g,function(a){for(var b,c=a.length;c--;)b=a[c],(h(b)||i(b))&&(f&&b.attr("data-mce-content")?(b.name="#text",b.type=3,b.raw=!0,b.value=b.attr("data-mce-content")):b.attr(g,null))})})});
--------------------------------------------------------------------------------
/src/admin/client/modules/shared/form/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import Toggle from 'material-ui/Toggle';
3 | import TextField from 'material-ui/TextField';
4 |
5 | export const CustomToggle = ({ input, label, className = '', disabled = false, style }) => {
6 | return (
7 | {
11 | input.onChange(isInputChecked)
12 | }}
13 | className={className}
14 | disabled={disabled}
15 | style={style}
16 | />
17 | )
18 | }
19 |
20 | export const NumberField = ({ input, label, className = '', disabled = false, style }) => (
21 | {
28 | let number = parseFloat(value);
29 | number = number ? number : 0;
30 | input.onChange(number)
31 | }}
32 | />
33 | )
34 |
35 | export const ColorField = ({ input, meta: { touched, error } }) => (
36 |
37 | )
38 |
--------------------------------------------------------------------------------
/locales/store/uk.json:
--------------------------------------------------------------------------------
1 | {
2 | "loading": "Завантаження ...",
3 | "optional": "не обов'язково",
4 | "shippingTo": "Доставка",
5 | "shippingMethods": "Варіанти доставки",
6 | "shippingMethod": "Спосіб доставки",
7 | "paymentMethods": "Варіанти оплати",
8 | "paymentMethod": "Спосіб оплати",
9 | "shippingAddress": "Адреса доставки",
10 | "billingAddress": "Адреса виставлення рахунку",
11 | "orderSubmit": "Замовлення підтверджую",
12 | "emptyCheckout": "Кошик порожній",
13 | "email": "Email",
14 | "mobile": "Мобільний",
15 | "country": "Країна",
16 | "state": "Область",
17 | "city": "Місто",
18 | "fullName": "ПІБ",
19 | "address1": "Адреса",
20 | "address2": "Адреса (додатково)",
21 | "postal_code": "Поштовий індекс",
22 | "phone": "Телефон",
23 | "company": "Назва компанії",
24 | "comments": "Примітка",
25 | "required": "Заповніть це поле.",
26 | "emailInvalid": "Будь ласка, введіть адресу електронної пошти.",
27 | "sameAsShipping": "Такий же, що і адреса доставки",
28 | "edit": "Змінити",
29 | "next": "Далі",
30 | "customerDetails": "Інформація про клієнта",
31 | "shipping": "Доставка",
32 | "payment": "Оплата"
33 | }
34 |
--------------------------------------------------------------------------------
/theme/src/components/cartIndicator.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { NavLink } from 'react-router-dom'
3 | import { themeSettings, text } from '../lib/settings'
4 |
5 | const CartCount = ({ cart }) => {
6 | if (cart && cart.items && cart.items.length > 0) {
7 | let itemsCount = cart.items.reduce((a, b) => a + b.quantity, 0);
8 | return {itemsCount};
9 | } else {
10 | return null;
11 | }
12 | }
13 |
14 | const CartIcon = ({ cartIsActive }) => {
15 | if(cartIsActive){
16 | return
17 | } else {
18 | return
19 | }
20 | }
21 |
22 | export default class CartIndicator extends React.PureComponent {
23 | render() {
24 | const { cart, onClick, cartIsActive } = this.props;
25 | return
26 |
27 |
28 |
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/locales/store/ru.json:
--------------------------------------------------------------------------------
1 | {
2 | "loading": "Загружается ...",
3 | "optional": "необязательно",
4 | "shippingTo": "Доставка",
5 | "shippingMethods": "Варианты доставки",
6 | "shippingMethod": "Способ доставки",
7 | "paymentMethods": "Варианты оплаты",
8 | "paymentMethod": "Способ оплаты",
9 | "shippingAddress": "Адрес доставки",
10 | "billingAddress": "Платежный адрес",
11 | "orderSubmit": "Разместить заказ",
12 | "emptyCheckout": "Ваша корзина пуста",
13 | "email": "Email",
14 | "mobile": "Мобильный",
15 | "country": "Страна",
16 | "state": "Область",
17 | "city": "Город",
18 | "fullName": "ФИО",
19 | "address1": "Адрес",
20 | "address2": "Адрес (дополнительно)",
21 | "postal_code": "Почтовый индекс",
22 | "phone": "Телефон",
23 | "company": "Название компании",
24 | "comments": "Примечание",
25 | "required": "Заполните это поле.",
26 | "emailInvalid": "Пожалуйста, введите действительный адрес электронной почты.",
27 | "sameAsShipping": "Такой же, что и адрес доставки",
28 | "edit": "Изменить",
29 | "next": "Далее",
30 | "customerDetails": "Информация о клиенте",
31 | "shipping": "Доставка",
32 | "payment": "Оплата"
33 | }
34 |
--------------------------------------------------------------------------------
/public/admin-assets/tinymce/plugins/save/plugin.min.js:
--------------------------------------------------------------------------------
1 | tinymce.PluginManager.add("save",function(a){function b(){var b;return b=tinymce.DOM.getParent(a.id,"form"),!a.getParam("save_enablewhendirty",!0)||a.isDirty()?(tinymce.triggerSave(),a.getParam("save_onsavecallback")?(a.execCallback("save_onsavecallback",a),void a.nodeChanged()):void(b?(a.setDirty(!1),b.onsubmit&&!b.onsubmit()||("function"==typeof b.submit?b.submit():c(a.translate("Error: Form submit field collision."))),a.nodeChanged()):c(a.translate("Error: No form element found.")))):void 0}function c(b){a.notificationManager.open({text:b,type:"error"})}function d(){var b=tinymce.trim(a.startContent);return a.getParam("save_oncancelcallback")?void a.execCallback("save_oncancelcallback",a):(a.setContent(b),a.undoManager.clear(),void a.nodeChanged())}function e(){var b=this;a.on("nodeChange dirty",function(){b.disabled(a.getParam("save_enablewhendirty",!0)&&!a.isDirty())})}a.addCommand("mceSave",b),a.addCommand("mceCancel",d),a.addButton("save",{icon:"save",text:"Save",cmd:"mceSave",disabled:!0,onPostRender:e}),a.addButton("cancel",{text:"Cancel",icon:!1,cmd:"mceCancel",disabled:!0,onPostRender:e}),a.addShortcut("Meta+S","","mceSave")});
--------------------------------------------------------------------------------
/src/api/server/routes/files.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const security = require('../lib/security');
4 | const FilesService = require('../services/files');
5 |
6 | class FilesRoute {
7 | constructor(router) {
8 | this.router = router;
9 | this.registerRoutes();
10 | }
11 |
12 | registerRoutes() {
13 | this.router.get('/v1/files', security.checkUserScope.bind(this, security.scope.READ_FILES), this.getFiles.bind(this));
14 | this.router.post('/v1/files', security.checkUserScope.bind(this, security.scope.WRITE_FILES), this.uploadFile.bind(this));
15 | this.router.delete('/v1/files/:file', security.checkUserScope.bind(this, security.scope.WRITE_FILES), this.deleteFile.bind(this));
16 | }
17 |
18 | getFiles(req, res, next) {
19 | FilesService.getFiles()
20 | .then((data) => {
21 | res.send(data)
22 | })
23 | .catch(next);
24 | }
25 |
26 | uploadFile(req, res, next) {
27 | FilesService.uploadFile(req, res, next);
28 | }
29 |
30 | deleteFile(req, res, next) {
31 | FilesService.deleteFile(req.params.file).then(() => {
32 | res.end()
33 | }).catch(next)
34 | }
35 | }
36 |
37 | module.exports = FilesRoute;
38 |
--------------------------------------------------------------------------------
/public/admin-assets/tinymce/plugins/visualblocks/plugin.min.js:
--------------------------------------------------------------------------------
1 | tinymce.PluginManager.add("visualblocks",function(a,b){function c(){var b=this;b.active(f),a.on("VisualBlocks",function(){b.active(a.dom.hasClass(a.getBody(),"mce-visualblocks"))})}var d,e,f;window.NodeList&&(a.addCommand("mceVisualBlocks",function(){var c,g=a.dom;d||(d=g.uniqueId(),c=g.create("link",{id:d,rel:"stylesheet",href:b+"/css/visualblocks.css"}),a.getDoc().getElementsByTagName("head")[0].appendChild(c)),a.on("PreviewFormats AfterPreviewFormats",function(b){f&&g.toggleClass(a.getBody(),"mce-visualblocks","afterpreviewformats"==b.type)}),g.toggleClass(a.getBody(),"mce-visualblocks"),f=a.dom.hasClass(a.getBody(),"mce-visualblocks"),e&&e.active(g.hasClass(a.getBody(),"mce-visualblocks")),a.fire("VisualBlocks")}),a.addButton("visualblocks",{title:"Show blocks",cmd:"mceVisualBlocks",onPostRender:c}),a.addMenuItem("visualblocks",{text:"Show blocks",cmd:"mceVisualBlocks",onPostRender:c,selectable:!0,context:"view",prependToContext:!0}),a.on("init",function(){a.settings.visualblocks_default_state&&a.execCommand("mceVisualBlocks",!1,null,{skip_focus:!0})}),a.on("remove",function(){a.dom.removeClass(a.getBody(),"mce-visualblocks")}))});
--------------------------------------------------------------------------------
/theme/src/components/head/cartIndicator.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { NavLink } from 'react-router-dom'
3 | import { themeSettings, text } from '../../lib/settings'
4 |
5 | const CartCount = ({ cart }) => {
6 | if (cart && cart.items && cart.items.length > 0) {
7 | let itemsCount = cart.items.reduce((a, b) => a + b.quantity, 0);
8 | return {itemsCount};
9 | } else {
10 | return null;
11 | }
12 | }
13 |
14 | const CartIcon = ({ cartIsActive }) => {
15 | if(cartIsActive){
16 | return
17 | } else {
18 | return
19 | }
20 | }
21 |
22 | export default class CartIndicator extends React.PureComponent {
23 | render() {
24 | const { cart, onClick, cartIsActive } = this.props;
25 | return
26 |
27 |
28 |
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/theme/src/components/header/cartIndicator.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { NavLink } from 'react-router-dom'
3 | import { themeSettings, text } from '../../lib/settings'
4 |
5 | const CartCount = ({ cart }) => {
6 | if (cart && cart.items && cart.items.length > 0) {
7 | let itemsCount = cart.items.reduce((a, b) => a + b.quantity, 0);
8 | return {itemsCount};
9 | } else {
10 | return null;
11 | }
12 | }
13 |
14 | const CartIcon = ({ cartIsActive }) => {
15 | if(cartIsActive){
16 | return
17 | } else {
18 | return
19 | }
20 | }
21 |
22 | export default class CartIndicator extends React.PureComponent {
23 | render() {
24 | const { cart, onClick, cartIsActive } = this.props;
25 | return
26 |
27 |
28 |
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/api/server/controllers/files.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const security = require('../lib/security');
4 | const FilesService = require('../services/files');
5 |
6 | class FilesController {
7 | constructor(router) {
8 | this.router = router;
9 | this.registerRoutes();
10 | }
11 |
12 | registerRoutes() {
13 | this.router.get('/v1/files', security.checkUserScope.bind(this, security.scope.READ_FILES), this.getFiles.bind(this));
14 | this.router.post('/v1/files', security.checkUserScope.bind(this, security.scope.WRITE_FILES), this.uploadFile.bind(this));
15 | this.router.delete('/v1/files/:file', security.checkUserScope.bind(this, security.scope.WRITE_FILES), this.deleteFile.bind(this));
16 | }
17 |
18 | getFiles(req, res, next) {
19 | FilesService.getFiles()
20 | .then((data) => {
21 | res.send(data)
22 | })
23 | .catch(next);
24 | }
25 |
26 | uploadFile(req, res, next) {
27 | FilesService.uploadFile(req, res, next);
28 | }
29 |
30 | deleteFile(req, res, next) {
31 | FilesService.deleteFile(req.params.file).then(() => {
32 | res.end()
33 | }).catch(next)
34 | }
35 | }
36 |
37 | module.exports = FilesController;
38 |
--------------------------------------------------------------------------------
/src/admin/client/modules/settings/themeSettings/components/imageEditor.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import api from 'lib/api'
3 | import ImageUpload from 'modules/shared/imageUpload'
4 |
5 | export default class ThemeImageUpload extends React.Component {
6 | constructor(props) {
7 | super(props);
8 | }
9 |
10 | onDelete = () => {
11 | const fileName = this.props.input.value;
12 | api.theme.assets.deleteFile(fileName).then(() => {
13 | this.props.input.onChange('');
14 | })
15 | }
16 |
17 | onUpload = formData => {
18 | api.theme.assets.uploadFile(formData).then(({ status, json }) => {
19 | const fileName = json.file;
20 | this.props.input.onChange(fileName);
21 | });
22 | }
23 |
24 | render() {
25 | let { input, label } = this.props;
26 | const imageUrl = input.value && input.value.length > 0 ? '/assets/images/' + input.value : null;
27 |
28 | return (
29 |
38 | )
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/admin/client/modules/customers/filter/index.js:
--------------------------------------------------------------------------------
1 | import { connect } from 'react-redux'
2 | import { fetchProducts, setFilterActive, setFilterDiscontinued, setFilterOnSale, setFilterStock } from '../actions'
3 | import Filter from './components/fields'
4 |
5 | const mapStateToProps = (state) => {
6 | return {
7 | active: state.products.filter_active,
8 | discontinued: state.products.filter_discontinued,
9 | on_sale: state.products.filter_on_sale,
10 | stock_status: state.products.filter_stock_status
11 | }
12 | }
13 |
14 | const mapDispatchToProps = (dispatch) => {
15 | return {
16 | setActive: (value) => {
17 | dispatch(setFilterActive(value));
18 | dispatch(fetchProducts());
19 | },
20 | setDiscontinued: (value) => {
21 | dispatch(setFilterDiscontinued(value));
22 | dispatch(fetchProducts());
23 | },
24 | setOnSale: (value) => {
25 | dispatch(setFilterOnSale(value));
26 | dispatch(fetchProducts());
27 | },
28 | setStock: (value) => {
29 | dispatch(setFilterStock(value));
30 | dispatch(fetchProducts());
31 | }
32 | }
33 | }
34 |
35 | export default connect(mapStateToProps, mapDispatchToProps)(Filter);
36 |
--------------------------------------------------------------------------------
/src/admin/client/modules/productCategories/head/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { connect } from 'react-redux'
3 | import { withRouter } from 'react-router'
4 | import { reset } from 'redux-form';
5 | import { deleteCategory, moveUpCategory, moveDownCategory, replaceCategory, createCategory } from '../actions'
6 | import Buttons from './components/buttons'
7 |
8 | const mapStateToProps = (state) => {
9 | return {
10 | selected: state.productCategories.items.find((item) => (item.id === state.productCategories.selectedId))
11 | }
12 | }
13 |
14 | const mapDispatchToProps = (dispatch) => {
15 | return {
16 | onMoveUp: () => {
17 | dispatch(moveUpCategory());
18 | },
19 | onMoveDown: () => {
20 | dispatch(moveDownCategory());
21 | },
22 | onDelete: (id) => {
23 | dispatch(deleteCategory(id));
24 | dispatch(reset('FormProductCategory'));
25 | },
26 | onMoveTo: (id) => {
27 | dispatch(replaceCategory(id));
28 | dispatch(reset('FormProductCategory'));
29 | },
30 | onCreate: () => {
31 | dispatch(createCategory());
32 | }
33 | }
34 | }
35 |
36 | export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Buttons));
37 |
--------------------------------------------------------------------------------
/src/admin/client/modules/productCategories/edit/index.js:
--------------------------------------------------------------------------------
1 | import { connect } from 'react-redux'
2 | import { updateCategory, deselectCategory, fetchCategories, deleteImage, uploadImage } from '../actions'
3 | import ProductCategoryEditForm from './components/form'
4 |
5 | const mapStateToProps = (state) => {
6 | return {
7 | uploadingImage: state.productCategories.uploadingImage,
8 | categoryId: state.productCategories.selectedId,
9 | items: state.productCategories.items,
10 | initialValues: state.productCategories.items.find((item) => (item.id === state.productCategories.selectedId)),
11 | isSaving: state.productCategories.isSaving
12 | }
13 | }
14 |
15 | const mapDispatchToProps = (dispatch) => {
16 | return {
17 | onImageDelete: () => {
18 | dispatch(deleteImage());
19 | },
20 | onImageUpload: (form) => {
21 | dispatch(uploadImage(form));
22 | },
23 | onSubmit: (values) => {
24 | delete values.image;
25 | if(!values.slug || values.slug === '') {
26 | values.slug = values.name;
27 | }
28 | dispatch(updateCategory(values));
29 | }
30 | }
31 | }
32 |
33 | export default connect(mapStateToProps, mapDispatchToProps)(ProductCategoryEditForm);
34 |
--------------------------------------------------------------------------------
/src/admin/client/modules/products/edit/variants/components/style.css:
--------------------------------------------------------------------------------
1 | .innerBox {
2 | padding: 30px;
3 | }
4 |
5 | .grid {}
6 |
7 | .gridHeadRow{
8 | display: flex;
9 | flex-flow: row wrap;
10 | width: 100%;
11 | background-color: rgba(0, 0, 0, 0.05);
12 | color: #a1a1a1;
13 | align-items: center;
14 | justify-content: space-around;
15 | align-items: center;
16 | text-align: center;
17 | min-height: 60px;
18 | cursor: default;
19 | }
20 |
21 | .gridHeadRow a {
22 | color: #000;
23 | text-decoration: none;
24 | cursor: pointer;
25 | }
26 |
27 | .gridRow {
28 | display: flex;
29 | flex-flow: row wrap;
30 | width: 100%;
31 | align-items: center;
32 | justify-content: space-around;
33 | align-items: center;
34 | text-align: center;
35 | border-bottom: 1px solid rgb(224, 224, 224);
36 | }
37 |
38 | .gridCol {
39 | flex: 1 1;
40 | overflow: hidden;
41 | }
42 |
43 | .gridCol:hover,
44 | .textInput:focus {
45 | background-color: rgba(0, 0, 0, 0.05);
46 | }
47 |
48 | .textInput {
49 | width: 100%;
50 | margin: 0;
51 | padding: 0;
52 | border: none;
53 | outline: none;
54 | background-color: transparent;
55 | font-size: 15px;
56 | text-align: center;
57 | height: 60px;
58 | }
59 |
--------------------------------------------------------------------------------
/theme/assets/css/cart.scss:
--------------------------------------------------------------------------------
1 | .mini-cart {
2 | position: absolute;
3 | width: 460px;
4 | top: calc(100%);
5 | right: calc(-100%);
6 | background: #fff;
7 | z-index: 99;
8 | box-shadow: 2px 2px 1px 0 rgba(0,0,0,0.2);
9 | border: 1px solid #f3f3f3;
10 | border-width: 1px 0 0 1px;
11 | transition: right 200ms ease-in-out;
12 | padding: 20px;
13 | text-align: left;
14 | font-size: 90%;
15 | }
16 |
17 | .mini-cart-open .mini-cart {
18 | right: 0;
19 | }
20 |
21 | .mini-cart-item-price {
22 | padding-bottom: 6px
23 | }
24 |
25 | .cart-option-name {
26 | color: #999;
27 | }
28 |
29 | .cart-quantity {
30 | color: #999;
31 | }
32 |
33 | .mini-cart .product-old-price {
34 | padding-right: 10px;
35 | color: #636363;
36 | }
37 |
38 | .mini-cart .product-new-price {
39 | color: #e72b1e;
40 | }
41 |
42 | .mini-cart .product-option {
43 | margin-bottom: 15px;
44 | }
45 |
46 | .mini-cart .product-option-name {
47 | color: #777;
48 | }
49 |
50 | /*
51 | Mobile
52 | */
53 | @media screen and (max-width: 768px) {
54 | .mini-cart {
55 | top: 3.25rem;
56 | position: fixed;
57 | width: 90%;
58 | z-index: 1002;
59 | bottom: 0;
60 | overflow-y: scroll;
61 | font-size: 82%;
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/docs/structure.md:
--------------------------------------------------------------------------------
1 | ## Application Structure
2 |
3 | ```
4 | .
5 | ├── config # Project and build configurations
6 | ├── dist # Distribution folder
7 | ├── locales # Text files
8 | ├── logs # Log files
9 | ├── public # Public static assets and uploads
10 | │ ├── admin # Dashboard index.html
11 | │ ├── admin-assets # Dashboard assets
12 | │ └── content # Store root folder
13 | |
14 | ├── scripts # Shell scripts for theme install/export
15 | ├── src # Application source code
16 | │ ├── admin # Dashboard application
17 | │ │ └── client # Client side code
18 | │ ├── api # REST API
19 | │ │ └── server # Server side code
20 | │ ├── store # Store application
21 | │ | ├── client # Client side code
22 | │ | ├── server # Server side code
23 | │ | └── shared # Universal code
24 | │ └── index.js # Server application start point
25 | ├── theme # Theme as a local package
26 | └── process.json # pm2 process file
27 | ```
28 |
--------------------------------------------------------------------------------
/public/admin-assets/tinymce/plugins/colorpicker/plugin.min.js:
--------------------------------------------------------------------------------
1 | tinymce.PluginManager.add("colorpicker",function(a){function b(b,c){function d(a){var b=new tinymce.util.Color(a),c=b.toRgb();f.fromJSON({r:c.r,g:c.g,b:c.b,hex:b.toHex().substr(1)}),e(b.toHex())}function e(a){f.find("#preview")[0].getEl().style.background=a}var f=a.windowManager.open({title:"Color",items:{type:"container",layout:"flex",direction:"row",align:"stretch",padding:5,spacing:10,items:[{type:"colorpicker",value:c,onchange:function(){var a=this.rgb();f&&(f.find("#r").value(a.r),f.find("#g").value(a.g),f.find("#b").value(a.b),f.find("#hex").value(this.value().substr(1)),e(this.value()))}},{type:"form",padding:0,labelGap:5,defaults:{type:"textbox",size:7,value:"0",flex:1,spellcheck:!1,onchange:function(){var a,b,c=f.find("colorpicker")[0];return a=this.name(),b=this.value(),"hex"==a?(b="#"+b,d(b),void c.value(b)):(b={r:f.find("#r").value(),g:f.find("#g").value(),b:f.find("#b").value()},c.value(b),void d(b))}},items:[{name:"r",label:"R",autofocus:1},{name:"g",label:"G"},{name:"b",label:"B"},{name:"hex",label:"#",value:"000000"},{name:"preview",type:"container",border:1}]}]},onSubmit:function(){b("#"+this.toJSON().hex)}});d(c)}a.settings.color_picker_callback||(a.settings.color_picker_callback=b)});
--------------------------------------------------------------------------------
/public/admin-assets/tinymce/plugins/pagebreak/plugin.min.js:
--------------------------------------------------------------------------------
1 | tinymce.PluginManager.add("pagebreak",function(a){var b="mce-pagebreak",c=a.getParam("pagebreak_separator",""),d=new RegExp(c.replace(/[\?\.\*\[\]\(\)\{\}\+\^\$\:]/g,function(a){return"\\"+a}),"gi"),e='
';a.addCommand("mcePageBreak",function(){a.settings.pagebreak_split_block?a.insertContent(""+e+"
"):a.insertContent(e)}),a.addButton("pagebreak",{title:"Page break",cmd:"mcePageBreak"}),a.addMenuItem("pagebreak",{text:"Page break",icon:"pagebreak",cmd:"mcePageBreak",context:"insert"}),a.on("ResolveName",function(c){"IMG"==c.target.nodeName&&a.dom.hasClass(c.target,b)&&(c.name="pagebreak")}),a.on("click",function(c){c=c.target,"IMG"===c.nodeName&&a.dom.hasClass(c,b)&&a.selection.select(c)}),a.on("BeforeSetContent",function(a){a.content=a.content.replace(d,e)}),a.on("PreInit",function(){a.serializer.addNodeFilter("img",function(b){for(var d,e,f=b.length;f--;)if(d=b[f],e=d.attr("class"),e&&-1!==e.indexOf("mce-pagebreak")){var g=d.parent;if(a.schema.getBlockElements()[g.name]&&a.settings.pagebreak_split_block){g.type=3,g.value=c,g.raw=!0,d.remove();continue}d.type=3,d.value=c,d.raw=!0}})})});
--------------------------------------------------------------------------------
/src/admin/client/modules/files/actions.js:
--------------------------------------------------------------------------------
1 | import * as t from './actionTypes'
2 | import api from 'lib/api'
3 | import messages from 'lib/text'
4 |
5 | function receiveFiles(files) {
6 | return {
7 | type: t.FILES_RECEIVE,
8 | files
9 | }
10 | }
11 |
12 | function filesUploadStart() {
13 | return {
14 | type: t.FILES_UPLOAD_START
15 | }
16 | }
17 |
18 | function filesUploadEnd() {
19 | return {
20 | type: t.FILES_UPLOAD_END
21 | }
22 | }
23 |
24 | export function fetchFiles() {
25 | return (dispatch, getState) => {
26 | return api.files.list().then(({status, json}) => {
27 | dispatch(receiveFiles(json))
28 | }).catch(error => {});
29 | }
30 | }
31 |
32 | export function uploadFiles(form) {
33 | return (dispatch, getState) => {
34 | dispatch(filesUploadStart());
35 | return api.files.upload(form).then(() => {
36 | dispatch(filesUploadEnd());
37 | dispatch(fetchFiles())
38 | }).catch(error => {
39 | dispatch(filesUploadEnd());
40 | });
41 | }
42 | }
43 |
44 | export function deleteFile(fileName) {
45 | return (dispatch, getState) => {
46 | return api.files.delete(fileName).then(() => {
47 | dispatch(fetchFiles())
48 | }).catch(error => {});
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/admin/client/modules/settings/tokens/edit/index.js:
--------------------------------------------------------------------------------
1 | import { connect } from 'react-redux'
2 | import { fetchToken, updateToken, createToken, receiveToken, deleteToken } from '../../actions'
3 | import Form from './components/form'
4 |
5 | const mapStateToProps = (state, ownProps) => {
6 | const {tokenId} = ownProps.match.params;
7 | return {
8 | tokenId: tokenId,
9 | initialValues: state.settings.tokenEdit,
10 | newToken: state.settings.newToken
11 | }
12 | }
13 |
14 | const mapDispatchToProps = (dispatch, ownProps) => {
15 | return {
16 | onLoad: () => {
17 | const {tokenId} = ownProps.match.params;
18 | if(tokenId) {
19 | dispatch(fetchToken(tokenId))
20 | } else {
21 | dispatch(receiveToken({ expiration: 24 }));
22 | }
23 | },
24 | onSubmit: (token) => {
25 | if(token.id) {
26 | dispatch(updateToken(token));
27 | } else {
28 | dispatch(createToken(token));
29 | }
30 | },
31 | onDelete: () => {
32 | const {tokenId} = ownProps.match.params;
33 | dispatch(deleteToken(tokenId));
34 | ownProps.history.push('/admin/settings/tokens');
35 | }
36 | }
37 | }
38 |
39 | export default connect(mapStateToProps, mapDispatchToProps)(Form);
40 |
--------------------------------------------------------------------------------
/src/api/server/lib/events.js:
--------------------------------------------------------------------------------
1 | const security = require('./security.js');
2 | const settings = require('./settings.js');
3 |
4 | let subscribers = [];
5 |
6 | const THEME_INSTALLED = 'theme-installed';
7 | const ORDER_RECEIVED = 'order-received';
8 | const ORDER_CHANGED = 'order-changed';
9 |
10 | const subscribe = (req, res) => {
11 | security.verifyToken(req.query.token, settings.jwtSecretKey).then(err => {
12 | if(err){
13 | res.status(403).end();
14 | } else {
15 | res.writeHead(200, {
16 | 'Content-Type': 'text/event-stream',
17 | 'Cache-Control': 'no-cache',
18 | 'Connection': 'keep-alive',
19 | 'X-Accel-Buffering': 'no'
20 | });
21 | subscribers.push(res);
22 |
23 | req.on("close", () => {
24 | subscribers = subscribers.filter(item => item !== res);
25 | });
26 | }
27 | })
28 | }
29 |
30 | const sendMessage = (data) => {
31 | const json = JSON.stringify(data);
32 | for(var i = 0; i < subscribers.length; i++) {
33 | try{
34 | subscribers[i].write(`data: ${json}\n\n`);
35 | } catch(e){
36 | }
37 | }
38 | }
39 |
40 | module.exports = {
41 | subscribe,
42 | sendMessage,
43 | THEME_INSTALLED,
44 | ORDER_RECEIVED,
45 | ORDER_CHANGED
46 | }
47 |
--------------------------------------------------------------------------------
/theme/src/components/productDetails/relatedProducts.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { themeSettings, text } from '../../lib/settings'
3 | import CustomProducts from '../products/custom'
4 | const Fragment = React.Fragment;
5 |
6 | export default class RelatedProducts extends React.PureComponent {
7 | constructor(props) {
8 | super(props);
9 | }
10 |
11 | render() {
12 | const { ids, settings, addCartItem, limit } = this.props;
13 | if(ids && ids.length > 0) {
14 | let title = themeSettings.related_products_title && themeSettings.related_products_title.length > 0
15 | ? themeSettings.related_products_title
16 | : text.relatedProducts;
17 |
18 | return (
19 |
32 | )
33 | } else {
34 | return null;
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/admin/client/modules/customers/list/index.js:
--------------------------------------------------------------------------------
1 | import { connect } from 'react-redux'
2 | import { fetchCustomers, selectCustomer, deselectCustomer, selectAllCustomer, deselectAllCustomer, fetchMoreCustomers } from '../actions'
3 | import List from './components/list'
4 |
5 | const mapStateToProps = (state) => {
6 | return {
7 | settings: state.settings.settings,
8 | items: state.customers.items,
9 | selected: state.customers.selected,
10 | loadingItems: state.customers.loadingItems,
11 | hasMore: state.customers.hasMore
12 | }
13 | }
14 |
15 | const mapDispatchToProps = (dispatch) => {
16 | return {
17 | onLoad: () => {
18 | dispatch(fetchCustomers());
19 | },
20 | onSelect: (customerId, checked) => {
21 | if(checked) {
22 | dispatch(selectCustomer(customerId));
23 | } else {
24 | dispatch(deselectCustomer(customerId));
25 | }
26 | },
27 | onSelectAll: (checked) => {
28 | if(checked) {
29 | dispatch(selectAllCustomer());
30 | } else {
31 | dispatch(deselectAllCustomer());
32 | }
33 | },
34 | loadMore: () => {
35 | dispatch(fetchMoreCustomers());
36 | }
37 | }
38 | }
39 |
40 | export default connect(mapStateToProps, mapDispatchToProps)(List);
41 |
--------------------------------------------------------------------------------
/src/admin/client/modules/head/index.js:
--------------------------------------------------------------------------------
1 | import { connect } from 'react-redux'
2 | import { withRouter } from 'react-router'
3 | import AppBar from './components/appBar'
4 |
5 | const mapStateToProps = (state) => {
6 | const productCategory = state.productCategories.items.find((item) => (item.id === state.productCategories.selectedId));
7 | const customerGroup = state.customerGroups.items.find((item) => (item.id === state.customerGroups.selectedId));
8 | const orderStatus = state.orderStatuses.items.find((item) => (item.id === state.orderStatuses.selectedId));
9 | const orderNumber = state.orders.editOrder ? state.orders.editOrder.number : null;
10 |
11 | return {
12 | productsSelectedCount: state.products.selected.length,
13 | customersSelectedCount: state.customers.selected.length,
14 | ordersSelectedCount: state.orders.selected.length,
15 | productCategoryName: productCategory ? productCategory.name : null,
16 | customerGroupName: customerGroup ? customerGroup.name : null,
17 | orderStatusName: orderStatus ? orderStatus.name: null,
18 | orderNumber: orderNumber
19 | }
20 | }
21 |
22 | const mapDispatchToProps = (dispatch) => {
23 | return {}
24 | }
25 |
26 | export default withRouter(connect(mapStateToProps, mapDispatchToProps)(AppBar));
27 |
--------------------------------------------------------------------------------
/public/admin-assets/tinymce/plugins/visualchars/plugin.min.js:
--------------------------------------------------------------------------------
1 | tinymce.PluginManager.add("visualchars",function(a){function b(b){function c(a){return''+a+""}function f(){var a,b="";for(a in n)b+=a;return new RegExp("["+b+"]","g")}function g(){var a,b="";for(a in n)b&&(b+=","),b+="span.mce-"+n[a];return b}var h,i,j,k,l,m,n,o,p=a.getBody(),q=a.selection;if(n={"\xa0":"nbsp","\xad":"shy"},d=!d,e.state=d,a.fire("VisualChars",{state:d}),o=f(),b&&(m=q.getBookmark()),d)for(i=[],tinymce.walk(p,function(a){3==a.nodeType&&a.nodeValue&&o.test(a.nodeValue)&&i.push(a)},"childNodes"),j=0;j=0;j--)a.dom.remove(i[j],1);q.moveToBookmark(m)}function c(){var b=this;a.on("VisualChars",function(a){b.active(a.state)})}var d,e=this;a.addCommand("mceVisualChars",b),a.addButton("visualchars",{title:"Show invisible characters",cmd:"mceVisualChars",onPostRender:c}),a.addMenuItem("visualchars",{text:"Show invisible characters",cmd:"mceVisualChars",onPostRender:c,selectable:!0,context:"view",prependToContext:!0}),a.on("beforegetcontent",function(a){d&&"raw"!=a.format&&!a.draft&&(d=!0,b(!1))})});
--------------------------------------------------------------------------------
/public/admin-assets/tinymce/plugins/tabfocus/plugin.min.js:
--------------------------------------------------------------------------------
1 | tinymce.PluginManager.add("tabfocus",function(a){function b(a){9!==a.keyCode||a.ctrlKey||a.altKey||a.metaKey||a.preventDefault()}function c(b){function c(c){function f(a){return"BODY"===a.nodeName||"hidden"!=a.type&&"none"!=a.style.display&&"hidden"!=a.style.visibility&&f(a.parentNode)}function i(a){return/INPUT|TEXTAREA|BUTTON/.test(a.tagName)&&tinymce.get(b.id)&&-1!=a.tabIndex&&f(a)}if(h=d.select(":input:enabled,*[tabindex]:not(iframe)"),e(h,function(b,c){return b.id==a.id?(g=c,!1):void 0}),c>0){for(j=g+1;j=0;j--)if(i(h[j]))return h[j];return null}var g,h,i,j;if(!(9!==b.keyCode||b.ctrlKey||b.altKey||b.metaKey||b.isDefaultPrevented())&&(i=f(a.getParam("tab_focus",a.getParam("tabfocus_elements",":prev,:next"))),1==i.length&&(i[1]=i[0],i[0]=":prev"),h=b.shiftKey?":prev"==i[0]?c(-1):d.get(i[0]):":next"==i[1]?c(1):d.get(i[1]))){var k=tinymce.get(h.id||h.name);h.id&&k?k.focus():tinymce.util.Delay.setTimeout(function(){tinymce.Env.webkit||window.focus(),h.focus()},10),b.preventDefault()}}var d=tinymce.DOM,e=tinymce.each,f=tinymce.explode;a.on("init",function(){a.inline&&tinymce.DOM.setAttrib(a.getBody(),"tabIndex",null),a.on("keyup",b),tinymce.Env.gecko?a.on("keypress keydown",c):a.on("keydown",c)})});
--------------------------------------------------------------------------------
/src/admin/client/modules/products/list/components/style.css:
--------------------------------------------------------------------------------
1 | .imageBox {
2 | height: 80px;
3 | }
4 |
5 | .image {
6 | max-width: 80px;
7 | max-height: 70px;
8 | border: 1px solid #eee;
9 | }
10 |
11 | .productName {
12 | display: block;
13 | text-decoration: none;
14 | font-weight: 400;
15 | font-size: 14px;
16 | }
17 |
18 | .productName small {
19 | color: rgba(0, 0, 0, 0.4);
20 | }
21 |
22 | .productActive {
23 | color: rgb(0,142,180);
24 | }
25 |
26 | .productInactive {
27 | color: rgba(0, 0, 0, 0.3);
28 | }
29 |
30 | .sku {
31 | word-break: break-all;
32 | }
33 |
34 | .stock {
35 | word-break: break-all;
36 | }
37 |
38 | .inStock {
39 | color: rgb(122,179,23);
40 | }
41 |
42 | .outOfStock {
43 | color: rgb(228,86,53);
44 | }
45 |
46 | .backorder {
47 | color: rgb(251,184,41);
48 | }
49 |
50 | .preorder {
51 | /*color: rgb(228,86,53);*/
52 | }
53 |
54 | .discontinued {
55 | color: rgba(0, 0, 0, 0.3);
56 | }
57 |
58 | .price {
59 | word-break: break-all;
60 | text-align: right;;
61 | }
62 |
63 | .price small {
64 | display: block;
65 | text-decoration: line-through;
66 | color: rgba(0, 0, 0, 0.4);
67 | }
68 |
69 | .more {
70 | padding: 40px 0;
71 | text-align: center;
72 | }
73 |
74 | .innerItem {
75 | padding: 0 16px;
76 | }
77 |
--------------------------------------------------------------------------------
/theme/src/containers/checkout.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { themeSettings, text } from '../lib/settings'
3 | import MetaTags from '../components/metaTags'
4 | import OrderSummary from '../components/orderSummary'
5 | const Fragment = React.Fragment;
6 |
7 | const CheckoutContainer = (props) => {
8 | const {pageDetails} = props.state;
9 | const {checkoutForm} = props;
10 |
11 | return (
12 |
13 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 | {checkoutForm}
29 |
30 |
31 |
32 |
33 |
34 | )
35 | }
36 |
37 | export default CheckoutContainer
38 |
--------------------------------------------------------------------------------
/src/admin/client/modules/orders/editHead/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { connect } from 'react-redux'
3 | import { withRouter } from 'react-router'
4 | import { addOrderItem, updateOrder, deleteCurrentOrder, closeOrder, cancelOrder } from '../actions'
5 | import Buttons from './components/buttons'
6 |
7 | const mapStateToProps = (state, ownProps) => {
8 | return {
9 | settings: state.settings.settings,
10 | order: state.orders.editOrder
11 | }
12 | }
13 |
14 | const mapDispatchToProps = (dispatch, ownProps) => {
15 | return {
16 | onDelete: () => {
17 | dispatch(deleteCurrentOrder());
18 | ownProps.history.push('/admin/orders');
19 | },
20 | setCancelled: (orderId) => {
21 | dispatch(cancelOrder(orderId));
22 | },
23 | holdOrder: (orderId) => {
24 | dispatch(updateOrder({ id: orderId, hold: true }));
25 | },
26 | resumeOrder: (orderId) => {
27 | dispatch(updateOrder({ id: orderId, hold: false }));
28 | },
29 | setClosed: (orderId) => {
30 | dispatch(closeOrder(orderId));
31 | },
32 | addItem: (orderId, productId) => {
33 | dispatch(addOrderItem(orderId, productId));
34 | }
35 | }
36 | }
37 |
38 | export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Buttons));
39 |
--------------------------------------------------------------------------------
/src/admin/client/modules/orders/list/index.js:
--------------------------------------------------------------------------------
1 | import { connect } from 'react-redux'
2 | import { withRouter } from 'react-router'
3 | import { fetchOrders, selectOrder, deselectOrder, selectAllOrder, deselectAllOrder, fetchMoreOrders } from '../actions'
4 | import List from './components/list'
5 |
6 | const mapStateToProps = (state, ownProps) => {
7 | return {
8 | settings: state.settings.settings,
9 | items: state.orders.items,
10 | selected: state.orders.selected,
11 | loadingItems: state.orders.loadingItems,
12 | hasMore: state.orders.hasMore
13 | }
14 | }
15 |
16 | const mapDispatchToProps = (dispatch, ownProps) => {
17 | return {
18 | onLoad: () => {
19 | dispatch(fetchOrders());
20 | },
21 | onSelect: (orderId, checked) => {
22 | if(checked) {
23 | dispatch(selectOrder(orderId));
24 | } else {
25 | dispatch(deselectOrder(orderId));
26 | }
27 | },
28 | onSelectAll: (checked) => {
29 | if(checked) {
30 | dispatch(selectAllOrder());
31 | } else {
32 | dispatch(deselectAllOrder());
33 | }
34 | },
35 | loadMore: () => {
36 | dispatch(fetchMoreOrders());
37 | }
38 | }
39 | }
40 |
41 | export default withRouter(connect(mapStateToProps, mapDispatchToProps)(List));
42 |
--------------------------------------------------------------------------------
/src/admin/client/modules/apps/reducer.js:
--------------------------------------------------------------------------------
1 | import * as t from './actionTypes'
2 |
3 | const initialState = {
4 | account: null,
5 | services: [],
6 | service: null,
7 | serviceSettings: null,
8 | serviceLogs: null,
9 | loadingEnableDisableService: false
10 | };
11 |
12 | export default(state = initialState, action) => {
13 | switch (action.type) {
14 | case t.ACCOUNT_RECEIVE:
15 | return Object.assign({}, state, {account: action.account})
16 | case t.SERVICES_RECEIVE:
17 | return Object.assign({}, state, {services: action.services})
18 | case t.SERVICE_RECEIVE:
19 | return Object.assign({}, state, {service: action.service})
20 | case t.SERVICE_SETTINGS_REQUEST:
21 | return Object.assign({}, state, {serviceSettings: null})
22 | case t.SERVICE_SETTINGS_RECEIVE:
23 | return Object.assign({}, state, {serviceSettings: action.serviceSettings})
24 | case t.SERVICE_LOGS_RECEIVE:
25 | return Object.assign({}, state, {serviceLogs: action.serviceLogs})
26 | case t.SERVICE_ENABLE_REQUEST:
27 | return Object.assign({}, state, {loadingEnableDisableService: true})
28 | case t.SERVICE_ENABLE_RECEIVE:
29 | return Object.assign({}, state, {loadingEnableDisableService: false})
30 | default:
31 | return state
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/api/server/lib/utils.js:
--------------------------------------------------------------------------------
1 | var SitemapService = require('../services/sitemap');
2 |
3 | var slug = require('slug');
4 | var slugConfig = {
5 | symbols: false, // replace unicode symbols or not
6 | remove: null, // (optional) regex to remove characters
7 | lower: true // result in lower case
8 | };
9 |
10 | const cleanSlug = (text) => {
11 | return slug(text || '', slugConfig);
12 | }
13 |
14 | const getAvailableSlug = (path, resource, enableCleanPath = true) => {
15 | return SitemapService.getPaths()
16 | .then(paths => {
17 | if(enableCleanPath){
18 | path = cleanSlug(path);
19 | }
20 |
21 | let pathExists = paths.find(e => e.path === '/' + path && e.resource != resource);
22 | while(pathExists) {
23 | path += '-2';
24 | pathExists = paths.find(e => e.path === '/' + path && e.resource != resource);
25 | }
26 | return path;
27 | })
28 | }
29 |
30 | const getCorrectFileName = (filename) => {
31 | if(filename){
32 | // replace unsafe characters
33 | return filename.replace(/[\s*/:;&?@$()<>#%\{\}|\\\^\~\[\]]/g, '-');
34 | } else {
35 | return filename;
36 | }
37 | }
38 |
39 | module.exports = {
40 | cleanSlug: cleanSlug,
41 | getAvailableSlug: getAvailableSlug,
42 | getCorrectFileName: getCorrectFileName
43 | }
44 |
--------------------------------------------------------------------------------
/theme/assets/images/payment/visa.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/admin/client/modules/products/edit/inventory/index.js:
--------------------------------------------------------------------------------
1 | import { connect } from 'react-redux'
2 | import { withRouter } from 'react-router'
3 | import { updateProduct } from '../../actions'
4 | import ProductInventoryForm from './components/form'
5 |
6 | const mapStateToProps = (state, ownProps) => {
7 | return {
8 | settings: state.settings.settings,
9 | initialValues: state.products.editProduct
10 | }
11 | }
12 |
13 | const mapDispatchToProps = (dispatch, ownProps) => {
14 | return {
15 | onSubmit: (values) => {
16 | dispatch(updateProduct({
17 | id: values.id,
18 | regular_price: values.regular_price,
19 | sale_price: values.sale_price,
20 | date_sale_from: values.date_sale_from,
21 | date_sale_to: values.date_sale_to,
22 | sku: values.sku,
23 | stock_quantity: values.stock_quantity,
24 | weight: values.weight,
25 | date_stock_expected: values.date_stock_expected,
26 | stock_tracking: values.stock_tracking,
27 | stock_preorder: values.stock_preorder,
28 | stock_backorder: values.stock_backorder,
29 | discontinued: values.discontinued,
30 | enabled: values.enabled
31 | }));
32 | }
33 | }
34 | }
35 |
36 | export default withRouter(connect(mapStateToProps, mapDispatchToProps)(ProductInventoryForm));
37 |
--------------------------------------------------------------------------------
/public/admin-assets/tinymce/plugins/advlist/plugin.min.js:
--------------------------------------------------------------------------------
1 | tinymce.PluginManager.add("advlist",function(a){function b(a,b){var c=[];return tinymce.each(b.split(/[ ,]/),function(a){c.push({text:a.replace(/\-/g," ").replace(/\b\w/g,function(a){return a.toUpperCase()}),data:"default"==a?"":a})}),c}function c(b,c){a.undoManager.transact(function(){var d,e=a.dom,f=a.selection;if(d=e.getParent(f.getNode(),"ol,ul"),!d||d.nodeName!=b||c===!1){var h={"list-style-type":c?c:""};a.execCommand("UL"==b?"InsertUnorderedList":"InsertOrderedList",!1,h)}c=c===!1?g[b]:c,g[b]=c,d=e.getParent(f.getNode(),"ol,ul"),d&&(e.setStyle(d,"listStyleType",c?c:null),d.removeAttribute("data-mce-style")),a.focus()})}function d(b){var c=a.dom.getStyle(a.dom.getParent(a.selection.getNode(),"ol,ul"),"listStyleType")||"";b.control.items().each(function(a){a.active(a.settings.data===c)})}var e,f,g={};e=b("OL",a.getParam("advlist_number_styles","default,lower-alpha,lower-greek,lower-roman,upper-alpha,upper-roman")),f=b("UL",a.getParam("advlist_bullet_styles","default,circle,disc,square")),a.addButton("numlist",{type:"splitbutton",tooltip:"Numbered list",menu:e,onshow:d,onselect:function(a){c("OL",a.control.settings.data)},onclick:function(){c("OL",!1)}}),a.addButton("bullist",{type:"splitbutton",tooltip:"Bullet list",menu:f,onshow:d,onselect:function(a){c("UL",a.control.settings.data)},onclick:function(){c("UL",!1)}})});
--------------------------------------------------------------------------------