Merge branch 'issue-39' into 'develop'

remove schedule/stats functionnalities - issue #39

See merge request ldc-web/projets/support-web!61
This commit is contained in:
Vincent BRIDIER 2023-08-18 10:36:00 +00:00
commit ef897b17b2
22 changed files with 44 additions and 2016 deletions

View file

@ -1,4 +1,3 @@
# TODO
- App\Http\Controllers\Bo\UserController::stats() : refator this using carbon.
- App\Models\Message:booted(): investigate why this make errors on prod,

View file

@ -1,118 +0,0 @@
<?php
namespace App\Enums\Planning;
use App\Traits\Enums\BaseEnum;
use JsonSerializable;
enum ActivityTypeEnum: string implements JsonSerializable
{
use BaseEnum;
case support = 'support';
case rnd = 'rnd';
case dev = 'dev';
case projects = 'projects';
case management = 'management';
case absence = 'absence';
case leaddev = 'leaddev';
/**
* Optionnal labels definition
*/
private const LABELS = [
self::support->name => 'Support',
self::rnd->name => 'R&D',
self::dev->name => 'Développement/Facturable',
self::projects->name => 'Projets & Réunions',
self::management->name => 'Organisation management',
self::absence->name => 'Absence',
self::leaddev->name => 'Lead Dev',
];
/**
* Optionnal labels definition
*/
private const COLORS = [
self::support->name => '#c6e0b4',
self::rnd->name => '#b4c6e7',
self::dev->name => '#00b0f0',
self::projects->name => '#ffe699',
self::management->name => '#f4b084',
self::absence->name => '#aeaaaa',
self::leaddev->name => '#ff7979',
];
/**
* Get Color
*
* @return string
*/
public function color(): string
{
return self::COLORS[$this->name];
}
/**
* Get enum colors
*
* @return array<string>
*/
public static function toColors(): array
{
return self::COLORS;
}
/**
* Datas to send with json_encode.
*
* @return mixed
*/
public function jsonSerialize(): mixed
{
return match ($this) {
self::support => [
'label' => self::support->label(),
'name' => self::support->name(),
'value' => self::support->value(),
'color' => self::support->color()
],
self::rnd => [
'label' => self::rnd->label(),
'name' => self::rnd->name(),
'value' => self::rnd->value(),
'color' => self::rnd->color()
],
self::dev => [
'label' => self::dev->label(),
'name' => self::dev->name(),
'value' => self::dev->value(),
'color' => self::dev->color()
],
self::projects => [
'label' => self::projects->label(),
'name' => self::projects->name(),
'value' => self::projects->value(),
'color' => self::projects->color()
],
self::management => [
'label' => self::management->label(),
'name' => self::management->name(),
'value' => self::management->value(),
'color' => self::management->color()
],
self::absence => [
'label' => self::absence->label(),
'name' => self::absence->name(),
'value' => self::absence->value(),
'color' => self::absence->color()
],
self::leaddev => [
'label' => self::leaddev->label(),
'name' => self::leaddev->name(),
'value' => self::leaddev->value(),
'color' => self::leaddev->color()
],
}; //end match
}
}

View file

@ -1,82 +0,0 @@
<?php
namespace App\Enums\Planning;
use App\Traits\Enums\BaseEnum;
use JsonSerializable;
enum CellModelEnum: string implements JsonSerializable
{
use BaseEnum;
case ticket = 'tickets';
case site = 'sites';
case project = 'projects';
/**
* Optionnal labels definition
*/
private const LABELS = [
self::ticket->name => 'Ticket',
self::site->name => 'Site',
self::project->name => 'Projet',
];
/**
* Optionnal tables definition
*
* This is now a const, so we can't do (new Ticket())->getTable() anymore,
* we need to write it as a constant string.
*/
private const TABLES = [
self::ticket->name => 'tickets',
self::site->name => 'sites',
self::project->name => 'projects',
];
/**
* Get Table
*
* @return string
*/
public function table(): string
{
return self::TABLES[$this->name];
}
/**
* Get enum tables
*
* @return array<string>
*/
public static function toTables(): array
{
return self::TABLES;
}
/**
* Datas to send with json_encode.
*
* @return mixed
*/
public function jsonSerialize(): mixed
{
return match ($this) {
self::ticket => [
'label' => self::ticket->label(),
'name' => self::ticket->name(),
'value' => self::ticket->value()
],
self::site => [
'label' => self::site->label(),
'name' => self::site->name(),
'value' => self::site->value()
],
self::project => [
'label' => self::project->label(),
'name' => self::project->name(),
'value' => self::project->value()
],
}; //end match
}
}

