- Itération Sites + Projets + Fichier + Journaux

- bump crud-policies to 0.1.9
This commit is contained in:
Jérémy Munsch 2021-07-25 19:11:33 +02:00 • committed by Jérémy Munsch
parent 3b242a63f5
commit 418a9c2e67
68 changed files with 1428 additions and 1104 deletions

View file

@ -0,0 +1,41 @@
<?php
namespace App\Enums;
use Kwaadpepper\Enum\BaseEnum;
/**
* @method static self collectionNeeds()
* @method static self specifications()
* @method static self quotation()
* @method static self tests()
* @method static self informations()
* @method static self feedback()
*/
class FileCategory extends BaseEnum
{
protected static function values(): array
{
return [
'collectionNeeds' => 0,
'specifications' => 1,
'quotation' => 2,
'tests' => 3,
'informations' => 4,
'feedback' => 5
];
}
protected static function labels(): array
{
return [
'collectionNeeds' => trans('Recueil des besoins'),
'specifications' => trans('Cahier des charges'),
'quotation' => trans('Devis'),
'tests' => trans('Recettage'),
'informations' => trans('Informations'),
'feedback' => trans('Retours client'),
];
}
}

29
app/Enums/FileType.php Normal file
View file

@ -0,0 +1,29 @@
<?php
namespace App\Enums;
use Kwaadpepper\Enum\BaseEnum;
/**
* @method static self stringlink()
* @method static self binfile()
*/
class FileType extends BaseEnum
{
protected static function values(): array
{
return [
'stringlink' => 0,
'binfile' => 1
];
}
protected static function labels(): array
{
return [
'stringlink' => trans('Lien uri'),
'binfile' => trans('Fichier hebergé')
];
}
}

View file

@ -0,0 +1,28 @@
<?php
namespace App\Events;
use App\Models\File;
use App\Models\User;
class FileCreated extends Loggable
{
/** @var File */
public $file;
/**
* Create a new event instance.
*
* @return void
*/
public function __construct(File $file, User $user)
{
parent::__construct($user);
$this->file = $file;
$this->message = trans(':username à crée le fichier :filename', [
'username' => $user->name,
'filename' => $file->name
]);
}
}

31
app/Events/Loggable.php Normal file
View file

@ -0,0 +1,31 @@
<?php
namespace App\Events;
use App\Models\User;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
abstract class Loggable
{
use Dispatchable;
use SerializesModels;
/** @var User */
public $user;
public $message = '';
/**
* Create a new event instance.
*
* @return void
*/
public function __construct(User $user)
{
$this->user = $user;
$this->message = trans(':username did someting', [
'username' => $user->name
]);
}
}

View file

@ -0,0 +1,28 @@
<?php
namespace App\Events;
use App\Models\Project;
use App\Models\User;
class ProjectUpdated extends Loggable
{
/** @var Project */
public $project;
/**
* Create a new event instance.
*
* @return void
*/
public function __construct(Project $project, User $user)
{
parent::__construct($user);
$this->project = $project;
$this->message = trans(':username à mis à jour projet :projectname', [
'username' => $user->name,
'projectname' => $project->name
]);
}
}

View file

@ -0,0 +1,28 @@
<?php
namespace App\Events;
use App\Models\Site;
use App\Models\User;
class SiteUpdated extends Loggable
{
/** @var Site */
public $site;
/**
* Create a new event instance.
*
* @return void
*/
public function __construct(Site $site, User $user)
{
parent::__construct($user);
$this->site = $site;
$this->message = trans(':username à mis à jour site :sitename', [
'username' => $user->name,
'sitename' => $site->name
]);
}
}

View file

@ -2,9 +2,53 @@
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\File;
use Illuminate\Database\Eloquent\Builder;
use Kwaadpepper\CrudPolicies\Http\Requests\CrudIndexRequest;
use Kwaadpepper\CrudPolicies\Traits\CrudController;
class FileController extends Controller
{
//
use CrudController {
index as crudIndex;
create as crudCreate;
}
/** @var File */
public static $modelClass = File::class;
public static $layout = 'layout.app';
public function indexQuery(Builder $query): Builder
{
$parent = request()->site ?? request()->project;
if ($parent) {
$query->whereHasMorph('parent', [get_class($parent)], function ($q) use ($parent) {
return $q->whereId($parent->id);
});
}
return $query;
}
public function index(CrudIndexRequest $request)
{
/** @var \Illuminate\View\View */
$view = $this->crudIndex($request);
if ($request->ajax()) {
return $view;
}
return view('files.index', $view->getData());
}
public function create(CrudIndexRequest $request)
{
/** @var \Illuminate\View\View */
$view = $this->crudCreate($request);
return view('files.create', $view->getData());
}
public function storeModel(File &$file)
{
$file->parent()->associate(request()->site ?? request()->project);
}
}

View file

@ -3,6 +3,7 @@
namespace App\Http\Controllers;
use App\Models\Log;
use Illuminate\Database\Eloquent\Builder;
use Kwaadpepper\CrudPolicies\Http\Requests\CrudIndexRequest;
use Kwaadpepper\CrudPolicies\Traits\CrudController;
@ -17,15 +18,37 @@ class LogController extends Controller
public static $layout = 'layout.app';
public function indexQuery(Builder $query): Builder
{
$parent = request()->site ?? request()->project;
if ($parent) {
$query->whereHasMorph('parent', [get_class($parent)], function ($q) use ($parent) {
return $q->whereId($parent->id);
});
}
return $query;
}
public function index(CrudIndexRequest $request)
{
// Autosort
if (!$request->sort_col and !$request->sort_way) {
$request->merge([
'sort_col' => 'created_at',
'sort_way' => 'desc',
]);
}
/** @var \Illuminate\View\View */
$view = $this->crudIndex($request);
if ($request->ajax()) {
return $view;
}
return view('logs.index', $view->getData());
}
public function storeModel(Log &$log)
{
$log->parent()->associate(request()->site);
$log->parent()->associate(request()->site ?? request()->project);
}
}

View file

@ -3,14 +3,27 @@
namespace App\Http\Controllers;
use App\Models\Project;
use Kwaadpepper\CrudPolicies\Http\Requests\CrudIndexRequest;
use Kwaadpepper\CrudPolicies\Traits\CrudController;
class ProjectController extends Controller
{
use CrudController;
use CrudController {
index as crudIndex;
}
/** @var Project */
public static $modelClass = Project::class;
public static $layout = 'layout.app';
public function index(CrudIndexRequest $request)
{
/** @var \Illuminate\View\View */
$view = $this->crudIndex($request);
if ($request->ajax()) {
return $view;
}
return view('projects.index', $view->getData());
}
}

View file

@ -21,6 +21,9 @@ class SiteController extends Controller
{
/** @var \Illuminate\View\View */
$view = $this->crudIndex($request);
if ($request->ajax()) {
return $view;
}
return view('sites.index', $view->getData());
}
}

View file

