Skip to content

Commit dfc9f76

Browse files
committed
main entry status
1 parent bdc6fc3 commit dfc9f76

File tree

6 files changed

+184
-8
lines changed

6 files changed

+184
-8
lines changed

packages/core/config/core.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -462,4 +462,24 @@
462462
'enabled' => env('SHARED_HOSTING_ENABLED', false),
463463
'token' => env('SHARED_HOSTING_TOKEN', 'secret'),
464464
],
465+
466+
/*
467+
|--------------------------------------------------------------------------
468+
| Draft Publishing Logic
469+
|--------------------------------------------------------------------------
470+
|
471+
| Configure how the main entry status is handled based on translation statuses.
472+
|
473+
| Options:
474+
| - 'auto_publish_single': Auto-publish main entry if only one translation exists and is published
475+
| - 'prompt_when_all_published': Prompt user to publish main entry when all translations are published
476+
| - 'prompt_when_any_published': Prompt user to publish main entry when any translation is published
477+
|
478+
*/
479+
480+
'draft_publish_logic' => [
481+
'auto_publish_single' => true,
482+
'prompt_when_all_published' => true,
483+
'prompt_when_any_published' => false,
484+
],
465485
];

packages/core/resources/lang/de/core.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,4 +154,6 @@
154154
'slug_unique' => 'Dieser Slug ist bereits vergeben.',
155155
'no_title_available' => 'Kein Titel verfügbar',
156156
'translation_create' => 'Übersetzung erstellen',
157+
'publish_main_entry' => 'Haupteintrag veröffentlichen',
158+
'publish_main_entry_description' => 'Diese Aktion veröffentlicht den Haupteintrag.',
157159
];

packages/core/resources/lang/en/core.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,4 +154,6 @@
154154
'slug_unique' => 'This slug is already taken.',
155155
'no_title_available' => 'No title available',
156156
'translation_create' => 'Create translation',
157+
'publish_main_entry' => 'Publish main entry',
158+
'publish_main_entry_description' => 'This action will publish the main entry.',
157159
];

packages/core/src/Entities/BaseResource.php

Lines changed: 56 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,21 @@
55
use Filament\Actions\Action;
66
use Filament\Actions\BulkAction;
77
use Filament\Actions\EditAction;
8+
use Filament\Actions\ViewAction;
9+
use Filament\Resources\Resource;
810
use Filament\Actions\RestoreAction;
911
use Filament\Actions\RestoreBulkAction;
10-
use Filament\Actions\ViewAction;
11-
use Filament\Forms\Components\MorphToSelect;
12-
use Filament\Infolists\Components\TextEntry;
12+
use Filament\Forms\Components\Checkbox;
1313
use Filament\Notifications\Notification;
14-
use Filament\Resources\Pages\CreateRecord;
1514
use Filament\Resources\Pages\EditRecord;
1615
use Filament\Resources\Pages\ViewRecord;
17-
use Filament\Resources\Resource;
1816
use Illuminate\Database\Eloquent\Builder;
17+
use Filament\Resources\Pages\CreateRecord;
18+
use Filament\Forms\Components\MorphToSelect;
19+
use Filament\Infolists\Components\TextEntry;
1920
use Illuminate\Database\Eloquent\SoftDeletes;
20-
use Illuminate\Database\Eloquent\SoftDeletingScope;
2121
use Moox\Clipboard\Forms\Components\CopyableField;
22+
use Illuminate\Database\Eloquent\SoftDeletingScope;
2223

