Merge branch 'develop' into trunk

This commit is contained in:
Vincent BRIDIER 2025-04-18 09:59:53 +02:00
commit 3a2b5a0af9
No known key found for this signature in database
GPG key ID: 8571BFA20420D512
59 changed files with 607 additions and 911 deletions

View file

@ -8,13 +8,17 @@ enum GitlabUsersEnum: int
{
use BaseEnum;
// Each user is associated to his ID on gitlab.
case nicolas = 24;
/**
* Each user is associated to his ID on gitlab.
*
* 24 is Nicolas Demangeat
*/
case default = 24;
/**
* Optionnal labels definition
*/
private const LABELS = [
self::nicolas->name => "Nicolas Demangeat",
self::default->name => "Default",
];
}

View file

@ -1,29 +0,0 @@
<?php
namespace App\Http\Controllers\Bo;
use App\Http\Controllers\Controller;
use App\Models\Dutyhour;
use Illuminate\Contracts\View\View;
class DashboardController extends Controller
{
/**
* Show Home page
*
* @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory
*/
public function index(): View
{
/**
* Get only duty hours for today or later.
*
* @var \Illuminate\Database\Eloquent\Builder $dutyhour
*/
$dutyhourModels = Dutyhour::where('date', '>', now()->modify('-1 day'))
->orderBy('date', 'asc')
->limit(10)
->get();
return view('home', compact('dutyhourModels'));
}
}

View file

@ -1,157 +0,0 @@
<?php
namespace App\Http\Controllers\Bo;
use App\Http\Controllers\Controller;
use App\Http\Requests\Bo\Dutyhours\StoreDutyhourRequest;
use App\Http\Requests\Bo\Dutyhours\UpdateDutyhourRequest;
use App\Models\Dutyhour;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
class DutyhourController extends Controller
{
/**
* Display a listing of the resource.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Contracts\View\View
*/
public function index(Request $request): \Illuminate\Contracts\View\View
{
/** @var \Illuminate\Database\Eloquent\Builder $dutyhourModels */
$dutyhourModels = Dutyhour::query();
/** @var string $search Search field */
$search = $request->search;
if ($search) {
$this->searchQuery(
$dutyhourModels,
$search,
null,
'date',
'person',
'place'
);
}
$searchFields = trans('Date, personne, lieu');
/** Sort columns with a query */
$this->sortQuery($dutyhourModels);
/** Custom pagination */
$dutyhourModels = $this->customPaginate($dutyhourModels, $request->pagination);
return view('bo.pages.dutyhours.index', compact('dutyhourModels', 'search', 'searchFields'));
}
/**
* Show the form for creating a new resource.
*
* @param \App\Models\Dutyhour $dutyhour
* @return \Illuminate\Contracts\View\View
*/
public function create(Dutyhour $dutyhour): \Illuminate\Contracts\View\View
{
return view('bo.pages.dutyhours.create', [
'dutyhourModel' => $dutyhour
]);
}
/**
* Store a newly created resource in storage.
*
* @param \App\Http\Requests\Bo\Dutyhours\StoreDutyhourRequest $request
* @return \Illuminate\Http\RedirectResponse
*/
public function store(StoreDutyhourRequest $request): \Illuminate\Http\RedirectResponse
{
return DB::transaction(function () use ($request) {
$dutyhour = new Dutyhour();
$dutyhour->fill($request->validated());
if ($dutyhour->saveOrFail()) {
return redirect()
->route('bo.dutyhours.edit', $dutyhour)
->with('success', trans(
'crud.messages.has_been_created',
['model' => Str::singular(trans('models.classes.dutyhours'))]
));
}
return redirect()
->back()
->with('error', trans(
'crud.messages.cannot_be_created',
['model' => Str::singular(trans('models.classes.dutyhours'))]
));
});
}
/**
* Show the form for editing the specified resource.
*
* @param \App\Models\Dutyhour $dutyhour
* @return \Illuminate\Contracts\View\View
*/
public function edit(Dutyhour $dutyhour): \Illuminate\Contracts\View\View
{
return view('bo.pages.dutyhours.edit', [
'dutyhourModel' => $dutyhour
]);
}
/**
* Update the specified resource in storage.
*
* @param \App\Http\Requests\Bo\Dutyhours\UpdateDutyhourRequest $request
* @param \App\Models\Dutyhour $dutyhour
* @return \Illuminate\Http\RedirectResponse
*/
public function update(UpdateDutyhourRequest $request, Dutyhour $dutyhour): \Illuminate\Http\RedirectResponse
{
return DB::transaction(function () use ($request, $dutyhour) {
$dutyhour->fill($request->validated());
if ($dutyhour->saveOrFail()) {
return redirect()
->route('bo.dutyhours.edit', $dutyhour)
->with('success', trans(
'crud.messages.has_been_updated',
['model' => Str::singular(trans('models.classes.dutyhours'))]
));
} //end if
return redirect()
->back()
->with('error', trans(
'crud.messages.cannot_be_updated',
['model' => Str::singular(trans('models.classes.dutyhours'))]
));
});
}
/**
* Remove the specified resource from storage.
*
* @param \App\Models\Dutyhour $dutyhour
* @return \Illuminate\Http\RedirectResponse
*/
public function destroy(Dutyhour $dutyhour): \Illuminate\Http\RedirectResponse
{
return DB::transaction(function () use ($dutyhour) {
if ($dutyhour->deleteOrFail()) {
return redirect()
->route('bo.dutyhours.index')
->with('success', trans(
'crud.messages.has_been_deleted',
['model' => Str::singular(trans('models.classes.dutyhours'))]
));
}
return redirect()
->back()
->with('error', trans(
':crud.messages.cannot_be_deleted',
['model' => Str::singular(trans('models.classes.dutyhours'))]
));
});
}
}

View file

@ -9,6 +9,7 @@ use App\Lib\Helpers\ToolboxHelper;
use App\Models\Site;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
@ -23,7 +24,7 @@ class SiteController extends Controller
public function index(Request $request): \Illuminate\Contracts\View\View
{
/** @var \App\Models\User $user */
$user = \auth()->user();
$user = Auth::user();
if ($user->isAdmin()) {
/** @var \Illuminate\Database\Eloquent\Builder $siteModels */

View file

@ -27,11 +27,11 @@ use App\Models\User;
use GrahamCampbell\GitLab\Facades\GitLab;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Http\Request;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Session;
use Illuminate\Support\Str;
use Illuminate\Support\Arr;
class TicketController extends Controller
{
@ -97,6 +97,12 @@ class TicketController extends Controller
TicketStatusEnum::archived
);
if (!$user->isAdmin() && $user->sites->count() === 1) {
$request->merge([
'pr' => $user->sites->first()->id,
]);
}
$tickets = $this->filterTickets($tickets, $request);
$tickets = $this->searchTicket($tickets, $request);
@ -107,8 +113,12 @@ class TicketController extends Controller
$tickets = $this->customPaginate($tickets, $request->pagination);
$sites = Site::select('id', 'name')->orderBy('name')->get();
$status = TicketStatusEnum::cases();
$types = TicketTypeEnum::cases();
$status = Arr::sort(TicketStatusEnum::cases(), function (TicketStatusEnum $value) {
return $value->label();
});
$types = Arr::sort(TicketTypeEnum::cases(), function (TicketTypeEnum $value) {
return $value->label();
});
return view('bo.pages.tickets.index', compact('tickets', 'sites', 'status', 'types'));
}
@ -140,13 +150,10 @@ class TicketController extends Controller
abort(403);
}
$linkedTicket = $ticket->linkedTicket()->get();
$messages = $ticket->messages()->orderBy('created_at', 'DESC')->get();
$isSubscribed = (bool)$ticket->subscriptions()->where('user_id', $user->id)->count();
return view('bo.pages.tickets.show', [
'ticket' => $ticket,
'linkedTicket' => $linkedTicket,
'messages' => $messages,
'isSubscribed' => $isSubscribed
]);
@ -553,6 +560,8 @@ class TicketController extends Controller
Session::remove('tickets.st');
Session::remove('tickets.pr');
Session::remove('tickets.ty');
Session::remove('tickets.sort_col');
Session::remove('tickets.sort_way');
Session::remove('tickets.or');
Session::remove('tickets.search');
}
@ -568,6 +577,12 @@ class TicketController extends Controller
if ($request->tys) {
Session::remove('tickets.ty');
}
if ($request->sort_col) {
Session::put('tickets.sort_col', $request->sort_col);
}
if ($request->sort_way) {
Session::put('tickets.sort_way', $request->sort_way);
}
if ($request->ord) {
Session::remove('tickets.or');
}
@ -576,7 +591,6 @@ class TicketController extends Controller
}
if ($request->st) {
Session::put('tickets.st', $request->st);
Session::remove('tickets.or');
}
if ($request->ty) {
Session::put('tickets.ty', $request->ty);
@ -584,9 +598,19 @@ class TicketController extends Controller
if ($request->ass) {
Session::put('tickets.ass', $request->ass);
}
if (Session::has('tickets.or')) {
Session::remove('tickets.ass');
Session::remove('tickets.st');
Session::remove('tickets.ty');
Session::remove('tickets.sort_col');
Session::remove('tickets.sort_way');
Session::remove('tickets.search');
}
if ($request->or && Session::has('tickets.pr')) {
Session::put('tickets.or', $request->or);
}
Session::save();
if (Session::has('tickets.pr')) {
@ -609,6 +633,24 @@ class TicketController extends Controller
if (Session::has('tickets.or')) {
$tickets->orderBy('order', 'ASC');
}
if (
Session::has('tickets.sort_col') and
Session::has('tickets.sort_way') and
in_array(Session::get('tickets.sort_col'), [
'type',
'title',
'assigned_to',
'date_mep',
'created_at',
'created_by'
])
) {
$tickets->orderBy(
Session::get('tickets.sort_col'),
Session::get('tickets.sort_way')
);
} else {
$tickets->orderBy('last_activity', 'DESC');
}
@ -707,7 +749,13 @@ class TicketController extends Controller
$description = \sprintf("%s<br>", $ticket->text);
$cLabel = match ($ticket->type) {
TicketTypeEnum::bug => 'c-bug',
TicketTypeEnum::evolution => 'c-feature',
TicketTypeEnum::evolution, TicketTypeEnum::newsletter => 'c-feature',
};
$assigneeId = match ($ticket->type) {
TicketTypeEnum::bug => GitlabUsersEnum::default->value,
TicketTypeEnum::evolution,
TicketTypeEnum::newsletter => $ticket->site->projectManager?->gitlab_id ?? GitlabUsersEnum::default->value
};
try {
@ -719,13 +767,17 @@ class TicketController extends Controller
}
$issue = GitLab::issues()->create($gitlabRepoId, [
'title' => 'ts-' . $ticket->id,
'title' => sprintf(
'ts-%s : %s',
$ticket->id,
$ticket->title
),
'description' => $description,
'labels' => \implode(",", [
'c-support',
$cLabel
]),
'assignee_id' => GitlabUsersEnum::nicolas,
'assignee_id' => $assigneeId,
]);
} catch (\Exception $e) {
\report($e);

View file

@ -1,47 +0,0 @@
<?php
namespace App\Http\Requests\Bo\Dutyhours;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Facades\Gate;
class StoreDutyhourRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return boolean
*/
public function authorize()
{
return Gate::allows('isAdmin');
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'date' => 'required|date|after_or_equal:today',
'person' => 'required|string|min:3|max:255',
'place' => 'required|string|min:3|max:255',
];
}
/**
* Get custom attributes for validator errors.
*
* @return array
*/
public function attributes(): array
{
return [
'date' => trans('Date de la permanence'),
'person' => trans('Personne associée à la permanence'),
'place' => trans('Lieu de la permanence'),
];
}
}

