IMPROVEMETS: Map and Widgets functionality

This commit is contained in:
Tony Air 2019-12-11 09:30:39 +07:00
parent a4adb0ab1d
commit ee112280e8
10 changed files with 329 additions and 18 deletions

View File

@ -49,7 +49,7 @@ DNADesign\ElementalUserForms\Model\ElementForm:
# Blog + Widgets module extensions
Page:
extensions:
- SilverStripe\Widgets\Extensions\WidgetPageExtension
- Site\Widgets\WidgetPageExtension
SilverStripe\Blog\Model\Blog:
extensions:
@ -57,3 +57,20 @@ SilverStripe\Blog\Model\Blog:
SilverStripe\Blog\Model\BlogPost:
extensions:
- Site\Extensions\BlogPostExtension
SilverStripe\Widgets\Model\Widget:
icon: '<i class="icon font-icon-p-document"></i>'
SilverStripe\Blog\Widgets\BlogArchiveWidget:
icon: '<i class="icon font-icon-p-archive"></i>'
SilverStripe\Blog\Widgets\BlogCategoriesWidget:
icon: '<i class="icon font-icon-page-multiple"></i>'
SilverStripe\Blog\Widgets\BlogFeaturedPostsWidget:
icon: '<i class="icon font-icon-chart-line"></i>'
SilverStripe\Blog\Widgets\BlogRecentPostsWidget:
icon: '<i class="icon font-icon-back-in-time"></i>'
SilverStripe\Blog\Widgets\BlogTagsCloudWidget:
icon: '<i class="icon font-icon-tags"></i>'
SilverStripe\Blog\Widgets\BlogTagsWidget:
icon: '<i class="icon font-icon-tags"></i>'
only_available_in:
- CMSMain_HiddenClass

View File

@ -11,7 +11,15 @@ SilverStripe\Core\Injector\Injector:
Symbiote\Addressable\GeocodeServiceInterface:
class: Symbiote\Addressable\MapboxGeocodeService
Symbiote\Addressable\MapboxGeocodeService:
mapbox_api_key: ''
A2nt\SilverStripeMapboxField\MapboxField:
map_style: 'mapbox://styles/mapbox/streets-v9' #'mapbox://styles/mapbox/light-v10'
Site\Elements\MapElement:
map_type: 'google-maps'
BetterBrief\GoogleMapField:
default_options:
api_key: ''
Symbiote\Addressable\MapboxGeocodeService:
mapbox_api_key: ''

View File

@ -9,7 +9,14 @@
namespace Site\Elements;
use A2nt\SilverStripeMapboxField\MapboxField;
use BetterBrief\GoogleMapField;
use DNADesign\Elemental\Models\ElementContent;
use SilverStripe\Core\Config\Config;
use SilverStripe\Forms\FieldList;
use SilverStripe\Forms\GridField\GridField;
use SilverStripe\Forms\GridField\GridFieldConfig_RelationEditor;
use SilverStripe\Forms\HTMLEditor\HTMLEditorField;
use SilverStripe\Forms\NumericField;
use Site\Controllers\MapElementController;
use Site\Extensions\MapExtension;
@ -26,27 +33,57 @@ class MapElement extends ElementContent
private static $table_name = 'MapElement';
private static $controller_class = MapElementController::class;
private static $map_type = 'mapbox';
private static $extensions = [
MapExtension::class,
];
public function getType()
public function getType():string
{
return self::$singular_name;
}
public function getCMSFields()
public function getCMSFields(): FieldList
{
$fields = parent::getCMSFields();
$fields->removeByName('Locations');
$fields->remove('HTML');
$tab = $fields->findOrMakeTab('Root.MapPins');
$tab->setTitle('Description');
$tab->push(HTMLEditorField::create('HTML', 'Content'));
$fields->addFieldsToTab('Root.Main', [
NumericField::create('MapZoom', 'Initial Map Zoom (enter a number from 0 to 24)'),
GridField::create(
'Locations',
'Locations',
$this->owner->Locations(),
GridFieldConfig_RelationEditor::create(100)
)
]);
return $fields;
}
public function MapAPIKey()
public function MapAPIKey(): string
{
return MapboxField::getAccessToken();
$type = self::config()->get('map_type');
switch ($type) {
case 'mapbox':
$key = MapboxField::getAccessToken();
break;
case 'google-maps':
$cfg = Config::inst()->get(GoogleMapField::class, 'default_options');
$key = $cfg['api_key'];
break;
default:
$key = '';
break;
}
return $key;
}
}

View File

