Bunch of structural upgrades and module integrations

This commit is contained in:
Tony Air 2018-07-02 08:54:18 +07:00
parent 80d396e3ca
commit ce7490bc90
59 changed files with 4432 additions and 1181 deletions

View File

@ -12,7 +12,10 @@ HtmlEditorConfig::get('cms')->enablePlugins([
'charmap',
'visualblocks',
'lists',
'charcount' => ModuleResourceLoader::resourceURL('drmartingonzo/ss-tinymce-charcount:client/dist/js/bundle.js'),
'charcount' => ModuleResourceLoader::resourceURL(
'drmartingonzo/ss-tinymce-charcount:client/dist/js/bundle.js'
),
]);
FulltextSearchable::enable();

13
app/_config/captcha.yml Normal file
View File

@ -0,0 +1,13 @@
SilverStripe\SpamProtection\Extension\FormSpamProtectionExtension:
default_spam_protector: UndefinedOffset\NoCaptcha\Forms\NocaptchaProtector
UndefinedOffset\NoCaptcha\Forms\NocaptchaField:
site_key: "YOUR_SITE_KEY" #Your site key (required)
secret_key: "YOUR_SECRET_KEY" #Your secret key (required)
verify_ssl: true #Allows you to disable php-curl's SSL peer verification by setting this to false (optional, defaults to true)
default_theme: "light" #Default theme color (optional, light or dark, defaults to light)
default_type: "image" #Default captcha type (optional, image or audio, defaults to image)
default_size: "normal" #Default size (optional, normal, compact or invisible, defaults to normal)
default_badge: "bottomright" #Default badge position (bottomright, bottomleft or inline, defaults to bottomright)
proxy_server: "" #Your proxy server address (optional)
proxy_auth: "" #Your proxy server authentication information (optional)

View File

@ -1,3 +1,10 @@
---
Name: webapp-elemental
After:
- elemental
- elemental-list
---
Page:
extensions:
- DNADesign\Elemental\Extensions\ElementalPageExtension
@ -5,7 +12,42 @@ Page:
DNADesign\Elemental\Models\BaseElement:
default_global_elements: true
extensions:
- Site\Extensions\ElementRows
- Site\Extensions\ElementRows
SilverStripe\CMS\Model\SiteTree:
allowed_elements:
- DNADesign\ElementalList\Model\ElementList
- DNADesign\Elemental\Models\ElementContent
- DNADesign\ElementalUserForms\Model\ElementForm
- Dynamic\Elements\Image\Elements\ElementImage
- Dynamic\Elements\Blog\Elements\ElementBlogPosts
- Dynamic\Elements\FlexSlider\Elements\ElementSlideshow
- Dynamic\Elements\Oembed\Elements\ElementOembed
- Dynamic\Elements\Elements\ElementTestimonials
- Site\Elements\TeamMembersElement
DNADesign\ElementalList\Model\ElementList:
default_global_elements: false
default_global_elements: false
allowed_elements:
- DNADesign\ElementalList\Model\ElementList
- DNADesign\Elemental\Models\ElementContent
- DNADesign\ElementalUserForms\Model\ElementForm
- Dynamic\Elements\Image\Elements\ElementImage
- Dynamic\Elements\Blog\Elements\ElementBlogPosts
- Dynamic\Elements\FlexSlider\Elements\ElementSlideshow
- Dynamic\Elements\Oembed\Elements\ElementOembed
- Dynamic\Elements\Elements\ElementTestimonials
- Site\Elements\TeamMembersElement
styles:
whiteframe: 'White Frame'
greybg: 'Grey Background'
noframe: 'No Frame'
DNADesign\Elemental\Models\ElementContent:
extensions:
- Site\Extensions\ElementContentWidget
Dynamic\Elements\Image\Elements\ElementImage:
extensions:
- Site\Extensions\ElementImageWidget

View File

@ -1,4 +1,16 @@
SilverStripe\SiteConfig\SiteConfig:
extensions:
- Site\Extensions\SiteConfigExtension
- Site\Extensions\SocialExtension
SilverStripe\SiteTree\SiteTree:
extensions:
- SiteTreeExtension
SilverStripe\Blog\Model\BlogPost:
extensions:
- Site\Extensions\BlogPostExtension
SilverStripe\Core\Injector\Injector:
SilverStripe\UserForms\Model\UserDefinedForm:
class: Site\Extensions\CMSMain_HiddenClass

