diff --git a/docs/getting-started/configuration.md b/docs/getting-started/configuration.md index 2c1714d4..91afc415 100644 --- a/docs/getting-started/configuration.md +++ b/docs/getting-started/configuration.md @@ -59,6 +59,7 @@ available resources: - CategoryResource, - CollectionResource, - FormResource, +- ResponseResource, ## Frontend Configuration diff --git a/resources/lang/ckb.json b/resources/lang/ckb.json index c47b44ec..20cafd3e 100644 --- a/resources/lang/ckb.json +++ b/resources/lang/ckb.json @@ -180,7 +180,7 @@ "Conditional Visibility" :"بینینی مەرجدار", "show when the field:" :"نیشان بدە کەی بەشەکە:", "has the value:" :"بەهای هەیە:", - "Embed" :"جێگیرکردن", + "Embed" :"جێگیرکردن:", "Hint Text" :"دەقی ئاماژە", "Hint Icon" :"ئایکۆنی ئاماژە", "Hint Color" :"ڕەنگی ئاماژە", diff --git a/resources/lang/de.json b/resources/lang/de.json index a4e840de..d971d4c2 100644 --- a/resources/lang/de.json +++ b/resources/lang/de.json @@ -180,7 +180,7 @@ "Conditional Visibility" :"Conditional Visibility", "show when the field:" :"show when the field:", "has the value:" :"has the value:", - "Embed" :"Embed", + "Embed" :"Embed:", "Hint Text" :"Hint Text", "Hint Icon" :"Hint Icon", "Hint Color" :"Hint Color", diff --git a/resources/lang/en.json b/resources/lang/en.json index 00ade997..49b4897f 100644 --- a/resources/lang/en.json +++ b/resources/lang/en.json @@ -180,7 +180,7 @@ "Conditional Visibility" :"Conditional Visibility", "show when the field:" :"show when the field:", "has the value:" :"has the value:", - "Embed" :"Embed", + "Embed" :"Embed:", "Hint Text" :"Hint Text", "Hint Icon" :"Hint Icon", "Hint Color" :"Hint Color", diff --git a/resources/lang/fr.json b/resources/lang/fr.json index 40afb82f..e15de8ae 100644 --- a/resources/lang/fr.json +++ b/resources/lang/fr.json @@ -180,7 +180,7 @@ "Conditional Visibility" :"Conditional Visibility", "show when the field:" :"show when the field:", "has the value:" :"has the value:", - "Embed" :"Embed", + "Embed" :"Embed:", "Hint Text" :"Hint Text", "Hint Icon" :"Hint Icon", "Hint Color" :"Hint Color", diff --git a/resources/views/filament/resources/response-resource/pages/browse-entry.blade.php b/resources/views/filament/resources/response-resource/pages/browse-entry.blade.php deleted file mode 100644 index 6021c134..00000000 --- a/resources/views/filament/resources/response-resource/pages/browse-entry.blade.php +++ /dev/null @@ -1,73 +0,0 @@ -
- @php - $getRecord = $getRecord(); - @endphp -
-
- - @foreach($getRecord->fieldsResponses as $resp) - @if($resp->field !== null) -
-

{{ $resp->field->name ?? '' }}

-

- {!! ( new $resp->field->type )->getResponse($resp->field, $resp) !!} -

-
-
- @endif - @endforeach -
-
-
- - - {{ __('User Details') }} - - @if($getRecord->user_id === null) - {{ __('By') }} {{ __('Visitor') }} - @else -
- -

- {{ ($getRecord->user->name) ?? '' }} - {{ ($getRecord->user->email) ?? '' }} -

-
- @endif -

- {{ __('created at') }}: - {{ $getRecord->created_at->format('Y.m/d') }}-{{ $getRecord->created_at->format('h:i a') }} -

-
- - -

{{ __('Entry Details') }}

-
- -
- {{ __('Form') }}: - {{ $getRecord->form->name ?? '' }} -
- -
- {{ __('status') }} - @php $getStatues = $getRecord->statusDetails() @endphp - - @svg($getStatues['icon'],'w-4 h-4 inline') - {{ $getStatues['label'] }} - -
- -
- {{ __('Notes') }}: - {!! nl2br($getRecord->notes) !!} -
-
-
-
-
diff --git a/resources/views/filament/resources/response-resource/pages/show-entry.blade.php b/resources/views/filament/resources/response-resource/pages/show-entry.blade.php index 32b6d46b..454c3ec6 100644 --- a/resources/views/filament/resources/response-resource/pages/show-entry.blade.php +++ b/resources/views/filament/resources/response-resource/pages/show-entry.blade.php @@ -1,9 +1,9 @@ - -
-
-
- - @foreach($response->fieldsResponses as $resp) +
+
+
+ +
+ @foreach($getRecord()->fieldsResponses as $resp) @if($resp->field !== null)

{{ $resp->field->name ?? '' }}

@@ -14,59 +14,72 @@
@endif @endforeach - -
-
- - - {{ __('User Details') }} - - @if($response->user_id === null) - {{ __('By') }} {{ __('Visitor') }} - @else -
- -

- {{ ($response->user->name) ?? '' }} - {{ ($response->user->email) ?? '' }} -

-
- @endif -

- {{ __('created at') }}: - {{ $response->created_at->format('Y.m/d') }}-{{ $response->created_at->format('h:i a') }} -

-
- - -

{{ __('Entry Details') }}

-
- -
- {{ __('Form') }}: - {{ $response->form->name ?? '' }} +
+
+
+
+ @if(isset($this->table)) + + @endif + + + {{ __('User Details') }} + + @if($getRecord()->user_id === null) + {{ __('By') }} {{ __('Visitor') }} + @else +
+ +

+ {{ ($getRecord()->user->name) ?? '' }} + {{ ($getRecord()->user->email) ?? '' }} +

+ @endif +

+ {{ __('created at') }}: + {{ $getRecord()->created_at->format('Y.m/d') }}-{{ $getRecord()->created_at->format('h:i a') }} +

+
+
+
+ + +

{{ __('Entry Details') }}

+
+ +
+ {{ __('Form') }}: + {{ $getRecord()->form->name ?? '' }} +
-
- {{ __('status') }} - @php $getStatues = $response->statusDetails() @endphp +
+ {{ __('status') }} + @php $getStatues = $getRecord()->statusDetails() @endphp - @svg($getStatues['icon'],'w-4 h-4 inline') + @svg($getStatues['icon'],'w-4 h-4 inline') {{ $getStatues['label'] }} - -
+ +
-
- {{ __('Notes') }}: - {!! nl2br($response->notes) !!} -
-
+
+ {{ __('Notes') }}: + {!! nl2br($getRecord()->notes) !!} +
+ + +
- \ No newline at end of file +
diff --git a/resources/views/themes/zeus/bolt/fill-forms.blade.php b/resources/views/themes/zeus/bolt/fill-forms.blade.php index 431992e4..f847c05d 100644 --- a/resources/views/themes/zeus/bolt/fill-forms.blade.php +++ b/resources/views/themes/zeus/bolt/fill-forms.blade.php @@ -8,27 +8,27 @@ @include($boltTheme.'.loading') - @if(class_exists(\LaraZeus\BoltPro\BoltProServiceProvider::class) && optional($zeusForm->options)['logo'] !== null && optional($zeusForm)->options['cover'] !== null) + @if(class_exists(\LaraZeus\Bolt\BoltProServiceProvider::class) && optional($zeusForm->options)['logo'] !== null && optional($zeusForm)->options['cover'] !== null)
logo
-

+

{{ $zeusForm->name ?? '' }}

@if(filled($zeusForm->description)) -
+
{{ $zeusForm->description ?? '' }}
@endif @if($zeusForm->start_date !== null) -
+
@svg('heroicon-o-calendar','h-5 w-5 inline-flex') {{ __('Available from') }}: @@ -43,7 +43,7 @@ class="bg-white rounded-full shadow-md shadow-custom-100 sm:w-24 object-cover" @endif @if(!$inline) - @if(!class_exists(\LaraZeus\BoltPro\BoltProServiceProvider::class) || (optional($zeusForm->options)['logo'] === null && optional($zeusForm->options)['cover'] === null)) + @if(!class_exists(\LaraZeus\Bolt\BoltProServiceProvider::class) || (optional($zeusForm->options)['logo'] === null && optional($zeusForm->options)['cover'] === null))

{{ $zeusForm->name ?? '' }}

{{ $zeusForm->description ?? '' }}

