From a9cf8b40b174aad071fbb9499e33a299d69ad976 Mon Sep 17 00:00:00 2001 From: Spitfire Date: Tue, 5 Dec 2023 16:23:10 -0600 Subject: [PATCH 1/3] Bulk Relation Creation --- .../Api/v1/EntityRelationApiController.php | 23 ++++++++++-- .../Controllers/Entity/RelationController.php | 32 +++++++++++------ app/Http/Controllers/RelationController.php | 35 +++++++++++++------ app/Http/Requests/StoreRelation.php | 6 +++- app/View/Components/Forms/Foreign.php | 3 ++ lang/en/entities/relations.php | 6 ++-- resources/api-docs/1.0/relations.md | 5 +-- .../views/components/forms/foreign.blade.php | 6 +++- resources/views/cruds/fields/target.blade.php | 27 ++++++++++---- .../entities/pages/relations/_form.blade.php | 14 ++++++++ 10 files changed, 119 insertions(+), 38 deletions(-) diff --git a/app/Http/Controllers/Api/v1/EntityRelationApiController.php b/app/Http/Controllers/Api/v1/EntityRelationApiController.php index b819b3acd0..cafe174c1c 100644 --- a/app/Http/Controllers/Api/v1/EntityRelationApiController.php +++ b/app/Http/Controllers/Api/v1/EntityRelationApiController.php @@ -40,10 +40,27 @@ public function store(Request $request, Campaign $campaign, Entity $entity) $this->authorize('access', $campaign); $this->authorize('update', $entity->child); - $data = $request->all(); + if ($request->has('targets')) { + $entities = $request->get('targets'); + } else { + $entities = [$request->get('target_id')]; + } + + $data = $request->only([ + 'owner_id', 'attitude', 'relation', 'colour', 'is_pinned', 'two_way', 'visibility_id' + ]); + $data['campaign_id'] = $campaign->id; - $model = Relation::create($data); - return new Resource($model); + + foreach ($entities as $entity_id) { + $data['target_id'] = $entity_id; + $model = Relation::create($data); + if ($request->has('two_way')) { + $model->createMirror(); + } + } + + return Resource::collection($entity->relationships()->has('target')->whereIn('target_id', $entities)->paginate()); } /** diff --git a/app/Http/Controllers/Entity/RelationController.php b/app/Http/Controllers/Entity/RelationController.php index c05ee95ac6..3fcd3d6e12 100644 --- a/app/Http/Controllers/Entity/RelationController.php +++ b/app/Http/Controllers/Entity/RelationController.php @@ -110,18 +110,28 @@ public function store(StoreRelation $request, Campaign $campaign, Entity $entity return response()->json(['success' => true]); } + if ($request->has('targets')) { + $entities = $request->get('targets'); + } else { + $entities = [$request->get('target_id')]; + } + $data = $request->only([ - 'owner_id', 'target_id', 'attitude', 'relation', 'colour', 'is_pinned', 'two_way', 'visibility_id' + 'owner_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(); + $data['campaign_id'] = $entity->campaign_id; + $count = 0; + foreach ($entities as $entity_id) { + $data['target_id'] = $entity_id; + $relation = new Relation(); + $relation = $relation->create($data); + $count++; + if ($request->has('two_way')) { + $relation->createMirror(); + $count++; + } } - $mode = $this->getModeOption(true); $redirect = [$campaign, $entity]; if (!empty($mode)) { @@ -130,9 +140,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' => $count, ])); } diff --git a/app/Http/Controllers/RelationController.php b/app/Http/Controllers/RelationController.php index d45b48f8b6..6aad007ace 100644 --- a/app/Http/Controllers/RelationController.php +++ b/app/Http/Controllers/RelationController.php @@ -77,23 +77,38 @@ public function store(StoreRelation $request, Campaign $campaign) } try { - $data = $request->all(); + $count = 0; + $data = $request->only([ + 'owner_id', 'attitude', 'relation', 'colour', 'is_pinned', 'two_way', 'visibility_id' + ]); $data['campaign_id'] = $campaign->id; - $model = new $this->model(); - /** @var Relation $new */ - $new = $model->create($data); - - if ($request->has('two_way')) { - $new->createMirror(); + if ($request->has('targets')) { + $entities = $request->get('targets'); + } else { + $entities = [$request->get('target_id')]; + } + foreach ($entities as $entity_id) { + $data['target_id'] = $entity_id; + $model = new $this->model(); + /** @var Relation $relation */ + $relation = $model->create($data); + $count++; + if (!isset($new)) { + $new = $relation; + } + if ($request->has('two_way')) { + $relation->createMirror(); + $count++; + } } - $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); diff --git a/app/Http/Requests/StoreRelation.php b/app/Http/Requests/StoreRelation.php index fd2b9eff3c..b59777dba8 100644 --- a/app/Http/Requests/StoreRelation.php +++ b/app/Http/Requests/StoreRelation.php @@ -28,7 +28,11 @@ 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', + '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', diff --git a/app/View/Components/Forms/Foreign.php b/app/View/Components/Forms/Foreign.php index 018f5f8e8d..2053ed2dd4 100644 --- a/app/View/Components/Forms/Foreign.php +++ b/app/View/Components/Forms/Foreign.php @@ -23,6 +23,7 @@ class Foreign extends Component public bool $allowNew; public bool $allowClear; public bool $required; + public bool $multiple; public ?string $entityType; public ?string $label; public ?string $placeholder; @@ -46,6 +47,7 @@ public function __construct( bool $allowClear = false, bool $required = false, bool $parent = false, + bool $multiple = false, string $entityType = null, string $key = null, string $label = null, @@ -74,6 +76,7 @@ public function __construct( $this->className = $class; $this->entityTypeID = $entityTypeID; $this->campaign = $campaign; + $this->multiple = $multiple; } /** diff --git a/lang/en/entities/relations.php b/lang/en/entities/relations.php index 9f94316922..35466769f6 100644 --- a/lang/en/entities/relations.php +++ b/lang/en/entities/relations.php @@ -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.', diff --git a/resources/api-docs/1.0/relations.md b/resources/api-docs/1.0/relations.md index 312d0a3a23..1221270d0c 100644 --- a/resources/api-docs/1.0/relations.md +++ b/resources/api-docs/1.0/relations.md @@ -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 | @@ -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. diff --git a/resources/views/components/forms/foreign.blade.php b/resources/views/components/forms/foreign.blade.php index d5debc28a9..5a016ac589 100644 --- a/resources/views/components/forms/foreign.blade.php +++ b/resources/views/components/forms/foreign.blade.php @@ -10,7 +10,10 @@
@endif -