Made separate repository for UI kit

This commit is contained in:
Tony Air 2019-06-08 22:54:43 +07:00
parent f62361099c
commit bf563b25a2
37 changed files with 1073 additions and 828 deletions

1
.gitignore vendored
View File

@ -10,3 +10,4 @@
/silverstripe-cache /silverstripe-cache
yarn-error\.log yarn-error\.log
package-lock.json package-lock.json
/app/client

View File

@ -3,6 +3,37 @@
## Simple WebPack boiler plate for SilverStripe ## Simple WebPack boiler plate for SilverStripe
Checkout files at /app/ folder for details Checkout files at /app/ folder for details
Take a look to https://github.com/a2nt/webpack-bootstrap-ui-kit.git for UI Kit details
### Requirements:
+ composer
+ node
+ yarn
### Installation:
```
git clone https://github.com/a2nt/silverstripe-webpack.git
cd silverstripe-webpack
composer install
npm install
cd app
git clone https://github.com/a2nt/webpack-bootstrap-ui-kit.git ./client
cd ..
```
+ edit .env, robots.txt, humans.txt, cache.appcache, manifest.json and package.json to setup your own project
## Installing composer at some cpanel hostings
```
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php -r "if (hash_file('SHA384', 'composer-setup.php') === '544e09ee996cdf60ece3804abc52599c22b1f40f4323403c44d44fdfdd586475ca9813a858088ffbc1f233e9b180f061') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
php composer-setup.php
php -r "unlink('composer-setup.php');"
php -d memory_limit=-1 composer.phar update --ignore-platform-reqs
```
### Features: ### Features:
+ You can use /app/_config/webpack.yml to setup webpack server parameters which will be used by webpack server and by SilverStripe to serve static content + You can use /app/_config/webpack.yml to setup webpack server parameters which will be used by webpack server and by SilverStripe to serve static content
@ -47,35 +78,13 @@ Checkout files at /app/ folder for details
+ /app/clent/src/scss (Your styling to be compiled) + /app/clent/src/scss (Your styling to be compiled)
+ /app/clent/src/scss/_components (Your custom SCSS components) + /app/clent/src/scss/_components (Your custom SCSS components)
+ /app/clent/src/scss/app.scss (main application file to include site-wide components) + /app/clent/src/scss/app.scss (main application file to include site-wide components)
+ /app/clent/src/scss/_variables.sccs (your custom variables, ex. bootstrap) + /app/clent/src/scss/_variables.sccs (your custom and bootstrap variables)
+ /app/clent/src/scss/_layout.sccs (Your site-wide styling) + /app/clent/src/scss/_layout.sccs (Your site-wide styling)
### Requirements:
+ composer + /app/client/src/index.html UI demo page
+ yarn + /app/client/src/html HTML templates to build UI demo
### Instalation:
Install composer:
```
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php -r "if (hash_file('SHA384', 'composer-setup.php') === '544e09ee996cdf60ece3804abc52599c22b1f40f4323403c44d44fdfdd586475ca9813a858088ffbc1f233e9b180f061') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
php composer-setup.php
php -r "unlink('composer-setup.php');"
php -d memory_limit=-1 composer.phar update --ignore-platform-reqs
```
```
git clone https://github.com/a2nt/silverstripe-webpack.git
cd silverstripe-webpack
composer install
npm install
```
+ edit robots.txt, humans.txt, cache.appcache, manifest.json and package.json to setup your own project
### Commands: ### Commands:

View File

File diff suppressed because one or more lines are too long

View File

View File

@ -1 +0,0 @@
module.exports = "../fonts/fontawesome-webfont.eot";

View File

@ -1 +0,0 @@
module.exports = "../fonts/fontawesome-webfont.svg";

View File

@ -1 +0,0 @@
module.exports = "../fonts/fontawesome-webfont.ttf";

View File

@ -1 +0,0 @@
module.exports = "../fonts/fontawesome-webfont.woff";

View File

@ -1 +0,0 @@
module.exports = "../fonts/fontawesome-webfont.woff2";

View File