2324
abstract class BaseResource extends Resource
2425
{
@@ -378,7 +379,50 @@ public static function getPublishAction(): Action
378379
->label(__('core::core.publish'))
379380
->keyBindings(['command+p', 'ctrl+p'])
380381
->color('secondary')
381-
->action(function ($livewire): void {
382+
->form(function ($livewire) {
383+
if ($livewire->record && method_exists($livewire->record, 'translations')) {
384+
$config = config('core.draft_publish_logic', [
385+
'auto_publish_single' => true,
386+
'prompt_when_all_published' => true,
387+
'prompt_when_any_published' => false,
388+
]);
389+
390+
$allTranslations = $livewire->record->translations()->get();
391+
$translationCount = $allTranslations->count();
392+
393+
if ($translationCount > 1) {
394+
$currentLocale = $livewire->lang ?? app()->getLocale();
395+
$publishedCount = $allTranslations->where('translation_status', 'published')->count();
396+
397+
$currentTranslation = $allTranslations->where('locale', $currentLocale)->first();
398+
if ($currentTranslation && $currentTranslation->translation_status !== 'published') {
399+
$publishedCount++; // This one will be published
400+
}
401+
402+
$shouldAsk = false;
403+
404+
if ($config['prompt_when_all_published'] && $publishedCount === $translationCount && $livewire->record->status !== 'published') {
405+
$shouldAsk = true;
406+
}
407+
408+
if ($config['prompt_when_any_published'] && $publishedCount > 0 && $livewire->record->status !== 'published') {
409+
$shouldAsk = true;
410+
}
411+
412+
if ($shouldAsk) {
413+
return [
414+
Checkbox::make('publish_main_entry')
415+
->label(__('core::core.publish_main_entry'))
416+
->helperText(__('core::core.publish_main_entry_description'))
417+
->default(true),
418+
];
419+
}
420+
}
421+
}
422+
423+
return [];
424+
})
425+
->action(function ($livewire, array $data): void {
382426
$livewire->data['translation_status'] = 'published';
383427
$livewire->save();
384428

@@ -393,6 +437,11 @@ public static function getPublishAction(): Action
393437
$translation->save();
394438
}
395439

440+
if (isset($data['publish_main_entry']) && $data['publish_main_entry'] && $livewire->record) {
441+
$livewire->record->status = 'published';
442+
$livewire->record->save();
443+
}
444+
396445
$url = static::getUrl('view', ['record' => $livewire->record]);
397446
if (isset($livewire->lang)) {
398447
$url .= '?lang='.$livewire->lang;

packages/core/src/Entities/Items/Draft/BaseDraftModel.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,10 @@ protected static function boot(): void
9393
static::creating(function ($model) {
9494
$model->uuid = (string) Str::uuid();
9595
$model->ulid = (string) Str::ulid();
96+
97+
if (empty($model->status)) {
98+
$model->status = 'draft';
99+
}
96100
});
97101

98102
static::deleted(function ($model) {

packages/core/src/Entities/Items/Draft/BaseDraftTranslationModel.php

Lines changed: 100 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@
22

33
namespace Moox\Core\Entities\Items\Draft;
44

5+
use Illuminate\Support\Facades\DB;
56
use Illuminate\Database\Eloquent\Model;
6-
use Illuminate\Database\Eloquent\Relations\MorphTo;
77
use Illuminate\Database\Eloquent\SoftDeletes;
8+
use Illuminate\Database\Eloquent\Relations\MorphTo;
89

910
abstract class BaseDraftTranslationModel extends Model
1011
{
@@ -108,6 +109,10 @@ protected static function boot(): void
108109
parent::boot();
109110

110111
static::creating(function ($model) {
112+
if (empty($model->translation_status)) {
113+
$model->translation_status = 'draft';
114+
}
115+
111116
if (auth()->check()) {
112117
$model->createdBy()->associate(auth()->user());
113118
}
@@ -121,6 +126,100 @@ protected static function boot(): void
121126
static::updating(function ($model) {
122127
$model->updatedBy()->associate(auth()->user());
123128
});
129+
130+
static::saved(function ($model) {
131+
DB::afterCommit(function () use ($model) {
132+
$model->checkAndUpdateMainEntryStatus();
133+
});
134+
});
135+
}
136+
137+
/**
138+
* Check and update main entry status based on translation statuses
139+
*/
140+
protected function checkAndUpdateMainEntryStatus(): void
141+
{
142+
$mainEntry = $this->getMainEntry();
143+
144+
if (!$mainEntry) {
145+
return;
146+
}
147+
148+
$config = config('core.draft_publish_logic', [
149+
'auto_publish_single' => true,
150+
'prompt_when_all_published' => true,
151+
'prompt_when_any_published' => false,
152+
]);
153+
154+
$mainEntry->load('translations');
155+
$allTranslations = $mainEntry->translations;
156+
$translationCount = $allTranslations->count();
157+
158+
$publishedCount = $allTranslations->where('translation_status', 'published')->count();
159+
160+
if ($translationCount === 1 && $config['auto_publish_single']) {
161+
$singleTranslation = $allTranslations->first();
162+
$newStatus = null;
163+
164+
if ($singleTranslation->translation_status === 'published') {
165+
$newStatus = 'published';
166+
} elseif (in_array($singleTranslation->translation_status, ['draft', 'waiting', 'private', 'scheduled'])) {
167+
$newStatus = $singleTranslation->translation_status;
168+
}
169+
170+
if ($newStatus && $mainEntry->status !== $newStatus) {
171+
$mainEntry->status = $newStatus;
172+
$mainEntry->timestamps = false; // Prevent updated_at from changing
173+
$mainEntry->save();
174+
$mainEntry->timestamps = true;
175+
}
176+
}
177+
178+
if ($translationCount > 1) {
179+
if ($publishedCount === 0 && $mainEntry->status === 'published') {
180+
$mainEntry->status = 'draft';
181+
$mainEntry->timestamps = false;
182+
$mainEntry->save();
183+
$mainEntry->timestamps = true;
184+
}
185+
186+
if ($mainEntry->status === 'published' && $publishedCount < $translationCount) {
187+
$unpublishedStatuses = $allTranslations
188+
->where('translation_status', '!=', 'published')
189+
->pluck('translation_status')
190+
->countBy()
191+
->sortDesc();
192+
193+
$newStatus = $unpublishedStatuses->keys()->first() ?? 'draft';
194+
if ($mainEntry->status !== $newStatus) {
195+
$mainEntry->status = $newStatus;
196+
$mainEntry->timestamps = false;
197+
$mainEntry->save();
198+
$mainEntry->timestamps = true;
199+
}
200+
}
201+
}
202+
}
203+
204+
/**
205+
* Get the main entry (parent model) for this translation
206+
* Uses the translatable relation that already exists
207+
*/
208+
protected function getMainEntry()
209+
{
210+
$tableName = $this->getTable();
211+
$foreignKey = str_replace('_translations', '_id', $tableName);
212+
213+
if (isset($this->attributes[$foreignKey]) && $this->attributes[$foreignKey]) {
214+
$parentClass = get_class($this);
215+
$parentClass = str_replace('Translation', '', $parentClass);
216+
217+
if (class_exists($parentClass)) {
218+
return $parentClass::find($this->attributes[$foreignKey]);
219+
}
220+
}
221+
222+
return null;
124223
}
125224

126225
/**

0 commit comments

Comments
 (0)