View file

@ -1,7 +0,0 @@
<?php
namespace App\Http\Requests\Bo\Dutyhours;
class UpdateDutyhourRequest extends StoreDutyhourRequest
{
}

View file

@ -3,6 +3,7 @@
namespace App\Http\Requests\Bo;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Facades\Auth;
class LinkTicket extends FormRequest
{
@ -13,7 +14,9 @@ class LinkTicket extends FormRequest
*/
public function authorize(): bool
{
return auth()->check();
/** @var \App\Models\User|null $user */
$user = Auth::user();
return Auth::check() && $user->isAdmin();
}
/**

View file

@ -29,6 +29,7 @@ class StoreSiteRequest extends FormRequest
'users' => 'nullable|array',
'users.*.id' => 'required|exists:users,id',
'gitlab_project_id' => 'nullable|unique:sites,gitlab_project_id',
'project_manager_id' => 'nullable|exists:users,id',
'url_re7' => 'nullable|url',
'url_prod' => 'nullable|url'
];
@ -46,6 +47,7 @@ class StoreSiteRequest extends FormRequest
'users' => trans('Utilisateurs associés au site'),
'users.*.id' => trans('Élément parmis les Utilisateurs associés au site'),
'gitlab_project_id' => trans('ID du dépôt Gitlab'),
'project_manager_id' => trans('Chef de projet'),
'url_re7' => trans('Url de RECETTE'),
'url_prod' => trans('Url de prod')
];

View file

@ -96,7 +96,7 @@ class StoreTicket extends FormRequest
}
}
],
'date_mep' => 'required|date',
'date_mep' => 'nullable|date',
'text' => 'required|string|min:40',
'title' => 'required|string|between:3,255',
'file_tickets' => 'sometimes|array',

View file

@ -34,7 +34,8 @@ class StoreUserRequest extends FormRequest
Rule::in(collect(RoleEnum::cases())->pluck('value')->all()),
],
'sites' => 'nullable|array',
'sites.*.id' => 'required|exists:sites,id'
'sites.*.id' => 'required|exists:sites,id',
'gitlab_id' => 'nullable|integer|unique:users,gitlab_id'
];
}
@ -51,6 +52,7 @@ class StoreUserRequest extends FormRequest
'role' => trans('Rôle de l\'utilisateur'),
'sites' => trans('Sites associés à l\'utilisateur'),
'sites.*.id' => trans('Élément parmis les sites associés à l\'utilisateur'),
'gitlab_id' => trans("ID de l'utilisateur Gitlab")
];
}
}

View file

@ -22,8 +22,7 @@ class AddStatusMessages
$message = new Message();
$message->ticket_id = $event->ticket->id;
// * Le message system est privé si demandé (eg: Assignation à une personne).
$message->type = $event->is_private ?
MessageTypeEnum::public : MessageTypeEnum::private;
$message->type = $event->is_private ? MessageTypeEnum::private : MessageTypeEnum::public;
if ($event->message) {
$message->message = $event->message;
} elseif ($event->user) {

View file

@ -1,43 +0,0 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
/**
* @property date $date
* @property string $person
* @property string $place
*/
class Dutyhour extends Model
{
use HasFactory;
/**
* Indicates if the model should be timestamped.
*
* @var boolean
*/
public $timestamps = true;
/**
* The attributes that are fillable.
*
* @var array
*/
protected $fillable = [
'date',
'person',
'place'
];
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $casts = [
'date' => 'date'
];
}

View file

@ -6,6 +6,7 @@ use App\Lib\Helpers\ToolboxHelper;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\SoftDeletes;
/**
@ -29,7 +30,8 @@ class Site extends Model
'name',
'url_re7',
'url_prod',
'gitlab_project_id'
'gitlab_project_id',
'project_manager_id'
];
/**
@ -109,6 +111,17 @@ class Site extends Model
return $this->belongsTo(Brand::class);
}
/**
* BelongsTo User relation
* The project manager of the site
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function projectManager(): BelongsTo
{
return $this->belongsTo(User::class, 'project_manager_id');
}
/**
* BelongsTo Project relation
*

View file

@ -198,7 +198,7 @@ class Ticket extends Model
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function linkedTicket()
public function linkedTickets()
{
return $this->belongsToMany(Ticket::class, 'linked_tickets', 'ticket_id', 'linked_ticket_id');
}

View file

@ -45,7 +45,8 @@ class User extends Authenticatable
'email',
'password',
'role',
'sites'
'sites',
'gitlab_id'
];
/**
@ -148,8 +149,8 @@ class User extends Authenticatable
*/
public static function adminUsers(): Collection
{
return Cache::rememberForever('AdminUsers', function () {
return self::whereIn('role', [RoleEnum::admin, RoleEnum::developper])->get();
return Cache::remember('AdminUsers', 86400, function () {
return self::whereIn('role', [RoleEnum::admin, RoleEnum::developper])->orderBy('name')->get();
});
}

View file

@ -7,6 +7,7 @@ use App\Enums\Tickets\TicketTypeEnum;
use App\Enums\Users\RoleEnum;
use App\Models\Ticket;
use App\Models\User;
use Error;
use Illuminate\Auth\Access\HandlesAuthorization;
class TicketPolicy
@ -283,8 +284,21 @@ class TicketPolicy
public function createGitlabIssue(User $user, Ticket $ticket)
{
return $user->role->equals(RoleEnum::developper)
&& ($ticket->type->equals(TicketTypeEnum::bug) || $ticket->type->equals(TicketTypeEnum::evolution))
&& ($ticket->type->equals(TicketTypeEnum::bug) || $ticket->type->equals(TicketTypeEnum::evolution) || $ticket->type->equals(TicketTypeEnum::newsletter))
&& !\is_null($ticket->site->gitlab_project_id)
&& \is_null($ticket->gitlab_issue);
}
/**
* Determine if the user can changeOrder
*
* @param User $user
* @return bool
* @throws Error
*/
public function changeOrder(User $user)
{
return $user->role->equals(RoleEnum::developper);
}
}

View file

@ -6,7 +6,6 @@ use App\Models\Brand;
use App\Models\Company;
use App\Models\Credit\Account;
use App\Models\Credit\CreditLog;
use App\Models\Dutyhour;
use App\Models\Information;
use App\Models\Invoice;
use App\Models\Label;
@ -91,7 +90,6 @@ class RouteServiceProvider extends ServiceProvider
Route::model('label', Label::class);
Route::model('marker', Marker::class);
Route::model('package', Package::class);
Route::model('dutyhour', Dutyhour::class);
Route::model('information', Information::class);
Route::model('company', Company::class);
Route::model('invoice', Invoice::class);

View file

@ -19,7 +19,7 @@ class TranslationServiceProvider extends ServiceProvider
{
foreach ($this->collectLocalesStrings() as $locale) {
// * Supported locales
Cache::rememberForever(sprintf('translations.%s', $locale), function () use ($locale) {
Cache::remember(sprintf('translations.%s', $locale), 84600, function () use ($locale) {
$translations = [
'php' => $this->phpTranslations($locale),
'json' => $this->jsonTranslations($locale),

View file

@ -0,0 +1,30 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::dropIfExists('dutyhours');
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::create('dutyhours', function (Blueprint $table) {
$table->id();
$table->date('date')->unique();
$table->string('person');
$table->string('place');
$table->timestamps();
});
}
};

View file

@ -0,0 +1,38 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up(): void
{
Schema::table('sites', function (Blueprint $table) {
$table->unsignedBigInteger('project_manager_id')
->nullable()
->after('brand_id')
->comment('Project manager relationship');
$table->foreign('project_manager_id')->references('id')->on('users')->nullOnDelete();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down(): void
{
Schema::table('sites', function (Blueprint $table) {
$table->dropForeign(['project_manager_id']);
$table->dropColumn('project_manager_id');
});
}
};

View file

@ -0,0 +1,36 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up(): void
{
Schema::table('users', function (Blueprint $table) {
$table->unsignedInteger('gitlab_id')
->unique()
->nullable()
->comment("ID du user Gitlab")
->after('remember_token');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down(): void
{
Schema::table('users', function (Blueprint $table) {
$table->dropColumn('gitlab_id');
});
}
};

View file

@ -14,7 +14,6 @@ return [
'packages' => 'Packages',
'invoices' => 'Invoices',
'companies' => 'Companies',
'dutyhours' => 'Duty Hours',
'informations' => 'Informations',
'ticket_types' => 'Ticket types'
]

View file

@ -221,7 +221,6 @@ return [
'order' => 'order',
'priority' => 'priority',
'default' => 'default',
'date_mep' => 'desired MEP date',
'date_mep_empty' => 'no date entered'
'date_mep' => 'Desired Launch'
]
];

View file

@ -56,5 +56,6 @@
"Whoops!": "Oups !",
"You are logged in!": "Vous êtes connecté·e !",
"You are receiving this email because we received a password reset request for your account.": "Vous recevez cet e-mail car nous avons reçu une demande de réinitialisation de mot de passe pour votre compte.",
"see_mode": "voir mode :mode"
"see_mode": "voir mode :mode",
"Website": "Site"
}

View file

@ -13,7 +13,6 @@ return [
'packages' => 'Forfaits',
'invoices' => 'Devis',
'companies' => 'Sociétés',
'dutyhours' => 'Permanences',
'informations' => 'Informations',
'ticket_types' => 'Type de ticket|Types de tickets'
]

View file

@ -257,7 +257,6 @@ return [
'order' => 'ordre',
'priority' => 'priorité',
'default' => 'défaut',
'date_mep' => 'date de MEP souhaitée',
'date_mep_empty' => 'aucune date renseignée'
'date_mep' => 'MEP souhaitée'
]
];

View file

@ -1,5 +1,5 @@
.container-xxl {
max-width: 1340px !important;
max-width: 1600px !important;
}
#app {

View file

@ -1,7 +1,5 @@
<td class="text-center align-middle">
@if (isset($value))
{{ $value }}
@endif
<b>{{ $value ?? '' }}</b>
@can('changeOrder', $model)
<div class="d-flex justify-content-center align-items-center">
<form @class(['invisible' => $loop->first and $models->onFirstPage()])

View file

@ -44,11 +44,11 @@
session("$routeName.sort_col") !== $col or
session("$routeName.sort_way") === 'asc' and session("$routeName.sort_col") === $col)
<a class="btn btn-sm btn-outline-secondary text-decoration-none ms-1"
href="{{ request()->fullUrlWithQuery(array_merge($iArgs, ['sort_way' => 'desc', 'rst' => null])) }}"data-bs-toggle="tooltip"
href="{{ request()->fullUrlWithQuery(array_merge($iArgs, ['sort_way' => 'desc', 'rst' => null])) }}" data-bs-toggle="tooltip"
title="{{ __('crud.other.sort_ascending', ['name' => str($colname)->lower()]) }}">
<i class="fas fa-arrow-up 2xs"></i>
</a>
@endif
</div>
</th>
@endif
@endif

View file

@ -1,46 +0,0 @@
@extends('layout.app', ['brParam' => $dutyhourModel])
@section('title', __('Création d\'une :model', ['model' => Str::singular(__('models.classes.dutyhours'))]))
@section('description', __('Création d\'une toute nouvelle :model', ['model' => Str::singular(__('models.classes.dutyhours'))]))
@section('breadcrumb', request()->route()->getName())
@section('content')
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pb-3">
<div class="d-flex flex-row align-items-center">
<a href="{{ route('bo.dutyhours.index') }}"
class="btn btn-primary text-decoration-none m-0 me-2"
data-bs-toggle="tooltip"
data-bs-placement="top"
title="{{ __('crud.helpers.list_all', ['model' => __('models.classes.dutyhours')]) }}">
<i class="fa-solid fa-arrow-left"></i>
</a>
@include('breadcrumbs.breadcrumb-body', ['brParam' => $dutyhourModel])
</div>
<div class="mb-2 mb-md-0">
<button id="formSubmitClone"
type="submit"
class="btn btn-primary"
data-bs-toggle="tooltip"
data-bs-placement="top"
title="{{ __('crud.helpers.save_model', ['model' => Str::singular(__('models.classes.dutyhours'))]) }}">
{{ __('crud.actions.save') }}
</button>
</div>
</div>
<form action="{{ route('bo.dutyhours.store') }}" method="POST" enctype="multipart/form-data">
@csrf
@include('bo.pages.dutyhours.form-inputs')
<div class="row mt-3">
<div class="col text-center">
<button id="formSubmit"
type="submit"
class="btn btn-primary"
data-bs-toggle="tooltip"
data-bs-placement="top"
title="{{ __('crud.helpers.save_model', ['model' => Str::singular(__('models.classes.dutyhours'))]) }}">
{{ __('crud.actions.save') }}
</button>
</div>
</div>
</form>
@endsection

View file

@ -1,62 +0,0 @@
@extends('layout.app', ['brParam' => $dutyhourModel])
@section('title', __('Édition d\'une :model', ['model' => Str::singular(__('models.classes.dutyhours'))]))
@section('description', __('Édition d\'une :model déjà existante', ['model' => Str::singular(__('models.classes.dutyhours'))]))
@section('breadcrumb', request()->route()->getName())
@section('content')
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pb-3">
<div class="d-flex flex-row align-items-start">
<a href="{{ route('bo.dutyhours.index') }}"
class="btn btn-primary text-decoration-none m-0 me-2"
data-bs-toggle="tooltip"
data-bs-placement="top"
title="{{ __('crud.helpers.list_all', ['model' => __('models.classes.dutyhours')]) }}">
<i class="fa-solid fa-arrow-left"></i>
</a>
@include('breadcrumbs.breadcrumb-body', ['brParam' => $dutyhourModel])
</div>
<div class="mb-2 mb-md-0">
<form action="{{ route('bo.dutyhours.destroy', $dutyhourModel->id) }}"
method="POST"
class="confirmDeleteTS">
@csrf
@method('DELETE')
<div class="btn-group" role="group">
<button id="formSubmitClone"
type="submit"
class="btn btn-primary"
data-bs-toggle="tooltip"
data-bs-placement="top"
title="{{ __('crud.helpers.save_model', ['model' => Str::singular(__('models.classes.dutyhours'))]) }}">
{{ __('crud.actions.save') }}
</button>
<button type="submit"
class="btn btn-danger"
data-bs-toggle="tooltip"
data-bs-placement="top"
title="{{ __('crud.helpers.delete_model', ['model' => Str::singular(__('models.classes.dutyhours'))]) }}">
<i class="fa-solid fa-trash"></i>
</button>
</div>
</form>
</div>
</div>
<form action="{{ route('bo.dutyhours.update', $dutyhourModel->id) }}" method="POST" enctype="multipart/form-data">
@csrf
@method('PUT')
@include('bo.pages.dutyhours.form-inputs')
<div class="row">
<div class="col text-center">
<button id="formSubmit"
type="submit"
class="btn btn-primary"
data-bs-toggle="tooltip"
data-bs-placement="top"
title="{{ __('crud.helpers.save_model', ['model' => Str::singular(__('models.classes.dutyhours'))]) }}">
{{ __('crud.actions.save') }}
</button>
</div>
</div>
</form>
@endsection

View file

@ -1,98 +0,0 @@
<div class="row">
{{-- DATE --}}
<div class="col-12 col-md-6 mb-3">
<fieldset class="border h-100 bg-white p-3">
<legend>{{ Str::ucfirst(__('validation.attributes.date')) }}</legend>
<div class="row">
<div class="col-12">
@include('bo.partials.inputs.date', [
'id' => 'dutyhourDate',
'label' => __(':field de la :model', [
'field' => Str::ucfirst(__('validation.attributes.date')),
'model' => Str::singular(__('models.classes.dutyhours')),
]),
'name' => 'date',
'defaultValue' => true,
'required' => true,
'model' => $dutyhourModel ?? null,
'helper' => __('La date doit être supérieure ou égale à aujourd\'hui.'),
])
</div>
</div>
</fieldset>
</div>
{{-- PERSON --}}
<div class="col-12 col-md-6 mb-3">
<fieldset class="border h-100 bg-white p-3">
<legend>{{ Str::ucfirst(__('validation.attributes.person')) }}</legend>
<div class="row">
<div class="col-12">
@include('bo.partials.inputs.varchar', [
'id' => 'dutyhourPerson',
'label' => __('Nom de la personne présente lors de la :model', [
'model' => Str::singular(__('models.classes.dutyhours')),
]),
'hasWordCounter' => true,
'name' => 'person',
'required' => true,
'model' => $dutyhourModel ?? null,
'helper' => __('validation.between.string', [
'attribute' => __('Nom de la personne présente lors de la :model', [
'model' => Str::singular(__('models.classes.dutyhours')),
]),
'min' => 3,
'max' => 255,
]),
'placeholder' => __(':field de la personne', [
'field' => Str::ucfirst(__('validation.attributes.name')),
]),
])
</div>
</div>
</fieldset>
</div>
{{-- PLACE --}}
<div class="col-12 col-md-6 mb-3">
<fieldset class="border h-100 bg-white p-3">
<legend>{{ Str::ucfirst(__('validation.attributes.place')) }}</legend>
<div class="row">
<div class="col-12">
@include('bo.partials.inputs.varchar', [
'id' => 'dutyhourPlace',
'label' => __('Endroit où se déroule la :model', [
'model' => Str::singular(__('models.classes.dutyhours')),
]),
'hasWordCounter' => true,
'name' => 'place',
'required' => true,
'model' => $dutyhourModel ?? null,
'helper' => __('validation.between.string', [
'attribute' => __('endroit où se déroule la :model', [
'model' => Str::singular(__('models.classes.dutyhours')),
]),
'min' => 3,
'max' => 255,
]),
'placeholder' => __('Lieu de la :model', [
'model' => Str::singular(__('models.classes.dutyhours')),
]),
])
</div>
</div>
</fieldset>
</div>
</div>
@push('scripts')
<script nonce="{{ $nonce }}">
document.addEventListener("DOMContentLoaded", () => {
// Submit button clone.
const submit = document.getElementById('formSubmit')
submitClone = document.getElementById('formSubmitClone');
submitClone.addEventListener('click', (event) => {
event.preventDefault();
submit.click('');
})
});
</script>
@endpush

View file

@ -1,68 +0,0 @@
@extends('layout.app')
@section('title', __('models.classes.dutyhours'))
@section('description', __('Liste de toutes les :model', ['model' => __('models.classes.dutyhours')]))
@section('content')
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center">
@include('breadcrumbs.breadcrumb-body')
<a href="{{ route('bo.dutyhours.create') }}"
class="btn btn-primary float-right"
data-bs-toggle="tooltip"
data-bs-placement="top"
title="{{ __('crud.helpers.create_model', ['model' => Str::singular(__('models.classes.dutyhours'))]) }}">
<i class="fa-solid fa-plus"></i>
</a>
</div>
@include('bo.modules.search-bar')
<table class="table table-hover">
@if (count($dutyhourModels) > 0)
<thead>
@include('bo.modules.table-col-sorter', [
'cols' => [
'date' => Str::ucfirst(__('validation.attributes.date')),
'person' => Str::ucfirst(__('validation.attributes.person')),
'place' => Str::ucfirst(__('validation.attributes.place')),
],
])
</thead>
<tbody>
@foreach ($dutyhourModels as $dutyhourModel)
<tr class="list-item border-bottom">
<td class="text-center align-middle">{{ $dutyhourModel->date->format('Y-m-d') }}</td>
<td class="text-center align-middle">{{ $dutyhourModel->person }}</td>
<td class="text-center align-middle">{{ $dutyhourModel->place }}</td>
<td class="text-end align-middle">
<form action="{{ route('bo.dutyhours.destroy', $dutyhourModel->id) }}"
method="POST"
class="btn-group confirmDeleteTS"
novalidate>
<a class="btn btn-sm btn-primary"
href="{{ route('bo.dutyhours.edit', ['dutyhour' => $dutyhourModel->id]) }}"
data-bs-toggle="tooltip"
data-bs-placement="top"
title="{{ __('crud.actions.update') }}">
<i class="fa-solid fa-pencil"></i>
</a>
@csrf
@method('DELETE')
<button type="submit"
class="btn btn-sm btn-danger"
data-bs-toggle="tooltip"
data-bs-placement="top"
title="{{ __('crud.actions.delete') }}">
<i class="fa-solid fa-trash"></i>
</button>
</form>
</td>
</tr>
@endforeach
</tbody>
@else
<tr>
<td class="text-center fw-bold border-0">{{ __('crud.other.no_model_found', ['model' => Str::singular(__('models.classes.dutyhours'))]) }}</td>
</tr>
@endif
</table>
{!! $dutyhourModels->links() !!}
@endsection

View file

@ -59,12 +59,14 @@
</div>
</fieldset>
</div>
</div>
<div class="row">
{{-- GITLAB_PROJECT_ID --}}
<div class="col-12 col-md-6 mb-3">
<fieldset class="h-100 border bg-white p-3">
<legend>{{ Str::ucfirst(__('validation.attributes.gitlab_project_id')) }}</legend>
<div class="row">
<div class="col-12 mb-3">
<div class="col-12">
@include('bo.partials.inputs.int-number', [
'id' => 'siteGitlabProject',
'label' => __(':field du :model', [
@ -86,6 +88,30 @@
</div>
</fieldset>
</div>
{{-- PROJECT MANAGER --}}
<div class="col-12 col-md-6 pb-3">
<fieldset class="h-100 mb-3 border bg-white p-3">
<legend>{{ __('Chef de projet') }}</legend>
<div class="row">
<div class="col-12">
<label for="project_manager" class="col-form-label">
<b>{{ __('Chef de projet') }}</b>
</label>
<select class="form-select" id="project_manager" name="project_manager_id">
<option></option>
@foreach (\App\Models\User::adminUsers() as $user)
<option value="{{ $user->id }}"
@if (intval(old('project_manager_id', ($siteModel and $siteModel->project_manager_id) ? $siteModel->project_manager_id : 0)) == $user->id) selected="selected" @endif>
{{ $user->name }}
</option>
@endforeach
</select>
</div>
</div>
</fieldset>
</div>
</div>
<div class="row">
{{-- SITE URLS --}}
<div class="col-12 mb-3">
<fieldset class="row w-100 h-100 mx-auto border bg-white p-3">

View file

@ -25,6 +25,7 @@
'name' => Str::ucfirst(__('validation.attributes.name')),
'url_re7' => Str::ucfirst(__('validation.attributes.url_re7')),
'url_prod' => Str::ucfirst(__('validation.attributes.url_prod')),
'project_manager_id' => __("Chef de projet"),
],
])
</thead>
@ -46,6 +47,13 @@
-
@endif
</td>
<td class="text-center align-middle">
@if ($siteModel->project_manager_id)
{{ $siteModel->projectManager->name }}
@else
-
@endif
</td>
@can('isAdmin')
<td class="text-end align-middle">
<form action="{{ route('bo.sites.destroy', $siteModel->id) }}"

View file

@ -81,6 +81,16 @@
@endif
</td>
</tr>
<tr class="list-item border-bottom">
<td class="text-center align-middle">{{ __("Chef de projet") }}</td>
<td class="text-center align-middle">
@if ($siteModel->project_manager_id)
{{ $siteModel->projectManager->name }}
@else
-
@endif
</td>
</tr>
<tr class="list-item border-bottom">
<td class="text-center align-middle">{{ Str::ucfirst(__('validation.attributes.created_at')) }}</td>
<td class="text-center align-middle"><span class="badge bg-info">{{ $siteModel->created_at }}</span></td>

View file

@ -96,7 +96,7 @@
<div class="form-group col">
<label class="col-form-label" for="date_mep">{{ __('Date de mise en production souhaitée') }}</label>
<input class="form-control" id="date_mep" name="date_mep" type="date" min="{{ date('Y-m-j') }}" value="{{ old('date_mep') ?? (isset($ticket) && !is_null($ticket->date_mep) ? $ticket->date_mep->format('Y-m-j') : date('Y-m-j')) }}">
<input class="form-control" id="date_mep" name="date_mep" type="date" min="{{ date('Y-m-j') }}" value="{{ old('date_mep') ?? (isset($ticket) && !is_null($ticket->date_mep) ? $ticket->date_mep->format('Y-m-j') : '') }}">
</div>
</div>

View file

@ -9,69 +9,56 @@
$userPr = Auth::user()->sites ?? collect([]);
@endphp
<div class="container-xxl container">
<div class="row">
<div class="col">
<h1 class="fw-bold">{{ __('Tickets') }}
@if (Session::get('tickets.st') == \App\Enums\Tickets\TicketStatusEnum::archived->value)
(Archivés)
@endif
</h1>
@if (session('tickets.pr'))
@php
$projectManager = \App\Models\Site::query()->find(session('tickets.pr'))->projectManager;
@endphp
@if($projectManager)
<h2>{{ __("Chef de projet") }} : {{ $projectManager->name; }}</h2>
@endif
@endif
</div>
<div class="col">
<a class="btn btn-primary float-end" href="{{ route('bo.ticket.create') }}">
<i class="fa-solid fa-square-plus"></i>&nbsp;&nbsp;{{ __('ticket') }}
</a>
</div>
</div>
<div class="row">
<div class="col">
<div class="card">
<div class="card-header">
<h2 class="d-inline">
{{ __('Gestion des tickets') }}
@if (Session::get('tickets.st') == \App\Enums\Tickets\TicketStatusEnum::archived->value)
(Archivés)
@endif
</h2>
<div class="float-end">
<div class="row">
<div class="col">
<div class="btn-group float-end">
@can('isAdmin')
<a class="btn btn-info" href="{{ route('bo.labels.index') }}"><i class="fa-solid fa-tags"></i></a>
@endcan
<a class="btn btn-primary" href="{{ route('bo.ticket.create') }}">
<i class="fa-solid fa-square-plus"></i>&nbsp;&nbsp;{{ __('ticket') }}
</a>
@if (session('tickets.pr') && session('tickets.st') != \App\Enums\Tickets\TicketStatusEnum::archived->value)
@if (session('tickets.or'))
<a class="btn btn-info float-end" href="{{ route('bo.ticket.index', ['ord' => -1]) }}">
<i class="fa-solid fa-equals"></i>&nbsp;&nbsp;{{ __('see_mode', ['mode' => __('validation.custom.default')]) }}
</a>
@else
<a class="btn btn-danger" href="{{ route('bo.ticket.index', ['or' => 1]) }}">
<i class="fa-solid fa-triangle-exclamation"></i>&nbsp;&nbsp;{{ __('see_mode', ['mode' => __('validation.custom.priority')]) }}
</a>
@endif
@endif
@if (session('tickets.st') == \App\Enums\Tickets\TicketStatusEnum::archived->value)
<a class="btn btn-success" href="{{ route('bo.ticket.index', ['sts' => -1]) }}">
<i class="fa-solid fa-inbox"></i>
</a>
@else
<a class="btn btn-secondary float-end"
href="{{ route('bo.ticket.index', ['st' => \App\Enums\Tickets\TicketStatusEnum::archived]) }}">
<i class="fa-solid fa-box-archive"></i>
</a>
@endif
<a class="btn btn-dark" href="{{ route('bo.ticket.index', ['rst' => 1]) }}">
<i class="fa-solid fa-eraser"></i>&nbsp;{{ __(' le tri') }}
</a>
</div>
<div class="float-end me-2">
<div class="row mt-3">
<div class="col">
<div class="row">
{{-- All sites --}}
<div class="col">
<div class="input-group">
<label class="input-group-text" for="selectProject">
<i class="fa-solid fa-diagram-project"></i>
</label>
<select class="form-select" id="selectProject">
<option value="-1">{{ __('Tous') }}</option>
<option value="-1">{{ __('Tous les sites') }}</option>
@foreach ($sites as $site)
@if (Auth::user()->isAdmin())
<option value="{{ $site->id }}"
@if (intval(session('tickets.pr')) == $site->id) selected="selected" @endif>{{ $site->name }}
@if (intval(session('tickets.pr')) == $site->id) selected="selected" @endif>
{{ $site->name }}
</option>
@elseif (
$userPr->filter(function ($pr) use ($site) {
return $pr->id === $site->id;
})->count())
<option value="{{ $site->id }}"
@if (intval(session('tickets.pr')) == $site->id) selected="selected" @endif>{{ $site->name }}
@if (intval(session('tickets.pr')) == $site->id) selected="selected" @endif>
{{ $site->name }}
</option>
@endif
@endforeach
@ -79,102 +66,144 @@
@push('scripts')
<script nonce="{{ $nonce }}">
document.getElementById('selectProject').addEventListener('change', function(e) {
window.location = '{{ route('bo.ticket.index') }}?' + (this.value == -1 ? 'prs=-1' : 'pr=' + this.value);
window.location = '{{ route('bo.ticket.index') }}?' + (this.value == -1 ? 'prs=-1' : 'pr=' + this
.value);
});
</script>
@endpush
</div>
</div>
<div class="float-end me-2">
<div class="input-group">
<label class="input-group-text" for="selectStatus"><i class="fa-solid fa-sign-hanging"></i></label>
<select class="form-select" id="selectStatus">
<option value="-1">{{ __('Tous') }}</option>
@foreach ($status as $statut)
<option value="{{ $statut->value }}"
@if (intval(session('tickets.st')) == $statut->value) selected="selected" @endif>{{ $statut->label() }}
</option>
@endforeach
</select>
@push('scripts')
<script nonce="{{ $nonce }}">
document.getElementById('selectStatus').addEventListener('change', function(e) {
window.location = '{{ route('bo.ticket.index') }}?' + (this.value == -1 ? 'sts=-1' : 'st=' + this.value);
});
</script>
@endpush
</div>
</div>
</div>
</div>
<div class="row">
@can('assignTickets', App\Models\Ticket::class)
{{-- All types --}}
<div class="col">
<div class="float-end me-2 mt-3">
<div class="input-group">
<label class="input-group-text" for="selectAssign"><i class="fa-solid fa-hat-wizard"></i></label>
<select class="form-select" id="selectAssign">
<option value="-1">{{ __('Tous') }}</option>
@foreach (\App\Models\User::adminUsers() as $user)
<option value="{{ $user->id }}"
@if (intval(session('tickets.ass')) == $user->id) selected="selected" @endif>{{ $user->name }}
</option>
@endforeach
</select>
@push('scripts')
<script nonce="{{ $nonce }}">
document.getElementById('selectAssign').addEventListener('change', function(e) {
window.location = '{{ route('bo.ticket.index') }}?' + (this.value == -1 ? 'assr=-1' : 'ass=' + this.value);
});
</script>
@endpush
</div>
</div>
</div>
@endcan
<div class="col">
<div class="float-end me-2 mt-3">
<div class="input-group">
<label class="input-group-text" for="selectType"><i class="fa-solid fa-ticket"></i></label>
<label class="input-group-text" for="selectType"><i
class="fa-solid fa-ticket"></i></label>
<select class="form-select" id="selectType">
<option value="-1">{{ __('Tous les types') }}</option>
@foreach ($types as $type)
<option value="{{ $type->value }}"
@if (intval(session('tickets.ty')) == $type->value) selected="selected" @endif>{{ $type->label() }}
@if (intval(session('tickets.ty')) == $type->value) selected="selected" @endif>
{{ $type->label() }}
</option>
@endforeach
</select>
@push('scripts')
<script nonce="{{ $nonce }}">
document.getElementById('selectType').addEventListener('change', function(e) {
window.location = '{{ route('bo.ticket.index') }}?' + (this.value == -1 ? 'tys=-1' : 'ty=' + this.value);
window.location = '{{ route('bo.ticket.index') }}?' + (this.value == -1 ? 'tys=-1' : 'ty=' + this
.value);
});
</script>
@endpush
</div>
</div>
</div>
<div class="col">
<form class="float-end mt-3" id="searchTicketForm"
action="{{ request()->fullUrlWithQuery(['search' => '']) }}">
<div class="input-group mb-3">
<input class="form-control" id="searchTicket" name="search" type="text"
value="{{ session()->get('tickets.search') }}" aria-label="{{ __('Recherche de ticket...') }}"
aria-describedby="searchTicket" placeholder="{{ __('Recherche de ticket...') }}">
<button class="btn btn-outline-danger" id="searchDelete" type="button"><i
class="fa-solid fa-delete-left"></i></button>
<button class="btn btn-outline-primary" type="submit"><i
class="fa-solid fa-magnifying-glass"></i></button>
{{-- All status --}}
<div class="col">
<div class="input-group">
<label class="input-group-text" for="selectStatus"><i
class="fa-solid fa-sign-hanging"></i></label>
<select class="form-select" id="selectStatus">
<option value="-1">{{ __('Tous les statuts') }}</option>
@foreach ($status as $statut)
<option value="{{ $statut->value }}"
@if (intval(session('tickets.st')) == $statut->value) selected="selected" @endif>
{{ $statut->label() }}
</option>
@endforeach
</select>
@push('scripts')
<script nonce="{{ $nonce }}">
document.getElementById('selectStatus').addEventListener('change', function(e) {
window.location = '{{ route('bo.ticket.index') }}?' + (this.value == -1 ? 'sts=-1' : 'st=' + this
.value);
});
</script>
@endpush
</div>
@push('scripts')
<script nonce="{{ $nonce }}">
document.getElementById('searchDelete').addEventListener('click', function(e) {
document.getElementById('searchTicket').value = '';
document.getElementById('searchTicketForm').submit();
});
</script>
@endpush
</form>
</div>
{{-- All assigned to --}}
@can('assignTickets', App\Models\Ticket::class)
<div class="col">
<div class="input-group">
<label class="input-group-text" for="selectAssign"><i
class="fa-solid fa-hat-wizard"></i></label>
<select class="form-select" id="selectAssign">
<option value="-1">{{ __("Sans filtre d'assignation") }}</option>
@foreach (\App\Models\User::adminUsers() as $user)
<option value="{{ $user->id }}"
@if (intval(session('tickets.ass')) == $user->id) selected="selected" @endif>
{{ $user->name }}
</option>
@endforeach
</select>
@push('scripts')
<script nonce="{{ $nonce }}">
document.getElementById('selectAssign').addEventListener('change', function(e) {
window.location = '{{ route('bo.ticket.index') }}?' + (this.value == -1 ? 'assr=-1' : 'ass=' + this
.value);
});
</script>
@endpush
</div>
</div>
@endcan
{{-- Search form --}}
<div class="col">
<form id="searchTicketForm"
action="{{ request()->fullUrlWithQuery(['search' => '']) }}">
<div class="input-group mb-3">
<input class="form-control" id="searchTicket" name="search" type="text"
value="{{ session()->get('tickets.search') }}"
aria-label="{{ __('Recherche de ticket...') }}" aria-describedby="searchTicket"
placeholder="{{ __('Recherche de ticket...') }}">
<button class="btn btn-outline-danger" id="searchDelete" type="button"><i
class="fa-solid fa-delete-left"></i></button>
<button class="btn btn-outline-primary" type="submit"><i
class="fa-solid fa-magnifying-glass"></i></button>
</div>
@push('scripts')
<script nonce="{{ $nonce }}">
document.getElementById('searchDelete').addEventListener('click', function(e) {
document.getElementById('searchTicket').value = '';
document.getElementById('searchTicketForm').submit();
});
</script>
@endpush
</form>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col">
<div class="btn-group float-end">
@if (session('tickets.pr') && session('tickets.st') != \App\Enums\Tickets\TicketStatusEnum::archived->value)
@if (session('tickets.or'))
<a class="btn btn-info float-end"
href="{{ route('bo.ticket.index', ['ord' => -1]) }}">
<i
class="fa-solid fa-equals"></i>&nbsp;&nbsp;{{ __('see_mode', ['mode' => __('validation.custom.default')]) }}
</a>
@else
<a class="btn btn-danger" href="{{ route('bo.ticket.index', ['or' => 1]) }}">
<i
class="fa-solid fa-triangle-exclamation"></i>&nbsp;&nbsp;{{ __('see_mode', ['mode' => __('validation.custom.priority')]) }}
</a>
@endif
@endif
@if (session('tickets.st') == \App\Enums\Tickets\TicketStatusEnum::archived->value)
<a class="btn btn-success" href="{{ route('bo.ticket.index', ['sts' => -1]) }}">
<i class="fa-solid fa-inbox"></i>
</a>
@else
<a class="btn btn-secondary float-end"
href="{{ route('bo.ticket.index', ['st' => \App\Enums\Tickets\TicketStatusEnum::archived]) }}">
<i class="fa-solid fa-box-archive"></i>
</a>
@endif
<a class="btn btn-dark" href="{{ route('bo.ticket.index', ['rst' => 1]) }}">
<i class="fa-solid fa-eraser"></i>&nbsp;{{ __(' le tri') }}
</a>
</div>
</div>
</div>
@ -187,13 +216,21 @@
$cols = [];
if (session('tickets.or')) {
$cols = array_merge($cols, [
'order' => Str::ucfirst(__('validation.custom.priority'))
'order' => Str::ucfirst(__('validation.custom.priority')),
]);
}
$cols = array_merge($cols, [
'id' => '#',
]);
if (!session()->has('tickets.pr') && !session('tickets.or')) {
$cols = array_merge($cols, [
'site' => Str::ucfirst(__('Website')),
]);
}
$cols = array_merge($cols, [
'id' => Str::ucfirst(__('validation.attributes.id')),
'title' => Str::ucfirst(__('validation.attributes.name')),
'type' => Str::ucfirst(__('validation.custom.type')),
'status' => Str::ucfirst(__('validation.attributes.status')),
'title' => Str::ucfirst(__('validation.attributes.name')),
]);
if (Auth::user()->isAdmin()) {
$cols = array_merge($cols, [
@ -208,13 +245,16 @@
@endphp
@include('bo.modules.table-col-sorter', [
'cols' => $cols,
'ignore' => ['id', 'tickets'],
'ignore' => session('tickets.or')
? array_keys($cols)
: ['id', 'site', 'status', 'tickets'],
])
</thead>
<tbody>
@if (!count($tickets))
<tr>
<td class="text-center" colspan="@if (Auth::user()->isAdmin()) 6 @else 5 @endif">
<td class="text-center"
colspan="@if (Auth::user()->isAdmin()) 9 @else 6 @endif">
<h2>{{ __('Aucun ticket') }}</h2>
</td>
</tr>
@ -227,26 +267,45 @@
'routeName' => 'ticket',
'model' => $ticket,
'models' => $tickets,
'value' => $key + 1,
'value' => ($key + 1) + (($tickets->currentPage() - 1) * $tickets->perPage()),
'noRightsVisible' => false,
])
@endif
{{-- id --}}
<td scope="row">
<div class="d-flex justify-content-between">
<span class="me-1">{{ $ticket->id }}&nbsp;&nbsp;@if ($ticket->is_internal)
<div class="d-flex justify-content-center">
<span>{{ $ticket->id }}&nbsp;&nbsp;
@if ($ticket->is_internal)
<i class="fa-solid fa-lock"></i>
@endif
</span>
<span class="d-flex flex-column text-end">
</div>
</td>
@if (!session()->has('tickets.pr') && !session('tickets.or'))
{{-- site --}}
<td scope="row">
<div class="d-flex justify-content-center">
@if (Auth::user()->isAdmin())
<a href="{{ route('bo.sites.show', $ticket->site) }}"
title="{{ __('Voir le site :sitename', [
'sitename' => $ticket->site->name,
]) }}">{{ $ticket->site->name }}</a>
@else
<span class="text-decoration-underline">{{ $ticket->site->name }}</span>
<span
class="text-decoration-underline">{{ $ticket->site->name }}</span>
@endif
</div>
</td>
@endif
{{-- type --}}
<td class="text-center">
<span
class="badge {{ $ticket->type->class() }}">{{ $ticket->type->label() }}</span>
</td>
{{-- status --}}
<td scope="row">
<div class="d-flex justify-content-between">
<span class="d-flex flex-column">
<span class="{{ $ticket->status->class() }} rounded text-center">
{{ $ticket->status->label() }}
</span>
@ -254,13 +313,9 @@
</div>
</td>
{{-- title --}}
<td class="text-center">
<td>
<span class="me-1">{{ $ticket->title }}</span>
</td>
{{-- type --}}
<td class="text-center">
<span class="badge {{ $ticket->type->class() }}">{{ $ticket->type->label() }}</span>
</td>
{{-- tag --}}
@php
$routeName = request()->route()->getName();
@ -277,10 +332,11 @@
@endcan
{{-- assigned_to / date_mep --}}
@if (Auth::user()->isAdmin())
<td>{{ $ticket->assignedUser ? $ticket->assignedUser->name : __('Personne') }}</td>
<td>{{ $ticket->assignedUser ? $ticket->assignedUser->name : __('Personne') }}
</td>
@endif
<td class="text-center">
{{ is_null($ticket->date_mep) ? Str::ucfirst(__("validation.custom.date_mep_empty")) : $ticket->date_mep->format('d/m/Y') }}
{{ is_null($ticket->date_mep) ? '-' : $ticket->date_mep->format('d/m/Y') }}
</td>
<td>{{ Carbon\Carbon::parse($ticket->created_at)->format('d/m/Y à H:i') }}</td>
<td>
@ -291,88 +347,97 @@
$ticket_files = $ticket->getFiles();
@endphp
@foreach ($ticket_files as $key => $file)
@if ($file !== null && (\App\Lib\Helpers\ToolboxHelper::isImageFile($file) || \App\Lib\Helpers\ToolboxHelper::isPdfFile($file)))
@if (
$file !== null &&
(\App\Lib\Helpers\ToolboxHelper::isImageFile($file) || \App\Lib\Helpers\ToolboxHelper::isPdfFile($file)))
<a class="glightbox btn btn-outline-dark"
data-gallery="gallery{{ $ticket->id }}" href="{{ asset($file) }}"
target="_blank"><i class="fa-solid fa-file-image"></i>
data-gallery="gallery{{ $ticket->id }}"
href="{{ asset($file) }}" target="_blank"><i
class="fa-solid fa-file-image"></i>
</a>
@break
@break
@endif
@endforeach
{{-- Modal du ticket --}}
<!-- Button trigger modal -->
<button class="btn btn-outline-info" data-bs-toggle="modal"
data-bs-target="#ticket{{ $ticket->id }}Modal"
type="button"><i class="fa-solid fa-eye"></i></button>
<a class="btn btn-outline-success"
href="{{ route('bo.ticket.show', $ticket->id) }}"><i
class="fa-solid fa-comment"></i></a>
@if (auth()->user()->isAdmin())
<a class="btn btn-outline-primary"
href="{{ route('bo.ticket.edit', $ticket) }}"><i
class="fa-solid fa-pen"></i></a>
@endif
@endforeach
{{-- Modal du ticket --}}
<!-- Button trigger modal -->
<button class="btn btn-outline-info" data-bs-toggle="modal"
data-bs-target="#ticket{{ $ticket->id }}Modal" type="button"><i
class="fa-solid fa-eye"></i></button>
<a class="btn btn-outline-success"
href="{{ route('bo.ticket.show', $ticket->id) }}"><i
class="fa-solid fa-comment"></i></a>
@if (auth()->user()->isAdmin())
<a class="btn btn-outline-primary"
href="{{ route('bo.ticket.edit', $ticket) }}"><i
class="fa-solid fa-pen"></i></a>
@endif
@can('changeStatus', $ticket)
@if (!$ticket->status->equals(\App\Enums\Tickets\TicketStatusEnum::archived))
<form class="confirmJS" method="POST"
action="{{ route('bo.ticket.archive', $ticket) }}">
@method('PUT')
@csrf
<button class="btn btn-outline-danger rounded-0 rounded-end" type="submit"><i
class="fa-solid fa-box-archive"></i></button>
</form>
@endif
@endcan
@can('changeStatus', $ticket)
@if (!$ticket->status->equals(\App\Enums\Tickets\TicketStatusEnum::archived))
<form class="confirmJS" method="POST"
action="{{ route('bo.ticket.archive', $ticket) }}">
@method('PUT')
@csrf
<button
class="btn btn-outline-danger rounded-0 rounded-end"
type="submit"><i
class="fa-solid fa-box-archive"></i></button>
</form>
@endif
@endcan
</div>
</div>
</div>
<!-- Modal -->
<div class="modal fade" id="ticket{{ $ticket->id }}Modal"
aria-labelledby="ticket{{ $ticket->id }}ModalLabel" aria-hidden="true" tabindex="-1">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="ticket{{ $ticket->id }}ModalLabel">
@can('isAdmin')
<a href="{{ route('bo.sites.show', $ticket->site) }}"
title="{{ __('Voir le site :sitename', [
'sitename' => $ticket->site->name,
]) }}"><b>{{ $ticket->site->name }}</b></a>
@else
<b>{{ $ticket->site->name }}</b>
@endcan -
<u>
{{ __('Ticket n°') }} {{ $ticket->id }}
@if ($ticket->is_internal)
<i class="fa-solid fa-lock"></i>
@endif
</u>&nbsp;-&nbsp;
<span class="badge {{ $ticket->type->class() }}">
{{ $ticket->type->label() }}
</span>
</h5>
<button class="btn btn-sm btn-primary bg-primary" data-bs-dismiss="modal"
type="button" aria-label="Close">
<i class="fa-solid fa-xmark text-white"></i>
</button>
</div>
<div class="modal-body">
@can('assignLabels', App\Models\Ticket::class)
<div class="mb-3 mt-1">
@foreach ($ticket->labels as $label)
<span class="badge label colorize"
data-color="{{ $label->color }}">{{ $label->name }}</span>
@endforeach
</div>
@endcan
<p>{!! clean(nl2br($ticket->text)) !!}</p>
</div>
<div class="modal-footer">
<button class="btn btn-sm btn-primary" data-bs-dismiss="modal"
type="button">{{ __('Fermer') }}</button>
<!-- Modal -->
<div class="modal fade" id="ticket{{ $ticket->id }}Modal"
aria-labelledby="ticket{{ $ticket->id }}ModalLabel"
aria-hidden="true" tabindex="-1">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title"
id="ticket{{ $ticket->id }}ModalLabel">
@can('isAdmin')
<a href="{{ route('bo.sites.show', $ticket->site) }}"
title="{{ __('Voir le site :sitename', [
'sitename' => $ticket->site->name,
]) }}"><b>{{ $ticket->site->name }}</b></a>
@else
<b>{{ $ticket->site->name }}</b>
@endcan -
<u>
{{ __('Ticket n°') }} {{ $ticket->id }}
@if ($ticket->is_internal)
<i class="fa-solid fa-lock"></i>
@endif
</u>&nbsp;-&nbsp;
<span class="badge {{ $ticket->type->class() }}">
{{ $ticket->type->label() }}
</span>
</h5>
<button class="btn btn-sm btn-primary bg-primary"
data-bs-dismiss="modal" type="button"
aria-label="Close">
<i class="fa-solid fa-xmark text-white"></i>
</button>
</div>
<div class="modal-body">
@can('assignLabels', App\Models\Ticket::class)
<div class="mb-3 mt-1">
@foreach ($ticket->labels as $label)
<span class="badge label colorize"
data-color="{{ $label->color }}">{{ $label->name }}</span>
@endforeach
</div>
@endcan
<p>{!! clean(nl2br($ticket->text)) !!}</p>
</div>
<div class="modal-footer">
<button class="btn btn-sm btn-primary"
data-bs-dismiss="modal"
type="button">{{ __('Fermer') }}</button>
</div>
</div>
</div>
</div>
</div>
</td>
</tr>
@endforeach
@ -385,5 +450,5 @@
</div>
</div>
</div>
</div>
</div>
@endsection