@ -1 +1 @@
{"hash":"3deb17371acdc75398d81da38fad464c","version":"0.0.9","optionHash":"48da8109542971737c0c3794682790d4","result":{"outputFilePrefix":"/icons/","html":["<meta name=\"mobile-web-app-capable\" content=\"yes\">","<meta name=\"theme-color\" content=\"#fff\">","<meta name=\"application-name\" content=\"ss-webpack-boilerplate\">","<link rel=\"apple-touch-icon\" sizes=\"57x57\" href=\"app/client/dist//icons/apple-touch-icon-57x57.png\">","<link rel=\"apple-touch-icon\" sizes=\"60x60\" href=\"app/client/dist//icons/apple-touch-icon-60x60.png\">","<link rel=\"apple-touch-icon\" sizes=\"72x72\" href=\"app/client/dist//icons/apple-touch-icon-72x72.png\">","<link rel=\"apple-touch-icon\" sizes=\"76x76\" href=\"app/client/dist//icons/apple-touch-icon-76x76.png\">","<link rel=\"apple-touch-icon\" sizes=\"114x114\" href=\"app/client/dist//icons/apple-touch-icon-114x114.png\">","<link rel=\"apple-touch-icon\" sizes=\"120x120\" href=\"app/client/dist//icons/apple-touch-icon-120x120.png\">","<link rel=\"apple-touch-icon\" sizes=\"144x144\" href=\"app/client/dist//icons/apple-touch-icon-144x144.png\">","<link rel=\"apple-touch-icon\" sizes=\"152x152\" href=\"app/client/dist//icons/apple-touch-icon-152x152.png\">","<link rel=\"apple-touch-icon\" sizes=\"180x180\" href=\"app/client/dist//icons/apple-touch-icon-180x180.png\">","<meta name=\"apple-mobile-web-app-capable\" content=\"yes\">","<meta name=\"apple-mobile-web-app-status-bar-style\" content=\"black-translucent\">","<meta name=\"apple-mobile-web-app-title\" content=\"ss-webpack-boilerplate\">","<link rel=\"icon\" type=\"image/png\" sizes=\"228x228\" href=\"app/client/dist//icons/coast-228x228.png\">","<meta name=\"msapplication-TileColor\" content=\"#fff\">","<meta name=\"msapplication-TileImage\" content=\"mstile-144x144.png\">","<meta name=\"msapplication-config\" content=\"browserconfig.xml\">","<link rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"app/client/dist//icons/favicon-32x32.png\">","<link rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"app/client/dist//icons/favicon-16x16.png\">","<link rel=\"shortcut icon\" href=\"app/client/dist//icons/favicon.ico\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 320px) and (device-height: 480px) and (-webkit-device-pixel-ratio: 1)\" href=\"app/client/dist//icons/apple-touch-startup-image-320x460.png\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 320px) and (device-height: 480px) and (-webkit-device-pixel-ratio: 2)\" href=\"app/client/dist//icons/apple-touch-startup-image-640x920.png\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 320px) and (device-height: 568px) and (-webkit-device-pixel-ratio: 2)\" href=\"app/client/dist//icons/apple-touch-startup-image-640x1096.png\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 375px) and (device-height: 667px) and (-webkit-device-pixel-ratio: 2)\" href=\"app/client/dist//icons/apple-touch-startup-image-750x1294.png\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 414px) and (device-height: 736px) and (orientation: landscape) and (-webkit-device-pixel-ratio: 3)\" href=\"app/client/dist//icons/apple-touch-startup-image-1182x2208.png\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 414px) and (device-height: 736px) and (orientation: portrait) and (-webkit-device-pixel-ratio: 3)\" href=\"app/client/dist//icons/apple-touch-startup-image-1242x2148.png\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 768px) and (device-height: 1024px) and (orientation: landscape) and (-webkit-device-pixel-ratio: 1)\" href=\"app/client/dist//icons/apple-touch-startup-image-748x1024.png\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 768px) and (device-height: 1024px) and (orientation: portrait) and (-webkit-device-pixel-ratio: 1)\" href=\"app/client/dist//icons/apple-touch-startup-image-768x1004.png\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 768px) and (device-height: 1024px) and (orientation: landscape) and (-webkit-device-pixel-ratio: 2)\" href=\"app/client/dist//icons/apple-touch-startup-image-1496x2048.png\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 768px) and (device-height: 1024px) and (orientation: portrait) and (-webkit-device-pixel-ratio: 2)\" href=\"app/client/dist//icons/apple-touch-startup-image-1536x2008.png\">"],"files":["/icons/android-chrome-36x36.png","/icons/android-chrome-48x48.png","/icons/android-chrome-72x72.png","/icons/android-chrome-144x144.png","/icons/android-chrome-192x192.png","/icons/android-chrome-96x96.png","/icons/android-chrome-384x384.png","/icons/android-chrome-256x256.png","/icons/android-chrome-512x512.png","/icons/apple-touch-icon-60x60.png","/icons/apple-touch-icon-57x57.png","/icons/apple-touch-icon-72x72.png","/icons/apple-touch-icon-114x114.png","/icons/apple-touch-icon-76x76.png","/icons/apple-touch-icon-120x120.png","/icons/apple-touch-icon-144x144.png","/icons/apple-touch-icon-180x180.png","/icons/apple-touch-icon-167x167.png","/icons/apple-touch-icon-152x152.png","/icons/apple-touch-icon-precomposed.png","/icons/apple-touch-icon.png","/icons/coast-228x228.png","/icons/yandex-browser-50x50.png","/icons/mstile-70x70.png","/icons/mstile-144x144.png","/icons/mstile-150x150.png","/icons/mstile-310x150.png","/icons/mstile-310x310.png","/icons/favicon-16x16.png","/icons/favicon-32x32.png","/icons/favicon.ico","/icons/apple-touch-startup-image-640x920.png","/icons/apple-touch-startup-image-320x460.png","/icons/apple-touch-startup-image-640x1096.png","/icons/apple-touch-startup-image-748x1024.png","/icons/apple-touch-startup-image-768x1004.png","/icons/apple-touch-startup-image-750x1294.png","/icons/apple-touch-startup-image-1182x2208.png","/icons/apple-touch-startup-image-1242x2148.png","/icons/apple-touch-startup-image-1536x2008.png","/icons/apple-touch-startup-image-1496x2048.png","/icons/firefox_app_128x128.png","/icons/firefox_app_60x60.png","/icons/firefox_app_512x512.png","/icons/manifest.json","/icons/yandex-browser-manifest.json","/icons/browserconfig.xml","/icons/manifest.webapp"]}} {"hash":"3deb17371acdc75398d81da38fad464c","version":"0.0.9","optionHash":"c067d9b2d6a96a86192ece0162f1b1ac","result":{"outputFilePrefix":"/icons/","html":["<meta name=\"mobile-web-app-capable\" content=\"yes\">","<meta name=\"theme-color\" content=\"#fff\">","<meta name=\"application-name\" content=\"Webpack App\">","<link rel=\"apple-touch-icon\" sizes=\"57x57\" href=\"app/client/dist//icons/apple-touch-icon-57x57.png\">","<link rel=\"apple-touch-icon\" sizes=\"60x60\" href=\"app/client/dist//icons/apple-touch-icon-60x60.png\">","<link rel=\"apple-touch-icon\" sizes=\"72x72\" href=\"app/client/dist//icons/apple-touch-icon-72x72.png\">","<link rel=\"apple-touch-icon\" sizes=\"76x76\" href=\"app/client/dist//icons/apple-touch-icon-76x76.png\">","<link rel=\"apple-touch-icon\" sizes=\"114x114\" href=\"app/client/dist//icons/apple-touch-icon-114x114.png\">","<link rel=\"apple-touch-icon\" sizes=\"120x120\" href=\"app/client/dist//icons/apple-touch-icon-120x120.png\">","<link rel=\"apple-touch-icon\" sizes=\"144x144\" href=\"app/client/dist//icons/apple-touch-icon-144x144.png\">","<link rel=\"apple-touch-icon\" sizes=\"152x152\" href=\"app/client/dist//icons/apple-touch-icon-152x152.png\">","<link rel=\"apple-touch-icon\" sizes=\"180x180\" href=\"app/client/dist//icons/apple-touch-icon-180x180.png\">","<meta name=\"apple-mobile-web-app-capable\" content=\"yes\">","<meta name=\"apple-mobile-web-app-status-bar-style\" content=\"black-translucent\">","<meta name=\"apple-mobile-web-app-title\" content=\"Webpack App\">","<link rel=\"icon\" type=\"image/png\" sizes=\"228x228\" href=\"app/client/dist//icons/coast-228x228.png\">","<meta name=\"msapplication-TileColor\" content=\"#fff\">","<meta name=\"msapplication-TileImage\" content=\"mstile-144x144.png\">","<meta name=\"msapplication-config\" content=\"browserconfig.xml\">","<link rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"app/client/dist//icons/favicon-32x32.png\">","<link rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"app/client/dist//icons/favicon-16x16.png\">","<link rel=\"shortcut icon\" href=\"app/client/dist//icons/favicon.ico\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 320px) and (device-height: 480px) and (-webkit-device-pixel-ratio: 1)\" href=\"app/client/dist//icons/apple-touch-startup-image-320x460.png\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 320px) and (device-height: 480px) and (-webkit-device-pixel-ratio: 2)\" href=\"app/client/dist//icons/apple-touch-startup-image-640x920.png\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 320px) and (device-height: 568px) and (-webkit-device-pixel-ratio: 2)\" href=\"app/client/dist//icons/apple-touch-startup-image-640x1096.png\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 375px) and (device-height: 667px) and (-webkit-device-pixel-ratio: 2)\" href=\"app/client/dist//icons/apple-touch-startup-image-750x1294.png\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 414px) and (device-height: 736px) and (orientation: landscape) and (-webkit-device-pixel-ratio: 3)\" href=\"app/client/dist//icons/apple-touch-startup-image-1182x2208.png\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 414px) and (device-height: 736px) and (orientation: portrait) and (-webkit-device-pixel-ratio: 3)\" href=\"app/client/dist//icons/apple-touch-startup-image-1242x2148.png\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 768px) and (device-height: 1024px) and (orientation: landscape) and (-webkit-device-pixel-ratio: 1)\" href=\"app/client/dist//icons/apple-touch-startup-image-748x1024.png\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 768px) and (device-height: 1024px) and (orientation: portrait) and (-webkit-device-pixel-ratio: 1)\" href=\"app/client/dist//icons/apple-touch-startup-image-768x1004.png\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 768px) and (device-height: 1024px) and (orientation: landscape) and (-webkit-device-pixel-ratio: 2)\" href=\"app/client/dist//icons/apple-touch-startup-image-1496x2048.png\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 768px) and (device-height: 1024px) and (orientation: portrait) and (-webkit-device-pixel-ratio: 2)\" href=\"app/client/dist//icons/apple-touch-startup-image-1536x2008.png\">"],"files":["/icons/android-chrome-36x36.png","/icons/android-chrome-48x48.png","/icons/android-chrome-72x72.png","/icons/android-chrome-144x144.png","/icons/android-chrome-96x96.png","/icons/android-chrome-192x192.png","/icons/android-chrome-384x384.png","/icons/android-chrome-256x256.png","/icons/android-chrome-512x512.png","/icons/apple-touch-icon-60x60.png","/icons/apple-touch-icon-57x57.png","/icons/apple-touch-icon-72x72.png","/icons/apple-touch-icon-76x76.png","/icons/apple-touch-icon-114x114.png","/icons/apple-touch-icon-120x120.png","/icons/apple-touch-icon-144x144.png","/icons/apple-touch-icon-152x152.png","/icons/apple-touch-icon-167x167.png","/icons/apple-touch-icon-180x180.png","/icons/apple-touch-icon.png","/icons/apple-touch-icon-precomposed.png","/icons/coast-228x228.png","/icons/yandex-browser-50x50.png","/icons/mstile-70x70.png","/icons/mstile-144x144.png","/icons/mstile-150x150.png","/icons/mstile-310x150.png","/icons/mstile-310x310.png","/icons/favicon-16x16.png","/icons/favicon-32x32.png","/icons/favicon.ico","/icons/apple-touch-startup-image-320x460.png","/icons/apple-touch-startup-image-640x920.png","/icons/apple-touch-startup-image-640x1096.png","/icons/apple-touch-startup-image-750x1294.png","/icons/apple-touch-startup-image-768x1004.png","/icons/apple-touch-startup-image-748x1024.png","/icons/apple-touch-startup-image-1242x2148.png","/icons/apple-touch-startup-image-1182x2208.png","/icons/apple-touch-startup-image-1496x2048.png","/icons/apple-touch-startup-image-1536x2008.png","/icons/firefox_app_60x60.png","/icons/firefox_app_128x128.png","/icons/firefox_app_512x512.png","/icons/manifest.json","/icons/yandex-browser-manifest.json","/icons/browserconfig.xml","/icons/manifest.webapp"]}}

View File

@ -1,6 +1,6 @@
{ {
"name": "ss-webpack-boilerplate", "name": "Webpack App",
"short_name": "ss-webpack-boilerplate", "short_name": "Webpack App",
"description": null, "description": null,
"dir": "auto", "dir": "auto",
"lang": "en-US", "lang": "en-US",

View File

@ -1,6 +1,6 @@
{ {
"version": "1.0", "version": "1.0",
"name": "ss-webpack-boilerplate", "name": "Webpack App",
"description": null, "description": null,
"icons": { "icons": {
"60": "firefox_app_60x60.png", "60": "firefox_app_60x60.png",

View File

@ -1 +0,0 @@
module.exports = "../fonts/fontawesome-webfont.svg";

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.0 KiB

View File

@ -1 +0,0 @@
!function(t){function n(r){if(e[r])return e[r].exports;var o=e[r]={i:r,l:!1,exports:{}};return t[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}var e={};n.m=t,n.c=e,n.d=function(t,e,r){n.o(t,e)||Object.defineProperty(t,e,{configurable:!1,enumerable:!0,get:r})},n.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return n.d(e,"a",e),e},n.o=function(t,n){return Object.prototype.hasOwnProperty.call(t,n)},n.p="app/client/dist/",n(n.s=32)}({32:function(t,n){}});

File diff suppressed because one or more lines are too long

View File

@ -1 +0,0 @@
!function(t){function n(r){if(e[r])return e[r].exports;var o=e[r]={i:r,l:!1,exports:{}};return t[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}var e={};n.m=t,n.c=e,n.d=function(t,e,r){n.o(t,e)||Object.defineProperty(t,e,{configurable:!1,enumerable:!0,get:r})},n.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return n.d(e,"a",e),e},n.o=function(t,n){return Object.prototype.hasOwnProperty.call(t,n)},n.p="app/client/dist/",n(n.s=33)}({33:function(t,n){}});

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.0 KiB

View File

@ -5,6 +5,7 @@ import 'jquery.inputmask/dist/jquery.inputmask.bundle';
import Events from "../_events"; import Events from "../_events";
import SpinnerUI from './_ui.spinner'; import SpinnerUI from './_ui.spinner';
import FormFieldUI from './_ui.form.fields';
const FormBasics = (($) => { const FormBasics = (($) => {
// Constants // Constants
@ -23,7 +24,12 @@ const FormBasics = (($) => {
$('[data-inputmask]').inputmask(); $('[data-inputmask]').inputmask();
const $fields = $element.find('input,textarea,select'); const $fields = $element.find(Events.FORM_FIELDS);
// init fields ui
$fields.each((i, el) => {
new FormFieldUI(el);
});
const $selectFields = $element.find('select:not([readonly])'); const $selectFields = $element.find('select:not([readonly])');
const $radioOptions = $element.find('input[type="radio"]'); const $radioOptions = $element.find('input[type="radio"]');
const separator = '::;::'; const separator = '::;::';
@ -61,7 +67,7 @@ const FormBasics = (($) => {
}); });
html += `<span class="option" data-val=${ $opt.attr('value') }>${ opt html += `<span class="option" data-val=${ $opt.attr('value') }>${ opt
} <i class="fas fa-times btn-remove"></i></span>`; } <i class="fas fa-times btn-remove"></i></span>`;
}); });

View File

@ -79,7 +79,9 @@ const FormValidate = (($) => {
badCallback(); badCallback();
} }
console.log('Invalid form data'); console.log('Invalid form data:');
console.log($el);
SpinnerUI.hide(); SpinnerUI.hide();
valid = false; valid = false;
return false; return false;

View File

@ -2,12 +2,12 @@ import Events from '../../_events';
import Routie from "routie"; import Routie from "routie";
$(window).on(`${Events.AJAX} ${Events.LOADED}`, () => { $(window).on(`${Events.AJAX} ${Events.LOADED}`, () => {
Routie({ Routie({
'navigation': function() { 'navigation': function() {
$('#NavbarCollapse').addClass('in'); $('#NavbarCollapse').addClass('in');
}, },
'carousel:id:num': function(id, num) { 'carousel:id:num': function(id, num) {
$(`#Carousel${ id}`).carousel(num); $(`#Carousel${ id}`).carousel(num);
}, },
}); });
}); });

View File

@ -3,17 +3,18 @@
*/ */
module.exports = { module.exports = {
AJAX: 'ajax-load', AJAX: 'ajax-load',
LOADED: 'load', LOADED: 'load',
SET_TARGET_UPDATE: 'set-target-update', SET_TARGET_UPDATE: 'set-target-update',
RESTORE_FIELD: 'restore-field', RESTORE_FIELD: 'restore-field',
FORM_INIT_BASICS: 'form-basics', FORM_INIT_BASICS: 'form-basics',
FORM_INIT_STEPPED: 'form-init-stepped', FORM_INIT_STEPPED: 'form-init-stepped',
FORM_INIT_VALIDATE: 'form-init-validate', FORM_INIT_VALIDATE: 'form-init-validate',
FORM_INIT_VALIDATE_FIELD: 'form-init-validate-field', FORM_INIT_VALIDATE_FIELD: 'form-init-validate-field',
FORM_INIT_STORAGE: 'form-init-storage', FORM_INIT_STORAGE: 'form-init-storage',
FORM_VALIDATION_FAILED: 'form-validation-failed', FORM_VALIDATION_FAILED: 'form-validation-failed',
FORM_STEPPED_NEW_STEP: 'form-new-step', FORM_STEPPED_NEW_STEP: 'form-new-step',
FORM_STEPPED_FIRST_STEP: 'form-first-step', FORM_STEPPED_FIRST_STEP: 'form-first-step',
FORM_STEPPED_LAST_STEP: 'form-last-step', FORM_STEPPED_LAST_STEP: 'form-last-step',
FORM_FIELDS: 'input,textarea,select',
}; };

View File

@ -7,43 +7,43 @@ import FormStepped from './_components/_ui.form.stepped';
const LayoutUI = (($) => { const LayoutUI = (($) => {
// Constants // Constants
const W = window; const W = window;
const D = document; const D = document;
const $Body = $('body'); const $Body = $('body');
const NAME = 'LayoutUI'; const NAME = 'LayoutUI';
const datepickerOptions = { const datepickerOptions = {
autoclose: true, autoclose: true,
startDate: 0, startDate: 0,
//todayBtn: true, //todayBtn: true,
todayHighlight: true, todayHighlight: true,
clearBtn: true, clearBtn: true,
}; };
class LayoutUI { class LayoutUI {
static init() { static init() {
const ui = this; const ui = this;
ui.dispose(); ui.dispose();
console.log(`Initializing: ${NAME}`); console.log(`Initializing: ${NAME}`);
// your custom UI // your custom UI
}
static dispose() {
console.log(`Destroying: ${NAME}`);
}
} }
$(W).on(`${Events.AJAX} ${Events.LOADED}`, () => { static dispose() {
LayoutUI.init(); console.log(`Destroying: ${NAME}`);
}); }
}
W.LayoutUI = LayoutUI; $(W).on(`${Events.AJAX} ${Events.LOADED}`, () => {
LayoutUI.init();
});
return LayoutUI; W.LayoutUI = LayoutUI;
return LayoutUI;
})($); })($);
export default LayoutUI; export default LayoutUI;

View File

@ -28,316 +28,321 @@ import SmoothScroll from 'smooth-scroll';
const smoothScroll = SmoothScroll(); const smoothScroll = SmoothScroll();
const MainUI = (($) => { const MainUI = (($) => {
// Constants // Constants
const W = window; const W = window;
const D = document; const D = document;
const $Body = $('body'); const $Body = $('body');
const NAME = 'MainUI'; const NAME = 'MainUI';
// get browser locale // get browser locale
//const Locale = $('html').attr('lang').substring(0, 2); //const Locale = $('html').attr('lang').substring(0, 2);
const $AlertNotify = $('#AlertNotify'); const $AlertNotify = $('#AlertNotify');
const $SiteWideMessage = $('#SiteWideMessage'); const $SiteWideMessage = $('#SiteWideMessage');
// get browser window visibility preferences // get browser window visibility preferences
// Opera 12.10, Firefox >=18, Chrome >=31, IE11 // Opera 12.10, Firefox >=18, Chrome >=31, IE11
const HiddenName = 'hidden'; const HiddenName = 'hidden';
const VisibilityChangeEvent = 'visibilitychange'; const VisibilityChangeEvent = 'visibilitychange';
// update visibility state // update visibility state
D.addEventListener(VisibilityChangeEvent, () => { D.addEventListener(VisibilityChangeEvent, () => {
if (D.visibilityState === HiddenName) { if (D.visibilityState === HiddenName) {
console.log('Tab: hidden'); console.log('Tab: hidden');
$Body.addClass('is-hidden'); $Body.addClass('is-hidden');
$Body.trigger('tabHidden'); $Body.trigger('tabHidden');
} else { } else {
console.log('Tab: focused'); console.log('Tab: focused');
$Body.removeClass('is-hidden'); $Body.removeClass('is-hidden');
$Body.trigger('tabFocused'); $Body.trigger('tabFocused');
} }
});
// update online/offline state
const updateOnlineStatus = function() {
if (!navigator.onLine) {
console.log('Tab: offline');
$Body.addClass('is-offline');
$Body.trigger('offline');
} else {
console.log('Tab: online');
$Body.removeClass('is-offline');
$Body.trigger('online');
}
};
if (typeof navigator.onLine !== 'undefined') {
W.addEventListener('offline', () => {
updateOnlineStatus();
}, false);
W.addEventListener('online', () => {
updateOnlineStatus();
}, false);
W.addEventListener('load', () => {
updateOnlineStatus();
}); });
}
// scrollTo
const ScrollTo = function(trigger, selector) {
smoothScroll.animateScroll(
D.querySelector(selector),
trigger, {
speed: 500,
offset: -20,
//easing: 'easeInOutCubic',
// Callback API
//before: function (anchor, toggle) {}, // Callback to run before scroll
//`after: function (anchor, toggle) {} // Callback to run after scroll
}
);
};
// update online/offline state // session ping
const updateOnlineStatus = function() { setInterval(() => {
if (!navigator.onLine) { if ($Body.hasClass('is-offline')) {
console.log('Tab: offline'); return;
$Body.addClass('is-offline');
$Body.trigger('offline');
} else {
console.log('Tab: online');
$Body.removeClass('is-offline');
$Body.trigger('online');
}
};
if (typeof navigator.onLine !== 'undefined') {
W.addEventListener('offline', () => {
updateOnlineStatus();
}, false);
W.addEventListener('online', () => {
updateOnlineStatus();
}, false);
W.addEventListener('load', () => {
updateOnlineStatus();
});
} }
// scrollTo $.ajax({
const ScrollTo = function(trigger, selector) { sync: false,
smoothScroll.animateScroll( async: true,
D.querySelector(selector), cache: false,
trigger, { url: '/Security/ping',
speed: 500, global: false,
offset: -20, type: 'POST',
//easing: 'easeInOutCubic', complete(data, datastatus) {
// Callback API if (datastatus !== 'success') {
//before: function (anchor, toggle) {}, // Callback to run before scroll W.location.reload(false);
//`after: function (anchor, toggle) {} // Callback to run after scroll
}
);
};
// session ping
setInterval(() => {
if ($Body.hasClass('is-offline')) {
return;
} }
},
});
}, 300000); // 5 min in ms
$.ajax({ W.URLDetails = {
sync: false, 'base': $('base').attr('href'),
async: true, 'relative': '/',
cache: false, 'hash': '',
url: '/Security/ping', };
global: false,
type: 'POST', class MainUI {
complete(data, datastatus) { // Static methods
if (datastatus !== 'success') {
W.location.reload(false); static init() {
} this.dispose();
console.log(`Initializing: ${NAME}`);
// update location details
this.updateLocation();
// mark available offline areas
if ('caches' in W) {
$('a.offline').addClass('offline-available');
}
this.loadImages();
// mark external links
$('a.external,a[rel="external"]').attr('target', '_blank');
// show encoded emails
/*$(D).find('.obm').each(function () {
if ($(this).attr('data-val') !== undefined) {
const email = $(this).attr('data-val').split('')
.reverse()
.join('')
.slice(0, -8)
.replace(/[a-zA-Z]/g, (c) => String.fromCharCode((c <= 'Z' ? 90 : 122) >= (c = c.charCodeAt(0) + 13) ? c : c - 26))
.replace('#AT#', '@');
const attr = $(this).attr('data-val-append');
if (attr !== undefined && attr !== false) {
$(this).append(email);
}
if ($(this).find('.sr-only').length > 0) {
$(this).find('.sr-only').append(email);
}
if ($(this).attr('href') !== undefined) {
$(this).attr('href', `mailto:${email}`);
}
}
});*/
//
// scroll links
$(D).on('click', '.js-scrollTo', (e) => {
e.preventDefault();
const el = e.currentTarget;
const $el = $(e.currentTarget);
const target = $el.data('target') || $el.attr('href');
if ($(target).length) {
ScrollTo(el, target);
} else {
console.log(`[ScrollTo] Undefined target: ${ target}`);
}
});
// load external fonts
if ($('[data-extfont]').length) {
$.getScript('//ajax.googleapis.com/ajax/libs/webfont/1/webfont.js', () => {
const fonts = [];
$('[data-extfont]').each((i, el) => {
fonts[i] = $(el).attr('data-extfont');
});
W.WebFont.load({
google: {
families: fonts,
}, },
});
}); });
}, 300000); // 5 min in ms }
W.URLDetails = { // data-set links
'base': $('base').attr('href'), $('[data-set-target]').on('click', (e) => {
'relative': '/', const $el = $(e.currentTarget);
'hash': '', const $target = $($el.data('set-target'));
};
class MainUI { if (!$target.length) {
// Static methods return;
static init() {
this.dispose();
console.log(`Initializing: ${NAME}`);
// update location details
this.updateLocation();
// mark available offline areas
if ('caches' in W) {
$('a.offline').addClass('offline-available');
}
this.loadImages();
// mark external links
$('a.external,a[rel="external"]').attr('target', '_blank');
// show encoded emails
/*$(D).find('.obm').each(function () {
if ($(this).attr('data-val') !== undefined) {
const email = $(this).attr('data-val').split('')
.reverse()
.join('')
.slice(0, -8)
.replace(/[a-zA-Z]/g, (c) => String.fromCharCode((c <= 'Z' ? 90 : 122) >= (c = c.charCodeAt(0) + 13) ? c : c - 26))
.replace('#AT#', '@');
const attr = $(this).attr('data-val-append');
if (attr !== undefined && attr !== false) {
$(this).append(email);
}
if ($(this).find('.sr-only').length > 0) {
$(this).find('.sr-only').append(email);
}
if ($(this).attr('href') !== undefined) {
$(this).attr('href', `mailto:${email}`);
}
}
});*/
//
// scroll links
$(D).on('click', '.js-scrollTo', (e) => {
e.preventDefault();
const el = e.currentTarget;
const $el = $(e.currentTarget);
ScrollTo(el, $el.attr('data-target'));
});
// load external fonts
if ($('[data-extfont]').length) {
$.getScript('//ajax.googleapis.com/ajax/libs/webfont/1/webfont.js', () => {
const fonts = [];
$('[data-extfont]').each(function(i, el) {
fonts[i] = $(el).attr('data-extfont');
});
W.WebFont.load({
google: {
families: fonts,
},
});
});
}
// data-set links
$('[data-set-target]').on('click', (e) => {
const $el = $(e.currentTarget);
const $target = $($el.data('set-target'));
if (!$target.length) {
return;
}
$target.each((i, targetEl) => {
const $targetEl = $(targetEl);
const tag = $targetEl.prop('tagName').toLowerCase();
if (tag === 'input' || tag === 'select') {
$targetEl.val($el.data('set-val'));
} else if (!$targetEl.hasClass('field')) {
$targetEl.text($el.data('set-val'));
}
});
$el.trigger(Events.SET_TARGET_UPDATE);
$target.closest('form').trigger(Events.SET_TARGET_UPDATE);
});
// hide spinner
Spinner.hide(() => {
$Body.addClass('loaded');
});
// fire page printing
if (W.URLDetails['hash'].indexOf('printpage') > -1) {
W.print();
}
} }
static updateLocation(url) { $target.each((i, targetEl) => {
let location = url || W.location.href; const $targetEl = $(targetEl);
location = location.replace(W.URLDetails['base'], '/'); const tag = $targetEl.prop('tagName').toLowerCase();
const hash = location.indexOf('#');
W.URLDetails.relative = location.split('#')[0]; if (tag === 'input' || tag === 'select') {
W.URLDetails.hash = (hash >= 0) ? location.substr(location.indexOf('#')) : ''; $targetEl.val($el.data('set-val'));
} } else if (!$targetEl.hasClass('field')) {
$targetEl.text($el.data('set-val'));
}
});
// show site-wide alert $el.trigger(Events.SET_TARGET_UPDATE);
static alert(msg, cls) { $target.closest('form').trigger(Events.SET_TARGET_UPDATE);
$SiteWideMessage.fadeOut('fast'); });
$SiteWideMessage.html(`<div class="page-alert"><div class="alert alert-${cls}"><i class="close" data-dismiss="alert">&times;</i>${msg}</div></div>`); // hide spinner
$SiteWideMessage.find('.page-alert').alert(); Spinner.hide(() => {
$Body.addClass('loaded');
});
$SiteWideMessage.find('.close[data-dismiss="alert"]').click(() => { // fire page printing
$SiteWideMessage.fadeOut('slow', () => { if (W.URLDetails['hash'].indexOf('printpage') > -1) {
$SiteWideMessage.find('.page-alert').alert('close'); W.print();
}); }
});
$SiteWideMessage.fadeIn('slow');
if ($AlertNotify.length) {
$AlertNotify[0].play();
}
$(W).trigger('alert-appeared');
}
// hide site-wide alert
static alertHide() {
if ($SiteWideMessage.length !== 0) {
$SiteWideMessage.fadeOut('slow', () => {
$SiteWideMessage.find('.alert').alert('close');
});
}
if (
$AlertNotify.length &&
typeof $AlertNotify[0].stop !== 'undefined'
) {
$AlertNotify[0].stop();
}
$(W).trigger('alert-removed');
}
// load all images
static loadImages() {
const $imgs = $Body.find('img');
const $imgUrls = [];
const $imgLazyUrls = [];
// collect image details
$imgs.each((i, el) => {
const $el = $(el);
const src = $el.attr('src');
const lazySrc = $el.data('lazy-src');
if (src && src.length) {
$imgUrls.push(src);
}
if (lazySrc && lazySrc.length) {
$imgLazyUrls.push(lazySrc);
$el.addClass('loading');
AjaxUI.preload([lazySrc]).then(() => {
$el.attr('src', lazySrc);
$el.addClass('loaded');
$el.removeClass('loading');
$el.trigger('image-lazy-loaded');
});
}
});
// load defined images
AjaxUI.preload($imgUrls).then(() => {
$(W).trigger('images-loaded');
// load lazy images
AjaxUI.preload($imgLazyUrls).then(() => {
console.log('All images are loaded!');
$(W).trigger('images-lazy-loaded');
});
});
}
static dispose() {
console.log(`Destroying: ${NAME}`);
}
} }
$(W).on(`${Events.AJAX} ${Events.LOADED}`, () => { static updateLocation(url) {
MainUI.init(); let location = url || W.location.href;
}); location = location.replace(W.URLDetails['base'], '/');
const hash = location.indexOf('#');
W.MainUI = MainUI; W.URLDetails.relative = location.split('#')[0];
W.URLDetails.hash = (hash >= 0) ? location.substr(location.indexOf('#')) : '';
}
return MainUI; // show site-wide alert
static alert(msg, cls) {
$SiteWideMessage.fadeOut('fast');
$SiteWideMessage.html(`<div class="page-alert"><div class="alert alert-${cls}"><i class="close" data-dismiss="alert">&times;</i>${msg}</div></div>`);
$SiteWideMessage.find('.page-alert').alert();
$SiteWideMessage.find('.close[data-dismiss="alert"]').click(() => {
$SiteWideMessage.fadeOut('slow', () => {
$SiteWideMessage.find('.page-alert').alert('close');
});
});
$SiteWideMessage.fadeIn('slow');
if ($AlertNotify.length) {
$AlertNotify[0].play();
}
$(W).trigger('alert-appeared');
}
// hide site-wide alert
static alertHide() {
if ($SiteWideMessage.length !== 0) {
$SiteWideMessage.fadeOut('slow', () => {
$SiteWideMessage.find('.alert').alert('close');
});
}
if (
$AlertNotify.length &&
typeof $AlertNotify[0].stop !== 'undefined'
) {
$AlertNotify[0].stop();
}
$(W).trigger('alert-removed');
}
// load all images
static loadImages() {
const $imgs = $Body.find('img');
const $imgUrls = [];
const $imgLazyUrls = [];
// collect image details
$imgs.each((i, el) => {
const $el = $(el);
const src = $el.attr('src');
const lazySrc = $el.data('lazy-src');
if (src && src.length) {
$imgUrls.push(src);
}
if (lazySrc && lazySrc.length) {
$imgLazyUrls.push(lazySrc);
$el.addClass('loading');
AjaxUI.preload([lazySrc]).then(() => {
$el.attr('src', lazySrc);
$el.addClass('loaded');
$el.removeClass('loading');
$el.trigger('image-lazy-loaded');
});
}
});
// load defined images
AjaxUI.preload($imgUrls).then(() => {
$(W).trigger('images-loaded');
// load lazy images
AjaxUI.preload($imgLazyUrls).then(() => {
console.log('All images are loaded!');
$(W).trigger('images-lazy-loaded');
});
});
}
static dispose() {
console.log(`Destroying: ${NAME}`);
}
}
$(W).on(`${Events.AJAX} ${Events.LOADED}`, () => {
MainUI.init();
});
W.MainUI = MainUI;
return MainUI;
})($); })($);
export default MainUI; export default MainUI;

View File

@ -29,7 +29,7 @@ import './_main';
import './_layout'; import './_layout';
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(require.context('../img/', false, /\.(png|jpe?g|svg)$/));

View File

@ -3,13 +3,13 @@
*/ */
module.exports = { module.exports = {
en: { en: {
jsSteppedForm: { jsSteppedForm: {
STEPCOUNTER: '<div class="steps-counter">Step <b class="current-step"></b> of <b class="total-steps"></b></div>', STEPCOUNTER: '<div class="steps-counter">Step <b class="current-step"></b> of <b class="total-steps"></b></div>',
STEPBUTTONS: '<div class="steps-buttons">' + STEPBUTTONS: '<div class="steps-buttons">' +
'<a href="#" class="step-ctrl step-prev"><i class="fas fa-chevron-left"></i> Prev</a>' + '<a href="#" class="step-ctrl step-prev"><i class="fas fa-chevron-left"></i> Prev</a>' +
' <a href="#" class="step-ctrl step-next">Next <i class="fas fa-chevron-right"></i></a>' + ' <a href="#" class="step-ctrl step-next">Next <i class="fas fa-chevron-right"></i></a>' +
'</div>', '</div>',
},
}, },
},
}; };

View File

@ -111,27 +111,29 @@ button, input, optgroup, select, textarea,
@extend .alert-danger; @extend .alert-danger;
} }
// stick navbar to top using mobile layout // element col paddings
#Header { .col-block {
position: relative; padding: $grid-gutter-height / 4;
padding-top: $grid-gutter-height / 2; }
padding-bottom: 1rem;
@media (min-width: map-get($grid-breakpoints, "lg")) { // rewrite btn opacity on hover
padding-top: 1rem; .btn {
padding-bottom: 0; &:hover,
&:focus {
opacity: 1;
} }
} }
#Navigation { // SS-messages
position: fixed; .message {
top: 0; @extend .alert;
left: 0;
width: 100%;
z-index: 10;
@media (min-width: map-get($grid-breakpoints, "lg")) { @extend .alert-info;
position: relative; }
margin-top: 1rem;
} .message.required,
.message.error {
@extend .alert;
@extend .alert-danger;
} }

View File

@ -4,6 +4,20 @@
/** /**
* Your custom style * Your custom style
*/ */
.bg-alt {
@extend .bg-dark;
background-color: $bg-alt !important;
}
.bootstrap-select .dropdown-toggle .filter-option .option {
background: #dedede;
padding: .2rem .5rem;
margin: .2rem;
color: #212529;
}
// shrink elements on scroll // shrink elements on scroll
body.shrink {} body.shrink {}
@ -16,44 +30,23 @@ body.shrink {}
.wrapper { .wrapper {
min-height: 100%; min-height: 100%;
padding-top: $grid-gutter-height; padding-bottom: $footer-size + $footer-bar-size + $grid-gutter-height / 2;
padding-bottom: 2rem;
//padding-top: $grid-gutter-height;
} }
.site-footer { .footer {
height: 2rem; height: $footer-size + $footer-bar-size + $grid-gutter-height / 2;
margin-top: -2rem; margin-top: -($footer-size + $footer-bar-size + $grid-gutter-height / 2);
} }
} }
// element col paddings // site blocks (elements)
.col-block {
padding: $grid-gutter-height / 4;
}
// rewrite btn opacity on hover
.btn {
&:hover,
&:focus {
opacity: 1;
}
}
// SS-messages
.message {
@extend .alert;
@extend .alert-info;
}
.message.required,
.message.error {
@extend .alert;
@extend .alert-danger;
}
.element { .element {
background-size: cover;
background-repeat: no-repeat;
&.site__elements__sliderelement { &.site__elements__sliderelement {
.element-container { .element-container {
width: 100%; width: 100%;
@ -61,11 +54,89 @@ body.shrink {}
max-width: none; max-width: none;
} }
} }
&.site__elements__accordion {
.card {
padding-left: 0;
padding-right: 0;
.card-header {
@extend .bg-dark;
}
}
}
} }
.bootstrap-select .dropdown-toggle .filter-option .option { // stick navbar to top using mobile layout
background: #dedede; /*#Header {
padding: .2rem .5rem; position: relative;
margin: .2rem; padding-top: $grid-gutter-height / 2;
color: #212529; padding-bottom: 1rem;
@media (min-width: map-get($grid-breakpoints, "lg")) {
padding-top: 1rem;
padding-bottom: 0;
}
}
#Navigation {
position: fixed;
top: 0;
left: 0;
width: 100%;
z-index: 10;
@media (min-width: map-get($grid-breakpoints, "lg")) {
position: relative;
margin-top: 1rem;
}
}*/
#Footer {
background-color: $dark;
color: darken($white, 5%);
.container,
.container-fluid {
padding-top: $grid-gutter-height / 2;
padding-bottom: $grid-gutter-height / 2;
}
a {
color: $white;
}
ul {
margin-bottom: 0;
}
.footer {
background-color: darken($dark, 5%);
.container,
.container-fluid {
padding-top: 0;
padding-bottom: 0;
}
.copyright {
padding-right: .5rem;
}
li {
padding: 0 .5rem;
}
}
@media (min-width: map-get($grid-breakpoints, "sm")) {
.wrapper {
padding-bottom: $footer-bar-size;
}
.footer {
height: $footer-bar-size;
margin-top: -$footer-bar-size;
line-height: $footer-bar-size;
}
}
} }

