PM-Editor UX: Kategorie in die Schreibfläche, Bild-Upload als Modal-Flow
Kategorie-Pflichtfeld direkt unter die Firma statt in die Sidebar. Titelbild-Upload öffnet ein Modal: erst Bild wählen, dann erscheinen die gestrafften Schritte (Herkunft & Bildnachweis mit Vorschlag aus dem Urheber, Personen & Rechte, Bestätigung), Optionales eingeklappt. Bildrechte-Checkbox im Einreichen-Modal nur noch mit eigenem Titelbild. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
c387048d7e
commit
2882bc44b2
10 changed files with 705 additions and 391 deletions
|
|
@ -1,5 +1,6 @@
|
|||
<?php
|
||||
|
||||
use App\Enums\AiImageDeclaration;
|
||||
use App\Enums\ImageLicenseType;
|
||||
use App\Models\Category;
|
||||
use App\Models\Company;
|
||||
|
|
@ -56,11 +57,29 @@ test('license type starts with an explicit placeholder before own photo option',
|
|||
|
||||
LivewireVolt::test('components.press-release-images-manager', ['pressReleaseId' => $pr->id])
|
||||
->call('openUploadForm')
|
||||
->set('newImage', UploadedFile::fake()->image('foto.jpg', 1200, 800))
|
||||
->assertSet('newLicenseType', '')
|
||||
->assertSee('Bitte wählen')
|
||||
->assertSee('Eigene Aufnahme');
|
||||
});
|
||||
|
||||
test('detail fields only appear after an image was selected', function () {
|
||||
/** @var TestCase $this */
|
||||
['owner' => $owner, 'pr' => $pr] = makeImageDraftOwner();
|
||||
$this->actingAs($owner);
|
||||
|
||||
LivewireVolt::test('components.press-release-images-manager', ['pressReleaseId' => $pr->id])
|
||||
->call('openUploadForm')
|
||||
->assertSee('Bild hierher ziehen oder klicken')
|
||||
->assertDontSee('Herkunft & Bildnachweis')
|
||||
->assertDontSee('Personen & Rechte Dritter')
|
||||
->assertDontSee('Rechte bestätigt')
|
||||
->set('newImage', UploadedFile::fake()->image('foto.jpg', 1200, 800))
|
||||
->assertSee('Herkunft & Bildnachweis')
|
||||
->assertSee('Personen & Rechte Dritter')
|
||||
->assertSee('Rechte bestätigt');
|
||||
});
|
||||
|
||||
test('title image upload form is collapsed until requested', function () {
|
||||
/** @var TestCase $this */
|
||||
['owner' => $owner, 'pr' => $pr] = makeImageDraftOwner();
|
||||
|
|
@ -180,6 +199,7 @@ test('valid upload stores license metadata and confirms rights', function () {
|
|||
->set('newCopyright', 'Foto: Jane Doe / Beispiel GmbH')
|
||||
->set('newAuthor', 'Jane Doe')
|
||||
->set('newLicenseType', ImageLicenseType::Own->value)
|
||||
->set('newAiDeclaration', AiImageDeclaration::Original->value)
|
||||
->set('newSourceUrl', 'https://example.com/source')
|
||||
->set('newPeopleRightsStatus', 'consent')
|
||||
->set('newPropertyRightsStatus', 'cleared')
|
||||
|
|
@ -228,6 +248,7 @@ test('valid cc upload stores license detail and license url', function () {
|
|||
->set('newAuthor', 'Jane Doe')
|
||||
->set('newCopyright', 'Foto: Jane Doe (CC BY 4.0)')
|
||||
->set('newLicenseType', ImageLicenseType::CreativeCommons->value)
|
||||
->set('newAiDeclaration', AiImageDeclaration::Original->value)
|
||||
->set('newLicenseDetail', 'cc_by')
|
||||
->set('newLicenseUrl', 'https://creativecommons.org/licenses/by/4.0/')
|
||||
->set('newPeopleRightsStatus', 'none')
|
||||
|
|
@ -244,7 +265,7 @@ test('valid cc upload stores license detail and license url', function () {
|
|||
expect($image->license_url)->toBe('https://creativecommons.org/licenses/by/4.0/');
|
||||
});
|
||||
|
||||
test('the public image credit is required', function () {
|
||||
test('the public image credit is required even when the suggestion was cleared', function () {
|
||||
/** @var TestCase $this */
|
||||
['owner' => $owner, 'pr' => $pr] = makeImageDraftOwner();
|
||||
$this->actingAs($owner);
|
||||
|
|
@ -253,6 +274,8 @@ test('the public image credit is required', function () {
|
|||
->set('newImage', UploadedFile::fake()->image('foto.jpg', 1200, 800))
|
||||
->set('newAuthor', 'Jane Doe')
|
||||
->set('newLicenseType', ImageLicenseType::Own->value)
|
||||
// Der Vorschlag aus dem Urheber wird bewusst entfernt.
|
||||
->set('newCopyright', '')
|
||||
->set('newPeopleRightsStatus', 'none')
|
||||
->set('newPropertyRightsStatus', 'none')
|
||||
->set('newRightsConfirmed', true)
|
||||
|
|
@ -311,9 +334,42 @@ test('a valid ai generated upload stores tool and ai flag', function () {
|
|||
expect($image->license_type)->toBe(ImageLicenseType::AiGenerated);
|
||||
expect($image->license_detail)->toBe('Midjourney v7');
|
||||
expect($image->is_ai_generated)->toBeTrue();
|
||||
// Lizenztyp „KI-generiert" setzt die KI-Kennzeichnung automatisch.
|
||||
expect($image->ai_declaration)->toBe(AiImageDeclaration::AiGenerated);
|
||||
expect($image->copyright)->toBe('Bild: KI-generiert (Midjourney v7)');
|
||||
});
|
||||
|
||||
test('the copyright suggestion follows the author but respects manual input', function () {
|
||||
/** @var TestCase $this */
|
||||
['owner' => $owner, 'pr' => $pr] = makeImageDraftOwner();
|
||||
$this->actingAs($owner);
|
||||
|
||||
LivewireVolt::test('components.press-release-images-manager', ['pressReleaseId' => $pr->id])
|
||||
->set('newLicenseType', ImageLicenseType::Own->value)
|
||||
->set('newAuthor', 'Jane Doe')
|
||||
->assertSet('newCopyright', 'Foto: Jane Doe')
|
||||
->set('newAuthor', 'John Smith')
|
||||
->assertSet('newCopyright', 'Foto: John Smith')
|
||||
->set('newCopyright', 'Eigener Nachweis')
|
||||
->set('newAuthor', 'Jane Doe')
|
||||
->assertSet('newCopyright', 'Eigener Nachweis');
|
||||
});
|
||||
|
||||
test('switching to ai replaces an automatically suggested author copyright', function () {
|
||||
/** @var TestCase $this */
|
||||
['owner' => $owner, 'pr' => $pr] = makeImageDraftOwner();
|
||||
$this->actingAs($owner);
|
||||
|
||||
LivewireVolt::test('components.press-release-images-manager', ['pressReleaseId' => $pr->id])
|
||||
->set('newLicenseType', ImageLicenseType::Own->value)
|
||||
->set('newAuthor', 'Jane Doe')
|
||||
->assertSet('newCopyright', 'Foto: Jane Doe')
|
||||
->set('newLicenseType', ImageLicenseType::AiGenerated->value)
|
||||
->assertSet('newCopyright', 'Bild: KI-generiert')
|
||||
->set('newLicenseType', ImageLicenseType::Own->value)
|
||||
->assertSet('newCopyright', 'Foto: Jane Doe');
|
||||
});
|
||||
|
||||
test('the ai copyright suggestion follows the tool but respects manual input', function () {
|
||||
/** @var TestCase $this */
|
||||
['owner' => $owner, 'pr' => $pr] = makeImageDraftOwner();
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
<?php
|
||||
|
||||
use App\Enums\AiTextDeclaration;
|
||||
use App\Enums\ImageLicenseType;
|
||||
use App\Enums\PressReleaseStatus;
|
||||
use App\Models\Plan;
|
||||
use Database\Seeders\RolesAndPermissionsSeeder;
|
||||
|
|
@ -58,6 +60,9 @@ test('submitting from the show modal moves the draft into review without consumi
|
|||
$this->actingAs($customer);
|
||||
|
||||
LivewireVolt::test('customer.press-releases.show', ['id' => $pr->id])
|
||||
// KI-Kennzeichnung (Art. 50 KI-VO) ist Pflicht im Submit-Modal.
|
||||
->set('aiTextDeclaration', AiTextDeclaration::None->value)
|
||||
->set('aiDeclarationConfirmed', true)
|
||||
->call('submitForReview')
|
||||
->assertHasNoErrors();
|
||||
|
||||
|
|
@ -66,6 +71,39 @@ test('submitting from the show modal moves the draft into review without consumi
|
|||
expect($customer->fresh()->press_release_quota_used_this_month)->toBe(0);
|
||||
});
|
||||
|
||||
test('the image rights confirmation is hidden while only the placeholder is active', function () {
|
||||
/** @var TestCase $this */
|
||||
['customer' => $customer, 'pr' => $pr] = makeCustomerForShowPhase8a();
|
||||
$this->actingAs($customer);
|
||||
|
||||
LivewireVolt::test('customer.press-releases.show', ['id' => $pr->id])
|
||||
->assertSee('Ihre Bestätigungen')
|
||||
->assertDontSee('Alle Bildrechte sind geklärt.')
|
||||
->assertSeeHtml("' / 4'");
|
||||
});
|
||||
|
||||
test('the image rights confirmation appears once an own title image exists', function () {
|
||||
/** @var TestCase $this */
|
||||
['customer' => $customer, 'pr' => $pr] = makeCustomerForShowPhase8a();
|
||||
|
||||
$pr->images()->create([
|
||||
'disk' => 'public',
|
||||
'path' => 'press-releases/'.$pr->id.'/images/title.jpg',
|
||||
'variants' => ['cover' => 'press-releases/'.$pr->id.'/images/title-cover.jpg'],
|
||||
'author' => 'Jane Doe',
|
||||
'license_type' => ImageLicenseType::Own->value,
|
||||
'rights_confirmed_at' => now(),
|
||||
'is_preview' => true,
|
||||
'sort_order' => 1,
|
||||
]);
|
||||
|
||||
$this->actingAs($customer);
|
||||
|
||||
LivewireVolt::test('customer.press-releases.show', ['id' => $pr->id])
|
||||
->assertSee('Alle Bildrechte sind geklärt.')
|
||||
->assertSeeHtml("' / 5'");
|
||||
});
|
||||
|
||||
test('the modal shows a booking notice instead of the submit flow when the gate is enforced', function () {
|
||||
/** @var TestCase $this */
|
||||
config()->set('billing.enforce_booking', true);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue