Notifications + Openning Hours extensions

This commit is contained in:
Tony Air 2019-01-10 18:10:31 +07:00
parent 6914a47f93
commit 992e9f54fd
16 changed files with 641 additions and 11 deletions

View File

@ -17,6 +17,10 @@ SilverStripe\View\SSViewer:
# extra_requirements_css:
# - 'colymba/gridfield-bulk-editing-tools:client/dist/styles/main.css'
SilverStripe\Admin\LeftAndMain:
extra_requirements_css:
- 'app/client/dist/css/cms.css'
SilverStripe\Forms\HTMLEditor\TinyMCEConfig:
editor_css:
- 'app/client/dist/css/editor.css'

View File

@ -1,5 +1,6 @@
SilverStripe\SiteConfig\SiteConfig:
extensions:
- Broarm\OpeningHours\OpeningHours
- Site\Extensions\SiteConfigExtension
- Site\Extensions\SocialExtension

View File

@ -43,7 +43,8 @@ const CarouselUI = (($) => {
// create arrows
if ($e.data('arrows')) {
$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>');
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-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>');
}
@ -67,8 +68,8 @@ const CarouselUI = (($) => {
$(event.target).carousel('prev');
});
$e.hammer().bind('tap', (event) => {
$(event.target).carousel('next');
$e.find('img').hammer().bind('tap', (event) => {
$e.carousel('next');
});
});
}
@ -87,4 +88,4 @@ const CarouselUI = (($) => {
return CarouselUI;
})($);
export default CarouselUI;
export default CarouselUI;

View File

@ -0,0 +1,108 @@
import $ from 'jquery';
import Events from '../_events';
const OpeningHoursUI = (($) => {
// Constants
const NAME = 'OpeningHoursUI';
class OpeningHoursUI {
// Static methods
static each(callback) {
$('.js-opening-hours').each(function(i, e) {
callback(i, $(e));
});
}
static init() {
this.dispose();
const hours = $.parseJSON($('.oppening-hours-json').html());
const date = new Date();
const dateYMD = this.Date_toYMD(date);
const weekday = [
'Sunday',
'Monday',
'Tuesday',
'Wednesday',
'Thursday',
'Friday',
'Saturday',
];
const today = weekday[date.getDay()];
let html = '<b class="opening-hours-status opening-hours-status-closed">Closed today</b>';
if (
typeof hours['days'] !== 'undefined' &&
typeof hours['days'][today] !== 'undefined' &&
hours['days'][today].length
) {
html = 'Open today ';
$.each(hours['days'][today], (i, v) => {
if (v['DisplayStart'] || v['DisplayEnd']) {
if (
(
v['DisplayStart'] && v['DisplayStart'] <= dateYMD &&
v['DisplayEnd'] && v['DisplayEnd'] >= dateYMD
) ||
(v['DisplayStart'] && v['DisplayStart'] <= dateYMD && !v['DisplayEnd']) ||
(v['DisplayEnd'] && v['DisplayEnd'] >= dateYMD && !v['DisplayStart'])
) {
html = 'Open today from ' + v['From'] + ' to ' + v['Till'];
return false;
}
} else {
if (i > 0) {
html += ', <br/>';
}
html += 'from ' + v['From'] + ' to ' + v['Till'];
}
});
html += ' <b class="opening-hours-status"></b>';
}
if (
typeof hours['holidays'] !== 'undefined' &&
typeof hours['holidays'][dateYMD] !== 'undefined'
) {
html = '<b class="opening-hours-status opening-hours-status-closed">Closed today' +
(hours['holidays'][dateYMD] ? ' for ' + hours['holidays'][dateYMD] : '') +
'</b>';
}
this.each((i, e) => {
const $e = $(e);
$e.html(html);
});
}
static Date_toYMD(date) {
var year, month, day;
year = String(date.getFullYear());
month = String(date.getMonth() + 1);
if (month.length == 1) {
month = '0' + month;
}
day = String(date.getDate());
if (day.length == 1) {
day = '0' + day;
}
return year + '-' + month + '-' + day;
}
static dispose() {
this.each((i, e) => {
$(e).html('');
});
}
}
$(window).on(`${Events.AJAX} ${Events.LOADED}`, () => {
OpeningHoursUI.init();
});
return OpeningHoursUI;
})($);
export default OpeningHoursUI;

View File

@ -0,0 +1,3 @@
#Menu-SilverStripe-CampaignAdmin-CampaignAdmin {
display: none;
}