@ -8,7 +8,6 @@
namespace Site\Extensions;
use SilverStripe\Core\Extension;
use SilverStripe\Forms\CompositeField;
use SilverStripe\Forms\FieldList;
@ -32,11 +31,12 @@ class MapExtension extends DataExtension
'Locations',
];
public function updateCMSFields(FieldList $fields)
public function updateCMSFields(FieldList $fields): void
{
parent::updateCMSFields($fields);
$fields->addFieldsToTab('Root.Map', [
$fields->removeByName('Locations');
$fields->addFieldsToTab('Root.MapPins', [
NumericField::create('MapZoom', 'Initial Map Zoom (enter a number from 0 to 24)'),
GridField::create(
'Locations',
@ -45,6 +45,8 @@ class MapExtension extends DataExtension
GridFieldConfig_RelationEditor::create(100)
)
]);
$fields->findOrMakeTab('Root.MapPins')->setTitle('Locations');
}
public function getGeoJSON(): string

View File

@ -12,6 +12,7 @@ use A2nt\SilverStripeMapboxField\MapboxField;
use A2nt\SilverStripeMapboxField\MarkerExtension;
use Sheadawson\Linkable\Forms\LinkField;
use Sheadawson\Linkable\Models\Link;
use SilverStripe\Forms\CheckboxField;
use SilverStripe\ORM\DataObject;
use SilverStripe\Versioned\Versioned;
use Site\Elements\MapElement;
@ -46,6 +47,8 @@ class MapPin extends DataObject
{
$fields = parent::getCMSFields();
$fields->removeByName('MapElements');
$fields->replaceField(
'PhoneNumberID',
LinkField::create('PhoneNumberID', 'Phone Number')
@ -57,8 +60,11 @@ class MapPin extends DataObject
LinkField::create('FaxID', 'FAX')
->setAllowedTypes(['Phone'])
);
$fields->removeByName(['Map', 'LatLngOverride', 'Lng','Lat']);
$fields->addFieldsToTab('Root.Map', [
$fields->addFieldsToTab('Root.Main', [
CheckboxField::create('LatLngOverride', 'Override Latitude and Longitude?')
->setDescription('Check this box and save to be able to edit the latitude and longitude manually.'),
MapboxField::create('Map', 'Choose a location', 'Lat', 'Lng'),
]);
@ -89,12 +95,12 @@ class MapPin extends DataObject
'Address',
'City',
'State',
'Country',
//'Country',
];
$n = count($fields);
for($i = 0; $i < $n; $i++) {
if(!isset($details[$i])){
for ($i = 0; $i < $n; $i++) {
if (!isset($details[$i])) {
continue;
}
@ -103,7 +109,7 @@ class MapPin extends DataObject
// get postal code
if ($name === 'State') {
$this->setField('PostalCode',substr($val ,strrpos($val, ' ')+1));
$this->setField('PostalCode', substr($val, strrpos($val, ' ')+1));
}
$this->setField($name, $val);
@ -111,7 +117,7 @@ class MapPin extends DataObject
}
}
}
}catch (\Exception $e) {
} catch (\Exception $e) {
}
}
}

View File

@ -0,0 +1,49 @@
<?php
namespace Site\Widgets;
use Sheadawson\Linkable\Forms\LinkField;
use Sheadawson\Linkable\Models\Link;
use SilverStripe\AssetAdmin\Forms\UploadField;
use SilverStripe\Assets\Image;
use SilverStripe\Widgets\Model\Widget;
if (!class_exists(Widget::class)) {
return;
}
class BannerWidget extends Widget
{
private static $title = 'Banner';
private static $cmsTitle = 'Banner';
private static $description = 'Shows banner with image and link.';
private static $icon = '<i class="icon font-icon-block-banner"></i>';
private static $table_name = 'BannerWidget';
private static $db = [
'Title' => 'Varchar(255)',
];
private static $has_one = [
'Image' => Image::class,
'Link' => Link::class,
];
private static $owns = [
'Image',
'Link',
];
public function getCMSFields()
{
$fields = parent::getCMSFields();
$fields->push(UploadField::create('Image')
->setAllowedFileCategories(['image/supported']));
$fields->push(LinkField::create('LinkID', 'Link'));
return $fields;
}
}

View File

@ -0,0 +1,155 @@
<?php
namespace Site\Widgets;
use DNADesign\Elemental\Controllers\ElementalAreaController;
use DNADesign\Elemental\Forms\ElementalAreaConfig;
use DNADesign\Elemental\Forms\ElementalAreaField;
use DNADesign\Elemental\Models\BaseElement;
use DNADesign\Elemental\Models\ElementalArea;
use SilverStripe\Control\Controller;
use SilverStripe\Core\Injector\Injector;
use SilverStripe\Forms\CompositeField;
use SilverStripe\Forms\FieldGroup;
use SilverStripe\Forms\FieldList;
use SilverStripe\Forms\FormField;
use SilverStripe\Forms\GridField\GridField;
use SilverStripe\Forms\GridField\GridFieldAddExistingAutocompleter;
use SilverStripe\Forms\GridField\GridFieldAddNewButton;
use SilverStripe\Forms\GridField\GridFieldConfig;
use SilverStripe\Forms\GridField\GridFieldConfig_Base;
use SilverStripe\Forms\GridField\GridFieldConfig_RelationEditor;
use SilverStripe\Forms\GridField\GridFieldDataColumns;
use SilverStripe\Forms\GridField\GridFieldDeleteAction;
use SilverStripe\Forms\GridField\GridFieldDetailForm;
use SilverStripe\Forms\GridField\GridFieldEditButton;
use SilverStripe\Forms\TabSet;
use SilverStripe\ORM\DataObjectInterface;
use SilverStripe\Widgets\Model\Widget;
use SilverStripe\Widgets\Model\WidgetArea;
use Symbiote\GridFieldExtensions\GridFieldAddNewMultiClass;
use UndefinedOffset\SortableGridField\Forms\GridFieldSortableRows;
class WidgetAreaField extends GridField
{
/**
* @var ElementalArea $area
*/
protected $area;
/**
* @var array $type
*/
protected $types = [];
/**
* @var null
*/
protected $inputType = null;
protected $modelClassName = Widget::class;
/**
* @param string $name
* @param ElementalArea $area
* @param string[] $blockTypes
*/
public function __construct($name, WidgetArea $area, array $blockTypes)
{
$this->setTypes($blockTypes);
$config = GridFieldConfig_Base::create();
$config->getComponentByType(GridFieldDataColumns::class)->setDisplayFields([
'Icon' => '',
'Title' => 'Title',
'LastEdited' => 'Changed',
])->setFieldFormatting([
'Icon' => static function($v, Widget $item) {
return '<span style="font-size:2rem">'.$item::config()->get('icon').'</span>';
}
]);
$config->addComponent(new GridFieldEditButton());
$config->addComponent(new GridFieldDeleteAction(false));
$config->addComponent(new GridFieldDetailForm(null, false, false));
$config->addComponent(new GridFieldSortableRows('Sort'));
if (!empty($blockTypes)) {
/** @var GridFieldAddNewMultiClass $adder */
$adder = Injector::inst()->create(GridFieldAddNewMultiClass::class);
$adder->setClasses($blockTypes);
$config->addComponent($adder);
}
// By default, no need for a title on the editor. If there is more than one area then use `setTitle` to describe
parent::__construct($name, '', $area->Widgets(), $config);
$this->area = $area;
$this->addExtraClass('element-editor__container no-change-track');
}
/**
* @param array $types
*
* @return $this
*/
public function setTypes($types)
{
$this->types = $types;
return $this;
}
/**
* @return array
*/
public function getTypes()
{
$types = $this->types;
$this->extend('updateGetTypes', $types);
return $types;
}
/**
* @return ElementalArea
*/
public function getArea()
{
return $this->area;
}
public function saveInto(DataObjectInterface $dataObject)
{
parent::saveInto($dataObject);
$elementData = $this->Value();
$idPrefixLength = strlen(sprintf(ElementalAreaController::FORM_NAME_TEMPLATE, ''));
if (!$elementData) {
return;
}
foreach ($elementData as $form => $data) {
// Extract the ID
$elementId = (int) substr($form, $idPrefixLength);
/** @var BaseElement $element */
$element = $this->getArea()->Widgets()->byID($elementId);
if (!$element) {
// Ignore invalid elements
continue;
}
$data = ElementalAreaController::removeNamespacesFromFields($data, $element->ID);
$element->updateFromFormData($data);
$element->write();
}
}
}

View File

@ -0,0 +1,37 @@
<?php
namespace Site\Widgets;
use DNADesign\Elemental\Forms\ElementalAreaField;
use SilverStripe\Forms\FieldList;
use SilverStripe\Widgets\Forms\WidgetAreaEditor;
use SilverStripe\Widgets\Model\Widget;
class WidgetPageExtension extends \SilverStripe\Widgets\Extensions\WidgetPageExtension
{
public function updateCMSFields(FieldList $fields)
{
parent::updateCMSFields($fields);
$tab = $fields->findOrMakeTab('Root.Widgets');
$tab->setTitle('Sidebar');
$tab->removeByName('SideBar');
$widgetTypes = WidgetAreaEditor::create('Sidebar')->AvailableWidgets();
$available = [];
/** @var Widget $type */
foreach ($widgetTypes as $type) {
$available[get_class($type)] = $type->getCMSTitle();
}
$tab->push(WidgetAreaField::create(
'SideBar',
$this->owner->Sidebar(),
$available
));
}
}

View File

@ -1,7 +1,7 @@
<div
class="mapAPI-map-container"
data-map-zoom="$MapZoom"
data-key="<% if $MapAPIKey %>$MapAPIKey<% else %>$SiteConfig.MapAPIKey<% end_if %>"
data-key="$MapAPIKey"
data-map-style="<% if $MapStyle %>$MapStyle<% else %>$SiteConfig.MapStyle<% end_if %>"
data-geojson="$GeoJSON.XML"
data-fly-to-marker="true"