Add: Edit subactivity
continuous-integration/drone/push Build is failing
Details
continuous-integration/drone/push Build is failing
Details
This commit is contained in:
parent
4cb2dddb43
commit
9598a44e13
|
@ -32,6 +32,7 @@ class ActivityStoreAction
|
|||
'name' => 'required|max:255',
|
||||
'is_filterable' => 'present|boolean',
|
||||
'subactivities' => 'present|array',
|
||||
'subactivities.*' => 'integer',
|
||||
];
|
||||
}
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@ class ActivityUpdateAction
|
|||
'name' => 'required|max:255',
|
||||
'is_filterable' => 'present|boolean',
|
||||
'subactivities' => 'present|array',
|
||||
'subactivities.*' => 'integer',
|
||||
];
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
<?php
|
||||
|
||||
namespace App\Activity\Api;
|
||||
|
||||
use App\Resources\SubactivityResource;
|
||||
use App\Subactivity;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Lorisleiva\Actions\Concerns\AsAction;
|
||||
|
||||
class SubactivityShowAction
|
||||
{
|
||||
use AsAction;
|
||||
|
||||
public function handle()
|
||||
{
|
||||
// ...
|
||||
}
|
||||
|
||||
public function asController(Subactivity $subactivity): JsonResponse
|
||||
{
|
||||
return response()->json([
|
||||
'data' => new SubactivityResource($subactivity),
|
||||
'meta' => SubactivityResource::meta(),
|
||||
]);
|
||||
}
|
||||
}
|
|
@ -34,6 +34,7 @@ class SubactivityStoreAction
|
|||
return [
|
||||
'name' => 'required|unique:subactivities,name',
|
||||
'activities' => 'present|array|min:1',
|
||||
'activities.*' => 'integer',
|
||||
'is_filterable' => 'present|boolean',
|
||||
];
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@ class SubactivityUpdateAction
|
|||
return [
|
||||
'name' => ['required', 'string', 'max:255', Rule::unique('subactivities', 'name')->ignore(request()->route('subactivity')->id)],
|
||||
'activities' => ['present', 'array', 'min:1'],
|
||||
'activities.*' => 'integer',
|
||||
'is_filterable' => 'present|boolean',
|
||||
];
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ namespace App\Activity\Resources;
|
|||
use App\Activity;
|
||||
use App\Http\Views\ActivityFilterScope;
|
||||
use App\Lib\HasMeta;
|
||||
use App\Resources\SubactivityResource;
|
||||
use App\Subactivity;
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
|
@ -49,7 +50,7 @@ class ActivityResource extends JsonResource
|
|||
public static function meta(): array
|
||||
{
|
||||
return [
|
||||
'subactivities' => Subactivity::select('name', 'id', 'is_filterable')->get(),
|
||||
'subactivities' => SubactivityResource::collectionWithoutMeta(Subactivity::get()),
|
||||
'filter' => ActivityFilterScope::fromRequest(request()->input('filter')),
|
||||
];
|
||||
}
|
||||
|
|
|
@ -25,9 +25,13 @@ trait HasMeta
|
|||
]);
|
||||
}
|
||||
|
||||
public static function collectionWithoutMeta($resource)
|
||||
{
|
||||
return parent::collection($resource);
|
||||
}
|
||||
|
||||
public static function meta(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
<?php
|
||||
|
||||
namespace App\Resources;
|
||||
|
||||
use App\Activity;
|
||||
use App\Activity\Resources\ActivityResource;
|
||||
use App\Lib\HasMeta;
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
/**
|
||||
* @mixin Subactivity
|
||||
*/
|
||||
class SubactivityResource extends JsonResource
|
||||
{
|
||||
use HasMeta;
|
||||
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
*
|
||||
* @return array|\Illuminate\Contracts\Support\Arrayable|\JsonSerializable
|
||||
*/
|
||||
public function toArray($request)
|
||||
{
|
||||
return [
|
||||
'id' => $this->id,
|
||||
'name' => $this->name,
|
||||
'is_filterable' => $this->is_filterable,
|
||||
'activities' => $this->activities->pluck('id')->toArray(),
|
||||
'links' => [
|
||||
'show' => route('api.subactivity.show', ['subactivity' => $this->getModel()]),
|
||||
'update' => route('api.subactivity.update', ['subactivity' => $this->getModel()]),
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
public static function meta(): array
|
||||
{
|
||||
return [
|
||||
'activities' => ActivityResource::collectionWithoutMeta(Activity::get()),
|
||||
];
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<div>
|
||||
<div class="flex space-x-3">
|
||||
<div class="flex space-x-3" v-if="model">
|
||||
<f-text size="sm" id="name" v-model="model.name" label="Name" required></f-text>
|
||||
<f-switch size="sm" v-model="model.is_filterable" name="subactivity_is_filterable" id="subactivity_is_filterable" label="Filterbar"></f-switch>
|
||||
</div>
|
||||
|
@ -25,12 +25,26 @@ export default {
|
|||
methods: {
|
||||
async store() {
|
||||
try {
|
||||
var response = await this.axios.post('/subactivity', this.model);
|
||||
this.$emit('stored', response.data);
|
||||
if (this.model.id) {
|
||||
var response = await this.axios.patch(this.model.links.update, this.model);
|
||||
this.$emit('updated', response.data);
|
||||
} else {
|
||||
var response = await this.axios.post('/subactivity', this.model);
|
||||
this.$emit('stored', response.data);
|
||||
}
|
||||
} catch (e) {
|
||||
this.errorsFromException(e);
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
async created() {
|
||||
if (this.value.id) {
|
||||
var payload = (await this.axios.get(this.value.links.show)).data;
|
||||
this.model = payload.data;
|
||||
} else {
|
||||
this.model = this.value;
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<form id="actionform" class="grow p-3" @submit.prevent="submit">
|
||||
<popup heading="Neue Untertätigkeit" v-if="mode === 'edit' && addingSubactivity === true" @close="addingSubactivity = false">
|
||||
<subactivity-form class="mt-4" :value="inner.subactivity_model" @stored="reloadSubactivities"></subactivity-form>
|
||||
<popup heading="Neue Untertätigkeit" v-if="mode === 'edit' && currentSubactivity !== null" @close="currentSubactivity = null">
|
||||
<subactivity-form class="mt-4" v-if="currentSubactivity" :value="currentSubactivity" @stored="reloadSubactivities" @updated="mergeSubactivity"></subactivity-form>
|
||||
</popup>
|
||||
<div class="flex space-x-3">
|
||||
<f-text id="name" v-model="inner.name" label="Name" required></f-text>
|
||||
|
@ -9,20 +9,15 @@
|
|||
</div>
|
||||
<div class="flex space-x-3 items-center mt-6 mb-2">
|
||||
<checkboxes-label>Untertätigkeiten</checkboxes-label>
|
||||
<icon-button icon="plus" v-if="mode === 'edit'" @click.prevent="addingSubactivity = true">Neu</icon-button>
|
||||
<icon-button icon="plus" v-if="mode === 'edit'" @click.prevent="currentSubactivity = inner.subactivity_model">Neu</icon-button>
|
||||
</div>
|
||||
<div class="grid gap-2 sm:grid-cols-2 md:grid-cols-4">
|
||||
<f-switch
|
||||
inline
|
||||
size="sm"
|
||||
:key="option.id"
|
||||
v-model="inner.subactivities"
|
||||
name="subactivities[]"
|
||||
:id="`subactivities-${option.id}`"
|
||||
:value="option.id"
|
||||
:label="option.name"
|
||||
v-for="option in subactivities"
|
||||
></f-switch>
|
||||
<div v-for="option in subactivities" class="flex items-center space-x-2">
|
||||
<a href="#" @click.prevent="currentSubactivity = option" class="transition hover:bg-yellow-600 group w-5 h-5 rounded-full flex items-center justify-center flex-none">
|
||||
<svg-sprite src="pencil" class="text-yellow-800 w-3 h-3 group-hover:text-yellow-200 transition"></svg-sprite>
|
||||
</a>
|
||||
<f-switch inline size="sm" :key="option.id" v-model="inner.subactivities" name="subactivities[]" :id="`subactivities-${option.id}`" :value="option.id" :label="option.name"></f-switch>
|
||||
</div>
|
||||
</div>
|
||||
<save-button form="actionform"></save-button>
|
||||
</form>
|
||||
|
@ -32,7 +27,7 @@
|
|||
export default {
|
||||
data: function () {
|
||||
return {
|
||||
addingSubactivity: false,
|
||||
currentSubactivity: null,
|
||||
subactivities: [...this.meta.subactivities],
|
||||
inner: {...this.data},
|
||||
mode: this.data.name === '' ? 'create' : 'edit',
|
||||
|
@ -63,7 +58,20 @@ export default {
|
|||
_self.subactivities = page.props.meta.subactivities;
|
||||
_self.inner.subactivities.push(model.id);
|
||||
_self.$success('Untertätigkeit gespeichert.');
|
||||
_self.addingSubactivity = false;
|
||||
_self.currentSubactivity = null;
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
mergeSubactivity(model) {
|
||||
var _self = this;
|
||||
|
||||
this.$inertia.reload({
|
||||
onSuccess(page) {
|
||||
_self.subactivities = page.props.meta.subactivities;
|
||||
_self.inner.subactivities = _self.inner.subactivities.map((s) => (s.id === model.id ? model : s));
|
||||
_self.$success('Untertätigkeit aktualisiert.');
|
||||
_self.currentSubactivity = null;
|
||||
},
|
||||
});
|
||||
},
|
||||
|
|
|
@ -6,6 +6,7 @@ use App\Activity\Actions\CreateAction as ActivityCreateAction;
|
|||
use App\Activity\Actions\DestroyAction as ActivityDestroyAction;
|
||||
use App\Activity\Actions\EditAction as ActivityEditAction;
|
||||
use App\Activity\Actions\IndexAction as ActivityIndexAction;
|
||||
use App\Activity\Api\SubactivityShowAction;
|
||||
use App\Activity\Api\SubactivityStoreAction;
|
||||
use App\Activity\Api\SubactivityUpdateAction;
|
||||
use App\Contribution\Actions\FormAction as ContributionFormAction;
|
||||
|
@ -64,4 +65,5 @@ Route::group(['middleware' => 'auth:web'], function (): void {
|
|||
Route::delete('/activity/{activity}', ActivityDestroyAction::class)->name('activity.destroy');
|
||||
Route::post('/subactivity', SubactivityStoreAction::class)->name('api.subactivity.store');
|
||||
Route::patch('/subactivity/{subactivity}', SubactivityUpdateAction::class)->name('api.subactivity.update');
|
||||
Route::get('/subactivity/{subactivity}', SubactivityShowAction::class)->name('api.subactivity.show');
|
||||
});
|
||||
|
|
|
@ -34,5 +34,14 @@ class EditTest extends TestCase
|
|||
'name' => 'Pupu',
|
||||
'is_filterable' => true,
|
||||
], $response, 'meta.subactivities.0');
|
||||
$this->assertInertiaHas([
|
||||
'id' => $activity->subactivities->first()->id,
|
||||
'name' => 'Pupu',
|
||||
'is_filterable' => true,
|
||||
'links' => [
|
||||
'show' => route('api.subactivity.show', ['subactivity' => $activity->subactivities->first()->id]),
|
||||
'update' => route('api.subactivity.update', ['subactivity' => $activity->subactivities->first()->id]),
|
||||
],
|
||||
], $response, 'meta.subactivities.0');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
|
||||
namespace Tests\Feature\Activity;
|
||||
|
||||
use App\Activity;
|
||||
use App\Subactivity;
|
||||
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||
use Tests\TestCase;
|
||||
|
||||
class SubactivityShowTest extends TestCase
|
||||
{
|
||||
use DatabaseTransactions;
|
||||
|
||||
public function testItShowsASubactivity(): void
|
||||
{
|
||||
$this->login()->loginNami()->withoutExceptionHandling();
|
||||
$subactivity = Subactivity::factory()->name('Asas')->filterable()->hasAttached(Activity::factory())->create();
|
||||
|
||||
$response = $this->getJson(route('api.subactivity.show', ['subactivity' => $subactivity]));
|
||||
|
||||
$response->assertJsonPath('data.id', $subactivity->id);
|
||||
$response->assertJsonPath('data.name', $subactivity->name);
|
||||
$response->assertJsonPath('data.links.update', route('api.subactivity.update', ['subactivity' => $subactivity]));
|
||||
$response->assertJsonPath('data.links.show', route('api.subactivity.show', ['subactivity' => $subactivity]));
|
||||
$response->assertJsonPath('data.activities.0', $subactivity->activities->first()->id);
|
||||
$response->assertJsonPath('meta.activities.0.name', $subactivity->activities->first()->name);
|
||||
$response->assertJsonPath('meta.activities.0.id', $subactivity->activities->first()->id);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue