Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

Appearance.php 6.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. <?php
  2. namespace App\Filament\Company\Pages\Setting;
  3. use App\Enums\Font;
  4. use App\Enums\MaxContentWidth;
  5. use App\Enums\ModalWidth;
  6. use App\Enums\PrimaryColor;
  7. use App\Enums\RecordsPerPage;
  8. use App\Enums\TableSortDirection;
  9. use App\Models\Setting\Appearance as AppearanceModel;
  10. use Filament\Actions\Action;
  11. use Filament\Actions\ActionGroup;
  12. use Filament\Forms\Components\Component;
  13. use Filament\Forms\Components\Section;
  14. use Filament\Forms\Components\Select;
  15. use Filament\Forms\Form;
  16. use Filament\Notifications\Notification;
  17. use Filament\Pages\Concerns\InteractsWithFormActions;
  18. use Filament\Pages\Page;
  19. use Filament\Support\Exceptions\Halt;
  20. use Illuminate\Auth\Access\AuthorizationException;
  21. use Illuminate\Contracts\Support\Htmlable;
  22. use Illuminate\Database\Eloquent\Model;
  23. use Livewire\Attributes\Locked;
  24. use Wallo\FilamentSelectify\Components\ToggleButton;
  25. use function Filament\authorize;
  26. /**
  27. * @property Form $form
  28. */
  29. class Appearance extends Page
  30. {
  31. use InteractsWithFormActions;
  32. protected static ?string $navigationIcon = 'heroicon-o-paint-brush';
  33. protected static ?string $title = 'Appearance';
  34. protected static ?string $navigationGroup = 'Settings';
  35. protected static ?string $slug = 'settings/appearance';
  36. protected static string $view = 'filament.company.pages.setting.appearance';
  37. public ?array $data = [];
  38. #[Locked]
  39. public ?AppearanceModel $record = null;
  40. public function getTitle(): string | Htmlable
  41. {
  42. return translate(static::$title);
  43. }
  44. public static function getNavigationLabel(): string
  45. {
  46. return translate(static::$title);
  47. }
  48. public function mount(): void
  49. {
  50. $this->record = AppearanceModel::firstOrNew([
  51. 'company_id' => auth()->user()->currentCompany->id,
  52. ]);
  53. abort_unless(static::canView($this->record), 404);
  54. $this->fillForm();
  55. }
  56. public function fillForm(): void
  57. {
  58. $data = $this->record->attributesToArray();
  59. $this->form->fill($data);
  60. }
  61. public function save(): void
  62. {
  63. try {
  64. $data = $this->form->getState();
  65. $this->handleRecordUpdate($this->record, $data);
  66. } catch (Halt $exception) {
  67. return;
  68. }
  69. $this->getSavedNotification()->send();
  70. }
  71. protected function getSavedNotification(): Notification
  72. {
  73. return Notification::make()
  74. ->success()
  75. ->title(__('filament-panels::resources/pages/edit-record.notifications.saved.title'));
  76. }
  77. public function form(Form $form): Form
  78. {
  79. return $form
  80. ->schema([
  81. $this->getGeneralSection(),
  82. $this->getLayoutSection(),
  83. $this->getDataPresentationSection(),
  84. ])
  85. ->model($this->record)
  86. ->statePath('data')
  87. ->operation('edit');
  88. }
  89. protected function getGeneralSection(): Component
  90. {
  91. return Section::make('General')
  92. ->schema([
  93. Select::make('primary_color')
  94. ->allowHtml()
  95. ->softRequired()
  96. ->localizeLabel()
  97. ->options(
  98. collect(PrimaryColor::cases())
  99. ->mapWithKeys(static fn ($case) => [
  100. $case->value => "<span class='flex items-center gap-x-4'>
  101. <span class='rounded-full w-4 h-4' style='background:rgb(" . $case->getColor()[600] . ")'></span>
  102. <span>" . $case->getLabel() . '</span>
  103. </span>',
  104. ]),
  105. ),
  106. Select::make('font')
  107. ->allowHtml()
  108. ->softRequired()
  109. ->localizeLabel()
  110. ->options(
  111. collect(Font::cases())
  112. ->mapWithKeys(static fn ($case) => [
  113. $case->value => "<span style='font-family:{$case->getLabel()}'>{$case->getLabel()}</span>",
  114. ]),
  115. ),
  116. ])->columns();
  117. }
  118. protected function getLayoutSection(): Component
  119. {
  120. return Section::make('Layout')
  121. ->schema([
  122. Select::make('max_content_width')
  123. ->softRequired()
  124. ->localizeLabel()
  125. ->options(MaxContentWidth::class),
  126. Select::make('modal_width')
  127. ->softRequired()
  128. ->localizeLabel()
  129. ->options(ModalWidth::class),
  130. Select::make('has_top_navigation')
  131. ->localizeLabel('Navigation Layout')
  132. ->selectablePlaceholder(false)
  133. ->boolean(translate('Top Navigation'), translate('Side Navigation')),
  134. ToggleButton::make('is_table_striped')
  135. ->localizeLabel('Striped Tables')
  136. ->onLabel(translate('Enabled'))
  137. ->offLabel(translate('Disabled')),
  138. ])->columns();
  139. }
  140. protected function getDataPresentationSection(): Component
  141. {
  142. return Section::make('Data Presentation')
  143. ->schema([
  144. Select::make('table_sort_direction')
  145. ->softRequired()
  146. ->localizeLabel()
  147. ->options(TableSortDirection::class),
  148. Select::make('records_per_page')
  149. ->softRequired()
  150. ->localizeLabel()
  151. ->options(RecordsPerPage::class),
  152. ])->columns();
  153. }
  154. protected function handleRecordUpdate(AppearanceModel $record, array $data): AppearanceModel
  155. {
  156. $record->fill($data);
  157. $keysToWatch = [
  158. 'primary_color',
  159. 'max_content_width',
  160. 'has_top_navigation',
  161. 'font',
  162. ];
  163. if ($record->isDirty($keysToWatch)) {
  164. $this->dispatch('appearanceUpdated');
  165. }
  166. $record->save();
  167. return $record;
  168. }
  169. /**
  170. * @return array<Action | ActionGroup>
  171. */
  172. protected function getFormActions(): array
  173. {
  174. return [
  175. $this->getSaveFormAction(),
  176. ];
  177. }
  178. protected function getSaveFormAction(): Action
  179. {
  180. return Action::make('save')
  181. ->label(__('filament-panels::resources/pages/edit-record.form.actions.save.label'))
  182. ->submit('save')
  183. ->keyBindings(['mod+s']);
  184. }
  185. public static function canView(Model $record): bool
  186. {
  187. try {
  188. return authorize('update', $record)->allowed();
  189. } catch (AuthorizationException $exception) {
  190. return $exception->toResponse()->allowed();
  191. }
  192. }
  193. }