View File

@ -2,102 +2,115 @@ import $ from 'jquery';
import Events from "../_events";
const FormStorage = (($) => {
// Constants
const NAME = 'jsFormStorage';
const DATA_KEY = NAME;
const STORAGE = window.localStorage;
// Constants
const NAME = 'jsFormStorage';
const DATA_KEY = NAME;
const STORAGE = window.localStorage;
class FormStorage {
// Constructor
constructor(element) {
this._element = element;
const $element = $(this._element);
const $elements = $element.find('input,textarea');
class FormStorage {
// Constructor
constructor(element) {
this._element = element;
const $element = $(this._element);
const $elements = $element.find('input,textarea');
const setRangeValues = function(el) {
let $el = $(el);
$el.siblings('.value').text($el.val());
};
$element.addClass(`${NAME}-active`);
$element.addClass(`${NAME}-active`);
// restore form data from localStorage
$elements.each(function () {
const id = $(this).attr('id');
const type = $(this).attr('type');
const val = STORAGE.getItem(NAME + id);
// restore form data from localStorage
$elements.each(function() {
const id = $(this).attr('id');
const type = $(this).attr('type');
const val = STORAGE.getItem(NAME + id);
if (id && val && type) {
if (type && (type === 'checkbox' || type === 'radio')) {
$(this).prop('checked', val);
} else {
$(this).val(val);
}
}
});
if (id && val && type) {
if (type && (type === 'checkbox' || type === 'radio')) {
$(this).prop('checked', val);
} else {
$(this).val(val);
}
}
});
// store form data into localStorage
$elements.change(function () {
const id = $(this).attr('id');
const type = $(this).attr('type');
let val = $(this).val();
// range fields
if (type && (type === 'checkbox' || type === 'radio')) {
val = !!$(this).is(':checked');
$('input[type="range"]').each(function() {
setRangeValues(this);
});
$('input[type="range"]').change(function() {
setRangeValues(this);
});
// store form data into localStorage
$elements.change(function() {
const id = $(this).attr('id');
const type = $(this).attr('type');
let val = $(this).val();
if (type && (type === 'checkbox' || type === 'radio')) {
val = !!$(this).is(':checked');
}
if (id && type && type !== 'password') {
STORAGE.setItem(NAME + id, val);
}
});
$element.submit(() => {
$element.data(DATA_KEY).clear();
});
$element.find('button,[type="submit"],[type="clear"]').click(() => {
$element.data(DATA_KEY).clear();
});
}
if (id && type && type !== 'password') {
STORAGE.setItem(NAME + id, val);
// Public methods
dispose() {
const $element = $(this._element);
$element.removeClass(`${NAME}-active`);
$.removeData(this._element, DATA_KEY);
this._element = null;
}
});
$element.submit(() => {
$element.data(DATA_KEY).clear();
});
clear() {
STORAGE.clear();
}
$element.find('button,[type="submit"],[type="clear"]').click(() => {
$element.data(DATA_KEY).clear();
});
static _jQueryInterface() {
if (typeof window.localStorage !== 'undefined') {
return this.each(function() {
// attach functionality to element
const $element = $(this);
let data = $element.data(DATA_KEY);
if (!data) {
data = new FormStorage(this);
$element.data(DATA_KEY, data);
}
});
}
}
}
// Public methods
dispose() {
const $element = $(this._element);
// jQuery interface
$.fn[NAME] = FormStorage._jQueryInterface;
$.fn[NAME].Constructor = FormStorage;
$.fn[NAME].noConflict = function() {
$.fn[NAME] = JQUERY_NO_CONFLICT;
return FormStorage._jQueryInterface;
};
$element.removeClass(`${NAME}-active`);
$.removeData(this._element, DATA_KEY);
this._element = null;
}
// auto-apply
$(window).on(`${Events.AJAX} ${Events.LOADED}`, () => {
$('form').jsFormStorage();
});
clear() {
STORAGE.clear();
}
static _jQueryInterface() {
if (typeof window.localStorage !== 'undefined') {
return this.each(function () {
// attach functionality to element
const $element = $(this);
let data = $element.data(DATA_KEY);
if (!data) {
data = new FormStorage(this);
$element.data(DATA_KEY, data);
}
});
}
}
}
// jQuery interface
$.fn[NAME] = FormStorage._jQueryInterface;
$.fn[NAME].Constructor = FormStorage;
$.fn[NAME].noConflict = function () {
$.fn[NAME] = JQUERY_NO_CONFLICT;
return FormStorage._jQueryInterface;
};
// auto-apply
$(window).on(`${Events.AJAX} ${Events.LOADED}`, () => {
$('form').jsFormStorage();
});
return FormStorage;
return FormStorage;
})($);
export default FormStorage;

View File

@ -300,4 +300,4 @@ const MainUI = (($) => {
return MainUI;
})($);
export default MainUI;
export default MainUI;

View File

@ -1,10 +0,0 @@
// bootstrap minify bugfix:
$navbar-dark-toggler-icon-bg: none;
$navbar-light-toggler-icon-bg: none;
// IE > 9
$enable-flex: true;
@import "~bootstrap/scss/functions";
@import "~bootstrap/scss/variables";
@import "~bootstrap/scss/mixins";

View File

@ -1,14 +1,3 @@
/**
* Your custom style
*/
@import "_components/ui.carousel";
// hide default page title cuz elemental object will be used to display titles
h1 {
display: none;
}
img {
max-width: 100%;
}

View File

@ -1,5 +1,8 @@
@import "./_variables";
h1, h2, h3, h4, h5, h6,
.h1, .h2, .h3, .h4, .h5, .h6 {
color: $dark-blue;
}
.typography {
@import "./types/editor";
}
}

View File

@ -1,5 +1,35 @@
@import "_bootstrap_variables";
/*
* Your custom variables
*/
*/
$font-family-base: "Lato", sans-serif;
$grid-gutter-height: 8rem;
$gray-900: #212529;
$white: #fff;
$blue: #016cb1;
$yellow: #ecac02;
$dark-blue: #113362;
$body-color: $gray-900;
$navbar-light-active-color: $blue;
$dropdown-border-color: $white;
/*
* bootstrap includes
* keep it at the end
*/
// bootstrap minify bugfix:
$navbar-dark-toggler-icon-bg: none;
$navbar-light-toggler-icon-bg: none;
// IE > 9
$enable-flex: true;
@import "~bootstrap/scss/functions";
@import "~bootstrap/scss/variables";
@import "~bootstrap/scss/mixins";

View File

@ -1,6 +1,7 @@
// Bootstrap
@import "_bootstrap_variables";
// Your custom variables
@import "_variables";
// Bootstrap
@import "~bootstrap/scss/root";
@import "~bootstrap/scss/reboot";
@import "~bootstrap/scss/type";
@ -45,10 +46,87 @@ $lightbox-link-hover-color: $link-hover-color;
@import "~meta-lightbox/scss/meta-lightbox";
@import "~meta-lightbox/scss/meta-lightbox-theme";
@import "_components/ui.carousel";
// Your custom variables
@import "_variables";
/*
* some basic styles
*/
// hide default page title cuz elemental object will be used to display titles
h1 {
display: none;
}
// don't let images be wider than the parent layer
iframe,
img {
max-width: 100%;
}
a:hover,
a:focus {
opacity: .8;
}
// transactions
.transition,
a, a img,
button, input, optgroup, select, textarea,
.btn,
.alert,
.dropdown,
[data-target],
.container,
.container-fluid,
.row,
[class="col-*"] {
transition: all 0.4s ease;
}
// stick navbar to top using mobile layout
#Header {
position: relative;
padding-top: $grid-gutter-height / 2;
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%;
@media (min-width: map-get($grid-breakpoints, "lg")) {
position: relative;
margin-top: 1rem;
}
}
// add top/bottom paddings for basic elements
.page-content > .element {
position: relative;
padding: ($grid-gutter-height / 2) 0;
// remove paddings of the slideshow
&.dynamic__elements__image__elements__elementimage,
&.dynamic__elements__flexslider__elements__elementslideshow {
padding: 0;
}
}
// remove container paddings for the slideshow
.dynamic__elements__image__elements__elementimage,
.dynamic__elements__flexslider__elements__elementslideshow {
.container-fluid {
padding: 0;
}
}
// Your custom UI
@import "_typography";
@import "_layout";
@import "_layout";

View File

@ -1 +1 @@
@import "../_variables";
@import "../_variables";

11
app/composer.json Normal file
View File

@ -0,0 +1,11 @@
{
"autoload": {
"psr-4": {
"Site\\": "app/src/"
},
"classmap": [
"app/src/Pages/Page.php",
"app/src/Pages/PageController.php"
]
}
}

View File

@ -0,0 +1,30 @@
<?php
/**
* Created by PhpStorm.
* User: tony
* Date: 6/30/18
* Time: 11:54 PM
*/
namespace Site\Elements;
use DNADesign\Elemental\Models\BaseElement;
use Site\Models\TeamMember;
class TeamMembersElement extends BaseElement
{
private static $singular_name = 'Team Members';
private static $plural_name = 'Team Members';
private static $description = 'Displays random Team Members';
public function getType()
{
return self::$singular_name;
}
public function Members()
{
return TeamMember::get()->sort('RAND()');
}
}

View File

@ -0,0 +1,40 @@
<?php
/**
* Created by PhpStorm.
* User: tony
* Date: 7/2/18
* Time: 12:10 AM
*/
namespace Site\Extensions;
use DNADesign\Elemental\Models\BaseElement;
use DNADesign\Elemental\Models\ElementContent;
use SilverStripe\ORM\DataExtension;
class BlogPostExtension extends DataExtension
{
/*
* Shows custom summary of the post, otherwise
* Displays summary of the first content element
*/
public function Summary($wordsToDisplay = 30)
{
$summary = $this->owner->getField('Summary');
if($summary){
return $summary;
}
BaseElement::
$element = ElementContent::get()->filter([
'ParentID' => $this->owner->ElementalArea()->ID,
'HTML:not' => [null],
])->first();
if($element){
return $element->dbObject('HTML')->Summary($wordsToDisplay);
}
return false;
}
}

View File

@ -0,0 +1,41 @@
<?php
/**
* Created by PhpStorm.
* User: tony
* Date: 6/24/18
* Time: 2:35 PM
*/
namespace Site\Extensions;
use Sheadawson\Linkable\Forms\LinkField;
use Sheadawson\Linkable\Models\Link;
use SilverStripe\FontAwesome\FontAwesomeField;
use SilverStripe\Forms\FieldList;
use SilverStripe\ORM\DataExtension;
class ElementContentWidget extends DataExtension
{
private static $db = [
'BlockIcon' => 'Varchar(255)',
];
private static $has_one = [
'BlockLink' => Link::class,
];
public function updateCMSFields(FieldList $fields)
{
parent::updateCMSFields($fields);
$tab = $fields->findOrMakeTab('Root.Main');
$tab->push(
FontAwesomeField::create('BlockIcon')
);
$tab->push(
LinkField::create('BlockLinkID', 'Link')
);
}
}

View File

@ -0,0 +1,111 @@
<?php
/**
* Created by PhpStorm.
* User: tony
* Date: 6/24/18
* Time: 1:46 AM
*/
namespace Site\Extensions;
use Dynamic\Elements\Image\Elements\ElementImage;
use Sheadawson\Linkable\Forms\LinkField;
use Sheadawson\Linkable\Models\Link;
use SilverStripe\Core\Config\Config;
use SilverStripe\Forms\DropdownField;
use SilverStripe\Forms\FieldList;
use SilverStripe\ORM\DataExtension;
class ElementImageWidget extends DataExtension
{
private static $available_heights = [
'300' => 'Small (300px)',
'400' => 'Medium (400px)',
'600' => 'Big (600px)',
];
private static $db = [
'ImageHeight' => 'Float',
'Content' => 'HTMLText',
];
private static $has_one = [
'ImageLink' => Link::class,
];
public function updateCMSFields(FieldList $fields)
{
parent::updateCMSFields($fields);
$fields->insertBefore(
'Image',
LinkField::create('ImageLinkID', 'Link')
);
$this->owner->ImageHeight = $this->getHeight();
$heights = Config::inst()->get(__CLASS__, 'available_heights');
if (count($heights)) {
$fields->replaceField(
'ImageHeight',
DropdownField::create(
'ImageHeight',
'Image Height',
$heights,
$this->getHeight()
)->setEmptyString('(unspecified)')
);
} else {
$fields->dataFieldByName('ImageHeight')
->setValue($this->getHeight());
}
}
public function ImageResized()
{
$image = $this->owner->Image();
$width = $this->getWidth();
$height = $this->getHeight();
if (!$width) {
return $height > 0
? $image->ScaleHeight($height)
: $image;
}
return $height > 0
? $image->Fill($width, $height)
: $image->ScaleWidth($width);
}
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;
}
public function getHeight()
{
$height = $this->owner->getField('ImageHeight');
if ($height > 0) {
return $height;
}
$sibling = $this->owner->getSibling(false, [
'ImageHeight:GreaterThan' => '0'
]);
if ($sibling && $sibling->getField('ImageHeight')) {
return $sibling->getField('ImageHeight');
}
return 0;
}
}

