mirror of
https://github.com/a2nt/silverstripe-webpack.git
synced 2024-10-22 17:05:31 +02:00
Video shortcodes, Webpack Image compression, other improvements
This commit is contained in:
parent
75ef9f569f
commit
fdcc1be513
@ -3,7 +3,10 @@
|
|||||||
use SilverStripe\Forms\HTMLEditor\HtmlEditorConfig;
|
use SilverStripe\Forms\HTMLEditor\HtmlEditorConfig;
|
||||||
use SilverStripe\Core\Manifest\ModuleResourceLoader;
|
use SilverStripe\Core\Manifest\ModuleResourceLoader;
|
||||||
use SilverStripe\ORM\Search\FulltextSearchable;
|
use SilverStripe\ORM\Search\FulltextSearchable;
|
||||||
|
use SilverStripe\View\Parsers\ShortcodeParser;
|
||||||
|
use Site\Extensions\EmbedShortcodeProvider;
|
||||||
|
|
||||||
|
// setup TinyMCE editor
|
||||||
$config = HtmlEditorConfig::get('cms');
|
$config = HtmlEditorConfig::get('cms');
|
||||||
$config->enablePlugins([
|
$config->enablePlugins([
|
||||||
'template',
|
'template',
|
||||||
@ -29,3 +32,9 @@ $config->setOption(
|
|||||||
);
|
);
|
||||||
|
|
||||||
FulltextSearchable::enable();
|
FulltextSearchable::enable();
|
||||||
|
|
||||||
|
// replace embed parser
|
||||||
|
$parser = ShortcodeParser::get('default');
|
||||||
|
$parser->unregister('embed');
|
||||||
|
$parser->register('embed', [EmbedShortcodeProvider::class, 'handle_shortcode']);
|
||||||
|
|
||||||
|
@ -7,6 +7,8 @@ Site\Templates\DeferredRequirements:
|
|||||||
version: false
|
version: false
|
||||||
static_domain: false
|
static_domain: false
|
||||||
deferred: true
|
deferred: true
|
||||||
|
jquery_version: '3.4.1'
|
||||||
|
fontawesome_version: '5.10.2'
|
||||||
|
|
||||||
SilverStripe\View\Requirements:
|
SilverStripe\View\Requirements:
|
||||||
disable_flush_combined: true
|
disable_flush_combined: true
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
"use strict";
|
import $ from 'jquery';
|
||||||
|
import './_consts';
|
||||||
import '../scss/app.scss';
|
|
||||||
|
|
||||||
// import Bootstrap
|
// import Bootstrap
|
||||||
import 'popper.js';
|
import 'popper.js';
|
||||||
@ -9,21 +8,7 @@ import 'bootstrap/js/dist/alert';
|
|||||||
import 'bootstrap/js/dist/button';
|
import 'bootstrap/js/dist/button';
|
||||||
import 'bootstrap/js/dist/carousel';
|
import 'bootstrap/js/dist/carousel';
|
||||||
import 'bootstrap/js/dist/collapse';
|
import 'bootstrap/js/dist/collapse';
|
||||||
|
import 'bootstrap/js/dist/dropdown';
|
||||||
import 'hammerjs/hammer';
|
|
||||||
import 'jquery-hammerjs/jquery.hammer';
|
|
||||||
|
|
||||||
// Routie
|
|
||||||
//import 'pouchdb/dist/pouchdb';
|
|
||||||
//import '@a2nt/ss-bootstrap-ui-webpack-boilerplate/src/js/_components/routes/index';
|
|
||||||
|
|
||||||
// conflicts with _components/_ui.hover.js (shows dropdown on hover)
|
|
||||||
//import 'bootstrap/js/dist/dropdown';
|
|
||||||
import '@a2nt/ss-bootstrap-ui-webpack-boilerplate/src/js/_components/_ui.hover';
|
|
||||||
|
|
||||||
import '@a2nt/ss-bootstrap-ui-webpack-boilerplate/src/js/_components/_ui.carousel';
|
|
||||||
import '@a2nt/ss-bootstrap-ui-webpack-boilerplate/src/js/_components/_ui.menu';
|
|
||||||
|
|
||||||
import 'bootstrap/js/dist/modal';
|
import 'bootstrap/js/dist/modal';
|
||||||
import 'bootstrap/js/dist/tooltip';
|
import 'bootstrap/js/dist/tooltip';
|
||||||
import 'bootstrap/js/dist/popover';
|
import 'bootstrap/js/dist/popover';
|
||||||
@ -31,57 +16,37 @@ import 'bootstrap/js/dist/scrollspy';
|
|||||||
import 'bootstrap/js/dist/tab';
|
import 'bootstrap/js/dist/tab';
|
||||||
//
|
//
|
||||||
|
|
||||||
import Spinner from '@a2nt/ss-bootstrap-ui-webpack-boilerplate/src/js/_components/_ui.spinner';
|
|
||||||
//import Multislider from '@a2nt/ss-bootstrap-ui-webpack-boilerplate/src/js/_components/_ui.multislider';
|
|
||||||
|
|
||||||
// Flyout UI
|
|
||||||
//import Flyout from '@a2nt/ss-bootstrap-ui-webpack-boilerplate/src/js/_components/_ui.flyout';
|
|
||||||
|
|
||||||
// Offcanvas menu
|
// Offcanvas menu
|
||||||
//import 'offcanvas-bootstrap/dist/js/bootstrap.offcanvas';
|
//import 'offcanvas-bootstrap/dist/js/bootstrap.offcanvas';
|
||||||
|
|
||||||
|
import '../scss/app.scss';
|
||||||
|
|
||||||
|
import '@a2nt/meta-lightbox/src/js/meta-lightbox';
|
||||||
|
// youtube video preview image
|
||||||
|
import '@a2nt/ss-bootstrap-ui-webpack-boilerplate/src/js/_components/_ui.video.preview';
|
||||||
|
|
||||||
|
// MainUI
|
||||||
|
import '@a2nt/ss-bootstrap-ui-webpack-boilerplate/src/js/_main';
|
||||||
|
|
||||||
// Uncomment it to enable meta-lightbox zooming on hover
|
// Uncomment it to enable meta-lightbox zooming on hover
|
||||||
//import 'jquery-zoom/jquery.zoom';
|
//import 'jquery-zoom/jquery.zoom';
|
||||||
|
|
||||||
// Toggle bootstrap form fields
|
// Forms UI
|
||||||
//import FormToggleUI from '@a2nt/ss-bootstrap-ui-webpack-boilerplate/src/js/_components/_ui.form.fields.toggle';
|
import '@a2nt/ss-bootstrap-ui-webpack-boilerplate/src/js/_components/_ui.form.basics';
|
||||||
|
import '@a2nt/ss-bootstrap-ui-webpack-boilerplate/src/js/_components/_ui.form.validate';
|
||||||
// Bootstrap Date & Time fields
|
import '@a2nt/ss-bootstrap-ui-webpack-boilerplate/src/js/_components/_ui.form.stepped';
|
||||||
//import FormDatetime from '@a2nt/ss-bootstrap-ui-webpack-boilerplate/src/js/_components/_ui.form.datetime';
|
|
||||||
|
|
||||||
// Stepped forms functionality
|
|
||||||
//import FormStepped from '@a2nt/ss-bootstrap-ui-webpack-boilerplate/src/js/_components/_ui.form.stepped';
|
|
||||||
|
|
||||||
// Forms validation functionality
|
|
||||||
//import FormValidate from '@a2nt/ss-bootstrap-ui-webpack-boilerplate/src/js/_components/_ui.form.validate';
|
|
||||||
|
|
||||||
// Store forms data into localStorage
|
|
||||||
//import FormStorage from '@a2nt/ss-bootstrap-ui-webpack-boilerplate/src/js/_components/_ui.form.storage';
|
|
||||||
|
|
||||||
// client-side images cropping
|
|
||||||
//import FormCroppie from '@a2nt/ss-bootstrap-ui-webpack-boilerplate/src/js/_components/_ui.form.croppie';
|
|
||||||
|
|
||||||
// Google NoCaptcha fields
|
|
||||||
//import NoCaptcha from '@a2nt/ss-bootstrap-ui-webpack-boilerplate/src/js/_components/_ui.nocaptcha';
|
|
||||||
|
|
||||||
// youtube video preview image
|
|
||||||
import '@a2nt/ss-bootstrap-ui-webpack-boilerplate/src/js/_components/_ui.video.preview';
|
|
||||||
|
|
||||||
// Meta Lightbox
|
|
||||||
import '@a2nt/meta-lightbox/src/js/index';
|
|
||||||
|
|
||||||
//import Confirmation from 'bootstrap-confirmation2/dist/bootstrap-confirmation';
|
|
||||||
//import Table from 'bootstrap-table/dist/bootstrap-table';
|
|
||||||
|
|
||||||
// AJAX UI
|
|
||||||
//import AjaxUI from '@a2nt/ss-bootstrap-ui-webpack-boilerplate/src/js/_components/_ui.ajax';
|
|
||||||
|
|
||||||
import '@a2nt/ss-bootstrap-ui-webpack-boilerplate/src/js/_main';
|
|
||||||
import './_layout';
|
|
||||||
|
|
||||||
|
// Import fonts and images
|
||||||
function importAll(r) {
|
function importAll(r) {
|
||||||
return r.keys().map(r);
|
return r.keys().map(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
const images = importAll(require.context('../img/', false, /\.(png|jpe?g|svg)$/));
|
const images = importAll(
|
||||||
const fontAwesome = importAll(require.context('font-awesome', false, /\.(otf|eot|svg|ttf|woff|woff2)$/));
|
require.context('../img/', false, /\.(png|jpe?g|svg)$/),
|
||||||
|
);
|
||||||
|
const fontAwesome = importAll(
|
||||||
|
require.context('font-awesome', false, /\.(otf|eot|svg|ttf|woff|woff2)$/),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Your custom JS
|
||||||
|
import './_layout';
|
||||||
|
@ -10,27 +10,29 @@
|
|||||||
|
|
||||||
.bootstrap-select .dropdown-toggle .filter-option .option {
|
.bootstrap-select .dropdown-toggle .filter-option .option {
|
||||||
background: #dedede;
|
background: #dedede;
|
||||||
padding: .2rem .5rem;
|
padding: 0.2rem 0.5rem;
|
||||||
margin: .2rem;
|
margin: 0.2rem;
|
||||||
color: #212529;
|
color: #212529;
|
||||||
}
|
}
|
||||||
|
|
||||||
// shrink elements on scroll
|
// shrink elements on scroll
|
||||||
body.shrink {}
|
body.shrink {
|
||||||
|
}
|
||||||
|
|
||||||
// sticky footer
|
// sticky footer
|
||||||
@media (min-width: map-get($grid-breakpoints, "sm")) {
|
@media (min-width: map-get($grid-breakpoints, 'sm')) {
|
||||||
html, body {
|
html,
|
||||||
|
body {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
min-height: 100%;
|
min-height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wrapper {
|
.wrapper {
|
||||||
min-height: 100%;
|
min-height: 100%;
|
||||||
padding-bottom: $footer-size + $footer-bar-size + $grid-gutter-height / 2;
|
padding-bottom: $footer-size + $footer-bar-size + $grid-gutter-height /
|
||||||
|
2;
|
||||||
|
|
||||||
//padding-top: $grid-gutter-height;
|
//padding-top: $grid-gutter-height;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.footer {
|
.footer {
|
||||||
@ -97,12 +99,6 @@ body.shrink {}
|
|||||||
background-color: $dark;
|
background-color: $dark;
|
||||||
color: darken($white, 5%);
|
color: darken($white, 5%);
|
||||||
|
|
||||||
.container,
|
|
||||||
.container-fluid {
|
|
||||||
padding-top: $grid-gutter-height / 2;
|
|
||||||
padding-bottom: $grid-gutter-height / 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
a {
|
a {
|
||||||
color: $white;
|
color: $white;
|
||||||
}
|
}
|
||||||
@ -114,22 +110,16 @@ body.shrink {}
|
|||||||
.footer {
|
.footer {
|
||||||
background-color: darken($dark, 5%);
|
background-color: darken($dark, 5%);
|
||||||
|
|
||||||
.container,
|
|
||||||
.container-fluid {
|
|
||||||
padding-top: 0;
|
|
||||||
padding-bottom: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.copyright {
|
.copyright {
|
||||||
padding-right: .5rem;
|
padding-right: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
li {
|
li {
|
||||||
padding: 0 .5rem;
|
padding: 0 0.5rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: map-get($grid-breakpoints, "sm")) {
|
@media (min-width: map-get($grid-breakpoints, 'sm')) {
|
||||||
.wrapper {
|
.wrapper {
|
||||||
padding-bottom: $footer-bar-size;
|
padding-bottom: $footer-bar-size;
|
||||||
}
|
}
|
||||||
|
@ -2,19 +2,45 @@
|
|||||||
* Your custom variables
|
* Your custom variables
|
||||||
*/
|
*/
|
||||||
|
|
||||||
$grid-breakpoints: (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px, xxl: 1390px, xxxl: 1590px);
|
$grid-breakpoints: (
|
||||||
$container-max-widths: (sm: 540px, md: 720px, lg: 960px, xl: 1140px, xxl: 1330px, xxxl: 1560px);
|
xs: 0,
|
||||||
|
sm: 576px,
|
||||||
|
md: 768px,
|
||||||
|
lg: 992px,
|
||||||
|
xl: 1200px,
|
||||||
|
xxl: 1390px,
|
||||||
|
xxxl: 1590px,
|
||||||
|
);
|
||||||
|
$container-max-widths: (
|
||||||
|
sm: 540px,
|
||||||
|
md: 720px,
|
||||||
|
lg: 960px,
|
||||||
|
xl: 1140px,
|
||||||
|
xxl: 1330px,
|
||||||
|
xxxl: 1560px,
|
||||||
|
);
|
||||||
|
|
||||||
$font-family-base: "Lato", sans-serif;
|
$font-family-base: 'Lato', sans-serif;
|
||||||
|
|
||||||
$grid-gutter-width: 2rem;
|
$grid-gutter-width: 2rem;
|
||||||
$grid-gutter-height: 2rem;
|
$grid-gutter-height: 2rem;
|
||||||
|
$grid-gutter-element-height: $grid-gutter-height * 2;
|
||||||
|
|
||||||
@import "~@a2nt/ss-bootstrap-ui-webpack-boilerplate/src/scss/_variables";
|
@import '~@a2nt/ss-bootstrap-ui-webpack-boilerplate/src/scss/_variables';
|
||||||
|
|
||||||
// Add your site-wide + content editor typography styling
|
// Add your site-wide + content editor typography styling
|
||||||
|
|
||||||
h1, h2, h3, h4, h5, h6,
|
h1,
|
||||||
.h1, .h2, .h3, .h4, .h5, .h6 {
|
h2,
|
||||||
color: $dark;
|
h3,
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6,
|
||||||
|
.h1,
|
||||||
|
.h2,
|
||||||
|
.h3,
|
||||||
|
.h4,
|
||||||
|
.h5,
|
||||||
|
.h6 {
|
||||||
|
color: $headings-color;
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ use SilverStripe\Forms\HTMLEditor\HTMLEditorField;
|
|||||||
use SilverStripe\Forms\NumericField;
|
use SilverStripe\Forms\NumericField;
|
||||||
use Site\Controllers\MapElementController;
|
use Site\Controllers\MapElementController;
|
||||||
use Site\Extensions\MapExtension;
|
use Site\Extensions\MapExtension;
|
||||||
|
use SilverStripe\Forms\GridField\GridFieldDataColumns;
|
||||||
|
|
||||||
class MapElement extends ElementContent
|
class MapElement extends ElementContent
|
||||||
{
|
{
|
||||||
@ -60,10 +61,16 @@ class MapElement extends ElementContent
|
|||||||
'Locations',
|
'Locations',
|
||||||
'Locations',
|
'Locations',
|
||||||
$this->owner->Locations(),
|
$this->owner->Locations(),
|
||||||
GridFieldConfig_RelationEditor::create(100)
|
$cfg = GridFieldConfig_RelationEditor::create(100)
|
||||||
)
|
)
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
$cfg->getComponentByType(GridFieldDataColumns::class)->setFieldFormatting([
|
||||||
|
'ShowAtMap' => static function ($v, $obj) {
|
||||||
|
return $v ? 'YES' : 'NO';
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
return $fields;
|
return $fields;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@ use SilverStripe\Forms\CheckboxField;
|
|||||||
use SilverStripe\Forms\DropdownField;
|
use SilverStripe\Forms\DropdownField;
|
||||||
use SilverStripe\ORM\DataExtension;
|
use SilverStripe\ORM\DataExtension;
|
||||||
use SilverStripe\Forms\FieldList;
|
use SilverStripe\Forms\FieldList;
|
||||||
|
use SilverStripe\Forms\LiteralField;
|
||||||
|
|
||||||
class ElementRows extends DataExtension
|
class ElementRows extends DataExtension
|
||||||
{
|
{
|
||||||
@ -95,6 +96,15 @@ class ElementRows extends DataExtension
|
|||||||
} else {
|
} else {
|
||||||
$fields->removeByName('Size');
|
$fields->removeByName('Size');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$tab = $fields->findOrMakeTab('Root.Settings')
|
||||||
|
->push(LiteralField::create(
|
||||||
|
'ClassName',
|
||||||
|
'<div class="form-group field text">'
|
||||||
|
.'<div class="form__field-label">Class</div>'
|
||||||
|
.'<div class="form__field-holder">'.$this->owner->getField('ClassName').'</div>'
|
||||||
|
.'</div>'
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getWidthPercetage()
|
public function getWidthPercetage()
|
||||||
|
52
app/src/Extensions/EmbedShortcodeProvider.php
Normal file
52
app/src/Extensions/EmbedShortcodeProvider.php
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
|
||||||
|
namespace Site\Extensions;
|
||||||
|
|
||||||
|
|
||||||
|
use SilverStripe\Core\Convert;
|
||||||
|
use SilverStripe\View\HTML;
|
||||||
|
|
||||||
|
class EmbedShortcodeProvider extends \SilverStripe\View\Shortcodes\EmbedShortcodeProvider
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Build video embed tag
|
||||||
|
*
|
||||||
|
* @param array $arguments
|
||||||
|
* @param string $content Raw HTML content
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected static function videoEmbed($arguments, $content)
|
||||||
|
{
|
||||||
|
// Ensure outer div has given width (but leave height auto)
|
||||||
|
if (!empty($arguments['width'])) {
|
||||||
|
$arguments['style'] = 'width:' . (int) $arguments['width'] . 'px';
|
||||||
|
//.';height:' . (int) $arguments['height'] . 'px';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert caption to <p>
|
||||||
|
if (!empty($arguments['caption'])) {
|
||||||
|
$xmlCaption = Convert::raw2xml($arguments['caption']);
|
||||||
|
$content .= "\n<p class=\"caption\">{$xmlCaption}</p>";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert arguments to data-*argument_name*
|
||||||
|
foreach ($arguments as $k => $v) {
|
||||||
|
if($k === 'class' || $k === 'style') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
unset($arguments[$k]);
|
||||||
|
$arguments['data-'.$k] = $v;
|
||||||
|
}
|
||||||
|
|
||||||
|
$arguments['class'] .= ' embed-youtube embed-responsive embed-responsive-16by9';
|
||||||
|
|
||||||
|
$iframe = strpos($content, 'iframe');
|
||||||
|
if($iframe >= 0) {
|
||||||
|
$content = substr($content, 0, $iframe+6).' class="embed-responsive-item" '.substr($content, $iframe +7);
|
||||||
|
}
|
||||||
|
|
||||||
|
return HTML::createTag('div', $arguments, $content);
|
||||||
|
}
|
||||||
|
}
|
@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
namespace Site\Extensions;
|
namespace Site\Extensions;
|
||||||
|
|
||||||
|
|
||||||
use SilverStripe\ORM\DataExtension;
|
use SilverStripe\ORM\DataExtension;
|
||||||
|
|
||||||
class EmbeddedObjectExtension extends DataExtension
|
class EmbeddedObjectExtension extends DataExtension
|
||||||
@ -25,7 +24,15 @@ class EmbeddedObjectExtension extends DataExtension
|
|||||||
public function setEmbedParams($params = [])
|
public function setEmbedParams($params = [])
|
||||||
{
|
{
|
||||||
// YouTube params
|
// YouTube params
|
||||||
if(stripos($this->owner->EmbedHTML, 'https://www.youtube.com/embed/') > 0) {
|
if (stripos($this->owner->EmbedHTML, 'https://www.youtube.com/embed/') > 0) {
|
||||||
|
$url = $this->owner->getField('SourceURL');
|
||||||
|
preg_match(
|
||||||
|
'/^(?:http(?:s)?:\/\/)?(?:www\.)?(?:m\.)?(?:youtu\.be\/|youtube\.com\/(?:(?:watch)?\?(?:.*&)?v(?:i)?=|(?:embed|v|vi|user)\/))([^\?&"\'>]+)/',
|
||||||
|
$url,
|
||||||
|
$matches
|
||||||
|
);
|
||||||
|
$videoID = $matches[1];
|
||||||
|
|
||||||
$params = array_merge([
|
$params = array_merge([
|
||||||
'feature=oembed',
|
'feature=oembed',
|
||||||
'wmode=transparent',
|
'wmode=transparent',
|
||||||
@ -48,7 +55,7 @@ class EmbeddedObjectExtension extends DataExtension
|
|||||||
|
|
||||||
$this->owner->EmbedHTML = preg_replace(
|
$this->owner->EmbedHTML = preg_replace(
|
||||||
'/src="([A-z0-9:\/\.]+)\??(.*?)"/',
|
'/src="([A-z0-9:\/\.]+)\??(.*?)"/',
|
||||||
'src="${1}?' . implode('&', $params) . '"',
|
'src="https://www.youtube.com/embed/'.$videoID.'?' . implode('&', $params) . '"',
|
||||||
$this->owner->EmbedHTML
|
$this->owner->EmbedHTML
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@ use SilverStripe\Forms\CompositeField;
|
|||||||
use SilverStripe\Forms\FieldList;
|
use SilverStripe\Forms\FieldList;
|
||||||
use SilverStripe\Forms\GridField\GridField;
|
use SilverStripe\Forms\GridField\GridField;
|
||||||
use SilverStripe\Forms\GridField\GridFieldConfig_RelationEditor;
|
use SilverStripe\Forms\GridField\GridFieldConfig_RelationEditor;
|
||||||
|
use SilverStripe\Forms\GridField\GridFieldDataColumns;
|
||||||
use SilverStripe\Forms\NumericField;
|
use SilverStripe\Forms\NumericField;
|
||||||
use SilverStripe\ORM\DataExtension;
|
use SilverStripe\ORM\DataExtension;
|
||||||
use Site\Models\MapPin;
|
use Site\Models\MapPin;
|
||||||
@ -42,19 +43,28 @@ class MapExtension extends DataExtension
|
|||||||
'Locations',
|
'Locations',
|
||||||
'Locations',
|
'Locations',
|
||||||
$this->owner->Locations(),
|
$this->owner->Locations(),
|
||||||
GridFieldConfig_RelationEditor::create(100)
|
$cfg = GridFieldConfig_RelationEditor::create(100)
|
||||||
)
|
)
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
$cfg->getComponentByType(GridFieldDataColumns::class)->setFieldFormatting([
|
||||||
|
'ShowAtMap' => static function ($v, $obj) {
|
||||||
|
return $v ? 'YES' : 'NO';
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
$fields->findOrMakeTab('Root.MapPins')->setTitle('Locations');
|
$fields->findOrMakeTab('Root.MapPins')->setTitle('Locations');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getGeoJSON(): string
|
public function getGeoJSON(): string
|
||||||
{
|
{
|
||||||
|
$locs = $this->owner->Locations()->filter('ShowAtMap', true);
|
||||||
|
|
||||||
$pins = [];
|
$pins = [];
|
||||||
foreach ($this->owner->Locations() as $off) {
|
foreach ($locs as $off) {
|
||||||
$pins[] = $off->getGeo();
|
$pins[] = $off->getGeo();
|
||||||
}
|
}
|
||||||
|
|
||||||
return json_encode([
|
return json_encode([
|
||||||
'type' => 'MarkerCollection',
|
'type' => 'MarkerCollection',
|
||||||
'features' => $pins
|
'features' => $pins
|
||||||
|
@ -49,7 +49,9 @@ class SiteConfigExtension extends DataExtension
|
|||||||
'Navigation',
|
'Navigation',
|
||||||
'Navigation',
|
'Navigation',
|
||||||
SiteTree::class
|
SiteTree::class
|
||||||
),
|
)->setDisableFunction(static function ($el) {
|
||||||
|
return $el->getField('ParentID') !== 0;
|
||||||
|
}),
|
||||||
TextareaField::create('Description', 'Website Description'),
|
TextareaField::create('Description', 'Website Description'),
|
||||||
TextareaField::create('ExtraCode', 'Extra site-wide HTML code'),
|
TextareaField::create('ExtraCode', 'Extra site-wide HTML code'),
|
||||||
DropdownField::create(
|
DropdownField::create(
|
||||||
|
@ -24,6 +24,7 @@ class MapPin extends DataObject
|
|||||||
|
|
||||||
private static $db = [
|
private static $db = [
|
||||||
'Title' => 'Varchar(255)',
|
'Title' => 'Varchar(255)',
|
||||||
|
'ShowAtMap' => 'Boolean(1)',
|
||||||
];
|
];
|
||||||
|
|
||||||
private static $has_one = [
|
private static $has_one = [
|
||||||
@ -43,6 +44,12 @@ class MapPin extends DataObject
|
|||||||
|
|
||||||
private static $default_sort = 'Title ASC, ID DESC';
|
private static $default_sort = 'Title ASC, ID DESC';
|
||||||
|
|
||||||
|
private static $summary_fields = [
|
||||||
|
'Title',
|
||||||
|
'Address',
|
||||||
|
'ShowAtMap',
|
||||||
|
];
|
||||||
|
|
||||||
public function getCMSFields()
|
public function getCMSFields()
|
||||||
{
|
{
|
||||||
$fields = parent::getCMSFields();
|
$fields = parent::getCMSFields();
|
||||||
@ -63,6 +70,7 @@ class MapPin extends DataObject
|
|||||||
$fields->removeByName(['Map', 'LatLngOverride', 'Lng','Lat']);
|
$fields->removeByName(['Map', 'LatLngOverride', 'Lng','Lat']);
|
||||||
|
|
||||||
$fields->addFieldsToTab('Root.Main', [
|
$fields->addFieldsToTab('Root.Main', [
|
||||||
|
CheckboxField::create('ShowAtMap', 'Show at the map?'),
|
||||||
CheckboxField::create('LatLngOverride', 'Override Latitude and Longitude?')
|
CheckboxField::create('LatLngOverride', 'Override Latitude and Longitude?')
|
||||||
->setDescription('Check this box and save to be able to edit the latitude and longitude manually.'),
|
->setDescription('Check this box and save to be able to edit the latitude and longitude manually.'),
|
||||||
MapboxField::create('Map', 'Choose a location', 'Lat', 'Lng'),
|
MapboxField::create('Map', 'Choose a location', 'Lat', 'Lng'),
|
||||||
|
@ -50,7 +50,7 @@ class PageController extends ContentController
|
|||||||
|
|
||||||
public function ElementalArea()
|
public function ElementalArea()
|
||||||
{
|
{
|
||||||
if($this->CurrentElement() || $this->getAction() !== 'index') {
|
if ($this->CurrentElement() || $this->getAction() !== 'index') {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,7 +61,7 @@ class PageController extends ContentController
|
|||||||
{
|
{
|
||||||
$controller_curr = Controller::curr();
|
$controller_curr = Controller::curr();
|
||||||
|
|
||||||
if(is_a($controller_curr, ElementFormController::class)) {
|
if (is_a($controller_curr, ElementFormController::class)) {
|
||||||
return $controller_curr;
|
return $controller_curr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,7 +104,7 @@ class PageController extends ContentController
|
|||||||
public function SearchResults()
|
public function SearchResults()
|
||||||
{
|
{
|
||||||
$term = $this->search_term;
|
$term = $this->search_term;
|
||||||
if(!$term) {
|
if (!$term) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,7 +126,7 @@ class PageController extends ContentController
|
|||||||
|
|
||||||
foreach ($elements as $element) {
|
foreach ($elements as $element) {
|
||||||
$page = Page::get()->filter('ElementalAreaID', $element->getField('ParentID'))->first();
|
$page = Page::get()->filter('ElementalAreaID', $element->getField('ParentID'))->first();
|
||||||
if(!$page) {
|
if (!$page) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -177,4 +177,9 @@ class PageController extends ContentController
|
|||||||
{
|
{
|
||||||
return DBDatetime::now();
|
return DBDatetime::now();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function isDev()
|
||||||
|
{
|
||||||
|
return Director::isDev();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,9 @@ class DeferredRequirements implements TemplateGlobalProvider
|
|||||||
private static $static_domain;
|
private static $static_domain;
|
||||||
private static $version;
|
private static $version;
|
||||||
private static $nojquery = false;
|
private static $nojquery = false;
|
||||||
|
private static $jquery_version = '3.4.1';
|
||||||
private static $nofontawesome = false;
|
private static $nofontawesome = false;
|
||||||
|
private static $fontawesome_version = '5.10.2';
|
||||||
private static $custom_requirements = [];
|
private static $custom_requirements = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -60,12 +62,19 @@ class DeferredRequirements implements TemplateGlobalProvider
|
|||||||
|
|
||||||
// Main libs
|
// Main libs
|
||||||
if (!$config['nojquery']) {
|
if (!$config['nojquery']) {
|
||||||
self::loadJS('//ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js');
|
self::loadJS(
|
||||||
|
'//ajax.googleapis.com/ajax/libs/jquery/'
|
||||||
|
.$config['jquery_version'].'/jquery.min.js'
|
||||||
|
);
|
||||||
}
|
}
|
||||||
// App libs
|
// App libs
|
||||||
if (!$config['nofontawesome']) {
|
if (!$config['nofontawesome']) {
|
||||||
self::loadCSS('//use.fontawesome.com/releases/v5.4.0/css/all.css');
|
self::loadCSS(
|
||||||
|
'//use.fontawesome.com/releases/v'
|
||||||
|
.$config['fontawesome_version'].'/css/all.css'
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
self::loadCSS($mainTheme.'.css');
|
self::loadCSS($mainTheme.'.css');
|
||||||
self::loadJS($mainTheme.'.js');
|
self::loadJS($mainTheme.'.js');
|
||||||
|
|
||||||
@ -176,17 +185,16 @@ class DeferredRequirements implements TemplateGlobalProvider
|
|||||||
return $url;
|
return $url;
|
||||||
}
|
}
|
||||||
|
|
||||||
$version = $config['version'];
|
$path = WebpackTemplateProvider::toPublicPath($url);
|
||||||
$version = $version
|
|
||||||
? strpos($url, '?') // inner URL
|
|
||||||
? '&'.$version // add param
|
|
||||||
: '?'.$version // new param
|
|
||||||
: ''; // no version defined
|
|
||||||
|
|
||||||
|
$absolutePath = Director::getAbsFile($path);
|
||||||
|
$hash = sha1_file($absolutePath);
|
||||||
|
|
||||||
|
$version = $config['version'] ? '&v='.$config['version'] : '';
|
||||||
//$static_domain = $config['static_domain'];
|
//$static_domain = $config['static_domain'];
|
||||||
//$static_domain = $static_domain ?: '';
|
//$static_domain = $static_domain ?: '';
|
||||||
|
|
||||||
return WebpackTemplateProvider::toPublicPath($url.$version);
|
return Controller::join_links(WebpackTemplateProvider::toPublicPath($url), '?m='.$hash.$version);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function config(): array
|
public static function config(): array
|
||||||
|
@ -1,36 +1,28 @@
|
|||||||
<?php
|
<?php
|
||||||
/** @noinspection PhpUnusedPrivateFieldInspection */
|
|
||||||
|
|
||||||
/**
|
/** @noinspection PhpUnusedPrivateFieldInspection */
|
||||||
* Directs assets requests to Webpack server or to static files
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Site\Templates;
|
namespace Site\Templates;
|
||||||
|
|
||||||
use SilverStripe\Core\Manifest\ModuleManifest;
|
use SilverStripe\Control\Controller;
|
||||||
use SilverStripe\View\SSViewer;
|
|
||||||
use SilverStripe\View\TemplateGlobalProvider;
|
use SilverStripe\View\TemplateGlobalProvider;
|
||||||
use SilverStripe\View\Requirements;
|
use SilverStripe\View\Requirements;
|
||||||
use SilverStripe\Control\Director;
|
|
||||||
use SilverStripe\Control\Controller;
|
|
||||||
use SilverStripe\Core\Config\Config;
|
use SilverStripe\Core\Config\Config;
|
||||||
|
use SilverStripe\Control\Director;
|
||||||
|
use SilverStripe\Core\Path;
|
||||||
|
|
||||||
class WebpackTemplateProvider implements TemplateGlobalProvider
|
class DeferredRequirements implements TemplateGlobalProvider
|
||||||
{
|
{
|
||||||
/**
|
private static $css = [];
|
||||||
* @var int port number
|
private static $js = [];
|
||||||
*/
|
private static $deferred = false;
|
||||||
private static $port = 3000;
|
private static $static_domain;
|
||||||
|
private static $version;
|
||||||
/**
|
private static $nojquery = false;
|
||||||
* @var string host name
|
private static $jquery_version = '3.4.1';
|
||||||
*/
|
private static $nofontawesome = false;
|
||||||
private static $hostname = 'localhost';
|
private static $fontawesome_version = '5.11.0';
|
||||||
|
private static $custom_requirements = [];
|
||||||
/**
|
|
||||||
* @var string assets static files directory
|
|
||||||
*/
|
|
||||||
private static $dist = 'client/dist';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return array
|
* @return array
|
||||||
@ -38,97 +30,172 @@ class WebpackTemplateProvider implements TemplateGlobalProvider
|
|||||||
public static function get_template_global_variables(): array
|
public static function get_template_global_variables(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'WebpackDevServer' => 'isActive',
|
'AutoRequirements' => 'Auto',
|
||||||
'WebpackCSS' => 'loadCSS',
|
'DeferedCSS' => 'loadCSS',
|
||||||
'WebpackJS' => 'loadJS',
|
'DeferedJS' => 'loadJS',
|
||||||
'ResourcesURL' => 'resourcesURL',
|
'WebpackActive' => '_webpackActive',
|
||||||
'ProjectName' => 'themeName',
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public static function Auto($class = false): string
|
||||||
* Load CSS file
|
|
||||||
* @param $path
|
|
||||||
*/
|
|
||||||
public static function loadCSS($path): void
|
|
||||||
{
|
{
|
||||||
if (self::isActive()) {
|
$config = Config::inst()->get(self::class);
|
||||||
return;
|
$projectName = WebpackTemplateProvider::projectName();
|
||||||
}
|
$mainTheme = WebpackTemplateProvider::mainTheme();
|
||||||
|
$mainTheme = $mainTheme ?: $projectName;
|
||||||
|
|
||||||
Requirements::css(self::_getPath($path));
|
$dir = Path::join(
|
||||||
}
|
Director::publicFolder(),
|
||||||
|
|
||||||
/**
|
|
||||||
* Load JS file
|
|
||||||
* @param $path
|
|
||||||
*/
|
|
||||||
public static function loadJS($path): void
|
|
||||||
{
|
|
||||||
Requirements::javascript(self::_getPath($path), ['type' => '']);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function projectName(): string
|
|
||||||
{
|
|
||||||
return Config::inst()->get(ModuleManifest::class, 'project');
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function mainTheme()
|
|
||||||
{
|
|
||||||
$themes = Config::inst()->get(SSViewer::class, 'themes');
|
|
||||||
return is_array($themes) && $themes[0] !== '$public' && $themes[0] !== '$default' ? $themes[0] : false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function resourcesURL($link = null): string
|
|
||||||
{
|
|
||||||
return Controller::join_links(Director::baseURL(), '/resources/'.self::projectName().'/client/dist/img/', $link);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if dev mode is enabled and if webpack server is online
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public static function isActive(): bool
|
|
||||||
{
|
|
||||||
$cfg = self::config();
|
|
||||||
return Director::isDev() && @fsockopen(
|
|
||||||
$cfg['HOSTNAME'],
|
|
||||||
$cfg['PORT']
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static function _getPath($path): string
|
|
||||||
{
|
|
||||||
return self::isActive() && strpos($path, '//') === false ?
|
|
||||||
self::_toDevServerPath($path) :
|
|
||||||
self::toPublicPath($path);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static function _toDevServerPath($path): string
|
|
||||||
{
|
|
||||||
$cfg = self::config();
|
|
||||||
return sprintf(
|
|
||||||
'%s%s:%s/%s',
|
|
||||||
Director::protocol(),
|
|
||||||
$cfg['HOSTNAME'],
|
|
||||||
$cfg['PORT'],
|
|
||||||
basename($path)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function toPublicPath($path): string
|
|
||||||
{
|
|
||||||
$cfg = self::config();
|
|
||||||
return strpos($path, '//') === false ?
|
|
||||||
Controller::join_links(
|
|
||||||
RESOURCES_DIR,
|
RESOURCES_DIR,
|
||||||
self::projectName(),
|
$projectName,
|
||||||
$cfg['DIST'],
|
'client',
|
||||||
(strpos($path, '.css') ? 'css' : 'js'),
|
'dist'
|
||||||
$path
|
);
|
||||||
)
|
$cssPath = Path::join($dir, 'css');
|
||||||
: $path;
|
$jsPath = Path::join($dir, 'js');
|
||||||
|
|
||||||
|
// Initialization
|
||||||
|
Requirements::block(THIRDPARTY_DIR.'/jquery/jquery.js');
|
||||||
|
/*if (defined('FONT_AWESOME_DIR')) {
|
||||||
|
Requirements::block(FONT_AWESOME_DIR.'/css/lib/font-awesome.min.css');
|
||||||
|
}*/
|
||||||
|
Requirements::set_force_js_to_bottom(true);
|
||||||
|
|
||||||
|
// Main libs
|
||||||
|
if (!$config['nojquery']) {
|
||||||
|
self::loadJS(
|
||||||
|
'//ajax.googleapis.com/ajax/libs/jquery/'
|
||||||
|
.$config['jquery_version'].'/jquery.min.js'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// App libs
|
||||||
|
if (!$config['nofontawesome']) {
|
||||||
|
self::loadCSS(
|
||||||
|
'//use.fontawesome.com/releases/v'
|
||||||
|
.$config['fontawesome_version'].'/css/all.css'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
self::loadCSS($mainTheme.'.css');
|
||||||
|
self::loadJS($mainTheme.'.js');
|
||||||
|
|
||||||
|
// Custom controller requirements
|
||||||
|
$curr_class = $class ?: get_class(Controller::curr());
|
||||||
|
if (isset($config['custom_requirements'][$curr_class])) {
|
||||||
|
foreach ($config['custom_requirements'][$curr_class] as $file) {
|
||||||
|
if (strpos($file, '.css')) {
|
||||||
|
self::loadCSS($file);
|
||||||
|
}
|
||||||
|
if (strpos($file, '.js')) {
|
||||||
|
self::loadJS($file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$curr_class = str_replace('\\', '.', $curr_class);
|
||||||
|
|
||||||
|
// Controller requirements
|
||||||
|
$themePath = Path::join($cssPath, $mainTheme.'_'.$curr_class . '.css');
|
||||||
|
$projectPath = Path::join($cssPath, $projectName.'_'.$curr_class . '.css');
|
||||||
|
if ($mainTheme && file_exists($themePath)) {
|
||||||
|
self::loadCSS($mainTheme.'_'.$curr_class . '.css');
|
||||||
|
} elseif (file_exists($projectPath)) {
|
||||||
|
self::loadCSS($projectName.'_'.$curr_class . '.css');
|
||||||
|
}
|
||||||
|
|
||||||
|
$themePath = Path::join($jsPath, $mainTheme.'_'.$curr_class . '.js');
|
||||||
|
$projectPath = Path::join($jsPath, $projectName.'_'.$curr_class . '.js');
|
||||||
|
if ($mainTheme && file_exists($themePath)) {
|
||||||
|
self::loadJS($mainTheme.'_'.$curr_class . '.js');
|
||||||
|
} elseif (file_exists($projectPath)) {
|
||||||
|
self::loadJS($projectName.'_'.$curr_class . '.js');
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::forTemplate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function loadCSS($css): void
|
||||||
|
{
|
||||||
|
$external = (mb_strpos($css, '//') === 0 || mb_strpos($css, 'http') === 0);
|
||||||
|
if ($external || (self::getDeferred() && !self::_webpackActive())) {
|
||||||
|
self::$css[] = $css;
|
||||||
|
} else {
|
||||||
|
WebpackTemplateProvider::loadCSS($css);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function loadJS($js): void
|
||||||
|
{
|
||||||
|
/*$external = (mb_substr($js, 0, 2) === '//' || mb_substr($js, 0, 4) === 'http');
|
||||||
|
if ($external || (self::getDeferred() && !self::_webpackActive())) {*/
|
||||||
|
// webpack supposed to load external JS
|
||||||
|
if (self::getDeferred() && !self::_webpackActive()) {
|
||||||
|
self::$js[] = $js;
|
||||||
|
} else {
|
||||||
|
WebpackTemplateProvider::loadJS($js);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static function _webpackActive(): bool
|
||||||
|
{
|
||||||
|
return WebpackTemplateProvider::isActive();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function setDeferred($bool): void
|
||||||
|
{
|
||||||
|
Config::inst()->set(__CLASS__, 'deferred', $bool);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getDeferred(): bool
|
||||||
|
{
|
||||||
|
return self::config()['deferred'];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function forTemplate(): string
|
||||||
|
{
|
||||||
|
$result = '';
|
||||||
|
self::$css = array_unique(self::$css);
|
||||||
|
foreach (self::$css as $css) {
|
||||||
|
$result .= '<i class="defer-cs" data-load="' . self::get_url($css) . '"></i>';
|
||||||
|
}
|
||||||
|
|
||||||
|
self::$js = array_unique(self::$js);
|
||||||
|
foreach (self::$js as $js) {
|
||||||
|
$result .= '<i class="defer-sc" data-load="' . self::get_url($js) . '"></i>';
|
||||||
|
}
|
||||||
|
|
||||||
|
$result .=
|
||||||
|
'<script>function lsc(a,b){var c=document.createElement("script");c.readyState'
|
||||||
|
.'?c.onreadystatechange=function(){"loaded"!=c.readyState&&"complete"!=c.readyState||(c.onreadystatechange=null,b())}'
|
||||||
|
.':c.onload=function(){b()},c.src=a,document.getElementsByTagName("body")[0].appendChild(c)}'
|
||||||
|
.'function lscd(a){a<s.length-1&&(a++,lsc(s.item(a).getAttribute("data-load"),function(){lscd(a)}))}'
|
||||||
|
.'for(var s=document.getElementsByClassName("defer-cs"),i=0;i<s.length;i++){var b=document.createElement("link");b.rel="stylesheet",'
|
||||||
|
.'b.type="text/css",b.href=s.item(i).getAttribute("data-load"),b.media="all";var c=document.getElementsByTagName("body")[0];'
|
||||||
|
.'c.appendChild(b)}var s=document.getElementsByClassName("defer-sc"),i=0;if(s.item(i)!==null)lsc(s.item(i).getAttribute("data-load"),function(){lscd(i)});'
|
||||||
|
.'</script>';
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function get_url($url): string
|
||||||
|
{
|
||||||
|
$config = self::config();
|
||||||
|
|
||||||
|
// external URL
|
||||||
|
if (strpos($url, '//') !== false) {
|
||||||
|
return $url;
|
||||||
|
}
|
||||||
|
|
||||||
|
$path = WebpackTemplateProvider::toPublicPath($url);
|
||||||
|
|
||||||
|
$absolutePath = Director::getAbsFile($path);
|
||||||
|
$hash = sha1_file($absolutePath);
|
||||||
|
|
||||||
|
$version = $config['version'] ? '&v='.$config['version'] : '';
|
||||||
|
//$static_domain = $config['static_domain'];
|
||||||
|
//$static_domain = $static_domain ?: '';
|
||||||
|
|
||||||
|
return Controller::join_links(WebpackTemplateProvider::toPublicPath($url), '?m='.$hash.$version);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function config(): array
|
public static function config(): array
|
||||||
|
37
app/src/Widgets/ContentWidget.php
Normal file
37
app/src/Widgets/ContentWidget.php
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
|
||||||
|
namespace Site\Widgets;
|
||||||
|
|
||||||
|
use Sheadawson\Linkable\Forms\LinkField;
|
||||||
|
use Sheadawson\Linkable\Models\Link;
|
||||||
|
use SilverStripe\AssetAdmin\Forms\UploadField;
|
||||||
|
use SilverStripe\Assets\Image;
|
||||||
|
use SilverStripe\Forms\HTMLEditor\HTMLEditorField;
|
||||||
|
use SilverStripe\Widgets\Model\Widget;
|
||||||
|
|
||||||
|
if (!class_exists(Widget::class)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
class ContentWidget extends Widget
|
||||||
|
{
|
||||||
|
private static $title = 'Content';
|
||||||
|
private static $cmsTitle = 'Content';
|
||||||
|
private static $description = 'Shows text content.';
|
||||||
|
private static $icon = '<i class="icon font-icon-block-content"></i>';
|
||||||
|
private static $table_name = 'ContentWidget';
|
||||||
|
|
||||||
|
private static $db = [
|
||||||
|
'Text' => 'HTMLText',
|
||||||
|
];
|
||||||
|
|
||||||
|
public function getCMSFields()
|
||||||
|
{
|
||||||
|
$fields = parent::getCMSFields();
|
||||||
|
|
||||||
|
$fields->push(HTMLEditorField::create('Text'));
|
||||||
|
|
||||||
|
return $fields;
|
||||||
|
}
|
||||||
|
}
|
60
app/src/Widgets/ElementWidget.php
Normal file
60
app/src/Widgets/ElementWidget.php
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
|
||||||
|
namespace Site\Widgets;
|
||||||
|
|
||||||
|
use DNADesign\Elemental\Models\BaseElement;
|
||||||
|
use DNADesign\ElementalList\Model\ElementList;
|
||||||
|
use SilverStripe\CMS\Model\SiteTree;
|
||||||
|
use SilverStripe\Forms\DropdownField;
|
||||||
|
use SilverStripe\Forms\TreeDropdownField;
|
||||||
|
use SilverStripe\Widgets\Model\Widget;
|
||||||
|
|
||||||
|
if (!class_exists(Widget::class)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
class ElementWidget extends Widget
|
||||||
|
{
|
||||||
|
private static $title = 'Virtual Element';
|
||||||
|
private static $cmsTitle = 'Virtual Element';
|
||||||
|
private static $description = 'Adds existing element to side bar';
|
||||||
|
private static $icon = '<i class="icon font-icon-block-banner"></i>';
|
||||||
|
private static $table_name = 'ElementWidget';
|
||||||
|
|
||||||
|
private static $has_one = [
|
||||||
|
'Element' => BaseElement::class,
|
||||||
|
];
|
||||||
|
|
||||||
|
public function getCMSFields()
|
||||||
|
{
|
||||||
|
$fields = parent::getCMSFields();
|
||||||
|
|
||||||
|
$fields->push(
|
||||||
|
DropdownField::create(
|
||||||
|
'ElementID',
|
||||||
|
'Displayed Element',
|
||||||
|
BaseElement::get()
|
||||||
|
->filter(['AvailableGlobally' => true])
|
||||||
|
->exclude(['ClassName' => ElementList::class])
|
||||||
|
)
|
||||||
|
/*TreeDropdownField::create(
|
||||||
|
'ElementID',
|
||||||
|
'Displayed Element',
|
||||||
|
SiteTree::class
|
||||||
|
)->setFilterFunction(static function($el){
|
||||||
|
return (bool) $el->getField('ElementalArea')->Elements()->count();
|
||||||
|
})*/
|
||||||
|
);
|
||||||
|
|
||||||
|
return $fields;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function SimpleClassName()
|
||||||
|
{
|
||||||
|
$el = $this->getField('Element');
|
||||||
|
var_dump($el);
|
||||||
|
die();
|
||||||
|
return $el->getSimpleClassName();
|
||||||
|
}
|
||||||
|
}
|
@ -3,10 +3,6 @@
|
|||||||
|
|
||||||
namespace Site\Widgets;
|
namespace Site\Widgets;
|
||||||
|
|
||||||
use Sheadawson\Linkable\Forms\LinkField;
|
|
||||||
use Sheadawson\Linkable\Models\Link;
|
|
||||||
use SilverStripe\AssetAdmin\Forms\UploadField;
|
|
||||||
use SilverStripe\Assets\Image;
|
|
||||||
use SilverStripe\Widgets\Model\Widget;
|
use SilverStripe\Widgets\Model\Widget;
|
||||||
|
|
||||||
if (!class_exists(Widget::class)) {
|
if (!class_exists(Widget::class)) {
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
namespace Site\Widgets;
|
namespace Site\Widgets;
|
||||||
|
|
||||||
|
|
||||||
use DNADesign\Elemental\Controllers\ElementalAreaController;
|
use DNADesign\Elemental\Controllers\ElementalAreaController;
|
||||||
use DNADesign\Elemental\Forms\ElementalAreaConfig;
|
use DNADesign\Elemental\Forms\ElementalAreaConfig;
|
||||||
use DNADesign\Elemental\Forms\ElementalAreaField;
|
use DNADesign\Elemental\Forms\ElementalAreaField;
|
||||||
@ -67,10 +66,10 @@ class WidgetAreaField extends GridField
|
|||||||
'Title' => 'Title',
|
'Title' => 'Title',
|
||||||
'Enabled' => 'Enabled',
|
'Enabled' => 'Enabled',
|
||||||
])->setFieldFormatting([
|
])->setFieldFormatting([
|
||||||
'Icon' => static function($v, Widget $item) {
|
'Icon' => static function ($v, Widget $item) {
|
||||||
return '<span style="font-size:2rem">'.$item::config()->get('icon').'</span>';
|
return '<span style="font-size:2rem">'.$item::config()->get('icon').'</span>';
|
||||||
},
|
},
|
||||||
'Enabled' => static function($v, Widget $item) {
|
'Enabled' => static function ($v, Widget $item) {
|
||||||
return $item->getField('Enabled') ? 'Yes' : 'No';
|
return $item->getField('Enabled') ? 'Yes' : 'No';
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
@ -141,7 +140,7 @@ class WidgetAreaField extends GridField
|
|||||||
// Extract the ID
|
// Extract the ID
|
||||||
$elementId = (int) substr($form, $idPrefixLength);
|
$elementId = (int) substr($form, $idPrefixLength);
|
||||||
|
|
||||||
/** @var BaseElement $element */
|
// @var BaseElement $element
|
||||||
$element = $this->getArea()->Widgets()->byID($elementId);
|
$element = $this->getArea()->Widgets()->byID($elementId);
|
||||||
|
|
||||||
if (!$element) {
|
if (!$element) {
|
||||||
|
@ -3,11 +3,11 @@
|
|||||||
|
|
||||||
namespace Site\Widgets;
|
namespace Site\Widgets;
|
||||||
|
|
||||||
|
|
||||||
use DNADesign\Elemental\Forms\ElementalAreaField;
|
use DNADesign\Elemental\Forms\ElementalAreaField;
|
||||||
use SilverStripe\Forms\FieldList;
|
use SilverStripe\Forms\FieldList;
|
||||||
use SilverStripe\Widgets\Forms\WidgetAreaEditor;
|
use SilverStripe\Widgets\Forms\WidgetAreaEditor;
|
||||||
use SilverStripe\Widgets\Model\Widget;
|
use SilverStripe\Widgets\Model\Widget;
|
||||||
|
use SilverStripe\Widgets\Model\WidgetArea;
|
||||||
|
|
||||||
class WidgetPageExtension extends \SilverStripe\Widgets\Extensions\WidgetPageExtension
|
class WidgetPageExtension extends \SilverStripe\Widgets\Extensions\WidgetPageExtension
|
||||||
{
|
{
|
||||||
@ -34,4 +34,16 @@ class WidgetPageExtension extends \SilverStripe\Widgets\Extensions\WidgetPageExt
|
|||||||
$available
|
$available
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function onBeforeWrite()
|
||||||
|
{
|
||||||
|
parent::onBeforeWrite();
|
||||||
|
|
||||||
|
if (!$this->owner->getField('SideBarID')) {
|
||||||
|
$area = WidgetArea::create();
|
||||||
|
$area->write();
|
||||||
|
|
||||||
|
$this->owner->setField('SideBarID', $area->ID);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,6 @@
|
|||||||
|
|
||||||
<% if $ShowTitle || $Content || $ImageLink %>
|
<% if $ShowTitle || $Content || $ImageLink %>
|
||||||
<div class="image-element__caption img-content">
|
<div class="image-element__caption img-content">
|
||||||
<div class="container">
|
|
||||||
<% if $ShowTitle %><h3 class="image-element__title title">$Title</h3><% end_if %>
|
<% if $ShowTitle %><h3 class="image-element__title title">$Title</h3><% end_if %>
|
||||||
|
|
||||||
<% if $Content %>
|
<% if $Content %>
|
||||||
@ -21,6 +20,5 @@
|
|||||||
<i class="fas fa-caret-right"></i>
|
<i class="fas fa-caret-right"></i>
|
||||||
</a>
|
</a>
|
||||||
<% end_if %>
|
<% end_if %>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<% end_if %>
|
<% end_if %>
|
||||||
|
@ -1,23 +1,49 @@
|
|||||||
<div class="page-content">
|
<div class="page-content page-content-main">
|
||||||
<h1 class="element page-header $DefaultContainer<% if $ElementalArea.Elements.Count < 1 %> no-elements<% end_if %>">
|
<div class="
|
||||||
|
element
|
||||||
|
page-header-element
|
||||||
|
<% if $ElementalArea.Elements.Count < 1 %>
|
||||||
|
d-block no-elements
|
||||||
|
<% else_if not $ElementalArea.Elements.First.ShowTitle && $ElementalArea.Elements.First.ClassName != Site\Elements\SliderElement %>
|
||||||
|
d-block
|
||||||
|
<% end_if %>
|
||||||
|
">
|
||||||
|
<div class="$DefaultContainer">
|
||||||
|
<h1 class="page-header">
|
||||||
$Title
|
$Title
|
||||||
</h1>
|
</h1>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<% if $CurrentElement %>
|
<% if $CurrentElement %>
|
||||||
|
<div class="current-element">
|
||||||
$CurrentElement
|
$CurrentElement
|
||||||
|
</div>
|
||||||
<% else %>
|
<% else %>
|
||||||
|
<div class="elemental-area">
|
||||||
$ElementalArea
|
$ElementalArea
|
||||||
|
</div>
|
||||||
<% end_if %>
|
<% end_if %>
|
||||||
|
|
||||||
<% if $Form %>
|
<% if $Form %>
|
||||||
<div class="element $DefaultContainer">
|
<div class="page-form-element element">
|
||||||
|
<div class="element_container">
|
||||||
|
<div class="$DefaultContainer">
|
||||||
$Form
|
$Form
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<% end_if %>
|
<% end_if %>
|
||||||
|
|
||||||
<% if $ExtraCode %>
|
<% if $ExtraCode %>
|
||||||
<div class="element $DefaultContainer extra-code extra-code-page">
|
<div class="page-extra-code">
|
||||||
|
<div class="element">
|
||||||
|
<div class="element_container">
|
||||||
|
<div class="$DefaultContainer">
|
||||||
$ExtraCode
|
$ExtraCode
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<% end_if %>
|
<% end_if %>
|
||||||
</div>
|
</div>
|
||||||
|
@ -13,5 +13,10 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<% if $isDev || $WebpackActive %>
|
||||||
|
<div id="DevOriginal"></div>
|
||||||
|
<% end_if %>
|
||||||
|
|
||||||
<%-- Site Wide Alert Message --%>
|
<%-- Site Wide Alert Message --%>
|
||||||
<% include SiteWideMessage %>
|
<% include SiteWideMessage %>
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
<% with $SiteConfig %>
|
<% with $SiteConfig %>
|
||||||
<div class="wrapper">
|
<div class="wrapper">
|
||||||
<div class="container">
|
<div class="element">
|
||||||
|
<div class="footer__container $Top.DefaultContainer">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-6">
|
<div class="col-sm-6">
|
||||||
<a href="/" class="logo2">
|
<a href="/" class="logo2">
|
||||||
@ -32,6 +33,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="copyright footer">
|
<div class="copyright footer">
|
||||||
|
@ -1,17 +1,10 @@
|
|||||||
<div class="element">
|
<div class="element">
|
||||||
|
<div class="element__container $DefaultContainer">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-4">
|
<div class="col-sm-4">
|
||||||
<a id="Logo" href="/"><img src="{$ResourcesURL('logo.png')}" alt="{$SiteConfig.Title}" /></a>
|
<a id="Logo" href="/"><img src="{$ResourcesURL('logo.png')}" alt="{$SiteConfig.Title}" /></a>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-8 text-right">
|
<div class="col-sm-8 text-right">
|
||||||
<div class="btn-group btn-group-lg" role="group">
|
|
||||||
<a href="#" class="btn btn-success">Contact</a>
|
|
||||||
<a href="#" class="btn btn-warning">Donate</a>
|
|
||||||
<a href="#" class="btn btn-secondary">
|
|
||||||
<i class="fas fa-search"></i>
|
|
||||||
<span class="sr-only">Search</span>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<% with $SiteConfig %>
|
<% with $SiteConfig %>
|
||||||
<% if $PhoneNumber %>
|
<% if $PhoneNumber %>
|
||||||
<span class="phone-number">
|
<span class="phone-number">
|
||||||
@ -32,4 +25,5 @@
|
|||||||
<% end_if %>
|
<% end_if %>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -32,6 +32,8 @@ $MetaTags
|
|||||||
<link rel="author" type="text/plain" href="{$AbsoluteBaseURL}humans.txt" />
|
<link rel="author" type="text/plain" href="{$AbsoluteBaseURL}humans.txt" />
|
||||||
<link rel="sitemap" type="application/xml" title="Sitemap" href="{$AbsoluteBaseURL}sitemap.xml" />
|
<link rel="sitemap" type="application/xml" title="Sitemap" href="{$AbsoluteBaseURL}sitemap.xml" />
|
||||||
|
|
||||||
|
|
||||||
|
<link rel="preconnect" href="https://use.fontawesome.com/" />
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||||
<link rel="preconnect" href="https://maps.google.com" />
|
<link rel="preconnect" href="https://maps.google.com" />
|
||||||
<link rel="preconnect" href="https://ajax.googleapis.com" />
|
<link rel="preconnect" href="https://ajax.googleapis.com" />
|
||||||
|
@ -4,7 +4,8 @@
|
|||||||
class="nav-link dropdown-toggle"
|
class="nav-link dropdown-toggle"
|
||||||
id="NavItem{$ID}"
|
id="NavItem{$ID}"
|
||||||
role="button"
|
role="button"
|
||||||
data-toggle="dropdown"
|
data-toggle="hover"
|
||||||
|
data-allow-click="true"
|
||||||
aria-haspopup="true"
|
aria-haspopup="true"
|
||||||
aria-expanded="false"
|
aria-expanded="false"
|
||||||
href="{$Link}"
|
href="{$Link}"
|
||||||
|
@ -1,30 +1,30 @@
|
|||||||
<div class="sc-links">
|
<div class="sc-links">
|
||||||
<% if $Facebook %>
|
<% if $Facebook %>
|
||||||
<a href="$Facebook.URL" title="Facebook" target="_blank">
|
<a href="$Facebook.LinkURL" title="Facebook" target="_blank">
|
||||||
<i class="fab fa-facebook"></i>
|
<i class="fab fa-facebook"></i>
|
||||||
<i class="sr-only">Facebook</i>
|
<i class="sr-only">Facebook</i>
|
||||||
</a>
|
</a>
|
||||||
<% end_if %>
|
<% end_if %>
|
||||||
<% if $LinkedIn %>
|
<% if $LinkedIn %>
|
||||||
<a href="$LinkedIn.URL" title="LinkedIn" target="_blank">
|
<a href="$LinkedIn.LinkURL" title="LinkedIn" target="_blank">
|
||||||
<i class="fab fa-linkedin"></i>
|
<i class="fab fa-linkedin"></i>
|
||||||
<i class="sr-only">LinkedIn</i>
|
<i class="sr-only">LinkedIn</i>
|
||||||
</a>
|
</a>
|
||||||
<% end_if %>
|
<% end_if %>
|
||||||
<% if $GooglePlus %>
|
<% if $GooglePlus %>
|
||||||
<a href="$GooglePlus.URL" title="Google+" target="_blank">
|
<a href="$GooglePlus.LinkURL" title="Google+" target="_blank">
|
||||||
<i class="fab fa-google-plus-g"></i>
|
<i class="fab fa-google-plus-g"></i>
|
||||||
<i class="sr-only">Google+</i>
|
<i class="sr-only">Google+</i>
|
||||||
</a>
|
</a>
|
||||||
<% end_if %>
|
<% end_if %>
|
||||||
<% if $Instagram %>
|
<% if $Instagram %>
|
||||||
<a href="$Instagram.URL" title="Instagram" target="_blank">
|
<a href="$Instagram.LinkURL" title="Instagram" target="_blank">
|
||||||
<i class="fab fa-instagram"></i>
|
<i class="fab fa-instagram"></i>
|
||||||
<i class="sr-only">Instagram</i>
|
<i class="sr-only">Instagram</i>
|
||||||
</a>
|
</a>
|
||||||
<% end_if %>
|
<% end_if %>
|
||||||
<% if $Twitter %>
|
<% if $Twitter %>
|
||||||
<a href="$Twitter.URL" title="Twitter" target="_blank">
|
<a href="$Twitter.LinkURL" title="Twitter" target="_blank">
|
||||||
<i class="fab fa-twitter"></i>
|
<i class="fab fa-twitter"></i>
|
||||||
<i class="sr-only">Twitter</i>
|
<i class="sr-only">Twitter</i>
|
||||||
</a>
|
</a>
|
||||||
|
@ -10,31 +10,49 @@
|
|||||||
|
|
||||||
<div class="wrapper">
|
<div class="wrapper">
|
||||||
<header id="Header">
|
<header id="Header">
|
||||||
<div class="$DefaultContainer">
|
|
||||||
<% include Header %>
|
<% include Header %>
|
||||||
</div>
|
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<main id="MainContent" data-ajax-region="LayoutAjax">
|
<main id="MainContent" data-ajax-region="LayoutAjax">
|
||||||
<% if $ParentID %>
|
<% if $ParentID %>
|
||||||
|
<div id="PageBreadcumbs">
|
||||||
$Breadcrumbs
|
$Breadcrumbs
|
||||||
|
</div>
|
||||||
|
<% else_if $ClassName != 'Site\Pages\HomePage' %>
|
||||||
|
<div id="PageBreadcumbs">
|
||||||
|
<nav class="breadcrumbs $DefaultContainer" aria-label="breadcrumb">
|
||||||
|
<ol class="breadcrumb">
|
||||||
|
<li class="breadcrumb-item">
|
||||||
|
<a href="/">Home</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="breadcrumb-item current active" aria-current="page">
|
||||||
|
<a href="$Link" class="breadcrumb-2">
|
||||||
|
$MenuTitle
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
<% end_if %>
|
<% end_if %>
|
||||||
|
|
||||||
<% if $SideBarView && $SideBarView.Widgets.Count %>
|
<% if $SideBarView && $SideBarView.Widgets.Count %>
|
||||||
<div class="$DefaultContainer">
|
<div class="content-holder">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-8">
|
<div class="col-md-9">
|
||||||
$Layout
|
$Layout
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-4">
|
<div class="col-md-3">
|
||||||
<div class="sidebar page-content">
|
<div class="page-content-sidebar page-content">
|
||||||
$SideBarView
|
$SideBarView
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<% else %>
|
<% else %>
|
||||||
|
<div class="content-holder">
|
||||||
$Layout
|
$Layout
|
||||||
|
</div>
|
||||||
<% end_if %>
|
<% end_if %>
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
|
@ -4,13 +4,13 @@
|
|||||||
<% if $Address2 %>
|
<% if $Address2 %>
|
||||||
<div class="addr2">{$Address2}</div>
|
<div class="addr2">{$Address2}</div>
|
||||||
<% end_if %>
|
<% end_if %>
|
||||||
<% if $City || $PostalCode %>
|
<% if $City || $Suburb || $PostalCode || $Postcode %>
|
||||||
<div class="city">
|
<div class="city">
|
||||||
{$City}, {$State} {$PostalCode}
|
{$City}{$Suburb}, {$State} {$PostalCode}{$Postcode}
|
||||||
</div>
|
</div>
|
||||||
<% end_if %>
|
<% end_if %>
|
||||||
<% if $Country %>
|
<% if $Country %>
|
||||||
<div class="d-none">{$Country}</div>
|
<div class="country d-none">{$Country}</div>
|
||||||
<% end_if %>
|
<% end_if %>
|
||||||
<% if $PhoneNumber %>
|
<% if $PhoneNumber %>
|
||||||
<% with $PhoneNumber %>
|
<% with $PhoneNumber %>
|
||||||
|
3
app/templates/Site/Widgets/ContentWidget.ss
Normal file
3
app/templates/Site/Widgets/ContentWidget.ss
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<% if $Text %>
|
||||||
|
<div class="typography">$Text</div>
|
||||||
|
<% end_if %>
|
9
app/templates/Site/Widgets/ElementWidget.ss
Normal file
9
app/templates/Site/Widgets/ElementWidget.ss
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<% if $Element %>
|
||||||
|
<% with $Element %>
|
||||||
|
<div class="element $SimpleClassName.LowerCase<% if $StyleVariant %> $StyleVariant<% end_if %><% if $ExtraClass %> $ExtraClass<% end_if %>" id="$Anchor">
|
||||||
|
<div class="element-container<% if $ContainerClass %> $ContainerClass<% end_if %>">
|
||||||
|
$forTemplate
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<% end_with %>
|
||||||
|
<% end_if %>
|
@ -1,6 +1,15 @@
|
|||||||
<% if $Submenu %>
|
<% if $Submenu %>
|
||||||
<nav>
|
<nav>
|
||||||
<ul class="nav flex-column">
|
<ul class="nav flex-column">
|
||||||
|
<% with $Page.Level(1) %>
|
||||||
|
<li class="nav-item-level1 nav-item {$CSSClass} $ExtraClass <% if $isCurrent || $isSection %> active<% end_if %>">
|
||||||
|
<b class="nav-link">
|
||||||
|
$MenuTitle.XML
|
||||||
|
<% if $isCurrent || $isSection %><i class="sr-only">(current)</i><% end_if %>
|
||||||
|
</b>
|
||||||
|
</li>
|
||||||
|
<% end_with %>
|
||||||
|
|
||||||
<% loop $Submenu %>
|
<% loop $Submenu %>
|
||||||
<% include NavItem %>
|
<% include NavItem %>
|
||||||
<% end_loop %>
|
<% end_loop %>
|
||||||
|
@ -69,6 +69,11 @@
|
|||||||
"foundation-emails": "^2.2.1",
|
"foundation-emails": "^2.2.1",
|
||||||
"gijgo": "^1.9.13",
|
"gijgo": "^1.9.13",
|
||||||
"html-webpack-plugin": "^4.0.0-beta.11",
|
"html-webpack-plugin": "^4.0.0-beta.11",
|
||||||
|
"imagemin-gifsicle": "^7.0.0",
|
||||||
|
"imagemin-jpegtran": "^6.0.0",
|
||||||
|
"imagemin-optipng": "^7.1.0",
|
||||||
|
"imagemin-svgo": "^7.0.0",
|
||||||
|
"imagemin-webpack": "^5.1.1",
|
||||||
"jquery": "^3.4.1",
|
"jquery": "^3.4.1",
|
||||||
"jquery-hammerjs": "^2.0.0",
|
"jquery-hammerjs": "^2.0.0",
|
||||||
"jquery-hoverintent": "*",
|
"jquery-hoverintent": "*",
|
||||||
|
@ -17,20 +17,21 @@ const FaviconsWebpackPlugin = require('favicons-webpack-plugin');
|
|||||||
|
|
||||||
const TerserPlugin = require('terser-webpack-plugin');
|
const TerserPlugin = require('terser-webpack-plugin');
|
||||||
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');
|
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');
|
||||||
|
const ImageminPlugin = require('imagemin-webpack');
|
||||||
|
|
||||||
let plugins = [
|
let plugins = [
|
||||||
new webpack.DefinePlugin({
|
new webpack.DefinePlugin({
|
||||||
'process.env': {
|
'process.env': {
|
||||||
'NODE_ENV': JSON.stringify('production')
|
NODE_ENV: JSON.stringify('production'),
|
||||||
}
|
},
|
||||||
}),
|
}),
|
||||||
new webpack.LoaderOptionsPlugin({
|
new webpack.LoaderOptionsPlugin({
|
||||||
minimize: true,
|
minimize: true,
|
||||||
debug: false
|
debug: false,
|
||||||
}),
|
}),
|
||||||
new ExtractTextPlugin({
|
new ExtractTextPlugin({
|
||||||
filename: 'css/[name].css',
|
filename: 'css/[name].css',
|
||||||
allChunks: true
|
allChunks: true,
|
||||||
}),
|
}),
|
||||||
|
|
||||||
new FaviconsWebpackPlugin({
|
new FaviconsWebpackPlugin({
|
||||||
@ -51,8 +52,8 @@ let plugins = [
|
|||||||
opengraph: true,
|
opengraph: true,
|
||||||
twitter: true,
|
twitter: true,
|
||||||
yandex: true,
|
yandex: true,
|
||||||
windows: true
|
windows: true,
|
||||||
}
|
},
|
||||||
}),
|
}),
|
||||||
new OptimizeCssAssetsPlugin({
|
new OptimizeCssAssetsPlugin({
|
||||||
//assetNameRegExp: /\.optimize\.css$/g,
|
//assetNameRegExp: /\.optimize\.css$/g,
|
||||||
@ -71,25 +72,59 @@ let plugins = [
|
|||||||
discardOverridden: true,
|
discardOverridden: true,
|
||||||
discardDuplicates: true,
|
discardDuplicates: true,
|
||||||
discardComments: {
|
discardComments: {
|
||||||
removeAll: true
|
removeAll: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
canPrint: true
|
canPrint: true,
|
||||||
|
}),
|
||||||
|
new ImageminPlugin({
|
||||||
|
bail: false, // Ignore errors on corrupted images
|
||||||
|
cache: true,
|
||||||
|
filter: (source, sourcePath) => {
|
||||||
|
if (source.byteLength < 512000) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
imageminOptions: {
|
||||||
|
plugins: [
|
||||||
|
['gifsicle', { interlaced: true }],
|
||||||
|
['jpegtran', { progressive: true }],
|
||||||
|
['optipng', { optimizationLevel: 5 }],
|
||||||
|
[
|
||||||
|
'svgo',
|
||||||
|
{
|
||||||
|
plugins: [
|
||||||
|
{
|
||||||
|
removeViewBox: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
],
|
||||||
|
},
|
||||||
}),
|
}),
|
||||||
];
|
];
|
||||||
|
|
||||||
// add themes favicons
|
// add themes favicons
|
||||||
commonVariables.themes.forEach((theme) => {
|
commonVariables.themes.forEach(theme => {
|
||||||
const faviconPath = path.join(__dirname, theme, conf.SRC, 'favicon.png');
|
const faviconPath = path.join(__dirname, theme, conf.SRC, 'favicon.png');
|
||||||
if (filesystem.existsSync(faviconPath)) {
|
if (filesystem.existsSync(faviconPath)) {
|
||||||
plugins.push(new FaviconsWebpackPlugin({
|
plugins.push(
|
||||||
|
new FaviconsWebpackPlugin({
|
||||||
title: 'Webpack App',
|
title: 'Webpack App',
|
||||||
logo: faviconPath,
|
logo: faviconPath,
|
||||||
prefix: '/' + theme + '-icons/',
|
prefix: '/' + theme + '-icons/',
|
||||||
emitStats: false,
|
emitStats: false,
|
||||||
persistentCache: true,
|
persistentCache: true,
|
||||||
inject: false,
|
inject: false,
|
||||||
statsFilename: path.join(conf.APPDIR, conf.DIST, theme + '-icons', 'iconstats.json'),
|
statsFilename: path.join(
|
||||||
|
conf.APPDIR,
|
||||||
|
conf.DIST,
|
||||||
|
theme + '-icons',
|
||||||
|
'iconstats.json',
|
||||||
|
),
|
||||||
icons: {
|
icons: {
|
||||||
android: true,
|
android: true,
|
||||||
appleIcon: true,
|
appleIcon: true,
|
||||||
@ -100,9 +135,10 @@ commonVariables.themes.forEach((theme) => {
|
|||||||
opengraph: true,
|
opengraph: true,
|
||||||
twitter: true,
|
twitter: true,
|
||||||
yandex: true,
|
yandex: true,
|
||||||
windows: true
|
windows: true,
|
||||||
}
|
},
|
||||||
}));
|
}),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -110,9 +146,10 @@ module.exports = merge(common, {
|
|||||||
mode: 'production',
|
mode: 'production',
|
||||||
optimization: {
|
optimization: {
|
||||||
namedModules: true, // NamedModulesPlugin()
|
namedModules: true, // NamedModulesPlugin()
|
||||||
splitChunks: { // CommonsChunkPlugin()
|
splitChunks: {
|
||||||
|
// CommonsChunkPlugin()
|
||||||
name: 'vendor',
|
name: 'vendor',
|
||||||
minChunks: 2
|
minChunks: 2,
|
||||||
},
|
},
|
||||||
noEmitOnErrors: true, // NoEmitOnErrorsPlugin
|
noEmitOnErrors: true, // NoEmitOnErrorsPlugin
|
||||||
concatenateModules: true, //ModuleConcatenationPlugin
|
concatenateModules: true, //ModuleConcatenationPlugin
|
||||||
@ -129,7 +166,7 @@ module.exports = merge(common, {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
|
|
||||||
devtool: '',
|
devtool: '',
|
||||||
@ -141,66 +178,78 @@ module.exports = merge(common, {
|
|||||||
},
|
},
|
||||||
|
|
||||||
module: {
|
module: {
|
||||||
rules: [{
|
rules: [
|
||||||
|
{
|
||||||
test: /\.s?css$/,
|
test: /\.s?css$/,
|
||||||
use: ExtractTextPlugin.extract({
|
use: ExtractTextPlugin.extract({
|
||||||
fallback: "style-loader",
|
fallback: 'style-loader',
|
||||||
use: [{
|
use: [
|
||||||
|
{
|
||||||
loader: 'css-loader',
|
loader: 'css-loader',
|
||||||
options: {
|
options: {
|
||||||
sourceMap: false
|
sourceMap: false,
|
||||||
}
|
},
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
loader: 'postcss-loader',
|
loader: 'postcss-loader',
|
||||||
options: {
|
options: {
|
||||||
sourceMap: false,
|
sourceMap: false,
|
||||||
plugins: [
|
plugins: [autoprefixer()],
|
||||||
autoprefixer()
|
},
|
||||||
]
|
},
|
||||||
}
|
{
|
||||||
}, {
|
loader: 'resolve-url-loader',
|
||||||
loader: 'resolve-url-loader'
|
},
|
||||||
}, {
|
{
|
||||||
loader: 'sass-loader',
|
loader: 'sass-loader',
|
||||||
options: {
|
options: {
|
||||||
sourceMap: false
|
sourceMap: false,
|
||||||
}
|
},
|
||||||
}, ]
|
},
|
||||||
})
|
],
|
||||||
}, {
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
test: /fontawesome([^.]+).(ttf|otf|eot|svg|woff(2)?)(\?[a-z0-9]+)?$/,
|
test: /fontawesome([^.]+).(ttf|otf|eot|svg|woff(2)?)(\?[a-z0-9]+)?$/,
|
||||||
use: [{
|
use: [
|
||||||
|
{
|
||||||
loader: 'file-loader',
|
loader: 'file-loader',
|
||||||
options: {
|
options: {
|
||||||
name: '[name].[ext]',
|
name: '[name].[ext]',
|
||||||
outputPath: 'fonts/',
|
outputPath: 'fonts/',
|
||||||
publicPath: '../fonts/'
|
publicPath: '../fonts/',
|
||||||
}
|
},
|
||||||
}]
|
},
|
||||||
}, {
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
test: /\.(ttf|otf|eot|svg|woff(2)?)$/,
|
test: /\.(ttf|otf|eot|svg|woff(2)?)$/,
|
||||||
use: [{
|
use: [
|
||||||
|
{
|
||||||
loader: 'file-loader',
|
loader: 'file-loader',
|
||||||
options: {
|
options: {
|
||||||
name: '[name].[ext]',
|
name: '[name].[ext]',
|
||||||
outputPath: 'fonts/',
|
outputPath: 'fonts/',
|
||||||
publicPath: '../fonts/'
|
publicPath: '../fonts/',
|
||||||
}
|
},
|
||||||
}]
|
},
|
||||||
}, {
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
test: /\.(png|jpg|jpeg|gif|svg)$/,
|
test: /\.(png|jpg|jpeg|gif|svg)$/,
|
||||||
loader: 'file-loader',
|
loader: 'file-loader',
|
||||||
options: {
|
options: {
|
||||||
name: '[name].[ext]',
|
name: '[name].[ext]',
|
||||||
outputPath: 'img/',
|
outputPath: 'img/',
|
||||||
publicPath: '../img/'
|
publicPath: '../img/',
|
||||||
/*,
|
/*,
|
||||||
name(file) {
|
name(file) {
|
||||||
//return 'public/[path][name].[ext]';
|
//return 'public/[path][name].[ext]';
|
||||||
return '[hash].[ext]';
|
return '[hash].[ext]';
|
||||||
},*/
|
},*/
|
||||||
},
|
},
|
||||||
}, ]
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
|
|
||||||
plugins: plugins,
|
plugins: plugins,
|
||||||
|
Loading…
Reference in New Issue
Block a user