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 %>
+ aria-current="page"<% end_if %>
+ >
+ <% if not Up.Unlinked %><% end_if %>
+ $MenuTitle.XML
+ <% if not Up.Unlinked %> <% end_if %>
+ <%-- if not $Last %>$Up.Delimiter.RAW<% end_if --%>
+
+ <% 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 %>
-
+
<% 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 @@
-
+
<% 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 %>
-