mirror of
https://github.com/a2nt/silverstripe-webpack.git
synced 2024-10-22 17:05:31 +02:00
Initial theming support
This commit is contained in:
parent
003d282905
commit
8429a6739a
@ -20,5 +20,12 @@ $config->enablePlugins([
|
||||
$config->addButtonsToLine(2, 'hr');
|
||||
$config->setOption('block_formats', 'Paragraph=p;Heading 2=h2;Heading 3=h3;Heading 4=h4;Heading 5=h5;Heading 6=h6;Address=address;Pre=pre');
|
||||
$config->setOption('invalid_elements', 'h1');
|
||||
$config->setOption(
|
||||
'table_class_list',
|
||||
[
|
||||
['title' => 'Transparent Table', 'value' => 'table-none'],
|
||||
['title' => 'Shaded rows', 'value' => 'table table-striped table-bordered'],
|
||||
]
|
||||
);
|
||||
|
||||
FulltextSearchable::enable();
|
||||
|
@ -19,8 +19,8 @@ SilverStripe\View\SSViewer:
|
||||
|
||||
SilverStripe\Admin\LeftAndMain:
|
||||
extra_requirements_css:
|
||||
- 'app/client/dist/css/cms.css'
|
||||
- 'app/client/dist/css/app_cms.css'
|
||||
|
||||
SilverStripe\Forms\HTMLEditor\TinyMCEConfig:
|
||||
editor_css:
|
||||
- 'app/client/dist/css/editor.css'
|
||||
- 'app/client/dist/css/app_editor.css'
|
||||
|
@ -25,6 +25,7 @@ SilverStripe\CMS\Model\SiteTree:
|
||||
- Dynamic\Elements\Oembed\Elements\ElementOembed
|
||||
- Dynamic\Elements\Elements\ElementTestimonials
|
||||
- Site\Elements\TeamMembersElement
|
||||
- Site\Elements\SliderElement
|
||||
|
||||
DNADesign\ElementalList\Model\ElementList:
|
||||
default_global_elements: false
|
||||
@ -50,4 +51,3 @@ DNADesign\Elemental\Models\ElementContent:
|
||||
Dynamic\Elements\Image\Elements\ElementImage:
|
||||
extensions:
|
||||
- Site\Extensions\ElementImageWidget
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
SilverStripe\SiteConfig\SiteConfig:
|
||||
extensions:
|
||||
- Broarm\OpeningHours\OpeningHours
|
||||
- Site\Extensions\SiteConfigExtension
|
||||
- Site\Extensions\SocialExtension
|
||||
|
||||
@ -19,3 +18,18 @@ Dynamic\FlexSlider\Model\SlideImage:
|
||||
SilverStripe\Core\Injector\Injector:
|
||||
SilverStripe\UserForms\Model\UserDefinedForm:
|
||||
class: Site\Extensions\CMSMain_HiddenClass
|
||||
SilverStripe\Security\MemberAuthenticator\LostPasswordHandler:
|
||||
class: Site\Extensions\LostPasswordHandlerExtension
|
||||
|
||||
# User Forms
|
||||
SilverStripe\UserForms\Form\UserForm:
|
||||
extensions:
|
||||
- Site\Extensions\PlaceholderFormExtension
|
||||
|
||||
SilverStripe\UserForms\Model\UserDefinedForm:
|
||||
extensions:
|
||||
- Site\Extensions\UserDefinedFormExtension
|
||||
|
||||
DNADesign\ElementalUserForms\Model\ElementForm:
|
||||
extensions:
|
||||
- Site\Extensions\UserDefinedFormExtension
|
||||
|
79
app/_config/files.yml
Normal file
79
app/_config/files.yml
Normal file
@ -0,0 +1,79 @@
|
||||
---
|
||||
Name: webapp-files
|
||||
---
|
||||
|
||||
SilverStripe\Assets\Upload_Validator:
|
||||
allowedExtensions:
|
||||
- 'stl'
|
||||
|
||||
SilverStripe\Assets\File:
|
||||
allowed_extensions:
|
||||
- 'ace'
|
||||
- 'arc'
|
||||
- 'arj'
|
||||
- 'asf'
|
||||
- 'au'
|
||||
- 'avi'
|
||||
- 'bmp'
|
||||
- 'bz2'
|
||||
- 'cab'
|
||||
- 'cda'
|
||||
- 'csv'
|
||||
- 'dmg'
|
||||
- 'doc'
|
||||
- 'docx'
|
||||
- 'dotx'
|
||||
- 'flv'
|
||||
- 'gif'
|
||||
- 'gpx'
|
||||
- 'gz'
|
||||
- 'hqx'
|
||||
- 'ico'
|
||||
- 'jpeg'
|
||||
- 'jpg'
|
||||
- 'kml'
|
||||
- 'm4a'
|
||||
- 'm4v'
|
||||
- 'mid'
|
||||
- 'midi'
|
||||
- 'mkv'
|
||||
- 'mov'
|
||||
- 'mp3'
|
||||
- 'mp4'
|
||||
- 'mpa'
|
||||
- 'mpeg'
|
||||
- 'mpg'
|
||||
- 'ogg'
|
||||
- 'ogv'
|
||||
- 'pages'
|
||||
- 'pcx'
|
||||
- 'pdf'
|
||||
- 'png'
|
||||
- 'pps'
|
||||
- 'ppt'
|
||||
- 'pptx'
|
||||
- 'potx'
|
||||
- 'ra'
|
||||
- 'ram'
|
||||
- 'rm'
|
||||
- 'rtf'
|
||||
- 'sit'
|
||||
- 'sitx'
|
||||
- 'tar'
|
||||
- 'tgz'
|
||||
- 'tif'
|
||||
- 'tiff'
|
||||
- 'txt'
|
||||
- 'wav'
|
||||
- 'webm'
|
||||
- 'wma'
|
||||
- 'wmv'
|
||||
- 'xls'
|
||||
- 'xlsx'
|
||||
- 'xltx'
|
||||
- 'zip'
|
||||
- 'zipx'
|
||||
- 'stl'
|
||||
app_categories:
|
||||
document:
|
||||
- 'stl'
|
@ -3,9 +3,11 @@
|
||||
# Cuz WebPack compiling script use it to set configuration
|
||||
|
||||
Site\Templates\WebpackTemplateProvider:
|
||||
SRC: app/client/src
|
||||
DIST: app/client/dist
|
||||
APPDIR: app
|
||||
THEMESDIR: themes
|
||||
HOSTNAME: localhost
|
||||
PORT: 3000
|
||||
TYPESJS: app/client/src/js/types
|
||||
TYPESSCSS: app/client/src/scss/types
|
||||
SRC: client/src
|
||||
DIST: client/dist
|
||||
TYPESJS: client/src/js/types
|
||||
TYPESSCSS: client/src/scss/types
|
@ -43,8 +43,7 @@ const CarouselUI = (($) => {
|
||||
|
||||
// create arrows
|
||||
if ($e.data('arrows')) {
|
||||
let $prev = $('<i class="carousel-control-prev" data-target="#' + id + '" role="button" data-slide="prev"><i class="fas fa-chevron-left" aria-hidden="true"></i><i class="sr-only">Previous</i></i>');
|
||||
$e.prepend($prev);
|
||||
$e.prepend('<i class="carousel-control-prev" data-target="#' + id + '" role="button" data-slide="prev"><i class="fas fa-chevron-left" aria-hidden="true"></i><i class="sr-only">Previous</i></i>');
|
||||
$e.prepend('<i class="carousel-control-next" data-target="#' + id + '" role="button" data-slide="next"><i class="fas fa-chevron-right" aria-hidden="true"></i><i class="sr-only">Next</i></i>');
|
||||
}
|
||||
|
||||
@ -68,8 +67,8 @@ const CarouselUI = (($) => {
|
||||
$(event.target).carousel('prev');
|
||||
});
|
||||
|
||||
$e.find('img').hammer().bind('tap', (event) => {
|
||||
$e.carousel('next');
|
||||
$e.hammer().bind('tap', (event) => {
|
||||
$(event.target).carousel('next');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -27,10 +27,26 @@ const FormBasics = (($) => {
|
||||
const $el = $(el);
|
||||
|
||||
$el.selectpicker({
|
||||
liveSearch: $el.data('live-search')
|
||||
iconBase: 'fas',
|
||||
tickIcon: 'fa-check',
|
||||
liveSearch: $el.data('live-search'),
|
||||
noneSelectedText: $el.data('none-selected-text') || 'Nothing selected',
|
||||
maxOptions: $el.data('max-options') || false,
|
||||
});
|
||||
|
||||
// FIX: hidden picker
|
||||
$el.parents('.field.dropdown').find('.dropdown-toggle').click();
|
||||
$el.parents('.field.dropdown').find('.dropdown-toggle').click();
|
||||
$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);
|
||||
|
||||
|
@ -104,6 +104,10 @@ const CroppieUI = (($) => {
|
||||
data.append(name, blob, name + '-image.png');
|
||||
data.append('ajax', '1');
|
||||
|
||||
if (!$(form).data('jsFormValidate').validate()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
url: $(form).attr('action'),
|
||||
data: data,
|
||||
@ -112,27 +116,29 @@ const CroppieUI = (($) => {
|
||||
type: $(form).attr('method'),
|
||||
success: function(data) {
|
||||
let IS_JSON = false;
|
||||
let json = {};
|
||||
try {
|
||||
IS_JSON = true;
|
||||
const json = $.parseJSON(data);
|
||||
json = $.parseJSON(data);
|
||||
} catch (e) {
|
||||
IS_JSON = false;
|
||||
}
|
||||
|
||||
if (IS_JSON && typeof json === 'object') {
|
||||
for (let k in json) {
|
||||
if (IS_JSON) {
|
||||
/*for (let k in json) {
|
||||
$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['link'] !== 'undefined') {
|
||||
G.location = json['link'];
|
||||
} else {
|
||||
G.location.reload(false);
|
||||
//G.location.reload(false);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
G.location.reload(false);
|
||||
$(form).replaceWith(data);
|
||||
//G.location.reload(false);
|
||||
}
|
||||
|
||||
SpinnerUI.hide();
|
||||
|
@ -65,22 +65,26 @@ const FormValidateField = (($) => {
|
||||
});
|
||||
}
|
||||
|
||||
this.removeError();
|
||||
if (valid) {
|
||||
this.removeError();
|
||||
return true;
|
||||
}
|
||||
|
||||
this.setError(scrollTo, msg);
|
||||
setTimeout(() => {
|
||||
this.setError(scrollTo, msg);
|
||||
}, 500);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
valideURL(str) {
|
||||
const regex = /(http|https):\/\/(\w+:{0,1}\w*)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%!\-\/]))?/;
|
||||
if (!regex.test(str)) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
const pattern = new RegExp('^(https?:\\/\\/){1}' + // protocol
|
||||
'((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.?)+[a-z]{2,}|' + // domain name
|
||||
'((\\d{1,3}\\.){3}\\d{1,3}))' + // OR ip (v4) address
|
||||
'(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*' + // port and path
|
||||
'(\\?[;&a-z\\d%_.~+=-]*)?' + // query string
|
||||
'(\\#[-a-z\\d_]*)?$', 'i'); // fragment locator
|
||||
return pattern.test(str);
|
||||
}
|
||||
|
||||
setError(scrollTo = true, msg = null) {
|
||||
|
@ -1,6 +1,7 @@
|
||||
import $ from 'jquery';
|
||||
import Events from "../_events";
|
||||
import FormValidateField from "./_ui.form.validate.field";
|
||||
import SpinnerUI from './_ui.spinner';
|
||||
|
||||
const FormValidate = (($) => {
|
||||
// Constants
|
||||
@ -67,6 +68,7 @@ const FormValidate = (($) => {
|
||||
validate(scrollTo = true, badCallback = false) {
|
||||
console.log('Checking the form ...');
|
||||
const ui = this;
|
||||
let valid = true;
|
||||
|
||||
ui._fields.each(function(i, el) {
|
||||
const $el = $(el);
|
||||
@ -77,9 +79,14 @@ const FormValidate = (($) => {
|
||||
badCallback();
|
||||
}
|
||||
|
||||
console.log('Invalid form data');
|
||||
SpinnerUI.hide();
|
||||
valid = false;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
return valid;
|
||||
}
|
||||
|
||||
static _jQueryInterface() {
|
||||
|
@ -20,7 +20,7 @@ import FormDatetime from './_components/_ui.form.datetime';
|
||||
import FormStepped from './_components/_ui.form.stepped';
|
||||
import FormValidate from './_components/_ui.form.validate';
|
||||
import FormStorage from './_components/_ui.form.storage';
|
||||
import FormCroppie from './_components/_ui.form.croppie';
|
||||
//import FormCroppie from './_components/_ui.form.croppie';
|
||||
|
||||
import AjaxUI from './_components/_ui.ajax';
|
||||
|
||||
|
@ -15,7 +15,13 @@
|
||||
}
|
||||
|
||||
.carousel-indicators li {
|
||||
box-shadow: 1px 1px #000;
|
||||
box-shadow: none;
|
||||
|
||||
// 1px 1px #000;
|
||||
}
|
||||
|
||||
.carousel-title {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.carousel-title,
|
||||
|
39
app/client/src/scss/_components/_ui.form.basics.scss
Normal file
39
app/client/src/scss/_components/_ui.form.basics.scss
Normal file
@ -0,0 +1,39 @@
|
||||
// date-time fields
|
||||
input.date,
|
||||
input.time {
|
||||
&[readonly] {
|
||||
background-color: $white;
|
||||
}
|
||||
}
|
||||
|
||||
.bootstrap-timepicker-widget,
|
||||
.datepicker-dropdown {
|
||||
border: 1px solid #ced4da;
|
||||
box-shadow: 0 0 3px #999;
|
||||
}
|
||||
|
||||
.bootstrap-timepicker-widget {
|
||||
.glyphicon {
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
display: inline-block;
|
||||
font-style: normal;
|
||||
font-variant: normal;
|
||||
text-rendering: auto;
|
||||
line-height: 1;
|
||||
font-family: Font Awesome\ 5 Free;
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
.glyphicon-chevron-up:before {
|
||||
content: "\f077";
|
||||
}
|
||||
|
||||
.glyphicon-chevron-down:before {
|
||||
content: "\f078";
|
||||
}
|
||||
|
||||
input {
|
||||
border: 1px solid #ced4da;
|
||||
}
|
||||
}
|
@ -60,6 +60,55 @@ button, input, optgroup, select, textarea,
|
||||
|
||||
.field {
|
||||
margin: ($grid-gutter-height / 4) 0;
|
||||
|
||||
&.composite {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
&.required {
|
||||
&:after {
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: 2rem;
|
||||
right: .5rem;
|
||||
content: "*";
|
||||
color: $red;
|
||||
z-index: 2;
|
||||
}
|
||||
}
|
||||
|
||||
&.holder-error,
|
||||
&.error {
|
||||
input, select, textarea {
|
||||
border-color: $red;
|
||||
}
|
||||
|
||||
label {
|
||||
color: $red;
|
||||
}
|
||||
}
|
||||
|
||||
.bootstrap-select:not([class*="col-"]):not([class*="form-control"]):not(.input-group-btn) {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.message {
|
||||
@extend .alert;
|
||||
|
||||
@extend .alert-info;
|
||||
|
||||
display: block;
|
||||
margin: .5rem 0;
|
||||
}
|
||||
|
||||
.message.validation,
|
||||
.message.required,
|
||||
.message.error {
|
||||
@extend .alert;
|
||||
|
||||
@extend .alert-danger;
|
||||
}
|
||||
|
||||
// stick navbar to top using mobile layout
|
||||
|
@ -53,42 +53,12 @@ body.shrink {}
|
||||
@extend .alert-danger;
|
||||
}
|
||||
|
||||
// date-time fields
|
||||
input.date,
|
||||
input.time {
|
||||
&[readonly] {
|
||||
background-color: $white;
|
||||
}
|
||||
}
|
||||
|
||||
.bootstrap-timepicker-widget,
|
||||
.datepicker-dropdown {
|
||||
border: 1px solid #ced4da;
|
||||
box-shadow: 0 0 3px #999;
|
||||
}
|
||||
|
||||
.bootstrap-timepicker-widget {
|
||||
.glyphicon {
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
display: inline-block;
|
||||
font-style: normal;
|
||||
font-variant: normal;
|
||||
text-rendering: auto;
|
||||
line-height: 1;
|
||||
font-family: Font Awesome\ 5 Free;
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
.glyphicon-chevron-up:before {
|
||||
content: "\f077";
|
||||
}
|
||||
|
||||
.glyphicon-chevron-down:before {
|
||||
content: "\f078";
|
||||
}
|
||||
|
||||
input {
|
||||
border: 1px solid #ced4da;
|
||||
.element {
|
||||
&.site__elements__sliderelement {
|
||||
.element-container {
|
||||
width: 100%;
|
||||
padding: 0;
|
||||
max-width: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -13,6 +13,7 @@
|
||||
@import "_components/_ui.lightbox";
|
||||
|
||||
@import "_components/_ui.main";
|
||||
@import "_components/_ui.form.basics";
|
||||
@import "_components/_ui.elemental";
|
||||
|
||||
// Your custom styling
|
||||
|
@ -45,6 +45,15 @@ table {
|
||||
@extend .table;
|
||||
|
||||
@extend .table-bordered;
|
||||
|
||||
@extend .table-striped;
|
||||
}
|
||||
|
||||
table {
|
||||
&.table-none {
|
||||
border: 0;
|
||||
|
||||
tr, td, th {
|
||||
border: 0;
|
||||
background: none !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,10 @@ en:
|
||||
SilverStripe\Security\Member:
|
||||
SURNAME: 'Last Name'
|
||||
db_Surname: 'Last Name'
|
||||
SUBJECTPASSWORDRESET: 'Your password reset link'
|
||||
ENTEREMAIL: 'Please enter an email address to get a password reset link.'
|
||||
PASSWORDRESETSENTHEADER: 'Password reset link sent'
|
||||
PASSWORDRESETSENTTEXT: 'Thank you. A reset link has been sent, provided an account exists for this email address.'
|
||||
Page:
|
||||
LOADINGTEXT: "LOADING .."
|
||||
JAVASCRIPTREQUIRED: "Please, enable javascript!"
|
||||
@ -13,3 +17,7 @@ en:
|
||||
db_Surname: 'Last Name'
|
||||
SilverShop\Page\CheckoutPage:
|
||||
ProceedToPayment: 'Send Order to Store'
|
||||
UndefinedOffset\NoCaptcha\Forms\NocaptchaField:
|
||||
EMPTY: "Please prove you are human - check the Captcha box."
|
||||
NOSCRIPT: "You must enable JavaScript to submit this form"
|
||||
VALIDATE_ERROR: "Captcha could not be validated"
|
||||
|
@ -61,17 +61,19 @@ class SliderElement extends ElementSlideshow
|
||||
]);
|
||||
|
||||
$grid = $fields->dataFieldByName('Slides');
|
||||
$config = $grid->getConfig();
|
||||
if ($grid) {
|
||||
$config = $grid->getConfig();
|
||||
|
||||
$columns = new GridFieldEditableColumns();
|
||||
$columns->setDisplayFields([
|
||||
'Hide' => [
|
||||
'title' => 'Hide it?',
|
||||
'field' => CheckboxField::class,
|
||||
],
|
||||
]);
|
||||
$columns = new GridFieldEditableColumns();
|
||||
$columns->setDisplayFields([
|
||||
'Hide' => [
|
||||
'title' => 'Hide it?',
|
||||
'field' => CheckboxField::class,
|
||||
],
|
||||
]);
|
||||
|
||||
$config->addComponent($columns);
|
||||
$config->addComponent($columns);
|
||||
}
|
||||
|
||||
return $fields;
|
||||
}
|
||||
|
69
app/src/Extensions/LostPasswordHandlerExtension.php
Normal file
69
app/src/Extensions/LostPasswordHandlerExtension.php
Normal file
@ -0,0 +1,69 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: tony
|
||||
* Date: 6/30/18
|
||||
* Time: 11:37 PM
|
||||
*/
|
||||
|
||||
namespace Site\Extensions;
|
||||
|
||||
use Sheadawson\Linkable\Forms\LinkField;
|
||||
use Sheadawson\Linkable\Models\Link;
|
||||
use SilverStripe\Control\HTTPResponse;
|
||||
use SilverStripe\Forms\FieldList;
|
||||
use SilverStripe\Forms\TextField;
|
||||
use SilverStripe\ORM\DataExtension;
|
||||
use SilverStripe\ORM\FieldType\DBField;
|
||||
use SilverStripe\Security\MemberAuthenticator\LostPasswordHandler;
|
||||
|
||||
class LostPasswordHandlerExtension extends LostPasswordHandler
|
||||
{
|
||||
private static $url_handlers = [
|
||||
'passwordsent' => 'passwordsent',
|
||||
];
|
||||
|
||||
private static $allowed_actions = [
|
||||
'passwordsent',
|
||||
];
|
||||
|
||||
/**
|
||||
* Show the "password sent" page, after a user has requested
|
||||
* to reset their password.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function passwordsent()
|
||||
{
|
||||
$message = _t(
|
||||
'SilverStripe\\Security\\Security.PASSWORDRESETSENTTEXT',
|
||||
"Thank you. A reset link has been sent, provided an account exists for this email address."
|
||||
);
|
||||
|
||||
$email = $this->getRequest()->getVar('email');
|
||||
$message = $email
|
||||
? 'Thank you! A reset link has been sent to \''.$email.'\', provided an account exists for this email address.'
|
||||
: $message;
|
||||
|
||||
return [
|
||||
'Title' => _t(
|
||||
'SilverStripe\\Security\\Security.PASSWORDRESETSENTHEADER',
|
||||
"Password reset link sent".($email ? ' to \''.$email.'\'' : '')
|
||||
),
|
||||
'ElementalArea' => DBField::create_field('HTMLFragment', "<p>$message</p>"),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Avoid information disclosure by displaying the same status, regardless wether the email address actually exists
|
||||
*
|
||||
* @param array $data
|
||||
* @return HTTPResponse
|
||||
*/
|
||||
protected function redirectToSuccess(array $data)
|
||||
{
|
||||
$link = $this->link('passwordsent').'?email='.$data['Email'];
|
||||
|
||||
return $this->redirect($this->addBackURLParam($link));
|
||||
}
|
||||
}
|
37
app/src/Extensions/PlaceholderFormExtension.php
Normal file
37
app/src/Extensions/PlaceholderFormExtension.php
Normal file
@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace Site\Extensions;
|
||||
|
||||
use SilverStripe\Core\Extension;
|
||||
use SilverStripe\Forms\CompositeField;
|
||||
use SilverStripe\Forms\FieldList;
|
||||
use SilverStripe\Forms\TextField;
|
||||
|
||||
class UserFormExtension extends Extension
|
||||
{
|
||||
public function updateFormFields(FieldList $fields)
|
||||
{
|
||||
foreach ($fields as $field) {
|
||||
$this->setPlaceholder($field);
|
||||
}
|
||||
}
|
||||
|
||||
private function setPlaceholder($field)
|
||||
{
|
||||
if(is_a($field, TextField::class)) {
|
||||
$field->setAttribute(
|
||||
'placeholder',
|
||||
$field->Title()
|
||||
.($field->hasClass('requiredField') ? '*' : '')
|
||||
);
|
||||
$field->setTitle('');
|
||||
}
|
||||
|
||||
if(is_a($field, CompositeField::class)) {
|
||||
$children = $field->getChildren();
|
||||
foreach ($children as $child) {
|
||||
$this->setPlaceholder($child);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -11,6 +11,7 @@ use SilverStripe\ORM\DataExtension;
|
||||
use SilverStripe\CMS\Model\SiteTree;
|
||||
use SilverStripe\Forms\FieldList;
|
||||
use SilverStripe\Forms\TreeMultiselectField;
|
||||
use SilverStripe\Forms\DropdownField;
|
||||
use BetterBrief\GoogleMapField;
|
||||
|
||||
class SiteConfigExtension extends DataExtension
|
||||
|
79
app/src/Extensions/UserDefinedFormExtension.php
Normal file
79
app/src/Extensions/UserDefinedFormExtension.php
Normal file
@ -0,0 +1,79 @@
|
||||
<?php
|
||||
|
||||
namespace Site\Extensions;
|
||||
|
||||
use SilverStripe\Forms\FieldList;
|
||||
use SilverStripe\Forms\GridField\GridFieldDataColumns;
|
||||
use SilverStripe\Forms\GridField\GridFieldPaginator;
|
||||
use SilverStripe\Forms\ListboxField;
|
||||
use SilverStripe\Forms\TextareaField;
|
||||
use SilverStripe\ORM\DataExtension;
|
||||
use SilverStripe\UserForms\Model\EditableFormField;
|
||||
|
||||
class UserDefinedFormExtension extends DataExtension
|
||||
{
|
||||
private static $db = [
|
||||
'CustomThankYouCode' => 'HTMLText',
|
||||
'RedirectOnComplete' => 'Boolean(0)',
|
||||
'RedirectOnCompleteURL' => 'Varchar(255)',
|
||||
];
|
||||
|
||||
private static $many_many = [
|
||||
'SubmissionColumns' => EditableFormField::class,
|
||||
];
|
||||
|
||||
public function updateCMSFields(FieldList $fields)
|
||||
{
|
||||
parent::updateCMSFields($fields);
|
||||
|
||||
$fields->removeByName('RedirectOnComplete');
|
||||
$fields->removeByName('RedirectOnCompleteURL');
|
||||
|
||||
$fields->removeByName('SubmissionColumns');
|
||||
|
||||
$fields->addFieldToTab(
|
||||
'Root.Main',
|
||||
ListboxField::create(
|
||||
'SubmissionColumns',
|
||||
'Display following columns at submissions list',
|
||||
$this->owner->Fields()->map('ID', 'Title')
|
||||
)
|
||||
);
|
||||
|
||||
$tab = $fields->findOrMakeTab('Root.FormOptions');
|
||||
|
||||
/*$tab->push(CheckboxField::create('RedirectOnComplete'));
|
||||
$tab->push(TextField::create('RedirectOnCompleteURL'));*/
|
||||
$tab->push(TextareaField::create('CustomThankYouCode'));
|
||||
|
||||
$grid = $fields->dataFieldByName('Submissions');
|
||||
|
||||
$config = $grid->getConfig();
|
||||
$config->getComponentByType(GridFieldPaginator::class)->setItemsPerPage(100);
|
||||
|
||||
$cols = $this->owner->SubmissionColumns();
|
||||
if ($grid && $cols->count()) {
|
||||
$dataCols = $config->getComponentByType(GridFieldDataColumns::class);
|
||||
|
||||
$columns = [
|
||||
'ID' => 'ID',
|
||||
'Created' => 'Created',
|
||||
];
|
||||
|
||||
foreach ($cols as $col) {
|
||||
$title = $col->getField('Title');
|
||||
$name = $col->getField('Name');
|
||||
$columns[$name] = [
|
||||
'title' => $title,
|
||||
'callback' => function($item) use ($name) {
|
||||
return $item->relField($name);
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
$columns['Actions'] = 'Actions';
|
||||
|
||||
$dataCols->setDisplayFields($columns);
|
||||
}
|
||||
}
|
||||
}
|
@ -18,6 +18,8 @@ use SilverStripe\Forms\RequiredFields;
|
||||
use SilverStripe\Control\HTTPRequest;
|
||||
use SilverStripe\ORM\ArrayList;
|
||||
use DNADesign\Elemental\Models\ElementContent;
|
||||
use DNADesign\Elemental\Models\ElementalArea;
|
||||
use DNADesign\ElementalUserForms\Control\ElementFormController;
|
||||
|
||||
class PageController extends ContentController
|
||||
{
|
||||
@ -38,6 +40,26 @@ class PageController extends ContentController
|
||||
return $this->render();
|
||||
}
|
||||
|
||||
public function ElementalArea()
|
||||
{
|
||||
if($this->CurrentElement()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ElementalArea::get()->byID($this->getField('ElementalAreaID'));
|
||||
}
|
||||
|
||||
public function CurrentElement()
|
||||
{
|
||||
$contoller_curr = Controller::curr();
|
||||
|
||||
if(is_a($contoller_curr, ElementFormController::class)) {
|
||||
return $contoller_curr;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function SearchForm()
|
||||
{
|
||||
return Form::create(
|
||||
@ -98,7 +120,7 @@ class PageController extends ContentController
|
||||
$results->removeDuplicates();
|
||||
|
||||
return ArrayData::create([
|
||||
'Title' => 'Search query "'.$term.'"',
|
||||
'Title' => 'You searched for: "'.$term.'"',
|
||||
'Results' => PaginatedList::create($results),
|
||||
]);
|
||||
}
|
||||
@ -124,8 +146,10 @@ class PageController extends ContentController
|
||||
|
||||
public function getSiteWideMessage()
|
||||
{
|
||||
if (!$this->site_message) {
|
||||
$session = $this->getRequest()->getSession();
|
||||
$request = $this->getRequest();
|
||||
|
||||
if ($request->isGET() && !$this->site_message) {
|
||||
$session = $request->getSession();
|
||||
$this->site_message = $session->get('SiteWideMessage');
|
||||
$session->clear('SiteWideMessage');
|
||||
}
|
||||
|
@ -36,6 +36,7 @@ class DeferedRequirements implements TemplateGlobalProvider
|
||||
public static function Auto($class = false)
|
||||
{
|
||||
$config = Config::inst()->get(self::class);
|
||||
$themeName = WebpackTemplateProvider::themeName();
|
||||
|
||||
// Initialization
|
||||
Requirements::block(THIRDPARTY_DIR.'/jquery/jquery.js');
|
||||
@ -50,10 +51,10 @@ class DeferedRequirements implements TemplateGlobalProvider
|
||||
}
|
||||
// App libs
|
||||
if (!$config['nofontawesome']) {
|
||||
DeferedRequirements::loadCSS('//use.fontawesome.com/releases/v5.3.1/css/all.css');
|
||||
DeferedRequirements::loadCSS('//use.fontawesome.com/releases/v5.4.0/css/all.css');
|
||||
}
|
||||
DeferedRequirements::loadCSS('app.css');
|
||||
DeferedRequirements::loadJS('app.js');
|
||||
DeferedRequirements::loadCSS($themeName.'.css');
|
||||
DeferedRequirements::loadJS($themeName.'.js');
|
||||
|
||||
// Class libs
|
||||
$class = get_class(Controller::curr());
|
||||
@ -72,17 +73,17 @@ class DeferedRequirements implements TemplateGlobalProvider
|
||||
$dir = Path::join(
|
||||
Director::publicFolder(),
|
||||
ManifestFileFinder::RESOURCES_DIR,
|
||||
'app',
|
||||
$themeName,
|
||||
'client',
|
||||
'dist'
|
||||
);
|
||||
|
||||
if (file_exists(Path::join($dir, 'css', $class . '.css'))) {
|
||||
DeferedRequirements::loadCSS($class . '.css');
|
||||
if (file_exists(Path::join($dir, 'css', $themeName.'_'.$class . '.css'))) {
|
||||
DeferedRequirements::loadCSS($themeName.'_'.$class . '.css');
|
||||
}
|
||||
|
||||
if (file_exists(Path::join($dir, 'js', $class . '.js'))) {
|
||||
DeferedRequirements::loadJS($class . '.js');
|
||||
if (file_exists(Path::join($dir, 'js', $themeName.'_'.$class . '.js'))) {
|
||||
DeferedRequirements::loadJS($themeName.'_'.$class . '.js');
|
||||
}
|
||||
|
||||
return self::forTemplate();
|
||||
@ -90,7 +91,8 @@ class DeferedRequirements implements TemplateGlobalProvider
|
||||
|
||||
public static function loadCSS($css)
|
||||
{
|
||||
if (self::$defered && !self::_webpackActive()) {
|
||||
$external = (mb_substr($css, 0, 2) === '//' || mb_substr($css, 0, 4) === 'http');
|
||||
if ($external || (self::$defered && !self::_webpackActive())) {
|
||||
self::$css[] = $css;
|
||||
} else {
|
||||
WebpackTemplateProvider::loadCSS($css);
|
||||
@ -99,6 +101,9 @@ class DeferedRequirements implements TemplateGlobalProvider
|
||||
|
||||
public static function loadJS($js)
|
||||
{
|
||||
/*$external = (mb_substr($js, 0, 2) === '//' || mb_substr($js, 0, 4) === 'http');
|
||||
if ($external || (self::$defered && !self::_webpackActive())) {*/
|
||||
// webpack supposed to load external JS
|
||||
if (self::$defered && !self::_webpackActive()) {
|
||||
self::$js[] = $js;
|
||||
} else {
|
||||
@ -118,10 +123,6 @@ class DeferedRequirements implements TemplateGlobalProvider
|
||||
|
||||
public static function forTemplate()
|
||||
{
|
||||
if (!self::$defered || self::_webpackActive()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$result = '';
|
||||
foreach (self::$css as $css) {
|
||||
$result .= '<i class="defer-cs" data-load="' . self::get_url($css) . '"></i>';
|
||||
@ -137,7 +138,7 @@ class DeferedRequirements implements TemplateGlobalProvider
|
||||
.'function lscd(a){a<s.length-1&&(a++,lsc(s.item(a).getAttribute("data-load"),function(){lscd(a)}))}'
|
||||
.'for(var s=document.getElementsByClassName("defer-cs"),i=0;i<s.length;i++){var b=document.createElement("link");b.rel="stylesheet",'
|
||||
.'b.type="text/css",b.href=s.item(i).getAttribute("data-load"),b.media="all";var c=document.getElementsByTagName("body")[0];'
|
||||
.'c.appendChild(b)}var s=document.getElementsByClassName("defer-sc"),i=0;lsc(s.item(i).getAttribute("data-load"),function(){lscd(i)});'
|
||||
.'c.appendChild(b)}var s=document.getElementsByClassName("defer-sc"),i=0;if(s.item(i)!==null)lsc(s.item(i).getAttribute("data-load"),function(){lscd(i)});'
|
||||
.'</script>';
|
||||
|
||||
return $result;
|
||||
|
@ -2,10 +2,11 @@
|
||||
|
||||
/**
|
||||
* Directs assets requests to Webpack server or to static files
|
||||
*/
|
||||
*/
|
||||
|
||||
namespace Site\Templates;
|
||||
|
||||
use SilverStripe\Core\Manifest\ModuleManifest;
|
||||
use SilverStripe\View\TemplateGlobalProvider;
|
||||
use SilverStripe\View\Requirements;
|
||||
use SilverStripe\Control\Director;
|
||||
@ -27,7 +28,7 @@ class WebpackTemplateProvider implements TemplateGlobalProvider
|
||||
/**
|
||||
* @var string assets static files directory
|
||||
*/
|
||||
private static $dist = 'app/client/dist';
|
||||
private static $dist = 'client/dist';
|
||||
|
||||
/**
|
||||
* @return array
|
||||
@ -38,7 +39,8 @@ class WebpackTemplateProvider implements TemplateGlobalProvider
|
||||
'WebpackDevServer' => 'isActive',
|
||||
'WebpackCSS' => 'loadCSS',
|
||||
'WebpackJS' => 'loadJS',
|
||||
'ResoursesURL' => 'resoursesURL',
|
||||
'ResourcesURL' => 'resourcesURL',
|
||||
'ProjectName' => 'themeName',
|
||||
];
|
||||
}
|
||||
|
||||
@ -48,6 +50,10 @@ class WebpackTemplateProvider implements TemplateGlobalProvider
|
||||
*/
|
||||
public static function loadCSS($path)
|
||||
{
|
||||
if (self::isActive()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Requirements::css(self::_getPath($path));
|
||||
}
|
||||
|
||||
@ -60,9 +66,14 @@ class WebpackTemplateProvider implements TemplateGlobalProvider
|
||||
Requirements::javascript(self::_getPath($path));
|
||||
}
|
||||
|
||||
public static function resoursesURL($link = null)
|
||||
public static function themeName()
|
||||
{
|
||||
return Controller::join_links(Director::baseURL(), '/resources/app/client/dist/img/', $link);
|
||||
return Config::inst()->get(ModuleManifest::class, 'project');
|
||||
}
|
||||
|
||||
public static function resourcesURL($link = null)
|
||||
{
|
||||
return Controller::join_links(Director::baseURL(), '/resources/'.self::themeName().'/client/dist/img/', $link);
|
||||
}
|
||||
|
||||
|
||||
@ -100,6 +111,7 @@ class WebpackTemplateProvider implements TemplateGlobalProvider
|
||||
{
|
||||
return strpos($path, '//') === false ?
|
||||
Controller::join_links(
|
||||
self::themeName(),
|
||||
Config::inst()->get(__CLASS__, 'DIST'),
|
||||
(strpos($path, '.css') ? 'css' : 'js'),
|
||||
$path
|
||||
|
89
app/src/Tests/TestServer.php
Normal file
89
app/src/Tests/TestServer.php
Normal file
@ -0,0 +1,89 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: tony
|
||||
* Date: 10/31/18
|
||||
* Time: 5:31 AM
|
||||
*/
|
||||
|
||||
namespace Site\Tests;
|
||||
|
||||
use SilverStripe\Assets\Upload_Validator;
|
||||
use SilverStripe\Core\Cache\FilesystemCacheFactory;
|
||||
use SilverStripe\Core\Config\Config;
|
||||
use SilverStripe\Core\Convert;
|
||||
use SilverStripe\Dev\BuildTask;
|
||||
use SilverStripe\Assets\File;
|
||||
|
||||
class TestServer extends BuildTask
|
||||
{
|
||||
protected $title = 'Test server';
|
||||
protected $description = 'Test server';
|
||||
|
||||
public function run($request)
|
||||
{
|
||||
echo '<style>table{width:100%}table td,table th{border:1px solid #dedede}</style>';
|
||||
|
||||
echo '<h2>Testing Uploads</h2>';
|
||||
$maxUpload = ini_get('upload_max_filesize');
|
||||
$maxPost = ini_get('post_max_size');
|
||||
|
||||
echo self::success('PHP max upload size: '.$maxUpload);
|
||||
echo self::success('PHP max post size: '.$maxPost);
|
||||
echo self::success('So calculated max upload size: '.self::formatBytes(min(
|
||||
Convert::memstring2bytes($maxUpload),
|
||||
Convert::memstring2bytes($maxPost)
|
||||
)));
|
||||
|
||||
$defaultSizes = Config::inst()->get(Upload_Validator::class, 'default_max_file_size');
|
||||
if($defaultSizes) {
|
||||
if(!is_array($defaultSizes)){
|
||||
echo self::error('default_max_file_size miss-configuration, plz fix');
|
||||
var_dump($defaultSizes);
|
||||
die();
|
||||
}
|
||||
|
||||
echo '<h3>Configured limits:</h3><table style="text-align:center">'
|
||||
.'<thead><tr><th>File</th><th>Size limit</th></tr></thead><tbody>';
|
||||
foreach ($defaultSizes as $k => $size) {
|
||||
echo '<tr><td>'.$k.'</td><td>'.$size.'</td></tr>';
|
||||
}
|
||||
echo '</tbody></table>';
|
||||
}
|
||||
die();
|
||||
}
|
||||
|
||||
|
||||
public static function formatBytes($size, $precision = 2)
|
||||
{
|
||||
$base = log($size, 1024);
|
||||
$suffixes = array('', 'K', 'M', 'G', 'T');
|
||||
|
||||
return round(pow(1024, $base - floor($base)), $precision) . $suffixes[(string)floor($base)];
|
||||
}
|
||||
|
||||
public static function error($text)
|
||||
{
|
||||
return '<span style="color:red">ERROR: '.$text.'</span><br/>';
|
||||
}
|
||||
|
||||
public static function success($text)
|
||||
{
|
||||
return '<span style="color:green">SUCCESS: '.$text.'</span><br/>';
|
||||
}
|
||||
|
||||
public static function warning($text)
|
||||
{
|
||||
return '<span style="color:#0014ff">WARNING: '.$text.'</span><br/>';
|
||||
}
|
||||
|
||||
public static function renderValidation($result)
|
||||
{
|
||||
echo '<p>';
|
||||
$msgs = $result->getMessages();
|
||||
foreach ($msgs as $msg) {
|
||||
echo self::error($msg['fieldName'].': '.$msg['message']);
|
||||
}
|
||||
echo '</p>';
|
||||
}
|
||||
}
|
@ -2,7 +2,11 @@
|
||||
<h1 class="page-header container<% if $ElementalArea.Elements.Count < 1 %> no-elements<% end_if %>">$Title</h1>
|
||||
|
||||
<div class="page-content">
|
||||
$ElementalArea
|
||||
<% if $CurrentElement %>
|
||||
$CurrentElement
|
||||
<% else %>
|
||||
$ElementalArea
|
||||
<% end_if %>
|
||||
|
||||
<% if $Form %>
|
||||
<div class="container">
|
||||
|
@ -27,7 +27,10 @@
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<% if $PrivacyPolicy %>
|
||||
<a href="$PrivacyPolicy.Link" target="_blank">$PrivacyPolicy.Title</a>
|
||||
<a href="$PrivacyPolicy.Link">$PrivacyPolicy.Title</a>
|
||||
<% end_if %>
|
||||
<% if $Sitemap %>
|
||||
<a href="$Sitemap.Link">$Sitemap.Title</a>
|
||||
<% end_if %>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,6 +1,6 @@
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
<a id="Logo" href="/"><img src="{$StaticPath('img/logo.png')}" alt="{$SiteConfig.Title}" /></a>
|
||||
<a id="Logo" href="/"><img src="{$ResoursesURL('logo.png')}" alt="{$SiteConfig.Title}" /></a>
|
||||
</div>
|
||||
<div class="col-sm-6 text-right">
|
||||
<% with $SiteConfig %>
|
||||
|
1
app/templates/Includes/SideBar.ss
Normal file
1
app/templates/Includes/SideBar.ss
Normal file
@ -0,0 +1 @@
|
||||
<div></div>
|
@ -0,0 +1,11 @@
|
||||
<div id="uff">
|
||||
<div class="on-complete-message user-form">
|
||||
$OnCompleteMessage
|
||||
</div>
|
||||
|
||||
<% if $CustomThankYouCode %>
|
||||
<div class="custom-code user-form">
|
||||
$CustomThankYouCode.RAW
|
||||
</div>
|
||||
<% end_if %>
|
||||
</div>
|
@ -4,7 +4,7 @@
|
||||
"description": "The SilverStripe Framework Installer",
|
||||
"require": {
|
||||
"php": ">=7.1.0",
|
||||
"silverstripe/recipe-cms": "1.2.x-dev",
|
||||
"silverstripe/recipe-cms": "^4",
|
||||
"wilr/silverstripe-googlesitemaps": "*",
|
||||
"silverstripe/userforms": "*",
|
||||
"undefinedoffset/sortablegridfield": "*",
|
||||
@ -13,37 +13,34 @@
|
||||
"jonom/silverstripe-betternavigator": "*",
|
||||
"silverstripe/externallinks": "*",
|
||||
"symbiote/silverstripe-gridfieldextensions": "*",
|
||||
"colymba/gridfield-bulk-editing-tools": "3.0.0-beta4",
|
||||
"colymba/gridfield-bulk-editing-tools": "^3",
|
||||
"dnadesign/silverstripe-elemental-list": "*",
|
||||
"dnadesign/silverstripe-elemental-virtual": "*",
|
||||
"dnadesign/silverstripe-elemental-userforms": "*",
|
||||
"dynamic/silverstripe-elemental-blocks": "*",
|
||||
"drmartingonzo/ss-tinymce-charcount": "^1.0",
|
||||
"drmartingonzo/ss-tinymce-charcount": "*",
|
||||
"axllent/silverstripe-version-truncator": "*",
|
||||
"firesphere/googlemapsfield": "^1.0@dev",
|
||||
"gorriecoe/silverstripe-dataobjecthistory": "^1.2",
|
||||
"mak001/silverstripe-categorization": "^1.0@dev",
|
||||
"axllent/silverstripe-bootstrap-forms": "^2.0",
|
||||
"silverstripe/redirectedurls": "dev-master",
|
||||
"firesphere/googlemapsfield": "*",
|
||||
"gorriecoe/silverstripe-dataobjecthistory": "*",
|
||||
"axllent/silverstripe-bootstrap-forms": "*",
|
||||
"silverstripe/redirectedurls": "*",
|
||||
"undefinedoffset/silverstripe-nocaptcha": "*",
|
||||
"a2nt/silverstripe-font-awesome-field": "dev-master",
|
||||
"stevie-mayhew/silverstripe-svg": "^2.1",
|
||||
"betterbrief/silverstripe-googlemapfield": "^2.1",
|
||||
"innoweb/silverstripe-sitemap": "^2.0",
|
||||
"silverstripe/multiuser-editing-alert": "^2.0",
|
||||
"gorriecoe/silverstripe-link": "^1.2",
|
||||
"gorriecoe/silverstripe-linkfield": "dev-master"
|
||||
"stevie-mayhew/silverstripe-svg": "*",
|
||||
"betterbrief/silverstripe-googlemapfield": "*",
|
||||
"innoweb/silverstripe-sitemap": "*",
|
||||
"silverstripe/multiuser-editing-alert": "*",
|
||||
"gorriecoe/silverstripe-link": "*",
|
||||
"gorriecoe/silverstripe-linkfield": "*"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^5.7",
|
||||
"lekoala/silverstripe-debugbar": "dev-master"
|
||||
},
|
||||
"repositories": [
|
||||
{
|
||||
"type": "vcs",
|
||||
"url": "https://github.com/a2nt/silverstripe-font-awesome"
|
||||
}
|
||||
],
|
||||
"repositories": [{
|
||||
"type": "vcs",
|
||||
"url": "https://github.com/a2nt/silverstripe-font-awesome"
|
||||
}],
|
||||
"extra": {
|
||||
"expose": [
|
||||
"app/client/dist"
|
||||
|
@ -29,6 +29,8 @@
|
||||
"bootstrap-offcanvas": "^1.0.0",
|
||||
"bootstrap-select": "^1.13.2",
|
||||
"bootstrap-timepicker": "^0.5.2",
|
||||
"bootstrap-confirmation2": "^4.0.4",
|
||||
"bootstrap-table": "^1.14.2",
|
||||
"core-util-is": "^1.0.2",
|
||||
"font-awesome": "^4.7.0",
|
||||
"foundation-emails": "^2.2.1",
|
||||
|
0
themes/sample/client/src/js/_layout.js
Normal file
0
themes/sample/client/src/js/_layout.js
Normal file
4
themes/sample/client/src/js/app.js
Normal file
4
themes/sample/client/src/js/app.js
Normal file
@ -0,0 +1,4 @@
|
||||
import '../scss/app.scss';
|
||||
|
||||
import 'js/app';
|
||||
import './_layout';
|
0
themes/sample/client/src/scss/_layout.scss
Normal file
0
themes/sample/client/src/scss/_layout.scss
Normal file
2
themes/sample/client/src/scss/app.scss
Normal file
2
themes/sample/client/src/scss/app.scss
Normal file
@ -0,0 +1,2 @@
|
||||
@import "~scss/app.scss";
|
||||
@import "_layout";
|
51
themes/sample/templates/Page.ss
Normal file
51
themes/sample/templates/Page.ss
Normal file
@ -0,0 +1,51 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="$ContentLocale.ATT" dir="$i18nScriptDirection.ATT">
|
||||
<%-- manifest="/cache.appcache" --%>
|
||||
<head>
|
||||
<% include MetaHead %>
|
||||
</head>
|
||||
|
||||
<body oncontextmenu="return false;"<% with $SiteConfig %> data-default-lng="$Longitude" data-default-lat="$Latitude"<% end_with %>>
|
||||
<%-- Upgrade your Browser notice --%>
|
||||
<!--[if lt IE 10]><div class="main-bn"><a href="https://www.google.com/chrome/browser/desktop/" title="<%t Page.UPGRADEBROWSER 'Upgrade your browser' %>"><%t Page.OUTDATEDBROWSER 'You are using an outdated browser. For a faster, safer browsing experience, upgrade for free today.' %></a></div><![endif]-->
|
||||
|
||||
<%-- No JS enabled notice --%>
|
||||
<noscript><div class="main-bn"><%t Page.JAVASCRIPTREQUIRED 'Please, enable javascript.' %></div></noscript>
|
||||
|
||||
<%-- Loading Spinner --%>
|
||||
<div id="PageLoading"><div class="loading-spinner"><div class="bubblingG"><i id="bubblingG_1"></i><i id="bubblingG_2"></i><i id="bubblingG_3"></i></div><br/><%t Page.LOADINGTEXT 'LOADING ..' %></div></div>
|
||||
|
||||
<%-- Site Wide Alert Message --%>
|
||||
<% include SiteWideMessage %>
|
||||
|
||||
<div class="wrapper">
|
||||
<header id="Header" class="container">
|
||||
<% include Header %>
|
||||
</header>
|
||||
|
||||
<main id="MainContent" data-ajax-region="LayoutAjax">
|
||||
$Layout
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<footer id="Footer" class="site-footer">
|
||||
<% include Footer %>
|
||||
</footer>
|
||||
|
||||
<div class="hidden-print">
|
||||
$BetterNavigator
|
||||
</div>
|
||||
|
||||
<%-- Require CSS+JS from /public/resourses/[js,css]/[ClassName].[js,css] --%>
|
||||
$AutoRequirements($ClassName).RAW
|
||||
|
||||
<%-- Mapbox --%>
|
||||
<script src="https://api.tiles.mapbox.com/mapbox-gl-js/v0.48.0/mapbox-gl.js"></script>
|
||||
<link href="https://api.tiles.mapbox.com/mapbox-gl-js/v0.48.0/mapbox-gl.css" rel="stylesheet" />
|
||||
|
||||
<%-- place extra requirements after this line --%>
|
||||
<div class="extra-code extra-code-site">
|
||||
$SiteConfig.ExtraCode
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -6,46 +6,79 @@ const webpack = require('webpack');
|
||||
const conf = require('./webpack.configuration');
|
||||
|
||||
const path = require('path');
|
||||
const filesystem = require('fs');
|
||||
|
||||
const includes = {
|
||||
app: path.join(__dirname, conf.SRC, 'js/app.js'),
|
||||
const includes = {};
|
||||
|
||||
const _addAppFiles = (theme) => {
|
||||
|
||||
const dirPath = path.resolve(__dirname, theme);
|
||||
const themeName = path.basename(theme);
|
||||
|
||||
if (filesystem.existsSync(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'))) {
|
||||
includes[`${themeName}`] = path.join(dirPath, conf.SRC, 'scss', 'app.scss');
|
||||
}
|
||||
|
||||
const _getAllFilesFromFolder = function(dir, includeSubFolders = true) {
|
||||
const dirPath = path.resolve(__dirname, dir);
|
||||
let results = [];
|
||||
|
||||
filesystem.readdirSync(dirPath).forEach((file) => {
|
||||
if (file.charAt(0) === '_') {
|
||||
return;
|
||||
}
|
||||
|
||||
const filePath = `${dirPath}/${file}`;
|
||||
const stat = filesystem.statSync(filePath);
|
||||
|
||||
if (stat && stat.isDirectory() && includeSubFolders) {
|
||||
results = results.concat(_getAllFilesFromFolder(filePath, includeSubFolders));
|
||||
} else {
|
||||
results.push(filePath);
|
||||
}
|
||||
});
|
||||
|
||||
return results;
|
||||
};
|
||||
|
||||
// add page specific scripts
|
||||
const typesJSPath = path.join(theme, conf.TYPESJS);
|
||||
if (filesystem.existsSync(typesJSPath)) {
|
||||
const pageScripts = _getAllFilesFromFolder(typesJSPath, true);
|
||||
pageScripts.forEach((file) => {
|
||||
includes[`${themeName}_${path.basename(file, '.js')}`] = file;
|
||||
});
|
||||
}
|
||||
|
||||
// add page specific scss
|
||||
const typesSCSSPath = path.join(theme, conf.TYPESSCSS);
|
||||
if (filesystem.existsSync(typesSCSSPath)) {
|
||||
const scssIncludes = _getAllFilesFromFolder(typesSCSSPath, true);
|
||||
scssIncludes.forEach((file) => {
|
||||
includes[`${themeName}_${path.basename(file, '.scss')}`] = file;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const _getAllFilesFromFolder = function(dir) {
|
||||
dir = path.resolve(__dirname, dir);
|
||||
_addAppFiles(conf.APPDIR);
|
||||
|
||||
const filesystem = require('fs');
|
||||
let results = [];
|
||||
// add themes
|
||||
if (conf.THEMESDIR) {
|
||||
const dir = path.resolve(__dirname, conf.THEMESDIR);
|
||||
|
||||
filesystem.readdirSync(dir).forEach((file) => {
|
||||
if (file === '_notes') {
|
||||
return;
|
||||
}
|
||||
if (filesystem.existsSync(dir)) {
|
||||
filesystem.readdirSync(dir).forEach((file) => {
|
||||
filePath = `${dir}/${file}`;
|
||||
const stat = filesystem.statSync(filePath);
|
||||
|
||||
file = `${dir}/${file}`;
|
||||
const stat = filesystem.statSync(file);
|
||||
|
||||
if (stat && stat.isDirectory()) {
|
||||
results = results.concat(_getAllFilesFromFolder(file));
|
||||
} else {
|
||||
results.push(file);
|
||||
}
|
||||
});
|
||||
|
||||
return results;
|
||||
};
|
||||
|
||||
// add page specific scripts
|
||||
const pageScripts = _getAllFilesFromFolder(conf.TYPESJS);
|
||||
pageScripts.forEach((file) => {
|
||||
includes[path.basename(file, '.js')] = file;
|
||||
});
|
||||
|
||||
// add page specific scss
|
||||
const scssIncludes = _getAllFilesFromFolder(conf.TYPESSCSS);
|
||||
scssIncludes.forEach((file) => {
|
||||
includes[path.basename(file, '.scss')] = file;
|
||||
});
|
||||
if (stat && stat.isDirectory()) {
|
||||
_addAppFiles(path.join(conf.THEMESDIR, file));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
entry: includes,
|
||||
@ -79,14 +112,6 @@ module.exports = {
|
||||
}, {
|
||||
test: /\.coffee?$/,
|
||||
use: 'coffee-loader',
|
||||
}, {
|
||||
test: /\.(png|jpg|jpeg|gif|svg)$/,
|
||||
loader: 'file-loader',
|
||||
options: {
|
||||
name: '[name].[ext]',
|
||||
outputPath: 'img/',
|
||||
publicPath: '../img/',
|
||||
},
|
||||
}, {
|
||||
test: /\.worker\.js$/,
|
||||
use: {
|
||||
@ -97,7 +122,12 @@ module.exports = {
|
||||
resolve: {
|
||||
modules: [
|
||||
path.resolve(__dirname, 'public'),
|
||||
'node_modules'
|
||||
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')
|
||||
],
|
||||
alias: {
|
||||
'jquery': require.resolve('jquery'),
|
||||
|
@ -25,7 +25,7 @@ const config = merge.strategy({
|
||||
},
|
||||
|
||||
output: {
|
||||
path: path.join(__dirname, conf.DIST),
|
||||
path: path.join(__dirname),
|
||||
filename: '[name].js',
|
||||
// necessary for HMR to know where to load the hot update chunks
|
||||
publicPath: 'https://' + conf.HOSTNAME + ':' + conf.PORT + '/'
|
||||
@ -80,7 +80,12 @@ const config = merge.strategy({
|
||||
}, {
|
||||
test: /\.(gif|png|jpg|jpeg|ttf|otf|eot|svg|woff(2)?)$/,
|
||||
use: [{
|
||||
loader: 'url-loader'
|
||||
loader: 'file-loader',
|
||||
options: {
|
||||
name(file) {
|
||||
return 'public/[path][name].[ext]';
|
||||
},
|
||||
},
|
||||
}]
|
||||
}]
|
||||
},
|
||||
@ -98,7 +103,9 @@ const config = merge.strategy({
|
||||
clientLogLevel: 'info',
|
||||
contentBase: [
|
||||
path.resolve(__dirname, 'public'),
|
||||
'node_modules'
|
||||
path.resolve(__dirname, 'public', 'resources'),
|
||||
path.resolve(__dirname, 'public', 'resources', conf.APPDIR, conf.DIST),
|
||||
'node_modules',
|
||||
],
|
||||
//watchContentBase: true,
|
||||
overlay: {
|
||||
@ -106,7 +113,7 @@ const config = merge.strategy({
|
||||
errors: true
|
||||
},
|
||||
headers: {
|
||||
'Access-Control-Allow-Origin': '*'
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
}
|
||||
},
|
||||
});
|
||||
|
@ -17,9 +17,9 @@ module.exports = merge(common, {
|
||||
devtool: '',
|
||||
|
||||
output: {
|
||||
path: path.join(__dirname, conf.DIST),
|
||||
filename: 'js/[name].js',
|
||||
publicPath: conf.DIST + '/',
|
||||
path: path.join(__dirname, conf.APPDIR, conf.DIST),
|
||||
filename: path.join('js', '[name].js'),
|
||||
publicPath: path.join(conf.APPDIR, conf.DIST),
|
||||
},
|
||||
|
||||
module: {
|
||||
@ -82,7 +82,20 @@ module.exports = merge(common, {
|
||||
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: [
|
||||
@ -106,9 +119,9 @@ module.exports = merge(common, {
|
||||
}),
|
||||
|
||||
new FaviconsWebpackPlugin({
|
||||
logo: path.join(__dirname, conf.SRC) + '/favicon.png',
|
||||
logo: path.join(__dirname, conf.APPDIR, conf.SRC, 'favicon.png'),
|
||||
prefix: '/icons/',
|
||||
statsFilename: conf.DIST + '/icons/iconstats.json',
|
||||
statsFilename: path.join(conf.APPDIR, conf.DIST, 'icons', 'iconstats.json'),
|
||||
icons: {
|
||||
android: true,
|
||||
appleIcon: true,
|
||||
|
Loading…
Reference in New Issue
Block a user