Merge branch 'dev' of ssh://git.congegni.net:4022/Congegni/sintonia_webapp into dev
This commit is contained in:
commit
36d3deab44
26 changed files with 521 additions and 243 deletions
|
@ -15,7 +15,14 @@ enum ShowRepeatType: int
|
||||||
return constant("self::$name");
|
return constant("self::$name");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function fromValue(int $value){
|
|
||||||
return constant("self::$value");
|
public static function fromValue(string $value){
|
||||||
|
foreach (self::cases() as $case) {
|
||||||
|
if ($case->value === $value) {
|
||||||
|
return $case;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new \InvalidArgumentException("No matching UserType found for value: $value");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
37
app/Filters/Show/ShowDaysFilters.php
Normal file
37
app/Filters/Show/ShowDaysFilters.php
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Filters\Show;
|
||||||
|
|
||||||
|
use App\Filters\FiltersType\IsFilter;
|
||||||
|
use App\Filters\FiltersType\LikeFilter;
|
||||||
|
|
||||||
|
class ShowDaysFilters
|
||||||
|
{
|
||||||
|
protected $filters = [
|
||||||
|
'show_id' => IsFilter::class,
|
||||||
|
];
|
||||||
|
|
||||||
|
public function apply($query, $filters)
|
||||||
|
{
|
||||||
|
foreach ($this->receivedFilters($filters) as $name => $value) {
|
||||||
|
switch ($name) {
|
||||||
|
case 'all':
|
||||||
|
$name = array_diff(array_keys($this->filters), ['all']);
|
||||||
|
$filterInstance = new $this->filters['all']();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$filterInstance = new $this->filters[$name]();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
$query = $filterInstance($query, $name, $value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $query;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function receivedFilters($filters)
|
||||||
|
{
|
||||||
|
return $filters->only(array_keys($this->filters));
|
||||||
|
}
|
||||||
|
}
|
|
@ -40,6 +40,7 @@ class CarbonShowRepetition
|
||||||
while ($currentDate->lte($dateStopInterval)) {
|
while ($currentDate->lte($dateStopInterval)) {
|
||||||
if ($repeatTypeEnum === ShowRepeatType::monthly) {
|
if ($repeatTypeEnum === ShowRepeatType::monthly) {
|
||||||
$nextMonth = $currentDate->addMonth();
|
$nextMonth = $currentDate->addMonth();
|
||||||
|
// With a flag we can skip this check and repeating based on the given month number
|
||||||
if ($nextMonth->day > $currentDate->day) {
|
if ($nextMonth->day > $currentDate->day) {
|
||||||
$nextMonth->day = $currentDate->day;
|
$nextMonth->day = $currentDate->day;
|
||||||
}
|
}
|
||||||
|
@ -52,4 +53,13 @@ class CarbonShowRepetition
|
||||||
|
|
||||||
return $dates;
|
return $dates;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function getNextStartDate(string $showFirstDate, int $showDayNumber): Carbon {
|
||||||
|
$date = Carbon::createFromFormat('Y-m-d', $showFirstDate);
|
||||||
|
$dayOfWeek = $date->dayOfWeek;
|
||||||
|
if($dayOfWeek != $showDayNumber){
|
||||||
|
$date = $date->next($showDayNumber);
|
||||||
|
}
|
||||||
|
return $date;
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -42,16 +42,17 @@ class ShowController extends Controller
|
||||||
public function store(Request $request)
|
public function store(Request $request)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$showInfos = $request->show;
|
$showData = $request->all();
|
||||||
$showDaysRules = $request->showDaysRules;
|
$showDays = $showData['show_days'];
|
||||||
$showDjs = $request->showDjs;
|
$showDJs = $showData['show_djs'];
|
||||||
$show = Show::firstOrCreate($showInfos);
|
$this->createShow($showData, $showDays, $showDJs);
|
||||||
$this->manageShowDays($show, $showDaysRules);
|
return response()->json([
|
||||||
$this->manageShowDjs($showDjs, $show);
|
'status' => 'success',
|
||||||
}catch(Exception $e){
|
'message' => 'Show saved successfully!'
|
||||||
|
]);
|
||||||
|
} catch (Exception $e) {
|
||||||
return response()->json(['message' => $e->getMessage()], 500);
|
return response()->json(['message' => $e->getMessage()], 500);
|
||||||
}
|
}
|
||||||
return response()->json(['message' => 'Show created successfully']);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function show(ShowResource $show)
|
public function show(ShowResource $show)
|
||||||
|
|
49
app/Http/Controllers/Show/ShowDaysController.php
Normal file
49
app/Http/Controllers/Show/ShowDaysController.php
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Show;
|
||||||
|
|
||||||
|
use App\Filters\Show\ShowFilters;
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Http\Requests\ShowDaysRequest;
|
||||||
|
use App\Http\Resources\ShowDaysResource;
|
||||||
|
use App\Models\Show\Show;
|
||||||
|
use App\Models\Show\ShowDays;
|
||||||
|
use App\Traits\Show\ShowDaysTrait;
|
||||||
|
use Illuminate\Http\ReqshowDaysFlatest;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
|
class ShowDaysController extends Controller
|
||||||
|
{
|
||||||
|
use ShowDaysTrait;
|
||||||
|
public function index(Request $request)
|
||||||
|
{
|
||||||
|
$queryParams = collect($request->except('flattenShowDays'));
|
||||||
|
$showDays = (new ShowDays())->searchFilter($queryParams)->get();
|
||||||
|
if($request->flattenShowDays) $showDays = $this->showDaysFlat($showDays);
|
||||||
|
return response()->json($showDays);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function store(ShowDaysRequest $request)
|
||||||
|
{
|
||||||
|
return new ShowDaysResource(ShowDays::create($request->validated()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function show(ShowDays $ShowDays)
|
||||||
|
{
|
||||||
|
return new ShowDaysResource($ShowDays);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function update(ShowDaysRequest $request, ShowDays $ShowDays)
|
||||||
|
{
|
||||||
|
$ShowDays->update($request->validated());
|
||||||
|
|
||||||
|
return new ShowDaysResource($ShowDays);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function destroy(ShowDays $ShowDays)
|
||||||
|
{
|
||||||
|
$ShowDays->delete();
|
||||||
|
|
||||||
|
return response()->json();
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
namespace App\Models\Show;
|
namespace App\Models\Show;
|
||||||
|
|
||||||
|
use App\Filters\Show\ShowDaysFilters;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
|
@ -41,4 +42,9 @@ class ShowDays extends Model
|
||||||
{
|
{
|
||||||
return $this->belongsTo(Show::class, 'show_id');
|
return $this->belongsTo(Show::class, 'show_id');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function scopeSearchFilter($query, $request) {
|
||||||
|
$filters = new ShowDaysFilters();
|
||||||
|
return $filters->apply($query, $request);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,9 +3,12 @@
|
||||||
namespace App\Traits\Show;
|
namespace App\Traits\Show;
|
||||||
|
|
||||||
use App\Enums\ShowRepeatType;
|
use App\Enums\ShowRepeatType;
|
||||||
|
use App\Helpers\CarbonShowRepetition;
|
||||||
|
use App\Helpers\Preferences;
|
||||||
use App\Lib\RabbitMQSender;
|
use App\Lib\RabbitMQSender;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
|
||||||
Trait ShowDaysTrait
|
trait ShowDaysTrait
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Each show may have a repetition rules, we set them in the db
|
* Each show may have a repetition rules, we set them in the db
|
||||||
|
@ -13,42 +16,43 @@ Trait ShowDaysTrait
|
||||||
* @param $showDaysRules
|
* @param $showDaysRules
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
|
* @throws \Exception
|
||||||
*/
|
*/
|
||||||
public function createShowDays($show, $showDays)
|
public function createShowDays($show, $showDays): void
|
||||||
{
|
{
|
||||||
for ($i = 0; $i < count($showDays['day']); $i++) {
|
try {
|
||||||
$showDay = $showDays;
|
// TODO this is incorrect, look up the preference helper, getDefaultTimezone is called statically but it should not
|
||||||
$showDay['repeat_type'] = ShowRepeatType::fromName($showDays['repeat_type']);
|
$timezone = config('app.timezone');
|
||||||
$showDay['day'] = $showDays['day'][$i];
|
foreach ($showDays['day'] as $day) {
|
||||||
|
$showDay = $showDays;
|
||||||
// Check if showDay already exists for this day and show ID
|
$showDay['first_show'] = CarbonShowRepetition::getNextStartDate($showDays['first_show'], $day);
|
||||||
$existingShowDay = $show->showDays()->where('day', $showDay['day'])->first();
|
$showDay['repeat_type'] = ShowRepeatType::fromName($showDays['repeat_type'])->value;
|
||||||
|
$showDay['day'] = $day;
|
||||||
if ($existingShowDay) {
|
$show->showDays()->create(
|
||||||
$existingShowDay->update([
|
[
|
||||||
'first_show' => $showDay['first_show'],
|
'first_show' => $showDay['first_show'],
|
||||||
'start_time' => $showDay['start_time'],
|
'start_time' => $showDay['start_time'],
|
||||||
'timezone' => $showDay['timezone'],
|
'timezone' => $showDay['timezone'],
|
||||||
'duration' => $showDay['duration'],
|
'duration' => $showDay['duration'],
|
||||||
'repeat_type' => $showDay['repeat_type']->value,
|
'repeat_type' => $showDay['repeat_type'],
|
||||||
]);
|
'day' => $showDay['day'],
|
||||||
continue;
|
'timezone' => $timezone,
|
||||||
|
]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
$show->showDays()->create($showDay);
|
} catch (\Exception $e) {
|
||||||
|
throw new \Exception($e->getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function manageShowDays($show, $showDays)
|
public function showDaysFlat(Collection $showDays): array {
|
||||||
{
|
$baseProps = $showDays->first()->toArray();
|
||||||
// TODO Determine if the show days rules have been changed
|
$earliestDate = $showDays->min('first_show');
|
||||||
// By editing the createShowDays, returning the days on which the rules have been changed
|
$daysArray = $showDays->pluck('day')->toArray();
|
||||||
// one could trigger the creation of only specific instances
|
|
||||||
// The hard part relies on finding out which show instances
|
return array_merge($baseProps, [
|
||||||
// belong to which showDays rules, as they do not have any fk to showDays
|
'first_show' => $earliestDate,
|
||||||
// Probably its complexity is higher than its advantages
|
'day' => $daysArray,
|
||||||
// if it is, then proceed to edit the show days rules and generate the show instances
|
]);
|
||||||
$this->createShowDays($show, $showDays);
|
|
||||||
$this->manageShowInstances($show);
|
|
||||||
RabbitMQSender::SendMessageToPypo('update_schedule', []);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -11,7 +11,7 @@ trait ShowDjTrait
|
||||||
/**
|
/**
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
public function manageShowDjs(array $showDjs, Show $show)
|
public function manageShowDjs(Show $show, array $showDjs)
|
||||||
{
|
{
|
||||||
// TODO Add protection so only Editor and Admin can edit the djs
|
// TODO Add protection so only Editor and Admin can edit the djs
|
||||||
|
|
||||||
|
@ -22,21 +22,26 @@ trait ShowDjTrait
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch current DJs for the show
|
try {
|
||||||
$currentDjs = $show->showDjs()->pluck('subjs_id')->toArray();
|
// Fetch current DJs for the show
|
||||||
|
$currentDjs = $show->showDjs()->pluck('subjs_id')->toArray();
|
||||||
|
|
||||||
// Compute the difference
|
// Compute the difference
|
||||||
$djsToAdd = array_diff($showDjs, $currentDjs);
|
$djsToAdd = array_diff($showDjs, $currentDjs);
|
||||||
$djsToRemove = array_diff($currentDjs, $showDjs);
|
$djsToRemove = array_diff($currentDjs, $showDjs);
|
||||||
|
|
||||||
// Remove DJs not in the list
|
// Remove DJs not in the list
|
||||||
foreach ($djsToRemove as $djId) {
|
foreach ($djsToRemove as $djId) {
|
||||||
$show->showDjs()->where('subjs_id', $djId)->delete();
|
$show->showDjs()->where('subjs_id', $djId)->delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add new DJs
|
||||||
|
foreach ($djsToAdd as $djId) {
|
||||||
|
$show->showDjs()->make(['subjs_id' => $djId]);
|
||||||
|
}
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return $e->getMessage();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add new DJs
|
|
||||||
foreach ($djsToAdd as $djId) {
|
|
||||||
$show->showDjs()->updateOrCreate(['subjs_id' => $djId]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -6,6 +6,7 @@ use App\Helpers\CarbonShowRepetition;
|
||||||
use App\Helpers\LengthFormatter;
|
use App\Helpers\LengthFormatter;
|
||||||
use App\Http\Resources\ShowResource;
|
use App\Http\Resources\ShowResource;
|
||||||
use App\Models\Preference;
|
use App\Models\Preference;
|
||||||
|
use App\Models\Show\Show;
|
||||||
use App\Models\ShowInstances\ShowInstances;
|
use App\Models\ShowInstances\ShowInstances;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use Carbon\CarbonInterval;
|
use Carbon\CarbonInterval;
|
||||||
|
@ -18,33 +19,31 @@ trait ShowInstancesTrait
|
||||||
*/
|
*/
|
||||||
public function checkOverlappingInstances(array $instancesDates, $duration, int $showId): void
|
public function checkOverlappingInstances(array $instancesDates, $duration, int $showId): void
|
||||||
{
|
{
|
||||||
|
$existingRanges = ShowInstances::where('show_id', '!=', $showId)
|
||||||
|
->get(['starts', 'ends'])
|
||||||
|
->map(fn($i) => [$i->starts, $i->ends]);
|
||||||
|
|
||||||
foreach ($instancesDates as $date) {
|
foreach ($instancesDates as $date) {
|
||||||
$instanceStartDate = $date;
|
$newStart = $date;
|
||||||
$instanceEndDate = clone $date;
|
$newEnd = (clone $date)->addHours($duration);
|
||||||
$instanceEndDate->addHours($duration);
|
|
||||||
|
|
||||||
// Query to check for overlaps
|
$hasOverlap = $existingRanges->contains(
|
||||||
$overlapExists = ShowInstances::where(
|
fn($range) => $newStart < $range[1] && $newEnd > $range[0]
|
||||||
function ($query) use ($instanceStartDate, $instanceEndDate, $showId) {
|
);
|
||||||
$query->where('starts', '<=', $instanceEndDate)
|
|
||||||
->where('ends', '>=', $instanceStartDate)
|
|
||||||
->where('show_id','!=', $showId);
|
|
||||||
}
|
|
||||||
)->exists();
|
|
||||||
|
|
||||||
if ($overlapExists) {
|
if ($hasOverlap) {
|
||||||
throw new Exception('Overlapping shows'); // Overlap found
|
throw new Exception("Overlap detected between $newStart and $newEnd");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function createShowInstances($instancesDates, $showDay, $show)
|
public function createShowInstances($instancesDates, $showDayDuration, $showId)
|
||||||
{
|
{
|
||||||
$showInstances = [];
|
$showInstances = [];
|
||||||
foreach ($instancesDates as $instanceDate) {
|
foreach ($instancesDates as $instanceDate) {
|
||||||
$showStartDate = $instanceDate->copy();
|
$showStartDate = $instanceDate->copy();
|
||||||
$duration = CarbonInterval::createFromFormat('H:i:s', $showDay->duration);
|
$duration = CarbonInterval::createFromFormat('H:i', $showDayDuration);
|
||||||
$showEndDate = $showStartDate->copy()->add($duration);
|
$showEndDate = $showStartDate->copy()->add($duration);
|
||||||
|
|
||||||
$timeFilled = LengthFormatter::generateStringTimeFilled($showStartDate, $showEndDate);
|
$timeFilled = LengthFormatter::generateStringTimeFilled($showStartDate, $showEndDate);
|
||||||
|
@ -53,7 +52,7 @@ trait ShowInstancesTrait
|
||||||
$showInstances[] = [
|
$showInstances[] = [
|
||||||
'starts' => $showStartDate,
|
'starts' => $showStartDate,
|
||||||
'ends' => $showEndDate,
|
'ends' => $showEndDate,
|
||||||
'show_id' => $show->id,
|
'show_id' => $showId,
|
||||||
'record' => 0,
|
'record' => 0,
|
||||||
'rebroadcast' => 0,
|
'rebroadcast' => 0,
|
||||||
'time_filled' => $timeFilled,
|
'time_filled' => $timeFilled,
|
||||||
|
@ -73,34 +72,36 @@ trait ShowInstancesTrait
|
||||||
* @param ShowResource $ShowResource
|
* @param ShowResource $ShowResource
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
* @throws \Exception
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
public function manageShowInstances($show)
|
public function manageShowInstances(Show $show)
|
||||||
{
|
{
|
||||||
$showDays = $show->showDays;
|
try {
|
||||||
$generationLimitDate = Preference::where('keystr', 'shows_populated_until')->value('valstr');
|
$generationLimitDate = Preference::where('keystr', 'shows_populated_until')->value('valstr');
|
||||||
$generationLimitDate = Carbon::createFromFormat('Y-m-d H:i:s', $generationLimitDate);
|
$generationLimitDate = Carbon::createFromFormat('Y-m-d H:i:s', $generationLimitDate);
|
||||||
$showInstances = [];
|
$showInstances = [];
|
||||||
|
foreach ($show->showDays as $showDay) {
|
||||||
|
try {
|
||||||
|
$lastShowDate = $showDay->last_show ?? $generationLimitDate;
|
||||||
|
$instancesDates = CarbonShowRepetition::generateDates(
|
||||||
|
$showDay->repeat_type,
|
||||||
|
$showDay->first_show,
|
||||||
|
$showDay->start_time,
|
||||||
|
$lastShowDate
|
||||||
|
);
|
||||||
|
|
||||||
foreach ($showDays as $showDay) {
|
$this->checkOverlappingInstances($instancesDates, $showDay->duration, $show->id);
|
||||||
try {
|
|
||||||
$lastShowDate = $showDay->last_show ?? $generationLimitDate;
|
|
||||||
$instancesDates = CarbonShowRepetition::generateDates(
|
|
||||||
$showDay->repeat_type,
|
|
||||||
$showDay->first_show,
|
|
||||||
$showDay->start_time,
|
|
||||||
$lastShowDate
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->checkOverlappingInstances($instancesDates, $showDay->duration, $show->id);
|
$showInstances[] = $this->createShowInstances($instancesDates, $showDay->duration, $show->id);
|
||||||
|
} catch (Exception $e) {
|
||||||
$showInstances[] = $this->createShowInstances($instancesDates, $showDay, $show);
|
throw new Exception($e->getMessage(), 500);
|
||||||
} catch (\Exception $e) {
|
}
|
||||||
throw new \Exception($e->getMessage(), 500);
|
|
||||||
}
|
}
|
||||||
}
|
foreach ($showInstances as $showInstance) {
|
||||||
foreach ($showInstances as $showInstance) {
|
$show->showInstances()->createMany($showInstance);
|
||||||
$show->showInstances()->createMany($showInstance);
|
}
|
||||||
|
} catch (Exception $e) {
|
||||||
|
throw new Exception($e->getMessage(), 500);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -2,7 +2,39 @@
|
||||||
|
|
||||||
namespace App\Traits\Show;
|
namespace App\Traits\Show;
|
||||||
|
|
||||||
|
use App\Lib\RabbitMQSender;
|
||||||
|
use App\Models\Show\Show;
|
||||||
|
use App\Models\Show\ShowHosts;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
|
||||||
trait ShowTrait
|
trait ShowTrait
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @param array $showData
|
||||||
|
* @param ShowDays[] $showDays
|
||||||
|
* @param ShowHosts[] $showDJs
|
||||||
|
*
|
||||||
|
* @return string|void
|
||||||
|
* @throws \Exception
|
||||||
|
*/
|
||||||
|
public function createShow(array $showData, array $showDays, array|null $showDJs)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
DB::beginTransaction();
|
||||||
|
$show = Show::create($showData);
|
||||||
|
$this->createShowDays($show, $showDays);
|
||||||
|
if (isset($showDJs)) {
|
||||||
|
$this->manageShowDjs($show, $showDJs);
|
||||||
|
}
|
||||||
|
$this->manageShowInstances($show);
|
||||||
|
$show->save();
|
||||||
|
DB::commit();
|
||||||
|
RabbitMQSender::SendMessageToPypo('update_schedule', []);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
DB::rollBack();
|
||||||
|
throw new \Exception($e->getMessage());
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
throw new \Exception($e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,20 +1,21 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import CalendarShowEvent from "@/components/content/partials/CalendarShowEvent.vue";
|
|
||||||
import {computed, onMounted, type Ref, ref} from "vue";
|
import {computed, onMounted, type Ref, ref} from "vue";
|
||||||
import {useAuthStore} from "@/stores/auth.store.ts";
|
import {useAuthStore} from "@/stores/auth.store.ts";
|
||||||
import ShowCreateEditForm from "@partials/show/ShowCreateEditForm.vue";
|
|
||||||
import {baseShow, deleteShow} from "@models/show/show.ts";
|
import {baseShow, deleteShow} from "@models/show/show.ts";
|
||||||
import type {calendarShowEvent} from "@models/misc/calendarShowEvent.ts";
|
|
||||||
import { nextTick } from "vue";
|
|
||||||
|
|
||||||
import {baseShowInstance, getShowInstances, type ShowInstance} from "@models/show/showInstance.ts";
|
import {baseShowInstance, getShowInstances, type ShowInstance} from "@models/show/showInstance.ts";
|
||||||
import {setShowInstancesForCalendar} from "@/composables/content/dashboard_page.ts";
|
import {setShowInstancesForCalendar} from "@/composables/content/dashboard_page.ts";
|
||||||
import {baseShowDays, getShowDays} from "@models/show/showDays.ts";
|
import {baseShowDays, getShowDays} from "@models/show/showDays.ts";
|
||||||
|
import type {calendarShowEvent} from "@models/misc/calendarShowEvent.ts";
|
||||||
import ShowInstanceForm from "@partials/show/ShowInstanceForm.vue";
|
import ShowInstanceForm from "@partials/show/ShowInstanceForm.vue";
|
||||||
|
import ShowForm from "@partials/show/ShowForm.vue";
|
||||||
|
import CalendarShowEvent from "@partials/show/CalendarShowEvent.vue"
|
||||||
|
import {extractTime} from "@/helpers/DateFormatter.ts";
|
||||||
|
|
||||||
|
// Store
|
||||||
const auth = useAuthStore();
|
const auth = useAuthStore();
|
||||||
const userRole = auth.userData.user.role;
|
const userRole = auth.userData.user.role;
|
||||||
|
|
||||||
|
// Data
|
||||||
const editMode = ref(false);
|
const editMode = ref(false);
|
||||||
const showCreateEditMode = ref(false);
|
const showCreateEditMode = ref(false);
|
||||||
const showInstanceCreateEditMode = ref(false);
|
const showInstanceCreateEditMode = ref(false);
|
||||||
|
@ -22,6 +23,9 @@ const showInstances = ref<ShowInstance[]>([]);
|
||||||
let showSelected = ref(baseShow());
|
let showSelected = ref(baseShow());
|
||||||
let selectedShowInstance = ref(baseShowInstance());
|
let selectedShowInstance = ref(baseShowInstance());
|
||||||
|
|
||||||
|
const shows: Ref<calendarShowEvent[]> = computed(() => setShowInstancesForCalendar(showInstances.value));
|
||||||
|
|
||||||
|
// Funcs
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
const today = new Date();
|
const today = new Date();
|
||||||
const startOfMonth = new Date(today.getFullYear(), today.getMonth() + 1, 1);
|
const startOfMonth = new Date(today.getFullYear(), today.getMonth() + 1, 1);
|
||||||
|
@ -33,9 +37,6 @@ onMounted(async () => {
|
||||||
showInstances.value = await getShowInstances(options);
|
showInstances.value = await getShowInstances(options);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
const shows: Ref<calendarShowEvent[]> = computed(() => setShowInstancesForCalendar(showInstances.value));
|
|
||||||
|
|
||||||
const toggleEditMode = () => {
|
const toggleEditMode = () => {
|
||||||
editMode.value = !editMode.value;
|
editMode.value = !editMode.value;
|
||||||
};
|
};
|
||||||
|
@ -51,7 +52,11 @@ const contextMenuEditInstance = (showInstanceId: number) => {
|
||||||
|
|
||||||
const contextMenuEditShow = async (showInstanceId: number) => {
|
const contextMenuEditShow = async (showInstanceId: number) => {
|
||||||
showSelected.value = showInstances.value[showInstanceId].show;
|
showSelected.value = showInstances.value[showInstanceId].show;
|
||||||
showSelected.value.showDays = await getShowDays({showId: showSelected.value.id, flattenShowDays: true});
|
let showDaysRules = await getShowDays({show_id: showSelected.value.id, flattenShowDays: true});
|
||||||
|
showDaysRules.firstShow = new Date(showDaysRules.firstShow);
|
||||||
|
// TODO Timezone problems
|
||||||
|
showDaysRules.startTime = extractTime(showDaysRules.startTime, true);
|
||||||
|
showSelected.value.showDays = showDaysRules;
|
||||||
showCreateEditMode.value = true;
|
showCreateEditMode.value = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -79,7 +84,7 @@ const resetItemEdited = () => {
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<template v-if="showCreateEditMode || showInstanceCreateEditMode">
|
<template v-if="showCreateEditMode || showInstanceCreateEditMode">
|
||||||
<ShowCreateEditForm v-if="showCreateEditMode" :show="showSelected" @go-back="resetItemEdited" />
|
<ShowForm v-if="showCreateEditMode" :show="showSelected" @go-back="resetItemEdited" />
|
||||||
<ShowInstanceForm v-if="showInstanceCreateEditMode" :showInstance="selectedShowInstance" @toggle-menu-edit-instance="toggleMenuEditInstance" />
|
<ShowInstanceForm v-if="showInstanceCreateEditMode" :showInstance="selectedShowInstance" @toggle-menu-edit-instance="toggleMenuEditInstance" />
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
|
|
|
@ -3,7 +3,7 @@ import {reactive, ref, watch} from "vue";
|
||||||
import Table from "@partials/Table.vue";
|
import Table from "@partials/Table.vue";
|
||||||
import ConfirmDelete from "@partials/dialogs/ConfirmDelete.vue";
|
import ConfirmDelete from "@partials/dialogs/ConfirmDelete.vue";
|
||||||
import {show_page} from "@/composables/content/show/show_page.ts";
|
import {show_page} from "@/composables/content/show/show_page.ts";
|
||||||
import ShowCreateEditForm from "@partials/show/ShowCreateEditForm.vue";
|
import ShowForm from "@partials/show/ShowForm.vue";
|
||||||
import {baseShow, type Show} from "@models/show/show";
|
import {baseShow, type Show} from "@models/show/show";
|
||||||
|
|
||||||
const {items, listData, headers, selected, loading, search, getItems, editItem, deleteItem} = show_page()
|
const {items, listData, headers, selected, loading, search, getItems, editItem, deleteItem} = show_page()
|
||||||
|
@ -82,7 +82,7 @@ watch(search, (newValue, oldValue) => {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<ShowCreateEditForm
|
<ShowForm
|
||||||
v-if="showSelected.id !== null && !dialog.open"
|
v-if="showSelected.id !== null && !dialog.open"
|
||||||
:show="showSelected"
|
:show="showSelected"
|
||||||
@go-back="resetItemEdited"
|
@go-back="resetItemEdited"
|
||||||
|
|
|
@ -1,8 +1,16 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
|
||||||
import {WeekDaysData} from "@models/show/ShowRepetition.ts";
|
import {WeekDaysData} from "@models/show/ShowRepetition.ts";
|
||||||
|
import type {PropType} from "vue";
|
||||||
|
import type {Show} from "@models/show/show.ts";
|
||||||
|
|
||||||
const selectedDays = defineModel()
|
const selectedDays = defineModel()
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
fixedDay: {
|
||||||
|
type: Number,
|
||||||
|
required: false,
|
||||||
|
},
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -14,6 +22,7 @@ const selectedDays = defineModel()
|
||||||
v-model="selectedDays"
|
v-model="selectedDays"
|
||||||
:label="day.dayName"
|
:label="day.dayName"
|
||||||
:value="day.type"
|
:value="day.type"
|
||||||
|
:disabled="day.type === props.fixedDay"
|
||||||
/>
|
/>
|
||||||
</v-col>
|
</v-col>
|
||||||
</v-row>
|
</v-row>
|
||||||
|
|
|
@ -2,7 +2,8 @@
|
||||||
import {onMounted, type PropType} from "vue";
|
import {onMounted, type PropType} from "vue";
|
||||||
import { ref, watch } from 'vue';
|
import { ref, watch } from 'vue';
|
||||||
import {getShowInstances} from "@models/show/showInstance.ts";
|
import {getShowInstances} from "@models/show/showInstance.ts";
|
||||||
|
import {getHoursMinutesFromString, getTimeDiff} from "@/helpers/DateFormatter.ts";
|
||||||
|
// Emits, props and models
|
||||||
const emits = defineEmits(['update:duration'])
|
const emits = defineEmits(['update:duration'])
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
|
@ -25,37 +26,26 @@ const props = defineProps({
|
||||||
})
|
})
|
||||||
|
|
||||||
const startTime = defineModel({default: '08:00'});
|
const startTime = defineModel({default: '08:00'});
|
||||||
|
|
||||||
|
// Data
|
||||||
const duration = ref('0:0');
|
const duration = ref('0:0');
|
||||||
const endTime = ref('');
|
const endTime = ref('');
|
||||||
const startMenu = ref(false);
|
const startMenu = ref(false);
|
||||||
const endMenu = ref(false);
|
const endMenu = ref(false);
|
||||||
|
|
||||||
|
|
||||||
const getDuration = (startTime: Date, endTime: Date) => {
|
// Func
|
||||||
const diffInMilliseconds = Math.abs(startTime.getTime() - endTime.getTime());
|
|
||||||
const remainingHours = Math.floor((diffInMilliseconds % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
|
|
||||||
const remainingMinutes = Math.floor((diffInMilliseconds % (1000 * 60 * 60)) / (1000 * 60));
|
|
||||||
|
|
||||||
return `${remainingHours}:${remainingMinutes}`;
|
|
||||||
};
|
|
||||||
|
|
||||||
const getHoursMinutes = (timeString: string) => {
|
|
||||||
const [ h, m ] = timeString.split(":");
|
|
||||||
const ms = new Date().setHours(h,m);
|
|
||||||
return new Date(ms)
|
|
||||||
};
|
|
||||||
|
|
||||||
const checkTime = () => {
|
const checkTime = () => {
|
||||||
if (startTime.value && endTime) {
|
if (startTime.value && endTime) {
|
||||||
const start = getHoursMinutes(startTime.value);
|
const start: Date = getHoursMinutesFromString(startTime.value);
|
||||||
let end = getHoursMinutes(endTime.value);
|
let end: Date = getHoursMinutesFromString(endTime.value);
|
||||||
|
|
||||||
if (end.getTime() <= start.getTime()) {
|
if (end.getTime() <= start.getTime()) {
|
||||||
end = new Date(start);
|
end = new Date(start);
|
||||||
end.setMinutes(start.getMinutes() + 60);
|
end.setMinutes(start.getMinutes() + 60);
|
||||||
endTime.value = end.toLocaleTimeString('en-US', { hour12: false, hour: '2-digit', minute: '2-digit' });;
|
endTime.value = end.toLocaleTimeString('en-US', { hour12: false, hour: '2-digit', minute: '2-digit' });;
|
||||||
}
|
}
|
||||||
duration.value = getDuration(start, end);
|
duration.value = getTimeDiff(start, end);
|
||||||
emits('update:duration', duration.value);
|
emits('update:duration', duration.value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ import type { PropType} from "vue";
|
||||||
import type {ContextMenuType} from "@models/misc/contextMenu"
|
import type {ContextMenuType} from "@models/misc/contextMenu"
|
||||||
import type {calendarShowEvent, ShowEventActionTrigger} from "@models/misc/calendarShowEvent.ts";
|
import type {calendarShowEvent, ShowEventActionTrigger} from "@models/misc/calendarShowEvent.ts";
|
||||||
import {calendarShowEventMenu} from "@models/misc/calendarShowEvent";
|
import {calendarShowEventMenu} from "@models/misc/calendarShowEvent";
|
||||||
import {ref, computed, onMounted} from 'vue';
|
import { ref } from 'vue';
|
||||||
import ContextMenu from '@partials/ContextMenu.vue';
|
import ContextMenu from '@partials/ContextMenu.vue';
|
||||||
|
|
||||||
const emit = defineEmits([
|
const emit = defineEmits([
|
|
@ -7,6 +7,7 @@ import {getUser} from "@models/User.ts";
|
||||||
import {getPlaylist} from "@models/playlist.ts";
|
import {getPlaylist} from "@models/playlist.ts";
|
||||||
import ColorPickerButton from "@partials/fields/misc/ColorPickerButton.vue";
|
import ColorPickerButton from "@partials/fields/misc/ColorPickerButton.vue";
|
||||||
|
|
||||||
|
// Props
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
show: {
|
show: {
|
||||||
type: Object as PropType<Show>,
|
type: Object as PropType<Show>,
|
||||||
|
@ -14,18 +15,22 @@ const props = defineProps({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Data
|
||||||
let usersDJs = ref([])
|
let usersDJs = ref([])
|
||||||
let playlists = ref([])
|
let playlists = ref([])
|
||||||
const isLoading = ref(false);
|
const loading = ref(false);
|
||||||
const showScheduleFormMode = ref(false);
|
const showScheduleFormMode = ref(false);
|
||||||
|
const isFormValid = ref(false);
|
||||||
|
// Store
|
||||||
|
const showStore = useShowStore()
|
||||||
|
showStore.loadShow(props.show)
|
||||||
|
|
||||||
const showFormStore = useShowStore()
|
// Funcs
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
isLoading.value = true
|
loading.value = true
|
||||||
await showFormStore.loadShow(props.show)
|
|
||||||
usersDJs.value = await getUser({role: 'dj'});
|
usersDJs.value = await getUser({role: 'dj'});
|
||||||
playlists.value = await getPlaylist({});
|
playlists.value = await getPlaylist({});
|
||||||
isLoading.value = false
|
loading.value = false
|
||||||
})
|
})
|
||||||
|
|
||||||
const toggleScheduleForm = () => {
|
const toggleScheduleForm = () => {
|
||||||
|
@ -34,32 +39,45 @@ const toggleScheduleForm = () => {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<v-card>
|
<v-card
|
||||||
|
:disabled="loading"
|
||||||
|
:loading="loading"
|
||||||
|
>
|
||||||
|
<template v-slot:loader="{ isActive }">
|
||||||
|
<v-progress-linear
|
||||||
|
:active="isActive"
|
||||||
|
color="deep-purple"
|
||||||
|
height="4"
|
||||||
|
indeterminate
|
||||||
|
></v-progress-linear>
|
||||||
|
</template>
|
||||||
|
|
||||||
<v-card-title>
|
<v-card-title>
|
||||||
<h3>Trasmissione</h3>
|
<h3>Trasmissione</h3>
|
||||||
</v-card-title>
|
</v-card-title>
|
||||||
|
|
||||||
<template v-if="showScheduleFormMode">
|
<template v-if="showScheduleFormMode">
|
||||||
<ShowScheduleForm
|
<ShowScheduleForm
|
||||||
v-model="showFormStore.currentShow.showDays"
|
v-model="showStore.currentShow.showDays"
|
||||||
@toggle-show-schedule-form="toggleScheduleForm"
|
@toggle-show-schedule-form="toggleScheduleForm"
|
||||||
@save-show-schedule="showFormStore.saveSchedule"
|
@trigger-show-creation="showStore.createShow"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<v-form>
|
<v-form ref="form" v-model="isFormValid">
|
||||||
<v-card-text>
|
<v-card-text>
|
||||||
<v-row no-gutters>
|
<v-row no-gutters>
|
||||||
<!-- Name Field -->
|
<!-- Name Field -->
|
||||||
<v-col cols="12" md="6" lg="4">
|
<v-col cols="12" md="6" lg="4">
|
||||||
<v-card>
|
<v-card>
|
||||||
<v-text-field
|
<v-text-field
|
||||||
v-model="showFormStore.currentShow.name"
|
v-model="showStore.currentShow.name"
|
||||||
label="Nome"
|
label="Nome"
|
||||||
density="compact"
|
density="compact"
|
||||||
:required="true"
|
@update:modelValue="value => showStore.updateField({ key: 'name', value })"
|
||||||
@update:modelValue="value => showFormStore.updateField({ key: 'name', value })"
|
:rules="[v => !!v || 'Nome è obbligatorio']"
|
||||||
|
required="true"
|
||||||
/>
|
/>
|
||||||
</v-card>
|
</v-card>
|
||||||
</v-col>
|
</v-col>
|
||||||
|
@ -68,11 +86,11 @@ const toggleScheduleForm = () => {
|
||||||
<v-col cols="12" md="6" lg="4">
|
<v-col cols="12" md="6" lg="4">
|
||||||
<v-card>
|
<v-card>
|
||||||
<v-text-field
|
<v-text-field
|
||||||
v-model="showFormStore.currentShow.url"
|
v-model="showStore.currentShow.url"
|
||||||
label="URL"
|
label="URL"
|
||||||
density="compact"
|
density="compact"
|
||||||
:required="true"
|
:required="true"
|
||||||
@update:modelValue="value => showFormStore.updateField({ key: 'url', value })"
|
@update:modelValue="value => showStore.updateField({ key: 'url', value })"
|
||||||
/>
|
/>
|
||||||
</v-card>
|
</v-card>
|
||||||
</v-col>
|
</v-col>
|
||||||
|
@ -81,11 +99,11 @@ const toggleScheduleForm = () => {
|
||||||
<v-col cols="12" md="6" lg="4">
|
<v-col cols="12" md="6" lg="4">
|
||||||
<v-card>
|
<v-card>
|
||||||
<v-text-field
|
<v-text-field
|
||||||
v-model="showFormStore.currentShow.genre"
|
v-model="showStore.currentShow.genre"
|
||||||
label="Genere"
|
label="Genere"
|
||||||
density="compact"
|
density="compact"
|
||||||
:required="true"
|
:required="true"
|
||||||
@update:modelValue="value => showFormStore.updateField({ key: 'genre', value })"
|
@update:modelValue="value => showStore.updateField({ key: 'genre', value })"
|
||||||
/>
|
/>
|
||||||
</v-card>
|
</v-card>
|
||||||
</v-col>
|
</v-col>
|
||||||
|
@ -94,11 +112,11 @@ const toggleScheduleForm = () => {
|
||||||
<v-col cols="12" md="6" lg="4">
|
<v-col cols="12" md="6" lg="4">
|
||||||
<v-card>
|
<v-card>
|
||||||
<v-textarea
|
<v-textarea
|
||||||
v-model="showFormStore.currentShow.description"
|
v-model="showStore.currentShow.description"
|
||||||
label="Descrizione"
|
label="Descrizione"
|
||||||
density="compact"
|
density="compact"
|
||||||
rows="2"
|
rows="2"
|
||||||
@update:modelValue="value => showFormStore.updateField({ key: 'description', value })"
|
@update:modelValue="value => showStore.updateField({ key: 'description', value })"
|
||||||
/>
|
/>
|
||||||
</v-card>
|
</v-card>
|
||||||
</v-col>
|
</v-col>
|
||||||
|
@ -107,9 +125,9 @@ const toggleScheduleForm = () => {
|
||||||
<v-col cols="12" md="6" lg="4">
|
<v-col cols="12" md="6" lg="4">
|
||||||
<v-card>
|
<v-card>
|
||||||
<ColorPickerButton
|
<ColorPickerButton
|
||||||
v-model="showFormStore.currentShow.backgroundColor"
|
v-model="showStore.currentShow.backgroundColor"
|
||||||
label="Colore di sfondo"
|
label="Colore di sfondo"
|
||||||
@update:modelValue="value => showFormStore.updateField({ key: 'backgroundColor', value })"
|
@update:modelValue="value => showStore.updateField({ key: 'backgroundColor', value })"
|
||||||
/>
|
/>
|
||||||
</v-card>
|
</v-card>
|
||||||
</v-col>
|
</v-col>
|
||||||
|
@ -118,11 +136,11 @@ const toggleScheduleForm = () => {
|
||||||
<v-col cols="12" md="6" lg="4">
|
<v-col cols="12" md="6" lg="4">
|
||||||
<v-card>
|
<v-card>
|
||||||
<v-file-input
|
<v-file-input
|
||||||
v-model="showFormStore.currentShow.imagePath"
|
v-model="showStore.currentShow.imagePath"
|
||||||
label="Percorso immagine"
|
label="Percorso immagine"
|
||||||
density="compact"
|
density="compact"
|
||||||
type="file"
|
type="file"
|
||||||
@update:modelValue="value => showFormStore.updateField({ key: 'imagePath', value })"
|
@update:modelValue="value => showStore.updateField({ key: 'imagePath', value })"
|
||||||
/>
|
/>
|
||||||
</v-card>
|
</v-card>
|
||||||
</v-col>
|
</v-col>
|
||||||
|
@ -133,24 +151,24 @@ const toggleScheduleForm = () => {
|
||||||
<v-card>
|
<v-card>
|
||||||
<v-checkbox
|
<v-checkbox
|
||||||
label="Attivare regole di ripetizione?"
|
label="Attivare regole di ripetizione?"
|
||||||
v-model="showFormStore.currentShow.hasAutoplaylist"
|
v-model="showStore.currentShow.hasAutoplaylist"
|
||||||
></v-checkbox>
|
></v-checkbox>
|
||||||
<v-checkbox
|
<v-checkbox
|
||||||
v-model="showFormStore.currentShow.autoplaylistRepeat"
|
v-model="showStore.currentShow.autoplaylistRepeat"
|
||||||
label="Ripetere playlist?"
|
label="Ripetere playlist?"
|
||||||
:disabled="!showFormStore.currentShow.hasAutoplaylist"
|
:disabled="!showStore.currentShow.hasAutoplaylist"
|
||||||
@update:modelValue="value => showFormStore.updateField({ key: 'autoplaylistRepeat', value })"
|
@update:modelValue="value => showStore.updateField({ key: 'autoplaylistRepeat', value })"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<v-select
|
<v-select
|
||||||
v-model="showFormStore.currentShow.autoplaylist_id"
|
v-model="showStore.currentShow.autoplaylistId"
|
||||||
:items="playlists"
|
:items="playlists"
|
||||||
label="Playlist"
|
label="Playlist"
|
||||||
density="compact"
|
density="compact"
|
||||||
item-title="name"
|
item-title="name"
|
||||||
item-value="id"
|
item-value="id"
|
||||||
:disabled="!showFormStore.currentShow.hasAutoplaylist"
|
:disabled="!showStore.currentShow.hasAutoplaylist"
|
||||||
@update:modelValue="value => showFormStore.updateField({ key: 'autoplaylistId', value })"
|
@update:modelValue="value => showStore.updateField({ key: 'autoplaylistId', value })"
|
||||||
/>
|
/>
|
||||||
</v-card>
|
</v-card>
|
||||||
</v-card>
|
</v-card>
|
||||||
|
@ -160,14 +178,14 @@ const toggleScheduleForm = () => {
|
||||||
<v-col cols="12" md="6" lg="4">
|
<v-col cols="12" md="6" lg="4">
|
||||||
<v-card>
|
<v-card>
|
||||||
<v-select
|
<v-select
|
||||||
v-model="showFormStore.currentShow.showDjs"
|
v-model="showStore.currentShow.showDjs"
|
||||||
:items="usersDJs"
|
:items="usersDJs"
|
||||||
label="DJs"
|
label="DJs"
|
||||||
density="compact"
|
density="compact"
|
||||||
item-title="login"
|
item-title="login"
|
||||||
item-value="id"
|
item-value="id"
|
||||||
multiple
|
multiple
|
||||||
@update:modelValue="value => showFormStore.updateField({ key: 'showDjs', value })"
|
@update:modelValue="value => showStore.updateField({ key: 'showDjs', value })"
|
||||||
/>
|
/>
|
||||||
</v-card>
|
</v-card>
|
||||||
</v-col>
|
</v-col>
|
||||||
|
@ -176,8 +194,8 @@ const toggleScheduleForm = () => {
|
||||||
|
|
||||||
<v-card-actions>
|
<v-card-actions>
|
||||||
<v-btn color="accent" @click="$emit('goBack')">Torna indietro</v-btn>
|
<v-btn color="accent" @click="$emit('goBack')">Torna indietro</v-btn>
|
||||||
<v-btn color="accent" @click="showFormStore.saveShow">Salva</v-btn>
|
<v-btn v-if="showStore.currentShow.id" color="accent" @click="showStore.updateShow()" :disabled="!isFormValid" >Salva</v-btn>
|
||||||
<v-btn color="accent" @click="toggleScheduleForm">Salva e schedula</v-btn>
|
<v-btn color="accent" @click="toggleScheduleForm" :disabled="!isFormValid" >Regole di programmazione</v-btn>
|
||||||
</v-card-actions>
|
</v-card-actions>
|
||||||
</v-form>
|
</v-form>
|
||||||
</template>
|
</template>
|
|
@ -1,39 +1,65 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {onMounted, ref, watch} from 'vue';
|
import {onMounted, ref, watch} from 'vue';
|
||||||
import {useShowStore} from "@/stores/show.store.ts";
|
import {useShowStore} from "@/stores/show.store.ts";
|
||||||
import {showRepetitionData} from "@models/show/ShowRepetition.ts";
|
import {showRepetitionData} from "@models/show/ShowRepetition.ts";
|
||||||
import DaysCheckbox from "@partials/fields/show/DaysCheckbox.vue";
|
import DaysCheckbox from "@partials/fields/show/DaysCheckbox.vue";
|
||||||
import ShowStartEndTime from "@partials/fields/show/ShowStartEndTime.vue";
|
import ShowStartEndTime from "@partials/fields/show/ShowStartEndTime.vue";
|
||||||
|
|
||||||
const emits =defineEmits(['toggle-show-schedule-form'])
|
// Emits and props
|
||||||
|
const emits = defineEmits(['toggle-show-schedule-form', 'trigger-show-creation'])
|
||||||
|
|
||||||
const showFormStore = useShowStore();
|
// Store
|
||||||
|
const showStore = useShowStore();
|
||||||
|
|
||||||
|
// Data
|
||||||
|
const checkBoxEnd = ref(false)
|
||||||
|
const checkBoxRepetition = ref(false)
|
||||||
|
const isFormValid = ref(false)
|
||||||
|
|
||||||
|
// Funcs
|
||||||
|
onMounted(() => {
|
||||||
|
const startDayShow = showStore.currentShow.showDays.firstShow.getDay();
|
||||||
|
let showDays = checkBoxRepetition.value ? showStore.currentShow.showDays.day : [];
|
||||||
|
showDays.push(startDayShow);
|
||||||
|
showStore.updateShowDaysField({ key: 'day', value: showDays });
|
||||||
|
});
|
||||||
|
|
||||||
|
const updateShowStartDay = (newStartDate) => {
|
||||||
|
const previousStartDayShow = showStore.currentShow.showDays.firstShow.getDay();
|
||||||
|
let showDays = showStore.currentShow.showDays.day.filter((item) => item !== previousStartDayShow);
|
||||||
|
|
||||||
|
showStore.updateShowDaysField({ key: 'firstShow', value: newStartDate });
|
||||||
|
const newStartDayShow = newStartDate.getDay();
|
||||||
|
showDays.push(newStartDayShow);
|
||||||
|
showStore.updateShowDaysField({ key: 'day', value: showDays });
|
||||||
|
};
|
||||||
|
|
||||||
const goBack = () => {
|
const goBack = () => {
|
||||||
// showFormStore.resetShowDays();
|
|
||||||
emits("toggle-show-schedule-form");
|
emits("toggle-show-schedule-form");
|
||||||
};
|
};
|
||||||
|
|
||||||
const saveShowSchedule = () => {
|
const saveShowSchedule = async () => {
|
||||||
showFormStore.saveSchedule();
|
if (showStore.currentShow.id) {
|
||||||
|
return await showStore.updateShowDays();
|
||||||
|
}
|
||||||
|
emits('trigger-show-creation')
|
||||||
};
|
};
|
||||||
|
|
||||||
const checkBoxEnd = ref(false)
|
|
||||||
const checkBoxRepetition = ref(false)
|
|
||||||
|
|
||||||
watch(checkBoxEnd, (checkBoxEnd) => {
|
watch(checkBoxEnd, (checkBoxEnd) => {
|
||||||
if(checkBoxEnd == false) showFormStore.updateShowDaysField({ key: 'lastShow', value: null })
|
if(checkBoxEnd == false) showStore.updateShowDaysField({ key: 'lastShow', value: null })
|
||||||
})
|
})
|
||||||
|
|
||||||
watch(checkBoxRepetition, (checkBoxRepetition) => {
|
watch(checkBoxRepetition, (newValue) => {
|
||||||
if(checkBoxRepetition == false) {
|
if (!newValue) {
|
||||||
showFormStore.updateShowDaysField({key: 'day', value: []})
|
const startDayShow = showStore.currentShow.showDays.firstShow.getDay();
|
||||||
// TODO By restoring the noRepeat from the day enum
|
showStore.updateShowDaysField({ key: 'day', value: [startDayShow] });
|
||||||
// one can toggle it's visibility based on the select box disabled value
|
showStore.updateShowDaysField({ key: 'repeatType', value: 'noRepeat' });
|
||||||
// Only cosmetic
|
|
||||||
showFormStore.updateShowDaysField({key: 'repeatType', value: -1})
|
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
|
|
||||||
|
// TODO Create a fixed selected day for repetition extracted from the start date
|
||||||
|
// Create a local ref var that get's the day number from the startDate, pass it
|
||||||
|
// to the days component as a fixed date
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -41,18 +67,19 @@ watch(checkBoxRepetition, (checkBoxRepetition) => {
|
||||||
<v-card-title>
|
<v-card-title>
|
||||||
<h3>Regole di programmazione</h3>
|
<h3>Regole di programmazione</h3>
|
||||||
</v-card-title>
|
</v-card-title>
|
||||||
<v-form>
|
<v-form ref="form" v-model="isFormValid">
|
||||||
<v-card-text>
|
<v-card-text>
|
||||||
<v-row no-gutters>
|
<v-row no-gutters>
|
||||||
<!-- First Show Date -->
|
<!-- First Show Date -->
|
||||||
<v-col cols="12" md="6" lg="4">
|
<v-col cols="12" md="6" lg="4">
|
||||||
<v-date-picker
|
<v-date-picker
|
||||||
v-model="showFormStore.currentShow.showDays.firstShow"
|
:value="showStore.currentShow.showDays.firstShow"
|
||||||
:min="new Date().toISOString().substring(0, 10)"
|
:min="new Date().toISOString().substring(0, 10)"
|
||||||
:title="'Data inizio'"
|
:title="'Data inizio'"
|
||||||
label="Data inizio"
|
label="Data inizio"
|
||||||
density="compact"
|
density="compact"
|
||||||
@update:modelValue="value => showFormStore.updateShowDaysField({ key: 'firstShow', value })"
|
required="true"
|
||||||
|
v-on:update:modelValue="updateShowStartDay"
|
||||||
/>
|
/>
|
||||||
</v-col>
|
</v-col>
|
||||||
|
|
||||||
|
@ -63,8 +90,8 @@ watch(checkBoxRepetition, (checkBoxRepetition) => {
|
||||||
v-model="checkBoxEnd"
|
v-model="checkBoxEnd"
|
||||||
></v-checkbox>
|
></v-checkbox>
|
||||||
<v-date-picker
|
<v-date-picker
|
||||||
v-model="showFormStore.currentShow.showDays.lastShow"
|
:v-model="showStore.currentShow.showDays.lastShow"
|
||||||
:min="showFormStore.currentShow.showDays.firstShow"
|
:min="showStore.currentShow.showDays.firstShow"
|
||||||
label="Data fine"
|
label="Data fine"
|
||||||
title="Data fine"
|
title="Data fine"
|
||||||
density="compact"
|
density="compact"
|
||||||
|
@ -75,11 +102,12 @@ watch(checkBoxRepetition, (checkBoxRepetition) => {
|
||||||
<!-- Start Time and Duration -->
|
<!-- Start Time and Duration -->
|
||||||
<v-col cols="12" md="6" lg="4">
|
<v-col cols="12" md="6" lg="4">
|
||||||
<ShowStartEndTime
|
<ShowStartEndTime
|
||||||
v-model="showFormStore.currentShow.showDays.startTime"
|
v-model="showStore.currentShow.showDays.startTime"
|
||||||
:start-time-label="'Ora inizio show'"
|
:start-time-label="'Ora inizio show'"
|
||||||
:duration-label="'Durata'"
|
:duration-label="'Durata'"
|
||||||
:end-time-label="'Orario di fine della trasmissione'"
|
:end-time-label="'Orario di fine della trasmissione'"
|
||||||
@update:duration="value => showFormStore.updateShowDaysField({ key: 'duration', value })"
|
@update:duration="value => showStore.updateShowDaysField({ key: 'duration', value })"
|
||||||
|
required="true"
|
||||||
/>
|
/>
|
||||||
</v-col>
|
</v-col>
|
||||||
|
|
||||||
|
@ -90,7 +118,7 @@ watch(checkBoxRepetition, (checkBoxRepetition) => {
|
||||||
v-model="checkBoxRepetition"
|
v-model="checkBoxRepetition"
|
||||||
></v-checkbox>
|
></v-checkbox>
|
||||||
<v-select
|
<v-select
|
||||||
v-model="showFormStore.currentShow.showDays.repeatType"
|
v-model="showStore.currentShow.showDays.repeatType"
|
||||||
:items="showRepetitionData"
|
:items="showRepetitionData"
|
||||||
label="Ripetizione"
|
label="Ripetizione"
|
||||||
density="compact"
|
density="compact"
|
||||||
|
@ -100,10 +128,11 @@ watch(checkBoxRepetition, (checkBoxRepetition) => {
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<DaysCheckbox
|
<DaysCheckbox
|
||||||
v-model="showFormStore.currentShow.showDays.day"
|
v-model="showStore.currentShow.showDays.day"
|
||||||
|
:disabled="!checkBoxRepetition || (showStore.currentShow.showDays.repeatType === 'noRepeat')"
|
||||||
|
:fixedDay="showStore.currentShow.showDays.firstShow.getDay()"
|
||||||
|
@update:modelValue="value => showStore.updateShowDaysField({ key: 'day', value })"
|
||||||
label="Giorni"
|
label="Giorni"
|
||||||
:disabled="!checkBoxRepetition"
|
|
||||||
@update:modelValue="value => showFormStore.updateShowDaysField({ key: 'day', value })"
|
|
||||||
/>
|
/>
|
||||||
</v-col>
|
</v-col>
|
||||||
</v-row>
|
</v-row>
|
||||||
|
@ -111,7 +140,7 @@ watch(checkBoxRepetition, (checkBoxRepetition) => {
|
||||||
|
|
||||||
<v-card-actions>
|
<v-card-actions>
|
||||||
<v-btn color="accent" @click="goBack">Torna indietro</v-btn>
|
<v-btn color="accent" @click="goBack">Torna indietro</v-btn>
|
||||||
<v-btn color="accent" @click="saveShowSchedule">Salva</v-btn>
|
<v-btn color="accent" @click="saveShowSchedule" :disabled="!isFormValid">Salva</v-btn>
|
||||||
</v-card-actions>
|
</v-card-actions>
|
||||||
</v-form>
|
</v-form>
|
||||||
</v-card>
|
</v-card>
|
||||||
|
|
|
@ -1,33 +1,31 @@
|
||||||
enum ShowRepeatEnum {
|
// TODO i18n strings
|
||||||
Weekly = 0,
|
export enum ShowRepeatEnum {
|
||||||
Biweekly = 1,
|
weekly = 'Weekly',
|
||||||
Triweekly = 4,
|
biweekly = 'Biweekly',
|
||||||
FourWeeks = 5,
|
triweekly = 'Triweekly',
|
||||||
Monthly = 2,
|
fourWeeks = 'Four weeks',
|
||||||
|
monthly = 'Monthly',
|
||||||
|
noRepeat = 'No repeat',
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ShowRepetitionType {
|
export interface ShowRepetitionType {
|
||||||
type: ShowRepeatEnum;
|
type: ShowRepeatEnum;
|
||||||
repeatName: string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const showRepetitionData: ShowRepetitionType[] = [
|
export const showRepetitionData: ShowRepetitionType[] = Object.entries(ShowRepeatEnum).map(([key, value]) => ({
|
||||||
{ type: ShowRepeatEnum.Weekly, repeatName: "Weekly" },
|
type: key as ShowRepeatEnum,
|
||||||
{ type: ShowRepeatEnum.Biweekly, repeatName: "Biweekly" },
|
repeatName: value,
|
||||||
{ type: ShowRepeatEnum.Triweekly, repeatName: "Triweekly" },
|
}));
|
||||||
{ type: ShowRepeatEnum.FourWeeks, repeatName: "Four Weeks" },
|
|
||||||
{ type: ShowRepeatEnum.Monthly, repeatName: "Monthly" },
|
|
||||||
];
|
|
||||||
|
|
||||||
|
|
||||||
enum WeekDaysEnum {
|
enum WeekDaysEnum {
|
||||||
Monday = 0,
|
Monday = 1,
|
||||||
Tuesday = 1,
|
Tuesday = 2,
|
||||||
Wednesday = 2,
|
Wednesday = 3,
|
||||||
Thursday = 3,
|
Thursday = 4,
|
||||||
Friday = 4,
|
Friday = 5,
|
||||||
Saturday = 5,
|
Saturday = 6,
|
||||||
Sunday = 6,
|
Sunday = 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface WeekDays {
|
export interface WeekDays {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import type {ShowInstance} from "@models/show/showInstance.ts";
|
import type {ShowInstance} from "@models/show/showInstance.ts";
|
||||||
import type {ShowDays} from "@models/show/showDays";
|
import type {ShowDays} from "@models/show/showDays";
|
||||||
import type {ShowDjs} from "@models/show/showDjs";
|
import type {ShowDJs} from "@models/show/showDJs.ts";
|
||||||
import axios, {type AxiosResponse} from "axios";
|
import axios, {type AxiosResponse} from "axios";
|
||||||
import {cleanOptions} from "@/helpers/AxiosHelper.ts";
|
import {cleanOptions} from "@/helpers/AxiosHelper.ts";
|
||||||
|
|
||||||
|
@ -18,13 +18,13 @@ export interface Show {
|
||||||
liveStreamPass?: string;
|
liveStreamPass?: string;
|
||||||
imagePath?: string | File;
|
imagePath?: string | File;
|
||||||
hasAutoplaylist: boolean;
|
hasAutoplaylist: boolean;
|
||||||
autoplaylist_id?: number;
|
autoplaylistId?: number;
|
||||||
autoplaylistRepeat: boolean;
|
autoplaylistRepeat: boolean;
|
||||||
|
|
||||||
// Relationships
|
// Relationships
|
||||||
block?: any;
|
block?: any;
|
||||||
showDays?: ShowDays;
|
showDays?: ShowDays;
|
||||||
showDjs?: ShowDjs[];
|
showDjs?: ShowDJs[];
|
||||||
showInstances?: ShowInstance[];
|
showInstances?: ShowInstance[];
|
||||||
playlist?: any;
|
playlist?: any;
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,7 @@ export interface Show {
|
||||||
export const baseShow = (): Show => {
|
export const baseShow = (): Show => {
|
||||||
return {
|
return {
|
||||||
id: null,
|
id: null,
|
||||||
name: '',
|
name: 'Esempio',
|
||||||
url: '',
|
url: '',
|
||||||
genre: '',
|
genre: '',
|
||||||
description: '',
|
description: '',
|
||||||
|
@ -42,7 +42,7 @@ export const baseShow = (): Show => {
|
||||||
liveStreamPass: '',
|
liveStreamPass: '',
|
||||||
imagePath: '',
|
imagePath: '',
|
||||||
hasAutoplaylist: false,
|
hasAutoplaylist: false,
|
||||||
autoplaylist_id: 0,
|
autoplaylistId: null,
|
||||||
autoplaylistRepeat: false,
|
autoplaylistRepeat: false,
|
||||||
showDjs: null,
|
showDjs: null,
|
||||||
showDays: null,
|
showDays: null,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { VTextField } from "vuetify/components";
|
import { VTextField } from "vuetify/components";
|
||||||
|
|
||||||
export interface ShowDjs {
|
export interface ShowDJs {
|
||||||
id?: number;
|
id?: number;
|
||||||
subjsId: number;
|
subjsId: number;
|
||||||
showId: number;
|
showId: number;
|
||||||
|
@ -11,7 +11,7 @@ export interface User {
|
||||||
login: string;
|
login: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function showDjsForm(item: ShowDjs) {
|
export function showDjsForm(item: ShowDJs) {
|
||||||
const visibleFields = {
|
const visibleFields = {
|
||||||
subjsId: 'Presentatore',
|
subjsId: 'Presentatore',
|
||||||
showId: 'Programma'
|
showId: 'Programma'
|
||||||
|
@ -22,7 +22,7 @@ export function showDjsForm(item: ShowDjs) {
|
||||||
Object.keys(visibleFields).forEach((key) => {
|
Object.keys(visibleFields).forEach((key) => {
|
||||||
fields[key] = {
|
fields[key] = {
|
||||||
label: visibleFields[key],
|
label: visibleFields[key],
|
||||||
value: item[key as keyof ShowDjs],
|
value: item[key as keyof ShowDJs],
|
||||||
component: VTextField,
|
component: VTextField,
|
||||||
disabled: false
|
disabled: false
|
||||||
};
|
};
|
|
@ -1,6 +1,8 @@
|
||||||
import axios, {type AxiosResponse} from "axios";
|
import axios, {type AxiosResponse} from "axios";
|
||||||
import {cleanOptions} from "@/helpers/AxiosHelper.ts";
|
import {cleanOptions, snakeToCamel} from "@/helpers/AxiosHelper.ts";
|
||||||
|
import type {ShowRepetitionType} from "@models/show/ShowRepetition.ts";
|
||||||
|
|
||||||
|
//TODO RepeatType should use the interface ShowRepetitionType
|
||||||
export interface ShowDays {
|
export interface ShowDays {
|
||||||
id?: number;
|
id?: number;
|
||||||
firstShow: Date;
|
firstShow: Date;
|
||||||
|
@ -9,7 +11,7 @@ export interface ShowDays {
|
||||||
timezone: string;
|
timezone: string;
|
||||||
duration: string;
|
duration: string;
|
||||||
day: number[];
|
day: number[];
|
||||||
repeatType: number;
|
repeatType: string;
|
||||||
nextPopDate?: string;
|
nextPopDate?: string;
|
||||||
showId?: number;
|
showId?: number;
|
||||||
record?: number;
|
record?: number;
|
||||||
|
@ -22,8 +24,8 @@ export const baseShowDays = ():ShowDays => {
|
||||||
startTime: '08:00',
|
startTime: '08:00',
|
||||||
timezone: '',
|
timezone: '',
|
||||||
duration: '01:00',
|
duration: '01:00',
|
||||||
day: [0],
|
day: [],
|
||||||
repeatType: 0,
|
repeatType: 'noRepeat',
|
||||||
nextPopDate: '',
|
nextPopDate: '',
|
||||||
showId: 0,
|
showId: 0,
|
||||||
record: 0
|
record: 0
|
||||||
|
@ -31,14 +33,14 @@ export const baseShowDays = ():ShowDays => {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getShowDays = async (options: {
|
export const getShowDays = async (options: {
|
||||||
showId?: number | null;
|
show_id?: number | null;
|
||||||
flattenShowDays?: boolean;
|
flattenShowDays?: boolean;
|
||||||
}): Promise<ShowDays> => {
|
}): Promise<ShowDays> => {
|
||||||
const filteredParams = cleanOptions(options);
|
const filteredParams = cleanOptions(options);
|
||||||
|
|
||||||
return await axios.get(`/showDays`, {params: filteredParams})
|
return await axios.get(`/showDays`, {params: filteredParams})
|
||||||
.then((response: AxiosResponse) => {
|
.then((response: AxiosResponse) => {
|
||||||
return response.data
|
return snakeToCamel(response.data);
|
||||||
}).catch((error: Error) => {
|
}).catch((error: Error) => {
|
||||||
console.log("Error: " + error);
|
console.log("Error: " + error);
|
||||||
})
|
})
|
||||||
|
|
|
@ -2,4 +2,30 @@ export function cleanOptions(options: Object): Object {
|
||||||
return Object.fromEntries(
|
return Object.fromEntries(
|
||||||
Object.entries(options).filter(([_, value]) => value !== undefined && value !== null)
|
Object.entries(options).filter(([_, value]) => value !== undefined && value !== null)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function camelToSnake(obj) {
|
||||||
|
if (Array.isArray(obj)) {
|
||||||
|
return obj.map(camelToSnake);
|
||||||
|
} else if (obj !== null && typeof obj === 'object') {
|
||||||
|
return Object.keys(obj).reduce((acc, key) => {
|
||||||
|
const snakeKey = key.replace(/([A-Z])/g, '_$1').toLowerCase();
|
||||||
|
acc[snakeKey] = camelToSnake(obj[key]);
|
||||||
|
return acc;
|
||||||
|
}, {});
|
||||||
|
}
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function snakeToCamel(obj) {
|
||||||
|
if (Array.isArray(obj)) {
|
||||||
|
return obj.map(snakeToCamel);
|
||||||
|
} else if (obj !== null && typeof obj === 'object') {
|
||||||
|
return Object.keys(obj).reduce((acc, key) => {
|
||||||
|
const camelKey = key.replace(/_([a-z])/g, (_, char) => char.toUpperCase());
|
||||||
|
acc[camelKey] = snakeToCamel(obj[key]);
|
||||||
|
return acc;
|
||||||
|
}, {});
|
||||||
|
}
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
|
@ -9,5 +9,23 @@ export function extractTime(dateTimeString: string, extractTime: boolean = false
|
||||||
const minutes = String(date.getMinutes()).padStart(2, '0');
|
const minutes = String(date.getMinutes()).padStart(2, '0');
|
||||||
return `${hours}:${minutes}`;
|
return `${hours}:${minutes}`;
|
||||||
}
|
}
|
||||||
return date.getFullYear() + '-' + (date.getMonth() + 1) + '-' + date.getDate();
|
return date.getFullYear() + '-' + String(date.getMonth() + 1).padStart(2, '0') + '-' + String(date.getDate()).padStart(2, '0');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export function getTimeDiff(startTime: Date, endTime: Date) {
|
||||||
|
const diffInMilliseconds = Math.abs(startTime.getTime() - endTime.getTime());
|
||||||
|
|
||||||
|
const hours = Math.floor((diffInMilliseconds % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
|
||||||
|
const minutes = Math.floor((diffInMilliseconds % (1000 * 60 * 60)) / (1000 * 60));
|
||||||
|
|
||||||
|
const formattedHours = String(hours).padStart(2, '0');
|
||||||
|
const formattedMinutes = String(minutes).padStart(2, '0');
|
||||||
|
|
||||||
|
return `${formattedHours}:${formattedMinutes}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getHoursMinutesFromString(timeString: string): Date {
|
||||||
|
const [ h, m ] = timeString.split(":");
|
||||||
|
const ms = new Date().setHours(h,m);
|
||||||
|
return new Date(ms)
|
||||||
|
}
|
|
@ -1,6 +1,9 @@
|
||||||
import { defineStore } from 'pinia'
|
import {defineStore} from 'pinia'
|
||||||
import { type Show } from '@models/show/show'
|
import {type Show} from '@models/show/show'
|
||||||
import type {ShowDays} from "@models/show/showDays";
|
import type {ShowDays} from "@models/show/showDays";
|
||||||
|
import axios, {type AxiosResponse} from "axios";
|
||||||
|
import {camelToSnake} from "@/helpers/AxiosHelper.ts";
|
||||||
|
import {extractTime} from "@/helpers/DateFormatter.ts";
|
||||||
|
|
||||||
export const useShowStore = defineStore('show', {
|
export const useShowStore = defineStore('show', {
|
||||||
state: () => ({
|
state: () => ({
|
||||||
|
@ -9,23 +12,46 @@ export const useShowStore = defineStore('show', {
|
||||||
}),
|
}),
|
||||||
actions: {
|
actions: {
|
||||||
async loadShow(showData: Show) {
|
async loadShow(showData: Show) {
|
||||||
this.currentShow = { ...showData }
|
this.currentShow = {...showData}
|
||||||
},
|
},
|
||||||
updateField(payload: { key: string; value: any }) {
|
updateField(payload: { key: string; value: any }) {
|
||||||
this.currentShow[payload.key] = payload.value
|
this.currentShow[payload.key] = payload.value
|
||||||
},
|
},
|
||||||
async saveShow() {
|
|
||||||
// Implement API call to save this.currentShow
|
|
||||||
},
|
|
||||||
async saveSchedule() {
|
|
||||||
// Implement schedule saving logic
|
|
||||||
},
|
|
||||||
resetShowDays() {
|
|
||||||
this.currentShow.showDays = { ...this.baseShowDays };
|
|
||||||
},
|
|
||||||
|
|
||||||
updateShowDaysField(payload: { key: string; value: any }) {
|
updateShowDaysField(payload: { key: string; value: any }) {
|
||||||
this.currentShow.showDays[payload.key] = payload.value;
|
this.currentShow.showDays[payload.key] = payload.value;
|
||||||
}
|
},
|
||||||
|
async createShow() {
|
||||||
|
let showData = {...this.currentShow};
|
||||||
|
showData.showDays.firstShow = extractTime(showData.showDays.firstShow);
|
||||||
|
if (showData.showDays.lastShow) {
|
||||||
|
showData.showDays.lastShow = extractTime(showData.showDays.lastShow);
|
||||||
|
}
|
||||||
|
showData = camelToSnake(showData);
|
||||||
|
return await axios.post(`/show`, showData)
|
||||||
|
.then((response: AxiosResponse) => {
|
||||||
|
return response.data
|
||||||
|
}).catch((error: Error) => {
|
||||||
|
console.log("Error: " + error);
|
||||||
|
})
|
||||||
|
},
|
||||||
|
async updateShow() {
|
||||||
|
return await axios.post(`/show`, this.currentShow)
|
||||||
|
.then((response: AxiosResponse) => {
|
||||||
|
return response.data
|
||||||
|
}).catch((error: Error) => {
|
||||||
|
console.log("Error: " + error.message);
|
||||||
|
})
|
||||||
|
},
|
||||||
|
async updateShowDays() {
|
||||||
|
return await axios.post(`/showDays`, this.currentShow.showDays)
|
||||||
|
.then((response: AxiosResponse) => {
|
||||||
|
return response.data
|
||||||
|
}).catch((error: Error) => {
|
||||||
|
console.log("Error: " + error);
|
||||||
|
})
|
||||||
|
},
|
||||||
|
resetShowDays() {
|
||||||
|
this.currentShow.showDays = {...this.baseShowDays};
|
||||||
|
},
|
||||||
}
|
}
|
||||||
})
|
})
|
|
@ -18,7 +18,10 @@ export const useShowInstanceStore = defineStore('showInstance', {
|
||||||
this.currentShowInstance = baseShowInstance()
|
this.currentShowInstance = baseShowInstance()
|
||||||
},
|
},
|
||||||
async saveShowInstance() {
|
async saveShowInstance() {
|
||||||
// Implement API call to save this.currentShowInstance
|
|
||||||
|
},
|
||||||
|
async updateShowInstance() {
|
||||||
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
})
|
})
|
|
@ -3,6 +3,7 @@
|
||||||
use App\Http\Controllers\Auth\LoginController;
|
use App\Http\Controllers\Auth\LoginController;
|
||||||
use App\Http\Controllers\FileController;
|
use App\Http\Controllers\FileController;
|
||||||
use App\Http\Controllers\Show\ShowController;
|
use App\Http\Controllers\Show\ShowController;
|
||||||
|
use App\Http\Controllers\Show\ShowDaysController;
|
||||||
use App\Http\Controllers\ShowInstance\ShowInstancesController;
|
use App\Http\Controllers\ShowInstance\ShowInstancesController;
|
||||||
use App\Http\Controllers\SmartBlockController;
|
use App\Http\Controllers\SmartBlockController;
|
||||||
use App\Http\Controllers\TrackTypeController;
|
use App\Http\Controllers\TrackTypeController;
|
||||||
|
@ -33,6 +34,7 @@ Route::resources([
|
||||||
'playlist' => PlaylistController::class,
|
'playlist' => PlaylistController::class,
|
||||||
'smartblock' => SmartBlockController::class,
|
'smartblock' => SmartBlockController::class,
|
||||||
'show' => ShowController::class,
|
'show' => ShowController::class,
|
||||||
|
'showDays' => ShowDaysController::class,
|
||||||
'showInstances' => ShowInstancesController::class,
|
'showInstances' => ShowInstancesController::class,
|
||||||
'user' => UserController::class,
|
'user' => UserController::class,
|
||||||
], [
|
], [
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue