Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add simple filter options for the forms dashboard #117

Merged
merged 12 commits into from
Nov 13, 2023
9 changes: 8 additions & 1 deletion app/Http/Controllers/Api/FormController.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,14 @@ class FormController extends Controller
{
public function index(Request $request)
{
$forms = $request->user()->forms()->get();
$request->validate([
'filter' => 'in:published,unpublished,trashed',
]);

$forms = $request->user()
->forms()
->withFilter($request->filter ?? null)
->get();

return response()->json($forms);
}
Expand Down
41 changes: 41 additions & 0 deletions app/Http/Controllers/Api/TrashedFormController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;

class TrashedFormController extends Controller
{
public function delete(Request $request, $form)
{
$model = $request->user()
->forms()
->withTrashed()
->where('uuid', $form)
->firstOrFail();

if (! $model->trashed()) {
return abort(422, 'You need to put the form into trash before deleting it permanently.');
}

$model->forceDelete();

return response()->json([], 200);
}

public function restore(Request $request, $form)
{
$model = $request->user()
->forms()
->withTrashed()
->where('uuid', $form)
->firstOrFail();

if ($model->trashed()) {
$model->restore();
}

return response()->json($model);
}
}
8 changes: 6 additions & 2 deletions app/Http/Controllers/DashboardController.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,14 @@ class DashboardController extends Controller
{
public function show(Request $request)
{
$forms = $request->user()->forms;
$request->validate([
'filter' => 'in:published,unpublished,trashed',
]);

$forms = $request->user()->forms()->withFilter($request->filter ?? null)->get();

return Inertia::render('Dashboard', [
'forms' => $forms,
'initialForms' => $forms,
]);
}
}
2 changes: 1 addition & 1 deletion app/Http/Controllers/FormSubmissionsExportController.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public function __invoke(Form $form)
$out = fopen('php://output', 'w');

// Add BOM for UTF-8 to help software like Excel to correctly identify encoding
fwrite($out, chr(0xEF) . chr(0xBB) . chr(0xBF));
fwrite($out, chr(0xEF).chr(0xBB).chr(0xBF));

fputcsv($out, array_keys($exportFormatted[0]));

Expand Down
4 changes: 2 additions & 2 deletions app/Http/Resources/FormSessionResponseResource.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public function toArray($request)
'name' => '',
'value' => '',
'original' => '',
'message' => ''
'message' => '',
];
}
}
Expand All @@ -50,7 +50,7 @@ protected function formatValue($value)
if ($this->formBlock->type === FormBlockType::consent) {
$accepted = $value['accepted'] ? 'yes' : 'no';

return $value['consent'] . ': ' . $accepted;
return $value['consent'].': '.$accepted;
}