View file

@ -1,77 +0,0 @@
<?php
namespace App\Enums\Planning;
use App\Traits\Enums\BaseEnum;
enum CellTypeEnum: string
{
use BaseEnum;
case support = 'support';
case rnd = 'rnd';
case dev = 'dev';
case projects = 'projects';
case management = 'management';
case absence = 'absence';
case leaddev = 'leaddev';
/**
* Optionnal values definition
*/
private const VALUES = [
self::support->name => '#c6e0b4',
self::rnd->name => '#b4c6e7',
self::dev->name => '#00b0f0',
self::projects->name => '#ffe699',
self::management->name => '#f4b084',
self::absence->name => '#aeaaaa',
self::leaddev->name => '#ff7979',
];
/**
* Optionnal labels definition
*/
private const LABELS = [
self::support->name => 'Support',
self::rnd->name => 'R&D',
self::dev->name => 'Développement/Facturable',
self::projects->name => 'Projets & Réunions',
self::management->name => 'Organisation management',
self::absence->name => 'Absence',
self::leaddev->name => 'Lead Dev',
];
/**
* Optionnal colors definition
*/
private const COLORS = [
self::support->name => '#c6e0b4',
self::rnd->name => '#b4c6e7',
self::dev->name => '#00b0f0',
self::projects->name => '#ffe699',
self::management->name => '#f4b084',
self::absence->name => '#aeaaaa',
self::leaddev->name => '#ff7979',
];
/**
* Get Color
*
* @return string
*/
public function color(): string
{
return self::COLORS[$this->name];
}
/**
* Get enum colors
*
* @return array<string>
*/
public static function toColors(): array
{
return self::COLORS;
}
}

View file

@ -1,33 +0,0 @@
<?php
namespace App\Enums\Planning;
use App\Traits\Enums\BaseEnum;
enum TableRowEnum: int
{
use BaseEnum;
case matin1 = 1;
case matin2 = 2;
case matin3 = 3;
case matin4 = 4;
case apresmidi1 = 5;
case apresmidi2 = 6;
case apresmidi3 = 7;
case apresmidi4 = 8;
/**
* Optionnal labels definition
*/
private const LABELS = [
self::matin1->name => "Matin 1",
self::matin2->name => "Matin 2",
self::matin3->name => "Matin 3",
self::matin4->name => "Matin 4",
self::apresmidi1->name => "Après-midi 1",
self::apresmidi2->name => "Après-midi 2",
self::apresmidi3->name => "Après-midi 3",
self::apresmidi4->name => "Après-midi 4",
];
}

View file