View File

@ -6,16 +6,18 @@
&.left {
float: left;
clear: left;
margin: 0 1rem 1rem 0;
}
&.center {
display: block;
margin: 0 auto;
margin: 1rem auto;
}
&.right {
float: right;
clear: right;
margin: 1rem 0 0 1rem;
}
}

View File

@ -0,0 +1,94 @@
<?php
namespace Site\Extensions;
use Dynamic\Elements\Blog\Elements\ElementBlogPosts;
use Innoweb\Sitemap\Pages\SitemapPage;
use Sheadawson\Linkable\Forms\LinkField;
use Sheadawson\Linkable\Models\Link;
use SilverStripe\AssetAdmin\Forms\UploadField;
use SilverStripe\Assets\Image;
use SilverStripe\Forms\CheckboxField;
use SilverStripe\Forms\DropdownField;
use SilverStripe\Forms\GridField\GridField;
use SilverStripe\Forms\GridField\GridFieldConfig;
use SilverStripe\Forms\GridField\GridFieldDeleteAction;
use SilverStripe\Forms\GridField\GridFieldToolbarHeader;
use SilverStripe\Forms\HeaderField;
use SilverStripe\Forms\LiteralField;
use SilverStripe\Forms\TextareaField;
use SilverStripe\Forms\TextField;
use SilverStripe\ORM\DataExtension;
use SilverStripe\CMS\Model\SiteTree;
use SilverStripe\Forms\FieldList;
use SilverStripe\Forms\TreeMultiselectField;
use BetterBrief\GoogleMapField;
use Site\Models\Holiday;
use Site\Models\Notification;
use Site\Models\OpeningHour;
use Symbiote\GridFieldExtensions\GridFieldAddNewInlineButton;
use Symbiote\GridFieldExtensions\GridFieldEditableColumns;
use Symbiote\GridFieldExtensions\GridFieldTitleHeader;
class NotificationsExtension extends DataExtension
{
private static $db = [
'ShowNotifications' => 'Boolean(1)',
];
private static $has_many = [
'Notifications' => Notification::class,
];
public function updateCMSFields(FieldList $fields)
{
$tab = $fields->findOrMakeTab('Root.Notifications');
if(!$this->owner->exists()) {
$tab->push(LiteralField::create(
'NotificationsNotice',
'<p class="message notice">The object must be saved before notifications can be added</p>'
));
return null;
}
$items = $this->owner->Notifications();
$config = GridFieldConfig::create();
$config->addComponents([
new GridFieldToolbarHeader(),
new GridFieldTitleHeader(),
new GridFieldEditableColumns(),
new GridFieldAddNewInlineButton('toolbar-header-right'),
new GridFieldDeleteAction(),
]);
$tab->setChildren(FieldList::create(
HeaderField::create('NotificationsHeader','Notifications'),
LiteralField::create(
'CurrentNotifications',
'<b>Current:</b>'
.$this->owner->renderWith('Site\\Objects\\NotificationsList')
),
CheckboxField::create('ShowNotifications'),
GridField::create(
'Notifications',
'',
$items,
$config
)
));
}
public function NotificationsToday()
{
$items = $this->owner->Notifications();
$time = time();
return $items->filter([
'DateOn:LessThanOrEqual' => date('Y-m-d', $time),
'DateOff:GreaterThanOrEqual' => date('Y-m-d', $time),
]);
}
}

View File

