diff --git a/app/_config/webpack.yml b/app/_config/webpack.yml
index 7341a0c..0038d1f 100644
--- a/app/_config/webpack.yml
+++ b/app/_config/webpack.yml
@@ -10,4 +10,5 @@ Site\Templates\WebpackTemplateProvider:
SRC: client/src
DIST: client/dist
TYPESJS: client/src/js/types
- TYPESSCSS: client/src/scss/types
\ No newline at end of file
+ TYPESSCSS: client/src/scss/types
+ webp: false
diff --git a/app/src/Elements/MapElement.php b/app/src/Elements/MapElement.php
index 1b21350..64451e4 100644
--- a/app/src/Elements/MapElement.php
+++ b/app/src/Elements/MapElement.php
@@ -74,7 +74,7 @@ class MapElement extends ElementContent
return $fields;
}
- public function MapAPIKey(): string
+ public static function MapAPIKey(): string
{
$type = self::config()->get('map_type');
diff --git a/app/src/Extensions/LeftAndMainExtension.php b/app/src/Extensions/LeftAndMainExtension.php
index dd22b81..86383a3 100644
--- a/app/src/Extensions/LeftAndMainExtension.php
+++ b/app/src/Extensions/LeftAndMainExtension.php
@@ -3,11 +3,24 @@
namespace Site\Extensions;
+use SilverStripe\Core\Config\Config;
use SilverStripe\Core\Extension;
+use SilverStripe\FontAwesome\FontAwesomeField;
+use SilverStripe\View\Requirements;
+use Site\Templates\DeferredRequirements;
class LeftAndMainExtension extends Extension
{
public function init()
{
+ $config = Config::inst()->get(DeferredRequirements::class);
+ // App libs
+ if (!$config['nofontawesome']) {
+ $v = !isset($config['fontawesome_version']) || !$config['fontawesome_version']
+ ? Config::inst()->get(FontAwesomeField::class, 'version')
+ : $config['fontawesome_version'];
+
+ Requirements::css('//use.fontawesome.com/releases/v'.$v.'/css/all.css');
+ }
}
-}
\ No newline at end of file
+}
diff --git a/app/src/Templates/WebpackTemplateProvider.php b/app/src/Templates/WebpackTemplateProvider.php
index d91a5a6..79826b1 100644
--- a/app/src/Templates/WebpackTemplateProvider.php
+++ b/app/src/Templates/WebpackTemplateProvider.php
@@ -31,6 +31,7 @@ class WebpackTemplateProvider implements TemplateGlobalProvider
* @var string assets static files directory
*/
private static $dist = 'client/dist';
+ private static $webp = false;
/**
* @return array
@@ -81,7 +82,20 @@ class WebpackTemplateProvider implements TemplateGlobalProvider
public static function resourcesURL($link = null): string
{
- return Controller::join_links(Director::baseURL(), '/resources/'.self::projectName().'/client/dist/img/', $link);
+ $cfg = self::config();
+
+ if ($cfg['webp'] && !self::isActive()) {
+ $link = str_replace(['.png','.jpg','.jpeg'], '.webp', $link);
+ }
+
+ return Controller::join_links(
+ Director::baseURL(),
+ '/resources/',
+ self::projectName(),
+ $cfg['dist'],
+ 'img',
+ $link
+ );
}
diff --git a/app/src/Tests/TestServer.php b/app/src/Tests/TestServer.php
index db1bb7b..88c5721 100644
--- a/app/src/Tests/TestServer.php
+++ b/app/src/Tests/TestServer.php
@@ -80,6 +80,13 @@ class TestServer extends BuildTask
echo self::error('Assets dir '.ASSETS_DIR.' dir is no writable!');
}
+ if (function_exists('imagewebp')) {
+ echo self::success('WebP is available');
+ } else {
+ echo self::error('WebP is not available');
+ }
+
+
die();
}
diff --git a/app/src/Traits/PaginatedListing.php b/app/src/Traits/PaginatedListing.php
new file mode 100644
index 0000000..0f8a5df
--- /dev/null
+++ b/app/src/Traits/PaginatedListing.php
@@ -0,0 +1,18 @@
+getRequest()->requestVars();
+ $vars = array_filter($vars);
+ $vars['page'] = $pageID ? $pageID : '2';
+
+ return $this->Link('?'.http_build_query($vars));
+ }
+}
diff --git a/app/templates/Includes/NavItem.ss b/app/templates/Includes/NavItem.ss
index 6b1c772..f04a6c5 100644
--- a/app/templates/Includes/NavItem.ss
+++ b/app/templates/Includes/NavItem.ss
@@ -9,7 +9,6 @@
aria-haspopup="true"
aria-expanded="false"
href="{$Link}"
- title="$Title.XML"
>
$MenuTitle.XML
<% if $isCurrent || $isSection %>(current)<% end_if %>
diff --git a/app/templates/Site/Objects/NotificationsList.ss b/app/templates/Site/Objects/NotificationsList.ss
index 0b3e0e7..2b80975 100644
--- a/app/templates/Site/Objects/NotificationsList.ss
+++ b/app/templates/Site/Objects/NotificationsList.ss
@@ -3,11 +3,7 @@
<% loop $NotificationsToday %>
-
-
-
-
- <% if $Title %>
+ <% if $DisplayTitle && $Title %>
$Title
<% end_if %>
@@ -25,6 +21,10 @@
<% end_with %>
<% end_if %>
+
+
+
+
<% end_loop %>
diff --git a/composer.json b/composer.json
index b8556d7..ea97e78 100755
--- a/composer.json
+++ b/composer.json
@@ -44,7 +44,8 @@
"a2nt/silverstripe-font-awesome-field": "dev-master",
"a2nt/silverstripe-mapboxfield": "dev-master",
"a2nt/silverstripe-progressivewebapp": "dev-master",
- "bummzack/sortablefile": "*"
+ "bummzack/sortablefile": "*",
+ "showpro/silverstripe-seo-images": "*"
},
"require-dev": {
"phpunit/phpunit": "^5.7",
diff --git a/package.json b/package.json
index 773deea..aaa1472 100755
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "ss-webpack-boilerplate",
- "version": "2.2.1",
+ "version": "2.0.2",
"description": "Lets you create SilverStripe faster",
"author": "Tony Air ",
"license": "MIT",
@@ -32,7 +32,7 @@
],
"dependencies": {
"@a2nt/meta-lightbox": "^2.2.1",
- "@a2nt/ss-bootstrap-ui-webpack-boilerplate": "^2.2.1",
+ "@a2nt/ss-bootstrap-ui-webpack-boilerplate": "^2.3.1",
"bootbox": "^4.4.0",
"bootstrap": "^4.5.0",
"bootstrap-confirmation2": "^4.1.0",
@@ -40,6 +40,7 @@
"bootstrap-offcanvas": "^1.0.0",
"bootstrap-table": "^1.16.0",
"bootstrap-timepicker": "^0.5.2",
+ "exif-js": "^2.3.0",
"font-awesome": "^4.7.0",
"hammerjs": "^2.0.8",
"inputmask": "^5.0.3",
@@ -50,23 +51,25 @@
"jquery.appear": "^1.0.1",
"mapbox-gl": "^1.11.0",
"material-design-color": "^2.3.2",
+ "moment": "^2.27.0",
+ "offcanvas-bootstrap": "^2.5.2",
"popper.js": "*",
"select2": "^4.0.13",
+ "setimmediate": "^1.0.5",
"smooth-scroll": "^14.2.1",
"sticky-sidebar": "^3.3.1",
+ "tablednd": "^1.0.3",
"yarn": "^1.22.4"
},
"devDependencies": {
"@a2nt/image-sprite-webpack-plugin": "^0.2.5",
- "@babel/core": "^7.10.2",
- "@babel/plugin-proposal-object-rest-spread": "^7.10.1",
- "@babel/plugin-transform-react-jsx": "^7.10.1",
- "@babel/preset-env": "^7.10.2",
+ "@babel/core": "^7.10.4",
+ "@babel/plugin-proposal-object-rest-spread": "^7.10.4",
+ "@babel/plugin-transform-react-jsx": "^7.10.4",
+ "@babel/preset-env": "^7.10.4",
"@google/markerclusterer": "^1.0.3",
"animate.css": "^3.7.2",
- "ansi-html": "^0.0.7",
- "ansi-regex": "^5.0.0",
- "autoprefixer": "^9.8.0",
+ "autoprefixer": "^9.8.4",
"babel-eslint": "^8.2.6",
"babel-loader": "^8.1.0",
"copy-webpack-plugin": "^4.6.0",
@@ -74,21 +77,22 @@
"cross-env": "^5.2.1",
"css-loader": "^3.6.0",
"eslint": "^4.19.1",
- "eslint-plugin-import": "^2.21.2",
+ "eslint-plugin-import": "^2.22.0",
"eslint-plugin-jquery": "^1.5.1",
- "eslint-plugin-react": "^7.20.0",
+ "eslint-plugin-react": "^7.20.3",
"exports-loader": "^0.7.0",
"favicons-webpack-plugin": "0.0.9",
"file-loader": "^5.1.0",
"font-awesome": "^4.7.0",
"hard-source-webpack-plugin": "^0.13.1",
- "html-entities": "^1.3.1",
"html-webpack-plugin": "^4.3.0",
"imagemin-gifsicle": "^7.0.0",
"imagemin-jpegtran": "^6.0.0",
"imagemin-optipng": "^7.1.0",
"imagemin-svgo": "^7.1.0",
+ "imagemin-webp": "^6.0.0",
"imagemin-webpack": "^5.1.1",
+ "img-optimize-loader": "^1.0.4",
"loglevel": "^1.6.8",
"mini-css-extract-plugin": "^0.9.0",
"node-sass": "^4.14.1",
@@ -102,8 +106,6 @@
"sass-lint-fix": "^1.12.1",
"sass-loader": "^8.0.2",
"script-ext-html-webpack-plugin": "^2.1.4",
- "sockjs-client": "^1.4.0",
- "strip-ansi": "^6.0.0",
"style-loader": "^0.19.1",
"svg-url-loader": "^2.3.3",
"terser-webpack-plugin": "^2.3.7",
diff --git a/test.php b/test.php
index b686799..a1ec5b4 100644
--- a/test.php
+++ b/test.php
@@ -5,9 +5,9 @@ ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
require_once('vendor/autoload.php');
-require_once('framework/core/Constants.php');
+//require_once('vendor/silverstripe/framework/src/Core/Constants.php');
-require_once('app/code/Tasks/TestServer.php');
+require_once('app/src/Tests/TestServer.php');
$req = new \SilverStripe\Control\NullHTTPRequest();
diff --git a/webpack.config.common.js b/webpack.config.common.js
index 09a6ded..a52d9a2 100755
--- a/webpack.config.common.js
+++ b/webpack.config.common.js
@@ -12,7 +12,6 @@ const filesystem = require('fs');
const includes = {};
const modules = [
- path.resolve(__dirname, 'public'),
path.resolve(__dirname, conf.APPDIR, 'client', 'src'),
path.resolve(__dirname, conf.APPDIR, 'client', 'src', 'js'),
path.resolve(__dirname, conf.APPDIR, 'client', 'src', 'scss'),
@@ -20,9 +19,11 @@ const modules = [
path.resolve(__dirname, conf.APPDIR, 'client', 'src', 'thirdparty'),
path.resolve(__dirname, conf.APPDIR, 'client', 'node_modules'),
path.resolve(__dirname, 'node_modules'),
+ path.resolve(__dirname),
+ path.resolve(__dirname, 'public'),
];
-const _addAppFiles = theme => {
+const _addAppFiles = (theme) => {
const dirPath = path.resolve(__dirname, theme);
const themeName = path.basename(theme);
@@ -44,11 +45,11 @@ const _addAppFiles = theme => {
modules.push(path.join(dirPath, 'client', 'src', 'img'));
modules.push(path.join(dirPath, 'client', 'src', 'thirdparty'));
- const _getAllFilesFromFolder = function(dir, includeSubFolders = true) {
+ const _getAllFilesFromFolder = function (dir, includeSubFolders = true) {
const dirPath = path.resolve(__dirname, dir);
let results = [];
- filesystem.readdirSync(dirPath).forEach(file => {
+ filesystem.readdirSync(dirPath).forEach((file) => {
if (file.charAt(0) === '_') {
return;
}
@@ -72,7 +73,7 @@ const _addAppFiles = theme => {
const typesJSPath = path.join(theme, conf.TYPESJS);
if (filesystem.existsSync(typesJSPath)) {
const pageScripts = _getAllFilesFromFolder(typesJSPath, true);
- pageScripts.forEach(file => {
+ pageScripts.forEach((file) => {
includes[`${themeName}_${path.basename(file, '.js')}`] = file;
});
}
@@ -81,7 +82,7 @@ const _addAppFiles = theme => {
const typesSCSSPath = path.join(theme, conf.TYPESSCSS);
if (filesystem.existsSync(typesSCSSPath)) {
const scssIncludes = _getAllFilesFromFolder(typesSCSSPath, true);
- scssIncludes.forEach(file => {
+ scssIncludes.forEach((file) => {
includes[`${themeName}_${path.basename(file, '.scss')}`] = file;
});
}
@@ -90,7 +91,7 @@ const _addAppFiles = theme => {
_addAppFiles(conf.APPDIR);
// add themes
-commonVariables.themes.forEach(theme => {
+commonVariables.themes.forEach((theme) => {
_addAppFiles(theme);
});
diff --git a/webpack.config.dev.js b/webpack.config.dev.js
index 2dbec6f..0bc214e 100755
--- a/webpack.config.dev.js
+++ b/webpack.config.dev.js
@@ -77,7 +77,7 @@ const config = merge.strategy({
],
},
{
- test: /\.(gif|png|jpg|jpeg|ttf|otf|eot|svg|woff(2)?)$/,
+ test: /\.(gif|png|jpg|jpeg|ttf|otf|eot|svg|webp|woff(2)?)$/,
use: [
{
loader: 'file-loader',
diff --git a/webpack.config.prod.js b/webpack.config.prod.js
index cca6f5d..34d6766 100755
--- a/webpack.config.prod.js
+++ b/webpack.config.prod.js
@@ -102,10 +102,11 @@ let plugins = [
],
},
],
+ ['webp', { quality: 100 }],
],
},
}),
- new ImageSpritePlugin({
+ /*new ImageSpritePlugin({
exclude: /exclude|original|default-|icons|sprite/,
commentOrigin: false,
compress: true,
@@ -115,11 +116,11 @@ let plugins = [
//outputPath: path.join(__dirname, conf.APPDIR, conf.DIST),
outputFilename: 'img/sprite-[hash].png',
padding: 0,
- }),
+ }),*/
];
// add themes favicons
-commonVariables.themes.forEach(theme => {
+commonVariables.themes.forEach((theme) => {
const faviconPath = path.join(__dirname, theme, conf.SRC, 'favicon.png');
if (filesystem.existsSync(faviconPath)) {
plugins.push(
@@ -272,17 +273,24 @@ module.exports = merge(common, {
],
},
{
- test: /\.(png|jpg|jpeg|gif|svg)$/,
+ test: /\.(png|webp|jpg|jpeg|gif|svg)$/,
+ loader: 'img-optimize-loader',
+ options: {
+ compress: {
+ // This will take more time and get smaller images.
+ mode: 'high', // 'lossless', 'low'
+ disableOnDevelopment: true,
+ webp: conf['webp'],
+ },
+ },
+ },
+ {
+ test: /\.(png|webp|jpg|jpeg|gif|svg)$/,
loader: 'file-loader',
options: {
- name: '[name].[ext]',
+ name: conf['webp'] ? '[name].webp' : '[name].[ext]',
outputPath: 'img/',
publicPath: '../img/',
- /*,
- name(file) {
- //return 'public/[path][name].[ext]';
- return '[hash].[ext]';
- },*/
},
},
],