@ -1,256 +0,0 @@
<?php
namespace App\Http\Controllers\Bo;
use App\Enums\Users\RoleEnum;
use App\Http\Controllers\Controller;
use App\Http\Requests\Bo\StoreScheduleRequest;
use App\Models\Schedule;
use App\Models\Ticket;
use App\Models\User;
use Illuminate\Http\Request;
use Carbon\CarbonImmutable;
use Illuminate\Database\Eloquent\Builder;
class ScheduleController extends Controller
{
/**
* Create the date
*
* @param \Illuminate\Http\Request $request
* @return \Carbon\CarbonImmutable|false
*/
private function dateCreation(Request $request)
{
$date = CarbonImmutable::now()->startOfWeek();
if ($request->p) {
$date = CarbonImmutable::createFromFormat('d/m/Y', $request->p)->startOfWeek();
}
return $date;
}
/**
* Create the users table.
*
* @param \Illuminate\Http\Request $request
* @return array
* @throws \Illuminate\Contracts\Container\BindingResolutionException BindingResolutionException.
*/
private function createUsers(Request $request)
{
$users = [];
if (!is_null($request->cookie('userAuthSchedule'))) {
$dbusers = User::where('id', auth()->user()->id)->get();
} else {
$dbusers = User::where('role', RoleEnum::developper)->get();
}
foreach ($dbusers as $user) {
$users[$user->id] = ['name' => $user->name];
}
return $users;
}
/**
* Display schedule.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory|\Illuminate\Http\RedirectResponse
* @throws \Illuminate\Contracts\Container\BindingResolutionException BindingResolutionException.
* @throws \Symfony\Component\Routing\Exception\RouteNotFoundException RouteNotFoundException.
*/
public function index(Request $request)
{
if (!\auth()->user()->role->equals(RoleEnum::developper) && !is_null($request->cookie('userAuthSchedule'))) {
return $this->showAllSchedules();
}
$date = $this->dateCreation($request);
$nbweeks = config('schedules.shownWeeks');
$users = $this->createUsers($request);
$schedules = Schedule::whereHas('user', function (Builder $query) use ($request) {
$query->where('deleted_at', null);
$query->where('role', RoleEnum::developper);
if (!is_null($request->cookie('userAuthSchedule'))) {
$query->where('id', auth()->user()->id);
}
})
->whereDate('date', '>=', $date)
->whereDate('date', '<=', $date->addDays($nbweeks * 7 - 1))
->orderBy('user_id')
->orderBy('slot')
->orderBy('date')
->get();
$arSchedules = array();
$prevUserId = null;
$prevDate = null;
$prevSlot = null;
foreach ($schedules as $schedule) {
$id_lie = ['label' => null, 'name' => null, 'value' => ''];
if (!is_null($schedule->model_lie)) {
if (isset($schedule->relatedModel->name)) {
$id_lie = [
'label' => $schedule->relatedModel->name,
'name' => $schedule->relatedModel->name,
'value' => $schedule->id_lie
];
} else {
$ticket = Ticket::find($schedule->id_lie);
$id_lie = [
'label' => 'Ticket ' . $schedule->id_lie,
'name' => $ticket->formatNameForSchedule($ticket),
'value' => $schedule->id_lie
];
}
$model_lie = $schedule->model_lie;
} else {
$model_lie = ['label' => null, 'value' => null];
}//end if
if ($prevUserId != $schedule->user_id) {
// New user.
$arSchedules[$schedule->user_id] = array(
$schedule->slot => array(
$schedule->date->format('d/m/Y') => array(
'id' => $schedule->id,
'type' => $schedule->activity,
'text' => $schedule->description,
'id_lie' => $id_lie,
'model_lie' => $model_lie,
),
)
);
} else {
// Same user.
if ($prevSlot != $schedule->slot) {
// New slot.
$arSchedules[$schedule->user_id][$schedule->slot] = array(
$schedule->date->format('d/m/Y') => array(
'id' => $schedule->id,
'type' => $schedule->activity,
'text' => $schedule->description,
'id_lie' => $id_lie,
'model_lie' => $model_lie,
),
);
} else {
// Same slot.
if ($prevDate != $schedule->date) {
// New date.
$arSchedules[$schedule->user_id][$schedule->slot][$schedule->date->format('d/m/Y')] = array(
'id' => $schedule->id,
'type' => $schedule->activity,
'text' => $schedule->description,
'id_lie' => $id_lie,
'model_lie' => $model_lie,
);
}
} //end if
} //end if
$prevUserId = $schedule->user_id;
$prevDate = $schedule->date;
$prevSlot = $schedule->slot;
} //end foreach
$weekCells = array();
for ($i = 0; $i < $nbweeks; $i++) {
$weekCells[] = array(
"num" => $date->addDays($i * 7)->weekOfYear,
"month" => $date->addDays($i * 7)->shortLocaleMonth,
"year" => $date->addDays($i * 7)->format('Y')
);
}
return view('bo.pages.schedule.index', compact('users', 'date', 'weekCells', 'arSchedules'));
}
/**
* Display cell content.
*
* @param \App\Http\Requests\Bo\StoreScheduleRequest $request
* @return \Illuminate\Http\JsonResponse
* @throws \Illuminate\Contracts\Container\BindingResolutionException BindingResolutionException.
*/
public function setCellContent(StoreScheduleRequest $request)
{
$date = CarbonImmutable::createFromFormat('d/m/Y', $request->date);
$fill = $request->all();
$fill['date'] = $date;
$schedule = Schedule::updateOrCreate(['id' => $request->id], $fill);
$schedule->saveOrFail();
$id_lie = array('label' => null, 'name' => null, 'value' => null);
if (!is_null($schedule->model_lie)) {
if (isset($schedule->relatedModel->name)) {
$id_lie = array(
'label' => $schedule->relatedModel->name,
'name' => $schedule->relatedModel->name,
'value' => $schedule->id_lie
);
} else {
$id_lie = array(
'label' => 'Ticket ' . $schedule->id_lie,
'name' => Ticket::find($schedule->id_lie)->formatNameForSchedule(Ticket::find($schedule->id_lie)),
'value' => $schedule->id_lie
);
}
$model_lie = $schedule->model_lie;
} else {
$model_lie = array('label' => null, 'name' => null, 'value' => null);
}
$arSchd = [
'id' => $schedule->id,
'user_id' => $schedule->user_id,
'date' => $schedule->date->format('d/m/Y'),
'activity' => $schedule->activity,
'description' => $schedule->description,
'id_lie' => $id_lie,
'model_lie' => $model_lie,
'slot' => $schedule->slot,
];
return \response()->json(['status' => true, 'sched' => $arSchd]);
}
/**
* Delet cell content.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\JsonResponse
* @throws \Illuminate\Contracts\Container\BindingResolutionException BindingResolutionException.
*/
public function eraseCellContent(Request $request)
{
$schedule = Schedule::findOrFail($request->id);
$schedule->delete();
return \response()->json(['status' => true]);
}
/**
* Display the auth user schedule.
*
* @return \Illuminate\Http\RedirectResponse
* @throws \Illuminate\Contracts\Container\BindingResolutionException BindingResolutionException.
* @throws \Symfony\Component\Routing\Exception\RouteNotFoundException RouteNotFoundException.
*/
public function showMySchedule()
{
return \redirect()->route('bo.schedule.index')->withCookie(cookie()->forever('userAuthSchedule', 'true'));
}
/**
* Display all the dev schedule.
*
* @return \Illuminate\Http\RedirectResponse
* @throws \Illuminate\Contracts\Container\BindingResolutionException BindingResolutionException.
* @throws \Symfony\Component\Routing\Exception\RouteNotFoundException RouteNotFoundException.
*/
public function showAllSchedules()
{
return \redirect()->route('bo.schedule.index')->withCookie(cookie()->forget('userAuthSchedule'));
}
}

