tenant admin startseite schicker gestaltet und super-admin und tenant admin (filament) aufgesplittet.
Es gibt nun task collections und vordefinierte tasks für alle. Onboarding verfeinert und webseite-carousel gefixt (logging später entfernen!)
This commit is contained in:
@@ -10,7 +10,13 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Spatie\Translatable\HasTranslations;
|
||||
use League\CommonMark\CommonMarkConverter;
|
||||
use League\CommonMark\Environment\Environment;
|
||||
use League\CommonMark\Extension\CommonMark\CommonMarkCoreExtension;
|
||||
use League\CommonMark\Extension\Table\TableExtension;
|
||||
use League\CommonMark\Extension\Autolink\AutolinkExtension;
|
||||
use League\CommonMark\Extension\Strikethrough\StrikethroughExtension;
|
||||
use League\CommonMark\Extension\TaskList\TaskListExtension;
|
||||
use League\CommonMark\MarkdownConverter;
|
||||
|
||||
class BlogPost extends Model
|
||||
{
|
||||
@@ -54,7 +60,15 @@ class BlogPost extends Model
|
||||
{
|
||||
return Attribute::get(function () {
|
||||
$markdown = $this->getTranslation('content', app()->getLocale());
|
||||
$converter = new CommonMarkConverter();
|
||||
|
||||
$environment = new Environment();
|
||||
$environment->addExtension(new CommonMarkCoreExtension());
|
||||
$environment->addExtension(new TableExtension());
|
||||
$environment->addExtension(new AutolinkExtension());
|
||||
$environment->addExtension(new StrikethroughExtension());
|
||||
$environment->addExtension(new TaskListExtension());
|
||||
|
||||
$converter = new MarkdownConverter($environment);
|
||||
return $converter->convert($markdown);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
|
||||
@@ -18,6 +19,11 @@ class Emotion extends Model
|
||||
'description' => 'array',
|
||||
];
|
||||
|
||||
public function tenant(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Tenant::class);
|
||||
}
|
||||
|
||||
public function eventTypes(): BelongsToMany
|
||||
{
|
||||
return $this->belongsToMany(EventType::class, 'emotion_event_type', 'emotion_id', 'event_type_id');
|
||||
|
||||
@@ -6,10 +6,13 @@ use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Znck\Eloquent\Relations\BelongsToThrough as BelongsToThroughRelation;
|
||||
use Znck\Eloquent\Traits\BelongsToThrough;
|
||||
|
||||
class Photo extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
use BelongsToThrough;
|
||||
|
||||
protected $table = 'photos';
|
||||
protected $guarded = [];
|
||||
@@ -47,5 +50,12 @@ class Photo extends Model
|
||||
{
|
||||
return $this->hasMany(PhotoLike::class);
|
||||
}
|
||||
}
|
||||
|
||||
public function tenant(): BelongsToThroughRelation
|
||||
{
|
||||
return $this->belongsToThrough(
|
||||
Tenant::class,
|
||||
Event::class
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,11 +2,14 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class Task extends Model
|
||||
{
|
||||
@@ -38,6 +41,59 @@ class Task extends Model
|
||||
return $this->belongsTo(TaskCollection::class, 'collection_id');
|
||||
}
|
||||
|
||||
public function tenant(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Tenant::class);
|
||||
}
|
||||
|
||||
public function sourceTask(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Task::class, 'source_task_id');
|
||||
}
|
||||
|
||||
public function derivedTasks(): HasMany
|
||||
{
|
||||
return $this->hasMany(Task::class, 'source_task_id');
|
||||
}
|
||||
|
||||
public function sourceCollection(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(TaskCollection::class, 'source_collection_id');
|
||||
}
|
||||
|
||||
public function scopeForTenant(Builder $query, ?int $tenantId): Builder
|
||||
{
|
||||
return $query->where(function (Builder $innerQuery) use ($tenantId) {
|
||||
$innerQuery->whereNull('tenant_id');
|
||||
|
||||
if ($tenantId) {
|
||||
$innerQuery->orWhere('tenant_id', $tenantId);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected static function booted(): void
|
||||
{
|
||||
static::creating(function (Task $task) {
|
||||
if (! $task->slug) {
|
||||
$task->slug = static::generateSlug(
|
||||
$task->title['en'] ?? $task->title['de'] ?? 'task'
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected static function generateSlug(string $base): string
|
||||
{
|
||||
$slugBase = Str::slug($base) ?: 'task';
|
||||
|
||||
do {
|
||||
$slug = $slugBase . '-' . Str::random(6);
|
||||
} while (static::where('slug', $slug)->exists());
|
||||
|
||||
return $slug;
|
||||
}
|
||||
|
||||
public function assignedEvents(): BelongsToMany
|
||||
{
|
||||
return $this->belongsToMany(Event::class, 'event_task', 'task_id', 'event_id')
|
||||
|
||||
@@ -4,7 +4,10 @@ namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Support\Arr;
|
||||
|
||||
class TaskCollection extends Model
|
||||
{
|
||||
@@ -14,10 +17,40 @@ class TaskCollection extends Model
|
||||
|
||||
protected $fillable = [
|
||||
'tenant_id',
|
||||
'name',
|
||||
'description',
|
||||
'slug',
|
||||
'name_translations',
|
||||
'description_translations',
|
||||
'event_type_id',
|
||||
'source_collection_id',
|
||||
'is_default',
|
||||
'position',
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'name_translations' => 'array',
|
||||
'description_translations' => 'array',
|
||||
];
|
||||
|
||||
public function eventType(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(EventType::class);
|
||||
}
|
||||
|
||||
public function tenant(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Tenant::class);
|
||||
}
|
||||
|
||||
public function sourceCollection(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(TaskCollection::class, 'source_collection_id');
|
||||
}
|
||||
|
||||
public function derivedCollections(): HasMany
|
||||
{
|
||||
return $this->hasMany(TaskCollection::class, 'source_collection_id');
|
||||
}
|
||||
|
||||
public function tasks(): BelongsToMany
|
||||
{
|
||||
return $this->belongsToMany(
|
||||
@@ -25,7 +58,7 @@ class TaskCollection extends Model
|
||||
'task_collection_task',
|
||||
'task_collection_id',
|
||||
'task_id'
|
||||
);
|
||||
)->withPivot(['sort_order']);
|
||||
}
|
||||
|
||||
public function events(): BelongsToMany
|
||||
@@ -35,7 +68,49 @@ class TaskCollection extends Model
|
||||
'event_task_collection',
|
||||
'task_collection_id',
|
||||
'event_id'
|
||||
);
|
||||
)->withPivot(['sort_order'])->withTimestamps();
|
||||
}
|
||||
|
||||
public function scopeGlobal($query)
|
||||
{
|
||||
return $query->whereNull('tenant_id');
|
||||
}
|
||||
|
||||
public function scopeForTenant($query, ?int $tenantId)
|
||||
{
|
||||
return $query->where(function ($inner) use ($tenantId) {
|
||||
$inner->whereNull('tenant_id');
|
||||
|
||||
if ($tenantId) {
|
||||
$inner->orWhere('tenant_id', $tenantId);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public function getNameAttribute(): string
|
||||
{
|
||||
return $this->resolveTranslation('name_translations');
|
||||
}
|
||||
|
||||
public function getDescriptionAttribute(): ?string
|
||||
{
|
||||
$value = $this->resolveTranslation('description_translations');
|
||||
|
||||
return $value ?: null;
|
||||
}
|
||||
|
||||
protected function resolveTranslation(string $attribute, ?string $locale = null): string
|
||||
{
|
||||
$translations = $this->{$attribute} ?? [];
|
||||
|
||||
if (is_string($translations)) {
|
||||
$translations = json_decode($translations, true) ?: [];
|
||||
}
|
||||
|
||||
$locale = $locale ?? app()->getLocale();
|
||||
|
||||
return $translations[$locale]
|
||||
?? Arr::first($translations)
|
||||
?? '';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -116,7 +116,11 @@ class User extends Authenticatable implements MustVerifyEmail, HasName, Filament
|
||||
return false;
|
||||
}
|
||||
|
||||
return in_array($this->role, ['tenant_admin', 'super_admin'], true);
|
||||
return match ($panel->getId()) {
|
||||
'superadmin' => $this->role === 'super_admin',
|
||||
'admin' => $this->role === 'tenant_admin',
|
||||
default => false,
|
||||
};
|
||||
}
|
||||
|
||||
public function canAccessTenant(Model $tenant): bool
|
||||
|
||||
Reference in New Issue
Block a user