@ -0,0 +1,189 @@
<?php
namespace Site\Extensions;
use Dynamic\Elements\Blog\Elements\ElementBlogPosts;
use Innoweb\Sitemap\Pages\SitemapPage;
use Sheadawson\Linkable\Forms\LinkField;
use Sheadawson\Linkable\Models\Link;
use SilverStripe\AssetAdmin\Forms\UploadField;
use SilverStripe\Assets\Image;
use SilverStripe\Forms\CheckboxField;
use SilverStripe\Forms\DropdownField;
use SilverStripe\Forms\GridField\GridField;
use SilverStripe\Forms\GridField\GridFieldConfig;
use SilverStripe\Forms\GridField\GridFieldDeleteAction;
use SilverStripe\Forms\GridField\GridFieldToolbarHeader;
use SilverStripe\Forms\HeaderField;
use SilverStripe\Forms\LiteralField;
use SilverStripe\Forms\TextareaField;
use SilverStripe\Forms\TextField;
use SilverStripe\ORM\DataExtension;
use SilverStripe\CMS\Model\SiteTree;
use SilverStripe\Forms\FieldList;
use SilverStripe\Forms\TreeMultiselectField;
use BetterBrief\GoogleMapField;
use Site\Models\Holiday;
use Site\Models\OpeningHour;
use Symbiote\GridFieldExtensions\GridFieldAddNewInlineButton;
use Symbiote\GridFieldExtensions\GridFieldEditableColumns;
use Symbiote\GridFieldExtensions\GridFieldTitleHeader;
class OpenningHoursExtension extends DataExtension
{
private static $db = [
'ShowOpeningHours' => 'Boolean(1)',
'OpenningHoursNote' => 'Varchar(255)',
];
private static $has_one = [
'OpeningHoursPage' => SiteTree::class,
];
private static $has_many = [
'OpeningHours' => OpeningHour::class,
'Holidays' => Holiday::class,
];
public function HoursLink()
{
return $this->owner->OpeningHoursPage()->Link();
}
public function updateCMSFields(FieldList $fields)
{
$tab = $fields->findOrMakeTab('Root.OpeningHours');
if(!$this->owner->exists()) {
$tab->push(LiteralField::create(
'OpeningHoursNotice',
'<p class="message notice">The object must be saved before opening hours can be added</p>'
));
return null;
}
$hours = $this->owner->OpeningHours();
$config = GridFieldConfig::create();
$config->addComponents([
new GridFieldToolbarHeader(),
new GridFieldTitleHeader(),
new GridFieldEditableColumns(),
new GridFieldAddNewInlineButton('toolbar-header-right'),
new GridFieldDeleteAction(),
]);
$tab->setChildren(FieldList::create(
HeaderField::create('OpeningHours','Opening Hours'),
LiteralField::create(
'CurrentOpeningHour',
'<b>Today:</b>'
.'<p class="message notice">'
.$this->owner->renderWith('Site\\Objects\\OpeningHoursList')
.'</p>'
),
CheckboxField::create('ShowOpeningHours'),
DropdownField::create(
'OpeningHoursPageID',
'Opening Hours Page',
SiteTree::get()->map()->toArray()
),
/*TextareaField::create('OpenningHoursNote'),
LiteralField::create(
'OpeningHoursNote',
'<p><b>Please, specify time ranges. For example:</b><br/>'
.'Monday 10:00 AM - 2:00 PM<br/>'
.'Monday 3:00 PM - 6:00 PM<br/>'
.'Tuesday 12:00 AM - 2:00 PM<br/>'
.'Tuesday 3:00 PM - 4:00 PM<br/>'
.'...<br/>'
.'<b>Short day example durring holidays:</b><br/>'
.'Monday 12:00 AM - 2:00 PM 12/31/2018 - 01/06/2019'
.'</p>'
),*/
GridField::create(
'OpeningHours',
'Opening Hours',
$hours,
$config
)
));
$tab = $fields->findOrMakeTab('Root.Holidays');
$tab->push(GridField::create(
'Holidays',
'Holidays',
$this->owner->Holidays(),
$config
));
}
/**
* Get the opening hours
*
* @return OpeningHour|DataObject|null
*/
public function OpeningHoursToday()
{
$hours = $this->owner->OpeningHours();
$time = time();
$today = $hours->filter([
'Day' => date('l', $time),
'DisplayStart:LessThanOrEqual' => date('Y-m-d', $time),
'DisplayEnd:GreaterThanOrEqual' => date('Y-m-d', $time),
]);
return $today->exists() ? $today : $hours->filter([
'Day' => date('l', $time),
'DisplayStart' => null,
'DisplayEnd' => null,
]);
}
public function OpeningHoursJSON()
{
$hours = $this->owner->OpeningHours();
$result = [];
foreach ($hours as $hour) {
$from = str_replace(':00', '', date('g:i a', strtotime($hour->getField('From'))));
$till = str_replace(':00', '', date('g:i a', strtotime($hour->getField('Till'))));
$result['days'][$hour->getField('Day')][] = [
'From' => $from,
'Till' => $till,
'DisplayStart' => $hour->getField('DisplayStart'),
'DisplayEnd' => $hour->getField('DisplayEnd'),
];
}
$holidays = $this->owner->Holidays();
foreach ($holidays as $holiday) {
$result['holidays'][$holiday->getField('Date')] = $holiday->getField('Title');
}
return json_encode($result);
}
public function onBeforeWrite()
{
parent::onBeforeWrite();
if ($this->owner->exists() && !$this->owner->OpeningHours()->exists()) {
$this->createOpeningHours();
}
}
/**
* Set up the opening hours for each day of the week
*/
private function createOpeningHours()
{
$days = OpeningHour::singleton()->dbObject('Day')->enumValues();
foreach ($days as $day) {
$openingHour = OpeningHour::create();
$openingHour->Day = $day;
$this->owner->OpeningHours()->add($openingHour);
}
}
}