View file

@ -117,7 +117,7 @@ class TicketController extends Controller
{
if ($request->ajax()) {
return \response()->json([
'label' => $ticket->formatNameForSchedule($ticket),
'label' => $ticket->formatName($ticket),
'value' => $ticket->id
]);
}
@ -622,7 +622,7 @@ class TicketController extends Controller
return ToolboxHelper::jsonPaginate(
$this->customPaginate($tickets, $request->pagination),
'formatNameForSchedule'
'formatName'
);
});
}

View file

@ -188,34 +188,6 @@ class UserController extends Controller
return app(ForgotPasswordController::class)->sendResetLinkEmail($request);
}
/**
* Show stats
*
* @return \Illuminate\Contracts\View\View
*/
public function stats(): \Illuminate\Contracts\View\View
{
/** @var \App\Models\User */
$user = auth()->user();
$stats = [];
$curYear = date('Y');
for ($i = 2021; $i <= $curYear; $i++) {
$start = $i . '-03-01';
$end = $i + 1 . '-02-' . $this->getLastDayFebruary($i + 1);
$datas = $user->schedules()->selectRaw('count(id) as nb, activity')
->whereBetween('date', [$start, $end])
->groupBy('activity')
->orderBy('activity', 'ASC')
->get();
$stats[sprintf("%d/%d", $i, $i + 1)] = $datas;
}
return view('bo.pages.users.stats', ['stats' => array_reverse($stats)]);
}
/**
* Get february last day date of the year
*

View file

@ -1,80 +0,0 @@
<?php
namespace App\Http\Requests\Bo;
use App\Enums\Planning\ActivityTypeEnum;
use App\Enums\Planning\CellModelEnum;
use App\Enums\Planning\TableRowEnum;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rules\Enum;
class StoreScheduleRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return boolean
*/
public function authorize()
{
return auth()->check() and $this->ajax();
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'user_id' => 'required|exists:users,id',
'date' => 'date_format:d/m/Y',
'activity' => [
'required',
new Enum(ActivityTypeEnum::class),
function ($attribute, $value, $fail) {
if (
\in_array($value, [
ActivityTypeEnum::dev->name(),
ActivityTypeEnum::projects->name(),
]) and
is_null($this->id_lie)
) {
$fail(trans("$attribute : Il est obligatoire d'assigner un type d'élement lié au ticket"));
}
}
],
'slot' => [
'required',
new Enum(TableRowEnum::class)
],
'model_lie' => [
'nullable',
new Enum(CellModelEnum::class),
],
'id_lie' => [
'required_with:model_lie',
'nullable',
'numeric',
],
'description' => 'required|string|min:3|max:90'
];
}
/**
* Get custom attributes for validator errors.
*
* @return array
*/
public function attributes(): array
{
return [
'user_id' => \trans('utilisateur'),
'activity' => \trans('type d\'activitée'),
'model_lie' => \trans('type d\'élément lié'),
'id_lie' => \trans('élément lié'),
'slot' => \trans('ligne de la journée'),
];
}
}

