diff --git a/app/_config/captcha.yml b/app/_config/captcha.yml index 191373a..5e4a6c6 100644 --- a/app/_config/captcha.yml +++ b/app/_config/captcha.yml @@ -1,3 +1,7 @@ +--- +Name: 'app-captcha' +--- + SilverStripe\SpamProtection\Extension\FormSpamProtectionExtension: default_spam_protector: UndefinedOffset\NoCaptcha\Forms\NocaptchaProtector @@ -10,4 +14,4 @@ UndefinedOffset\NoCaptcha\Forms\NocaptchaField: default_size: "normal" #Default size (optional, normal, compact or invisible, defaults to normal) default_badge: "bottomright" #Default badge position (bottomright, bottomleft or inline, defaults to bottomright) proxy_server: "" #Your proxy server address (optional) - proxy_auth: "" #Your proxy server authentication information (optional) \ No newline at end of file + proxy_auth: "" #Your proxy server authentication information (optional) diff --git a/app/_config/columns.yml b/app/_config/columns.yml index c10a689..b4458c5 100644 --- a/app/_config/columns.yml +++ b/app/_config/columns.yml @@ -1,3 +1,7 @@ +--- +Name: 'webapp-columns' +--- + Site\Extensions\ElementRows: container_max_width: 1140 column_class: 'col-block col-md-' diff --git a/app/_config/debugbar.yml b/app/_config/debugbar.yml index b0d38c2..2154cb2 100644 --- a/app/_config/debugbar.yml +++ b/app/_config/debugbar.yml @@ -1,5 +1,5 @@ --- -Name: debugbarext +Name: 'webapp-debugbar' After: - 'framework' - 'debugbar' @@ -9,4 +9,4 @@ Only: LeKoala\DebugBar\DebugBar: enabled_in_admin: false query_limit: 500 - max_header_length: 2048 \ No newline at end of file + max_header_length: 2048 diff --git a/app/_config/elements.yml b/app/_config/elements.yml index f4f9dfd..c9f3166 100644 --- a/app/_config/elements.yml +++ b/app/_config/elements.yml @@ -29,6 +29,7 @@ SilverStripe\CMS\Model\SiteTree: - DNADesign\ElementalVirtual\Model\ElementVirtual DNADesign\ElementalList\Model\ElementList: + inline_editable: false default_global_elements: false allowed_elements: - DNADesign\ElementalList\Model\ElementList @@ -46,9 +47,12 @@ DNADesign\ElementalList\Model\ElementList: noframe: 'No Frame' DNADesign\Elemental\Models\ElementContent: + default_global_elements: false + inline_editable: false extensions: - Site\Extensions\ElementContentWidget Dynamic\Elements\Image\Elements\ElementImage: + inline_editable: false extensions: - Site\Extensions\ElementImageWidget diff --git a/app/_config/extensions.yml b/app/_config/extensions.yml index a65b9f9..59341f3 100644 --- a/app/_config/extensions.yml +++ b/app/_config/extensions.yml @@ -1,16 +1,20 @@ +--- +Name: webapp-extensions +--- +# Basic extensions + +SilverStripe\Admin\LeftAndMain: + extensions: + - Site\Extensions\LeftAndMainExtension + SilverStripe\SiteConfig\SiteConfig: extensions: - Site\Extensions\SiteConfigExtension - - Site\Extensions\SocialExtension -SilverStripe\SiteTree\SiteTree: +SilverStripe\CMS\Model\SiteTree: extensions: - Site\Extensions\SiteTreeExtension -SilverStripe\Blog\Model\BlogPost: - extensions: - - Site\Extensions\BlogPostExtension - Sheadawson\Linkable\Models\EmbeddedObject: extensions: - Site\Extensions\EmbeddedObjectExtension @@ -27,7 +31,7 @@ SilverStripe\Core\Injector\Injector: Sheadawson\Linkable\Forms\EmbeddedObjectField: class: Site\Extensions\EmbedObjectField -# User Forms +# User Forms module SilverStripe\UserForms\Form\UserForm: extensions: - Site\Extensions\PlaceholderFormExtension @@ -39,3 +43,12 @@ SilverStripe\UserForms\Model\UserDefinedForm: DNADesign\ElementalUserForms\Model\ElementForm: extensions: - Site\Extensions\UserDefinedFormExtension + +# Blog + Widgets module extensions +Page: + extensions: + - SilverStripe\Widgets\Extensions\WidgetPageExtension + +SilverStripe\Blog\Model\BlogPost: + extensions: + - Site\Extensions\BlogPostExtension diff --git a/app/_config/googlemapfield.yml b/app/_config/googlemapfield.yml deleted file mode 100644 index 940666d..0000000 --- a/app/_config/googlemapfield.yml +++ /dev/null @@ -1,4 +0,0 @@ -BetterBrief\GoogleMapField: - default_options: - api_key: 'YOUR_API_KEY' - show_search_box: true diff --git a/app/_config/map.yml b/app/_config/map.yml new file mode 100644 index 0000000..ba5a1a2 --- /dev/null +++ b/app/_config/map.yml @@ -0,0 +1,17 @@ +--- +Name: 'webapp-map' +After: + - 'silverstripe-mapboxfield' + - 'addressable' +--- +SilverStripe\Core\Injector\Injector: + A2nt\SilverStripeMapboxField\MarkerExtension: + properties: + geocoder: %$Symbiote\Addressable\MapboxGeocodeService + Symbiote\Addressable\GeocodeServiceInterface: + class: Symbiote\Addressable\MapboxGeocodeService + +Symbiote\Addressable\MapboxGeocodeService: + mapbox_api_key: '' +A2nt\SilverStripeMapboxField\MapboxField: + map_style: 'mapbox://styles/mapbox/streets-v9' #'mapbox://styles/mapbox/light-v10' diff --git a/app/_config/payment.yml b/app/_config/payment.yml index 6bc6630..e00f6b9 100644 --- a/app/_config/payment.yml +++ b/app/_config/payment.yml @@ -1,5 +1,5 @@ --- -Name: payment +Name: 'webapp-payment' --- SilverStripe\Omnipay\Model\Payment: allowed_gateways: diff --git a/app/_config/requirements.yml b/app/_config/requirements.yml index b0e7942..3458929 100644 --- a/app/_config/requirements.yml +++ b/app/_config/requirements.yml @@ -1,3 +1,6 @@ +--- +Name: 'webapp-requirements' +--- Site\Templates\DeferedRequirements: nojquery: false nofontawesome: false diff --git a/app/_config/shop.yml_ b/app/_config/shop.yml_ index a5b9959..e489a8b 100644 --- a/app/_config/shop.yml_ +++ b/app/_config/shop.yml_ @@ -1,5 +1,5 @@ --- -Name: shop +Name: 'webapp-shop' --- SilverStripe\Core\Injector\Injector: SilverShop\Checkout\SinglePageCheckoutComponentConfig: diff --git a/app/_config/themes.yml b/app/_config/themes.yml index e02cde1..247fc5c 100644 --- a/app/_config/themes.yml +++ b/app/_config/themes.yml @@ -1,5 +1,5 @@ --- -Name: webapp-themes +Name: 'webapp-themes' --- SilverStripe\View\SSViewer: diff --git a/app/_config/version-truncator.yml b/app/_config/version-truncator.yml index 3477e43..c11f6a6 100644 --- a/app/_config/version-truncator.yml +++ b/app/_config/version-truncator.yml @@ -1,6 +1,8 @@ +--- +Name: 'webapp-version-truncator' +--- Axllent\VersionTruncator\VersionTruncator: keep_versions: 4 # how many (published) versions of each page to keep keep_drafts: 2 # how many drafts of each page to keep keep_redirects: true # keep page versions that have a different URLSegment (for redirects) keep_old_page_types: false # keep page versions where page type (ClassName) has changed - \ No newline at end of file diff --git a/app/client/src/js/_components/_ui.map.api.js b/app/client/src/js/_components/_ui.map.api.js index f789bf2..1517692 100644 --- a/app/client/src/js/_components/_ui.map.api.js +++ b/app/client/src/js/_components/_ui.map.api.js @@ -1,11 +1,11 @@ 'use strict'; import $ from 'jquery'; -import Events from "../_events"; -import mapBoxGL from "mapbox-gl"; +import Events from '../_events'; +import mapBoxGL from 'mapbox-gl'; //import "./mapStorage"; -import "../../scss/_components/_ui.map.scss"; +import '../../scss/_components/_ui.map.scss'; const W = window; @@ -21,41 +21,45 @@ const MapAPI = (($) => { class MapAPI { // Constructor - constructor(element) { - this._element = element; - const $element = $(this._element); - const geojson = $element.data('geojson'); + constructor(el) { + this._el = el; + const $el = $(this._el); + const config = $el.data(); const center = [ - ($element.data('lng') ? $element.data('lng') : $BODY.data('default-lng')), - ($element.data('lat') ? $element.data('lat') : $BODY.data('default-lat')), + (config['lng'] ? config['lng'] : $BODY.data('default-lng')), + (config['lat'] ? config['lat'] : $BODY.data('default-lat')), ]; - const popup = new mapboxgl.Popup({ + const popup = new mapBoxGL.Popup({ closeOnClick: false, className: 'popup', }); - currentStyle = this.getStyle(); - mapBoxGL.accessToken = $element.data('key'); + currentStyle = this.getStyle(); + mapBoxGL.accessToken = $el.data('key'); Map = new mapBoxGL.Map({ - 'container': $element.find('.mapAPI-map')[0], - 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 - } - } - }*/ - }) + 'container': $el.find('.mapAPI-map')[0], + 'center': center, + //hash: true, + 'style': currentStyle, + 'localIdeographFontFamily': $BODY.css('font-family'), + 'zoom': (config['mapZoom'] ? config['mapZoom'] : 10), + 'attributionControl': false, + 'antialias': true, + /*'pitch': 45, + 'bearing': -17.6*/ + + /*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, })) @@ -66,34 +70,107 @@ const MapAPI = (($) => { }, trackUserLocation: true, }), 'bottom-right') - .addControl(new mapboxgl.ScaleControl({ + .addControl(new mapBoxGL.ScaleControl({ maxWidth: 80, unit: 'metric', - }), 'top-left'); + }), 'top-left') + .addControl(new mapboxgl.FullscreenControl()); + + $el.data('Map', Map); + $el.data('Popup', popup); // event.target Map.on('load', (e) => { + // Insert the layer beneath any symbol layer. + if (config['3d']) { + const layers = Map.getStyle().layers; + let labelLayerId; + for (let i = 0; i < layers.length; i++) { + if (layers[i].type === 'symbol' && layers[i].layout['text-field']) { + labelLayerId = layers[i].id; + break; + } + } + + Map.addLayer({ + 'id': '3d-buildings', + 'source': 'composite', + 'source-layer': 'building', + 'filter': ['==', 'extrude', 'true'], + 'type': 'fill-extrusion', + 'minzoom': 15, + 'paint': { + 'fill-extrusion-color': '#aaa', + + // use an 'interpolate' expression to add a smooth transition effect to the + // buildings as the user zooms in + 'fill-extrusion-height': [ + "interpolate", ["linear"], + ["zoom"], + 15, 0, + 15.05, ["get", "height"] + ], + 'fill-extrusion-base': [ + "interpolate", ["linear"], + ["zoom"], + 15, 0, + 15.05, ["get", "min_height"] + ], + 'fill-extrusion-opacity': .6 + } + }, labelLayerId); + } + + const firstMarker = config['geojson'].features[0].geometry.coordinates; + //Map.setCenter(firstMarker); + const bounds = new mapBoxGL.LngLatBounds(firstMarker, firstMarker); + // add markers to map - geojson.features.forEach((marker) => { - // create a DOM element for the marker - const $el = $(`
${ marker.icon }
`); + config['geojson'].features.forEach((marker) => { + const id = marker.id; + const crds = marker.geometry.coordinates; + const content = marker.properties.content; + + // create a DOM el for the marker + const $el = $(`
${ marker.icon }
`); $el.on('click', () => { - console.log('Marker click'); - const coordinates = marker.geometry.coordinates; - const content = marker.properties.content; - console.log(popup); - popup.setLngLat(coordinates) + popup.setLngLat(crds) .setHTML(content) .addTo(Map); + + if (config['flyToMarker']) { + Map.flyTo({ + center: crds, + zoom: 17, + }); + } + + $el.trigger(Events.MAPMARKERCLICK); }); // add marker to map - new mapboxgl.Marker($el[0]) - .setLngLat(marker.geometry.coordinates) + new mapBoxGL.Marker($el[0]) + .setLngLat(crds) .addTo(Map); + bounds.extend(crds); }); + Map.fitBounds(bounds, { + padding: 30, + }); + + popup.on('close', (e) => { + if (config['flyToBounds']) { + Map.fitBounds(bounds, { + padding: 30, + }); + } + $el.trigger(Events.MAPPOPUPCLOSE); + }); + + $el.trigger(Events.MAPLOADED); + $(W).trigger(Events.MAPLOADED); console.log('Map is loaded'); }); @@ -124,7 +201,7 @@ const MapAPI = (($) => { }, 36000); - $element.addClass(`${NAME}-active`); + $el.addClass(`${NAME}-active`); } // Public methods @@ -133,36 +210,37 @@ const MapAPI = (($) => { } getStyle() { + const $el = $(this._el); + return $el.data('map-style'); 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'; } + // day + return 'mapbox://styles/mapbox/streets-v9'; } dispose() { - const $element = $(this._element); + const $el = $(this._el); - $element.removeClass(`${NAME}-active`); - $.removeData(this._element, DATA_KEY); - this._element = null; + $el.removeClass(`${NAME}-active`); + $.removeData(this._el, DATA_KEY); + this._el = 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); + // attach functionality to el + const $el = $(this); + let data = $el.data(DATA_KEY); if (!data) { data = new MapAPI(this); - $element.data(DATA_KEY, data); + $el.data(DATA_KEY, data); } }); } diff --git a/app/client/src/js/_components/_ui.menu.js b/app/client/src/js/_components/_ui.menu.js index 44c6c88..8e52cea 100644 --- a/app/client/src/js/_components/_ui.menu.js +++ b/app/client/src/js/_components/_ui.menu.js @@ -7,37 +7,37 @@ const SlidingMenu = (($) => { class SlidingMenu { // Constructor - constructor(element) { - this._element = element; - const $element = $(this._element); - $element.addClass(`${NAME}-active`); + constructor(el) { + const $el = $(this._el); + this.$el = $el; + $el.addClass(`${NAME}-active`); // esc button - $(window).on('keyup',((e) => { + $(window).on('keyup', ((e) => { if (e.which === 27) { - $element.find('.is-open[data-toggle="offcanvas"]').click(); + $el.find('.is-open[data-toggle="offcanvas"]').click(); } })); } // Public methods dispose() { - console.log(`Disposing: ${NAME} elements`); + console.log(`Disposing: ${NAME} els`); - $(this._element).removeClass(`${NAME}-active`); - $.removeData(this._element, DATA_KEY); - this._element = null; + this.$el.removeClass(`${NAME}-active`); + $.removeData(this.$el, DATA_KEY); + this.$el = null; } static _jQueryInterface() { - return this.each(function () { - // attach functionality to element - const $element = $(this); - let data = $element.data(DATA_KEY); + return this.each(function() { + // attach functionality to el + const $el = $(this); + let data = $el.data(DATA_KEY); if (!data) { data = new SlidingMenu(this); - $element.data(DATA_KEY, data); + $el.data(DATA_KEY, data); } }); } @@ -46,7 +46,7 @@ const SlidingMenu = (($) => { // jQuery interface $.fn[NAME] = SlidingMenu._jQueryInterface; $.fn[NAME].Constructor = SlidingMenu; - $.fn[NAME].noConflict = function () { + $.fn[NAME].noConflict = function() { $.fn[NAME] = JQUERY_NO_CONFLICT; return SlidingMenu._jQueryInterface; }; diff --git a/app/client/src/js/_events.js b/app/client/src/js/_events.js index 5c0ed2e..c962402 100644 --- a/app/client/src/js/_events.js +++ b/app/client/src/js/_events.js @@ -5,6 +5,9 @@ module.exports = { AJAX: 'ajax-load', LOADED: 'load', + MAPLOADED: 'map-loaded', + MAPMARKERCLICK: 'map-marker-click', + MAPPOPUPCLOSE: 'map-popup-close', SET_TARGET_UPDATE: 'set-target-update', RESTORE_FIELD: 'restore-field', FORM_INIT_BASICS: 'form-basics', diff --git a/app/client/src/js/_main.js b/app/client/src/js/_main.js index 57f424f..c0ccb8f 100644 --- a/app/client/src/js/_main.js +++ b/app/client/src/js/_main.js @@ -15,20 +15,40 @@ import './_components/routes/index'; import Events from './_events'; import Spinner from './_components/_ui.spinner'; +// youtube video preview image import './_components/_ui.video.preview'; + import './_components/_ui.carousel'; import './_components/_ui.menu'; +// Bootstrap hover menu +import './_components/_ui.hover'; + import FormBasics from './_components/_ui.form.basics'; + +// Toggle bootstrap form fields //import FormToggleUI from './_components/_ui.form.fields.toggle'; + +// Bootstrap Date & Time fields //import FormDatetime from './_components/_ui.form.datetime'; -import FormStepped from './_components/_ui.form.stepped'; + +// Stepped forms functionality +//import FormStepped from './_components/_ui.form.stepped'; + +// Forms validation functionality import FormValidate from './_components/_ui.form.validate'; + +// Store forms data into localStorage import FormStorage from './_components/_ui.form.storage'; + +// client-side images cropping //import FormCroppie from './_components/_ui.form.croppie'; +// AJAX functionality import AjaxUI from './_components/_ui.ajax'; + +// Google NoCaptcha fields import NoCaptcha from './_components/_ui.nocaptcha'; import SmoothScroll from 'smooth-scroll'; diff --git a/app/client/src/js/_pageType_and_component_template.js b/app/client/src/js/_pageType_and_component_template.js deleted file mode 100644 index d43863e..0000000 --- a/app/client/src/js/_pageType_and_component_template.js +++ /dev/null @@ -1,92 +0,0 @@ -import $ from 'jquery'; - -const TypePage = (($) => { - // Constants - const NAME = 'TypePage'; - // const DATA_KEY = "pageUI." + NAME; - - const Events = require('./_events'); - - class TypePage { - // Static methods - static init() { - console.log(`Initializing: ${NAME}`); - } - - static destroy() { - console.log(`Destroying: ${NAME}`); - } - - /** - * jQuery extension functions - // Constructor - constructor(element) { - console.log("Constructing: " + NAME + " elements"); - - this._element = element; - } - - // Public methods - dispose() { - console.log("Disposing: " + NAME + " elements"); - - $.removeData(this._element, DATA_KEY); - this._element = null; - } - - static _jQueryInterface() { - return this.each(function () { - // attach functionality to element - const $element = $(this); - let data = $element.data(DATA_KEY); - - if (!data) { - data = new TypePage(this); - $element.data(DATA_KEY, data); - } - }) - } - */ - } - - $(window).on(`${Events.AJAX} ${Events.LOADED}`, () => { - TypePage.init(); - }); - - // JQuery extension functions - /* - $.fn[NAME] = TypePage._jQueryInterface; - $.fn[NAME].Constructor = TypePage; - $.fn[NAME].noConflict = function () { - $.fn[NAME] = JQUERY_NO_CONFLICT; - return TypePage._jQueryInterface; - }; - // auto-apply - $(".ui." + NAME).ready(function(){ - $(".ui." + NAME).TypePage(); - }); */ - - return TypePage; -})($); - -export default TypePage; - - -/* -import $ from 'jquery'; - -(function (G) { - G.initPulsePage = function () { - G.destroyPulsePage(); - }; - - G.destroyPulsePage = function () {}; - - $(window).on("ajax-content-loaded", function () { - G.initPulsePage(); - }); - - $(document).ready(function () { - G.initPulsePage(); - }); -}(this)); */ diff --git a/app/client/src/js/app.js b/app/client/src/js/app.js index f23e37b..3f9ed37 100644 --- a/app/client/src/js/app.js +++ b/app/client/src/js/app.js @@ -7,10 +7,7 @@ import 'bootstrap/js/dist/alert'; import 'bootstrap/js/dist/button'; import 'bootstrap/js/dist/carousel'; import 'bootstrap/js/dist/collapse'; - -// conflicting with bootstrap-select/dist/js/bootstrap-select import 'bootstrap/js/dist/dropdown'; - import 'bootstrap/js/dist/modal'; import 'bootstrap/js/dist/tooltip'; import 'bootstrap/js/dist/popover'; @@ -18,14 +15,12 @@ import 'bootstrap/js/dist/scrollspy'; import 'bootstrap/js/dist/tab'; // -//import Vue from 'vue/dist/vue.esm.js'; - -// import Bootstrap-Vue -/*import { Carousel } from 'bootstrap-vue/es/components'; -Vue.use(Carousel);*/ +// Offcanvas menu import 'offcanvas-bootstrap/dist/js/bootstrap.offcanvas'; -import 'jquery-zoom/jquery.zoom'; + +// Uncomment it to enable meta-lightbox zooming on hover +//import 'jquery-zoom/jquery.zoom'; import 'meta-lightbox/meta-lightbox'; import './_main'; diff --git a/app/client/src/scss/_components/_ui.main.scss b/app/client/src/scss/_components/_ui.main.scss index 21582e6..9582a87 100644 --- a/app/client/src/scss/_components/_ui.main.scss +++ b/app/client/src/scss/_components/_ui.main.scss @@ -146,22 +146,36 @@ button, input, optgroup, select, textarea, } // dropdown hover +/* +.dropdown.show { + .dropdown { + &:hover, + &:focus { + .dropdown-menu { + display: block; + } + } + } +} @media only screen and (min-width: map-get($grid-breakpoints, "md")) { - .dropdown-hover .collapse ul li { + .dropdown-hover ul li { position: relative; } - .dropdown-hover .collapse ul li:hover { - > .dropdown-toggle::after { - transform: rotate(-90deg); - } + .dropdown-hover ul li { + &:hover, + &:focus { + > .dropdown-toggle::after { + transform: rotate(-90deg); + } - > ul { - display: block; + > ul { + display: block; + } } } - .dropdown-hover .collapse ul ul { + .dropdown-hover ul ul { position: absolute; top: 100%; left: 0; @@ -169,16 +183,20 @@ button, input, optgroup, select, textarea, display: none; } - /*******/ - .dropdown-hover .collapse ul ul li { + .dropdown-hover ul ul li { position: relative; } - .dropdown-hover .collapse ul ul li:hover > ul { - display: block; + .dropdown-hover ul ul li { + &:hover, + &:focus { + > ul { + display: block; + } + } } - .dropdown-hover .collapse ul ul ul { + .dropdown-hover ul ul ul { position: absolute; top: 0; left: 100%; @@ -186,16 +204,20 @@ button, input, optgroup, select, textarea, display: none; } - /*******/ - .dropdown-hover .collapse ul ul ul li { + .dropdown-hover ul ul ul li { position: relative; } - .dropdown-hover .collapse ul ul ul li:hover ul { - display: block; + .dropdown-hover ul ul ul li { + &:hover, + &:focus { + ul { + display: block; + } + } } - .dropdown-hover .collapse ul ul ul ul { + .dropdown-hover ul ul ul ul { position: absolute; top: 0; left: -100%; @@ -203,9 +225,28 @@ button, input, optgroup, select, textarea, display: none; z-index: 1; } -} +}*/ // dark dropdowns +.navbar-dark { + .nav-link { + @include hover-focus { + background: $navbar-dark-hover-background; + } + } + + .active > .nav-link, + .nav-link.active { + background: $navbar-dark-active-background; + } + + .nav-link.show, + .navbar-nav .show > .nav-link { + background: $navbar-dark-show-background; + color: $navbar-dark-show-color; + } +} + .dropdown-menu.bg-dark { border-color: $dark; @@ -231,8 +272,37 @@ button, input, optgroup, select, textarea, .dropdown-item { @include hover-focus { - color: $navbar-dark-brand-hover-color; - background: $dark; + color: $navbar-dark-hover-color; + background: $navbar-dark-hover-background; + } + + + &.active, + &:active { + background: $navbar-dark-active-background; + } + + .nav-link { + background: none; } } } + +// pulse +.pulse { + animation: pulse 0.8s linear infinite; +} + +@keyframes pulse { + 0% { + transform: scale(1); + } + + 50% { + transform: scale(0.8); + } + + 100% { + transform: scale(1); + } +} diff --git a/app/client/src/scss/_components/_ui.map.scss b/app/client/src/scss/_components/_ui.map.scss index 8b24d61..abf817e 100644 --- a/app/client/src/scss/_components/_ui.map.scss +++ b/app/client/src/scss/_components/_ui.map.scss @@ -6,10 +6,30 @@ margin-bottom: 1rem; } +.mapboxgl-popup-content { + box-shadow: 0px 4px 10px 0px rgba(0, 0, 0, 0.4); + + .mapboxgl-popup-close-button { + font-size: 2rem; + padding: .5rem; + + &:hover, + &:focus { + background: $primary; + color: $white; + } + } +} + .mapboxgl-marker { width: 30px; height: 30px; font-size: 30px; cursor: pointer; text-align: center; + color: $primary; + + .fas { + animation: pulse 0.8s linear infinite; + } } diff --git a/app/client/src/scss/_layout.scss b/app/client/src/scss/_layout.scss index af74152..abb60c7 100644 --- a/app/client/src/scss/_layout.scss +++ b/app/client/src/scss/_layout.scss @@ -55,6 +55,10 @@ body.shrink {} } } + &.dynamic__elements__image__elements__elementimage { + text-align: center; + } + &.site__elements__accordion { .card { padding-left: 0; diff --git a/app/client/src/scss/_typography.scss b/app/client/src/scss/_typography.scss index 91df2db..0f0fd4e 100644 --- a/app/client/src/scss/_typography.scss +++ b/app/client/src/scss/_typography.scss @@ -4,14 +4,16 @@ h1, h2, h3, h4, h5, h6, } .bg-dark { - h1, h2, h3, h4, h5, h6, - .h1, .h2, .h3, .h4, .h5, .h6, - .typography, - a { - color: $white; - } + h1, h2, h3, h4, h5, h6, + .h1, .h2, .h3, .h4, .h5, .h6, + .typography, + a { + color: $white; + } } .typography { + @include clearfix; + @import "./types/editor"; } diff --git a/app/src/Extensions/ElementContentWidget.php b/app/src/Extensions/ElementContentWidget.php index 8687582..707f4ff 100644 --- a/app/src/Extensions/ElementContentWidget.php +++ b/app/src/Extensions/ElementContentWidget.php @@ -8,7 +8,6 @@ namespace Site\Extensions; - use Sheadawson\Linkable\Forms\LinkField; use Sheadawson\Linkable\Models\Link; use SilverStripe\FontAwesome\FontAwesomeField; @@ -29,13 +28,9 @@ class ElementContentWidget extends DataExtension { parent::updateCMSFields($fields); - $tab = $fields->findOrMakeTab('Root.Main'); - $tab->push( - FontAwesomeField::create('BlockIcon') - ); - - $tab->push( - LinkField::create('BlockLinkID', 'Link') - ); + $fields->addFieldsToTab('Root.Main', [ + FontAwesomeField::create('BlockIcon'), + LinkField::create('BlockLinkID', 'Link'), + ]); } -} \ No newline at end of file +} diff --git a/app/src/Extensions/ElementImageWidget.php b/app/src/Extensions/ElementImageWidget.php index a81694c..102989d 100644 --- a/app/src/Extensions/ElementImageWidget.php +++ b/app/src/Extensions/ElementImageWidget.php @@ -12,6 +12,7 @@ use Dynamic\Elements\Image\Elements\ElementImage; use Sheadawson\Linkable\Forms\LinkField; use Sheadawson\Linkable\Models\Link; use SilverStripe\Core\Config\Config; +use SilverStripe\Forms\CheckboxField; use SilverStripe\Forms\DropdownField; use SilverStripe\Forms\FieldList; use SilverStripe\ORM\DataExtension; @@ -25,6 +26,7 @@ class ElementImageWidget extends DataExtension ]; private static $db = [ + 'Resize' => 'Boolean(1)', 'ImageHeight' => 'Float', 'Content' => 'HTMLText', ]; @@ -45,6 +47,12 @@ class ElementImageWidget extends DataExtension $this->owner->ImageHeight = $this->getHeight(); $heights = Config::inst()->get(__CLASS__, 'available_heights'); + + $fields->replaceField('Resize', CheckboxField::create( + 'Resize', + 'Would you like to scale image?' + )); + if (count($heights)) { $fields->replaceField( 'ImageHeight', @@ -53,7 +61,9 @@ class ElementImageWidget extends DataExtension 'Image Height', $heights, $this->getHeight() - )->setEmptyString('(unspecified)') + ) + ->setEmptyString('(unspecified)') + ->displayIf('Resize')->isChecked()->end() ); } else { $fields->dataFieldByName('ImageHeight') @@ -64,6 +74,11 @@ class ElementImageWidget extends DataExtension public function ImageResized() { $image = $this->owner->Image(); + + if (!$this->owner->Resize) { + return $image; + } + $width = $this->getWidth(); $height = $this->getHeight(); diff --git a/app/src/Extensions/LeftAndMainExtension.php b/app/src/Extensions/LeftAndMainExtension.php new file mode 100644 index 0000000..dd22b81 --- /dev/null +++ b/app/src/Extensions/LeftAndMainExtension.php @@ -0,0 +1,13 @@ + 'Text', - 'Longitude' => 'Varchar(255)', - 'Latitude' => 'Varchar(255)', + 'Longitude' => 'Decimal(10, 8)', + 'Latitude' => 'Decimal(11, 8)', 'MapZoom' => 'Int', - 'MapAPIKey' => 'Varchar(255)', + //'MapAPIKey' => 'Varchar(255)', 'Description' => 'Varchar(255)', ]; @@ -37,40 +38,49 @@ class SiteConfigExtension extends DataExtension public function updateCMSFields(FieldList $fields) { - $tab = $fields->findOrMakeTab('Root.Main'); + $fields->addFieldsToTab('Root.Main', [ + TreeMultiselectField::create( + 'Navigation', + 'Navigation', + SiteTree::class + ), + TextareaField::create('Description', 'Website Description'), + TextareaField::create('ExtraCode', 'Extra site-wide HTML code'), + DropdownField::create( + 'PrivacyPolicyID', + 'Privacy Policy Page', + SiteTree::get()->map()->toArray() + ), + DropdownField::create( + 'SitemapID', + 'Sitemap Page', + SitemapPage::get()->map()->toArray() + ), + ]); - $tab->push(TreeMultiselectField::create( - 'Navigation', - 'Navigation', - SiteTree::class - )); - - $tab->push(TextareaField::create('ExtraCode', 'Extra site-wide HTML code')); - - $tab->push(DropdownField::create( - 'PrivacyPolicyID', - 'Privacy Policy Page', - SiteTree::get()->map()->toArray() - )); - - $tab->push(DropdownField::create( - 'SitemapID', - 'Sitemap Page', - SitemapPage::get()->map()->toArray() - )); - - $tab->push(TextareaField::create('Description', 'Website Description')); - - $mapTab = $fields->findOrMakeTab('Root.GoogleMaps'); - $mapTab->push(TextField::create('MapAPIKey')); - $mapTab->push(TextField::create('MapZoom')); - $mapTab->push(GoogleMapField::create( + $mapTab = $fields->findOrMakeTab('Root.Maps'); + $fields->addFieldsToTab('Root.Maps', [ + //TextField::create('MapAPIKey'), + TextField::create('MapZoom'), + MapboxField::create('Map', 'Choose a location', 'Latitude', 'Longitude'), + ]); + /*GoogleMapField::create( $this->owner, 'Location', [ 'show_search_box' => true, ] - )); + )*/ + } + + public function MapAPIKey() + { + return MapboxField::config()->get('access_token'); + } + + public function MapStyle() + { + return MapboxField::config()->get('map_style'); } public function getGeoJSON() diff --git a/app/src/Extensions/SiteTreeExtension.php b/app/src/Extensions/SiteTreeExtension.php index a571b3a..1a8d5af 100644 --- a/app/src/Extensions/SiteTreeExtension.php +++ b/app/src/Extensions/SiteTreeExtension.php @@ -18,11 +18,11 @@ class SiteTreeExtension extends DataExtension public function updateCMSFields(FieldList $fields) { - $tab = $fields->findOrMakeTab('Root.Settings'); - - $tab->push(Textarea::create( - 'ExtraCode', - 'Extra page specific HTML code' - )); + $fields->addFieldsToTab('Root.Settings', [ + TextareaField::create( + 'ExtraCode', + 'Extra page specific HTML code' + ), + ]); } } diff --git a/app/src/Pages/Page.php b/app/src/Pages/Page.php index 1b9b299..d1365cd 100644 --- a/app/src/Pages/Page.php +++ b/app/src/Pages/Page.php @@ -38,4 +38,9 @@ class Page extends SiteTree return false; } + + public function CSSClass() + { + return str_replace(['\\'], '-', $this->getField('ClassName')); + } } diff --git a/app/templates/BreadcrumbsTemplate.ss b/app/templates/BreadcrumbsTemplate.ss index ccfafd2..8289fc6 100644 --- a/app/templates/BreadcrumbsTemplate.ss +++ b/app/templates/BreadcrumbsTemplate.ss @@ -1,16 +1,21 @@ <% if $Pages %> - + <% loop $Pages %> + + <% end_loop %> + + <% end_if %> diff --git a/app/templates/Dynamic/Elements/Image/Elements/ElementImage.ss b/app/templates/Dynamic/Elements/Image/Elements/ElementImage.ss index 60a9b9a..fa37597 100644 --- a/app/templates/Dynamic/Elements/Image/Elements/ElementImage.ss +++ b/app/templates/Dynamic/Elements/Image/Elements/ElementImage.ss @@ -1,11 +1,12 @@ <% if $ImageResized %> -
+
<% if $ImageLink %><% end_if %> - $Title.ATT + $Title.ATT <% if $ImageLink %><% end_if %>
<% end_if %> +<% if $ShowTitle || $Content || $ImageLink %>
<% if $ShowTitle %>

$Title

<% end_if %> @@ -21,4 +22,5 @@ <% end_if %>
-
\ No newline at end of file +
+<% end_if %> diff --git a/app/templates/Includes/Content.ss b/app/templates/Includes/Content.ss index 59b2378..742034d 100644 --- a/app/templates/Includes/Content.ss +++ b/app/templates/Includes/Content.ss @@ -1,5 +1,5 @@
-

$Title

+

$Title

<% if $CurrentElement %> diff --git a/app/templates/Includes/NavItem.ss b/app/templates/Includes/NavItem.ss index 6899a43..03c66f1 100644 --- a/app/templates/Includes/NavItem.ss +++ b/app/templates/Includes/NavItem.ss @@ -1,5 +1,5 @@ <% if $Children %> - <% else %> -