From 179d8232d1cd6ddfafe8c5c7032186d06706210b Mon Sep 17 00:00:00 2001 From: Tony Air Date: Sun, 26 Aug 2018 17:46:03 +0700 Subject: [PATCH] Mapbox API + SilverShop improvements --- .htaccess | 109 +++++++ app/_config/config.yml | 8 +- app/_config/elements.yml | 2 + app/_config/extensions.yml | 6 + app/_config/googlemapfield.yml | 3 + app/_config/payment.yml | 6 + app/_config/requirements.yml | 4 + app/client/src/js/_components/_ui.map.api.js | 292 ++++++++++-------- .../SilverShop.Page.CheckoutPageController.js | 1 + .../src/scss/_components/_ui.carousel.scss | 4 - .../src/scss/_components/_ui.elemental.scss | 6 +- app/client/src/scss/_components/_ui.main.scss | 8 + app/client/src/scss/_components/_ui.map.scss | 15 + app/client/src/scss/_components/_ui.shop.scss | 8 + app/client/src/scss/types/HomePage.scss | 1 - app/client/src/scss/types/order.scss | 163 ++++++++++ app/src/Extensions/AddressExtension.php | 29 ++ app/src/Extensions/SiteConfigExtension.php | 37 ++- app/src/Models/CheckoutMapComponent.php | 47 +++ app/src/Models/CheckoutNoDeliveryConfig.php | 43 +++ app/src/Templates/DeferedRequirements.php | 19 +- app/templates/Includes/Content.ss | 8 +- app/templates/Page.ss | 6 +- app/templates/SilverShop/Cart/Cart.ss | 10 +- .../SilverShop/Includes/AccountNavigation.ss | 75 ++--- .../SilverShop/Includes/OrderHistory.ss | 2 +- app/templates/SilverShop/Model/Order.ss | 3 +- .../Model/Order_Content_ItemLine.ss | 2 +- .../SilverShop/Page/Layout/AccountPage.ss | 32 +- .../Page/Layout/AccountPage_addressbook.ss | 124 ++++---- .../Page/Layout/AccountPage_editprofile.ss | 42 ++- .../Page/Layout/AccountPage_order.ss | 4 + .../SilverShop/Page/Layout/CartPage.ss | 54 ++-- .../SilverShop/Page/Layout/CheckoutPage.ss | 6 +- package.json | 1 + php.ini | 4 + 36 files changed, 862 insertions(+), 322 deletions(-) create mode 100644 .htaccess create mode 100644 app/_config/googlemapfield.yml create mode 100644 app/_config/payment.yml create mode 100644 app/client/src/js/types/SilverShop.Page.CheckoutPageController.js create mode 100644 app/client/src/scss/_components/_ui.map.scss create mode 100644 app/client/src/scss/_components/_ui.shop.scss delete mode 100644 app/client/src/scss/types/HomePage.scss create mode 100644 app/client/src/scss/types/order.scss create mode 100644 app/src/Extensions/AddressExtension.php create mode 100644 app/src/Models/CheckoutMapComponent.php create mode 100644 app/src/Models/CheckoutNoDeliveryConfig.php create mode 100644 php.ini diff --git a/.htaccess b/.htaccess new file mode 100644 index 0000000..fa05289 --- /dev/null +++ b/.htaccess @@ -0,0 +1,109 @@ +Header set X-Content-Security-Policy "allow 'self'; media-src *; img-src *; script-src 'self' https://ajax.googleapis.com; style-src 'self';" +Header always append X-Frame-Options SAMEORIGIN +ServerSignature Off + +mod_gzip_on Yes +mod_gzip_dechunk Yes +mod_gzip_item_include file .(html?|txt|css|js|php|pl)$ +mod_gzip_item_include handler ^cgi-script$ +mod_gzip_item_include mime ^text/.* +mod_gzip_item_include mime ^application/x-javascript.* +mod_gzip_item_exclude mime ^image/.* +mod_gzip_item_exclude rspheader ^Content-Encoding:.*gzip.* + + +ExpiresActive On +ExpiresByType image/jpg "access 1 year" +ExpiresByType image/jpeg "access 1 year" +ExpiresByType image/gif "access 1 year" +ExpiresByType image/png "access 1 year" +ExpiresByType text/css "access 1 month" +ExpiresByType text/html "access 1 month" +ExpiresByType application/pdf "access 1 month" +ExpiresByType text/x-javascript "access 1 month" +ExpiresByType application/x-shockwave-flash "access 1 month" +ExpiresByType image/x-icon "access 1 year" +ExpiresDefault "access 1 month" + + +RewriteEngine On +RewriteCond %{HTTPS} off +RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301] +RewriteCond %{HTTP_HOST} !^www\. +RewriteRule ^(.*)$ https://www.%{HTTP_HOST}/$1 [R=301,L] + +### SILVERSTRIPE START ### +# Deny access to templates (but allow from localhost) + + Order deny,allow + Deny from all + Allow from 127.0.0.1 + + +# Deny access to IIS configuration + + Order deny,allow + Deny from all + + +# Deny access to YAML configuration files which might include sensitive information + + Order allow,deny + Deny from all + + +# Route errors to static pages automatically generated by SilverStripe +ErrorDocument 404 /assets/error-404.html +ErrorDocument 500 /assets/error-500.html + + + SetEnv HTTP_MOD_REWRITE On + RewriteEngine On + RewriteBase '/' + + # Deny access to potentially sensitive files and folders +RewriteCond %{REQUEST_URI} !^/[0-9]+\..+\.cpaneldcv$ +RewriteCond %{REQUEST_URI} !^/\.well-known/acme-challenge/[0-9a-zA-Z_-]+$ +RewriteCond %{REQUEST_URI} !^/\.well-known/pki-validation/[A-F0-9]{32}\.txt(?:\ Comodo\ DCV)?$ + RewriteRule ^vendor(/|$) - [F,L,NC] +RewriteCond %{REQUEST_URI} !^/[0-9]+\..+\.cpaneldcv$ +RewriteCond %{REQUEST_URI} !^/\.well-known/acme-challenge/[0-9a-zA-Z_-]+$ +RewriteCond %{REQUEST_URI} !^/\.well-known/pki-validation/[A-F0-9]{32}\.txt(?:\ Comodo\ DCV)?$ + RewriteRule silverstripe-cache(/|$) - [F,L,NC] +RewriteCond %{REQUEST_URI} !^/[0-9]+\..+\.cpaneldcv$ +RewriteCond %{REQUEST_URI} !^/\.well-known/acme-challenge/[0-9a-zA-Z_-]+$ +RewriteCond %{REQUEST_URI} !^/\.well-known/pki-validation/[A-F0-9]{32}\.txt(?:\ Comodo\ DCV)?$ + RewriteRule composer\.(json|lock) - [F,L,NC] + + # Process through SilverStripe if no file with the requested name exists. + # Pass through the original path as a query parameter, and retain the existing parameters. + RewriteCond %{REQUEST_URI} ^(.*)$ + RewriteCond %{REQUEST_FILENAME} !-f +RewriteCond %{REQUEST_URI} !^/[0-9]+\..+\.cpaneldcv$ +RewriteCond %{REQUEST_URI} !^/\.well-known/acme-challenge/[0-9a-zA-Z_-]+$ +RewriteCond %{REQUEST_URI} !^/\.well-known/pki-validation/[A-F0-9]{32}\.txt(?:\ Comodo\ DCV)?$ + RewriteRule .* framework/main.php?url=%1 [QSA] + +### SILVERSTRIPE END ### + +RewriteCond %{REQUEST_URI} !^/[0-9]+\..+\.cpaneldcv$ +RewriteCond %{REQUEST_URI} !^/\.well-known/acme-challenge/[0-9a-zA-Z_-]+$ +RewriteCond %{REQUEST_URI} !^/\.well-known/pki-validation/[A-F0-9]{32}\.txt(?:\ Comodo\ DCV)?$ +RewriteRule ^\.git - [F,L,NC] +RewriteCond %{REQUEST_URI} !^/[0-9]+\..+\.cpaneldcv$ +RewriteCond %{REQUEST_URI} !^/\.well-known/acme-challenge/[0-9a-zA-Z_-]+$ +RewriteCond %{REQUEST_URI} !^/\.well-known/pki-validation/[A-F0-9]{32}\.txt(?:\ Comodo\ DCV)?$ +RewriteRule \.sql$ - [F,L,NC] +RewriteCond %{REQUEST_URI} !^/[0-9]+\..+\.cpaneldcv$ +RewriteCond %{REQUEST_URI} !^/\.well-known/acme-challenge/[0-9a-zA-Z_-]+$ +RewriteCond %{REQUEST_URI} !^/\.well-known/pki-validation/[A-F0-9]{32}\.txt(?:\ Comodo\ DCV)?$ +RewriteRule \.editorconfig - [F,L,NC] +RewriteCond %{REQUEST_URI} !^/[0-9]+\..+\.cpaneldcv$ +RewriteCond %{REQUEST_URI} !^/\.well-known/acme-challenge/[0-9a-zA-Z_-]+$ +RewriteCond %{REQUEST_URI} !^/\.well-known/pki-validation/[A-F0-9]{32}\.txt(?:\ Comodo\ DCV)?$ +RewriteRule error_log - [F,L,NC] +RewriteCond %{REQUEST_URI} !^/[0-9]+\..+\.cpaneldcv$ +RewriteCond %{REQUEST_URI} !^/\.well-known/acme-challenge/[0-9a-zA-Z_-]+$ +RewriteCond %{REQUEST_URI} !^/\.well-known/pki-validation/[A-F0-9]{32}\.txt(?:\ Comodo\ DCV)?$ +RewriteRule Envoy\.blade\.php - [F,L,NC] + diff --git a/app/_config/config.yml b/app/_config/config.yml index 7cd246e..4b2ce51 100644 --- a/app/_config/config.yml +++ b/app/_config/config.yml @@ -21,9 +21,5 @@ SilverStripe\Forms\HTMLEditor\TinyMCEConfig: editor_css: - 'app/client/dist/css/editor.css' -SilverStripe\Assets\File: - allowed_extensions: - - svg - app_categories: - image: - - svg +SilverShop\Extension\ShopConfigExtension: + base_currency: USD diff --git a/app/_config/elements.yml b/app/_config/elements.yml index a2ebbad..56772db 100644 --- a/app/_config/elements.yml +++ b/app/_config/elements.yml @@ -25,6 +25,8 @@ SilverStripe\CMS\Model\SiteTree: - Dynamic\Elements\Elements\ElementTestimonials - Site\Elements\TeamMembersElement - Site\Elements\SliderElement + - Site\Elements\PromotionElement + - Site\Elements\StoreElement DNADesign\ElementalList\Model\ElementList: default_global_elements: false diff --git a/app/_config/extensions.yml b/app/_config/extensions.yml index d1b6168..6fcd4bd 100644 --- a/app/_config/extensions.yml +++ b/app/_config/extensions.yml @@ -14,3 +14,9 @@ SilverStripe\Blog\Model\BlogPost: SilverStripe\Core\Injector\Injector: SilverStripe\UserForms\Model\UserDefinedForm: class: Site\Extensions\CMSMain_HiddenClass + SilverShop\Checkout\SinglePageCheckoutComponentConfig: + class: Site\Models\CheckoutNoDeliveryConfig + +#SilverShop\Model\Address: +# extensions: +# - Site\Extensions\AddressExtension \ No newline at end of file diff --git a/app/_config/googlemapfield.yml b/app/_config/googlemapfield.yml new file mode 100644 index 0000000..16f16b4 --- /dev/null +++ b/app/_config/googlemapfield.yml @@ -0,0 +1,3 @@ +BetterBrief\GoogleMapField: + default_options: + api_key: 'YOUR_API_KEY' diff --git a/app/_config/payment.yml b/app/_config/payment.yml new file mode 100644 index 0000000..6bc6630 --- /dev/null +++ b/app/_config/payment.yml @@ -0,0 +1,6 @@ +--- +Name: payment +--- +SilverStripe\Omnipay\Model\Payment: + allowed_gateways: + - 'Manual' diff --git a/app/_config/requirements.yml b/app/_config/requirements.yml index 64c0467..275e978 100644 --- a/app/_config/requirements.yml +++ b/app/_config/requirements.yml @@ -3,4 +3,8 @@ Site\Templates\DeferedRequirements: nofontawesome: false version: false static_domain: false + custom_requirements: + SilverShop\Page\AccountPageController: + - SilverShop.Page.CheckoutPageController.js + - SilverShop.Page.CheckoutPageController.css diff --git a/app/client/src/js/_components/_ui.map.api.js b/app/client/src/js/_components/_ui.map.api.js index 12d40b5..cdf501b 100644 --- a/app/client/src/js/_components/_ui.map.api.js +++ b/app/client/src/js/_components/_ui.map.api.js @@ -5,162 +5,182 @@ import Events from "../_events"; import mapBoxGL from "mapbox-gl"; //import "./mapStorage"; -import "../../scss/types/MapPage.scss"; +import "../../scss/_components/_ui.map.scss"; const W = window; const MapAPI = (($) => { - const STORAGE = W.localStorage; + const STORAGE = W.localStorage; - // Constants - const NAME = 'jsMapAPI'; - const DATA_KEY = NAME; - const $BODY = $('body'); - let Map; - let currentStyle; + // Constants + const NAME = 'jsMapAPI'; + const DATA_KEY = NAME; + const $BODY = $('body'); + let Map; + let currentStyle; - class MapAPI { - // Constructor - constructor(element) { - this._element = element; - const $element = $(this._element); - currentStyle = this.getStyle(); + class MapAPI { + // Constructor + constructor(element) { + this._element = element; + const $element = $(this._element); + const geojson = $element.data('geojson'); + const center = [ + ($element.data('lng') ? $element.data('lng') : $BODY.data('default-lng')), + ($element.data('lat') ? $element.data('lat') : $BODY.data('default-lat')), + ]; + const popup = new mapboxgl.Popup({ + closeOnClick: false, + className: 'popup' + }); + currentStyle = this.getStyle(); + mapBoxGL.accessToken = $element.data('key'); - mapBoxGL.accessToken = 'pk.eyJ1IjoidG9ueS1haXIiLCJhIjoiY2l1OHoxZGp4MDAxZzJ0cHl0Y25jOWFpMCJ9.BC-YvTC2hUKhNbae4iAPCA'; + Map = new mapBoxGL.Map({ + 'container': $element.find('.mapAPI-map')[0], + 'center': center, + //hash: true, + 'style': currentStyle, + //localIdeographFontFamily: $BODY.css('font-family'), + 'zoom': ($element.data('map-zoom') ? $element.data('map-zoom') : 10), + 'attributionControl': false + /*transformRequest: (url, resourceType)=> { + if(resourceType === 'Source' && url.startsWith('http://myHost')) { + return { + url: url.replace('http', 'https'), + headers: { 'my-custom-header': true}, + credentials: 'include' // Include cookies for cross-origin requests + } + } + }*/ + }) + .addControl(new mapBoxGL.AttributionControl({ + compact: true + })) + .addControl(new mapBoxGL.NavigationControl(), 'top-right') + .addControl(new mapBoxGL.GeolocateControl({ + positionOptions: { + enableHighAccuracy: true, + }, + trackUserLocation: true, + }), 'bottom-right') + .addControl(new mapboxgl.ScaleControl({ + maxWidth: 80, + unit: 'metric' + }), 'top-left'); - Map = new mapBoxGL.Map({ - container: $element.find('.mapAPI-map')[0], - center: [$BODY.data('default-lng'), $BODY.data('default-lat')], - //hash: true, - style: currentStyle, - //localIdeographFontFamily: $BODY.css('font-family'), - zoom: $element.data('map-zoom'), - attributionControl: false - /*transformRequest: (url, resourceType)=> { - if(resourceType === 'Source' && url.startsWith('http://myHost')) { - return { - url: url.replace('http', 'https'), - headers: { 'my-custom-header': true}, - credentials: 'include' // Include cookies for cross-origin requests - } - } - }*/ - }) - .addControl(new mapBoxGL.AttributionControl({ - compact: true - })) - .addControl(new mapBoxGL.NavigationControl(), 'top-right') - .addControl(new mapBoxGL.GeolocateControl({ - positionOptions: { - enableHighAccuracy: true, - }, - trackUserLocation: true, - }),'bottom-right') - .addControl(new mapboxgl.ScaleControl({ - maxWidth: 80, - unit: 'metric' - }),'top-left'); + // event.target + Map.on('load', (e) => { + // add markers to map + geojson.features.forEach(function(marker) { + // create a DOM element for the marker + const $el = $('
' + marker.icon + '
'); - // event.target - Map.on('load',(e) => { - console.log('Map is loaded'); - /*Map.addSource('dem', { - "type": "raster-dem", - "url": "mapbox://mapbox.terrain-rgb" - }); - Map.addLayer({ - "id": "hillshading", - "source": "dem", - "type": "hillshade" - });*/ - }); + $el.on('click', function() { + console.log('Marker click'); + const coordinates = marker.geometry.coordinates; + const content = marker.properties.content; + console.log(popup); + popup.setLngLat(coordinates) + .setHTML(content) + .addTo(Map); + }); - /*Map.on('render',function(event){ - console.log('map moved'); - console.log(event); - }); + // add marker to map + new mapboxgl.Marker($el[0]) + .setLngLat(marker.geometry.coordinates) + .addTo(Map); + }); - // event: MapDataEvent - Map.on('dataloading',() => { - console.log('Loading map data'); - //console.log(event); - }); + console.log('Map is loaded'); + }); - // event: MapDataEvent - Map.on('data',(event) => { - console.log('Map data updated'); - //console.log(event); - });*/ + /*Map.on('render',function(event){ + console.log('map moved'); + console.log(event); + }); - // check time every 60 mins and change to night style - const api = this; - setInterval(() => { - const newStyle = api.getStyle(); - if(newStyle !== currentStyle){ - Map.setStyle(api.getStyle()); + // event: MapDataEvent + Map.on('dataloading',() => { + console.log('Loading map data'); + //console.log(event); + }); + + // event: MapDataEvent + Map.on('data',(event) => { + console.log('Map data updated'); + //console.log(event); + });*/ + + // check time every 60 mins and change to night style + const api = this; + setInterval(() => { + const newStyle = api.getStyle(); + if (newStyle !== currentStyle) { + Map.setStyle(api.getStyle()); + } + }, 36000); + + + $element.addClass(`${NAME}-active`); } - },36000); + // Public methods + getMap() { + return Map; + } - $element.addClass(`${NAME}-active`); + getStyle() { + return 'mapbox://styles/mapbox/streets-v9'; + const hour = new Date().getHours(); + if (hour < 6 || hour > 18) { + // night + //return 'mapbox://styles/mapbox/streets-v7'; + return 'mapbox://styles/tony-air/cjeacwih92iu42rpd8tcmuyb2'; + } else { + // day + return 'mapbox://styles/mapbox/streets-v9'; + } + } + + dispose() { + const $element = $(this._element); + + $element.removeClass(`${NAME}-active`); + $.removeData(this._element, DATA_KEY); + this._element = null; + } + + static _jQueryInterface() { + if (typeof W.localStorage !== 'undefined') { + return this.each(function() { + // attach functionality to element + const $element = $(this); + let data = $element.data(DATA_KEY); + + if (!data) { + data = new MapAPI(this); + $element.data(DATA_KEY, data); + } + }); + } + } } - // Public methods - getMap() { - return Map; - } + // jQuery interface + $.fn[NAME] = MapAPI._jQueryInterface; + $.fn[NAME].Constructor = MapAPI; + $.fn[NAME].noConflict = function() { + $.fn[NAME] = JQUERY_NO_CONFLICT; + return MapAPI._jQueryInterface; + }; - getStyle() { - return 'mapbox://styles/mapbox/streets-v9'; - const hour = new Date().getHours(); - if(hour < 6 || hour > 18) { - // night - //return 'mapbox://styles/mapbox/streets-v7'; - return 'mapbox://styles/tony-air/cjeacwih92iu42rpd8tcmuyb2'; - }else{ - // day - return 'mapbox://styles/mapbox/streets-v9'; - } - } + // auto-apply + $(W).on(`${Events.AJAX} ${Events.LOADED}`, () => { + $('.mapAPI-map-container').jsMapAPI(); + }); - dispose() { - const $element = $(this._element); - - $element.removeClass(`${NAME}-active`); - $.removeData(this._element, DATA_KEY); - this._element = null; - } - - static _jQueryInterface() { - if (typeof W.localStorage !== 'undefined') { - return this.each(function () { - // attach functionality to element - const $element = $(this); - let data = $element.data(DATA_KEY); - - if (!data) { - data = new MapAPI(this); - $element.data(DATA_KEY, data); - } - }); - } - } - } - - // jQuery interface - $.fn[NAME] = MapAPI._jQueryInterface; - $.fn[NAME].Constructor = MapAPI; - $.fn[NAME].noConflict = function () { - $.fn[NAME] = JQUERY_NO_CONFLICT; - return MapAPI._jQueryInterface; - }; - - // auto-apply - $(W).on(`${Events.AJAX} ${Events.LOADED}`, () => { - $('.mapAPI-map-container').jsMapAPI(); - }); - - return MapAPI; + return MapAPI; })($); export default MapAPI; diff --git a/app/client/src/js/types/SilverShop.Page.CheckoutPageController.js b/app/client/src/js/types/SilverShop.Page.CheckoutPageController.js new file mode 100644 index 0000000..c4d5780 --- /dev/null +++ b/app/client/src/js/types/SilverShop.Page.CheckoutPageController.js @@ -0,0 +1 @@ +import '../_components/_ui.map.api'; diff --git a/app/client/src/scss/_components/_ui.carousel.scss b/app/client/src/scss/_components/_ui.carousel.scss index 4f8be2b..3d3c1f2 100644 --- a/app/client/src/scss/_components/_ui.carousel.scss +++ b/app/client/src/scss/_components/_ui.carousel.scss @@ -16,10 +16,6 @@ .carousel-indicators li { box-shadow: 1px 1px #000; - - &.active { - background: $blue; - } } .carousel-title, diff --git a/app/client/src/scss/_components/_ui.elemental.scss b/app/client/src/scss/_components/_ui.elemental.scss index a9da826..e33600e 100644 --- a/app/client/src/scss/_components/_ui.elemental.scss +++ b/app/client/src/scss/_components/_ui.elemental.scss @@ -3,8 +3,12 @@ */ // hide default page title cuz elemental object will be used to display titles -h1 { +h1.page-header { display: none; + + &.no-elements { + display: block; + } } // add top/bottom paddings for basic elements diff --git a/app/client/src/scss/_components/_ui.main.scss b/app/client/src/scss/_components/_ui.main.scss index a077118..2fd2c15 100644 --- a/app/client/src/scss/_components/_ui.main.scss +++ b/app/client/src/scss/_components/_ui.main.scss @@ -37,6 +37,14 @@ button, input, optgroup, select, textarea, transition: all 0.4s ease; } +.btn-toolbar { + margin-top: $grid-gutter-height / 2; +} + +.field { + margin: ($grid-gutter-height / 4) 0; +} + // stick navbar to top using mobile layout #Header { position: relative; diff --git a/app/client/src/scss/_components/_ui.map.scss b/app/client/src/scss/_components/_ui.map.scss new file mode 100644 index 0000000..8b24d61 --- /dev/null +++ b/app/client/src/scss/_components/_ui.map.scss @@ -0,0 +1,15 @@ +@import "../variables"; +@import "~mapbox-gl/dist/mapbox-gl.css"; + +.mapAPI-map { + height: 30rem; + margin-bottom: 1rem; +} + +.mapboxgl-marker { + width: 30px; + height: 30px; + font-size: 30px; + cursor: pointer; + text-align: center; +} diff --git a/app/client/src/scss/_components/_ui.shop.scss b/app/client/src/scss/_components/_ui.shop.scss new file mode 100644 index 0000000..ada7ca5 --- /dev/null +++ b/app/client/src/scss/_components/_ui.shop.scss @@ -0,0 +1,8 @@ +.cart-footer { + margin-top: $grid-gutter-height / 2; +} + +.address-panel, +.account-nav { + margin-bottom: $grid-gutter-height / 2; +} diff --git a/app/client/src/scss/types/HomePage.scss b/app/client/src/scss/types/HomePage.scss deleted file mode 100644 index 916afb4..0000000 --- a/app/client/src/scss/types/HomePage.scss +++ /dev/null @@ -1 +0,0 @@ -@import "../variables"; \ No newline at end of file diff --git a/app/client/src/scss/types/order.scss b/app/client/src/scss/types/order.scss new file mode 100644 index 0000000..fe673b1 --- /dev/null +++ b/app/client/src/scss/types/order.scss @@ -0,0 +1,163 @@ +@import "../_variables"; + +h1.title { + display: block; + text-align: right; + border-bottom: 1px solid $border-color; + text-transform: uppercase; + line-height: 1.5em; +} + +.warningMessage { + position: relative; + padding: $alert-padding-y $alert-padding-x; + margin-bottom: $alert-margin-bottom; + border: $alert-border-width solid transparent; + + @include border-radius($alert-border-radius); + + color: #856404; + background-color: #fff3cd; + border-color: #ffeeba; +} + +#Content { + text-align: left; + margin: auto; + padding-left: 20px; +} + +#Content td {} + +#Content .emailTitle { + font-family: $font-family-base; + font-weight: normal; + font-size: $h1-font-size; +} + +#Content .PageTitle { + padding: 5px; + color: $body-color; + font-size: 14px; + font-family: $font-family-base; +} + +#Content .footer td { + padding: 10px; +} + +#Content .footer td.right { + text-align: right; +} + +#Content .typography { + padding: 0px 10px; +} + +#Content .typography a { + font-size: 1em; + text-decoration: underline; +} + +#Content .typography a:hover { + text-decoration: none; +} + +#Content .typography ul { + padding: 2px 15px; +} + +#Content .typography ul li { + padding: 2px 5px; +} + +#Content .typography p { + margin: 0.75em 0em; + color: $body-color; +} + +table#SenderTable .sender, +table#SenderTable .meta { + width: 50%; +} + +table#MetaTable { + margin-left: auto; +} + +table#MetaTable .label { + font-weight: bold; +} + +#ShippingTable td, +#ShippingTable th { + width: 50%; +} + +table.infotable { + border: 1px solid $border-color; + border-collapse: collapse; + width: 100%; + border-top: 1px solid $border-color; + border-bottom: 1px solid $border-color; + background: $body-bg; + margin-top: 10px; +} + +table.infotable td.product.title { + color: $link-color; + font-size: $h3-font-size; + font-weight: normal; + font-family: $font-family-base; +} + +table.infotable tr td, +table.infotable tr th { + padding: 5px; + color: $body-color; + border: 1px solid $border-color; +} + +table.infotable td { + vertical-align: middle; +} + +table.infotable tr.summary { + font-weight: bold; +} + +table.infotable td.ordersummary { + font-size: 1em; + border-bottom: 1px solid $border-color; +} + +table.infotable tr th { + font-weight: bold; +} + +table.infotable tr td a { + color: $link-color; + text-decoration: underline; +} + +table.infotable tr td a:hover { + text-decoration: none; +} + +table.infotable .modifierRow, +table.infotable .threeColHeader { + text-align: right; +} + +table.infotable .right { + text-align: right; +} + +table.infotable .center { + text-align: center; +} + +table.infotable .left, +table.infotable th { + text-align: left; +} diff --git a/app/src/Extensions/AddressExtension.php b/app/src/Extensions/AddressExtension.php new file mode 100644 index 0000000..b2a74cb --- /dev/null +++ b/app/src/Extensions/AddressExtension.php @@ -0,0 +1,29 @@ +push($field); + $fields->remove($field); + } + + $holder->addExtraClass('col-sm-6'); + $fields->push($holder); + } +} \ No newline at end of file diff --git a/app/src/Extensions/SiteConfigExtension.php b/app/src/Extensions/SiteConfigExtension.php index 57f6d8c..30d0fca 100644 --- a/app/src/Extensions/SiteConfigExtension.php +++ b/app/src/Extensions/SiteConfigExtension.php @@ -2,20 +2,24 @@ namespace Site\Extensions; +use SilverStripe\AssetAdmin\Forms\UploadField; +use SilverStripe\Assets\Image; use SilverStripe\Forms\TextareaField; +use SilverStripe\Forms\TextField; use SilverStripe\ORM\DataExtension; use SilverStripe\CMS\Model\SiteTree; use SilverStripe\Forms\FieldList; use SilverStripe\Forms\TreeMultiselectField; +use BetterBrief\GoogleMapField; class SiteConfigExtension extends DataExtension { private static $db = [ 'ExtraCode' => 'Text', - ]; - - private static $has_one = [ - 'PrivacyPolicy' => SiteTree::class, + 'Longitude' => 'Varchar(255)', + 'Latitude' => 'Varchar(255)', + 'MapZoom' => 'Int', + 'MapAPIKey' => 'Varchar(255)' ]; private static $many_many = [ @@ -32,8 +36,29 @@ class SiteConfigExtension extends DataExtension SiteTree::class )); - $tab->push(TreeDropdownField::create('PrivacyPolicyID', 'Select privacy policy page', SiteTree::class)); - $tab->push(TextareaField::create('ExtraCode', 'Extra site-wide HTML code')); + + $mapTab = $fields->findOrMakeTab('Root.GoogleMaps'); + $mapTab->push(TextField::create('MapAPIKey')); + $mapTab->push(TextField::create('MapZoom')); + $mapTab->push(GoogleMapField::create( + $this->owner, + 'Location' + )); + } + + public function getGeoJSON() + { + return '{"type": "MarkerCollection","features": [{"type": "Feature","icon": "",' + .'"properties": {"content": "'.$this->owner->getTitle().'"},"geometry": {"type": "Point",' + .'"coordinates": ['.$this->owner->getField('Longitude').','.$this->owner->getField('Latitude').']}}]}'; + } + + public function DirectionsLink() + { + return '' + .' Get Directions'; } } diff --git a/app/src/Models/CheckoutMapComponent.php b/app/src/Models/CheckoutMapComponent.php new file mode 100644 index 0000000..8c5df20 --- /dev/null +++ b/app/src/Models/CheckoutMapComponent.php @@ -0,0 +1,47 @@ +process($config) + ) + ); + } + + public function validateData(Order $order, array $data) + { + } + + public function setData(Order $order, array $data) + { + } + + public function getData(Order $order) + { + return []; + } +} \ No newline at end of file diff --git a/app/src/Models/CheckoutNoDeliveryConfig.php b/app/src/Models/CheckoutNoDeliveryConfig.php new file mode 100644 index 0000000..af1cb1e --- /dev/null +++ b/app/src/Models/CheckoutNoDeliveryConfig.php @@ -0,0 +1,43 @@ +addComponent(CustomerDetails::create()); + + if (Checkout::member_creation_enabled() && !Security::getCurrentUser()) { + $this->addComponent(Membership::create()); + } + + if (count(GatewayInfo::getSupportedGateways()) > 1) { + $this->addComponent(Payment::create()); + } + + $this->addComponent(Notes::create()); + + $this->addComponent(CheckoutMapComponent::create()); + $this->addComponent(Terms::create()); + } +} \ No newline at end of file diff --git a/app/src/Templates/DeferedRequirements.php b/app/src/Templates/DeferedRequirements.php index 65da24f..3b8fe93 100644 --- a/app/src/Templates/DeferedRequirements.php +++ b/app/src/Templates/DeferedRequirements.php @@ -19,6 +19,7 @@ class DeferedRequirements implements TemplateGlobalProvider private static $version; private static $nojquery = false; private static $nofontawesome = false; + private static $custom_requirements = []; /** * @return array @@ -55,7 +56,19 @@ class DeferedRequirements implements TemplateGlobalProvider DeferedRequirements::loadJS('app.js'); // Class libs - $class = str_replace('\\', '.', get_class(Controller::curr())); + $class = get_class(Controller::curr()); + if(isset($config['custom_requirements'][$class])){ + foreach ($config['custom_requirements'][$class] as $file) { + if(strpos($file,'.css')){ + DeferedRequirements::loadCSS($file); + } + if(strpos($file,'.js')){ + DeferedRequirements::loadJS($file); + } + } + } + + $class = str_replace('\\', '.', $class); $dir = Path::join( Director::publicFolder(), ManifestFileFinder::RESOURCES_DIR, @@ -64,8 +77,8 @@ class DeferedRequirements implements TemplateGlobalProvider 'dist' ); - if (file_exists(Path::join($dir, 'css', '_' . $class . '.css'))) { - DeferedRequirements::loadCSS('_' . $class . '.css'); + if (file_exists(Path::join($dir, 'css', $class . '.css'))) { + DeferedRequirements::loadCSS( $class . '.css'); } if (file_exists(Path::join($dir, 'js', $class . '.js'))) { diff --git a/app/templates/Includes/Content.ss b/app/templates/Includes/Content.ss index 82d353d..309ed0a 100644 --- a/app/templates/Includes/Content.ss +++ b/app/templates/Includes/Content.ss @@ -1,11 +1,11 @@
-