View file

@ -12,6 +12,11 @@
{{ $ticket->full_name }}
@if ($ticket->is_internal)<i class="fa-solid fa-lock"></i>@endif
<span class="badge {{ $ticket->type->class() }}">{{ $ticket->type->label() }}</span>
@if (auth()->user()->isAdmin())
<a class="btn btn-primary"
href="{{ route('bo.ticket.edit', $ticket) }}"><i
class="fa-solid fa-pen"></i></a>
@endif
</h2>
<div class="col d-flex flex-row text-end">
@can('suscribeToTicket', $ticket)
@ -99,7 +104,9 @@
@endif
<div>
<h4>
{{ __('Suivi') }}
@if ($ticket->site->projectManager)
{{ __("Chef de projet") }} : {{ $ticket->site->projectManager->name }}
@endif
@can('createMessage', $ticket)
<button class="btn btn-sm btn-primary float-end mx-1" data-bs-toggle="modal" data-bs-target="#messageModal" type="button">
{{ __('Répondre') }}
@ -272,6 +279,10 @@
@endforeach
</div>
@endif
@php
$linkedTickets = $ticket->linkedTickets;
@endphp
@if (!$linkedTickets->isEmpty() or auth()->user()->can('linkTicket', $ticket))
<hr>
<div class="flex-col">
<div>
@ -292,7 +303,7 @@
</div>
@endcan
<div class="row row-cols-auto gap-2">
@foreach ($linkedTicket as $linked)
@foreach ($linkedTickets as $linked)
<div class="col">
@can('linkTicket', $ticket)
<form id="form_unlink_ticket" action="{{ route('bo.ticket.unlink', ['ticket' => $ticket, 'linkedTicket' => $linked]) }}" method="POST">
@ -300,8 +311,8 @@
@method('DELETE')
<div class="input-group mt-2">
@endcan
<a class="btn btn-xl btn-outline-primary" href="{{ route('bo.ticket.show', $linked->id) }}" title="{{ Str::ucfirst(__('crud.other.view_linked_ticket', ['model' => $linked->id])) }}">
TICKET - {{ $linked->id }}
<a class="btn btn-xl btn-outline-primary" target="_blank" href="{{ route('bo.ticket.show', $linked->id) }}" title="{{ Str::ucfirst(__('crud.other.view_linked_ticket', ['model' => $linked->id])) }}">
TICKET - #{{ $linked->id }}
</a>
@can('linkTicket', $ticket)
<button class="btn btn-xl btn-outline-danger" type="submit" title="{{ Str::ucfirst(__('crud.other.unlink_ticket', ['model' => $linked->id])) }}"><i class="fa-solid fa-link-slash"></i></button>
@ -311,6 +322,7 @@
</div>
@endforeach
</div>
@endif
</div>
<hr>
@can('createGitlabIssue', $ticket)