@ -2,7 +2,6 @@
namespace App\Http\Controllers;
use App\Enums\Role;
use App\Enums\TicketStatus;
use App\Enums\TicketType;
use App\Http\Requests\ChangeTicketStatus;
@ -137,16 +136,17 @@ class TicketController extends Controller
public function create()
{
$user = Auth::user();
if ($user->role->value === 1) {
/** @var \App\Models\User */
$user = auth()->user();
if ($user->isAdmin()) {
$sites = Site::orderBy('name')->get();
} else {
$sites = $user->sites;
}
if (!count($sites)) {
return redirect()->route('site.create')
->with('warning', 'Vous devez tout d\'abord créer un projet pour y ajouter un ticket');
return redirect()->route('sites.create')
->with('warning', 'Vous devez tout d\'abord créer un site pour y ajouter un ticket');
}
return view('ticket.create', compact('sites'));
}

View file

@ -0,0 +1,28 @@
<?php
namespace App\Listeners;
use App\Events\Loggable;
use App\Models\Log;
class HandleLoggable
{
/**
* Handle the event.
*
* @param Loggable $loggable
* @return void
*/
public function handle(Loggable $loggable)
{
$log = new Log([
'entry' => trans(':username à crée le fichier :filename', [
'username' => $loggable->user->name,
'filename' => $loggable->file->name
])
]);
$log->user()->associate($loggable->user);
$log->parent()->associate($loggable->file->parent);
$log->saveOrFail();
}
}

View file

@ -2,10 +2,134 @@
namespace App\Models;
use App\Enums\FileCategory;
use App\Enums\FileType;
use App\Events\FileCreated;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Kwaadpepper\CrudPolicies\Enums\CrudAction;
use Kwaadpepper\CrudPolicies\Enums\CrudType;
use Kwaadpepper\CrudPolicies\Traits\IsCrudModel;
use Kwaadpepper\Enum\Traits\CastsEnums;
class File extends Model
{
use CastsEnums;
use HasFactory;
use IsCrudModel;
protected $enumCasts = [
'category' => FileCategory::class,
'type' => FileType::class
];
protected $crudLabelColumn = 'name';
protected $crudValueColumn = 'id';
protected $fillable = ['type', 'uri', 'file', 'name', 'category'];
public function __construct($attributes = [])
{
self::$editableProperties = [
'name' => [
'label' => trans('Nom'),
'type' => CrudType::string(),
'nullable' => false,
'actions' => [
CrudAction::viewAny(),
CrudAction::view(),
CrudAction::update(),
CrudAction::create()
]
],
'type' => [
'label' => trans('Type'),
'type' => CrudType::enum(),
'enum' => FileType::class,
'required' => true,
'nullable' => false,
'actions' => [
CrudAction::viewAny(),
CrudAction::view(),
CrudAction::create()
]
],
'category' => [
'label' => trans('Categorie'),
'type' => CrudType::enum(),
'enum' => FileCategory::class,
'required' => true,
'nullable' => false,
'actions' => [
CrudAction::viewAny(),
CrudAction::view(),
CrudAction::update(),
CrudAction::create()
]
],
'uri' => [
'label' => trans('Lien uri'),
'type' => CrudType::uri(),
'required' => false,
'nullable' => true,
'validate' => [
'required_without:file',
'nullable'
],
'actions' => [
CrudAction::view(),
CrudAction::create()
]
],
'file' => [
'label' => trans('Fichier'),
'type' => CrudType::file(),
'required' => false,
'nullable' => true,
'validate' => [
'required_without:uri',
'nullable',
'mimes:pdf',
'max:5120'
],
'accept' => 'application/pdf',
'actions' => [
CrudAction::view(),
CrudAction::create()
]
],
'created_at' => [
'label' => trans('Créé le'),
'type' => CrudType::string(),
'actions' => [
CrudAction::viewAny(),
CrudAction::view()
]
]
];
parent::__construct($attributes);
}
protected static function booted()
{
static::created(function (File $file) {
event(new FileCreated($file, \auth()->user()));
});
}
public function parent()
{
return $this->morphTo();
}
public function parentSite()
{
return $this->morphTo('parent', 'site');
}
public function parentProject()
{
return $this->morphTo('parent', 'project');
}
}

View file

@ -41,11 +41,31 @@ class Log extends Model
CrudAction::create(),
CrudAction::update(),
]
],
'created_at' => [
'label' => trans('Créé le'),
'type' => CrudType::string(),
'actions' => [
CrudAction::viewAny(),
CrudAction::view()
]
]
];
parent::__construct($attributes);
}
protected static function booted()
{
static::creating(function (Log $log) {
$log->user()->associate(auth()->user());
});
}
public function user()
{
return $this->belongsTo(User::class);
}
public function parent()
{
return $this->morphTo();

View file

@ -2,6 +2,7 @@
namespace App\Models;
use App\Events\ProjectUpdated;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Kwaadpepper\CrudPolicies\Enums\CrudAction;
@ -17,7 +18,10 @@ class Project extends Model
protected $crudValueColumn = 'id';
protected $fillable = ['name'];
protected $fillable = [
'name', 'status',
'description', 'todo', 'sites'
];
public function __construct($attributes = [])
{
@ -97,31 +101,24 @@ class Project extends Model
CrudAction::viewAny(),
CrudAction::view(),
CrudAction::create(),
CrudAction::update(),
]
],
'logs' => [
'label' => trans('Journaux'),
'type' => CrudType::belongsToMany(),
'belongsToMany' => Log::class,
'belongsToManyLabel' => 'id',
'nullable' => true,
'readonly' => function () {
/** @var \App\Models\User */
$user = auth()->user();
return !$user->isAdmin();
},
'actions' => [
CrudAction::viewAny(),
CrudAction::view(),
CrudAction::create(),
CrudAction::update(),
]
]
];
parent::__construct($attributes);
}
protected static function booted()
{
static::updated(function (Project $project) {
event(new ProjectUpdated($project, \auth()->user()));
});
}
public function sites()
{
return $this->belongsToMany(Site::class, 'project_site');
}
public function logs()
{
return $this->morphMany(Log::class, 'parent');

View file

@ -2,6 +2,7 @@
namespace App\Models;
use App\Events\SiteUpdated;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
@ -60,10 +61,10 @@ class Site extends Model
CrudAction::update(),
]
],
'logs' => [
'label' => trans('Journaux'),
'projects' => [
'label' => trans('Projets'),
'type' => CrudType::belongsToMany(),
'belongsToMany' => Log::class,
'belongsToMany' => Project::class,
'belongsToManyLabel' => 'name',
'nullable' => true,
'readonly' => function () {
@ -72,9 +73,10 @@ class Site extends Model
return !$user->isAdmin();
},
'actions' => [
CrudAction::viewAny(),
CrudAction::view(),
CrudAction::create(),
CrudAction::update(),
CrudAction::update()
]
]
];
@ -99,6 +101,9 @@ class Site extends Model
File::makeDirectory($newPath, 0755, true);
}
});
static::updated(function (Site $site) {
event(new SiteUpdated($site, \auth()->user()));
});
static::deleted(function (Site $site) {
$path = Site::ticketAssetsFullPath($site->slug_name);
if (File::exists($path)) {
@ -117,6 +122,11 @@ class Site extends Model
return $this->hasMany(Ticket::class, 'site_id');
}
public function projects()
{
return $this->belongsToMany(Project::class);
}
public function logs()
{
return $this->morphMany(Log::class, 'parent');

View file

@ -17,10 +17,10 @@ use Kwaadpepper\Enum\Traits\CastsEnums;
class User extends Authenticatable
{
use HasFactory;
use Notifiable;
use CastsEnums;
use HasFactory;
use IsCrudModel;
use Notifiable;
use SoftDeletes;
protected $enumCasts = [

View file

@ -29,9 +29,9 @@ class FilePolicy extends RootPolicy
'file' => [
'viewAny' => URR::make('userIsAdmin', $user),
'view' => URR::make('userIsAdmin', $user),
'update' => URR::make('userIsAdmin', $user),
'update' => URR::make('denyEveryOne'),
'create' => URR::make('userIsAdmin', $user),
'delete' => URR::make('userIsAdmin', $user)
'delete' => URR::make('userIsDev', $user)
]
];
}

View file

@ -3,10 +3,12 @@
namespace App\Policies;
use App\Models\User;
use App\Policies\Rules\LogStaticRules;
use App\Policies\Rules\UserRoleRules as URR;
use Illuminate\Auth\Access\HandlesAuthorization;
use Illuminate\Database\Eloquent\Model;
use Kwaadpepper\CrudPolicies\Policies\RootPolicy;
use Kwaadpepper\CrudPolicies\Policies\Rules\StaticRules;
class LogPolicy extends RootPolicy
{
@ -28,10 +30,13 @@ class LogPolicy extends RootPolicy
$this->policies = [
'log' => [
'viewAny' => URR::make('userIsAdmin', $user),
'view' => URR::make('userIsAdmin', $user),
'update' => URR::make('userIsAdmin', $user),
'view' => URR::make('denyEveryOne'),
'update' => StaticRules::or([
URR::make('userIsDev', $user),
LogStaticRules::make('logIsOwnedByUser', $user, $model)
]),
'create' => URR::make('userIsAdmin', $user),
'delete' => URR::make('userIsAdmin', $user)
'delete' => URR::make('denyEveryOne')
]
];
}

View file

@ -0,0 +1,20 @@
<?php
namespace App\Policies\Rules;
use App\Models\Log;
use App\Models\User;
use Kwaadpepper\CrudPolicies\Policies\Rules\StaticRules;
/**
* Userlevel Policiy Static Rules
*! Rules has to return boolean value
*/
abstract class LogStaticRules extends StaticRules
{
protected static function logIsOwnedByUser(User $user, Log $log)
{
return $log->user->id === $user->id;
}
}

View file

@ -2,6 +2,7 @@
namespace App\Policies\Rules;
use App\Enums\Role;
use App\Models\User;
use Kwaadpepper\CrudPolicies\Policies\Rules\StaticRules;
@ -17,6 +18,11 @@ abstract class UserRoleRules extends StaticRules
return $user->isAdmin();
}
protected static function userIsDev(User $user)
{
return $user->role->equals(Role::developper());
}
protected static function allowEveryOne()
{
return true;

View file

@ -2,10 +2,14 @@
namespace App\Providers;
use App\Events\FileCreated;
use App\Events\NotifySubscriptions;
use App\Events\NotifyTicketCreator;
use App\Events\ProjectUpdated;
use App\Events\SiteUpdated;
use App\Events\TicketStatusChanged;
use App\Listeners\AddStatusMessages;
use App\Listeners\HandleLoggable;
use App\Listeners\SendNotificationMail;
use App\Listeners\SendNotificationMailToTicketCreator;
use App\Listeners\SendSubscriptionsNotificationsMail;
@ -22,18 +26,13 @@ class EventServiceProvider extends ServiceProvider
* @var array
*/
protected $listen = [
Registered::class => [
SendEmailVerificationNotification::class,
],
TicketStatusChanged::class => [
AddStatusMessages::class
],
NotifySubscriptions::class => [
SendSubscriptionsNotificationsMail::class
],
NotifyTicketCreator::class => [
SendNotificationMailToTicketCreator::class
],
Registered::class => [SendEmailVerificationNotification::class],
TicketStatusChanged::class => [AddStatusMessages::class],
NotifySubscriptions::class => [SendSubscriptionsNotificationsMail::class],
NotifyTicketCreator::class => [SendNotificationMailToTicketCreator::class],
FileCreated::class => [HandleLoggable::class],
ProjectUpdated::class => [HandleLoggable::class],
SiteUpdated::class => [HandleLoggable::class]
];
/**

View file

@ -4,6 +4,7 @@ namespace App\Providers;
use App\Models\File;
use App\Models\Log;
use App\Models\Project;
use App\Models\Site;
use App\Models\Ticket;
use App\Models\User;
@ -47,6 +48,7 @@ class RouteServiceProvider extends ServiceProvider
Route::model('log', Log::class);
Route::model('user', User::class);
Route::model('site', Site::class);
Route::model('project', Project::class);
Route::bind('ticket', function ($value) {
return Ticket::where('id', $value)->has('site')->firstOrFail();
});

View file

@ -13,7 +13,7 @@
"fideloper/proxy": "^4.4",
"fruitcake/laravel-cors": "^2.0",
"guzzlehttp/guzzle": "^7.0.1",
"kwaadpepper/crud-policies": "^0.1.6",
"kwaadpepper/crud-policies": "^0.1.9",
"kwaadpepper/enum": "^0.1.4",
"laravel/framework": "^8.12",
"laravel/tinker": "^2.5",

14
composer.lock generated
View file

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "423d32ed253f88ee52f916f755af96d8",
"content-hash": "5a8f79c46916ad9100d6accc3cdefacf",
"packages": [
{
"name": "asm89/stack-cors",
@ -1399,16 +1399,16 @@
},
{
"name": "kwaadpepper/crud-policies",
"version": "0.1.6",
"version": "0.1.9",
"source": {
"type": "git",
"url": "https://github.com/Kwaadpepper/crud-policies.git",
"reference": "ab9b92e71f3529a767562f1d13046bbf1308a9a4"
"reference": "cb0c3848fe252a4211891f907df387f746bd9750"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Kwaadpepper/crud-policies/zipball/ab9b92e71f3529a767562f1d13046bbf1308a9a4",
"reference": "ab9b92e71f3529a767562f1d13046bbf1308a9a4",
"url": "https://api.github.com/repos/Kwaadpepper/crud-policies/zipball/cb0c3848fe252a4211891f907df387f746bd9750",
"reference": "cb0c3848fe252a4211891f907df387f746bd9750",
"shasum": ""
},
"require": {
@ -1456,9 +1456,9 @@
],
"support": {
"issues": "https://github.com/Kwaadpepper/crud-policies/issues",
"source": "https://github.com/Kwaadpepper/crud-policies/tree/0.1.6"
"source": "https://github.com/Kwaadpepper/crud-policies/tree/0.1.9"
},
"time": "2021-07-22T09:25:02+00:00"
"time": "2021-07-27T08:58:38+00:00"
},
{
"name": "kwaadpepper/enum",

View file

@ -232,6 +232,7 @@ return [
'CrudAction' => App\Enums\CrudAction::class,
'CrudType' => App\Enums\CrudType::class,
'Role' => App\Enums\Role::class,
'FileType' => App\Enums\FileType::class,
],
];

View file

@ -4,7 +4,7 @@ use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateProjetSiteTable extends Migration
class CreateProjectSiteTable extends Migration
{
/**
* Run the migrations.
@ -13,7 +13,7 @@ class CreateProjetSiteTable extends Migration
*/
public function up()
{
Schema::create('projet_site', function (Blueprint $table) {
Schema::create('project_site', function (Blueprint $table) {
$table->foreignId('project_id')->constrained('projects')->cascadeOnDelete();
$table->foreignId('site_id')->constrained('sites');
$table->unique(['project_id', 'site_id']);
@ -27,6 +27,6 @@ class CreateProjetSiteTable extends Migration
*/
public function down()
{
Schema::dropIfExists('projet_site');
Schema::dropIfExists('project_site');
}
}

View file

@ -16,6 +16,7 @@ class CreateLogsTable extends Migration
Schema::create('logs', function (Blueprint $table) {
$table->id();
$table->text('entry');
$table->foreignId('user_id')->constrained('users');
$table->morphs('parent'); // can be Site or Projet
$table->timestamps();
});

View file

@ -16,7 +16,8 @@ class CreateFilesTable extends Migration
Schema::create('files', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('path');
$table->string('uri', 2000)->nullable(); // max uri length is 2k
$table->string('file')->nullable();
$table->smallInteger('type');
$table->smallInteger('category');
$table->morphs('parent'); // can be Site or Projet

27
public/css/app.css vendored
View file

@ -1,4 +1,27 @@
@import url(https://fonts.googleapis.com/css?family=Nunito);
a.col_sort :active,a.col_sort :hover,a.col_sort:link,a.col_sort :visited{text-decoration:none}.container-xxl{max-width:1340px!important}.alert-success .text-muted{color:#166218!important}.alert-primary .text-muted,.alert-primary .text-primary{color:#0b475e!important}.alert-secondary .text-muted{color:#bdbdbd!important}.alert-danger .text-muted{color:#cf0b00!important}
a.col_sort:link, a.col_sort :visited, a.col_sort :hover, a.col_sort :active {
text-decoration: none;
}
/*# sourceMappingURL=app.css.map*/
.container-xxl {
max-width: 1340px !important;
}
.alert-success .text-muted {
color: #166218 !important;
}
.alert-primary .text-muted {
color: #0b475e !important;
}
.alert-primary .text-primary {
color: #0b475e !important;
}
.alert-secondary .text-muted {
color: #bdbdbd !important;
}
.alert-danger .text-muted {
color: #cf0b00 !important;
}

535
public/js/app.js vendored

File diff suppressed because one or more lines are too long

View file

@ -8,14 +8,11 @@
<div class="card">
@include('crud-policies::crud.modules.flashMessage')
<div class="card-header">
@can('viewAny', $modelClass)
<a href="{{ CrudController::getRoutePrefixed("$modelTable.index") }}">{{ transFb(sprintf('models.classes.%s', strtolower(Str::plural(class_basename($modelClass)))), Str::plural(class_basename($modelClass))) }}</a>&nbsp;-&nbsp;{{ __('crud-policies::crud.create') }}
@else
{{ Str::plural(class_basename($modelClass)) }}&nbsp;-&nbsp;{{ __('crud-policies::crud.create') }}
@endcan
@include('crud-policies::crud.modules.breadcrumb', ['action' => CrudAction::create()])
@include('crud-policies::crud.modules.actionbar.bar', ['action' => CrudAction::create()])
</div>
<div class="card-body">
<form action="{{ CrudController::getRoutePrefixed("$modelTable.store") }}" method="POST" @if($hasImage) enctype="multipart/form-data" @endif>
<form action="{{ CrudController::getRoutePrefixed("$modelTable.store") }}" method="POST" @if($hasFile) enctype="multipart/form-data" @endif>
@csrf
<table class="table table-sm table-bordered border-primary align-middle table-striped text-center">
<thead class="thead-dark">
@ -46,3 +43,35 @@
</div>
@include('crud-policies::crud.modules.scriptConstants')
@endsection
@push('scripts')
<script>
$(document).ready(() => {
let changeFields = () => {
let $iUri = $('#uri');
let $iFile = $('#file');
let $iUriLine = $iUri.closest('tr');
let $iFileLine = $iFile.closest('tr');
let val = $('#type').val();
console.log(val)
if(val == 0) {
$iUri.prop('required', true);
$iUri.prop('disabled', false);
$iUriLine.removeClass('d-none');
$iFile.prop('required', false);
$iFile.prop('disabled', true);
$iFileLine.addClass('d-none');
} else {
$iUri.prop('required', false);
$iUri.prop('disabled', true);
$iUriLine.addClass('d-none');
$iFile.prop('required', true);
$iFile.prop('disabled', false);
$iFileLine.removeClass('d-none');
}
};
changeFields();
$('#type').change(changeFields);
});
</script>
@endpush

View file

@ -8,10 +8,8 @@
<div class="card">
@include('crud-policies::crud.modules.flashMessage')
<div class="card-header">
<a href="{{ CrudController::getRoutePrefixed("$modelTable.index") }}">{{ transFb(sprintf('models.classes.%s', strtolower(Str::plural(class_basename($modelClass)))), Str::plural(class_basename($modelClass))) }}</a>&nbsp;-&nbsp;{{ __('crud-policies::crud.viewAny') }}
@can('create', $modelClass)
<a href="{{ CrudController::getRoutePrefixed("$modelTable.create") }}" class="btn btn-primary float-end">{{ __('crud-policies::crud.create') }}</a>
@endcan
@include('crud-policies::crud.modules.breadcrumb', ['action' => CrudAction::viewAny()])
@include('crud-policies::crud.modules.actionbar.bar', ['action' => CrudAction::viewAny()])
</div>
<div class="card-body">
<div class="row justify-content-center">
@ -72,6 +70,14 @@
@endif
@endforeach
<td>
@if($model->type->equals(FileType::stringlink()))
<a href="{{ $model->uri }}" target="_blank">{{ pathinfo($model->uri, PATHINFO_BASENAME) }}</a>
@else
<a href="{{ sprintf('/storage/%s', $model->file) }}" target="_blank">{{ pathinfo($model->file, PATHINFO_BASENAME) }}</a>
@endif
</td>
{{-- MODEL ACTIONS --}}
<td>
<div class="btn-group" role="group" aria-label="{{ Str::plural(__('crud-policies::crud.action')) }}">

View file

@ -7,84 +7,83 @@
{{ config('app.name', 'Laravel') }}
@endif
</a>
@auth
<div class="collapse navbar-collapse" id="navbarSupportedContent">
@if (Auth::user()->isAdmin())
<ul class="navbar-nav me-auto">
<li class="nav-item">
<a class="nav-link @if(strpos(request()->route()->getName(), 'ticket') === 0)active @endif" href="{{ route('ticket.index') }}">Tickets</a>
</li>
<li class="nav-item">
<a class="nav-link @if(strpos(request()->route()->getName(), 'sites') === 0)active @endif" href="{{ route('sites.index') }}">Sites</a>
</li>
<li class="nav-item">
<a class="nav-link @if(strpos(request()->route()->getName(), 'projects') === 0)active @endif" href="{{ route('projects.index') }}">Projets</a>
</li>
<li class="nav-item">
<a class="nav-link @if(strpos(request()->route()->getName(), 'users') === 0)active @endif" href="{{ route('users.index') }}">Utilisateurs</a>
</li>
</ul>
@endif
<ul class="navbar-nav me-auto">
<li class="nav-item">
<span class="nav-link text-primary font-weight-bold">{{ __('Tickets') }}</span>
</li>
<li class="nav-item">
<span class="nav-link text-dark">{{ __('Nouveau') }}&nbsp;:&nbsp;<span class="text-info">{{ $ticketsNew }}</span></span>
</li>
<li class="nav-item">
<span class="nav-link text-dark">{{ __('En cours') }}&nbsp;:&nbsp;<span class="text-info">{{ $ticketsInProgress }}</span></span>
</li>
<li class="nav-item">
{{-- Mouhahahaha --}}
<span class="nav-link text-dark">{{ __('Charge') }}&nbsp;:&nbsp;<span class="text-danger">{{ __('Elevée') }}</span></span>
{{-- <span class="nav-link text-dark">Charge&nbsp;:&nbsp;<span class="text-info">Stable</span></span> --}}
</li>
</ul>
</div>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
@if (Auth::user()->isAdmin())
<ul class="navbar-nav me-auto">
<li class="nav-item">
<a class="nav-link @if(strpos(request()->route()->getName(), 'ticket') === 0)active @endif" href="{{ route('ticket.index') }}">Tickets</a>
</li>
<li class="nav-item">
<a class="nav-link @if(strpos(request()->route()->getName(), 'sites') === 0)active @endif" href="{{ route('sites.index') }}">Sites</a>
</li>
<li class="nav-item">
<a class="nav-link @if(strpos(request()->route()->getName(), 'projects') === 0)active @endif" href="{{ route('projects.index') }}">Projets</a>
</li>
<li class="nav-item">
<a class="nav-link @if(strpos(request()->route()->getName(), 'users') === 0)active @endif" href="{{ route('users.index') }}">Utilisateurs</a>
</li>
</ul>
@endif
<ul class="navbar-nav me-auto">
<li class="nav-item">
<span class="nav-link text-primary font-weight-bold">{{ __('Tickets') }}</span>
</li>
<li class="nav-item">
<span class="nav-link text-dark">{{ __('Nouveau') }}&nbsp;:&nbsp;<span class="text-info">{{ $ticketsNew }}</span></span>
</li>
<li class="nav-item">
<span class="nav-link text-dark">{{ __('En cours') }}&nbsp;:&nbsp;<span class="text-info">{{ $ticketsInProgress }}</span></span>
</li>
<li class="nav-item">
{{-- Mouhahahaha --}}
<span class="nav-link text-dark">{{ __('Charge') }}&nbsp;:&nbsp;<span class="text-danger">{{ __('Elevée') }}</span></span>
{{-- <span class="nav-link text-dark">Charge&nbsp;:&nbsp;<span class="text-info">Stable</span></span> --}}
</li>
</ul>
</div>
@endauth
<!-- Left Side Of Navbar -->
<ul class="navbar-nav me-auto">
@if(Auth::check() and !Auth::user()->role->equals(Role::client()))
<li class="{{ Auth::user()->role->equals(Role::admin()) ? 'text-primary' : 'text-success'}}">
{{ Auth::user()->role->label }}
</li>
@endif
</ul>
<!-- Right Side Of Navbar -->
<ul class="navbar-nav ms-auto me-2">
<!-- Authentication Links -->
@auth
<li class="nav-item dropdown">
<a id="navbarDropdown" class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
{{ __('Bonjour') }}&nbsp;{{ Auth::user()->name }} <span class="caret"></span>
</a>
<div class="dropdown-menu dropdown-menu-right" aria-labelledby="navbarDropdown">
<a class="dropdown-item" href="#"
onclick="event.preventDefault();
document.getElementById('logout-form').submit();">
{{ __('Déconnexion') }}
</a>
<form id="logout-form" action="{{route('logout')}}" method="POST" style="display: none;">
@csrf
</form>
</div>
</li>
@else
<li class="nav-item">
<a class="nav-link" href="{{route('login')}}">{{ __('Connexion') }}</a>
</li>
@endguest
</ul>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="{{ __('Toggle navigation') }}">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<!-- Left Side Of Navbar -->
<ul class="navbar-nav me-auto">
@if(!Auth::user()->role->equals(Role::client()))
<li class="{{ Auth::user()->role->equals(Role::admin()) ? 'text-primary' : 'text-success'}}">
{{ Auth::user()->role->label }}
</li>
@endif
</ul>
<!-- Right Side Of Navbar -->
<ul class="navbar-nav ms-auto">
<!-- Authentication Links -->
@auth
<li class="nav-item dropdown">
<a id="navbarDropdown" class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false" v-pre>
{{ __('Bonjour') }}&nbsp;{{ Auth::user()->name }} <span class="caret"></span>
</a>
<div class="dropdown-menu dropdown-menu-right" aria-labelledby="navbarDropdown">
<a class="dropdown-item" href="#"
onclick="event.preventDefault();
document.getElementById('logout-form').submit();">
{{ __('Déconnexion') }}
</a>
<form id="logout-form" action="{{route('logout')}}" method="POST" style="display: none;">
@csrf
</form>
</div>
</li>
@else
<li class="nav-item">
<a class="nav-link" href="{{route('login')}}">{{ __('Connexion') }}</a>
</li>
@endguest
</ul>
</div>
</div>
</nav>

View file

@ -8,10 +8,8 @@
<div class="card">
@include('crud-policies::crud.modules.flashMessage')
<div class="card-header">
<a href="{{ CrudController::getRoutePrefixed("$modelTable.index") }}">{{ transFb(sprintf('models.classes.%s', strtolower(Str::plural(class_basename($modelClass)))), Str::plural(class_basename($modelClass))) }}</a>&nbsp;-&nbsp;{{ __('crud-policies::crud.viewAny') }}
@can('create', $modelClass)
<a href="{{ CrudController::getRoutePrefixed("$modelTable.create") }}" class="btn btn-primary float-end">{{ __('crud-policies::crud.create') }}</a>
@endcan
@include('crud-policies::crud.modules.breadcrumb', ['action' => CrudAction::viewAny()])
@include('crud-policies::crud.modules.actionbar.bar', ['action' => CrudAction::viewAny()])
</div>
<div class="card-body">
<div class="row justify-content-center">
@ -32,49 +30,31 @@
</form>
</div>
</div>
<table class="table text-center">
<thead class="thead-dark">
@include('crud-policies::crud.modules.sorter')
</thead>
<tbody>
@if(count($models))
{{-- INIT QUERIES for OPTIMIZING --}}
@foreach ($modelClass::getEditableProperties() as $fieldName => $prop)
@if($prop['type']->equals(CrudType::order()))
@php ${"$modelTable$fieldName"} = $modelClass::max($fieldName); @endphp
@endif
@if($prop['type']->equals(CrudType::belongsTo()))
@php try { $models->load(Str::singular((new $prop['belongsTo']())->getTable())); } catch(\Exception $e) {} @endphp
@endif
@if($prop['type']->equals(CrudType::belongsToMany()))
@php $models->load("$fieldName"); @endphp
@endif
@endforeach
@if(count($models))
{{-- DISPLAY MODELS --}}
@foreach($models as $model)
<tr>
@foreach ($modelClass::getEditableProperties() as $fieldName => $prop)
@if(in_array(CrudAction::viewAny(), $prop['actions']))
@switch($prop['type'])
@case(CrudType::password())
{{-- Ignore --}}
@break
@default
<td>@include('crud-policies::crud.printfield', [
'action' => CrudAction::viewAny(),
'field' => $model->{$fieldName},
'props' => $prop,
"$modelTable$fieldName" => ${"$modelTable$fieldName"} ?? null
])</td>
@endswitch
@endif
@endforeach
{{-- INIT QUERIES for OPTIMIZING --}}
@foreach ($modelClass::getEditableProperties() as $fieldName => $prop)
@if($prop['type']->equals(CrudType::order()))
@php ${"$modelTable$fieldName"} = $modelClass::max($fieldName); @endphp
@endif
@if($prop['type']->equals(CrudType::belongsTo()))
@php try { $models->load(Str::singular((new $prop['belongsTo']())->getTable())); } catch(\Exception $e) {} @endphp
@endif
@if($prop['type']->equals(CrudType::belongsToMany()))
@php $models->load("$fieldName"); @endphp
@endif
@endforeach
{{-- MODEL ACTIONS --}}
<td>
<div class="btn-group" role="group" aria-label="{{ Str::plural(__('crud-policies::crud.action')) }}">
{{-- DISPLAY MODELS --}}
@foreach($models as $model)
<div class="col-8 mt-5 @if($loop->even)float-end @else float-start @endif">
<div class="card text-center">
<div class="card-header">
<div class="d-inline-block badge bg-primary fs-6 mt-1">
{{ $model->created_at }}
</div>
<div class="btn-group float-end" role="group" aria-label="{{ Str::plural(__('crud-policies::crud.action')) }}">
@can('view', $model)
<a href="{{ CrudController::getRoutePrefixed("$modelTable.show", $model) }}" class="btn btn-sm btn-primary">{{ __('crud-policies::crud.view') }}</a>
@endcan
@ -89,19 +69,22 @@
</form>
@endcan
</div>
</td>
</tr>
@endforeach
@else
<tr>
<td colspan="{{ count($modelClass::getEditableProperties()) }}">
{{ __('crud-policies::crud.nothingtoshow') }}
</td>
</tr>
@endif
</tbody>
</table>
{{ $models->links() }}
</div>
<div class="card-body">
<h5 class="card-title">{{ __('Par :username', [
'username' => $model->user->name
])}}</h5>
<div class="card-text">{{ $model->entry }}</div>
</div>
</div>
</div>
@endforeach
@else
{{ __('crud-policies::crud.nothingtoshow') }}
@endif
</div>
<div class="row justify-content-center mt-5 mb-5">
<div class="col-1">{{ $models->links() }}</div>
</div>
</div>
@include('crud-policies::crud.modules.scriptConstants')

View file

@ -0,0 +1,10 @@
@if(request()->project)
<a href="{{ route('projects.show', request()->project) }}" class="btn btn-success float-end">{{ __('Projet') }}</a>
<a href="{{ route('projects.logs.index', request()->project) }}" class="btn btn-dark float-end">{{ __('Journaux') }}</a>
<a href="{{ route('projects.files.index', request()->project) }}" class="btn btn-dark float-end">{{ __('Fichiers') }}</a>
@endif
@if(request()->site)
<a href="{{ route('sites.show', request()->site) }}" class="btn btn-success float-end">{{ __('Site') }}</a>
<a href="{{ route('sites.logs.index', request()->site) }}" class="btn btn-dark float-end">{{ __('Journaux') }}</a>
<a href="{{ route('sites.files.index', request()->site) }}" class="btn btn-dark float-end">{{ __('Fichiers') }}</a>
@endif

View file

@ -0,0 +1,112 @@
@extends($viewLayout)
@section('title', sprintf('%s - %s', transFb(sprintf('models.classes.%s', strtolower(Str::plural(class_basename($modelClass)))), Str::plural(class_basename($modelClass))), __('crud-policies::crud.viewAny')))
@section('description', sprintf('%s %s', __('crud-policies::crud.viewAny'), trans(Str::plural(class_basename($modelClass)))))
@section('metaIndex', 'noindex,nofollow')
@section('content')
<div class="card">
@include('crud-policies::crud.modules.flashMessage')
<div class="card-header">
@include('crud-policies::crud.modules.breadcrumb', ['action' => CrudAction::viewAny()])
@include('crud-policies::crud.modules.actionbar.bar', ['action' => CrudAction::viewAny()])
</div>
<div class="card-body">
<div class="row justify-content-center">
<div class="col">
{{ $models->links() }}
</div>
<div class="col">
<form action="{{ url()->current() }}">
<div class="input-group mb-3">
<input type="search" name="search" class="form-control" value="{{ request()->search }}"/>
<input type="text" name="sort_col" class="d-none" value="{{ request()->sort_col }}"/>
<input type="text" name="sort_way" class="d-none" value="{{ request()->sort_way }}"/>
<a class="btn btn-danger" href="{{ url()->current() }}">{{ __('crud-policies::crud.reset') }}</a>
<button type="submit" class="btn btn-primary">
{{ __('crud-policies::crud.search') }}
</button>
</div>
</form>
</div>
</div>
<table class="table text-center">
<thead class="thead-dark">
@include('crud-policies::crud.modules.sorter')
</thead>
<tbody>
@if(count($models))
{{-- INIT QUERIES for OPTIMIZING --}}
@foreach ($modelClass::getEditableProperties() as $fieldName => $prop)
@if($prop['type']->equals(CrudType::order()))
@php ${"$modelTable$fieldName"} = $modelClass::max($fieldName); @endphp
@endif
@if($prop['type']->equals(CrudType::belongsTo()))
@php try { $models->load(Str::singular((new $prop['belongsTo']())->getTable())); } catch(\Exception $e) {} @endphp
@endif
@if($prop['type']->equals(CrudType::belongsToMany()))
@php $models->load("$fieldName"); @endphp
@endif
@endforeach
{{-- DISPLAY MODELS --}}
@foreach($models as $model)
<tr>
@foreach ($modelClass::getEditableProperties() as $fieldName => $prop)
@if(in_array(CrudAction::viewAny(), $prop['actions']))
@switch($prop['type'])
@case(CrudType::password())
{{-- Ignore --}}
@break
@default
<td>@include('crud-policies::crud.printfield', [
'action' => CrudAction::viewAny(),
'field' => $model->{$fieldName},
'props' => $prop,
"$modelTable$fieldName" => ${"$modelTable$fieldName"} ?? null
])</td>
@endswitch
@endif
@endforeach
{{-- MODEL ACTIONS --}}
<td>
<div class="btn-group" role="group" aria-label="{{ Str::plural(__('crud-policies::crud.action')) }}">
@can('view', $model)
<a href="{{ CrudController::getRoutePrefixed("$modelTable.show", $model) }}" class="btn btn-sm btn-primary">{{ __('crud-policies::crud.view') }}</a>
@endcan
@can('update', $model)
<a href="{{ CrudController::getRoutePrefixed("$modelTable.edit", $model) }}" class="btn btn-sm btn-info">{{ __('crud-policies::crud.edit') }}</a>
@endcan
@can('delete', $model)
<form action="{{ CrudController::getRoutePrefixed("$modelTable.destroy", $model) }}" method="POST" onsubmit="__CRUD.confirmDelete(event)">
@csrf
@method('DELETE')
<button type="submit" class="btn btn-sm btn-danger">{{ __('crud-policies::crud.delete') }}</button>
</form>
@endcan
@can('viewAny', \App\Models\Log::class)
<a href="{{ CrudController::getRoutePrefixed("projects.logs.index", $model) }}" class="btn btn-sm btn-dark">{{ __('Journaux') }}</a>
@endcan
@can('viewAny', \App\Models\File::class)
<a href="{{ CrudController::getRoutePrefixed("projects.files.index", $model) }}" class="btn btn-sm btn-dark">{{ __('Fichiers') }}</a>
@endcan
</div>
</td>
</tr>
@endforeach
@else
<tr>
<td colspan="{{ count($modelClass::getEditableProperties()) }}">
{{ __('crud-policies::crud.nothingtoshow') }}
</td>
</tr>
@endif
</tbody>
</table>
{{ $models->links() }}
</div>
</div>
@include('crud-policies::crud.modules.scriptConstants')
@endsection

View file

@ -8,10 +8,8 @@
<div class="card">
@include('crud-policies::crud.modules.flashMessage')
<div class="card-header">
<a href="{{ CrudController::getRoutePrefixed("$modelTable.index") }}">{{ transFb(sprintf('models.classes.%s', strtolower(Str::plural(class_basename($modelClass)))), Str::plural(class_basename($modelClass))) }}</a>&nbsp;-&nbsp;{{ __('crud-policies::crud.viewAny') }}
@can('create', $modelClass)
<a href="{{ CrudController::getRoutePrefixed("$modelTable.create") }}" class="btn btn-primary float-end">{{ __('crud-policies::crud.create') }}</a>
@endcan
@include('crud-policies::crud.modules.breadcrumb', ['action' => CrudAction::viewAny()])
@include('crud-policies::crud.modules.actionbar.bar', ['action' => CrudAction::viewAny()])
</div>
<div class="card-body">
<div class="row justify-content-center">
@ -58,6 +56,13 @@
@foreach ($modelClass::getEditableProperties() as $fieldName => $prop)
@if(in_array(CrudAction::viewAny(), $prop['actions']))
@switch($prop['type'])
@case(CrudType::belongsToMany() and $prop['belongsToMany'] === \App\Models\Project::class)
<td>
@foreach($model->{$fieldName} as $pSite)
<a href="{{ CrudController::getRoutePrefixed($pSite->getTable().'.show', $pSite) }}">{{ $pSite->{$prop['belongsToManyLabel']} }}</a>
@endforeach
</td>
@break
@case(CrudType::password())
{{-- Ignore --}}
@break

View file

@ -1,57 +0,0 @@
@extends($viewLayout)
@section('title', sprintf('%s - %s', transFb(sprintf('models.classes.%s', strtolower(Str::plural(class_basename($modelClass)))), Str::plural(class_basename($modelClass))), __('crud-policies::crud.edit')))
@section('description', sprintf('%s %s', __('crud-policies::crud.edit'), trans(class_basename($modelClass))))
@section('metaIndex', 'noindex,nofollow')
@section('content')
<div class="card">
@include('crud-policies::crud.modules.flashMessage')
<div class="card-header">
@can('viewAny', $modelClass)
<a href="{{ CrudController::getRoutePrefixed("$modelTable.index") }}">{{ transFb(sprintf('models.classes.%s', strtolower(Str::plural(class_basename($modelClass)))), Str::plural(class_basename($modelClass))) }}</a>&nbsp;-&nbsp;{{ __('crud-policies::crud.edit') }}
@else
{{ trans(Str::plural(class_basename($modelClass))) }}&nbsp;-&nbsp;{{ __('crud-policies::crud.edit') }}
@endcan
<div class="btn-group float-end" role="group" aria-label="{{ __('crud-policies::crud.action') }}">
@can('view', $model)
<a href="{{ CrudController::getRoutePrefixed("$modelTable.show", $model) }}" class="btn btn-primary ">{{ __('crud-policies::crud.view') }}</a>
@endcan
@can('delete', $model)
<form action="{{ CrudController::getRoutePrefixed("$modelTable.destroy", $model) }}" method="POST" onsubmit="__CRUD.confirmDelete(event)">
@csrf
@method('DELETE')
<button type="submit" class="btn btn-danger">{{ __('crud-policies::crud.delete') }}</button>
</form>
@endcan
</div>
</div>
<div class="card-body">
<form action="{{ CrudController::getRoutePrefixed("$modelTable.update", $model) }}" method="POST" @if($hasImage) enctype="multipart/form-data" @endif>
@method('put')
@csrf
<table class="table table-sm table-bordered border-primary align-middle table-striped text-center">
<thead class="thead-dark">
<tr>
<th scope="col" class="w-25">{{ __('crud-policies::crud.property') }}</th>
<th scope="col" class="w-75">{{ __('crud-policies::crud.value') }}</th>
</tr>
</thead>
<tbody>
@foreach ($modelClass::getEditableProperties() as $fieldName => $prop)
@if(in_array(CrudAction::update(), $prop['actions']))
<tr>
@include('crud-policies::crud.formfield')
</tr>
@endif
@endforeach
</tbody>
</table>
<div class="col text-center">
<button class="btn btn-info" type="submit">{{ __('crud-policies::crud.update') }}</button>
</div>
</form>
</div>
</div>
@include('crud-policies::crud.modules.scriptConstants')
@endsection

View file

@ -1,53 +0,0 @@
@php
$readonly = is_callable($prop['readonly']) ? $prop['readonly']() : $prop['readonly'];
@endphp
@switch($prop['type'])
@case(CrudType::password())
@include('crud-policies::crud.formfields.password')
@break
@case(CrudType::boolean())
@include('crud-policies::crud.formfields.boolean')
@break
@case(CrudType::int())
@include('crud-policies::crud.formfields.int')
@break
@case(CrudType::float())
@include('crud-policies::crud.formfields.float')
@break
@case(CrudType::unsignedint())
@include('crud-policies::crud.formfields.int', ['unsigned' => true])
@break
@case(CrudType::unsignedfloat())
@include('crud-policies::crud.formfields.float', ['unsigned' => true])
@break
@case(CrudType::email())
@include('crud-policies::crud.formfields.email')
@break
@case(CrudType::text())
@include('crud-policies::crud.formfields.text')
@break
@case(CrudType::json())
@include('crud-policies::crud.formfields.json')
@break
@case(CrudType::image())
@include('crud-policies::crud.formfields.image')
@break
@case(CrudType::enum())
@include('crud-policies::crud.formfields.enum')
@break
@case(CrudType::order())
@include('crud-policies::crud.formfields.order')
@break
@case(CrudType::color())
@include('crud-policies::crud.formfields.color')
@break
@case(CrudType::belongsTo())
@include('crud-policies::crud.formfields.belongsTo')
@break
@case(CrudType::belongsToMany())
@include('crud-policies::crud.formfields.belongsToMany')
@break
@case(CrudType::string())
@default
@include('crud-policies::crud.formfields.string')
@endswitch

View file

@ -1,32 +0,0 @@
@php
$related = isset($model) ? $props[$fieldName]['belongsTo']::find($model->{$fieldName}) : null;
if($related) {
$related = [
'label' => $related->crudLabel,
'value' => $related->crudValue
];
}
@endphp
<td>
<label for="{{ $fieldName }}" class="form-label">{{ $prop['label'] }}</label>
</td>
<td>
<belongs-to
readonly="{{ $readonly }}"
tablename="{{ $modelTable }}"
name="{{ $fieldName }}"
db-value='@json($related)'>
</belongs-to>
</td>
@push('scriptsConstants')
<script>
if (!window.__CRUD) {
window.__CRUD = {};
}
if(!window.__CRUD._routes) {
window.__CRUD._routes = {};
}
window.__CRUD._routes['{{$modelTable}}.{{$fieldName}}.model.index'] = '{{ CrudController::getRoutePrefixed((new $props[$fieldName]['belongsTo'])->getTable().'.index') }}';
</script>
@endpush

View file

@ -1,31 +0,0 @@
@php
$related = isset($model) ? $model->{$fieldName}->mapWithKeys(function ($model) use($prop) {
return [$model->{'id'} => [
'label' => $model->{$prop['belongsToManyLabel']},
'value' => $model->{'id'}
]];
}) : [];
@endphp
<td>
<label for="{{ $fieldName }}" class="form-label">{{ $prop['label'] }}</label>
</td>
<td>
<belongs-to-many
readonly="{{ $readonly }}"
tablename="{{ $modelTable }}"
name="{{ $fieldName }}"
db-value='@json($related)'>
</belongs-to-many>
</td>
@push('scriptsConstants')
<script>
if (!window.__CRUD) {
window.__CRUD = {};
}
if(!window.__CRUD._routes) {
window.__CRUD._routes = {};
}
window.__CRUD._routes['{{$modelTable}}.{{$fieldName}}.model.index'] = '{{ CrudController::getRoutePrefixed((new $props[$fieldName]['belongsToMany'])->getTable().'.index') }}';
</script>
@endpush

View file

@ -1,20 +0,0 @@
<td>
<label for="{{ $fieldName }}" class="form-label">{{ $prop['label'] }}</label>
</td>
<td>
<label for="{{ $fieldName }}" class="row">
<div class="col">
<div class="form-check form-switch ms-2">
<input
id="{{ $fieldName }}"
name="{{ $fieldName }}"
type="checkbox"
class="ml-2 form-check-input"
value="1"
@if(old($fieldName) ?? ((isset($model) and $model->{$fieldName}) ? $model->{$fieldName} : $prop['default'] ?? false))checked @endif
@if($prop['disabled'])disabled @endif
@if($readonly)readonly @endif>
</div>
</div>
</label>
</td>

View file

@ -1,32 +0,0 @@
<td>
<label for="{{ $fieldName }}" class="form-label">{{ $prop['label'] }}</label>
</td>
<td>
@if(strlen($prop['placeholder']))
<div class="form-floating">
<input
id="{{ $fieldName }}"
name="{{ $fieldName }}"
type="text"
data-jscolor=""
class="form-control"
value="{{ old($fieldName) ?? $model->{$fieldName} ?? $prop['default'] ?? '' }}"
@if($prop['disabled'])disabled @endif
@if($readonly)readonly @endif
@if($prop['required'] or (!$prop['required'] and !$prop['nullable']))required @endif>
<label for="{{ $fieldName }}" class="form-label">{{ __('ex: :placeholder', ['placeholder' => $prop['placeholder']]) }}</label>
</div>
@else
<input
id="{{ $fieldName }}"
name="{{ $fieldName }}"
type="text"
data-jscolor=""
class="form-control"
value="{{ old($fieldName) ?? $model->{$fieldName} ?? $prop['default'] ?? '' }}"
@if($prop['disabled'])disabled @endif
@if($readonly)readonly @endif
@if($prop['required'] or (!$prop['required'] and !$prop['nullable']))required @endif>
@endif
</td>
@include('crud-policies::crud.modules.color')

View file

@ -1,33 +0,0 @@
<td>
<label for="{{ $fieldName }}" class="form-label">{{ $prop['label'] }}</label>
</td>
<td>
@if(strlen($prop['placeholder']))
<div class="form-floating">
<input
id="{{ $fieldName }}"
name="{{ $fieldName }}"
type="email"
class="form-control"
value="{{ old($fieldName) ?? $model->{$fieldName} ?? $prop['default'] ?? '' }}"
@if(isset($prop['rules']['max']))maxlength="{{ $prop['rules']['max'] }}"@endif
@if(isset($prop['rules']['min']))minlength="{{ $prop['rules']['min'] }}"@endif
@if($prop['disabled'])disabled @endif
@if($readonly)readonly @endif
@if($prop['required'] or (!$prop['required'] and !$prop['nullable']))required @endif>
<label for="{{ $fieldName }}" class="form-label">{{ __('ex: :placeholder', ['placeholder' => $prop['placeholder']]) }}</label>
</div>
@else
<input
id="{{ $fieldName }}"
name="{{ $fieldName }}"
type="email"
class="form-control"
value="{{ old($fieldName) ?? $model->{$fieldName} ?? $prop['default'] ?? '' }}"
@if(isset($prop['rules']['max']))maxlength="{{ $prop['rules']['max'] }}"@endif
@if(isset($prop['rules']['min']))minlength="{{ $prop['rules']['min'] }}"@endif
@if($prop['disabled'])disabled @endif
@if($readonly)readonly @endif
@if($prop['required'] or (!$prop['required'] and !$prop['nullable']))required @endif>
@endif
</td>

View file

@ -1,13 +0,0 @@
<td>
<label for="{{ $fieldName }}" class="form-label">{{ $prop['label'] }}</label>
</td>
<td>
<select id="{{ $fieldName }}" class="form-control" name="{{ $fieldName }}" @if($readonly) readonly @endif @if($prop['disabled']) disabled @endif>
{{-- TODO handle enum nullable ? --}}
{{-- @if($prop['nullable'])
@endif --}}
@foreach ($prop['enum']::toArray() as $enum)
<option value="{{$enum->value}}" @if(isset($model) and $enum->equals($model->{$fieldName}))selected @endif>{{__($enum->label)}}</option>
@endforeach
</select>
</td>

View file

@ -1,22 +0,0 @@
<td>
<label for="{{ $fieldName }}" class="form-label">{{ $prop['label'] }}</label>
</td>
<td>
<input
id="{{ $fieldName }}"
class="form-control"
name="{{ $fieldName }}"
type="number"
placeholder="{{ $prop['placeholder'] }}"
step="0.000001"
@if(isset($unsigned))
min="0"
@endif
value="{{ old($fieldName) ?? $model->{$fieldName} ?? $prop['rules']['min'] ?? $prop['default'] ?? 0 }}"
@if(isset($prop['rules']['max']))max="{{ $prop['rules']['max'] }}"@endif
@if(isset($prop['rules']['min']))min="{{ $prop['rules']['min'] }}"@endif
@if(isset($prop['rules']['step']))step="{{ $prop['rules']['step'] }}"@endif
@if($prop['disabled'])disabled @endif
@if($readonly)readonly @endif
@if($prop['required'] or (!$prop['required'] and !$prop['nullable']))required @endif>
</td>

View file

@ -1,26 +0,0 @@
<td>
<label for="{{ $fieldName }}" class="form-label">{{ $prop['label'] }}</label>
</td>
<td>
@if(strlen($prop['placeholder']))
<div class="form-floating">
@endif
<input
id="{{ $fieldName }}"
name="{{ $fieldName }}"
type="file"
class="form-control"
value="{{ old($fieldName) ?? $model->{$fieldName} ?? $prop['default'] ?? '' }}"
@if(isset($prop['rules']['max']))maxlength="{{ $prop['rules']['max'] }}"@endif
@if(isset($prop['rules']['min']))minlength="{{ $prop['rules']['min'] }}"@endif
@if($prop['disabled'])disabled @endif
@if($readonly)readonly @endif
@if(($prop['required'] or (!$prop['required'] and !$prop['nullable'])) and !(isset($model) and $model->{$fieldName}))required @endif>
@if(strlen($prop['placeholder']))
<label for="{{ $fieldName }}" class="form-label">{{ __('ex: :placeholder', ['placeholder' => $prop['placeholder']]) }}</label>
</div>
@endif
@if(isset($model) and $model->{$fieldName})
<img class="img-responsive" src="{{ sprintf('/storage/%s', $model->{$fieldName}) }}" alt="{{ sprintf('/storage/%s', $model->{$fieldName}) }}">
@endif
</td>

View file

@ -1,21 +0,0 @@
<td>
<label for="{{ $fieldName }}" class="form-label">{{ $prop['label'] }}</label>
</td>
<td>
<input
id="{{ $fieldName }}"
class="form-control"
name="{{ $fieldName }}"
type="number"
placeholder="{{ $prop['placeholder'] }}"
@if(isset($unsigned))
min="0"
@endif
value="{{ old($fieldName) ?? $model->{$fieldName} ?? $prop['rules']['min'] ?? $prop['default'] ?? 0 }}"
@if(isset($prop['rules']['max']))max="{{ $prop['rules']['max'] }}"@endif
@if(isset($prop['rules']['min']))min="{{ $prop['rules']['min'] }}"@endif
@if(isset($prop['rules']['step']))step="{{ $prop['rules']['step'] }}"@endif
@if($prop['disabled'])disabled @endif
@if($readonly)readonly @endif
@if($prop['required'] or (!$prop['required'] and !$prop['nullable']))required @endif>
</td>

View file

@ -1,23 +0,0 @@
@php
$jsonValue = old($fieldName) ?? (
(isset($model) and $model->{$fieldName}) ?
(
is_array($model->{$fieldName}) ?
json_encode($model->{$fieldName}) : $model->{$fieldName}
) : $prop['default']
);
@endphp
<td>
<label for="{{ $fieldName }}" class="form-label">{{ $prop['label'] }}</label>
</td>
<td>
<div class="mb-3">
<div id="{{ $fieldName }}jsoneditor"></div>
<textarea id="{{ $fieldName }}" name="{{ $fieldName }}" rows="3" class="form-control d-none" @if($readonly) readonly @endif>{!! $jsonValue !!}</textarea>
</div>
</td>
@include('crud-policies::crud.modules.jsoneditor', [
'fieldName' => $fieldName,
'value' => $jsonValue,
'prop' => $prop
])

View file

@ -1,19 +0,0 @@
<td>
<label for="{{ $fieldName }}" class="form-label">{{ $prop['label'] }}</label>
</td>
<td>
<select
id="{{ $fieldName }}"
name="{{ $fieldName }}"
class="form-control"
@if($readonly)readonly @endif
@if($prop['required'] or (!$prop['required'] and !$prop['nullable']))required @endif
@if($prop['disabled'])disabled @endif>
@foreach($modelClass::orderBy($fieldName)->pluck($fieldName) as $order)
<option value="{{ $order }}" @if(isset($model) and $model->order === $order)selected @endif>{{ $order }}</option>
@endforeach
@if(!isset($model))
<option value="{{ $modelClass::pluck($fieldName)->max() +1 }}" selected>{{ $modelClass::pluck($fieldName)->max() +1 }}</option>
@endif
</select>
</td>

View file

@ -1,67 +0,0 @@
<td>
<label for="{{ $fieldName }}" class="form-label">{{ $prop['label'] }}</label>
</td>
<td>
@if(strlen($prop['placeholder']))
<div class="form-floating">
<input
id="{{ $fieldName }}"
name="{{ $fieldName }}"
type="password"
class="form-control"
placeholder="{{ $prop['placeholder'] }}"
@if(isset($prop['rules']['max']))maxlength="{{ $prop['rules']['max'] }}"@endif
@if(isset($prop['rules']['min']))minlength="{{ $prop['rules']['min'] }}"@endif
@if($prop['disabled'])disabled @endif
@if($readonly)readonly @endif
@if($prop['required'] or !$prop['nullable'])required @endif>
<label for="{{ $fieldName }}" class="form-label">{{ __('ex: :placeholder', ['placeholder' => $prop['placeholder']]) }}</label>
</div>
@else
<input
id="{{ $fieldName }}"
name="{{ $fieldName }}"
type="password"
class="form-control"
placeholder="{{ $prop['placeholder'] }}"
@if(isset($prop['rules']['max']))maxlength="{{ $prop['rules']['max'] }}"@endif
@if(isset($prop['rules']['min']))minlength="{{ $prop['rules']['min'] }}"@endif
@if($prop['disabled'])disabled @endif
@if($readonly)readonly @endif
@if($prop['required'] or !$prop['nullable'])required @endif>
@endif
</td>
</tr><tr>
<td>
<label for="{{ $fieldName }}-confirm" class="form-label">{{ __('Confirmation')}}&nbsp;{{ $prop['label'] }}</label>
</td>
<td>
@if(strlen($prop['placeholder']))
<div class="form-floating">
<input
id="{{ $fieldName }}-confirm"
name="{{ $fieldName }}-confirm"
type="password"
class="form-control"
placeholder="{{ $prop['placeholder'] }}"
@if(isset($prop['rules']['max']))maxlength="{{ $prop['rules']['max'] }}"@endif
@if(isset($prop['rules']['min']))minlength="{{ $prop['rules']['min'] }}"@endif
@if($prop['disabled'])disabled @endif
@if($readonly)readonly @endif
@if($prop['required'] or !$prop['nullable'])required @endif>
<label for="{{ $fieldName }}-confirm" class="form-label">{{ __('ex: :placeholder', ['placeholder' => $prop['placeholder']]) }}</label>
</div>
@else
<input
id="{{ $fieldName }}-confirm"
name="{{ $fieldName }}-confirm"
type="password"
class="form-control"
placeholder="{{ $prop['placeholder'] }}"
@if(isset($prop['rules']['max']))maxlength="{{ $prop['rules']['max'] }}"@endif
@if(isset($prop['rules']['min']))minlength="{{ $prop['rules']['min'] }}"@endif
@if($prop['disabled'])disabled @endif
@if($readonly)readonly @endif
@if($prop['required'] or !$prop['nullable'])required @endif>
@endif
</td>

View file

@ -1,33 +0,0 @@
<td>
<label for="{{ $fieldName }}" class="form-label">{{ $prop['label'] }}</label>
</td>
<td>
@if(strlen($prop['placeholder']))
<div class="form-floating">
<input
id="{{ $fieldName }}"
name="{{ $fieldName }}"
type="text"
class="form-control"
value="{{ old($fieldName) ?? $model->{$fieldName} ?? $prop['default'] ?? '' }}"
@if(isset($prop['rules']['max']))maxlength="{{ $prop['rules']['max'] }}"@endif
@if(isset($prop['rules']['min']))minlength="{{ $prop['rules']['min'] }}"@endif
@if($prop['disabled'])disabled @endif
@if($readonly)readonly @endif
@if($prop['required'] or (!$prop['required'] and !$prop['nullable']))required @endif>
<label for="{{ $fieldName }}" class="form-label">{{ __('ex: :placeholder', ['placeholder' => $prop['placeholder']]) }}</label>
</div>
@else
<input
id="{{ $fieldName }}"
name="{{ $fieldName }}"
type="text"
class="form-control"
value="{{ old($fieldName) ?? $model->{$fieldName} ?? $prop['default'] ?? '' }}"
@if(isset($prop['rules']['max']))maxlength="{{ $prop['rules']['max'] }}"@endif
@if(isset($prop['rules']['min']))minlength="{{ $prop['rules']['min'] }}"@endif
@if($prop['disabled'])disabled @endif
@if($readonly)readonly @endif
@if($prop['required'] or (!$prop['required'] and !$prop['nullable']))required @endif>
@endif
</td>

View file

@ -1,13 +0,0 @@
<td>
<label for="{{ $fieldName }}" class="form-label">{{ $prop['label'] }}</label>
</td>
<td>
<div class="mb-3">
<textarea id="{{ $fieldName }}" name="{{ $fieldName }}" rows="3" class="form-control" @if($readonly) readonly @endif>{{
old($fieldName) ?? $model->{$fieldName} ?? $prop['default'] ?? ''
}}</textarea>
</div>
</td>
@include('crud-policies::crud.modules.ckeditor', [
'fieldName' => $fieldName
])

View file

@ -1,90 +0,0 @@
<!doctype html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<title>{{ config('app.name') }}@hasSection('title') - @yield('title')@endif</title>
<meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="description" content="@yield('description')">
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<meta name="robots" content="index, follow">
<link rel="canonical" href="{{ url()->current() }}" />
<!-- STYLES -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.1/dist/css/bootstrap.min.css" integrity="sha256-hHKA3d/HttC8OW3Sl093W8DoZudhHJDj++kZYo6MLzA=" crossorigin="anonymous">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/sweetalert2@11.0.16/dist/sweetalert2.min.css" integrity="sha256-qpXwccFYncH5gTqXFe9EXZ8QeDw1Re68bbNVfFZzIzg=" crossorigin="anonymous">
<link rel="stylesheet" href="{{ route('crud-policies.httpFileSend.asset', [
'type' => 'css',
'fileUri' => 'crud.css'
]) }}">
@stack('styles')
</head>
<body>
<div id="app">
<nav class="navbar navbar-expand-lg navbar-dark bg-dark sticky-top">
<div class="container-fluid">
<a class="navbar-brand" href="/">{{ config('app.name') }}</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarScroll" aria-controls="navbarScroll" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarScroll">
<ul class="navbar-nav ms-auto my-2 my-lg-0 navbar-nav-scroll " style="--bs-scroll-height: 100px;">
@auth()
<li class="nav-item"><span class="nav-link text-success">{{ auth()->user()->name }}</span></li>
@endauth
</ul>
</div>
</div>
</nav>
<div class="container-fluid">
<div class="row">
@if(isset($modelsClasses))
<nav id="sidebarMenu" class="col-md-3 col-lg-2 min-height-100vh d-md-block bg-light sidebar collapse">
<div class="sidebar-sticky pt-3 d-flex flex-column justify-content-between align-items-center">
<div class="col-12 mt-4">
@foreach($modelsClasses as $crudModel)
@if(
auth()->user()->can('viewAny', $crudModel) or
auth()->user()->can('create', $crudModel)
)
<h6 class="sidebar-heading px-3 mb-1 text-muted">
<span>{{ __(ucfirst(collect(explode('\\', $crudModel))->last())) }}</span>
</h6>
@php
$crudModel = new $crudModel();
@endphp
<ul class="nav flex-column mb-2">
@can('viewAny', $crudModel)
<li class="nav-item"><a class="nav-link" href="{{ CrudController::getRoutePrefixed(sprintf('%s.index', $crudModel->getTable())) }}">{{ __('crud-policies::crud.viewAny') }}</a></li>
@endcan
@can('create', $crudModel)
<li class="nav-item"><a class="nav-link" href="{{ CrudController::getRoutePrefixed(sprintf('%s.create', $crudModel->getTable())) }}">{{ __('crud-policies::crud.create') }}</a></li>
@endcan
</ul>
<hr>
@endcan
@endforeach
</div>
</div>
</nav>
<main role="main" class="col-md-9 mt-5 mb-5 ml-sm-auto col-lg-10 px-md-4">
@else
<main role="main" class="mt-5 mb-5">
@endif
@yield('content')
</main>
</div>
</div>
</div>
@stack('scriptsConstants')
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.1/dist/js/bootstrap.bundle.min.js" integrity="sha256-edRDsV9ULIqKzKjpN/KjyQ7Lp4vUn9usbJuHjH8Sk+k=" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11.0.16/dist/sweetalert2.all.min.js" integrity="sha256-551HBsteMvKOSqjUXSmRy/EOF0bBNbWB96b5L3Deh8A=" crossorigin="anonymous"></script>
<script src="//cdn.jsdelivr.net/npm/sweetalert2@10"></script>
<script src="{{ route('crud-policies.httpFileSend.asset', [
'type' => 'js',
'fileUri' => 'crud.js'
]) }}"></script>
@stack('scripts')
</body>
</html>

View file

@ -0,0 +1,21 @@
<div class="btn-group float-end" role="group" aria-label="{{ Str::plural(__('crud-policies::crud.action')) }}">
@switch($action)
@case(CrudAction::viewAny())
@include('modules.crudAction')
@include('crud-policies::crud.modules.actionbar.create')
@break
@case(CrudAction::view())
@include('modules.crudAction')
@include('crud-policies::crud.modules.actionbar.update')
@include('crud-policies::crud.modules.actionbar.delete')
@break
@case(CrudAction::create())
@include('modules.crudAction')
@break
@case(CrudAction::update())
@include('modules.crudAction')
@include('crud-policies::crud.modules.actionbar.view')
@include('crud-policies::crud.modules.actionbar.delete')
@break
@endswitch
</div>

View file

@ -0,0 +1,3 @@
@can('create', $modelClass)
<a href="{{ CrudController::getRoutePrefixed("$modelTable.create") }}" class="btn btn-primary float-end">{{ __('crud-policies::crud.create') }}</a>
@endcan

View file

@ -0,0 +1,7 @@
@can('delete', $model)
<form action="{{ CrudController::getRoutePrefixed("$modelTable.destroy", $model)}}" method="POST" onsubmit="__CRUD.confirmDelete(event)">
@csrf
@method('DELETE')
<button type="submit" class="btn btn-danger">{{ __('crud-policies::crud.delete') }}</button>
</form>
@endcan

View file

@ -0,0 +1,3 @@
@can('update', $model)
<a href="{{ CrudController::getRoutePrefixed("$modelTable.edit", $model)}}" class="btn btn-info ">{{ __('crud-policies::crud.update') }}</a>
@endcan

View file

@ -0,0 +1,3 @@
@can('view', $model)
<a href="{{ CrudController::getRoutePrefixed("$modelTable.show", $model) }}" class="btn btn-primary ">{{ __('crud-policies::crud.view') }}</a>
@endcan

View file

@ -1,15 +0,0 @@
@push('scripts')
@if(!isset($ckeditorInput))
@php View::share('ckeditorInput', true) @endphp
<script src="https://cdn.ckeditor.com/ckeditor5/27.1.0/classic/ckeditor.js"></script>
@endif
<script>
ClassicEditor
.create(
document.querySelector( '#{{ $fieldName }}' )
)
.catch( error => {
console.error( error );
});
</script>
@endpush

View file

@ -1,6 +0,0 @@
@if(!isset($CrudColorLib))
@push('scripts')
@php View::share('CrudColorLib', true) @endphp
<script src="https://cdnjs.cloudflare.com/ajax/libs/jscolor/2.4.5/jscolor.min.js"></script>
@endpush
@endif

View file

@ -1,44 +0,0 @@
@if ($message = Session::get('success'))
<div class="alert alert-success alert-dismissible fade show">
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="{{ __('crud-policies::crud.close') }}"></button>
<strong>{!! nl2br(e($message)) !!}</strong>
</div>
@endif
@if ($message = Session::get('error'))
<div class="alert alert-danger alert-dismissible fade show">
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="{{ __('crud-policies::crud.close') }}"></button>
<strong>{!! nl2br(e($message)) !!}</strong>
</div>
@endif
@if ($message = Session::get('warning'))
<div class="alert alert-warning alert-dismissible fade show">
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="{{ __('crud-policies::crud.close') }}"></button>
<strong>{!! nl2br(e($message)) !!}</strong>
</div>
@endif
@if ($message = Session::get('info'))
<div class="alert alert-info alert-dismissible fade show">
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="{{ __('crud-policies::crud.close') }}"></button>
<strong>{!! nl2br(e($message)) !!}</strong>
</div>
@endif
@if ($errors->any())
<div class="alert alert-danger alert-dismissible fade show">
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="{{ __('crud-policies::crud.close') }}"></button>
@if ($errors->any())
<ul class="list-unstyled">
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
@endif
</div>
@endif

View file

@ -1,27 +0,0 @@
@if(!isset($JsonEditor))
@push('scripts')
@php View::share('JsonEditor', true) @endphp
<script src="https://cdnjs.cloudflare.com/ajax/libs/jsoneditor/9.5.1/jsoneditor.min.js" integrity="sha512-NA6kPrAqyMsKDzpFPDLTE9TJn1iwCXSQOSIpdWBgVJMrnNIeYZECh8ePT5QI1tBVN6ZiTklWW3RKOLlxQDfMkA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
@endpush
@push('styles')
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jsoneditor/9.5.1/jsoneditor.min.css" integrity="sha512-ZS7UFcBWqviCnOtlrIz47Z10BQYs/qYJLIh/uUIVHRBjJ2zDVZ7ALvPssEqRLDObR66r5fEaY8NaLvIOOxQ1Vw==" crossorigin="anonymous" referrerpolicy="no-referrer" />
@endpush
@endif
@push('scripts')
<script>
let container = document.getElementById('{{ $fieldName.'jsoneditor' }}');
let input = document.getElementById('{{ $fieldName }}');
window.editor = new JSONEditor(container, {
mode: '{{ $prop['mode'] }}',
modes: {!! json_encode($prop['modes']) !!},
indentation: 2,
onError: function(error) {
console.log(error);
},
onChange: function() {
input.value = JSON.stringify(editor.getText());
}
}, {!! $jsonValue !!})
</script>
@endpush

View file

@ -1,10 +0,0 @@
@push('scriptsConstants')
<script>
if (!window.__CRUD) {
window.__CRUD = {};
}
window.__CRUD._locale = '{{ app()->getLocale() }}';
window.__CRUD._translations = @json(cache(sprintf('crud-policies.translations.%s', app()->getLocale())) ?? '{}');
window.__CRUD._asset = '{{ asset('') }}';
</script>
@endpush

View file

@ -1,34 +0,0 @@
<tr>
@foreach ($modelClass::getEditableProperties() as $colname => $prop)
@php
$sortParams = ['sort_col' => $colname];
$sortParams = request()->search ?
array_merge($sortParams, ['search' => request()->search]) : $sortParams;
@endphp
@if(in_array(CrudAction::viewAny(), $prop['actions']))
@switch($prop['type'])
@case(CrudType::password())
{{-- Ignore --}}
@break
@default
<th scope="col">
{{ $prop['label'] }}
@if(!session("crud.$modelTable.sort_way") or session("crud.$modelTable.sort_col") !== $colname or (session("crud.$modelTable.sort_way") === 'desc' and session("crud.$modelTable.sort_col") === $colname))
<a class="col_sort text-secondary lead asc" href="{{ CrudController::getRoutePrefixed("$modelTable.index", array_merge($sortParams, ['sort_way' => 'asc'])) }}">&nbsp;&darr;&nbsp;</a>
@endif
@if(!session("crud.$modelTable.sort_way") or session("crud.$modelTable.sort_col") !== $colname or (session("crud.$modelTable.sort_way") === 'asc' and session("crud.$modelTable.sort_col") === $colname))
<a class="col_sort text-secondary lead desc" href="{{ CrudController::getRoutePrefixed("$modelTable.index", array_merge($sortParams, ['sort_way' => 'desc'])) }}">&nbsp;&uarr;&nbsp;</a>
@endif
</th>
@endswitch
@endif
@endforeach
<th scope="col">
@if(session("crud.$modelTable.sort_way") and session("crud.$modelTable.sort_col"))
<a href="{{ request()->fullUrlWithQuery(['sort_col' => '', 'sort_way' => '']) }}" class="btn btn-small btn-danger">&#9003;</a>
@endif
</th>
</tr>

View file

@ -1,109 +0,0 @@
@switch($action)
@case(CrudAction::viewAny())
@switch($props['type'])
@case(CrudType::email())
<a href="mailto:$field">{{ $field }}</a>
@break
@case(CrudType::enum())
{{ $model->{$fieldName}->label }}
@break
@case(CrudType::belongsTo())
@php
$obj = null;
$obj = $model->{Str::singular((new $prop['belongsTo']())->getTable())} ??
$prop['belongsTo']::find($model->{$fieldName});
@endphp
{{ $obj->{$model->crudLabelColumn} }}
@break
@case(CrudType::belongsToMany())
{{ $model->{$fieldName}->implode($prop['belongsToManyLabel'], ',') }}
@break
@case(CrudType::boolean())
@if($model->{$fieldName})OUI @else NON @endif
@break
@case(CrudType::image())
<img class="img-responsive" src="{{ sprintf('/storage/%s', $model->{$fieldName}) }}" alt="{{ sprintf('/storage/%s', $model->{$fieldName}) }}">
@break
@case(CrudType::order())
@if(
Session::get("crud.$modelTable.sort_col") === $fieldName and
Session::get("crud.$modelTable.sort_way") === 'asc'
)
<span>
@if($model->{$fieldName} - 1 >= 0)
<form class="d-inline" action="{{ route('crud-policies.models.changeOrder', [
'modelTable' => $modelTable,
'modelId' => $model->id,
'colName' => $fieldName,
'newOrder' => $model->{$fieldName} - 1,
'oldUrl' => base64_encode(request()->getRequestUri())
]) }}" method="POST">
@csrf
@method('put')
<button class="col_sort btn btn-xs btn-primary text-decoration-none fw-bold lead desc">↑</button>
</form>
&nbsp;
@else
<span class="ms-2 me-3">&nbsp;</span>
@endif
{{ $model->{$fieldName} }}
@if(${"$modelTable$fieldName"} !== $model->{$fieldName})
&nbsp;
<form class="d-inline" action="{{ route('crud-policies.models.changeOrder', [
'modelTable' => $modelTable,
'modelId' => $model->id,
'colName' => $fieldName,
'newOrder' => $model->{$fieldName} + 1,
'oldUrl' => base64_encode(request()->getRequestUri())
]) }}" method="POST">
@csrf
@method('put')
<button class="col_sort btn btn-xs btn-primary text-decoration-none fw-bold lead asc">↓</button>
</form>
@else
<span class="ms-2 me-3">&nbsp;</span>
@endif
</span>
@else
{{ $model->{$fieldName} }}
@endif
@break
@default
{{ $field }}
@endswitch
@break
@case(CrudAction::view())
@switch($props['type'])
@case(CrudType::email())
<a href="mailto:$field">{{ $field }}</a>
@break
@case(CrudType::enum())
{{ $model->{$fieldName}->label }}
@break
@case(CrudType::json())
@json($field)
@break
@case(CrudType::boolean())
@if($model->{$fieldName})OUI @else NON @endif
@break
@case(CrudType::image())
<img class="img-responsive" src="{{ sprintf('/storage/%s', $model->{$fieldName}) }}" alt="{{ sprintf('/storage/%s', $model->{$fieldName}) }}">
@break
@case(CrudType::order())
{{ $model->{$fieldName} }}
@break
@case(CrudType::belongsTo())
{{ $prop['belongsTo']::find($model->{$fieldName})->{$model->crudLabelColumn} }}
@break
@case(CrudType::belongsToMany())
{{ $model->{$fieldName}->implode($prop['belongsToManyLabel'], ',') }}
@break
@default
{{ $field }}
@endswitch
@break
@default
@dd('unknown action')
@endswitch

