Skip to content

Commit a6f6904

Browse files
AllanKoderCopilotCopilot
authored
Resource edits tab (#52)
* dropdown link changes, and version upgrades * Custom Polymorphic Types * Apply automatic changes * Using new morphs * Apply automatic changes * upvote changes * Resource edits, and tests * Apply automatic changes * Update resources/js/Pages/AboutUs.vue Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update app/Services/ResourceEditsService.php Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * nits * [WIP] Address feedback on Resource edits tab PR (#53) * Initial plan * Fix mobile navigation to use consistent route for Resource Edits Co-authored-by: AllanKoder <74692833+AllanKoder@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: AllanKoder <74692833+AllanKoder@users.noreply.github.com> --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
1 parent 2345e3c commit a6f6904

38 files changed

Lines changed: 1017 additions & 423 deletions

app/Http/Controllers/CommentController.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
use App\Http\Resources\CommentResource;
77
use App\Http\Resources\UserResource;
88
use App\Services\CommentService;
9-
use App\Services\ModelResolverService;
9+
use App\Services\UpvoteService;
1010
use Illuminate\Http\Request;
1111
use Illuminate\Support\Facades\Auth;
1212
use Illuminate\Support\Facades\DB;
@@ -17,8 +17,9 @@
1717

1818
class CommentController extends Controller
1919
{
20-
public function __construct(protected ModelResolverService $modelResolver,
20+
public function __construct(
2121
protected CommentService $commentService,
22+
protected UpvoteService $upvoteService,
2223
) {}
2324

2425
/**
@@ -42,6 +43,8 @@ public function store(StoreCommentRequest $request)
4243
'depth' => $comment->depth,
4344
]);
4445

46+
$this->upvoteService->upvote('comment', $comment->id);
47+
4548
DB::commit();
4649

4750
return response()->json([

app/Http/Controllers/ComputerScienceResourceController.php

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@
88
use App\Models\ComputerScienceResource;
99
use App\Services\ComputerScienceResourceFilter;
1010
use App\Services\ComputerScienceResourceService;
11+
use App\Services\UpvoteService;
1112
use Illuminate\Http\Request;
1213
use Illuminate\Support\Facades\Auth;
14+
use Illuminate\Support\Facades\DB;
1315
use Illuminate\Support\Facades\Log;
1416
use Inertia\Inertia;
1517
use Throwable;
@@ -18,6 +20,7 @@ class ComputerScienceResourceController extends Controller
1820
{
1921
public function __construct(
2022
protected ComputerScienceResourceService $resourceService,
23+
protected UpvoteService $upvoteService,
2124
protected ComputerScienceResourceFilter $filterService
2225
) {}
2326

@@ -63,7 +66,21 @@ public function store(StoreResourceRequest $request)
6366
{
6467
$validatedData = $request->validated();
6568
try {
69+
DB::beginTransaction();
6670
$resource = $this->resourceService->createResource($validatedData);
71+
72+
Log::info('Resource created', [
73+
'resource_id' => $resource->id,
74+
'user_id' => Auth::id(),
75+
'name' => $resource->name,
76+
'slug' => $resource->slug,
77+
'platforms' => $resource->platforms,
78+
]);
79+
80+
$this->upvoteService->upvote('resource', $resource->id);
81+
82+
DB::commit();
83+
6784
session()->flash('success', 'Created Resource!');
6885

6986
return response()->json($resource);
@@ -77,10 +94,13 @@ public function store(StoreResourceRequest $request)
7794

7895
return response()->json($e->resource);
7996
} catch (Throwable $e) {
80-
Log::error('Error creating resource', [
81-
'user_id' => Auth::id(),
97+
DB::rollBack();
98+
99+
Log::critical('Failed to create resource', [
82100
'error' => $e->getMessage(),
83101
'trace' => $e->getTraceAsString(),
102+
'user_id' => Auth::id(),
103+
'data' => $validatedData,
84104
]);
85105

86106
return response()->json([], 500);

app/Http/Controllers/ResourceEditsController.php

Lines changed: 61 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,10 @@
66
use App\Models\ComputerScienceResource;
77
use App\Models\ResourceEdits;
88
use App\Services\ResourceEditsService;
9+
use Illuminate\Http\Request;
910
use Illuminate\Support\Facades\Auth;
10-
use Illuminate\Support\Facades\DB;
1111
use Illuminate\Support\Facades\Log;
12-
use Illuminate\Support\Facades\Storage;
1312
use Inertia\Inertia;
14-
use Str;
1513
use Throwable;
1614

1715
class ResourceEditsController extends Controller
@@ -39,36 +37,61 @@ public function create(string $slug)
3937
public function store(ComputerScienceResource $computerScienceResource, StoreResourceEditRequest $request)
4038
{
4139
$validatedData = $request->validated();
42-
$proposedChanges = $validatedData['proposed_changes'] ?? [];
43-
44-
$actualChanges = $this->resourceEditsService->calculateChanges($computerScienceResource, $proposedChanges);
45-
46-
// Add image path to the actual changes
47-
if (array_key_exists('image_file', $proposedChanges)) {
48-
$actualChanges['image_path'] = null;
49-
if (isset($proposedChanges['image_file'])) {
50-
$path = $proposedChanges['image_file']->store('resource-edits', 'public');
51-
$actualChanges['image_path'] = $path;
52-
}
53-
unset($actualChanges['image_file']);
54-
}
5540

56-
if (empty($actualChanges)) {
57-
Log::warning("Resource edit was submitted without any changes for resource ID: {$computerScienceResource->id}");
41+
try {
42+
$resourceEdit = $this->resourceEditsService->createResourceEdit($computerScienceResource, $validatedData);
43+
44+
Log::info('Resource edit created', [
45+
'resource_edit_id' => $resourceEdit->id,
46+
'resource_id' => $computerScienceResource->id,
47+
'user_id' => Auth::id(),
48+
'edit_title' => $resourceEdit->edit_title,
49+
]);
50+
51+
return redirect()->route('resource_edits.show', ['slug' => $resourceEdit->slug])
52+
->with('success', 'Edits Created!');
53+
} catch (\InvalidArgumentException $e) {
54+
Log::warning('Resource edit submitted with no changes', [
55+
'resource_id' => $computerScienceResource->id,
56+
'user_id' => Auth::id(),
57+
'error' => $e->getMessage(),
58+
]);
5859

5960
return redirect()->back()->with('warning', 'Cannot submit an edit with no changes made.');
61+
} catch (Throwable $e) {
62+
Log::critical('Failed to create resource edit', [
63+
'error' => $e->getMessage(),
64+
'trace' => $e->getTraceAsString(),
65+
'resource_id' => $computerScienceResource->id,
66+
'user_id' => Auth::id(),
67+
'data' => $validatedData,
68+
]);
69+
70+
return redirect()->back()->withErrors(['error' => 'Failed to create resource edit. Please try again.']);
6071
}
72+
}
6173

62-
$resourceEdit = ResourceEdits::create([
63-
'user_id' => Auth::id(),
64-
'computer_science_resource_id' => $computerScienceResource->id,
65-
'edit_title' => $validatedData['edit_title'],
66-
'edit_description' => $validatedData['edit_description'],
67-
'proposed_changes' => $actualChanges,
68-
]);
74+
public function index(Request $request)
75+
{
76+
try {
77+
$data = $this->resourceEditsService->getIndexData($request);
6978

70-
return redirect()->route('resource_edits.show', ['slug' => $resourceEdit->slug])
71-
->with('success', 'Edits Created!');
79+
return Inertia::render('ResourceEdits/Index', $data);
80+
} catch (Throwable $e) {
81+
Log::error('Error loading resource edits index', [
82+
'user_id' => Auth::id(),
83+
'query' => $request->query(),
84+
'error' => $e->getMessage(),
85+
'trace' => $e->getTraceAsString(),
86+
]);
87+
88+
// Return an empty page with an error flash so the UI can show a message
89+
session()->flash('error', 'Unable to load resource edits right now.');
90+
91+
return Inertia::render('ResourceEdits/Index', [
92+
'resource_edits' => ResourceEdits::query()->paginate(1),
93+
]);
94+
}
7295
}
7396

7497
public function show(string $slug)
@@ -83,57 +106,10 @@ public function show(string $slug)
83106
]);
84107
}
85108

86-
public function merge(ResourceEditsService $editsService, ResourceEdits $resourceEdits)
109+
public function merge(ResourceEdits $resourceEdits)
87110
{
88-
if (! $editsService->canMergeEdits($resourceEdits)) {
89-
return redirect()->back()->with('warning', 'Not enough approvals');
90-
}
91-
92-
DB::beginTransaction();
93111
try {
94-
$resource = ComputerScienceResource::findOrFail($resourceEdits->computer_science_resource_id);
95-
96-
// Go through each property in proposed_changes, and if it exists. then set the value
97-
$changes = $resourceEdits->proposed_changes;
98-
$proposedFields = ['name', 'description', 'page_url', 'platforms', 'difficulties', 'pricing'];
99-
foreach ($proposedFields as $field) {
100-
if (array_key_exists($field, $changes)) {
101-
$resource->$field = $changes[$field];
102-
}
103-
}
104-
105-
if (array_key_exists('image_path', $changes)) {
106-
if ($resource->image_path) {
107-
Storage::disk('public')->delete($resource->image_path);
108-
}
109-
$destPath = null;
110-
if (isset($changes['image_path'])) {
111-
// Move the new file from 'resource-edits' to 'resource'
112-
$sourcePath = $changes['image_path'];
113-
$fileExtension = pathinfo($sourcePath, PATHINFO_EXTENSION);
114-
$newFileName = Str::random(40).'.'.$fileExtension;
115-
$destPath = 'resource/'.$newFileName;
116-
117-
// TODO: FIGURE OUT WHAT TO DO IN CASE OF EXCEPTION IN CODE FROM LATER STEPS
118-
Storage::disk('public')->move($sourcePath, $destPath);
119-
}
120-
// Update image_path in DB
121-
$resource->image_path = $destPath;
122-
}
123-
124-
$resource->save();
125-
126-
$proposedTagFields = ['topics_tags', 'programming_languages_tags', 'general_tags'];
127-
foreach ($proposedTagFields as $field) {
128-
if (array_key_exists($field, $changes)) {
129-
$resource->$field = $changes[$field];
130-
}
131-
}
132-
133-
// Delete the edit since we successfully merged the changes
134-
$resourceEdits->delete();
135-
136-
DB::commit();
112+
$resource = $this->resourceEditsService->mergeResourceEdit($resourceEdits);
137113

138114
Log::info('Resource edit merged', [
139115
'resource_id' => $resource->id,
@@ -145,12 +121,20 @@ public function merge(ResourceEditsService $editsService, ResourceEdits $resourc
145121

146122
return redirect(route('resources.show', ['slug' => $resource->slug]))
147123
->with('success', 'Successfully Merged Changes!');
124+
} catch (\LogicException $e) {
125+
Log::warning('Insufficient approvals for resource edit merge', [
126+
'resource_edit_id' => $resourceEdits->id,
127+
'user_id' => Auth::id(),
128+
'error' => $e->getMessage(),
129+
]);
130+
131+
return redirect()->back()->with('warning', 'Not enough approvals');
148132
} catch (Throwable $e) {
149-
DB::rollBack();
150133
Log::critical('Failed to merge resource edits', [
151134
'error' => $e->getMessage(),
152135
'trace' => $e->getTraceAsString(),
153136
'resource_edit_id' => $resourceEdits->id,
137+
'user_id' => Auth::id(),
154138
]);
155139

156140
return redirect()->back()->withErrors(['error' => 'Failed to merge resource edits. Please try again.']);

app/Http/Controllers/ResourceReviewController.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,16 @@
55
use App\Http\Requests\StoreResourceReviewRequest;
66
use App\Models\ComputerScienceResource;
77
use App\Models\ResourceReview;
8+
use App\Services\UpvoteService;
89
use Illuminate\Support\Facades\Auth;
910
use Illuminate\Support\Facades\Log;
1011

1112
class ResourceReviewController extends Controller
1213
{
14+
public function __construct(
15+
protected UpvoteService $upvoteService,
16+
) {}
17+
1318
// Store the review on the resource
1419
public function store(StoreResourceReviewRequest $request, ComputerScienceResource $computerScienceResource)
1520
{
@@ -58,6 +63,8 @@ public function store(StoreResourceReviewRequest $request, ComputerScienceResour
5863
'review_id' => $review->id,
5964
]);
6065

66+
$this->upvoteService->upvote('review', $review->id);
67+
6168
return response()->json($review);
6269
}
6370

app/Http/Requests/StoreCommentRequest.php

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,12 @@
22

33
namespace App\Http\Requests;
44

5-
use App\Services\ModelResolverService;
65
use Illuminate\Foundation\Http\FormRequest;
76
use Illuminate\Support\Facades\Auth;
87
use Illuminate\Validation\Rule;
98

109
class StoreCommentRequest extends FormRequest
1110
{
12-
protected $modelResolver;
13-
14-
public function __construct(ModelResolverService $modelResolver)
15-
{
16-
parent::__construct();
17-
$this->modelResolver = $modelResolver;
18-
}
19-
2011
/**
2112
* Determine if the user is authorized to make this request.
2213
*/

app/Providers/AppServiceProvider.php

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace App\Providers;
44

5+
use Illuminate\Database\Eloquent\Relations\Relation;
56
use Illuminate\Support\ServiceProvider;
67

78
class AppServiceProvider extends ServiceProvider
@@ -22,6 +23,13 @@ public function register(): void
2223
*/
2324
public function boot(): void
2425
{
25-
//
26+
Relation::enforceMorphMap([
27+
'resource' => \App\Models\ComputerScienceResource::class,
28+
'review' => \App\Models\ResourceReview::class,
29+
'comment' => \App\Models\Comment::class,
30+
'edit' => \App\Models\ResourceEdits::class,
31+
'user' => \App\Models\User::class,
32+
// Add other model types here
33+
]);
2634
}
2735
}

app/Providers/ModelResolverServiceProvider.php

Lines changed: 0 additions & 27 deletions
This file was deleted.

0 commit comments

Comments
 (0)