View file

@ -118,6 +118,25 @@
</div>
</fieldset>
</div>
{{-- GITLAB_USER_ID --}}
<div class="col-12 col-md-6 mb-3">
<fieldset class="h-100 border bg-white p-3">
<legend>{{ __("ID de l'utilisateur Gitlab") }}</legend>
<div class="row">
<div class="col-12">
@include('bo.partials.inputs.int-number', [
'id' => 'siteGitlabUserId',
'label' => __("ID de l'utilisateur Gitlab"),
'name' => 'gitlab_id',
'required' => false,
'model' => $userModel ?? null,
'helper' => __("ID de l'utilisateur Gitlab"),
'step' => 1,
])
</div>
</div>
</fieldset>
</div>
</div>
@push('scripts')

View file

@ -10,6 +10,6 @@
</select>
@include('modules.input-error', [
'inputName' => $name,
'helperId' => "{{ $id }}Help",
'helperId' => $id."Help",
'helper' => $helper
])

View file

@ -10,6 +10,6 @@
value="{{ old($name, ((isset($model) and $model->{$name}) ? ($model->{$name}->format('Y-m-d') ?? ($defaultValue ? Carbon\Carbon::today() : '')) : ($defaultValue ? Carbon\Carbon::today() : ''))) }}">
@include('modules.input-error', [
'inputName' => $name,
'helperId' => "{$id}Help",
'helperId' => $id."Help",
'helper' => $helper
])

