Skip to content

Commit

Permalink
Merge pull request #780 from owlchester/bulk-relation-creation
Browse files Browse the repository at this point in the history
Bulk Relation Creation
  • Loading branch information
ilestis authored Dec 7, 2023
2 parents 809d447 + 286a293 commit fd53b32
Show file tree
Hide file tree
Showing 10 changed files with 143 additions and 49 deletions.
17 changes: 12 additions & 5 deletions app/Http/Controllers/Api/v1/EntityRelationApiController.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,18 @@
use App\Models\Entity;
use App\Http\Requests\StoreRelation as Request;
use App\Http\Resources\RelationResource as Resource;
use App\Services\Entity\RelationService;
use App\Models\Relation;

class EntityRelationApiController extends ApiController
{
protected RelationService $relationService;

public function __construct(RelationService $relationService)
{
$this->relationService = $relationService;
}

/**
* @return \Illuminate\Http\Resources\Json\AnonymousResourceCollection
* @throws \Illuminate\Auth\Access\AuthorizationException
Expand All @@ -32,18 +40,17 @@ public function show(Campaign $campaign, Entity $entity, Relation $relation)
}

/**
* @return Resource
* @return \Illuminate\Http\Resources\Json\AnonymousResourceCollection
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function store(Request $request, Campaign $campaign, Entity $entity)
{
$this->authorize('access', $campaign);
$this->authorize('update', $entity->child);

$data = $request->all();
$data['campaign_id'] = $campaign->id;
$model = Relation::create($data);
return new Resource($model);
$this->relationService->campaign($campaign)->createRelations($request);

return Resource::collection($entity->relationships()->has('target')->whereIn('target_id', $this->relationService->getEntities())->paginate());
}

/**
Expand Down
23 changes: 8 additions & 15 deletions app/Http/Controllers/Entity/RelationController.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,20 @@
use App\Models\Entity;
use App\Models\Relation;
use App\Services\Entity\ConnectionService;
use App\Services\Entity\RelationService;
use App\Traits\GuestAuthTrait;

class RelationController extends Controller
{
use GuestAuthTrait;

protected ConnectionService $connectionService;
protected RelationService $relationService;

public function __construct(ConnectionService $connectionService)
public function __construct(ConnectionService $connectionService, RelationService $relationService)
{
$this->connectionService = $connectionService;
$this->relationService = $relationService;
}

public function index(Campaign $campaign, Entity $entity)
Expand Down Expand Up @@ -110,17 +113,7 @@ public function store(StoreRelation $request, Campaign $campaign, Entity $entity
return response()->json(['success' => true]);
}

$data = $request->only([
'owner_id', 'target_id', 'attitude', 'relation', 'colour', 'is_pinned', 'two_way', 'visibility_id'
]);
$data['campaign_id'] = $entity->campaign_id;

$relation = new Relation();
$relation = $relation->create($data);

if ($request->has('two_way')) {
$relation->createMirror();
}
$this->relationService->campaign($campaign)->createRelations($request);

$mode = $this->getModeOption(true);
$redirect = [$campaign, $entity];
Expand All @@ -130,9 +123,9 @@ public function store(StoreRelation $request, Campaign $campaign, Entity $entity

return redirect()
->route('entities.relations.index', $redirect)
->with('success', trans('entities/relations.create.success', [
'target' => $relation->target->name,
'entity' => $entity->name
->with('success', trans_choice('entities/relations.create.success_bulk', $count, [
'entity' => $entity->name,
'count' => $this->relationService->getCount(),
]));
}

Expand Down
25 changes: 11 additions & 14 deletions app/Http/Controllers/RelationController.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,14 @@
use App\Datagrids\Actions\RelationDatagridActions;
use App\Datagrids\Filters\RelationFilter;
use App\Http\Requests\StoreRelation;
use App\Services\Entity\RelationService;
use App\Models\Campaign;
use App\Models\Relation;

class RelationController extends CrudController
{
protected RelationService $relationService;

protected string $view = 'relations';
protected string $route = 'relations';
protected $langKey = 'entities/relations';
Expand All @@ -36,12 +39,13 @@ class RelationController extends CrudController

public string $titleKey;

public function __construct()
public function __construct(RelationService $relationService)
{
parent::__construct();
$this->middleware('auth');

$this->titleKey = __('sidebar.relations');
$this->relationService = $relationService;
}

/**
Expand Down Expand Up @@ -77,23 +81,16 @@ public function store(StoreRelation $request, Campaign $campaign)
}

try {
$data = $request->all();
$data['campaign_id'] = $campaign->id;

$model = new $this->model();
/** @var Relation $new */
$new = $model->create($data);

if ($request->has('two_way')) {
$new->createMirror();
}
$this->relationService->campaign($campaign)->createRelations($request);
$new = $this->relationService->getNew();
$count = $this->relationService->getCount();

$success = __($this->langKey . '.create.success', [
'target' => $new->target->name,
$success = trans_choice($this->langKey . '.create.success_bulk', $count, [
'entity' => link_to(
$new->owner->url(),
$new->owner->name
)
),
'count' => $count,
]);
session()->flash('success_raw', $success);

Expand Down
7 changes: 6 additions & 1 deletion app/Http/Requests/StoreRelation.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,12 @@ public function rules()
{
return $this->clean([
'owner_id' => 'required|exists:entities,id',
'target_id' => 'required|exists:entities,id|different:owner_id',
'targets' => 'required_without:target_id',
// @phpstan-ignore-next-line
'targets' => [
'*' => 'exists:entities,id',
],
'target_id' => 'required_without:targets|exists:entities,id|different:owner_id',
'relation' => 'required|max:255',
'visibility_id' => 'nullable|exists:visibilities,id',
'attitude' => 'min:-100|max:100',
Expand Down
64 changes: 64 additions & 0 deletions app/Services/Entity/RelationService.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<?php

namespace App\Services\Entity;

use App\Http\Requests\StoreRelation;
use App\Models\Relation;
use App\Traits\CampaignAware;

class RelationService
{
use CampaignAware;

protected array $entities;
protected Relation $new;
protected int $count;

/**
*/
public function createRelations(StoreRelation $request): self
{
$this->count = 0;
$data = $request->only([
'owner_id', 'attitude', 'relation', 'colour', 'is_pinned', 'two_way', 'visibility_id'
]);
$data['campaign_id'] = $this->campaign->id;

if ($request->has('targets')) {
$this->entities = $request->get('targets');
} else {
$this->entities = [$request->get('target_id')];
}
foreach ($this->entities as $entity_id) {
$data['target_id'] = $entity_id;
$relation = new Relation();
$relation = $relation->create($data);
$this->count++;
if (!isset($new)) {
$new = $relation;
}
if ($request->has('two_way')) {
$relation->createMirror();
$this->count++;
}
}
$this->new = $new;

return $this;
}

public function getEntities(): array
{
return $this->entities;
}

public function getNew(): Relation
{
return $this->new;
}

public function getCount(): int
{
return $this->count;
}
}
6 changes: 3 additions & 3 deletions lang/en/entities/relations.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@
'timeline_element' => 'Timeline element',
],
'create' => [
'new_title' => 'New connection',
'success' => 'Connection :target added to :entity.',
'title' => 'New connection for :name',
'new_title' => 'New connection',
'success_bulk' => '{1} Added :count connection to :entity.|[2,*] Added :count connections to :entity.',
'title' => 'New connection for :name',
],
'delete_mirrored' => [
'helper' => 'This connection is mirrored on the target entity. Select this option to also remove the mirrored connection.',
Expand Down
5 changes: 3 additions & 2 deletions resources/api-docs/1.0/relations.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,8 @@ To create a relation, use the following endpoint.
| :- | :- | :- |
| `relation` | `string` (Required, max 255) | Description of the relation |
| `owner_id` | `int` (Required) | The relation's entity |
| `target_id` | `int` (Required) | The relation's target entity |
| `target_id` | `int` (Required if `targets` is not set) | The relation's target entity |
| `targets` | `array` (Required if `target_id` is not set) | An array of the relation's target entities |
| `attitude` | `int` | -100 to 100 |
| `colour` | `string` | Hex colour of the attitude (with or without the `#`) |
| `two_way` | `boolean` | If set, will duplicate the relation but in the other direction |
Expand All @@ -94,7 +95,7 @@ To create a relation, use the following endpoint.

### Results

> {success} Code 200 with JSON body of the new relation.
> {success} Code 200 with JSON body of the new relations.

<a name="update-relation"></a>
Expand Down
4 changes: 2 additions & 2 deletions resources/views/components/forms/foreign.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@
<div class="join w-full">
@endif

<select
<select
@if ($multiple) multiple="multiple" @endif
name="{{ $name }}"
name="{{ $name }}"
id="{{ $id }}"
class="w-full select2 join-item"
style="width: 100%"
Expand Down
27 changes: 20 additions & 7 deletions resources/views/cruds/fields/target.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,23 @@
$required = !isset($bulk);
$preset = $target ?? null;
@endphp

@include('cruds.fields.entity', [
'name' => 'target_id',
'label' => __('entities/relations.fields.target'),
'allowClear' => false,
'route' => null,
])
@if(empty($relation) && $required)
<x-forms.foreign
field="targets"
:required="true"
label="entities/relations.fields.target"
:multiple="true"
name="targets[]"
id="targets[]"
:campaign="$campaign"
:route="route('search.entities-with-relations', [$campaign])"
>
</x-forms.foreign>
@else
@include('cruds.fields.entity', [
'name' => 'target_id',
'label' => __('entities/relations.fields.target'),
'allowClear' => false,
'route' => null,
])
@endif
14 changes: 14 additions & 0 deletions resources/views/entities/pages/relations/_form.blade.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,19 @@
{{ csrf_field() }}

<x-grid>
@if(empty($relation))
<x-forms.foreign
field="targets"
:required="true"
label="entities/relations.fields.target"
:multiple="true"
name="targets[]"
id="targets[]"
:campaign="$campaign"
:route="route('search.entities-with-relations', [$campaign])"
>
</x-forms.foreign>
@else
@include('cruds.fields.entity', [
'name' => 'target_id',
'required' => true,
Expand All @@ -10,6 +23,7 @@
'dropdownParent' => request()->ajax() ? '#primary-dialog' : null,
'allowClear' => false,
])
@endif
<x-forms.field field="relation" :required="true" :label="__('entities/relations.fields.relation')">
{!! Form::text('relation', null, ['placeholder' => __('entities/relations.placeholders.relation'), 'class' => '', 'maxlength' => 191, 'required']) !!}
</x-forms.field>
Expand Down

0 comments on commit fd53b32

Please sign in to comment.