View File

@ -1,6 +1,15 @@
h1, h2, h3, h4, h5, h6, h1, h2, h3, h4, h5, h6,
.h1, .h2, .h3, .h4, .h5, .h6 { .h1, .h2, .h3, .h4, .h5, .h6 {
color: $dark-blue; color: $dark;
}
.bg-dark {
h1, h2, h3, h4, h5, h6,
.h1, .h2, .h3, .h4, .h5, .h6,
.typography,
a {
color: $white;
}
} }
.typography { .typography {

View File

@ -11,13 +11,18 @@ $white: #fff;
$blue: #016cb1; $blue: #016cb1;
$yellow: #ecac02; $yellow: #ecac02;
$dark-blue: #113362; //$dark: #047072;
//$primary: $dark;
$bg-alt: $yellow;
$body-color: $gray-900; $body-color: $gray-900;
$navbar-light-active-color: $blue; $navbar-light-active-color: $blue;
$dropdown-border-color: $white; $dropdown-border-color: $white;
$footer-size: 16rem;
$footer-bar-size: 2.5rem;
/* /*
* bootstrap includes * bootstrap includes
* keep it at the end * keep it at the end

View File

@ -43,6 +43,7 @@
"jquery-zoom": "^1.7.21", "jquery-zoom": "^1.7.21",
"jquery.appear": "^1.0.1", "jquery.appear": "^1.0.1",
"jquery.inputmask": "^3.3.4", "jquery.inputmask": "^3.3.4",
"mapbox-gl": "^1.0.0",
"meta-lightbox": "^1.0.0", "meta-lightbox": "^1.0.0",
"offcanvas-bootstrap": "^2.5.2", "offcanvas-bootstrap": "^2.5.2",
"popper.js": "^1.15.0", "popper.js": "^1.15.0",

View File

@ -11,152 +11,153 @@ const filesystem = require('fs');
const includes = {}; const includes = {};
const modules = [ const modules = [
path.resolve(__dirname, 'public'), path.resolve(__dirname, 'public'),
path.resolve(__dirname, conf.APPDIR, 'client', 'src'), path.resolve(__dirname, conf.APPDIR, 'client', 'src'),
path.resolve(__dirname, conf.APPDIR, 'client', 'src', 'js'), path.resolve(__dirname, conf.APPDIR, 'client', 'src', 'js'),
path.resolve(__dirname, conf.APPDIR, 'client', 'src', 'scss'), path.resolve(__dirname, conf.APPDIR, 'client', 'src', 'scss'),
path.resolve(__dirname, conf.APPDIR, 'client', 'src', 'img'), path.resolve(__dirname, conf.APPDIR, 'client', 'src', 'img'),
path.resolve(__dirname, conf.APPDIR, 'client', 'src', 'thirdparty'), path.resolve(__dirname, conf.APPDIR, 'client', 'src', 'thirdparty'),
path.resolve(__dirname, 'node_modules') path.resolve(__dirname, conf.APPDIR, 'client', 'node_modules'),
path.resolve(__dirname, 'node_modules')
]; ];
const _addAppFiles = (theme) => { const _addAppFiles = (theme) => {
const dirPath = path.resolve(__dirname, theme); const dirPath = path.resolve(__dirname, theme);
const themeName = path.basename(theme); const themeName = path.basename(theme);
if (filesystem.existsSync(path.join(dirPath, conf.SRC, 'js', 'app.js'))) { if (filesystem.existsSync(path.join(dirPath, conf.SRC, 'js', 'app.js'))) {
includes[`${themeName}`] = path.join(dirPath, conf.SRC, 'js', 'app.js'); includes[`${themeName}`] = path.join(dirPath, conf.SRC, 'js', 'app.js');
} else if (filesystem.existsSync(path.join(dirPath, conf.SRC, 'scss', 'app.scss'))) { } else if (filesystem.existsSync(path.join(dirPath, conf.SRC, 'scss', 'app.scss'))) {
includes[`${themeName}`] = path.join(dirPath, conf.SRC, 'scss', 'app.scss'); includes[`${themeName}`] = path.join(dirPath, conf.SRC, 'scss', 'app.scss');
} }
modules.push(path.join(dirPath, 'client', 'src', 'js')); modules.push(path.join(dirPath, 'client', 'src', 'js'));
modules.push(path.join(dirPath, 'client', 'src', 'scss')); modules.push(path.join(dirPath, 'client', 'src', 'scss'));
modules.push(path.join(dirPath, 'client', 'src', 'img')); modules.push(path.join(dirPath, 'client', 'src', 'img'));
modules.push(path.join(dirPath, 'client', 'src', 'thirdparty')); 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); const dirPath = path.resolve(__dirname, dir);
let results = []; let results = [];
filesystem.readdirSync(dirPath).forEach((file) => { filesystem.readdirSync(dirPath).forEach((file) => {
if (file.charAt(0) === '_') { if (file.charAt(0) === '_') {
return; return;
} }
const filePath = path.join(dirPath, file); const filePath = path.join(dirPath, file);
const stat = filesystem.statSync(filePath); const stat = filesystem.statSync(filePath);
if (stat && stat.isDirectory() && includeSubFolders) { if (stat && stat.isDirectory() && includeSubFolders) {
results = results.concat(_getAllFilesFromFolder(filePath, includeSubFolders)); results = results.concat(_getAllFilesFromFolder(filePath, includeSubFolders));
} else { } else {
results.push(filePath); results.push(filePath);
} }
}); });
return results; return results;
}; };
// add page specific scripts // add page specific scripts
const typesJSPath = path.join(theme, conf.TYPESJS); const typesJSPath = path.join(theme, conf.TYPESJS);
if (filesystem.existsSync(typesJSPath)) { if (filesystem.existsSync(typesJSPath)) {
const pageScripts = _getAllFilesFromFolder(typesJSPath, true); const pageScripts = _getAllFilesFromFolder(typesJSPath, true);
pageScripts.forEach((file) => { pageScripts.forEach((file) => {
includes[`${themeName}_${path.basename(file, '.js')}`] = file; includes[`${themeName}_${path.basename(file, '.js')}`] = file;
}); });
} }
// add page specific scss // add page specific scss
const typesSCSSPath = path.join(theme, conf.TYPESSCSS); const typesSCSSPath = path.join(theme, conf.TYPESSCSS);
if (filesystem.existsSync(typesSCSSPath)) { if (filesystem.existsSync(typesSCSSPath)) {
const scssIncludes = _getAllFilesFromFolder(typesSCSSPath, true); const scssIncludes = _getAllFilesFromFolder(typesSCSSPath, true);
scssIncludes.forEach((file) => { scssIncludes.forEach((file) => {
includes[`${themeName}_${path.basename(file, '.scss')}`] = file; includes[`${themeName}_${path.basename(file, '.scss')}`] = file;
}); });
} }
}; };
_addAppFiles(conf.APPDIR); _addAppFiles(conf.APPDIR);
// add themes // add themes
commonVariables.themes.forEach((theme) => { commonVariables.themes.forEach((theme) => {
_addAppFiles(theme); _addAppFiles(theme);
}); });
module.exports = { module.exports = {
entry: includes, entry: includes,
devtool: 'source-map', devtool: 'source-map',
externals: { externals: {
'jquery': 'jQuery', 'jquery': 'jQuery',
}, },
optimization: { optimization: {
namedModules: true, // NamedModulesPlugin() namedModules: true, // NamedModulesPlugin()
splitChunks: { // CommonsChunkPlugin() splitChunks: { // CommonsChunkPlugin()
name: 'vendor', name: 'vendor',
minChunks: 2 minChunks: 2
},
noEmitOnErrors: true, // NoEmitOnErrorsPlugin
concatenateModules: true //ModuleConcatenationPlugin
}, },
noEmitOnErrors: true, // NoEmitOnErrorsPlugin
concatenateModules: true //ModuleConcatenationPlugin
},
module: { module: {
rules: [{ rules: [{
test: /\.jsx?$/, test: /\.jsx?$/,
exclude: /node_modules/, exclude: /node_modules/,
use: { use: {
loader: 'babel-loader', loader: 'babel-loader',
options: { options: {
presets: [ presets: [
['es2015', { ['es2015', {
modules: false, modules: false,
}], }],
['stage-2'], ['stage-2'],
], ],
plugins: [ plugins: [
['transform-react-jsx'], ['transform-react-jsx'],
['react-hot-loader/babel'], ['react-hot-loader/babel'],
], ],
},
},
}, {
test: /\.tsx?$/,
use: 'ts-loader',
exclude: /node_modules/,
}, {
test: /\.coffee?$/,
use: 'coffee-loader',
}, {
test: /\.worker\.js$/,
use: {
loader: 'worker-loader',
},
}],
},
resolve: {
modules: modules,
alias: {
'jquery': require.resolve('jquery'),
'jQuery': require.resolve('jquery'),
}, },
},
}, {
test: /\.tsx?$/,
use: 'ts-loader',
exclude: /node_modules/,
}, {
test: /\.coffee?$/,
use: 'coffee-loader',
}, {
test: /\.worker\.js$/,
use: {
loader: 'worker-loader',
},
}],
},
resolve: {
modules: modules,
alias: {
'jquery': require.resolve('jquery'),
'jQuery': require.resolve('jquery'),
}, },
plugins: [ },
new webpack.ProvidePlugin({ plugins: [
$: 'jquery', new webpack.ProvidePlugin({
jQuery: 'jquery', $: 'jquery',
'window.jQuery': 'jquery', jQuery: 'jquery',
Popper: ['popper.js', 'default'], 'window.jQuery': 'jquery',
Util: 'exports-loader?Util!bootstrap/js/dist/util', Popper: ['popper.js', 'default'],
Alert: 'exports-loader?Alert!bootstrap/js/dist/alert', Util: 'exports-loader?Util!bootstrap/js/dist/util',
Button: 'exports-loader?Button!bootstrap/js/dist/button', Alert: 'exports-loader?Alert!bootstrap/js/dist/alert',
Carousel: 'exports-loader?Carousel!bootstrap/js/dist/carousel', Button: 'exports-loader?Button!bootstrap/js/dist/button',
Collapse: 'exports-loader?Collapse!bootstrap/js/dist/collapse', Carousel: 'exports-loader?Carousel!bootstrap/js/dist/carousel',
Dropdown: 'exports-loader?Dropdown!bootstrap/js/dist/dropdown', Collapse: 'exports-loader?Collapse!bootstrap/js/dist/collapse',
Modal: 'exports-loader?Modal!bootstrap/js/dist/modal', Dropdown: 'exports-loader?Dropdown!bootstrap/js/dist/dropdown',
Tooltip: 'exports-loader?Tooltip!bootstrap/js/dist/tooltip', Modal: 'exports-loader?Modal!bootstrap/js/dist/modal',
Popover: 'exports-loader?Popover!bootstrap/js/dist/popover', Tooltip: 'exports-loader?Tooltip!bootstrap/js/dist/tooltip',
Scrollspy: 'exports-loader?Scrollspy!bootstrap/js/dist/scrollspy', Popover: 'exports-loader?Popover!bootstrap/js/dist/popover',
Tab: 'exports-loader?Tab!bootstrap/js/dist/tab', Scrollspy: 'exports-loader?Scrollspy!bootstrap/js/dist/scrollspy',
}), Tab: 'exports-loader?Tab!bootstrap/js/dist/tab',
], }),
],
}; };

View File

@ -14,109 +14,109 @@ const IP = process.env.IP || conf.HOSTNAME;
const PORT = process.env.PORT || conf.PORT; const PORT = process.env.PORT || conf.PORT;
const config = merge.strategy({ const config = merge.strategy({
entry: 'prepend' entry: 'prepend'
})(common, { })(common, {
mode: 'development', mode: 'development',
entry: { entry: {
app: [ app: [
'react-hot-loader/patch', 'react-hot-loader/patch',
'webpack-dev-server/client?https://' + conf.HOSTNAME + ':' + conf.PORT, 'webpack-dev-server/client?https://' + conf.HOSTNAME + ':' + conf.PORT,
'webpack/hot/only-dev-server', 'webpack/hot/only-dev-server',
] ]
}, },
output: { output: {
path: path.join(__dirname), path: path.join(__dirname),
filename: '[name].js', filename: '[name].js',
// necessary for HMR to know where to load the hot update chunks // necessary for HMR to know where to load the hot update chunks
publicPath: 'https://' + conf.HOSTNAME + ':' + conf.PORT + '/' publicPath: 'https://' + conf.HOSTNAME + ':' + conf.PORT + '/'
}, },
module: { module: {
rules: [{ rules: [{
test: /\.scss$/, test: /\.scss$/,
use: [{ use: [{
loader: 'style-loader', loader: 'style-loader',
options: { options: {
sourceMap: true sourceMap: true
}
}, {
loader: 'css-loader',
options: {
sourceMap: true
}
}, {
loader: 'postcss-loader',
options: {
sourceMap: true,
plugins: [
autoprefixer({
// If we want to use the same browser list for more tools
// this list should be moved to package.json
// https://evilmartians.com/chronicles/autoprefixer-7-browserslist-2-released
browsers: [
'ie >= 11',
'ie_mob >= 11',
'Safari >= 10',
'Android >= 4.4',
'Chrome >= 44', // Retail
'Samsung >= 4'
]
})
]
}
}, {
loader: 'resolve-url-loader'
}, {
loader: 'sass-loader',
options: {
sourceMap: true
}
}, ]
}, {
test: /fontawesome([^.]+).(ttf|otf|eot|svg|woff(2)?)(\?[a-z0-9]+)?$/,
use: [{
loader: 'url-loader'
}]
}, {
test: /\.(gif|png|jpg|jpeg|ttf|otf|eot|svg|woff(2)?)$/,
use: [{
loader: 'file-loader',
options: {
name(file) {
return 'public/[path][name].[ext]';
},
},
}]
}]
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
],
devServer: {
host: IP,
port: PORT,
historyApiFallback: true,
hot: false,
clientLogLevel: 'info',
disableHostCheck: true,
contentBase: [
path.resolve(__dirname, 'public'),
path.resolve(__dirname, 'public', 'resources'),
path.resolve(__dirname, 'public', 'resources', conf.APPDIR, conf.DIST),
'node_modules',
],
//watchContentBase: true,
overlay: {
warnings: true,
errors: true
},
headers: {
'Access-Control-Allow-Origin': '*',
} }
}, {
loader: 'css-loader',
options: {
sourceMap: true
}
}, {
loader: 'postcss-loader',
options: {
sourceMap: true,
plugins: [
autoprefixer({
// If we want to use the same browser list for more tools
// this list should be moved to package.json
// https://evilmartians.com/chronicles/autoprefixer-7-browserslist-2-released
browsers: [
'ie >= 11',
'ie_mob >= 11',
'Safari >= 10',
'Android >= 4.4',
'Chrome >= 44', // Retail
'Samsung >= 4'
]
})
]
}
}, {
loader: 'resolve-url-loader'
}, {
loader: 'sass-loader',
options: {
sourceMap: true
}
}, ]
}, {
test: /fontawesome([^.]+).(ttf|otf|eot|svg|woff(2)?)(\?[a-z0-9]+)?$/,
use: [{
loader: 'url-loader'
}]
}, {
test: /\.(gif|png|jpg|jpeg|ttf|otf|eot|svg|woff(2)?)$/,
use: [{
loader: 'file-loader',
options: {
name(file) {
return 'public/[path][name].[ext]';
},
},
}]
}]
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
],
devServer: {
host: IP,
port: PORT,
historyApiFallback: true,
hot: false,
clientLogLevel: 'info',
disableHostCheck: true,
contentBase: [
path.resolve(__dirname, 'public'),
path.resolve(__dirname, 'public', 'resources'),
path.resolve(__dirname, 'public', 'resources', conf.APPDIR, conf.DIST),
'node_modules',
],
//watchContentBase: true,
overlay: {
warnings: true,
errors: true
}, },
headers: {
'Access-Control-Allow-Origin': '*',
}
},
}); });
module.exports = config; module.exports = config;

View File

@ -17,174 +17,174 @@ const FaviconsWebpackPlugin = require('favicons-webpack-plugin');
const UglifyJSPlugin = require('uglifyjs-webpack-plugin'); const UglifyJSPlugin = require('uglifyjs-webpack-plugin');
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({
title: 'Webpack App', title: 'Webpack App',
logo: path.join(__dirname, conf.APPDIR, conf.SRC, 'favicon.png'), logo: path.join(__dirname, conf.APPDIR, conf.SRC, 'favicon.png'),
prefix: '/icons/', prefix: '/icons/',
emitStats: false, emitStats: false,
persistentCache: true, persistentCache: true,
inject: false, inject: false,
statsFilename: path.join(conf.APPDIR, conf.DIST, 'icons', 'iconstats.json'), statsFilename: path.join(conf.APPDIR, conf.DIST, 'icons', 'iconstats.json'),
icons: { icons: {
android: true, android: true,
appleIcon: true, appleIcon: true,
appleStartup: true, appleStartup: true,
coast: true, coast: true,
favicons: true, favicons: true,
firefox: true, firefox: true,
opengraph: true, opengraph: true,
twitter: true, twitter: true,
yandex: true, yandex: true,
windows: true windows: true
} }
}), }),
]; ];
// 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,
appleStartup: true, appleStartup: true,
coast: true, coast: true,
favicons: true, favicons: true,
firefox: true, firefox: true,
opengraph: true, opengraph: true,
twitter: true, twitter: true,
yandex: true, yandex: true,
windows: true windows: true
} }
})); }));
} }
}); });
module.exports = merge(common, { 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
concatenateModules: true, //ModuleConcatenationPlugin
minimizer: [
new UglifyJSPlugin({
uglifyOptions: {
sourceMap: false,
comments: false
}
})
]
}, },
noEmitOnErrors: true, // NoEmitOnErrorsPlugin
concatenateModules: true, //ModuleConcatenationPlugin
minimizer: [
new UglifyJSPlugin({
uglifyOptions: {
sourceMap: false,
comments: false
}
})
]
},
devtool: '', devtool: '',
output: { output: {
path: path.join(__dirname, conf.APPDIR, conf.DIST), path: path.join(__dirname, conf.APPDIR, conf.DIST),
filename: path.join('js', '[name].js'), filename: path.join('js', '[name].js'),
publicPath: path.join(conf.APPDIR, conf.DIST), publicPath: path.join(conf.APPDIR, conf.DIST),
}, },
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,
minimize: true minimize: true
} }
}, {
loader: 'postcss-loader',
options: {
sourceMap: false,
plugins: [
autoprefixer({
// If we want to use the same browser list for more tools
// this list should be moved to package.json
// https://evilmartians.com/chronicles/autoprefixer-7-browserslist-2-released
browsers: [
'ie >= 11',
'ie_mob >= 11',
'Safari >= 10',
'Android >= 4.4',
'Chrome >= 44', // Retail
'Samsung >= 4'
]
})
]
}
}, {
loader: 'resolve-url-loader'
}, {
loader: 'sass-loader',
options: {
sourceMap: false
}
}, ]
})
}, { }, {
test: /fontawesome([^.]+).(ttf|otf|eot|svg|woff(2)?)(\?[a-z0-9]+)?$/, loader: 'postcss-loader',
use: [{ options: {
loader: 'file-loader', sourceMap: false,
options: { plugins: [
name: '[name].[ext]', autoprefixer({
outputPath: 'fonts/', // If we want to use the same browser list for more tools
publicPath: '../fonts/' // this list should be moved to package.json
} // https://evilmartians.com/chronicles/autoprefixer-7-browserslist-2-released
}] browsers: [
'ie >= 11',
'ie_mob >= 11',
'Safari >= 10',
'Android >= 4.4',
'Chrome >= 44', // Retail
'Samsung >= 4'
]
})
]
}
}, { }, {
test: /\.(ttf|otf|eot|svg|woff(2)?)$/, loader: 'resolve-url-loader'
use: [{
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: 'fonts/',
publicPath: '../fonts/'
}
}]
}, { }, {
test: /\.(png|jpg|jpeg|gif|svg)$/, loader: 'sass-loader',
loader: 'file-loader', options: {
options: { sourceMap: false
name: '[name].[ext]', }
outputPath: 'img/',
publicPath: '../img/'
/*,
name(file) {
//return 'public/[path][name].[ext]';
return '[hash].[ext]';
},*/
},
}, ] }, ]
}, })
}, {
test: /fontawesome([^.]+).(ttf|otf|eot|svg|woff(2)?)(\?[a-z0-9]+)?$/,
use: [{
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: 'fonts/',
publicPath: '../fonts/'
}
}]
}, {
test: /\.(ttf|otf|eot|svg|woff(2)?)$/,
use: [{
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: 'fonts/',
publicPath: '../fonts/'
}
}]
}, {
test: /\.(png|jpg|jpeg|gif|svg)$/,
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: 'img/',
publicPath: '../img/'
/*,
name(file) {
//return 'public/[path][name].[ext]';
return '[hash].[ext]';
},*/
},
}, ]
},
plugins: plugins, plugins: plugins,
}); });