$Title

+

$Title

-
+
$ElementalArea <% if $Form %> -
+
$Form
<% end_if %> @@ -15,6 +15,6 @@ $ExtraCode
<% end_if %> -
+
diff --git a/app/templates/Page.ss b/app/templates/Page.ss index 67d23ce..28c50fd 100644 --- a/app/templates/Page.ss +++ b/app/templates/Page.ss @@ -5,7 +5,7 @@ <% include MetaHead %> - + data-default-lng="$Longitude" data-default-lat="$Latitude"<% end_with %>> <%-- Upgrade your Browser notice --%> @@ -36,6 +36,10 @@ <%-- Require CSS+JS from /public/resourses/[js,css]/[ClassName].[js,css] --%> $AutoRequirements($ClassName).RAW + <%-- Mapbox --%> + + + <%-- place extra requirements after this line --%>
$SiteConfig.ExtraCode diff --git a/app/templates/SilverShop/Cart/Cart.ss b/app/templates/SilverShop/Cart/Cart.ss index cb136b9..6dda45f 100644 --- a/app/templates/SilverShop/Cart/Cart.ss +++ b/app/templates/SilverShop/Cart/Cart.ss @@ -1,5 +1,5 @@ <% if $Items %> - "> +
"> @@ -27,7 +27,7 @@ <% if $Image %> <% end_if %> @@ -54,7 +54,7 @@ $RemoveField <% else %> "> - x + <% end_if %> @@ -111,7 +111,7 @@
<% else %> -

