events werden nun erfolgreich gespeichert, branding wird nun erfolgreich gespeichert, emotionen können nun angelegt werden. Task Ansicht im Event admin verbessert, Buttons in FAB umgewandelt und vereinheitlicht. Teilen-Link Guest PWA schicker gemacht, SynGoogleFonts ausgebaut (mit Einzel-Family-Download).
This commit is contained in:
@@ -13,6 +13,7 @@ use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class EmotionController extends Controller
|
||||
{
|
||||
@@ -21,8 +22,15 @@ class EmotionController extends Controller
|
||||
$tenantId = $this->currentTenant($request)->id;
|
||||
|
||||
$query = Emotion::query()
|
||||
->whereNull('tenant_id')
|
||||
->orWhere('tenant_id', $tenantId)
|
||||
->when(true, function ($builder) use ($tenantId) {
|
||||
// Prefer tenant-specific and global emotions if the column exists
|
||||
if (Schema::hasColumn('emotions', 'tenant_id')) {
|
||||
$builder->where(function ($inner) use ($tenantId) {
|
||||
$inner->whereNull('tenant_id')
|
||||
->orWhere('tenant_id', $tenantId);
|
||||
});
|
||||
}
|
||||
})
|
||||
->with('eventTypes');
|
||||
|
||||
if ($request->boolean('only_tenant')) {
|
||||
@@ -35,7 +43,18 @@ class EmotionController extends Controller
|
||||
|
||||
$query->orderByRaw('tenant_id is null desc')->orderBy('sort_order')->orderBy('id');
|
||||
|
||||
$emotions = $query->paginate($request->integer('per_page', 25));
|
||||
$emotions = $query->paginate($request->integer('per_page', 50));
|
||||
|
||||
if ($emotions->isEmpty() && ! $request->boolean('only_tenant')) {
|
||||
// Fallback: return any emotions regardless of tenant to avoid empty selectors
|
||||
$fallback = Emotion::query()
|
||||
->with('eventTypes')
|
||||
->orderBy('sort_order')
|
||||
->orderBy('id')
|
||||
->paginate($request->integer('per_page', 50));
|
||||
|
||||
return EmotionResource::collection($fallback);
|
||||
}
|
||||
|
||||
return EmotionResource::collection($emotions);
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ class TaskCollectionController extends Controller
|
||||
$query = TaskCollection::query()
|
||||
->forTenant($tenantId)
|
||||
->with('eventType')
|
||||
->withCount('tasks')
|
||||
->withCount(['tasks', 'events'])
|
||||
->orderBy('position')
|
||||
->orderBy('id');
|
||||
|
||||
@@ -46,6 +46,27 @@ class TaskCollectionController extends Controller
|
||||
$query->where('tenant_id', $tenantId);
|
||||
}
|
||||
|
||||
if ($request->boolean('top_picks')) {
|
||||
if ($eventTypeSlug = $request->query('event_type')) {
|
||||
$query->where(function ($inner) use ($eventTypeSlug) {
|
||||
$inner->whereNull('event_type_id')
|
||||
->orWhereHas('eventType', fn ($q) => $q->where('slug', $eventTypeSlug));
|
||||
});
|
||||
}
|
||||
|
||||
$query->whereHas('tasks')
|
||||
->orderByDesc('events_count')
|
||||
->orderByDesc('updated_at')
|
||||
->orderBy('position')
|
||||
->orderBy('id');
|
||||
|
||||
$limit = $request->integer('limit', 3);
|
||||
|
||||
return TaskCollectionResource::collection(
|
||||
$query->limit($limit)->get()
|
||||
);
|
||||
}
|
||||
|
||||
$perPage = $request->integer('per_page', 15);
|
||||
|
||||
return TaskCollectionResource::collection(
|
||||
@@ -57,7 +78,8 @@ class TaskCollectionController extends Controller
|
||||
{
|
||||
$this->authorizeAccess($request, $collection);
|
||||
|
||||
$collection->load(['eventType', 'tasks' => fn ($query) => $query->with('assignedEvents')]);
|
||||
$collection->load(['eventType', 'tasks' => fn ($query) => $query->with('assignedEvents')])
|
||||
->loadCount(['tasks', 'events']);
|
||||
|
||||
return response()->json(new TaskCollectionResource($collection));
|
||||
}
|
||||
@@ -81,7 +103,11 @@ class TaskCollectionController extends Controller
|
||||
|
||||
return response()->json([
|
||||
'message' => __('Task-Collection erfolgreich importiert.'),
|
||||
'collection' => new TaskCollectionResource($result['collection']->load('eventType')->loadCount('tasks')),
|
||||
'collection' => new TaskCollectionResource(
|
||||
$result['collection']
|
||||
->load('eventType')
|
||||
->loadCount(['tasks', 'events'])
|
||||
),
|
||||
'created_task_ids' => $result['created_task_ids'],
|
||||
'attached_task_ids' => $result['attached_task_ids'],
|
||||
]);
|
||||
|
||||
@@ -31,7 +31,7 @@ class TaskController extends Controller
|
||||
$inner->whereNull('tenant_id')
|
||||
->orWhere('tenant_id', $tenantId);
|
||||
})
|
||||
->with(['taskCollection', 'assignedEvents', 'eventType'])
|
||||
->with(['taskCollection', 'assignedEvents', 'eventType', 'emotion'])
|
||||
->orderByRaw('tenant_id is null desc')
|
||||
->orderBy('sort_order')
|
||||
->orderBy('created_at', 'desc');
|
||||
@@ -80,7 +80,7 @@ class TaskController extends Controller
|
||||
|
||||
$task = Task::create($payload);
|
||||
|
||||
$task->load(['taskCollection', 'assignedEvents', 'eventType']);
|
||||
$task->load(['taskCollection', 'assignedEvents', 'eventType', 'emotion']);
|
||||
|
||||
return response()->json([
|
||||
'message' => 'Task erfolgreich erstellt.',
|
||||
@@ -97,7 +97,7 @@ class TaskController extends Controller
|
||||
abort(404, 'Task nicht gefunden.');
|
||||
}
|
||||
|
||||
$task->load(['taskCollection', 'assignedEvents', 'eventType']);
|
||||
$task->load(['taskCollection', 'assignedEvents', 'eventType', 'emotion']);
|
||||
|
||||
return response()->json(new TaskResource($task));
|
||||
}
|
||||
@@ -156,7 +156,7 @@ class TaskController extends Controller
|
||||
{
|
||||
$tenantId = $this->currentTenant($request)->id;
|
||||
|
||||
if ($task->tenant_id !== $tenantId || $event->tenant_id !== $tenantId) {
|
||||
if (($task->tenant_id && $task->tenant_id !== $tenantId) || $event->tenant_id !== $tenantId) {
|
||||
abort(404);
|
||||
}
|
||||
|
||||
@@ -193,7 +193,9 @@ class TaskController extends Controller
|
||||
}
|
||||
|
||||
$tasks = Task::whereIn('id', $taskIds)
|
||||
->where('tenant_id', $tenantId)
|
||||
->where(function ($query) use ($tenantId) {
|
||||
$query->whereNull('tenant_id')->orWhere('tenant_id', $tenantId);
|
||||
})
|
||||
->get();
|
||||
|
||||
$attached = 0;
|
||||
@@ -219,13 +221,63 @@ class TaskController extends Controller
|
||||
}
|
||||
|
||||
$tasks = Task::whereHas('assignedEvents', fn ($q) => $q->where('event_id', $event->id))
|
||||
->with(['taskCollection', 'eventType'])
|
||||
->orderBy('created_at', 'desc')
|
||||
->with(['taskCollection', 'eventType', 'emotion'])
|
||||
->orderBy('tasks.id')
|
||||
->paginate($request->get('per_page', 15));
|
||||
|
||||
return TaskResource::collection($tasks);
|
||||
}
|
||||
|
||||
public function bulkDetachFromEvent(Request $request, Event $event): JsonResponse
|
||||
{
|
||||
$tenantId = $this->currentTenant($request)->id;
|
||||
|
||||
if ($event->tenant_id !== $tenantId) {
|
||||
abort(404);
|
||||
}
|
||||
|
||||
$taskIds = $request->input('task_ids', []);
|
||||
|
||||
if (empty($taskIds)) {
|
||||
return ApiError::response(
|
||||
'task_ids_missing',
|
||||
'Keine Aufgaben angegeben',
|
||||
'Bitte wähle mindestens eine Aufgabe aus.',
|
||||
Response::HTTP_BAD_REQUEST
|
||||
);
|
||||
}
|
||||
|
||||
$detached = $event->tasks()->whereIn('tasks.id', $taskIds)->detach();
|
||||
|
||||
return response()->json([
|
||||
'message' => "{$detached} Tasks vom Event entfernt.",
|
||||
]);
|
||||
}
|
||||
|
||||
public function reorderForEvent(Request $request, Event $event): JsonResponse
|
||||
{
|
||||
$tenantId = $this->currentTenant($request)->id;
|
||||
|
||||
if ($event->tenant_id !== $tenantId) {
|
||||
abort(404);
|
||||
}
|
||||
|
||||
$taskIds = $request->input('task_ids', []);
|
||||
|
||||
if (empty($taskIds) || ! is_array($taskIds)) {
|
||||
return ApiError::response(
|
||||
'task_ids_missing',
|
||||
'Keine Aufgaben angegeben',
|
||||
'Bitte wähle mindestens eine Aufgabe aus.',
|
||||
Response::HTTP_BAD_REQUEST
|
||||
);
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'message' => 'Reihenfolge gespeichert.',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get tasks from a specific collection.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user