# Calendar Operation

[![The Whole Fruit Manifesto](https://img.shields.io/badge/writing%20standard-the%20whole%20fruit-brightgreen)](https://github.com/the-whole-fruit/manifesto)

This package provides a dead-simple way to add a "Calendar" view to your Siberfx CRUDs.  Save many hours of time integrating [FullCalendar](https://fullcalendar.io/), and benfit from the experience and best practices of the Siberfx core team. Here are the key features:

**Calendar View**
- Easily access a calendar representation of your CRUD entries by switching to the "Calendar" view.

**Navigation**
- Add calendar events when selecting a date or a date range.  
- Access event options like preview, edit, delete, when clicking on it.  
- Easily add more options to the event menu, to allow users to perform user-driven actions.  

**Integration**
- Seamlessly integrates with existing Siberfx CRUDs, adding calendar functionality without significant code changes.  
You don't need to change your crud field names, you can simply map them to the calendar fields.

## Demo

![Calendar Operation for Backpack](https://backpackforlaravel.com/uploads/news_images/calendar-operation.jpg)

Online demo: https://demo.backpackforlaravel.com/

## Installation


2) **Add the operation to your `EntityCrudController`**, by adding the `CalendarOperation` trait to your `EntityCrudController`. This will also add the Calendar button toggle to your List view:

```diff
class EntityCrudController extends CrudController
{
    ...
    use \Siberfx\CRUD\app\Http\Controllers\Operations\ListOperation;
+   use \Siberfx\CalendarOperation\CalendarOperation;
```

3) **Configure your calendar operation.** These are the default settings for the calendar operation, use only if you want to change them.

```php
public function setupCalendarOperation()
{
    // Set the initial view
    CRUD::setOperationSetting('initial-view', 'dayGridMonth');

    // Set the available views
    CRUD::setOperationSetting('views', ['dayGridMonth', 'timeGridWeek', 'timeGridDay']);

    // Are the calendar events editable?
    CRUD::setOperationSetting('editable', true);

    // Set the calendar default colors
    CRUD::setOperationSetting('background_color', '#3788d8');
    CRUD::setOperationSetting('text_color', '#ffffff');

    // CalendarOperation will inject a javascript into your create and 
    // update views to handle the date fields as we do on our demo.
    CRUD::setOperationSetting('with-javascript-widget', true);
}
```

Calendar operation uses the fields `title`, `start`, `end`, `background_color`, and `text_color` to display the events on the calendar.
You don't need to follow this naming convention, you can map your fields to the calendar fields.
Here is an example of how you'd map your fields to the calendar fields if you're using different names:

```php
// in the EntityCrudController ...
protected function getCalendarFieldsMap(): array
{
    // Map your fields to the calendar fields.
    return [
        'title' => 'title',
        'start' => 'start',
        'end' => 'end',
        'background_color' => 'background_color',
        'text_color' => 'text_color',
        'all_day' => 'all_day',
    ];

    // you only need to map the fields that you use and are different:
    return [
        'title' => 'event_name',
        'start' => 'start_date',
    ];
}
```

If you're just creating the migrations for a new CRUD, we recommend you to use use following settings in order to avoid mapping the fields:

```php
Schema::create('calendar', function (Blueprint $table) {
    $table->id();
    $table->string('title');
    $table->dateTime('start');
    $table->dateTime('end')->nullable(); // optional
    $table->string('background_color')->nullable(); // optional
    $table->string('text_color')->nullable(); // optional
    // ...
    $table->timestamps();
});
```

## Customizing 

### Edit calendar javascript options

Backpack sets some "opinionated" defaults for the calendar, but you can change them by calling `setOperationSetting('javascript-configuration')` on `setupCalendarOperation()`.

```php
public function setupCalendarOperation()
{
    CRUD::setOperationSetting('javascript-configuration', [
        // ... FullCalendar options
        // https://fullcalendar.io/docs
        'dayMaxEvents' => false, // by default backpack uses 5
    ]);
}

```


### Add/Remove menu items to the calendar event menu

Backpack ships with 3 default buttons stored inside the `calendar.line-buttons` setting. These are the default buttons:
- Preview - redirects the user to the event show page
- Edit - redirects the user to the event edit page
- Delete - call the delete event endpoint

The access to those actions are the same as for the CRUD operations, so you can use the same `access` attribute to control the visibility of the buttons.

```php
public function setupCalendarOperation()
{
    // if user is not admin, don't show any of the event buttons
    if(!siberfx_user()->hasRole('admin'))
    {
        CRUD::denyAccess(['delete', 'update', 'show'])
    }

    // to remove the default buttons, you can just clear the setting array:
    CRUD::setOperationSetting('line-buttons', []);

    // ... now add your custom buttons
}
```

If you want to add custom menu items to the calendar event menu, you can do so by calling `addCalendarLineButton()` on `setupCalendarOperation()`.

```php
$this->addCalendarLineButton(
    action: 'email',
    label: 'Send Email',
    group: 'send'
    url: fn($event) => siberfx_url('send-email', ['email' => $event->email]), // $event is the model instance
);
```

As you can see, you can add  a `url` to the button, and it will be used as the `href` attribute of the button. Using a closure we ensure that you have the `$event` instance available to build the URL.

`access` atribute in buttons also support a closure:
```php
    access: fn($event) => siberfx_user()->hasRole('admin'), // only show button for admins
```

### Configure event colors
Apart from saving the event colors directly on the database, you can also use a closure to determine the color based on the event properties.
```php
public function setupCalendarOperation()
{
CRUD::setOperationSetting('background_color', fn($event) => $event->active ? 'green' : 'red');

// same principle applies to text color
CRUD::setOperationSetting('text_color', fn($event) => $event->active ? 'white' : 'black');
}
```

### Using Javascript to handle the menu items
Every time you click on a menu item, a `menuClick` event will be dispatched in Javascript, with the `action` and `properties` of the button. You can listen to this event and do whatever you want with it.

```php
$this->addCalendarLineButton(
    action: 'alert',
    label: 'Javascript Event',
    group: 'alert',
    properties: [
        'message' => 'Alert message!',
    ],
);
```

```javascript
document.getElementById('calendar').addEventListener('menuClick', e => {
  let { action, event, properties } = e.detail;
  if (action === "alert") alert(`Event ${event.id} — ${properties.message}`);
});
```

This will trigger an alert with the message `"Event 1 — Alert message!"`.

## Changelog

Please see the [changelog file](https://backpackforlaravel.com/products/calendar-operation/CHANGELOG.md).

## Support

This is a first-party Siberfx addon. If you're having any problems with it, please open a discussion in our [community forum](https://github.com/Laravel-Backpack/community-forum/discussions).

## Contributing

This is a closed-source package. For bug reports, feature requests and improvement proposals, please open a discussion in our [community forum](https://github.com/Laravel-Backpack/community-forum/discussions).

## Security

If you discover any security related issues, please email info@siberfx.com instead of using the issue tracker.

## Credits

- [Antonio Almeida](https://github.com/promatik)
- [Pedro Martins](https://github.com/pxpm)
- [Cristian Tabacitu](https://github.com/tabacitu)

## License

This project was released under EULA, so you can install it on top of any Siberfx & Laravel project. Please see the [license file](https://backpackforlaravel.com/products/calendar-operation/license.md) for more information. 

[ico-version]: https://img.shields.io/packagist/v/backpack/calendar-operation.svg?style=flat-square
[ico-download]: https://img.shields.io/packagist/dt/backpack/calendar-operation.svg?style=flat-square

[link-packagist]: https://packagist.org/packages/backpack/calendar-operation
[link-calendar]: https://packagist.org/packages/backpack/calendar-operation
[link-author]: https://github.com/laravel-backpack
[link-contributors]: ../../contributors
