Compare commits
	
		
			5 Commits
		
	
	
		
			cff62ebc1d
			...
			d53a6d23d2
		
	
	| Author | SHA1 | Date | 
|---|---|---|
| 
							
							
								 | 
						d53a6d23d2 | |
| 
							
							
								 | 
						ccef61352d | |
| 
							
							
								 | 
						5be7987d80 | |
| 
							
							
								 | 
						ac592920e7 | |
| 
							
							
								 | 
						68651b6c16 | 
| 
						 | 
					@ -0,0 +1,41 @@
 | 
				
			||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace App\Form\Actions;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use App\Form\Models\Form;
 | 
				
			||||||
 | 
					use App\Lib\Events\Succeeded;
 | 
				
			||||||
 | 
					use Illuminate\Http\JsonResponse;
 | 
				
			||||||
 | 
					use Lorisleiva\Actions\Concerns\AsAction;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class FormCopyAction
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    use AsAction;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @param array<string, mixed> $attributes
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function handle(Form $form): Form
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $newForm = $form->replicate();
 | 
				
			||||||
 | 
					        $newForm->save();
 | 
				
			||||||
 | 
					        $newForm->update(['name' => $form->name.' - Kopie', 'is_active' => false]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        foreach ($form->getRegisteredMediaCollections() as $collection) {
 | 
				
			||||||
 | 
					            foreach ($form->getMedia($collection->name) as $media) {
 | 
				
			||||||
 | 
					                $media->copy($newForm, $collection->name);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        ClearFrontendCacheAction::run();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return $form;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function asController(Form $form): JsonResponse
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $this->handle($form);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Succeeded::message('Veranstaltung kopiert.')->dispatch();
 | 
				
			||||||
 | 
					        return response()->json([]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -56,11 +56,12 @@ class FormResource extends JsonResource
 | 
				
			||||||
            'links' => [
 | 
					            'links' => [
 | 
				
			||||||
                'participant_index' => route('form.participant.index', ['form' => $this->getModel(), 'parent' => null]),
 | 
					                'participant_index' => route('form.participant.index', ['form' => $this->getModel(), 'parent' => null]),
 | 
				
			||||||
                'participant_root_index' => route('form.participant.index', ['form' => $this->getModel(), 'parent' => -1]),
 | 
					                'participant_root_index' => route('form.participant.index', ['form' => $this->getModel(), 'parent' => -1]),
 | 
				
			||||||
                'update' => route('form.update', ['form' => $this->getModel()]),
 | 
					                'update' => route('form.update', $this->getModel()),
 | 
				
			||||||
                'destroy' => route('form.destroy', ['form' => $this->getModel()]),
 | 
					                'destroy' => route('form.destroy', $this->getModel()),
 | 
				
			||||||
                'is_dirty' => route('form.is-dirty', ['form' => $this->getModel()]),
 | 
					                'is_dirty' => route('form.is-dirty', $this->getModel()),
 | 
				
			||||||
                'frontend' => str(app(FormSettings::class)->registerUrl)->replace('{slug}', $this->slug),
 | 
					                'frontend' => str(app(FormSettings::class)->registerUrl)->replace('{slug}', $this->slug),
 | 
				
			||||||
                'export' => route('form.export', ['form' => $this->getModel()]),
 | 
					                'export' => route('form.export', $this->getModel()),
 | 
				
			||||||
 | 
					                'copy' => route('form.copy', $this->getModel()),
 | 
				
			||||||
            ]
 | 
					            ]
 | 
				
			||||||
        ];
 | 
					        ];
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -47,8 +47,8 @@ class FormFactory extends Factory
 | 
				
			||||||
            'description' => EditorRequestFactory::new()->toData(),
 | 
					            'description' => EditorRequestFactory::new()->toData(),
 | 
				
			||||||
            'excerpt' => $this->faker->words(10, true),
 | 
					            'excerpt' => $this->faker->words(10, true),
 | 
				
			||||||
            'config' => ['sections' => []],
 | 
					            'config' => ['sections' => []],
 | 
				
			||||||
            'from' => $this->faker->dateTimeBetween('+1 week', '+4 weeks')->format('Y-m-d H:i:s'),
 | 
					            'from' => $this->faker->dateTimeBetween('+1 week', '+3 weeks')->format('Y-m-d'),
 | 
				
			||||||
            'to' => $this->faker->dateTimeBetween('+1 week', '+4 weeks')->format('Y-m-d H:i:s'),
 | 
					            'to' => $this->faker->dateTimeBetween('+4 week', '+6 weeks')->format('Y-m-d'),
 | 
				
			||||||
            'registration_from' => $this->faker->dateTimeBetween(Carbon::parse('-2 weeks'), now())->format('Y-m-d H:i:s'),
 | 
					            'registration_from' => $this->faker->dateTimeBetween(Carbon::parse('-2 weeks'), now())->format('Y-m-d H:i:s'),
 | 
				
			||||||
            'registration_until' => $this->faker->dateTimeBetween(now(), Carbon::parse('+2 weeks'))->format('Y-m-d H:i:s'),
 | 
					            'registration_until' => $this->faker->dateTimeBetween(now(), Carbon::parse('+2 weeks'))->format('Y-m-d H:i:s'),
 | 
				
			||||||
            'mail_top' => EditorRequestFactory::new()->toData(),
 | 
					            'mail_top' => EditorRequestFactory::new()->toData(),
 | 
				
			||||||
| 
						 | 
					@ -65,7 +65,7 @@ class FormFactory extends Factory
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public function sections(array $sections): self
 | 
					    public function sections(array $sections): self
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return $this->state(['config' => ['sections' => array_map(fn ($section) => $section->create(), $sections)]]);
 | 
					        return $this->state(['config' => ['sections' => array_map(fn($section) => $section->create(), $sections)]]);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -200,7 +200,7 @@ import ConditionsForm from './ConditionsForm.vue';
 | 
				
			||||||
import { useToast } from 'vue-toastification';
 | 
					import { useToast } from 'vue-toastification';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const props = defineProps(indexProps);
 | 
					const props = defineProps(indexProps);
 | 
				
			||||||
const { meta, data, reloadPage, create, single, edit, cancel, submit, remove, getFilter, setFilter } = useIndex(props.data, 'form');
 | 
					const { meta, data, reloadPage, reload, create, single, edit, cancel, submit, remove, getFilter, setFilter } = useIndex(props.data, 'form');
 | 
				
			||||||
const axios = inject('axios');
 | 
					const axios = inject('axios');
 | 
				
			||||||
const toast = useToast();
 | 
					const toast = useToast();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -228,9 +228,9 @@ const allFields = computed(() => {
 | 
				
			||||||
    return result;
 | 
					    return result;
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function onCopy(form) {
 | 
					async function onCopy(form) {
 | 
				
			||||||
    single.value = {...meta.value.default, ...form};
 | 
					    await axios.post(form.links.copy, {});
 | 
				
			||||||
    single.value.id = null;
 | 
					    reload(false);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function setTemplate(template) {
 | 
					function setTemplate(template) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -23,6 +23,7 @@ use App\Fileshare\Actions\FileshareStoreAction;
 | 
				
			||||||
use App\Fileshare\Actions\FileshareUpdateAction;
 | 
					use App\Fileshare\Actions\FileshareUpdateAction;
 | 
				
			||||||
use App\Fileshare\Actions\ListFilesAction;
 | 
					use App\Fileshare\Actions\ListFilesAction;
 | 
				
			||||||
use App\Form\Actions\ExportAction as ActionsExportAction;
 | 
					use App\Form\Actions\ExportAction as ActionsExportAction;
 | 
				
			||||||
 | 
					use App\Form\Actions\FormCopyAction;
 | 
				
			||||||
use App\Form\Actions\FormDestroyAction;
 | 
					use App\Form\Actions\FormDestroyAction;
 | 
				
			||||||
use App\Form\Actions\FormIndexAction;
 | 
					use App\Form\Actions\FormIndexAction;
 | 
				
			||||||
use App\Group\Actions\GroupBulkstoreAction;
 | 
					use App\Group\Actions\GroupBulkstoreAction;
 | 
				
			||||||
| 
						 | 
					@ -179,6 +180,7 @@ Route::group(['middleware' => 'auth:web'], function (): void {
 | 
				
			||||||
    Route::get('/participant/{participant}/fields', ParticipantFieldsAction::class)->name('participant.fields');
 | 
					    Route::get('/participant/{participant}/fields', ParticipantFieldsAction::class)->name('participant.fields');
 | 
				
			||||||
    Route::patch('/participant/{participant}', ParticipantUpdateAction::class)->name('participant.update');
 | 
					    Route::patch('/participant/{participant}', ParticipantUpdateAction::class)->name('participant.update');
 | 
				
			||||||
    Route::post('/form/{form}/participant', ParticipantStoreAction::class)->name('form.participant.store');
 | 
					    Route::post('/form/{form}/participant', ParticipantStoreAction::class)->name('form.participant.store');
 | 
				
			||||||
 | 
					    Route::post('/form/{form}/copy', FormCopyAction::class)->name('form.copy');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // ------------------------------------ fileshare -----------------------------------
 | 
					    // ------------------------------------ fileshare -----------------------------------
 | 
				
			||||||
    Route::post('/fileshare', FileshareStoreAction::class)->name('fileshare.store');
 | 
					    Route::post('/fileshare', FileshareStoreAction::class)->name('fileshare.store');
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -145,6 +145,15 @@ class FormIndexActionTest extends FormTestCase
 | 
				
			||||||
        $this->callFilter('form.index', [])->assertInertiaPath('data.data.0.links.frontend', 'https://example.com/form/zem-2024/register');
 | 
					        $this->callFilter('form.index', [])->assertInertiaPath('data.data.0.links.frontend', 'https://example.com/form/zem-2024/register');
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function testItDisplaysCopyUrl(): void
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $this->withoutExceptionHandling()->login()->loginNami();
 | 
				
			||||||
 | 
					        $form = Form::factory()->create();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        sleep(1);
 | 
				
			||||||
 | 
					        $this->callFilter('form.index', [])->assertInertiaPath('data.data.0.links.copy', route('form.copy', $form));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function testItDoesntReturnInactiveForms(): void
 | 
					    public function testItDoesntReturnInactiveForms(): void
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $this->withoutExceptionHandling()->login()->loginNami();
 | 
					        $this->withoutExceptionHandling()->login()->loginNami();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,70 @@
 | 
				
			||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Tests\Feature\Form;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use App\Form\Models\Form;
 | 
				
			||||||
 | 
					use Illuminate\Foundation\Testing\DatabaseTransactions;
 | 
				
			||||||
 | 
					use Illuminate\Support\Arr;
 | 
				
			||||||
 | 
					use Tests\Lib\CreatesFormFields;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uses(DatabaseTransactions::class);
 | 
				
			||||||
 | 
					uses(CreatesFormFields::class);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					beforeEach(function () {
 | 
				
			||||||
 | 
					    test()->fakeMessages();
 | 
				
			||||||
 | 
					    test()->setUpForm();
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					dataset('media', fn () => [
 | 
				
			||||||
 | 
					    ['mailattachments'],
 | 
				
			||||||
 | 
					    ['headerImage'],
 | 
				
			||||||
 | 
					]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					it('copies a form', function () {
 | 
				
			||||||
 | 
					    test()->login()->loginNami()->withoutExceptionHandling();
 | 
				
			||||||
 | 
					    $form = Form::factory()->name('Lager')->create();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    test()->post(route('form.copy', ['form' => $form]))
 | 
				
			||||||
 | 
					        ->assertOk();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    test()->assertDatabaseCount('forms', 2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $newForm = Form::where('name', 'Lager - Kopie')->firstOrFail();
 | 
				
			||||||
 | 
					    test()->assertEquals(
 | 
				
			||||||
 | 
					        Arr::except($form->fresh()->toArray(), ['id', 'name', 'slug', 'created_at', 'updated_at', 'is_active']),
 | 
				
			||||||
 | 
					        Arr::except($newForm->fresh()->toArray(), ['id', 'name', 'slug', 'created_at', 'updated_at', 'is_active'])
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					it('copies the forms media', function (string $collectionName) {
 | 
				
			||||||
 | 
					    test()->login()->loginNami()->withoutExceptionHandling();
 | 
				
			||||||
 | 
					    $form = Form::factory()->withImage($collectionName, 'lala.jpg')->name('Lager')->create();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    test()->post(route('form.copy', ['form' => $form]))->assertOk();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    test()->assertDatabaseCount('forms', 2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $newForm = Form::where('name', 'Lager - Kopie')->firstOrFail();
 | 
				
			||||||
 | 
					    test()->assertEquals($form->getMedia($collectionName)->first()->name, $newForm->getMedia($collectionName)->first()->name);
 | 
				
			||||||
 | 
					    test()->assertNotEquals($form->getMedia($collectionName)->first()->id, $newForm->getMedia($collectionName)->first()->id);
 | 
				
			||||||
 | 
					    test()->assertNotEquals($form->getMedia($collectionName)->first()->getFullUrl(), $newForm->getMedia($collectionName)->first()->getFullUrl());
 | 
				
			||||||
 | 
					})->with('media');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					it('deactivates a copied form', function () {
 | 
				
			||||||
 | 
					    test()->login()->loginNami()->withoutExceptionHandling();
 | 
				
			||||||
 | 
					    $form = Form::factory()->name('Lager')->create(['is_active' => true]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    test()->post(route('form.copy', ['form' => $form]))->assertOk();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $newForm = Form::where('name', 'Lager - Kopie')->firstOrFail();
 | 
				
			||||||
 | 
					    test()->assertEquals(false, $newForm->is_active);
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					it('shows success message', function () {
 | 
				
			||||||
 | 
					    test()->login()->loginNami()->withoutExceptionHandling();
 | 
				
			||||||
 | 
					    $form = Form::factory()->create();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    test()->post(route('form.copy', ['form' => $form]))->assertOk();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    test()->assertSuccessMessage('Veranstaltung kopiert.');
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
| 
						 | 
					@ -3,12 +3,14 @@
 | 
				
			||||||
namespace Tests;
 | 
					namespace Tests;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use App\Group;
 | 
					use App\Group;
 | 
				
			||||||
 | 
					use App\Lib\Events\Succeeded;
 | 
				
			||||||
use App\Member\Member;
 | 
					use App\Member\Member;
 | 
				
			||||||
use App\Setting\NamiSettings;
 | 
					use App\Setting\NamiSettings;
 | 
				
			||||||
use App\User;
 | 
					use App\User;
 | 
				
			||||||
use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
 | 
					use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
 | 
				
			||||||
use Illuminate\Http\RedirectResponse;
 | 
					use Illuminate\Http\RedirectResponse;
 | 
				
			||||||
use Illuminate\Support\Arr;
 | 
					use Illuminate\Support\Arr;
 | 
				
			||||||
 | 
					use Illuminate\Support\Facades\Event;
 | 
				
			||||||
use Illuminate\Support\Facades\Http;
 | 
					use Illuminate\Support\Facades\Http;
 | 
				
			||||||
use Illuminate\Testing\AssertableJsonString;
 | 
					use Illuminate\Testing\AssertableJsonString;
 | 
				
			||||||
use Illuminate\Testing\TestResponse;
 | 
					use Illuminate\Testing\TestResponse;
 | 
				
			||||||
| 
						 | 
					@ -192,4 +194,16 @@ class TestCase extends BaseTestCase
 | 
				
			||||||
            return $this;
 | 
					            return $this;
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function fakeMessages() {
 | 
				
			||||||
 | 
					        Event::fake([Succeeded::class]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return $this;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function assertSuccessMessage(string $message) {
 | 
				
			||||||
 | 
					        Event::assertDispatched(Succeeded::class, fn ($event) => $event->message === $message);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return $this;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue