mirror of
https://github.com/a2nt/silverstripe-webpack.git
synced 2024-10-22 17:05:31 +02:00
JS improvements
This commit is contained in:
parent
4231243674
commit
18af5420d5
@ -26,6 +26,7 @@ SilverStripe\CMS\Model\SiteTree:
|
||||
- Dynamic\Elements\Elements\ElementTestimonials
|
||||
- Site\Elements\TeamMembersElement
|
||||
- Site\Elements\SliderElement
|
||||
- DNADesign\ElementalVirtual\Model\ElementVirtual
|
||||
|
||||
DNADesign\ElementalList\Model\ElementList:
|
||||
default_global_elements: false
|
||||
|
@ -5,7 +5,7 @@ SilverStripe\SiteConfig\SiteConfig:
|
||||
|
||||
SilverStripe\SiteTree\SiteTree:
|
||||
extensions:
|
||||
- SiteTreeExtension
|
||||
- Site\Extensions\SiteTreeExtension
|
||||
|
||||
SilverStripe\Blog\Model\BlogPost:
|
||||
extensions:
|
||||
|
@ -1,3 +1,4 @@
|
||||
BetterBrief\GoogleMapField:
|
||||
default_options:
|
||||
api_key: 'YOUR_API_KEY'
|
||||
show_search_box: true
|
||||
|
@ -22,30 +22,77 @@ const FormBasics = (($) => {
|
||||
const $fields = $element.find('input,textarea,select');
|
||||
const $selectFields = $element.find('select:not([readonly])');
|
||||
const $radioOptions = $element.find('input[type="radio"]');
|
||||
const separator = ', ';
|
||||
|
||||
$selectFields.each((i, el) => {
|
||||
const $el = $(el);
|
||||
const maxOptions = $el.data('max-options') || false;
|
||||
|
||||
$el.selectpicker({
|
||||
$el.selectpicker($.extend({
|
||||
iconBase: 'fas',
|
||||
tickIcon: 'fa-check',
|
||||
liveSearch: $el.data('live-search'),
|
||||
noneSelectedText: $el.data('none-selected-text') || 'Nothing selected',
|
||||
maxOptions: $el.data('max-options') || false,
|
||||
virtualScroll: false,
|
||||
dropupAuto: false,
|
||||
size: 10,
|
||||
maxOptions: maxOptions,
|
||||
}, $el.data(), {
|
||||
multipleSeparator: separator,
|
||||
}));
|
||||
|
||||
// wrap options
|
||||
$el.on('rendered.bs.select', () => {
|
||||
if (!$el.val().length) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const $container = $el.parent().find('.filter-option-inner-inner');
|
||||
const val = $container.text();
|
||||
const vals = val.split(separator);
|
||||
let html = '';
|
||||
|
||||
vals.forEach((opt) => {
|
||||
const $opt = $el.find('option').filter((i, e) => {
|
||||
return $(e).text() === opt;
|
||||
});
|
||||
|
||||
html += '<span class="option" data-val=' + $opt.attr('value') + '>' + opt +
|
||||
' <i class="fas fa-times btn-remove"></i></span>';
|
||||
});
|
||||
|
||||
$container.html(html);
|
||||
|
||||
// remove value
|
||||
$container.find('.option').on('click', (e) => {
|
||||
e.preventDefault();
|
||||
|
||||
const $opt = $(e.currentTarget);
|
||||
const val = $opt.data('val').toString();
|
||||
//$opt.remove();
|
||||
|
||||
let vals = $el.selectpicker('val');
|
||||
const i = vals.indexOf(val);
|
||||
if (i > -1) {
|
||||
vals.splice(i, 1);
|
||||
$el.selectpicker('val', vals);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
// FIX: hidden picker
|
||||
$el.selectpicker('render');
|
||||
$el.selectpicker('refresh');
|
||||
$el.selectpicker('toggle');
|
||||
document.activeElement.blur();
|
||||
|
||||
//$el.selectpicker('show');
|
||||
//$el.selectpicker('hide');
|
||||
|
||||
/*$el.parents('.field.dropdown').find('.dropdown-toggle').click();
|
||||
$el.parents('.field.dropdown').find('.dropdown-toggle').click();
|
||||
$el.parents('.field.dropdown').find('.dropdown-toggle').click();
|
||||
$el.parents('.field.dropdown').find('.dropdown-toggle').blur();
|
||||
$el.parents('.field.dropdown').find('.dropdown-toggle').blur();*/
|
||||
});
|
||||
|
||||
// FIX: hidden picker click
|
||||
if ($selectFields.length) {
|
||||
setTimeout(() => {
|
||||
$(window).scrollTop(0, 0);
|
||||
}, 600);
|
||||
}
|
||||
|
||||
$fields.each((e, el) => {
|
||||
const $el = $(el);
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
import $ from 'jquery';
|
||||
|
||||
import MainUI from "../_main";
|
||||
import Events from '../_events';
|
||||
import SpinnerUI from './_ui.spinner';
|
||||
|
||||
@ -33,7 +34,7 @@ const CroppieUI = (($) => {
|
||||
const ui = this;
|
||||
const $el = $(element);
|
||||
|
||||
ui._element = element;
|
||||
ui.$el = $el;
|
||||
$el.data(DATA_KEY, this);
|
||||
|
||||
ui.input = $el.find('input[type="file"]');
|
||||
@ -42,10 +43,14 @@ const CroppieUI = (($) => {
|
||||
ui.width = ui.input.data('width');
|
||||
ui.height = ui.input.data('height');
|
||||
|
||||
$el.append('<div class="cropper-wrap"><div class="cropper-container"></div></div>');
|
||||
$el.append(
|
||||
'<div class="cropper-wrap"><div class="cropper-container"></div>' +
|
||||
'<a href="#" class="btn-remove"><i class="fas fa-times"></i> Remove</a></div>'
|
||||
);
|
||||
//$el.append(ui.inputData);
|
||||
|
||||
ui.uploadCrop = $el.find('.cropper-container');
|
||||
ui.uploadCropWrap = $el.find('.cropper-wrap');
|
||||
ui.uploadCrop = ui.uploadCropWrap.find('.cropper-container');
|
||||
|
||||
const ratio = ui.width / (ui.uploadCrop.width() - 32);
|
||||
ui.uploadCrop.croppie({
|
||||
@ -62,11 +67,23 @@ const CroppieUI = (($) => {
|
||||
ui.input.on('change', (e) => {
|
||||
this.readFile(e.currentTarget);
|
||||
});
|
||||
|
||||
$el.find('.btn-remove').on('click', (e) => {
|
||||
e.preventDefault();
|
||||
|
||||
ui.uploadCrop.removeClass('ready');
|
||||
$el.find('.croppie-image').remove();
|
||||
|
||||
ui.$el.find('input[type="file"]').val('');
|
||||
ui.$el.find('input[type="file"]').change();
|
||||
|
||||
ui.uploadCropWrap.hide();
|
||||
});
|
||||
}
|
||||
|
||||
readFile(input) {
|
||||
const ui = this;
|
||||
const $el = $(ui._element);
|
||||
const $el = ui.$el;
|
||||
const $form = $el.closest('form');
|
||||
|
||||
if (input.files && input.files[0]) {
|
||||
@ -79,6 +96,7 @@ const CroppieUI = (($) => {
|
||||
});
|
||||
|
||||
ui.uploadCrop.show();
|
||||
ui.uploadCropWrap.show();
|
||||
}
|
||||
|
||||
reader.readAsDataURL(input.files[0]);
|
||||
@ -87,6 +105,10 @@ const CroppieUI = (($) => {
|
||||
//$(input).val('');
|
||||
SpinnerUI.show();
|
||||
|
||||
if (!ui.uploadCrop.hasClass('ready')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
ui.uploadCrop.croppie('result', {
|
||||
type: 'blob',
|
||||
size: {
|
||||
@ -129,12 +151,24 @@ const CroppieUI = (($) => {
|
||||
$form.find('select[name="' + k + '"],input[name="' + k + '"],textarea[name="' + k + '"]').setError(true, json[k]);
|
||||
}*/
|
||||
|
||||
if (typeof json['status'] !== 'undefined' && json['status'] === 'success') {
|
||||
if (typeof json['status'] !== 'undefined') {
|
||||
if (json['status'] === 'success') {
|
||||
MainUI.alert(json['message'], json['status']);
|
||||
|
||||
if (typeof json['link'] !== 'undefined') {
|
||||
setTimeout(() => {
|
||||
G.location = json['link'];
|
||||
}, 2000);
|
||||
} else {
|
||||
//G.location.reload(false);
|
||||
}
|
||||
} else if (json['status'] === 'error') {
|
||||
MainUI.alert(json['message'], json['status']);
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof json['form'] !== 'undefined') {
|
||||
$(form).replaceWith(json['form']);
|
||||
}
|
||||
} else {
|
||||
$(form).replaceWith(data);
|
||||
|
72
app/client/src/js/_components/_ui.nocaptcha.js
Normal file
72
app/client/src/js/_components/_ui.nocaptcha.js
Normal file
@ -0,0 +1,72 @@
|
||||
import $ from 'jquery';
|
||||
import Events from '../_events';
|
||||
import Spinner from './_ui.spinner';
|
||||
|
||||
const NoCaptcha = (($) => {
|
||||
// Constants
|
||||
const W = window;
|
||||
const D = document;
|
||||
const $Body = $('body');
|
||||
|
||||
const NAME = 'NoCaptcha';
|
||||
|
||||
class NoCaptcha {
|
||||
static init() {
|
||||
const ui = this;
|
||||
ui.dispose();
|
||||
|
||||
console.log(`Initializing: ${NAME}`);
|
||||
this.renderCaptcha();
|
||||
}
|
||||
|
||||
static dispose() {
|
||||
console.log(`Destroying: ${NAME}`);
|
||||
}
|
||||
|
||||
static renderCaptcha() {
|
||||
console.log(`Rendering Captcha: ${NAME}`);
|
||||
|
||||
if (typeof grecaptcha === 'undefined') {
|
||||
console.log('Captcha API isn\'t available yet');
|
||||
}
|
||||
|
||||
const $_noCaptchaFields = $('.g-recaptcha');
|
||||
|
||||
const submitListener = (e) => {
|
||||
e.preventDefault();
|
||||
|
||||
grecaptcha.execute();
|
||||
};
|
||||
|
||||
$_noCaptchaFields.each((i, field) => {
|
||||
const $field = $(field);
|
||||
|
||||
if ($field.data('widgetid')) {
|
||||
return;
|
||||
}
|
||||
|
||||
const $form = $field.data('form') ? $('#' + $field.data('form')) : $field.parents('form');
|
||||
|
||||
//For the invisible captcha we need to setup some callback listeners
|
||||
if ($field.data('size') === 'invisible' && !$field.data('callback')) {
|
||||
$form.on('submit', submitListener);
|
||||
}
|
||||
|
||||
const widget_id = grecaptcha.render(field, $field.data());
|
||||
$field.data('widgetid', widget_id);
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
$(W).on(`${Events.AJAX}`, () => {
|
||||
NoCaptcha.init();
|
||||
});
|
||||
|
||||
W.NoCaptcha = NoCaptcha;
|
||||
W.noCaptchaFieldRender = NoCaptcha.renderCaptcha;
|
||||
|
||||
return NoCaptcha;
|
||||
})($);
|
||||
|
||||
export default NoCaptcha;
|
105
app/client/src/js/_components/_ui.video.preview.js
Normal file
105
app/client/src/js/_components/_ui.video.preview.js
Normal file
@ -0,0 +1,105 @@
|
||||
"use strict";
|
||||
|
||||
import $ from 'jquery';
|
||||
|
||||
import MainUI from "../_main";
|
||||
import Events from '../_events';
|
||||
import SpinnerUI from './_ui.spinner';
|
||||
|
||||
const VideoPreviewUI = (($) => {
|
||||
|
||||
const NAME = 'jsVideoPreviewUI';
|
||||
const DATA_KEY = NAME;
|
||||
|
||||
const G = window;
|
||||
const D = document;
|
||||
|
||||
class VideoPreviewUI {
|
||||
|
||||
constructor(el) {
|
||||
console.log(`Initializing: ${NAME}`);
|
||||
|
||||
const ui = this;
|
||||
ui.$_el = $(el);
|
||||
ui.innerHTML = ui.$_el[0].innerHTML;
|
||||
|
||||
ui.$_el.data(DATA_KEY, this);
|
||||
const href = ui.$_el.attr('href') || ui.$_el.data('href');
|
||||
let video;
|
||||
|
||||
if (video = href.match(/(youtube|youtube-nocookie|youtu|vimeo)\.(com|be)\/(watch\?v=([\w-]+)|([\w-]+))/)) {
|
||||
let video_id;
|
||||
|
||||
if (video[1] === 'youtube' || video[1] === 'youtube-nocookie') {
|
||||
video_id = video[4];
|
||||
}
|
||||
if (video[1] === 'youtu') {
|
||||
video_id = video[3];
|
||||
}
|
||||
|
||||
if (video[1] == 'vimeo') {
|
||||
video_id = video[3];
|
||||
ui.$_el.addClass('loading');
|
||||
$.ajax({
|
||||
type: 'GET',
|
||||
url: 'https://vimeo.com/api/v2/video/' + video_id + '.json',
|
||||
jsonp: 'callback',
|
||||
dataType: 'jsonp',
|
||||
success: function(data) {
|
||||
const thumbnail_src = data[0].thumbnail_large;
|
||||
ui.show(thumbnail_src);
|
||||
ui.$_el.removeClass('loading');
|
||||
}
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (video_id) {
|
||||
ui.show(`//i3.ytimg.com/vi/${video_id}/0.jpg`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
show(src) {
|
||||
const ui = this;
|
||||
ui.$_el[0].innerHTML = '';
|
||||
ui.$_el.append(`<img src="${src}" alt="Video" />`);
|
||||
}
|
||||
|
||||
static dispose() {
|
||||
console.log(`Destroying: ${NAME}`);
|
||||
ui.$_el[0].innerHTML = ui.innerHTML;
|
||||
}
|
||||
|
||||
static _jQueryInterface() {
|
||||
return this.each((i, el) => {
|
||||
// attach functionality to element
|
||||
const $el = $(el);
|
||||
let data = $el.data(DATA_KEY);
|
||||
|
||||
if (!data) {
|
||||
data = new VideoPreviewUI(el);
|
||||
$el.data(DATA_KEY, data);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// jQuery interface
|
||||
$.fn[NAME] = VideoPreviewUI._jQueryInterface;
|
||||
$.fn[NAME].Constructor = VideoPreviewUI;
|
||||
$.fn[NAME].noConflict = () => {
|
||||
$.fn[NAME] = JQUERY_NO_CONFLICT;
|
||||
return VideoPreviewUI._jQueryInterface;
|
||||
};
|
||||
|
||||
// auto-apply
|
||||
$(window).on(`${Events.AJAX} ${Events.LOADED}`, () => {
|
||||
$('[data-video-preview="true"]').jsVideoPreviewUI();
|
||||
});
|
||||
|
||||
return VideoPreviewUI;
|
||||
})($);
|
||||
|
||||
export default VideoPreviewUI;
|
@ -62,3 +62,10 @@ body.shrink {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.bootstrap-select .dropdown-toggle .filter-option .option {
|
||||
background: #dedede;
|
||||
padding: .2rem .5rem;
|
||||
margin: .2rem;
|
||||
color: #212529;
|
||||
}
|
||||
|
@ -80,15 +80,7 @@ class ElementImageWidget extends DataExtension
|
||||
|
||||
public function getWidth()
|
||||
{
|
||||
$columnSize = $this->owner->getColumnSizeRecursive();
|
||||
if (!$columnSize) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$max = Config::inst()->get(ElementRows::class, 'container_max_width');
|
||||
$size = 12 / $columnSize;
|
||||
|
||||
return $max / $size;
|
||||
return $this->owner->getColumnWidthRecursive();
|
||||
}
|
||||
|
||||
public function getHeight()
|
||||
|
@ -98,7 +98,7 @@ class ElementRows extends DataExtension
|
||||
|
||||
public function getWidthPercetage()
|
||||
{
|
||||
return $this->isColumn() ? $this->owner->getField('Size') / 12 * 100 : false;
|
||||
return $this->isColumn() ? $this->owner->getField('Size') / self::colsNumber() * 100 : false;
|
||||
}
|
||||
|
||||
public function isList()
|
||||
@ -153,15 +153,47 @@ class ElementRows extends DataExtension
|
||||
|
||||
if ($object->isColumn() && $object->getField('Size')) {
|
||||
return (int) $object->getField('Size');
|
||||
} else {
|
||||
}
|
||||
|
||||
$parent = $object->Parent()->getOwnerPage();
|
||||
|
||||
if (is_a($parent, 'Page')) {
|
||||
return ($this->owner->getField('ContainerType') === 'container-fluid') ? false : 12;
|
||||
return ($this->owner->getField('ContainerType') === 'container-fluid') ? false : self::colsNumber();
|
||||
}
|
||||
|
||||
return $object->getColumnSizeRecursive($parent);
|
||||
}
|
||||
|
||||
public function getColumnWidthRecursive($object = null, $max = null)
|
||||
{
|
||||
$max = $max ? $max : self::maxWidth();
|
||||
|
||||
$object = $object ? $object : $this->owner;
|
||||
|
||||
if(!$object->isRoot()){
|
||||
$size = $object->getField('Size');
|
||||
$max = $size ? $max / (self::colsNumber() / $size) : $max;
|
||||
$parent = $object->Parent()->getOwnerPage();
|
||||
|
||||
return $this->getColumnWidthRecursive($parent, $max);
|
||||
}
|
||||
|
||||
return $max;
|
||||
}
|
||||
|
||||
public static function colsNumber()
|
||||
{
|
||||
$db = Config::inst()->get(self::class, 'db');
|
||||
$sizes = $db['Size'];
|
||||
$sizes = preg_replace('!Enum\("([0-9,]+)","([0-9]+)"\)!i','$1', $sizes);
|
||||
$sizes = explode(',',$sizes);
|
||||
|
||||
return max($sizes);
|
||||
}
|
||||
|
||||
public static function maxWidth()
|
||||
{
|
||||
return Config::inst()->get(self::class, 'container_max_width');
|
||||
}
|
||||
|
||||
public function ExtraClass()
|
||||
|
@ -7,7 +7,7 @@ use SilverStripe\Forms\CompositeField;
|
||||
use SilverStripe\Forms\FieldList;
|
||||
use SilverStripe\Forms\TextField;
|
||||
|
||||
class UserFormExtension extends Extension
|
||||
class PlaceholderFormExtension extends Extension
|
||||
{
|
||||
public function updateFormFields(FieldList $fields)
|
||||
{
|
||||
|
@ -5,6 +5,7 @@ namespace Site\Extensions;
|
||||
use Innoweb\Sitemap\Pages\SitemapPage;
|
||||
use SilverStripe\AssetAdmin\Forms\UploadField;
|
||||
use SilverStripe\Assets\Image;
|
||||
use SilverStripe\Blog\Model\BlogPost;
|
||||
use SilverStripe\Forms\TextareaField;
|
||||
use SilverStripe\Forms\TextField;
|
||||
use SilverStripe\ORM\DataExtension;
|
||||
@ -21,7 +22,8 @@ class SiteConfigExtension extends DataExtension
|
||||
'Longitude' => 'Varchar(255)',
|
||||
'Latitude' => 'Varchar(255)',
|
||||
'MapZoom' => 'Int',
|
||||
'MapAPIKey' => 'Varchar(255)'
|
||||
'MapAPIKey' => 'Varchar(255)',
|
||||
'Description' => 'Varchar(255)',
|
||||
];
|
||||
|
||||
private static $has_one = [
|
||||
@ -57,12 +59,17 @@ class SiteConfigExtension extends DataExtension
|
||||
SitemapPage::get()->map()->toArray()
|
||||
));
|
||||
|
||||
$tab->push(TextareaField::create('Description', 'Website Description'));
|
||||
|
||||
$mapTab = $fields->findOrMakeTab('Root.GoogleMaps');
|
||||
$mapTab->push(TextField::create('MapAPIKey'));
|
||||
$mapTab->push(TextField::create('MapZoom'));
|
||||
$mapTab->push(GoogleMapField::create(
|
||||
$this->owner,
|
||||
'Location'
|
||||
'Location',
|
||||
[
|
||||
'show_search_box' => true,
|
||||
]
|
||||
));
|
||||
}
|
||||
|
||||
@ -80,4 +87,9 @@ class SiteConfigExtension extends DataExtension
|
||||
.$this->owner->getField('Longitude').'" class="btn btn-primary btn-directions" target="_blank">'
|
||||
.'<i class="fas fa-road"></i> Get Directions</a>';
|
||||
}
|
||||
|
||||
public function getLatestBlogPosts()
|
||||
{
|
||||
return BlogPost::get()->sort('PublishDate DESC');
|
||||
}
|
||||
}
|
||||
|
1
app/src/Shop/_manifest_exclude
Normal file
1
app/src/Shop/_manifest_exclude
Normal file
@ -0,0 +1 @@
|
||||
Remove it in case u need silvershop module
|
@ -9,6 +9,7 @@ use SilverStripe\Core\Config\Config;
|
||||
use SilverStripe\Control\Director;
|
||||
use SilverStripe\Core\Path;
|
||||
use SilverStripe\Core\Manifest\ManifestFileFinder;
|
||||
use SilverStripe\CMS\Controllers\CMSMain;
|
||||
|
||||
class DeferedRequirements implements TemplateGlobalProvider
|
||||
{
|
||||
@ -35,9 +36,14 @@ class DeferedRequirements implements TemplateGlobalProvider
|
||||
|
||||
public static function Auto($class = false)
|
||||
{
|
||||
if (is_a(Controller::curr(), CMSMain::class)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$config = Config::inst()->get(self::class);
|
||||
$projectName = WebpackTemplateProvider::projectName();
|
||||
$mainTheme = WebpackTemplateProvider::mainTheme();
|
||||
$mainTheme = $mainTheme ? $mainTheme : $projectName;
|
||||
|
||||
// Initialization
|
||||
Requirements::block(THIRDPARTY_DIR.'/jquery/jquery.js');
|
||||
@ -54,6 +60,7 @@ class DeferedRequirements implements TemplateGlobalProvider
|
||||
if (!$config['nofontawesome']) {
|
||||
DeferedRequirements::loadCSS('//use.fontawesome.com/releases/v5.4.0/css/all.css');
|
||||
}
|
||||
|
||||
DeferedRequirements::loadCSS($mainTheme.'.css');
|
||||
DeferedRequirements::loadJS($mainTheme.'.js');
|
||||
|
||||
|
@ -3,12 +3,22 @@
|
||||
*/
|
||||
|
||||
const webpack = require('webpack');
|
||||
const conf = require('./webpack.configuration');
|
||||
const commonVariables = require('./webpack.configuration');
|
||||
const conf = commonVariables.configuration;
|
||||
|
||||
const path = require('path');
|
||||
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'),
|
||||
path.resolve(__dirname, conf.APPDIR, 'client', 'src', 'img'),
|
||||
path.resolve(__dirname, conf.APPDIR, 'client', 'src', 'thirdparty'),
|
||||
path.resolve(__dirname, 'node_modules')
|
||||
];
|
||||
|
||||
const _addAppFiles = (theme) => {
|
||||
|
||||
@ -21,6 +31,11 @@ const _addAppFiles = (theme) => {
|
||||
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', 'scss'));
|
||||
modules.push(path.join(dirPath, 'client', 'src', 'img'));
|
||||
modules.push(path.join(dirPath, 'client', 'src', 'thirdparty'));
|
||||
|
||||
const _getAllFilesFromFolder = function(dir, includeSubFolders = true) {
|
||||
const dirPath = path.resolve(__dirname, dir);
|
||||
let results = [];
|
||||
@ -30,7 +45,7 @@ const _addAppFiles = (theme) => {
|
||||
return;
|
||||
}
|
||||
|
||||
const filePath = `${dirPath}/${file}`;
|
||||
const filePath = path.join(dirPath, file);
|
||||
const stat = filesystem.statSync(filePath);
|
||||
|
||||
if (stat && stat.isDirectory() && includeSubFolders) {
|
||||
@ -65,20 +80,9 @@ const _addAppFiles = (theme) => {
|
||||
_addAppFiles(conf.APPDIR);
|
||||
|
||||
// add themes
|
||||
if (conf.THEMESDIR) {
|
||||
const dir = path.resolve(__dirname, conf.THEMESDIR);
|
||||
|
||||
if (filesystem.existsSync(dir)) {
|
||||
filesystem.readdirSync(dir).forEach((file) => {
|
||||
filePath = `${dir}/${file}`;
|
||||
const stat = filesystem.statSync(filePath);
|
||||
|
||||
if (stat && stat.isDirectory()) {
|
||||
_addAppFiles(path.join(conf.THEMESDIR, file));
|
||||
}
|
||||
commonVariables.themes.forEach((theme) => {
|
||||
_addAppFiles(theme);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
entry: includes,
|
||||
@ -120,15 +124,7 @@ module.exports = {
|
||||
}],
|
||||
},
|
||||
resolve: {
|
||||
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'),
|
||||
path.resolve(__dirname, conf.APPDIR, 'client', 'src', 'img'),
|
||||
path.resolve(__dirname, conf.APPDIR, 'client', 'src', 'thirdparty'),
|
||||
path.resolve(__dirname, 'node_modules')
|
||||
],
|
||||
modules: modules,
|
||||
alias: {
|
||||
'jquery': require.resolve('jquery'),
|
||||
'jQuery': require.resolve('jquery'),
|
||||
|
@ -7,7 +7,8 @@ const autoprefixer = require('autoprefixer');
|
||||
const webpack = require('webpack');
|
||||
const merge = require('webpack-merge');
|
||||
const common = require('./webpack.config.common.js');
|
||||
const conf = require('./webpack.configuration');
|
||||
const commonVariables = require('./webpack.configuration');
|
||||
const conf = commonVariables.configuration;
|
||||
|
||||
const IP = process.env.IP || conf.HOSTNAME;
|
||||
const PORT = process.env.PORT || conf.PORT;
|
||||
@ -101,6 +102,7 @@ const config = merge.strategy({
|
||||
historyApiFallback: true,
|
||||
hot: false,
|
||||
clientLogLevel: 'info',
|
||||
disableHostCheck: true,
|
||||
contentBase: [
|
||||
path.resolve(__dirname, 'public'),
|
||||
path.resolve(__dirname, 'public', 'resources'),
|
||||
|
@ -3,16 +3,81 @@
|
||||
*/
|
||||
|
||||
const webpack = require('webpack');
|
||||
const conf = require('./webpack.configuration');
|
||||
const commonVariables = require('./webpack.configuration');
|
||||
const conf = commonVariables.configuration;
|
||||
const merge = require('webpack-merge');
|
||||
const common = require('./webpack.config.common.js');
|
||||
|
||||
const filesystem = require('fs');
|
||||
const path = require('path');
|
||||
const autoprefixer = require('autoprefixer');
|
||||
|
||||
const ExtractTextPlugin = require('extract-text-webpack-plugin');
|
||||
const FaviconsWebpackPlugin = require('favicons-webpack-plugin');
|
||||
|
||||
let plugins = [
|
||||
new webpack.DefinePlugin({
|
||||
'process.env': {
|
||||
'NODE_ENV': JSON.stringify('production')
|
||||
}
|
||||
}),
|
||||
new webpack.LoaderOptionsPlugin({
|
||||
minimize: true,
|
||||
debug: false
|
||||
}),
|
||||
new webpack.optimize.ModuleConcatenationPlugin(),
|
||||
new webpack.optimize.UglifyJsPlugin({
|
||||
sourceMap: false,
|
||||
comments: false
|
||||
}),
|
||||
new ExtractTextPlugin({
|
||||
filename: 'css/[name].css',
|
||||
allChunks: true
|
||||
}),
|
||||
|
||||
new FaviconsWebpackPlugin({
|
||||
logo: path.join(__dirname, conf.APPDIR, conf.SRC, 'favicon.png'),
|
||||
prefix: '/icons/',
|
||||
statsFilename: path.join(conf.APPDIR, conf.DIST, 'icons', 'iconstats.json'),
|
||||
icons: {
|
||||
android: true,
|
||||
appleIcon: true,
|
||||
appleStartup: true,
|
||||
coast: true,
|
||||
favicons: true,
|
||||
firefox: true,
|
||||
opengraph: true,
|
||||
twitter: true,
|
||||
yandex: true,
|
||||
windows: true
|
||||
}
|
||||
}),
|
||||
];
|
||||
|
||||
// add themes favicons
|
||||
commonVariables.themes.forEach((theme) => {
|
||||
const faviconPath = path.join(__dirname, theme, conf.SRC, 'favicon.png');
|
||||
if (filesystem.existsSync(faviconPath)) {
|
||||
plugins.push(new FaviconsWebpackPlugin({
|
||||
logo: faviconPath,
|
||||
prefix: '/' + theme + '-icons/',
|
||||
statsFilename: path.join(conf.APPDIR, conf.DIST, theme + '-icons', 'iconstats.json'),
|
||||
icons: {
|
||||
android: true,
|
||||
appleIcon: true,
|
||||
appleStartup: true,
|
||||
coast: true,
|
||||
favicons: true,
|
||||
firefox: true,
|
||||
opengraph: true,
|
||||
twitter: true,
|
||||
yandex: true,
|
||||
windows: true
|
||||
}
|
||||
}));
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = merge(common, {
|
||||
devtool: '',
|
||||
|
||||
@ -98,42 +163,5 @@ module.exports = merge(common, {
|
||||
}, ]
|
||||
},
|
||||
|
||||
plugins: [
|
||||
new webpack.DefinePlugin({
|
||||
'process.env': {
|
||||
'NODE_ENV': JSON.stringify('production')
|
||||
}
|
||||
}),
|
||||
new webpack.LoaderOptionsPlugin({
|
||||
minimize: true,
|
||||
debug: false
|
||||
}),
|
||||
new webpack.optimize.ModuleConcatenationPlugin(),
|
||||
new webpack.optimize.UglifyJsPlugin({
|
||||
sourceMap: false,
|
||||
comments: false
|
||||
}),
|
||||
new ExtractTextPlugin({
|
||||
filename: 'css/[name].css',
|
||||
allChunks: true
|
||||
}),
|
||||
|
||||
new FaviconsWebpackPlugin({
|
||||
logo: path.join(__dirname, conf.APPDIR, conf.SRC, 'favicon.png'),
|
||||
prefix: '/icons/',
|
||||
statsFilename: path.join(conf.APPDIR, conf.DIST, 'icons', 'iconstats.json'),
|
||||
icons: {
|
||||
android: true,
|
||||
appleIcon: true,
|
||||
appleStartup: true,
|
||||
coast: true,
|
||||
favicons: true,
|
||||
firefox: true,
|
||||
opengraph: true,
|
||||
twitter: true,
|
||||
yandex: true,
|
||||
windows: true
|
||||
}
|
||||
}),
|
||||
],
|
||||
plugins: plugins,
|
||||
});
|
||||
|
@ -3,8 +3,31 @@
|
||||
*/
|
||||
|
||||
const path = require('path');
|
||||
const filesystem = require('fs');
|
||||
const fs = require('fs');
|
||||
const yaml = require('js-yaml');
|
||||
|
||||
const conf = yaml.safeLoad(fs.readFileSync(path.join(__dirname, 'app/_config/webpack.yml'), 'utf8'));
|
||||
|
||||
module.exports = conf['Site\\Templates\\WebpackTemplateProvider'];
|
||||
let themes = [];
|
||||
// add themes
|
||||
if (conf['Site\\Templates\\WebpackTemplateProvider'].THEMESDIR) {
|
||||
const themeDir = conf['Site\\Templates\\WebpackTemplateProvider'].THEMESDIR;
|
||||
const dir = path.resolve(__dirname, themeDir);
|
||||
|
||||
if (filesystem.existsSync(dir)) {
|
||||
filesystem.readdirSync(dir).forEach((file) => {
|
||||
filePath = path.join(themeDir, file);
|
||||
const stat = filesystem.statSync(filePath);
|
||||
|
||||
if (stat && stat.isDirectory()) {
|
||||
themes.push(filePath);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
configuration: conf['Site\\Templates\\WebpackTemplateProvider'],
|
||||
themes: themes,
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user