if ($this->formBlock->type === FormBlockType::rating || $this->formBlock->type === FormBlockType::scale) {
Expand Down
1 change: 1 addition & 0 deletions app/Http/Resources/PublicFormResource.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ public function toArray($request)
'show_social_links' => $this->show_social_links,
'show_form_progress' => $this->show_form_progress,
'is_published' => $this->is_published,
'is_trashed' => $this->is_trashed,
'avatar' => $this->avatar,
'background' => $this->background,
'company_name' => $this->company_name,
Expand Down
31 changes: 10 additions & 21 deletions app/Jobs/CallWebhookJob.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,17 @@

namespace App\Jobs;

use Exception;
use App\Http\Resources\FormSessionResource;
use App\Models\FormSession;
use App\Models\FormWebhook;
use Illuminate\Bus\Queueable;
use GuzzleHttp\RequestOptions;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Http;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use App\Http\Resources\FormSessionResource;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Symfony\Component\HttpClient\HttpClient;
use Symfony\Component\HttpClient\NoPrivateNetworkHttpClient;
use Symfony\Component\HttpClient\Exception\TransportException;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;
use Symfony\Contracts\HttpClient\Exception\HttpExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
use Symfony\Contracts\HttpClient\HttpClientInterface;

class CallWebhookJob implements ShouldQueue
{
Expand Down Expand Up @@ -47,36 +41,31 @@ public function __construct(FormSession $session, FormWebhook $webhook)
*
* @return void
*/
public function handle()
public function handle(HttpClientInterface $client)
{
$payload = FormSessionResource::make($this->session)->resolve();


$client = new NoPrivateNetworkHttpClient(HttpClient::create());

$client->withOptions([
'headers' => $this->webhook->headers ?? []
'headers' => $this->webhook->headers ?? [],
]);


$response = $client->request($this->webhook->webhook_method, $this->webhook->webhook_url, [
'json' => $payload,
]);

try {

$status = $response->getStatusCode();
$body = $response->getContent();
$json = $response->toArray();
$json = json_decode($body);
$headers = $response->getHeaders();
} catch (HttpExceptionInterface $e) {
$errorResponse = $e->getResponse();

$status = $errorResponse->getStatusCode(false);
$body = $errorResponse->getContent(false);
$json = $errorResponse->toArray(false);
$json = json_decode($body);
$headers = $errorResponse->getHeaders(false);
} catch (Exception $e) {
} catch (\Exception $e) {
$status = 500;
$body = $e->getMessage();
$json = ['error' => $e->getMessage()];
Expand Down
4 changes: 1 addition & 3 deletions app/Listeners/FormSessionNotificationListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,8 @@

namespace App\Listeners;

use Illuminate\Support\Facades\Mail;
use App\Mail\FormSubmissionNotification;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Support\Facades\Mail;

class FormSessionNotificationListener
{
Expand Down
7 changes: 4 additions & 3 deletions app/Mail/FormSubmissionNotification.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,22 @@

namespace App\Mail;

use App\Http\Resources\FormSessionResource;
use App\Models\FormSession;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailables\Content;
use Illuminate\Queue\SerializesModels;
use Illuminate\Mail\Mailables\Envelope;
use App\Http\Resources\FormSessionResource;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\SerializesModels;

class FormSubmissionNotification extends Mailable implements ShouldQueue
{
use Queueable;
use SerializesModels;

public $session;

public $form;

/**
Expand Down
17 changes: 17 additions & 0 deletions app/Models/Form.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use App\Http\Resources\PublicFormResource;
use App\Models\Traits\TemplateExportsAndImports;
use Hashids\Hashids;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
Expand Down Expand Up @@ -64,6 +65,7 @@ class Form extends BaseModel
'completed_sessions',
'completion_rate',
'is_published',
'is_trashed',
'initials',
];

Expand Down Expand Up @@ -147,6 +149,16 @@ public function user(): BelongsTo
return $this->belongsTo(User::class);
}

public function scopeWithFilter(Builder $builder, ?string $filter)
{
return match ($filter) {
'published' => $builder->published(),
'unpublished' => $builder->whereNull('published_at')->orWhereDate('published_at', '>', Carbon::now()),
'trashed' => $builder->withTrashed()->whereNotNull('deleted_at'),
default => $builder,
};
}

public function route()
{
return route('forms.show', $this->uuid);
Expand Down Expand Up @@ -198,6 +210,11 @@ public function getBackgroundAttribute()
return false;
}

public function getIsTrashedAttribute()
{
return $this->deleted_at && $this->deleted_at->isPast();
}

public function getIsPublishedAttribute()
{
return $this->published_at && $this->published_at->isPast();
Expand Down
10 changes: 9 additions & 1 deletion app/Providers/AppServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\ServiceProvider;
use Symfony\Component\HttpClient\HttpClient;
use Symfony\Component\HttpClient\NoPrivateNetworkHttpClient;
use Symfony\Contracts\HttpClient\HttpClientInterface;

class AppServiceProvider extends ServiceProvider
{
Expand All @@ -16,7 +19,12 @@ class AppServiceProvider extends ServiceProvider
*/
public function register()
{
//
$this->app->bind(
HttpClientInterface::class,
function ($app) {
return new NoPrivateNetworkHttpClient(HttpClient::create());
}
);
}

/**
Expand Down
10 changes: 5 additions & 5 deletions app/Providers/EventServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@
namespace App\Providers;

use App\Events\FormPublished;
use App\Listeners\CreatePreviewImage;
use Illuminate\Support\Facades\Event;
use Illuminate\Auth\Events\Registered;
use App\Events\FormSessionCompletedEvent;
use App\Listeners\FormSubmitWebhookListener;
use App\Listeners\CreatePreviewImage;
use App\Listeners\FormSessionNotificationListener;
use App\Listeners\FormSubmitWebhookListener;
use Illuminate\Auth\Events\Registered;
use Illuminate\Auth\Listeners\SendEmailVerificationNotification;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Event;

class EventServiceProvider extends ServiceProvider
{
Expand All @@ -30,7 +30,7 @@ class EventServiceProvider extends ServiceProvider

FormSessionCompletedEvent::class => [
FormSubmitWebhookListener::class,
FormSessionNotificationListener::class
FormSessionNotificationListener::class,
],
];

Expand Down
9 changes: 9 additions & 0 deletions database/factories/FormFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,13 @@ public function unpublished()
];
});
}

public function deleted()
{
return $this->state(function ($attributes) {
return [
'deleted_at' => Carbon::now(),
];
});
}
}
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
"vitest": "^0.31.4"
},
"dependencies": {
"@deck9/ui": "^0.12.12",
"@deck9/ui": "^0.12.13",
"@headlessui/vue": "^1.7.14",
"@highlightjs/vue-plugin": "^2.1.0",
"@inertiajs/inertia": "^0.11.1",
Expand Down
Loading
Loading