View file

@ -24,7 +24,7 @@
@endif
@include('modules.input-error', [
'inputName' => $name,
'helperId' => '{{ $id }}Help',
'helperId' => $id."Help",
'helper' => $helper
])

View file

@ -3,9 +3,7 @@
<b>{{ $label }} {{ $required ? '*' : '' }}</b>
</label>
@endif
@if(isset($appendText))
<div class="input-group">
@endif
<input id="{{ $id }}"
name="{{ $name }}"
type="number"
@ -39,6 +37,6 @@
</div>
@include('modules.input-error', [
'inputName' => $name,
'helperId' => '{{ $id }}Help',
'helperId' => $id.'Help',
'helper' => $helper
])

View file

@ -16,6 +16,6 @@ $data = [
<div class="belongs-to-many-dropdown" data-json='@json($data)'></div>
@include('modules.input-error', [
'inputName' => $name,
'helperId' => "{$id}Help",
'helperId' => $id."Help",
'helper' => $helper,
])

View file

@ -11,6 +11,6 @@
value="{{ old($name, ((isset($model) and $model->{$name}) ? $model->{$name}->format('Y-m-d\TH:i') : '')) }}">
@include('modules.input-error', [
'inputName' => $name,
'helperId' => $id . 'Help',
'helperId' => $id."Help",
'helper' => (isset($model) and $model->{$name}) ? __('Leave empty for immediate display of the slider.') : __('Empty for immediate display of the slider.')
])

View file

@ -23,6 +23,6 @@ $data = [
<div class="search-belongs-to-dropdown" data-json='@json($data)'></div>
@include('modules.input-error', [
'inputName' => $name,
'helperId' => "{$id}Help",
'helperId' => $id."Help",
'helper' => $helper,
])

View file

@ -12,7 +12,7 @@ $data = [
<div class="ck-editor" data-json='@json($data)'></div>
@include('modules.input-error', [
'inputName' => $name,
'helperId' => "{$id}Help",
'helperId' => $id."Help",
'helper' => $helper ?? __('crud.minicrud.text_warning', ['number' => 15]) . '. ' . __('validation.min.string', [
'attribute' => $input['label'],
'min' => 15

View file

@ -23,7 +23,7 @@
<div class="list-item" data-json='@json($data)'></div>
@include('modules.input-error', [
'inputName' => $name,
'helperId' => "{$id}Help",
'helperId' => $id."Help",
'helper' => $helper,
])
</div>

View file

@ -10,6 +10,6 @@
value="{{ old($name, ((isset($model) and $model->{$name}) ? ($model->{$name}->format('Y-m-d\TH:i') ?? ($defaultValue ? Carbon\Carbon::today() : '')) : ($defaultValue ? Carbon\Carbon::today() : ''))) }}">
@include('modules.input-error', [
'inputName' => $name,
'helperId' => "{$id}Help",
'helperId' => $id."Help",
'helper' => $helper
])

View file

@ -10,5 +10,5 @@
@if(old($name, (old('_token') ? false : ($model->{$name} ?? false)))) checked @endif>
</div>
@include('modules.input-error', [
'inputName' => $name, 'helperId' => '{{ $id }}Help' , 'helper' => $helper
'inputName' => $name, 'helperId' => $id."Help", 'helper' => $helper
])

View file

@ -10,6 +10,6 @@
</select>
@include('modules.input-error', [
'inputName' => $name,
'helperId' => "{{ $id }}Help",
'helperId' => $id."Help",
'helper' => $helper
])

View file

@ -22,6 +22,6 @@ $data = [
<div class="input-text-auto" data-json='@json($data)'></div>
@include('modules.input-error', [
'inputName' => $name,
'helperId' => "{$id}Help",
'helperId' => $id."Help",
'helper' => $helper
])

View file

@ -21,6 +21,6 @@
@endif>
@include('modules.input-error', [
'inputName' => $name,
'helperId' => $id.'Help',
'helperId' => $id."Help",
'helper' => $helper
])

View file

@ -1,58 +0,0 @@
@extends('layout.app')
@section('title', __('Accueil'))
@section('description', __('Page d\'accueil du site :site', ['site' => config('app.name')]))
@section('content')
<div class="container">
<div class="row mt-4">
<div class="col mb-5">
<a href="{{ route('bo.ticket.create') }}" class="btn btn-primary">
{{ __('Créer un ticket') }}
</a>
<a href="{{ route('bo.sites.index') }}" class="btn btn-primary ms-3">
{{ __('Voir mes sites') }}
</a>
</div>
</div>
<div class="row">
<div class="col">
<h2 class="col h2 mb-3">
<span class="fw-bold">{{ __('models.classes.dutyhours') . __(' à venir') }}</span>
</h2>
</div>
</div>
<div class="row">
<div class="col">
<div class="table-responsive">
<table class="table fix-action m-0">
<thead>
<tr>
<th>{{ __('Date') }}</th>
<th>{{ __('Personne présente') }}</th>
<th>{{ __('Lieu de la permanence') }}</th>
</tr>
</thead>
<tbody>
@if($dutyhourModels->count())
@foreach ($dutyhourModels as $dutyhourModel)
<tr>
<td class="align-middle">{{ $dutyhourModel->date->formatLocalized('%d/%m/%Y') }}</td>
<td class="align-middle">{{ $dutyhourModel->person }}</td>
<td class="align-middle">{{ $dutyhourModel->place }}</td>
</tr>
@endforeach
@else
<tr>
<td colspan="5" class="text-center">
<span class="h3">{{ __('Aucune :model prévue prochainement', ['model' => Str::singular(__('models.classes.dutyhours')) ])}}</span>
</td>
</tr>
@endif
</tbody>
</table>
</div>
</div>
</div>
</div>
@endsection

View file

@ -40,14 +40,14 @@
<a class="dropdown-item @if(Route::is('bo.packages.*'))active @endif" href="{{ route('bo.packages.index') }}">{{ __('models.classes.packages') }}</a>
@endcan
@can('isAdmin')
<a class="dropdown-item @if(Route::is('bo.dutyhours.*'))active @endif" href="{{ route('bo.dutyhours.index') }}">{{ __('models.classes.dutyhours') }}</a>
@endcan
@can('isAdmin')
<a class="dropdown-item @if(Route::is('bo.informations.*'))active @endif" href="{{ route('bo.informations.index') }}">{{ __('models.classes.informations') }}</a>
@endcan
@can('isAdmin')
<a class="dropdown-item @if(Route::is('bo.ticket_types.*'))active @endif" href="{{ route('bo.ticket_types.index') }}">{{ trans_choice('models.classes.ticket_types', 2) }}</a>
@endcan
@can('isAdmin')
<a class="dropdown-item @if(Route::is('bo.labels.*'))active @endif" href="{{ route('bo.labels.index') }}">{{ __('models.classes.labels') }}</a>
@endcan
</div>
</li>
@endcan
@ -108,7 +108,7 @@
{{ __('Identifiants') }}
</a>
<form id="logout-form" class="dropdown-item" action="{{route('logout')}}" method="POST" class="d-none">
<form id="logout-form" class="dropdown-item" action="{{route('logout')}}" method="POST">
@csrf
<button class="btn btn-link p-0 text-decoration-none text-body-secondary text-capitalize" type="submit">{{ __('Déconnexion') }}</button>
</form>

View file

@ -3,7 +3,6 @@
use App\Enums\Invoices\InvoiceStatusEnum;
use App\Models\Brand;
use App\Models\Company;
use App\Models\Dutyhour;
use App\Models\Information;
use App\Models\Invoice;
use App\Models\Label;
@ -28,19 +27,6 @@ Breadcrumbs::for('bo.packages.edit', function (Generator $trail, Package $packag
$trail->push(__('crud.actions.edit'), route('bo.packages.edit', $package->id));
});
// * DUTYHOURS
Breadcrumbs::for('bo.dutyhours.index', function (Generator $trail) {
$trail->push(__('models.classes.dutyhours'), route('bo.dutyhours.index'));
});
Breadcrumbs::for('bo.dutyhours.create', function (Generator $trail) {
$trail->parent('bo.dutyhours.index');
$trail->push(__('crud.actions.create'), route('bo.dutyhours.create'));
});
Breadcrumbs::for('bo.dutyhours.edit', function (Generator $trail, Dutyhour $dutyhour) {
$trail->parent('bo.dutyhours.index');
$trail->push(__('crud.actions.edit'), route('bo.dutyhours.edit', $dutyhour->id));
});
// * INFORMATIONS
Breadcrumbs::for('bo.informations.index', function (Generator $trail) {
$trail->push(__('models.classes.informations'), route('bo.informations.index'));

View file

@ -5,8 +5,6 @@ use App\Http\Controllers\Bo\CompanyController;
use App\Http\Controllers\Bo\Credit\AccountController;
use App\Http\Controllers\Bo\Credit\CreditLogController;
use App\Http\Controllers\Bo\Credit\EstimationController;
use App\Http\Controllers\Bo\DashboardController;
use App\Http\Controllers\Bo\DutyhourController;
use App\Http\Controllers\Bo\InformationController;
use App\Http\Controllers\Bo\InvoiceController;
use App\Http\Controllers\Bo\LabelController;
@ -43,7 +41,9 @@ Route::middleware('admin-secure')
Route::middleware('auth:backend')
->group(function () {
// * HOME
Route::get('/', [DashboardController::class, 'index'])->name('dashboard');
Route::get('/', function(){
return redirect()->route('bo.ticket.index');
})->name('dashboard');
Route::middleware(['can:isAdmin'])
->group(function () {
@ -56,7 +56,6 @@ Route::middleware('admin-secure')
->middleware('htmlsanitize:template')
->parameters(['ticket_types' => 'ticket_type']);
Route::resource('packages', PackageController::class)->except('show');
Route::resource('dutyhours', DutyhourController::class)->except('show');
Route::resource('invoices', InvoiceController::class)
->withoutMiddleware('htmlsanitize')
->middleware(['htmlsanitize:comment']);