View File

@ -0,0 +1,57 @@
<?php
/**
* Created by PhpStorm.
* User: tony
* Date: 9/12/18
* Time: 2:55 AM
*/
namespace Site\Models;
use Dynamic\FlexSlider\Model\SlideImage;
use Sheadawson\Linkable\Forms\LinkField;
use Sheadawson\Linkable\Models\Link;
use SilverStripe\ORM\DataObject;
use SilverStripe\ORM\ValidationResult;
use SilverStripe\SiteConfig\SiteConfig;
class Holiday extends DataObject
{
private static $table_name = 'Holiday';
private static $db = [
'Title' => 'Varchar(255)',
'Date' => 'Date',
];
private static $has_one = [
'Parent' => SiteConfig::class,
];
private static $summary_fields = [
'Title' => 'Title',
'Date' => 'Date',
];
private static $default_sort = 'Date ASC, Title ASC';
public function validate()
{
$result = parent::validate();
$exists = self::get()->filter([
'ID:not' => $this->ID,
'Date' => $this->getField('Date'),
])->exists();
if($exists) {
return $result->addError(
'Holiday was defined already.',
ValidationResult::TYPE_ERROR
);
}
return $result;
}
}

View File

@ -0,0 +1,63 @@
<?php
/**
* Created by PhpStorm.
* User: tony
* Date: 9/12/18
* Time: 2:55 AM
*/
namespace Site\Models;
use Dynamic\FlexSlider\Model\SlideImage;
use Sheadawson\Linkable\Forms\LinkField;
use Sheadawson\Linkable\Models\Link;
use SilverStripe\ORM\DataObject;
use SilverStripe\ORM\ValidationResult;
use SilverStripe\SiteConfig\SiteConfig;
class Notification extends DataObject
{
private static $table_name = 'Notification';
private static $db = [
'Title' => 'Varchar(255)',
'Content' => 'Text',
'DateOn' => 'Date',
'DateOff' => 'Date',
];
private static $has_one = [
'Parent' => SiteConfig::class,
];
private static $summary_fields = [
'Title' => 'Title',
'Content' => 'Text',
'DateOn' => 'Turn on date',
'DateOff' => 'Turn off date',
];
private static $default_sort = 'DateOn DESC, DateOff DESC, Title ASC';
public function validate()
{
$result = parent::validate();
if(!$this->getField('DateOn') || !$this->getField('DateOff')) {
return $result->addError(
'Turn on and turn off dates are required.',
ValidationResult::TYPE_ERROR
);
}
if(!$this->getField('Content')) {
return $result->addError(
'Text field required.',
ValidationResult::TYPE_ERROR
);
}
return $result;
}
}

