marshmallow/filament-fullcalendar

与 Filament 集成的最受欢迎的 JavaScript 日历分支 💛

v1.7.0 2023-03-09 08:46 UTC

This package is auto-updated.

Last update: 2024-08-31 00:37:08 UTC


README

FullCalendar Widget

Latest Version on Packagist GitHub Tests Action Status GitHub Code Style Action Status Total Downloads

特性

  • 接受来自 FullCalendar 的所有配置
  • 事件点击和拖拽事件
  • 创建和编辑事件的模态框 新功能 v1.0

支持 Filament

filament-logo

目录


安装

您可以通过 composer 安装此包

composer require saade/filament-fullcalendar

您可以使用以下命令发布配置文件

php artisan vendor:publish --tag="filament-fullcalendar-config"

用法

由于该包 不会 自动将 FullCalendarWidget 小部件添加到您的 Filament 面板,您可以自由扩展小部件并自行定制。

  1. 首先,创建一个 Filament 小部件
php artisan make:filament-widget CalendarWidget

这将在此项目中创建一个新的 App\Filament\Widgets\CalendarWidget 类。


  1. 您新建的小部件应扩展此包中的 Saade\FilamentFullCalendar\Widgets\FullCalendarWidget

警告

不要忘记从生成的类中删除 protected static string $view

<?php

namespace App\Filament\Widgets;

use Saade\FilamentFullCalendar\Widgets\FullCalendarWidget;

class CalendarWidget extends FullCalendarWidget
{
    /**
     * Return events that should be rendered statically on calendar.
     */
    public function getViewData(): array
    {
        return [
            [
                'id' => 1,
                'title' => 'Breakfast!',
                'start' => now()
            ],
            [
                'id' => 2,
                'title' => 'Meeting with Pamela',
                'start' => now()->addDay(),
                'url' => 'https://some-url.com',
                'shouldOpenInNewTab' => true,
            ]
        ];
    }

    /**
     * FullCalendar will call this function whenever it needs new event data.
     * This is triggered when the user clicks prev/next or switches views on the calendar.
     */
    public function fetchEvents(array $fetchInfo): array
    {
        // You can use $fetchInfo to filter events by date.
        return [];
    }
}

警告

您应该使用 getViewData 来显示初始数据,并使用 fetchEvents 来在翻页时获取新事件。

这两个方法都应该返回一个 EventObject 数组。


配置

这是默认配置文件的正文。

您可以使用 FullCalendar 根对象上的任何属性。请参阅:FullCalendar 文档 了解可用选项。它支持其中大部分。

<?php

/**
 * Consider this file the root configuration object for FullCalendar.
 * Any configuration added here, will be added to the calendar.
 * @see https://fullcalendar.io/docs#toc
 */

return [
    'timeZone' => config('app.timezone'),

    'locale' => config('app.locale'),

    'headerToolbar' => [
        'left'   => 'prev,next today',
        'center' => 'title',
        'right'  => 'dayGridMonth,dayGridWeek,dayGridDay'
    ],

    'navLinks' => true,

    'editable' => true,

    'selectable' => false,

    'dayMaxEvents' => true
];

样式

如果您正在 构建自定义 Filament 主题,则需要额外一步来使日历主题与您的自定义主题匹配。

将此行添加到您的 resources/css/filament.css 文件中(或您正在使用的任何文件)。

@import '../../vendor/saade/filament-fullcalendar/resources/css/filament-fullcalendar.css';

此文件的最终内容应类似于以下内容

@import '../../vendor/filament/forms/dist/module.esm.css';
+ @import '../../vendor/saade/filament-fullcalendar/resources/css/filament-fullcalendar.css';
@import 'tippy.js/dist/tippy.css';

@import 'tailwindcss/base';
@import 'tailwindcss/components';
@import 'tailwindcss/utilities';

监听事件

目前支持的唯一与事件相关的事件是: EventClickEventDrop

它们默认被注释掉,以免 livewire 在未使用它们的情况下发送请求。您可以将它们粘贴到您的 CalendarWidget 类中。见: FiresEvents

v1.0.0 以来,我们使用 onEventClick 来打开编辑模态框。如果您需要挂钩此事件,请确保使用 parent::onEventClick() 调用原始方法,以保持模态框按预期打开。

/**
 * Triggered when the user clicks an event.
 */
public function onEventClick($event): void
{
    parent::onEventClick($event);

    // your code
}

/**
 * Triggered when dragging stops and the event has moved to a different day/time.
 */
public function onEventDrop($newEvent, $oldEvent, $relatedEvents): void
{
    // your code
}

/**
 * Triggered when event's resize stops.
 */
public function onEventResize($event, $oldEvent, $relatedEvents): void
{
    // your code
}

使用模态框创建和编辑事件。

v1.0.0 以来,您可以使用模态框创建和编辑事件。

要自定义模态框,请在此小部件中覆盖以下属性

  • protected string $modalWidth
  • protected string $modalLabel

保存和编辑事件的流程由您决定,因为这个插件不依赖于模型来保存日历事件。

创建事件

事件可以通过两种方式创建。

  • 点击某一天(默认)
  • 选择日期范围(在日历日上点击并拖动)(您需要同意此操作,在配置文件中设置 selectable => true。)

这将打开创建事件模态框。

当创建表单提交时,它将在您的组件上调用 createEvent 函数。请确保将以下代码片段添加到您的日历类中。

public function createEvent(array $data): void
{
    // Create the event with the provided $data.
}

如果默认表单无法满足您的需求,您可以覆盖 getCreateEventFormSchema 并像正常 Filament 表单一样使用它。