View File

@ -12,22 +12,22 @@ const conf = yaml.safeLoad(fs.readFileSync(path.join(__dirname, 'app/_config/web
let themes = []; let themes = [];
// add themes // add themes
if (conf['Site\\Templates\\WebpackTemplateProvider'].THEMESDIR) { if (conf['Site\\Templates\\WebpackTemplateProvider'].THEMESDIR) {
const themeDir = conf['Site\\Templates\\WebpackTemplateProvider'].THEMESDIR; const themeDir = conf['Site\\Templates\\WebpackTemplateProvider'].THEMESDIR;
const dir = path.resolve(__dirname, themeDir); const dir = path.resolve(__dirname, themeDir);
if (filesystem.existsSync(dir)) { if (filesystem.existsSync(dir)) {
filesystem.readdirSync(dir).forEach((file) => { filesystem.readdirSync(dir).forEach((file) => {
filePath = path.join(themeDir, file); filePath = path.join(themeDir, file);
const stat = filesystem.statSync(filePath); const stat = filesystem.statSync(filePath);
if (stat && stat.isDirectory()) { if (stat && stat.isDirectory()) {
themes.push(filePath); themes.push(filePath);
} }
}); });
} }
} }
module.exports = { module.exports = {
configuration: conf['Site\\Templates\\WebpackTemplateProvider'], configuration: conf['Site\\Templates\\WebpackTemplateProvider'],
themes: themes, themes: themes,
}; };