diff --git a/src/BoltPlugin.php b/src/BoltPlugin.php index ae4169a3..f15edda7 100644 --- a/src/BoltPlugin.php +++ b/src/BoltPlugin.php @@ -8,6 +8,7 @@ use LaraZeus\Bolt\Filament\Resources\CategoryResource; use LaraZeus\Bolt\Filament\Resources\CollectionResource; use LaraZeus\Bolt\Filament\Resources\FormResource; +use LaraZeus\Bolt\Filament\Resources\ResponseResource; final class BoltPlugin implements Plugin { @@ -25,6 +26,7 @@ public function register(Panel $panel): void ->resources([ CollectionResource::class, FormResource::class, + ResponseResource::class, CategoryResource::class, ]); } diff --git a/src/Concerns/EntriesAction.php b/src/Concerns/EntriesAction.php new file mode 100644 index 00000000..8c2dfb85 --- /dev/null +++ b/src/Concerns/EntriesAction.php @@ -0,0 +1,44 @@ +form_id; + + return [ + ActionGroup::make([ + Action::make('brows') + ->icon('heroicon-o-eye') + ->visible($formId !== 0) + ->label(__('Brows Entries')) + ->url(fn (): string => ResponseResource::getUrl('brows') . '?form_id=' . $formId), + Action::make('list') + ->icon('heroicon-o-bars-4') + ->visible($formId !== 0) + ->label(__('List Entries')) + ->url(fn (): string => ResponseResource::getUrl() . '?form_id=' . $formId), + Action::make('report') + ->icon('heroicon-o-document-chart-bar') + ->visible($formId !== 0) + ->label(__('Entries Report')) + ->url(fn (): string => ResponseResource::getUrl('report') . '?form_id=' . $formId), + ]) + ->button() + ->color('info') + ->label(__('Entries')) + ->tooltip(__('view all entries')) + ->icon('clarity-data-cluster-line') + ->tooltip(__('view all entries')), + ]; + } +} diff --git a/src/Concerns/Schemata.php b/src/Concerns/Schemata.php index c03fb3b2..78e1b688 100644 --- a/src/Concerns/Schemata.php +++ b/src/Concerns/Schemata.php @@ -225,10 +225,10 @@ public static function getTabsSchema(): array Tabs\Tab::make('design') ->label(__('Design')) - ->visible(class_exists(\LaraZeus\BoltPro\BoltProServiceProvider::class) && config('zeus-bolt.allow_design')) + ->visible(fn ( + ): bool => class_exists(\LaraZeus\BoltPro\BoltProServiceProvider::class) && config('zeus-bolt.allow_design')) ->schema([ ViewField::make('options.primary_color') - ->hiddenLabel() ->view('zeus::filament.components.color-picker'), FileUpload::make('options.logo') ->disk(config('zeus-bolt.uploadDisk')) diff --git a/src/Filament/Resources/FormResource.php b/src/Filament/Resources/FormResource.php index 31a3c168..1418baa7 100644 --- a/src/Filament/Resources/FormResource.php +++ b/src/Filament/Resources/FormResource.php @@ -8,8 +8,6 @@ use Filament\Infolists\Components\Section; use Filament\Infolists\Components\TextEntry; use Filament\Infolists\Infolist; -use Filament\Pages\SubNavigationPosition; -use Filament\Resources\Pages\Page; use Filament\Tables\Actions\Action; use Filament\Tables\Actions\ActionGroup; use Filament\Tables\Actions\DeleteAction; @@ -33,6 +31,7 @@ use LaraZeus\Bolt\Concerns\Schemata; use LaraZeus\Bolt\Filament\Actions\ReplicateFormAction; use LaraZeus\Bolt\Filament\Resources\FormResource\Pages; +use LaraZeus\Bolt\Filament\Resources\ResponseResource\Pages\ListResponses; use LaraZeus\Bolt\Models\Form as ZeusForm; class FormResource extends BoltResource @@ -48,8 +47,6 @@ class FormResource extends BoltResource protected static Closure | array | null $boltFormSchema = null; - protected static SubNavigationPosition $subNavigationPosition = SubNavigationPosition::Top; - public static function getModel(): string { return BoltPlugin::getModel('Form'); @@ -92,6 +89,7 @@ public static function infolist(Infolist $infolist): Infolist TextEntry::make('description'), IconEntry::make('is_active') ->icon(fn (string $state): string => match ($state) { + '1' => 'clarity-check-circle-line', '0' => 'clarity-times-circle-solid', default => 'clarity-check-circle-line', }) @@ -123,9 +121,6 @@ public static function getBoltFormSchemaUsing(array | Closure | null $form): voi static::$boltFormSchema = $form; } - /** - * @throws \Exception - */ public static function table(Table $table): Table { return $table @@ -179,9 +174,6 @@ public static function getPages(): array 'create' => Pages\CreateForm::route('/create'), 'edit' => Pages\EditForm::route('/{record}/edit'), 'view' => Pages\ViewForm::route('/{record}'), - 'report' => Pages\ManageResponses::route('/{record}/report'), - 'browse' => Pages\BrowseResponses::route('/{record}/browse'), - 'viewResponse' => Pages\ViewResponse::route('/{record}/response/{responseID}'), ]; if (class_exists(\LaraZeus\BoltPro\BoltProServiceProvider::class)) { @@ -214,52 +206,30 @@ public static function getActions(): array $action = [ ViewAction::make(), EditAction::make('edit'), + Action::make('entries') + ->color('info') + ->label(__('Entries')) + ->icon('clarity-data-cluster-line') + ->tooltip(__('view all entries')) + ->url(fn (ZeusForm $record): string => ListResponses::getUrl(['form_id' => $record->id])), + Action::make('prefilledLink') + ->label(__('Prefilled Link')) + ->icon('heroicon-o-link') + ->tooltip(__('Get Prefilled Link')) + ->visible(class_exists(\LaraZeus\BoltPro\BoltProServiceProvider::class)) + ->url(fn (ZeusForm $record): string => FormResource::getUrl('prefilled', [$record])), ReplicateFormAction::make(), - RestoreAction::make(), DeleteAction::make(), ForceDeleteAction::make(), - - ActionGroup::make([ - Action::make('entries') - ->color('warning') - ->label(__('Entries')) - ->icon('clarity-data-cluster-line') - ->tooltip(__('view all entries')) - ->url(fn (ZeusForm $record): string => url('admin/responses?form_id=' . $record->id)), - ]) - ->dropdown(false), + RestoreAction::make(), ]; - $advancedActions = $moreActions = []; - - if (class_exists(\LaraZeus\BoltPro\BoltProServiceProvider::class)) { - $advancedActions[] = Action::make('prefilledLink') - ->label(__('Prefilled Link')) - ->icon('iconpark-formone-o') - ->tooltip(__('Get Prefilled Link')) - ->visible(class_exists(\LaraZeus\BoltPro\BoltProServiceProvider::class)) - ->url(fn (ZeusForm $record): string => FormResource::getUrl('prefilled', [$record])); - } - if (class_exists(\LaraZeus\Helen\HelenServiceProvider::class)) { //@phpstan-ignore-next-line - $advancedActions[] = \LaraZeus\Helen\Actions\ShortUrlAction::make('get-link') - ->label(__('Short Link')) + $action[] = \LaraZeus\Helen\Actions\ShortUrlAction::make('get-link') ->distUrl(fn (ZeusForm $record) => route('bolt.form.show', $record)); } - $moreActions[] = ActionGroup::make($advancedActions)->dropdown(false); - - return [ActionGroup::make(array_merge($action, $moreActions))]; - } - - public static function getRecordSubNavigation(Page $page): array - { - return $page->generateNavigationItems([ - Pages\ViewForm::class, - Pages\EditForm::class, - Pages\ManageResponses::class, - Pages\BrowseResponses::class, - ]); + return [ActionGroup::make($action)]; } } diff --git a/src/Filament/Resources/FormResource/Pages/BrowseResponses.php b/src/Filament/Resources/FormResource/Pages/BrowseResponses.php deleted file mode 100644 index a4eaf764..00000000 --- a/src/Filament/Resources/FormResource/Pages/BrowseResponses.php +++ /dev/null @@ -1,58 +0,0 @@ -paginated([1]) - ->recordClasses('!bg-gray-50') - ->query(BoltPlugin::getModel('Response')::query()->where('form_id', $this->record->id)) - ->columns([ - ViewColumn::make('response') - ->label(__('Browse Entries')) - ->view('zeus::filament.resources.response-resource.pages.browse-entry'), - ]) - ->actions([ - SetResponseStatus::make(), - ], position: ActionsPosition::AfterContent) - ->filters([ - SelectFilter::make('status') - ->options(BoltPlugin::getModel('FormsStatus')::query()->pluck('label', 'key')) - ->label(__('Status')), - ]); - } - - public static function getNavigationLabel(): string - { - return __('Browse Entries'); - } - - public function getTitle(): string - { - return __('Browse Entries'); - } -} diff --git a/src/Filament/Resources/FormResource/Pages/EditForm.php b/src/Filament/Resources/FormResource/Pages/EditForm.php index 219c0ea1..09ca8826 100644 --- a/src/Filament/Resources/FormResource/Pages/EditForm.php +++ b/src/Filament/Resources/FormResource/Pages/EditForm.php @@ -5,6 +5,7 @@ use Filament\Actions\Action; use Filament\Actions\LocaleSwitcher; use Filament\Resources\Pages\EditRecord; +use LaraZeus\Bolt\Concerns\EntriesAction; use LaraZeus\Bolt\Filament\Resources\FormResource; use LaraZeus\Bolt\Models\Form; @@ -14,6 +15,7 @@ class EditForm extends EditRecord { use EditRecord\Concerns\Translatable; + use EntriesAction; protected static string $resource = FormResource::class; @@ -21,6 +23,7 @@ protected function getHeaderActions(): array { return [ LocaleSwitcher::make(), + ...$this->getEntriesActions($this->record->id), Action::make('open') ->label(__('Open')) ->icon('heroicon-o-arrow-top-right-on-square') diff --git a/src/Filament/Resources/FormResource/Pages/ViewForm.php b/src/Filament/Resources/FormResource/Pages/ViewForm.php index bfdf0e59..441d3194 100644 --- a/src/Filament/Resources/FormResource/Pages/ViewForm.php +++ b/src/Filament/Resources/FormResource/Pages/ViewForm.php @@ -3,8 +3,10 @@ namespace LaraZeus\Bolt\Filament\Resources\FormResource\Pages; use Filament\Actions\Action; +use Filament\Actions\EditAction; use Filament\Actions\LocaleSwitcher; use Filament\Resources\Pages\ViewRecord; +use LaraZeus\Bolt\Concerns\EntriesAction; use LaraZeus\Bolt\Filament\Resources\FormResource; use LaraZeus\Bolt\Models\Form; @@ -13,6 +15,7 @@ */ class ViewForm extends ViewRecord { + use EntriesAction; use ViewRecord\Concerns\Translatable; protected static string $resource = FormResource::class; @@ -21,6 +24,8 @@ protected function getHeaderActions(): array { return [ LocaleSwitcher::make(), + EditAction::make(), + ...$this->getEntriesActions($this->record->id), Action::make('open') ->label(__('Open')) ->icon('heroicon-o-arrow-top-right-on-square') diff --git a/src/Filament/Resources/FormResource/Pages/ViewResponse.php b/src/Filament/Resources/FormResource/Pages/ViewResponse.php deleted file mode 100644 index bc0d6c1f..00000000 --- a/src/Filament/Resources/FormResource/Pages/ViewResponse.php +++ /dev/null @@ -1,77 +0,0 @@ -response = Response::find($this->responseID); - static::authorizeResourceAccess(); - } - - protected function getHeaderActions(): array - { - return [ - Action::make('set-status') - ->visible(function (): bool { - return $this->response->form->extensions === null; - }) - ->label(__('Set Status')) - ->icon('heroicon-o-tag') - ->form([ - Select::make('status') - ->label(__('status')) - ->default(fn () => $this->response->status) - ->options(BoltPlugin::getModel('FormsStatus')::query()->pluck('label', 'key')) - ->required(), - Textarea::make('notes') - ->default(fn () => $this->response->notes) - ->label(__('Notes')), - ]) - ->action(function (array $data): void { - $this->response->status = $data['status']; - $this->response->notes = $data['notes']; - $this->response->save(); - }), - ]; - } - - public function getTitle(): string | Htmlable - { - return __('view response #') . $this->response->id; - } - - public function getBreadcrumbs(): array - { - return [ - FormResource::getUrl() => FormResource::getBreadcrumb(), - FormResource::getUrl('view', ['record' => $this->record->slug]) => $this->record->name, - FormResource::getUrl('report', ['record' => $this->record->slug]) => __('Entries Report'), - __('view the entry'), - ]; - } -} diff --git a/src/Filament/Resources/ResponseResource.php b/src/Filament/Resources/ResponseResource.php new file mode 100644 index 00000000..bf5cba55 --- /dev/null +++ b/src/Filament/Resources/ResponseResource.php @@ -0,0 +1,137 @@ +count(); + } + + public static function getModelLabel(): string + { + return __('Entries'); + } + + public static function getPluralModelLabel(): string + { + return __('Entries'); + } + + public static function getNavigationLabel(): string + { + return __('Entries'); + } + + public static function form(Form $form): Form + { + return $form + ->schema([ + ViewField::make('response') + ->view('zeus::filament.resources.response-resource.components.view-responses') + ->label('') + ->columnSpan(2), + ]); + } + + public static function table(Table $table): Table + { + return $table + ->columns([ + Split::make([ + ImageColumn::make('user.avatar') + ->circular() + ->grow(false) + ->label(__('Avatar')), + Stack::make([ + TextColumn::make('user.name') + ->label(__('User Name')) + ->searchable(), + TextColumn::make('user.email') + ->searchable() + ->label(__('User Email')) + ->wrap() + ->extraAttributes(['class' => 'text-gray-400']) + ->size('sm') + ->weight('medium') + ->icon('heroicon-s-envelope'), + ]), + ]), + TextColumn::make('form.name') + ->label(__('form')) + ->searchable() + ->visible(! request()->filled('form_id')), + Stack::make([ + TextColumn::make('created_at')->label(__('Created Date'))->dateTime()->sortable()->searchable(), + TextColumn::make('status') + ->badge() + ->label(__('status')) + ->colors(BoltPlugin::getModel('FormsStatus')::pluck('key', 'color')->toArray()) + ->icons(BoltPlugin::getModel('FormsStatus')::pluck('key', 'icon')->toArray()) + ->grow(false) + ->searchable('status'), + TextColumn::make('notes')->label(__('Notes'))->searchable(), + ]), + ]) + ->contentGrid([ + 'md' => 2, + 'xl' => 3, + ]) + ->modifyQueryUsing(function (Builder $query, Table $table) { + //@phpstan-ignore-next-line + return $query->where('form_id', $table->getLivewire()->form_id); + }) + ->defaultSort('created_at', 'description') + ->actions([ + ViewAction::make(), + SetResponseStatus::make(), + ]) + ->filters([ + SelectFilter::make('status') + ->options(BoltPlugin::getModel('FormsStatus')::query()->pluck('label', 'key')) + ->label(__('Status')), + ]); + } + + public static function getPages(): array + { + return [ + 'brows' => Pages\BrowseResponses::route('/brows'), + 'report' => Pages\ReportResponses::route('/report'), + 'index' => Pages\ListResponses::route('/'), + 'view' => Pages\ViewResponse::route('/{record}'), + ]; + } +} diff --git a/src/Filament/Resources/ResponseResource/Pages/BrowseResponses.php b/src/Filament/Resources/ResponseResource/Pages/BrowseResponses.php new file mode 100644 index 00000000..e7c291e1 --- /dev/null +++ b/src/Filament/Resources/ResponseResource/Pages/BrowseResponses.php @@ -0,0 +1,73 @@ +paginated([1]) + ->recordClasses('bg-gray-100') + ->query(BoltPlugin::getModel('Response')::query()->where('form_id', $this->form_id)) + ->columns([ + Tables\Columns\ViewColumn::make('response') + ->label(__('Browse Entries')) + ->view('zeus::filament.resources.response-resource.pages.show-entry'), + ]) + ->actions([ + SetResponseStatus::make(), + ], position: Tables\Enums\ActionsPosition::AfterContent) + ->filters([ + SelectFilter::make('status') + ->options(BoltPlugin::getModel('FormsStatus')::query()->pluck('label', 'key')) + ->label(__('Status')), + ]); + } + + protected function getHeaderActions(): array + { + return $this->getEntriesActions(); + } + + public function getBreadcrumbs(): array + { + $form = BoltPlugin::getModel('Form')::findOrFail($this->form_id); + $breadcrumb = $this->getBreadcrumb(); + + return [ + FormResource::getUrl() => FormResource::getBreadcrumb(), + FormResource::getUrl('view', ['record' => $form->slug]) => $form->name, + ...(filled($breadcrumb) ? [$breadcrumb] : []), + ]; + } +} diff --git a/src/Filament/Resources/ResponseResource/Pages/ListResponses.php b/src/Filament/Resources/ResponseResource/Pages/ListResponses.php new file mode 100644 index 00000000..19ba7a27 --- /dev/null +++ b/src/Filament/Resources/ResponseResource/Pages/ListResponses.php @@ -0,0 +1,42 @@ +getEntriesActions(); + } + + public function getHeading(): string | Htmlable + { + return __('List Entries'); + } + + public function getBreadcrumbs(): array + { + $form = BoltPlugin::getModel('Form')::find($this->form_id); + abort_if($form === null, 404); + + return [ + FormResource::getUrl() => FormResource::getBreadcrumb(), + FormResource::getUrl('view', ['record' => $form->slug]) => $form->name, + '#' => __('List Entries'), + ]; + } +} diff --git a/src/Filament/Resources/FormResource/Pages/ManageResponses.php b/src/Filament/Resources/ResponseResource/Pages/ReportResponses.php similarity index 55% rename from src/Filament/Resources/FormResource/Pages/ManageResponses.php rename to src/Filament/Resources/ResponseResource/Pages/ReportResponses.php index c5f928dd..4e42b7a5 100644 --- a/src/Filament/Resources/FormResource/Pages/ManageResponses.php +++ b/src/Filament/Resources/ResponseResource/Pages/ReportResponses.php @@ -1,32 +1,44 @@ label(__('Avatar')) ->circular() ->toggleable(), - TextColumn::make('user.name') ->label(__('Name')) ->toggleable() ->sortable() ->default(__('guest')) ->searchable(), - TextColumn::make('status') ->toggleable() ->sortable() ->badge() - ->label(__('status')) + ->label(__('response status')) ->colors(BoltPlugin::getModel('FormsStatus')::pluck('key', 'color')->toArray()) ->icons(BoltPlugin::getModel('FormsStatus')::pluck('key', 'icon')->toArray()) ->grow(false) @@ -56,14 +66,13 @@ public function table(Table $table): Table TextColumn::make('notes') ->label(__('notes')) ->sortable() - ->searchable() ->toggleable(), ]; /** * @var Field $field. */ - foreach ($this->record->fields->sortBy('ordering') as $field) { + foreach ($this->form->fields->sortBy('ordering') as $field) { $getFieldTableColumn = (new $field->type)->TableColumn($field); if ($getFieldTableColumn !== null) { @@ -73,7 +82,6 @@ public function table(Table $table): Table $mainColumns[] = TextColumn::make('created_at') ->sortable() - ->searchable() ->dateTime() ->label(__('created at')) ->toggleable(); @@ -81,49 +89,64 @@ public function table(Table $table): Table return $table ->query( BoltPlugin::getModel('Response')::query() - ->where('form_id', $this->record->id) + ->where('form_id', $this->form_id) ->with(['fieldsResponses']) - ->withoutGlobalScopes([ - SoftDeletingScope::class, - ]) ) ->columns($mainColumns) ->actions([ SetResponseStatus::make(), - Tables\Actions\DeleteAction::make(), - Tables\Actions\ForceDeleteAction::make(), - Tables\Actions\RestoreAction::make(), ]) ->filters([ - Tables\Filters\TrashedFilter::make(), SelectFilter::make('status') ->options(BoltPlugin::getModel('FormsStatus')::query()->pluck('label', 'key')) ->label(__('Status')), ]) ->bulkActions([ - Tables\Actions\DeleteBulkAction::make(), - Tables\Actions\RestoreBulkAction::make(), - Tables\Actions\ForceDeleteBulkAction::make(), - FilamentExportBulkAction::make('export') ->icon('heroicon-o-document-arrow-down') ->label(__('Export')), ]) ->recordUrl( - fn (Response $record): string => FormResource::getUrl('viewResponse', [ - 'record' => $record->form->slug, - 'responseID' => $record, - ]), + fn (Model $record): string => ResponseResource::getUrl('view', ['record' => $record]), ); } - public static function getNavigationLabel(): string + protected function getHeaderActions(): array { - return __('Entries Report'); + return $this->getEntriesActions(); + } + + public function mount(): void + { + abort_unless(request()->filled('form_id'), 404); + + $this->form_id = request('form_id', 0); + $this->form = BoltPlugin::getModel('Form')::with(['fields'])->find($this->form_id); } public function getTitle(): string { return __('Entries Report'); } + + public function getFieldResponseValue(Response $record, Field $field): string + { + $fieldResponse = $record->fieldsResponses->where('field_id', $field->id)->first(); + if ($fieldResponse === null) { + return ''; + } + + return (new $fieldResponse->field->type)->getResponse($fieldResponse->field, $fieldResponse); + } + + public function getBreadcrumbs(): array + { + $breadcrumb = $this->getBreadcrumb(); + + return [ + FormResource::getUrl() => FormResource::getBreadcrumb(), + FormResource::getUrl('view', ['record' => $this->form->slug]) => $this->form->name, + ...(filled($breadcrumb) ? [$breadcrumb] : []), + ]; + } } diff --git a/src/Filament/Resources/ResponseResource/Pages/ViewResponse.php b/src/Filament/Resources/ResponseResource/Pages/ViewResponse.php new file mode 100644 index 00000000..92cbdb28 --- /dev/null +++ b/src/Filament/Resources/ResponseResource/Pages/ViewResponse.php @@ -0,0 +1,46 @@ +visible(function (): bool { + return $this->record->form->extensions === null; + }) + ->label(__('Set Status')) + ->icon('heroicon-o-tag') + ->action(function (array $data): void { + $this->record->status = $data['status']; + $this->record->notes = $data['notes']; + $this->record->save(); + }) + ->form([ + Select::make('status') + ->label(__('status')) + ->default(fn (Response $record) => $record->status) + ->options(BoltPlugin::getModel('FormsStatus')::query()->pluck('label', 'key')) + ->required(), + Textarea::make('notes') + ->default(fn (Response $record) => $record->notes) + ->label(__('Notes')), + ]), + ]; + } +} diff --git a/src/Models/Field.php b/src/Models/Field.php index cd5363a9..10b6ebc2 100644 --- a/src/Models/Field.php +++ b/src/Models/Field.php @@ -5,6 +5,7 @@ use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; +use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\SoftDeletes; use LaraZeus\Bolt\BoltPlugin; @@ -59,10 +60,10 @@ public function form(): BelongsTo return $this->belongsTo(BoltPlugin::getModel('Form')); } - /** @return BelongsTo */ - public function section(): BelongsTo + /** @return BelongsToMany
*/ + public function section(): BelongsToMany { - return $this->belongsTo(BoltPlugin::getModel('Section')); + return $this->belongsToMany(BoltPlugin::getModel('Section')); } /** @return HasMany */ diff --git a/src/Models/Response.php b/src/Models/Response.php index 776d178e..4b8c42fb 100644 --- a/src/Models/Response.php +++ b/src/Models/Response.php @@ -18,7 +18,6 @@ * @property string $status * @property string $notes * @property string $response - * @property Form $form */ class Response extends Model { @@ -62,7 +61,7 @@ public function user(): BelongsTo } /** @return BelongsTo */ - public function form(): BelongsTo + public function form() { return $this->belongsTo(BoltPlugin::getModel('Form')); } diff --git a/tests/ResourcesTest.php b/tests/ResourcesTest.php index 96fcb408..be873f5d 100644 --- a/tests/ResourcesTest.php +++ b/tests/ResourcesTest.php @@ -3,6 +3,7 @@ use LaraZeus\Bolt\Filament\Resources\CategoryResource; use LaraZeus\Bolt\Filament\Resources\CollectionResource; use LaraZeus\Bolt\Filament\Resources\FormResource; +use LaraZeus\Bolt\Filament\Resources\ResponseResource; use LaraZeus\Bolt\Models\Form; use function Pest\Laravel\get; @@ -28,8 +29,8 @@ ->assertSuccessful(); }); -/*it('can render Response List', function () { +it('can render Response List', function () { $form = Form::factory()->create(); get(ResponseResource::getUrl('index', ['form_id' => $form->id])) ->assertSuccessful(); -});*/ +});