View File

@ -8,64 +8,82 @@
namespace Site\Extensions;
use DNADesign\ElementalList\Model\ElementList;
use Dynamic\Elements\Image\Elements\ElementImage;
use SilverStripe\Forms\DropdownField;
use SilverStripe\ORM\DataExtension;
use SilverStripe\Forms\FieldList;
use SilverStripe\ORM\FieldType\DBEnum;
class ElementRows extends DataExtension
{
private static $container_max_width = 1140;
private static $column_class = 'col-md-';
private static $container_styles = [
'container' => 'Fixed container',
'container-fluid' => 'Fluid Container',
'container' => 'Fixed container',
'container-fluid' => 'Fluid Container',
];
private static $db = [
'Size' => 'Enum("1,2,3,4,5,6,7,8,9,10,11,12","6")',
'ContainerType' => 'Varchar(254)',
'Size' => 'Enum("1,2,3,4,5,6,7,8,9,10,11,12","6")',
];
public function updateCMSFields(FieldList $fields)
{
parent::updateCMSFields($fields);
$tab = $fields->findOrMakeTab('Root.Main');
if($this->isRoot() && $this->isList()) {
$styleDropdown = $fields->dataFieldByName('Style');
if ($styleDropdown) {
$styleDropdown->setSource(self::$container_styles);
} else {
$styleDropdown = DropdownField::create(
'Style',
_t(__CLASS__.'.STYLE', 'Style variation'),
self::$container_styles
);
$fields->insertBefore($styleDropdown, 'ExtraClass');
}
// container type
if ($this->isRoot()) {
$tab->push(DropdownField::create(
'ContainerType',
_t(__CLASS__.'.CONTAINERTYPE', 'Container Type'),
self::$container_styles
));
} else {
$fields->removeByName('ContainerType');
}
if($this->isColumn()) {
// column size
if ($this->isColumn()) {
$sizes = $this->owner->dbObject('Size');
$defaultSize = $sizes->getDefaultValue();
$sizeDropdown = DropdownField::create(
'Size',
'Column Size (12 cols grid, ex. for 3 equal cols: 12/3 = 4 is the size that you need)',
$sizes->enumValues()
_t(
__CLASS__.'.SIZE',
'Column Size'
),
array_combine(
array_values($sizes->enumValues()),
[
'8.3%',
'16.6%',
'25%',
'33%',
'41.6%',
'50%',
'58.3%',
'66.4%',
'74.7%',
'83%',
'91.3%',
'100%',
]
)
);
$tab->push($sizeDropdown);
// set default size
if(!$this->owner->getField('Size')){
$sibling = $this->owner->Parent()
->Elements()
->exclude('ID', $this->owner->ID)
->last();
if (!$this->owner->getField('Size')) {
$sibling = $this->getSibling();
$sizeDropdown->setValue($sibling ? $sibling->getField('Size') : $defaultSize);
}
}else{
} else {
$fields->removeByName('Size');
}
}
@ -77,7 +95,7 @@ class ElementRows extends DataExtension
public function isRow()
{
if(!$this->isList()){
if (!$this->isList()) {
return false;
}
@ -86,7 +104,7 @@ class ElementRows extends DataExtension
public function isColumn()
{
if(!$this->isRoot() && !$this->isRow()){
if (!$this->isRoot()) {
return true;
}
@ -96,35 +114,66 @@ class ElementRows extends DataExtension
public function isRoot()
{
$parent = $this->owner->Parent()->getOwnerPage();
if(is_a($parent, 'Page')){
if (is_a($parent, 'Page')) {
return true;
}
return false;
}
public function getSibling($any = true, $filter = [], $exclude = [])
{
$class = $any ? $this->owner->baseClass() : $this->owner->ClassName;
return $class::get()->filter(array_merge(
['ParentID' => $this->owner->Parent()->ID],
$filter
))->exclude(array_merge(
['ID' => $this->owner->ID],
$exclude
))->last();
}
public function getColumnSizeRecursive($object = null)
{
$object = $object ? $object : $this->owner;
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 $object->getColumnSizeRecursive($parent);
}
}
public function ExtraClass()
{
return $this->isColumn()
? self::$column_class.$this->owner->getField('Size')
: '';
return $this->owner->getField('ExtraClass')
.(
$this->isColumn()
? ' col '.self::$column_class.$this->owner->getField('Size')
: ''
);
}
/*
* if it's root element and it doesn't contain any container styles
* add the first one
*/
public function updateStyleVariant(&$style)
public function ContainerClass()
{
$style = $this->owner->getField('Style');
$type = $this->owner->getField('ContainerType');
$container_styles = array_keys(self::$container_styles);
if(
$this->isRoot()
&& $this->isList()
&& !in_array($style, $container_styles)
){
$style = $container_styles[0];
if (!$type && $this->isRoot()) {
$type = $container_styles[0];
}
return $type;
}
}
}

View File

@ -0,0 +1,17 @@
<?php
/**
* Created by PhpStorm.
* User: tony
* Date: 7/2/18
* Time: 1:05 AM
*/
namespace Site\Extensions;
use SilverStripe\ORM\HiddenClass;
use Page;
class CMSMain_HiddenClass extends Page implements HiddenClass
{
}

View File

@ -2,26 +2,23 @@
namespace Site\Extensions;
use SilverStripe\Forms\TextareaField;
use SilverStripe\ORM\DataExtension;
use SilverStripe\CMS\Model\SiteTree;
use SilverStripe\Forms\FieldList;
use SilverStripe\Forms\TreeMultiselectField;
use Sheadawson\Linkable\Models\Link;
use SilverStripe\Forms\TextField;
use Sheadawson\Linkable\Forms\LinkField;
class SiteConfigExtension extends DataExtension
{
private static $db = [
'Address' => 'Varchar(255)',
];
private static $has_one = [
'PhoneNumber' => Link::class
'ShortDescription' => 'Text',
'ExtraCode' => 'Text',
];
private static $many_many = [
'Navigation' => SiteTree::class
'Navigation' => SiteTree::class,
'Services' => SiteTree::class,
'QuickLinks' => SiteTree::class,
];
public function updateCMSFields(FieldList $fields)
@ -33,10 +30,20 @@ class SiteConfigExtension extends DataExtension
'Navigation',
SiteTree::class
));
$tab->push(
LinkField::create('PhoneNumberID', 'Phone Number')
->setAllowedTypes(['Phone'])
);
$tab->push(TextField::create('Address'));
$tab->push(TreeMultiselectField::create(
'Services',
'Services',
SiteTree::class
));
$tab->push(TreeMultiselectField::create(
'QuickLinks',
'QuickLinks',
SiteTree::class
));
$tab->push(TextareaField::create('ShortDescription'));
$tab->push(TextareaField::create('ExtraCode', 'Extra site-wide HTML code'));
}
}

View File

@ -0,0 +1,28 @@
<?php
namespace Site\Extensions;
use SilverStripe\ORM\DataExtension;
use SilverStripe\CMS\Model\SiteTree;
use SilverStripe\Forms\FieldList;
use SilverStripe\Forms\TreeMultiselectField;
use Sheadawson\Linkable\Models\Link;
use SilverStripe\Forms\TextField;
use Sheadawson\Linkable\Forms\LinkField;
class SiteTreeExtension extends DataExtension
{
private static $db = [
'ExtraCode' => 'Text',
];
public function updateCMSFields(FieldList $fields)
{
$tab = $fields->findOrMakeTab('Root.Settings');
$tab->push(Textarea::create(
'ExtraCode',
'Extra page specific HTML code'
));
}
}

View File

@ -0,0 +1,63 @@
<?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\Forms\FieldList;
use SilverStripe\Forms\TextField;
use SilverStripe\ORM\DataExtension;
use SilverStripe\UserForms\Model\UserDefinedForm;
class SocialExtension extends DataExtension
{
private static $db = [
'Address' => 'Varchar(255)',
];
private static $has_one = [
'Facebook' => Link::class,
'LinkedIn' => Link::class,
'GooglePlus' => Link::class,
'Instagram' => Link::class,
'Twitter' => Link::class,
'PublicEmail' => Link::class,
'PhoneNumber' => Link::class,
];
public function updateCMSFields(FieldList $fields)
{
parent::updateCMSFields($fields);
$linkFields = [
LinkField::create('FacebookID'),
LinkField::create('LinkedInID'),
LinkField::create('GooglePlusID'),
LinkField::create('InstagramID'),
LinkField::create('TwitterID'),
];
foreach ($linkFields as $field) {
$field->setAllowedTypes(['URL']);
}
$fields->findOrMakeTab('Root.Social');
UserDefinedForm::
$fields->addFieldsToTab('Root.Social', [
LinkField::create('PublicEmailID', 'Public Email')
->setAllowedTypes(['Email']),
LinkField::create('PhoneNumberID', 'Phone Number')
->setAllowedTypes(['Phone']),
TextField::create('Address'),
]);
$fields->addFieldsToTab('Root.Social', $linkFields);
}
}

View File

@ -0,0 +1,54 @@
<?php
/**
* Created by PhpStorm.
* User: tony
* Date: 6/30/18
* Time: 11:36 PM
*/
namespace Site\Models;
use SilverStripe\Assets\Image;
use SilverStripe\ORM\DataObject;
use SilverStripe\Versioned\Versioned;
use Site\Extensions\SocialExtension;
use Site\Pages\TeamPage;
class TeamMember extends DataObject
{
private static $table_name = 'TeamMember';
private static $db = [
'FirstName' => 'Varchar(254)',
'LastName' => 'Varchar(254)',
'Company' => 'Varchar(254)',
'Position' => 'Varchar(254)',
];
private static $has_one = [
'Photo' => Image::class,
'Page' => TeamPage::class,
];
private static $extensions = [
SocialExtension::class,
Versioned::class,
];
private static $owns = [
'Photo',
];
private static $summary_fields = [
'Company',
'FirstName',
'LastName',
'Position',
];
public function getTitle()
{
return $this->getField('Company').' | '.$this->getField('FirstName').' '.$this->getField('LastName');
}
}

View File

@ -1,6 +1,7 @@
<?php
namespace Site\Pages;
use Page;
class HomePage extends Page

View File

@ -1,6 +1,7 @@
<?php
namespace Site\Pages;
use PageController;
class HomePageController extends PageController

View File

@ -5,7 +5,12 @@
//namespace Site\Pages;
use SilverStripe\CMS\Controllers\ContentController;
use SilverStripe\ORM\FieldType\DBDatetime;
class PageController extends ContentController
{
public function CurrentTime()
{
return DBDatetime::now();
}
}

View File

@ -0,0 +1,42 @@
<?php
/**
* Created by PhpStorm.
* User: tony
* Date: 6/30/18
* Time: 11:46 PM
*/
namespace Site\Pages;
use SilverStripe\Forms\GridField\GridField;
use SilverStripe\Forms\GridField\GridFieldConfig_RecordEditor;
use Site\Models\TeamMember;
class TeamPage extends \Page
{
private static $has_many = [
'Members' => TeamMember::class,
];
private static $owns = [
'Members',
];
public function getCMSFields()
{
$fields = parent::getCMSFields();
$fields->addFieldToTab(
'Root.Members',
GridField::create(
'Members',
'',
$this->Members(),
GridFieldConfig_RecordEditor::create()
)
);
return $fields;
}
}

View File

@ -0,0 +1,15 @@
<?php
/**
* Created by PhpStorm.
* User: tony
* Date: 6/30/18
* Time: 11:49 PM
*/
namespace Site\Pages;
class TeamPageController extends \PageController
{
}

View File

@ -0,0 +1,5 @@
<div class="element $SimpleClassName.LowerCase<% if $StyleVariant %> $StyleVariant<% end_if %><% if $ExtraClass %> $ExtraClass<% end_if %>" id="$Anchor">
<div class="element-container<% if $ContainerClass %> $ContainerClass<% end_if %>">
$Element
</div>
</div>

View File

@ -0,0 +1,18 @@
<div class="content-element__content <% if $Style %>$CssStyle<% end_if %>">
<% if $BlockIcon %>
<i class="content-element__icon $BlockIcon"></i>
<% end_if %>
<% if $ShowTitle %>
<h2 class="content-element__title">$Title</h2>
<% end_if %>
<div class="typography">
$HTML
</div>
<% if $BlockLink %>
<a href="$BlockLink.URL" class="btn btn-default">
$BlockLink.Title
</a>
<% end_if %>
</div>

View File

@ -0,0 +1,10 @@
<div class="form-element__form $ExtraClass">
<div class="row">
<div class="col-md-6">
<% if $Title && $ShowTitle %>
<h2 class="form-element__title">$Title</h2>
<% end_if %>
$Form
</div>
</div>
</div>

View File

@ -0,0 +1,14 @@
<% if $Title && $ShowTitle %><h2 class="element__title text-center">$Title</h2><% end_if %>
<% if $Content %><div class="element__content">$Content</div><% end_if %>
<% if $PostsList %>
<div class="row">
<% loop $PostsList %>
<div class="col-sm-4">
<% include BlogPostInfo %>
</div>
<% end_loop %>
</div>
<%-- p><a href="$Blog.Link" class="btn btn-primary" title="Go to the $Title page">View all posts</a></p --%>
<% end_if %>

View File

@ -0,0 +1,14 @@
<% if $Title && $ShowTitle %><h2 class="element__title text-center">$Title</h2><% end_if %>
<% if $Content %><div class="element__content">$Content</div><% end_if %>
<% if $TestimonialsList %>
<div class="row">
<% loop $TestimonialsList %>
<% if $Content || $Name || $Affiliation %>
<div class="col-sm-6">
<% include Objects\Testimonial %>
</div>
<% end_if %>
<% end_loop %>
</div>
<% end_if %>

View File

@ -1,4 +1,24 @@
<% if $ShowTitle %><h3>$Title</h3><% end_if %>
<% if $Image %>
<img src="$Image.URL" class="img-responsive" alt="$Title.ATT">
<% if $ImageResized %>
<div class="image-element__image<% if $Height %> height{$Height}<% end_if %><% if $Width %> width{$Width}<% end_if %>">
<% if $ImageLink %><a href="$ImageLink.URL"><% end_if %>
<img src="$ImageResized.URL" class="img-responsive" alt="$Title.ATT">
<% if $ImageLink %></a><% end_if %>
</div>
<% end_if %>
<div class="image-element__caption img-content">
<div class="container">
<% if $ShowTitle %><h3 class="image-element__title title">$Title</h3><% end_if %>
<% if $Content %>
<div class="image-element__content typography">$Content</div>
<% end_if %>
<% if $ImageLink %>
<a href="$ImageLink.URL" class="image-element__btn btn btn-default">
$ImageLink.Title
<i class="fas fa-caret-right"></i>
</a>
<% end_if %>
</div>
</div>

View File

@ -0,0 +1,25 @@
<div class="blog-post-info">
<div class="published-date">
<div class="day">$PublishDate.Format("d")</div>
<div class="month">$PublishDate.Format("MMM")</div>
</div>
<% if $FeaturedImage %>
<div class="img">
<a href="$Link">$FeaturedImage.Fill(350,200)</a>
</div>
<% end_if %>
<% include SilverStripe\\Blog\\EntryMeta %>
<h5 class="title">
<a href="$Link.ATT" title="Go to the $Title post">
$Title
</a>
</h5>
<div class="typography summary">
$Summary
</div>
<a href="{$Link}" class="btn btn-link">Read More &raquo;</a>
</div>