protected static function getCreateEventFormSchema(): array
{
    return [
        Forms\Components\TextInput::make('title')
            ->required(),
        Forms\Components\DatePicker::make('start')
            ->required(),
        Forms\Components\DatePicker::make('end')
            ->default(null),
    ];
}

您可以通过覆盖 getCreateEventModalTitle() 方法来更改模态框标题为自定义标题

public function getCreateEventModalTitle(): string 
{
    return __('filament::resources/pages/create-record.title', ['label' => $this->getModalLabel()]);
}

您可以通过覆盖 getCreateEventModalSubmitButtonLabel()getCreateEventModalCloseButtonLabel() 方法来更改模态框按钮标签为自定义标签

public function getCreateEventModalSubmitButtonLabel(): string 
{
    return __('filament::resources/pages/create-record.form.actions.create.label');
}

public function getCreateEventModalCloseButtonLabel(): string 
{
    return __('filament::resources/pages/create-record.form.actions.cancel.label');
}

编辑事件

可以通过在日历上点击事件来编辑事件。

这将打开编辑事件模态框。

当编辑表单提交时,它将在您的组件上调用 editEvent 函数。请确保将以下代码片段添加到您的日历类中。

public function editEvent(array $data): void
{
    // Edit the event with the provided $data.

    /**
     * here you can access to 2 properties to perform update
     * 1. $this->event_id
     * 2. $this->event
    */

    # $this->event_id
    // the value is retrieved from event's id key
    // eg: Appointment::find($this->event);

    # $this->event
    // model instance is resolved by user defined resolveEventRecord() funtion. See example below
    // eg: $this->event->update($data);

}

// Resolve Event record into Model property
public function resolveEventRecord(array $data): Model
{
    // Using Appointment class as example
    return Appointment::find($data['id']);
}

如果默认表单无法满足您的需求,您可以覆盖 getEditEventFormSchema 并像正常 Filament 表单一样使用它。

protected static function getEditEventFormSchema(): array
{
    return [
        Forms\Components\TextInput::make('title')
            ->required(),
        Forms\Components\DatePicker::make('start')
            ->required(),
        Forms\Components\DatePicker::make('end')
            ->default(null),
    ];
}

您可以通过覆盖 getEditEventModalTitle() 方法来更改模态框标题为自定义标题

public function getCreateEventModalTitle(): string 
{
    return __('filament::resources/pages/create-record.title', ['label' => $this->getModalLabel()]);
}

您可以通过覆盖 getEditEventModalSubmitButtonLabel()getEditEventModalCloseButtonLabel() 方法来更改模态框按钮标签为自定义标签

public function getEditEventModalSubmitButtonLabel(): string 
{
    return __('filament::resources/pages/edit-record.form.actions.save.label');
}

public function getEditEventModalCloseButtonLabel(): string 
{
    return $this->editEventForm->isDisabled()
        ? __('filament-support::actions/view.single.modal.actions.close.label')
        : __('filament::resources/pages/edit-record.form.actions.cancel.label');
}

授权操作

如果您想授权 view 操作,您可以覆盖此包附带的自定义授权方法。

public static function canView(?array $event = null): bool
{
    // When event is null, MAKE SURE you allow View otherwise the entire widget/calendar won't be rendered
    if ($event === null) {
        return true;
    }
    
    // Returning 'false' will not show the event Modal.
    return true;
}

如果您想授权 editcreate 操作,您可以覆盖此包附带的自定义授权方法。

public static function canCreate(): bool
{
    // Returning 'false' will remove the 'Create' button on the calendar.
    return true;
}

public static function canEdit(?array $event = null): bool
{
    // Returning 'false' will disable the edit modal when clicking on a event.
    return true;
}

如果您想禁用所有操作或将日历保持为 v1.0.0 的原始状态,您可以为所有上述方法返回 false,或使用方便的关心 CantManageEvents。这将禁用所有日历模态框。

class CalendarWidget extends FullCalendarWidget
{
    use CantManageEvents;

    // ...
}

监听取消模态框

如果您想了解模态框何时被取消,您可以向您的组件 $listener 数组添加以下 Livewire 事件

    protected $listeners = [
        'cancelledFullcalendarCreateEventModal' => 'onCreateEventCancelled',
        'cancelledFullcalendarEditEventModal' => 'onEditEventCancelled',
    ];

刷新日历事件

如果您想刷新日历事件,您可以在您的组件类中调用 $this->refreshEvents()。这将调用 getViewData() 并重新渲染日历上的事件。

public function yourMethod(): void
{
    $this->refreshEvents();
}

根据日历视图过滤事件

如果您想根据当前在日历中显示的天数来筛选事件,您可以从 CanFetchEvents 特性实现 fetchInfo() 方法。将以下代码添加到您的日历组件

/**
 * FullCalendar will call this function whenever it needs new event data.
 * This is triggered when the user clicks prev/next or switches views.
 *
 * @see https://fullcalendar.io/docs/events-function
 * @param array $fetchInfo start and end date of the current view
 */
public function fetchEvents(array $fetchInfo): array
{
    return [];
}

您可以根据时间段 $fetchInfo['start']$fetchInfo['end'] 过滤事件。

示例

public function fetchEvents(array $fetchInfo): array
{
    $schedules = Appointment::query()
        ->where([
            ['start_at', '>=', $fetchInfo['start']],
            ['end_at', '<', $fetchInfo['end']],
        ])
        ->get();

    $data = $schedules->map( ... );

    return $data;
}

测试

composer test

变更日志

有关最近更改的更多信息,请参阅 变更日志

贡献

有关详细信息,请参阅 贡献指南

安全漏洞

有关如何报告安全漏洞的更多信息,请参阅 我们的安全策略

鸣谢

许可

MIT 许可证(MIT)。有关更多信息,请参阅 许可文件