View File

@ -0,0 +1,90 @@
<?php
/**
* Created by PhpStorm.
* User: tony
* Date: 9/12/18
* Time: 2:55 AM
*/
namespace Site\Models;
use Dynamic\FlexSlider\Model\SlideImage;
use Sheadawson\Linkable\Forms\LinkField;
use Sheadawson\Linkable\Models\Link;
use SilverStripe\ORM\DataObject;
use SilverStripe\ORM\ValidationResult;
use SilverStripe\SiteConfig\SiteConfig;
class OpeningHour extends DataObject
{
private static $table_name = 'OpeningHour';
private static $db = [
'Day' => 'Enum("Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday", "Monday")',
'From' => 'Time',
'Till' => 'Time',
'Comment' => 'Varchar(255)',
'DisplayStart' => 'Date',
'DisplayEnd' => 'Date',
];
private static $has_one = [
'Parent' => SiteConfig::class,
];
private static $defaults = [
'From' => '09:00:00',
'Till' => '22:00:00',
];
private static $summary_fields = [
'Day' => 'Day *',
'From' => 'From *',
'Till' => 'Till *',
//'Comment' => 'Comment',
'DisplayStart' => 'Display Start',
'DisplayEnd' => 'Display End',
];
private static $default_sort = 'Day ASC, From ASC';
public function validate()
{
$result = parent::validate();
if(
!$this->getField('Day')
|| !$this->getField('From')
|| !$this->getField('Till')
|| $this->getField('From') > $this->getField('Till')
) {
return $result->addError(
'Day, From and Till fields are required or wrong time range was specified.',
ValidationResult::TYPE_ERROR
);
}
$exists = self::get()->filter([
'ID:not' => $this->ID,
'ParentID' => $this->getField('ParentID'),
'Day' => $this->getField('Day'),
'From:GreaterThanOrEqual' => $this->getField('From'),
'Till:LessThanOrEqual' => $this->getField('Till'),
])->exists();
if($exists) {
return $result->addError(
'Hours were defined already for specified range.',
ValidationResult::TYPE_ERROR
);
}
return $result;
}
public function forTemplate()
{
return $this->renderWith(__CLASS__);
}
}

View File

@ -1,10 +1,9 @@
<% if $SiteWideMessage %>
<% with $SiteWideMessage %>
<div class="alert alert-fixed-top alert-{$Type}">
{$Message}
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<i class="fas fa-times"></i>
</button>
</div>
<% end_with %>
<% end_if %>
<% with $SiteConfig %>
<% include Site\Objects\NotificationsList %>
<% end_with %>

View File

@ -0,0 +1 @@
<b>$Day:</b> $From.Nice - $Till.Nice

View File

@ -0,0 +1,10 @@
<% if $ShowNotifications && $NotificationsToday %>
<% loop $NotificationsToday %>
<div class="alert alert-warning">
<% if $Title %>
<b>$Title:</b>
<% end_if %>
$Content
</div>
<% end_loop %>
<% end_if %>

View File

@ -0,0 +1,7 @@
<% if $OpeningHoursToday %>
<% loop $OpeningHoursToday %>
$forTemplate<br/>
<% end_loop %>
<% else %>
<b class="hours hous-closed">Closed</b>
<% end_if %>

View File

@ -31,7 +31,8 @@
"stevie-mayhew/silverstripe-svg": "^2.1",
"betterbrief/silverstripe-googlemapfield": "^2.1",
"innoweb/silverstripe-sitemap": "^2.0",
"silverstripe/multiuser-editing-alert": "^2.0"
"silverstripe/multiuser-editing-alert": "^2.0",
"bramdeleeuw/silverstripe-openinghours": "^1.0"
},
"require-dev": {
"phpunit/phpunit": "^5.7",