View file

@ -1,80 +0,0 @@
<?php
namespace App\Models;
use App\Enums\Planning\ActivityTypeEnum;
use App\Enums\Planning\CellModelEnum;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
/**
* @property User $user_id
* @property date $date
* @property integer $slot
* @property ActivityTypeEnum $activity
* @property string $description
* @property Ticket|Site|Projet $id_lie
* @property CellModelEnum $model_lie
*/
class Schedule extends Model
{
use HasFactory;
/**
* The attributes that are fillable.
*
* @var array
*/
protected $fillable = [
'user_id',
'date',
'slot',
'activity',
'description',
'id_lie',
'model_lie'
];
/**
* The attributes that should be cast.
*
* @var array
*/
protected $casts = [
'date' => 'date',
'activity' => ActivityTypeEnum::class,
'model_lie' => CellModelEnum::class
];
// * RELATIONSHIPS
/**
* BelongsTo User relation
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function user()
{
return $this->belongsTo(User::class);
}
/**
* Relationship to linked objet
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function relatedModel()
{
switch ($this->model_lie->value) {
case 'sites':
return $this->belongsTo(Site::class, 'id_lie');
case 'projects':
return $this->belongsTo(Project::class, 'id_lie');
case 'tickets':
return $this->belongsTo(Ticket::class, 'id_lie');
default:
return new BelongsTo($this->newQuery(), $this, '', '', '');
}
}
}

View file

@ -265,7 +265,7 @@ class Ticket extends Model
* @param self $ticket
* @return string
*/
public static function formatNameForSchedule(self $ticket): string
public static function formatName(self $ticket): string
{
return sprintf(
'Ticket %d (%s): %s',

View file

@ -191,14 +191,4 @@ class User extends Authenticatable
{
return $this->belongsToMany(Site::class);
}
/**
* HasMany Schedule relation
*
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function schedules()
{
return $this->hasMany(Schedule::class);
}
}

View file

@ -1,7 +1,6 @@
<?php
use App\Enums\Invoices\InvoiceStatusEnum;
use App\Models\Invoice;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

View file

@ -0,0 +1,40 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class DropSchedulesTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up(): void
{
Schema::dropIfExists('schedules');
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down(): void
{
Schema::create('schedules', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')->unique();
$table->foreign('user_id')->on('sites')->references('id');
$table->date('date')->unique();
$table->tinyInteger('slot')->unique();
$table->string('activity')->nullable();
$table->text('description');
$table->bigInteger('id_lie');
$table->string('model_lie');
$table->timestamps();
});
}
}

View file

@ -14,7 +14,6 @@ return [
'download' => 'Télécharger',
'historic' => 'Historique',
'credit' => 'Créditer',
'stats' => 'Statistiques',
],
'helpers' => [

File diff suppressed because it is too large Load diff

View file

@ -1,76 +0,0 @@
@extends('layout.app')
@section('title', __('Planning'))
@section('description', __('Planning de l\'équipe Uwil'))
@section('content')
<div id="planning" class="container container-xxl vueComponent">
<div class="row sticky-top bg-white z-2 py-2 mb-3">
<div class="col">
<h4 class="d-inline me-3">{{__('Légende')}}</h4>
<div class="d-inline">
@foreach(\App\Enums\Planning\CellTypeEnum::cases() as $type)
<span class="badge text-dark celltype-{{ Str::slug($type->label()) }} my-1">{{ $type->label() }}</span>
@endforeach
</div>
</div>
@if (\auth()->user()->role->equals(\App\Enums\Users\RoleEnum::developper))
<div class="col-2 text-end p-0">
@if (request()->cookie('userAuthSchedule'))
<a href="{{ route('bo.schedule.showAllSchedules') }}" class="btn btn-primary btn-sm">{{__('Afficher les plannings')}}</a>
@else
<a href="{{ route('bo.schedule.showMySchedule') }}" class="btn btn-primary btn-sm">{{__('Afficher mon planning')}}</a>
@endif
</div>
@endif
</div>
@php
$dataVue = [
'browseDate' => $date,
'schedules' => $arSchedules,
'activities' => \App\Enums\Planning\ActivityTypeEnum::toArray(),
'models' => \App\Enums\Planning\CellModelEnum::toArray(),
'users' => $users,
'weeks' => $weekCells,
'daySlots' => Config::get('schedules.daySlots'),
'showWeekends' => 'false',
];
@endphp
<div id="schedule" data-json='@json($dataVue)'></div>
</div>
@endsection
@push('styles')
<style nonce="{{ $nonce }}">
.support {
background-color: {{ \App\Enums\Planning\CellTypeEnum::support->color() }} !important;
}
.rnd {
background-color: {{ \App\Enums\Planning\CellTypeEnum::rnd->color() }} !important;
}
.dev {
background-color: {{ \App\Enums\Planning\CellTypeEnum::dev->color() }} !important;
}
.projects {
background-color: {{ \App\Enums\Planning\CellTypeEnum::projects->color() }} !important;
}
.management {
background-color: {{ \App\Enums\Planning\CellTypeEnum::management->color() }} !important;
}
.absence, .Sat, .Sun {
background-color: {{ \App\Enums\Planning\CellTypeEnum::absence->color() }} !important;
}
.leaddev {
background-color: {{ \App\Enums\Planning\CellTypeEnum::leaddev->color() }} !important;
}
.empty {
background-color: #FFF !important;
}
@foreach(\App\Enums\Planning\CellTypeEnum::cases() as $type)
.celltype-{{ Str::slug($type->label()) }} {
background-color: {{ $type->color() }};
font-size: 1rem;
}
@endforeach
</style>
@endpush

View file

@ -1,58 +0,0 @@
@extends('layout.app')
@section('title', __('Statistiques'))
@section('description', __('Statistiques de l\':model :user', ['model' => Str::singular(__('models.classes.users')), 'user' => auth()->user()->name]))
@section('content')
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center">
@include('breadcrumbs.breadcrumb-body')
</div>
@foreach ($stats as $index => $stat)
<table class="table mt-3">
<thead class="table-dark">
<tr>
<th>{{ $index }}</th>
<th>{{ __('Jour(s)') }}</th>
<th>%</th>
</tr>
</thead>
<tbody>
@php
$workdays = 260;
if (strpos($index, '2021') !== false) {
$workdays = 105;
}
$sum = 0;
@endphp
@foreach ($stat as $data)
<tr class="{{ Str::slug('celltype-'. \App\Enums\Planning\CellTypeEnum::make($data->activity->value)->label()) }}">
<td><b>{{ $data->activity->label() }}</b></td>
<td class="w-25"><b>{{ $data->nb / Config::get('schedules.daySlots') }}</b></td>
<td class="w-25">{{ round((($data->nb / Config::get('schedules.daySlots')) / $workdays) * 100) }}%</td>
</tr>
@php $sum += $data->nb; @endphp
@endforeach
<tr>
<td><b>{{ __('Total') }}</b></td>
<td class="w-25"><b>{{ $sum / Config::get('schedules.daySlots') }} / {{ $workdays }}</b></td>
<td class="w-25"><b>{{ round((($sum / 8) / $workdays) * 100) }}%</b></td>
</tr>
</tbody>
</table>
@endforeach
@endsection
@push('styles')
<style nonce="{{ $nonce }}">
@foreach(\App\Enums\Planning\CellTypeEnum::cases() as $type)
.celltype-{{ Str::slug($type->label()) }} {
background-color: {{ $type->color() }};
border: 1px solid black;
td {
background-color: inherit;
}
}
@endforeach
</style>
@endpush

View file

@ -68,11 +68,6 @@
</li>
@endcan
@endif
@can('isAdmin')
<li class="nav-item">
<a class="nav-link @if(Route::is('bo.schedule.*'))active @endif" href="{{ route('bo.schedule.index') }}">{{ __('Planning') }}</a>
</li>
@endcan
</ul>
@can('isAdmin')
<ul class="navbar-nav me-auto">
@ -109,11 +104,6 @@
</a>
<div class="dropdown-menu dropdown-menu-right" aria-labelledby="navbarDropdown">
@can('isDev')
<a class="dropdown-item" href="{{ route('bo.users.stats') }}">
{{ __('Statistiques') }}
</a>
@endcan
<a class="dropdown-item" href="{{ route('bo.users.passwordReset') }}">
{{ __('Identifiants') }}
</a>

View file

@ -25,11 +25,6 @@
show: "{{ route('bo.projects.show', ['project' => 'PROJECT']) }}",
"json-paginate": "{{ route('bo.projects.json-paginate') }}"
};
window.__SYSTEM._routes.schedule = {
index: "{{ route('bo.schedule.index') }}",
setCellContent: "{{ route('bo.schedule.setCellContent') }}",
eraseCellContent: "{{ route('bo.schedule.eraseCellContent') }}"
};
window.__SYSTEM._routes.invoices = {
"json-paginate": "{{ route('bo.invoices.json-paginate') }}",
};

View file

@ -66,10 +66,6 @@ Breadcrumbs::for('bo.users.edit', function (Generator $trail, User $user) {
$trail->parent('bo.users.index');
$trail->push(__('crud.actions.edit'), route('bo.users.edit', $user->id));
});
Breadcrumbs::for('bo.users.stats', function (Generator $trail) {
$trail->parent('bo.users.index');
$trail->push(__('crud.actions.stats'));
});
// * TICKET_TYPES
Breadcrumbs::for('bo.ticket_types.index', function (Generator $trail) {

View file

@ -12,7 +12,6 @@ use App\Http\Controllers\Bo\InvoiceController;
use App\Http\Controllers\Bo\LabelController;
use App\Http\Controllers\Bo\PackageController;
use App\Http\Controllers\Bo\ProjectController;
use App\Http\Controllers\Bo\ScheduleController;
use App\Http\Controllers\Bo\SiteController;
use App\Http\Controllers\Bo\TicketController;
use App\Http\Controllers\Bo\TicketTypeController;
@ -47,6 +46,7 @@ Route::middleware('admin-secure')
Route::middleware(['can:isAdmin'])
->group(function () {
// * RESOURCES
Route::resource('users', UserController::class)->except('show');
Route::resource('informations', InformationController::class)->except('show');
Route::resource('ticket_types', TicketTypeController::class)
->only(['index', 'edit', 'update'])
@ -68,10 +68,6 @@ Route::middleware('admin-secure')
->parameters(['credit_accounts' => 'account', 'credit_logs' => 'credit_log']);
Route::resource('labels', LabelController::class)->except('show');
// * USERS
Route::resource('users', UserController::class)->except('show');
Route::get('/users/stats', [UserController::class, 'stats'])->name('users.stats');
// * INVOICES
Route::get('/invoices/json/paginate', [InvoiceController::class, 'jsonPaginate'])
->name('invoices.json-paginate');
@ -94,27 +90,6 @@ Route::middleware('admin-secure')
Route::post('/ticket/{ticket}/create-issue', [TicketController::class, 'createGitlabIssue'])
->middleware('can:createGitlabIssue,ticket')
->name('ticket.create-issue');
// * SCHEDULE
Route::prefix('/schedule')
->name('schedule.')
->group(function () {
Route::get('/', [ScheduleController::class, 'index'])->name('index');
Route::post('/setCellContent', [ScheduleController::class, 'setCellContent'])
->name('setCellContent');
Route::post('/eraseCellContent', [
ScheduleController::class,
'eraseCellContent'
])
->name('eraseCellContent');
Route::get('/show-my-schedule', [ScheduleController::class, 'showMySchedule'])
->name('showMySchedule');
Route::get('/show-all-schedules', [
ScheduleController::class,
'showAllSchedules'
])
->name('showAllSchedules');
});
});
Route::resource('credit_accounts', AccountController::class)
->only(['index'])