+

<%t SilverShop\Cart\ShoppingCart.NoItems "There are no items in your cart." %> -

+
<% end_if %> diff --git a/app/templates/SilverShop/Includes/AccountNavigation.ss b/app/templates/SilverShop/Includes/AccountNavigation.ss index acc26a3..c853937 100644 --- a/app/templates/SilverShop/Includes/AccountNavigation.ss +++ b/app/templates/SilverShop/Includes/AccountNavigation.ss @@ -1,47 +1,28 @@ -
- -
- <% with $CurrentMember %> -
-
<%t SilverShop\Page\AccountPage.MemberName 'Name' %>
-
$Name
- -
<%t SilverShop\Page\AccountPage.MemberEmail 'Email' %>
-
$Email
- -
<%t SilverShop\Page\AccountPage.MemberSince 'Member Since' %>
-
$Created.Nice
- -
<%t SilverShop\Page\AccountPage.MemberLastVisit 'Last Visit' %>
-
$LastVisited.Nice
- -
<%t SilverShop\Page\AccountPage.NumberOfOrders 'Number of orders' %>
-
<% if $PastOrders %>{$PastOrders.Count}<% else %>0<% end_if %>
-
- <% end_with %> -
-
+ diff --git a/app/templates/SilverShop/Includes/OrderHistory.ss b/app/templates/SilverShop/Includes/OrderHistory.ss index 8dc4193..7442179 100644 --- a/app/templates/SilverShop/Includes/OrderHistory.ss +++ b/app/templates/SilverShop/Includes/OrderHistory.ss @@ -17,7 +17,7 @@ $Items.Quantity $Total.Nice $StatusI18N - + <%t SilverShop\Generic.View 'view' %> diff --git a/app/templates/SilverShop/Model/Order.ss b/app/templates/SilverShop/Model/Order.ss index 249a882..eceafa9 100644 --- a/app/templates/SilverShop/Model/Order.ss +++ b/app/templates/SilverShop/Model/Order.ss @@ -1,8 +1,9 @@ -<% require css("silvershop/core: client/dist/css/order.css") %> +<% require css("app/client/dist/css/order.css") %> <%-- As Order.ss is also used in emails, avoid div, paragraph and heading elements --%> <% include SilverShop\Model\Order_Address %> <% include SilverShop\Model\Order_Content %> + <% if $Total %> <% if $Payments %> <% include SilverShop\Model\Order_Payments %> diff --git a/app/templates/SilverShop/Model/Order_Content_ItemLine.ss b/app/templates/SilverShop/Model/Order_Content_ItemLine.ss index 5cdd758..c43bd02 100644 --- a/app/templates/SilverShop/Model/Order_Content_ItemLine.ss +++ b/app/templates/SilverShop/Model/Order_Content_ItemLine.ss @@ -2,7 +2,7 @@ <% if $Image %> "> - $Buyable.Title + $Buyable.Title <% end_if %> diff --git a/app/templates/SilverShop/Page/Layout/AccountPage.ss b/app/templates/SilverShop/Page/Layout/AccountPage.ss index 778580e..04db297 100644 --- a/app/templates/SilverShop/Page/Layout/AccountPage.ss +++ b/app/templates/SilverShop/Page/Layout/AccountPage.ss @@ -1,21 +1,25 @@ -
+
diff --git a/app/templates/SilverShop/Page/Layout/AccountPage_addressbook.ss b/app/templates/SilverShop/Page/Layout/AccountPage_addressbook.ss index 2d2960c..1485e29 100644 --- a/app/templates/SilverShop/Page/Layout/AccountPage_addressbook.ss +++ b/app/templates/SilverShop/Page/Layout/AccountPage_addressbook.ss @@ -2,72 +2,78 @@ diff --git a/app/templates/SilverShop/Page/Layout/AccountPage_order.ss b/app/templates/SilverShop/Page/Layout/AccountPage_order.ss index 6ff091f..7cd0261 100644 --- a/app/templates/SilverShop/Page/Layout/AccountPage_order.ss +++ b/app/templates/SilverShop/Page/Layout/AccountPage_order.ss @@ -14,6 +14,10 @@ <% with $Order %> <% include SilverShop\Model\Order %> <% end_with %> + + <% with $SiteConfig %> + <% include Objects\Map %> + <% end_with %> $ActionsForm <% end_if %>
diff --git a/app/templates/SilverShop/Page/Layout/CartPage.ss b/app/templates/SilverShop/Page/Layout/CartPage.ss index f5a332d..c9a1927 100644 --- a/app/templates/SilverShop/Page/Layout/CartPage.ss +++ b/app/templates/SilverShop/Page/Layout/CartPage.ss @@ -1,35 +1,37 @@ -
+
<% include Content %> - <% if $Cart %> - - <% if $CartForm %> - $CartForm - <% else %> - <% with $Cart %><% include SilverShop\Cart\Cart Editable=true %><% end_with %> - <% end_if %> - - <% else %> -
<%t SilverShop\Cart\ShoppingCart.NoItems "There are no items in your cart." %>
- <% end_if %> - -
diff --git a/app/templates/SilverShop/Page/Layout/CheckoutPage.ss b/app/templates/SilverShop/Page/Layout/CheckoutPage.ss index e9c73b1..adc6aee 100644 --- a/app/templates/SilverShop/Page/Layout/CheckoutPage.ss +++ b/app/templates/SilverShop/Page/Layout/CheckoutPage.ss @@ -1,14 +1,17 @@ -
+
<% if $PaymentErrorMessage %> +
<%t SilverShop\Page\CheckoutPage.PaymentErrorMessage 'Received error from payment gateway:' %> $PaymentErrorMessage
+
<% end_if %> <% include Content %> +
<% if $Cart %> <% with $Cart %> <% include SilverShop\Cart\Cart ShowSubtotals=true %> @@ -18,5 +21,6 @@ <% else %>
<%t SilverShop\Cart\ShoppingCart.NoItems "There are no items in your cart." %>
<% end_if %> +
diff --git a/package.json b/package.json index 9e55143..d6e1b9d 100755 --- a/package.json +++ b/package.json @@ -33,6 +33,7 @@ "jquery": "^3.3.1", "jquery-hammerjs": "^2.0.0", "jquery-zoom": "^1.7.21", + "mapbox-gl": "^0.48.0", "meta-lightbox": "^1.0.0", "offcanvas-bootstrap": "^2.5.2", "popper.js": "^1.14.3", diff --git a/php.ini b/php.ini new file mode 100644 index 0000000..dfa5d16 --- /dev/null +++ b/php.ini @@ -0,0 +1,4 @@ +date.timezone = "America/New_York" +display_errors = Off +magic_quotes_gpc = Off +expose_php = Off