I am trying to display Google Calendar in Laravel application. I can fetch Google Calender using this package.
How can I display Calendar like below ?
Thanks #Prisoner. I used below code in my controller.
<?php
namespace App\Http\Controllers;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Routing\Controller as BaseController;
use Spatie\GoogleCalendar\Event;
use Calendar;
class HomeController extends BaseController
{
public function calendar() {
$events = [];
$data = Event::get();
if($data->count()){
foreach ($data as $key => $value) {
$events[] = Calendar::event(
$value->name,
true,
new \DateTime($value->startDate),
new \DateTime($value->endDate.' +1 day')
);
}
}
$calendar = Calendar::addEvents($events);
return view('welcome', compact('calendar'));
}
}
But I am getting White screen.
Related
In DataObjects, the getCMSFields method creates all the appropriate CMS Fields automatically (it is called scaffolding). However, in classes that extend SiteTree (i.e. Pages) this does not happen.
How can I use this form field scaffolding in Pages?
Besides calling DataObject::getCMSFields() as you already suggested in your own answer, it is also possible to instantiate a scafolder directly:
public function getCMSFields() {
// with tabs
$scaffolder = new FormScaffolder($this);
$scaffolder->restrictFields = ['Title', 'Content'];
$scaffolder->tabbed = true;
$fields = $scaffolder->getFieldList();
$fields->addFieldToTab('Root.Main', [
new MySpecialFieldWithCustomOptions('Links', 'My Links', $foobar),
]);
return $fields;
}
public function getCMSFields() {
// without tabs
$scaffolder = new FormScaffolder($this);
$scaffolder->restrictFields = ['Title', 'Content'];
$fields = $scaffolder->getFieldList();
$fields->push(
new MySpecialFieldWithCustomOptions('Links', 'My Links', $foobar)
);
return $fields;
}
This will work with any DataObject ($this has to be an instace of DataObject). Pages a subclass of DataObjects.
restrictFields is optional, if not provided, it will do all fields it can find.
We go back to DataObject and get the scaffolded fields:
use SilverStripe\ORM\DataObject;
use Page;
class MyPage extends Page
{
private static $db = [
'MyField' => 'Varchar',
];
private static $has_one = [
'MyRelation' => 'MyClass',
];
public function getCMSFields()
{
// fields from Page class
$fields = parent::getCMSFields();
// fields from DataObject class.
$fieldRepository = DataObject::getCMSFields();
$fields->addFieldsToTab(
'Root.MyExtraFields',
[
$fieldRepository->dataFieldByName('MyField'),
$fieldRepository->dataFieldByName('MyRelationID'),
]
);
return $fields;
}
}
I'm trying to remove the Export to CSV button in the top of a GridField in ModelAdmin.
I can't seem to find the class that creates the button (GridFieldExportButton right?). I'm guessing there is a function that populates the GridField with buttons / "actions" which I'm not familiar with.
To remove the scaffolded GridField for relationships...
class MyDataObject extends DataObject {
...
private static $has_many= array(
'OtherDataObjects' => 'OtherDataObject'
);
...
function getCMSFields() {
$fields = parent::getCMSFields();
if($grid = $fields->dataFieldByName('OtherDataObjects'))
$grid->getConfig()
->removeComponentsByType('SilverStripe\Forms\GridField\GridFieldExportButton');
return $fields;
}
...
}
If you are making the GridField then just add this when you create the field...
$gridField->getConfig()->removeComponentsByType('SilverStripe\Forms\GridField\GridFieldExportButton');
If you are looking for a gridfield that isn't within a data object edit form and is actually...
class MyAdmin extends ModelAdmin {
...
function getEditForm($id = null, $fields = null) {
$form = parent::getEditForm($id, $fields);
if($this->modelClass == 'MyDataObjectName') {
$form->Fields()
->fieldByName($this->sanitiseClassName($this->modelClass))
->getConfig()
->removeComponentsByType('SilverStripe\Forms\GridField\GridFieldExportButton');
}
return $form;
}
...
}
Setting model_importers to empty will do the reverse and remove the import ...
class MyAdmin extends ModelAdmin {
...
static $model_importers = array();
...
}
I have created a holder page KochiHolder as below and performed a database rebuild successfully. I have set the $allowed_children of KochiHolder to only accept KochiPage or VirtualPage.
In the CMS I cannot create a VirtualPage under a KochiHolder page.
Why is $allowed_children not working correctly? How do I allow VirtualPage to be created as a sub page of KochiHolder?
KochiHolder
class KochiHolder extends Page {
private static $db = array(
);
private static $has_one = array(
'Photo' => 'Image'
);
private static $can_be_root = false;
private static $allowed_children = array('KochiPage', 'VirtualPage');
public function getCMSFields() {
$fields = parent::getCMSFields();
$fields->addFieldToTab("Root.Images", new UploadField('Photo'));
return $fields;
}
}
After a bit of debugging of CMSPageAddController (more specifically, the doAdd action) that Silverstripe uses for the "Add Page" screen in the CMS, I believe I found the root cause of the problem.
So the following error seems to be occurring: Page type "Page" not allowed as child of this parent page (well, that is the error I was getting in my test)
In the SiteTree class, it has a validate function which checks what the allowed children are. One of the checks for this is unrolling VirtualPage to the page it is a virtual of. (There is probably a little more to it than that - I need to do more investigating)
Good news is that you can override this functionality however it isn't great. Basically, because your class extends Page which extends SiteTree, if you specify your own validate function on Page (as VirtualPage extends Page too) you would be able to override the functionality.
In my tests, I used the following:
public function validate()
{
$result = parent::validate();
if ($this instanceof VirtualPage)
{
$newResult = new ValidationResult();
$items = $result->messageList();
foreach ($items as $key => $value)
{
if ($key != 'ALLOWED_CHILDREN')
{
$newResult->error($value, $key);
}
}
return $newResult;
}
return $result;
}
It isn't perfect and it makes some assumptions (eg. error codes are assumed for all items in the messageList but that isn't always the case). I haven't done heaps of testing with it but it does work for my recreation of your particular scenario.
I would like to use GridField to view and create new child pages. Parent is DocumentHolder, child is Document. Both extend SiteTree. When I click to "Add Document" (button generated by grid), fill in the fields and confirm the form, the parent page is ignored and the page is created in root. It works well when I use DataObject. The code looks like this:
class DocumentHolder extends SiteTree
{
private static $allowed_children = array(
'Document'
);
private static $default_child = "Document";
public function getCMSFields()
{
$fields = parent::getCMSFields();
$gridField = new GridField('Documents', 'Documents', SiteTree::get('Document')->filter('ParentID', $this->ID), GridFieldConfig_RecordEditor::create());
$fields->addFieldToTab("Root.Uploads", $gridField);
return $fields;
}
}
class Document extends SiteTree
{
private static $db = array(
);
private static $has_one = array(
);
}
Thanks for help.
Since SiteTree already has a relationship to its Children pages set up, you may as well use it! Since allowed_children will only ever be documents, try this instead:
$gridField = new GridField('Documents', 'Documents', $this->Children(), GridFieldConfig_RecordEditor::create());
I ran into this problem earlier working on my holderpage module. You need to set the ParentID by default. Here's two strategies;
You can use populateDefaults on the child class. E.g.
class Document extends SiteTree
{
private static $default_parent = 'DocumentHolder';
private static $can_be_root = false;
public function populateDefaults(){
parent::populateDefaults();
$this->ParentID = DataObject::get_one(self::$default_parent)->ID;
}
...
Or you can manipulate the record in the gridfield with a custom GridFieldDetailForm implementation or via the updateItemEditForm callback.
<?php
class MyGridFieldDetailForm_ItemRequest extends GridFieldDetailForm_ItemRequest
{
public function ItemEditForm()
{
$form = parent::ItemEditForm();
if (! $this->record->exists() && $this->record->is_a('SiteTree')) {
$parent_page = $this->getController()->currentPage();
if ($parent_page && $parent_page->exists()) {
$this->record->ParentID = $parent_page->ID;
// update URLSegment #TODO perhaps more efficiently?
$field = $this->record->getCMSFields()->dataFieldByName('URLSegment');
$form->Fields()->replaceField('URLSegment', $field);
}
}
return $form;
}
}
This is more complicated although it allowed me to create an effortless module / addon ( https://github.com/briceburg/silverstripe-holderpage )
If I have a $has_many relationship that I want to manage with a GridField in the cms, how would I go about putting a limit on the number of how many relations one object can have? Is this possible?
Can I do this in the model or would it have to be a check I add into the GridField I'm using to add and remove relations?
I'm looking at implementing GridField_SaveHandler to make a custom GridFieldComponent but not sure how I can use this to abort the save if i detect something is wrong.
the following 2 solutions are not the cleanest way to solve this, but the most pragmatic and easiest to implement.
basically, what I suggest to do, is just count the objects and remove the ability to add new records once the count is above a certain number.
if you want to limit the number of records on a single relation/grid (lets say max 5 players per team):
class Player extends Dataobject {
private static $db = array('Title' => 'Varchar');
private static $has_one = array('TeamPage' => 'TeamPage');
}
class TeamPage extends Page {
private static $has_one = array('Players' => 'Player');
public function getCMSFields() {
$fields = parent::getCMSFields();
$config = GridFieldConfig_RecordEditor::create();
if ($this->Players()->count > 5) {
// remove the buttons if we don't want to allow more records to be added/created
$config->removeComponentsByType('GridFieldAddNewButton');
$config->removeComponentsByType('GridFieldAddExistingAutocompleter');
}
$grid = GridField::create('Players', 'Players on this Team', $this->Players(), $config);
$fields->addFieldToTab('Root.Main', $grid);
return $fields;
}
}
if you want to limit the total number of records globally (if we limit this way to 5, this means if 1 Team already has 3 Players, then the 2nd team can only have 2):
class Player extends Dataobject {
private static $db = array('Title' => 'Varchar');
private static $has_one = array('TeamPage' => 'TeamPage');
public function canCreate($member = null) {
if (Player::get()->count() > 5) {
return false;
}
return parent::canCreate($member);
}
}
class TeamPage extends Page {
private static $has_one = array('Players' => 'Player');
public function getCMSFields() {
$fields = parent::getCMSFields();
$config = GridFieldConfig_RecordEditor::create();
$grid = GridField::create('Players', 'Players on this Team', $this->Players(), $config);
$fields->addFieldToTab('Root.Main', $grid);
return $fields;
}
}
I have wrote a quick jQuery plugin to limit the number of items a GridField can have: -
Download the plugin here: - gridfieldlimit.js
https://letscrate.com/f/monkeyben/silverstripe/gridfieldlimit.js
Set up the plugin in the getCMSFields function: -
// Pass GridField configs, each one containing field name and item limit
$vars = array(
"GridFieldLimits" => "[['GRIDFIELD_NAME_1', 3], ['GRIDFIELD_NAME_2', 6]]",
);
// Load the jquery gridfield plugin
Requirements::javascriptTemplate("themes/YOUR_THEME_NAME/javascript/gridfieldlimit.js", $vars);
works for me: make the canCreate method of the DataObject that's managed by your GridField check for existing objects.
of course, this doesn't allow you to implement a customg GridFieldComponent, as you need to modify the DataObject code.