View file

@ -1,61 +0,0 @@
@extends($viewLayout)
@section('title', sprintf('%s - %s', transFb(sprintf('models.classes.%s', strtolower(Str::plural(class_basename($modelClass)))), Str::plural(class_basename($modelClass))), __('crud-policies::crud.view')))
@section('description', sprintf('%s %s', __('crud-policies::crud.view'), trans(class_basename($modelClass))))
@section('metaIndex', 'noindex,nofollow')
@section('content')
<div class="card">
@include('crud-policies::crud.modules.flashMessage')
<div class="card-header">
@can('viewAny', $modelClass)
<a href="{{ CrudController::getRoutePrefixed("$modelTable.index")}}">{{ transFb(sprintf('models.classes.%s', strtolower(Str::plural(class_basename($modelClass)))), Str::plural(class_basename($modelClass))) }}</a>&nbsp;-&nbsp;{{ __('crud-policies::crud.view') }}
@else
{{ trans(Str::plural(class_basename($modelClass))) }}&nbsp;-&nbsp;{{ __('crud-policies::crud.show') }}
@endcan
<div class="btn-group float-end" role="group" aria-label="{{ Str::plural(__('crud-policies::crud.action')) }}">
@can('update', $model)
<a href="{{ CrudController::getRoutePrefixed("$modelTable.edit", $model)}}" class="btn btn-info ">{{ __('crud-policies::crud.update') }}</a>
@endcan
@can('delete', $model)
<form action="{{ CrudController::getRoutePrefixed("$modelTable.destroy", $model)}}" method="POST" onsubmit="__CRUD.confirmDelete(event)">
@csrf
@method('DELETE')
<button type="submit" class="btn btn-danger">{{ __('crud-policies::crud.delete') }}</button>
</form>
@endcan
</div>
</div>
<div class="card-body">
<table class="table table-sm table-bordered border-primary align-top table-striped text-center">
<thead class="thead-dark">
<tr>
<th scope="col" class="w-25">{{ __('crud-policies::crud.property') }}</th>
<th scope="col" class="w-75">{{ __('crud-policies::crud.value') }}</th>
</tr>
</thead>
<tbody>
@foreach ($modelClass::getEditableProperties() as $fieldName => $prop)
@if(in_array(CrudAction::view(), $prop['actions']))
@switch($prop['type'])
@case(CrudType::password())
{{-- Ignore --}}
@break
@default
<tr>
<td>{{ $prop['label'] }}</td>
<td>@include('crud-policies::crud.printfield', [
'action' => CrudAction::view(),
'field' => $model->{$fieldName},
'props' => $prop
])</td>
</tr>
@endswitch
@endif
@endforeach
</tbody>
</table>
</div>
</div>
@include('crud-policies::crud.modules.scriptConstants')
@endsection