Merge branch 'develop' into trunk

This commit is contained in:
Vincent BRIDIER 2023-08-14 11:24:22 +02:00
commit d2324145a4
No known key found for this signature in database
GPG key ID: 8571BFA20420D512
542 changed files with 32397 additions and 29269 deletions

5
.browserslistrc Normal file
View file

@ -0,0 +1,5 @@
# Browsers that we support
last 3 version
> 0.3%
not dead # no browsers without security updates

2
.dockerignore Normal file
View file

@ -0,0 +1,2 @@
.git
*.md

View file

@ -3,9 +3,9 @@ root = true
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
indent_style = space
indent_size = 4
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true
[*.md]
@ -13,3 +13,9 @@ trim_trailing_whitespace = false
[*.{yml,yaml}]
indent_size = 2
[docker-compose.yml]
indent_size = 4
[*.vue]
indent_size = 2

View file

@ -5,6 +5,7 @@ APP_DEBUG=true
APP_URL=http://localhost
LOG_CHANNEL=stack
LOG_DEPRECATIONS_CHANNEL=null
LOG_LEVEL=debug
DB_CONNECTION=mysql
@ -16,6 +17,7 @@ DB_PASSWORD=
BROADCAST_DRIVER=log
CACHE_DRIVER=file
FILESYSTEM_DISK=local
QUEUE_CONNECTION=sync
SESSION_DRIVER=file
SESSION_LIFETIME=120
@ -31,4 +33,15 @@ MAIL_FROM_NAME="${APP_NAME}"
MAIL_LIST_SERVICEWEB=equipe.web@ldc.fr
MAIL_ADMIN=equipe.web@ldc.fr
# Sentry
SENTRY_LARAVEL_DSN=
LDC_STATUS_CHECKER_API_KEY=
# ADMIN SECURE
# - API ENDPOINT (Optional)
LDC_WEB_API_ENDPOINT=
# - API KEY
LDC_WEB_API_KEY=
# - LIST SEPARATED WITH ',' (Optional)
LDC_WEB_CIDR_MANUAL_ALLOWED_LIST=

View file

@ -10,16 +10,16 @@
],
"overrides": [
{
"files": ["*.ts", "*.vue"],
"rules": {
"no-undef": "off"
}
"files": ["*.ts", "*.vue"],
"rules": {
"no-undef": "off"
}
},
{
"files": ["*.vue"],
"rules": {
"indent": "off"
}
"files": ["*.vue"],
"rules": {
"indent": "off"
}
}
],
"parser": "vue-eslint-parser",
@ -35,7 +35,21 @@
"linebreak-style": ["error", "unix"],
"quotes": ["error", "double"],
"semi": ["error", "always"],
"vue/script-indent": ["error", 2, { "baseIndent": 0 }],
"vue/script-indent": ["error", 2, { "baseIndent": 0, "switchCase": 1 }],
"vue/one-component-per-file": "off"
},
"settings": {
"import/resolver": {
"node": {
"extensions": [".js", ".vue", ".ts", ".d.ts"]
},
"alias": {
"extensions": [".vue", ".js", ".ts", ".scss", ".d.ts"],
"map": [
["~", "./resources/assets"],
["@", "./node_modules"]
]
}
}
}
}

14
.gitattributes vendored
View file

@ -1,5 +1,11 @@
* text=auto
*.css linguist-vendored
*.scss linguist-vendored
*.js linguist-vendored
* text=auto eol=lf
*.blade.php diff=html
*.css diff=css
*.html diff=html
*.md diff=markdown
*.php diff=php
/.github export-ignore
CHANGELOG.md export-ignore
.styleci.yml export-ignore

30
.gitignore vendored
View file

@ -1,21 +1,23 @@
/node_modules
/public/hot
/public/storage
/public/fichiers
/public/*
/storage/*.key
/vendor
.vscode
.env
.env.backup
.env.dev
.env.prod
.env.production
.phpunit.result.cache
.stylelintcache
/.fleet
/.idea
/.phpunit.cache
/.vscode
/node_modules
/public/build
/public/cache
/public/hot
/public/sitemap.xml
/public/storage
/storage/*.key
/vendor
auth.json
docker-compose.override.yml
Homestead.json
Homestead.yaml
npm-debug.log
yarn-error.log
package-lock.json
composer.lock
.idea/
auth.json

View file

@ -1,19 +1,24 @@
include:
- project: 'ldc-web/shared-ci'
ref: 'main'
file: 'lint/lint7.3.yml'
file: 'lint/lint.yml'
- project: 'ldc-web/shared-ci'
ref: 'main'
file: 'security/security7.3.yml'
file: 'security/security.yml'
- project: 'ldc-web/shared-ci'
ref: 'main'
file: 'build/build7.3.yml'
file: 'build/build.yml'
- project: 'ldc-web/shared-ci'
ref: 'main'
file: 'test/test.yml'
- project: 'ldc-web/shared-ci'
ref: 'main'
file: 'deploy/deploy.yml'
stages:
- lint
- security
- build
- test
- deploy

View file

@ -1,13 +0,0 @@
php:
preset: laravel
disabled:
- no_unused_imports
finder:
not-name:
- index.php
- server.php
js:
finder:
not-name:
- webpack.mix.js
css: true

View file

@ -1,8 +1,16 @@
{
"extends": [
"stylelint-config-standard-scss",
"stylelint-config-sass-guidelines",
"stylelint-config-idiomatic-order"
],
"plugins": [
"stylelint-scss"
],
"files": [
"**/*.css",
"**/*.scss"
],
"ignoreFiles": [
"**/vendor/*.css",
"**/vendor/**/*.css",
@ -19,6 +27,22 @@
"string-quotes": "double",
"selector-max-id": null,
"color-no-invalid-hex": true,
"order/properties-alphabetical-order": null
"order/properties-alphabetical-order": null,
"max-nesting-depth": 5,
"selector-max-compound-selectors": 5,
"declaration-colon-space-after": "always-single-line",
"function-parentheses-space-inside": "never-single-line",
"declaration-colon-newline-after": null,
"value-list-comma-newline-after": null,
"scss/double-slash-comment-empty-line-before": [
"always",
{
"ignore": [
"between-comments",
"stylelint-commands",
"inside-block"
]
}
]
}
}

5
Dockerfile Normal file
View file

@ -0,0 +1,5 @@
FROM registry.s-web.fr/ldc-web/projets/ldc-web-images-docker/ldcweb-production-8.2:latest
COPY --chown=www-data:www-data . /app/srcs
USER root
RUN chmod -R 755 /app/srcs/storage
USER www-data

4
README.md Normal file
View file

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

View file

@ -2,10 +2,9 @@
namespace App\Console\Commands;
use App\Enums\Role;
use App\Enums\Users\RoleEnum;
use App\Models\User;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\ValidationException;
@ -16,7 +15,7 @@ class CreateUser extends Command
*
* @var string
*/
protected $signature = 'create:user';
protected $signature = 'user:create';
/**
* The console command description.
@ -25,6 +24,34 @@ class CreateUser extends Command
*/
protected $description = 'Create a user';
/**
* The name of the new user.
*
* @var string
*/
protected $name;
/**
* The email of the new user.
*
* @var string
*/
protected $email;
/**
* The password of the new user.
*
* @var string
*/
protected $password;
/**
* The role of the new user.
*
* @var integer
*/
protected $role;
/**
* Execute the console command.
*
@ -32,59 +59,110 @@ class CreateUser extends Command
*/
public function handle()
{
$email = null;
while (is_null($email)) {
try {
$tmp = $this->ask('Type the wanted user email', 'equipe.web@ldc.fr');
$validator = Validator::make(['email' => $tmp], [
'email' => 'required|unique:users,email|email:rfc,dns'
]);
$validator->validate();
$email = $tmp;
} catch (ValidationException $e) {
$this->error(sprintf(
'Please provide a valid email %s',
\implode(',', collect($e->errors())->flatten()->all())
));
continue;
}
}
$name = null;
while (is_null($name)) {
$this->name = null;
$this->addName();
$this->email = null;
$this->addEmail();
$this->password = null;
$this->addPassword();
$this->role = null;
$this->addRole();
$user = new User([
'name' => $this->name,
'email' => $this->email,
'password' => $this->password,
'role' => $this->role
]);
$user->saveOrFail();
$this->info('User created.');
return 0;
}
/**
* Add a firstname to the user.
*
* @return void
*/
private function addName(): void
{
while (is_null($this->name)) {
try {
$tmp = $this->ask('Type the wanted user name', 'Admin');
$validator = Validator::make(['name' => $tmp], [
'name' => 'required|min:5,max:255'
'name' => 'required|min:3|max:255'
]);
$validator->validate();
$name = $tmp;
$this->name = $tmp;
} catch (ValidationException $e) {
$this->error(sprintf(
'Please provide a valid name %s',
\implode(',', collect($e->errors())->flatten()->all())
));
continue;
}
}
} //end try
}; //end while
}
$password = null;
/**
* Add an email to the user.
*
* @return void
*/
private function addEmail(): void
{
while (is_null($this->email)) {
try {
$tmp = $this->ask('Type the wanted user email', 'equipe.web@ldc.fr');
$validator = Validator::make(['email' => $tmp], [
'email' => 'required|unique:users,email|email:rfc,dns'
]);
$validator->validate();
$this->email = $tmp;
} catch (ValidationException $e) {
$this->error(sprintf(
'Please provide a valid email %s',
\implode(',', collect($e->errors())->flatten()->all())
));
continue;
} //end try
}; //end while
}
/**
* Add a password to the user.
*
* @return void
*/
private function addPassword(): void
{
while (
($password = $this->secret(
(!\is_null($password) ? 'Failed to confirm, ' : '') . 'Type the wanted user password'
($this->password = $this->secret(
(!\is_null($this->password) ? 'Failed to confirm, ' : '') . 'Type the wanted user password'
)) !== $this->secret('Confirm the password')
) {
continue;
}; //end while
}
/**
* Add a password to the user.
*
* @return void
*/
private function addRole(): void
{
while (is_null($this->role)) {
$tmp = $this->confirm('Is the user an admin?');
$validator = Validator::make(['role' => $tmp], [
'role' => 'required|boolean'
]);
$validator->validate();
$this->role = $tmp ? RoleEnum::admin : RoleEnum::client;
};
$user = new User();
$user->name = $name;
$user->email = $email;
$user->role = $this->confirm('Is the user an admin?') ? Role::admin() : Role::client();
$user->password = Hash::make($password);
$user->saveOrFail();
$this->info('User created.');
return 0;
}
}

View file

@ -1,38 +0,0 @@
<?php
namespace App\Enums\Credit;
use Kwaadpepper\Enum\BaseEnumRoutable;
/**
* @method static self development()
* @method static self seo()
*/
class AccountType extends BaseEnumRoutable
{
/**
* Enum values
*
* @return array
*/
protected static function values(): array
{
return [
'development' => 0,
'seo' => 1
];
}
/**
* Enum labels
*
* @return array
*/
protected static function labels(): array
{
return [
'development' => trans('Jours de développement'),
'seo' => trans('Jours de seo')
];
}
}

View file

@ -0,0 +1,21 @@
<?php
namespace App\Enums\Credit;
use App\Traits\Enums\BaseEnum;
enum AccountTypeEnum: int
{
use BaseEnum;
case development = 0;
case seo = 1;
/**
* Optionnal labels definition
*/
private const LABELS = [
self::development->name => "Jours de développement",
self::seo->name => "Jours de seo",
];
}

View file

@ -1,38 +0,0 @@
<?php
namespace App\Enums\Credit;
use Kwaadpepper\Enum\BaseEnumRoutable;
/**
* @method static self credit()
* @method static self debit()
*/
class BalanceOperation extends BaseEnumRoutable
{
/**
* Enum values
*
* @return array
*/
protected static function values(): array
{
return [
'credit' => 0,
'debit' => 1
];
}
/**
* Enum labels
*
* @return array
*/
protected static function labels(): array
{
return [
'credit' => trans('Créditer un compte'),
'debit' => trans('Débiter un compte')
];
}
}

View file

@ -0,0 +1,21 @@
<?php
namespace App\Enums\Credit;
use App\Traits\Enums\BaseEnum;
enum BalanceOperationEnum: int
{
use BaseEnum;
case credit = 0;
case debit = 1;
/**
* Optionnal labels definition
*/
private const LABELS = [
self::credit->name => "Créditer un compte",
self::debit->name => "Débiter un compte",
];
}

View file

@ -1,41 +0,0 @@
<?php
namespace App\Enums\Credit;
use Kwaadpepper\Enum\BaseEnumRoutable;
/**
* @method static self pending()
* @method static self accepted()
* @method static self refused()
*/
class EstimationStatus extends BaseEnumRoutable
{
/**
* Enum values
*
* @return array
*/
protected static function values(): array
{
return [
'pending' => 0,
'accepted' => 1,
'refused' => 2
];
}
/**
* Enum labels
*
* @return array
*/
protected static function labels(): array
{
return [
'pending' => trans('En attente'),
'accepted' => trans('Acceptée'),
'refused' => trans('Refusée'),
];
}
}

View file

@ -0,0 +1,23 @@
<?php
namespace App\Enums\Credit;
use App\Traits\Enums\BaseEnum;
enum EstimationStatusEnum: int
{
use BaseEnum;
case pending = 0;
case accepted = 1;
case refused = 2;
/**
* Optionnal labels definition
*/
private const LABELS = [
self::pending->name => "En attente",
self::accepted->name => "Acceptée",
self::refused->name => "Refusée",
];
}

View file

@ -1,50 +0,0 @@
<?php
namespace App\Enums;
use Kwaadpepper\Enum\BaseEnumRoutable;
/**
* @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 BaseEnumRoutable
{
/**
* Enum values
*
* @return array
*/
protected static function values(): array
{
return [
'collectionNeeds' => 0,
'specifications' => 1,
'quotation' => 2,
'tests' => 3,
'informations' => 4,
'feedback' => 5
];
}
/**
* Enum labels
*
* @return array
*/
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'),
];
}
}

View file

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

View file

@ -1,90 +0,0 @@
<?php
namespace App\Enums;
use Kwaadpepper\Enum\BaseEnumRoutable;
/**
* @method static self primary()
* @method static self secondary()
* @method static self success()
* @method static self danger()
* @method static self warning()
* @method static self info()
* @method static self light()
* @method static self dark()
* @method static self white()
*/
class InfoColors extends BaseEnumRoutable
{
/**
* Enum values
*
* @return array
*/
protected static function values(): array
{
return [
'primary' => 0,
'secondary' => 1,
'success' => 2,
'danger' => 3,
'warning' => 4,
'info' => 5,
'light' => 6,
'dark' => 7,
'white' => 8
];
}
/**
* Enum labels
*
* @return array
*/
protected static function labels(): array
{
return [
'primary' => trans('Primary'),
'secondary' => trans('Secondary'),
'success' => trans('Success'),
'danger' => trans('Danger'),
'warning' => trans('Warning'),
'info' => trans('Info'),
'light' => trans('Light'),
'dark' => trans('Dark'),
'white' => trans('white')
];
}
/**
* Enum classes
*
* @return array
*/
protected static function classes(): array
{
return [
'primary' => 'primary',
'secondary' => 'secondary',
'success' => 'success',
'danger' => 'danger',
'warning' => 'warning',
'info' => 'info',
'light' => 'light',
'dark' => 'dark',
];
}
/**
* @param string $attribute
* @return integer|string
*/
public function __get(string $attribute)
{
if ($attribute === 'class') {
return $this->classes()[$this->getDefinition()];
}
return parent::__get($attribute);
}
}

View file

@ -0,0 +1,53 @@
<?php
namespace App\Enums\Informations;
use App\Traits\Enums\BaseEnum;
enum InfoColorsEnum: int
{
use BaseEnum;
case primary = 0;
case secondary = 1;
case success = 2;
case danger = 3;
case warning = 4;
case info = 5;
case light = 6;
case dark = 7;
/**
* Optionnal labels definition
*/
private const CLASSES = [
self::primary->name => "primary",
self::secondary->name => "secondary",
self::success->name => "success",
self::danger->name => "danger",
self::warning->name => "warning",
self::info->name => "info",
self::light->name => "light",
self::dark->name => "dark",
];
/**
* Get Class
*
* @return string
*/
public function class(): string
{
return self::CLASSES[$this->name];
}
/**
* Get enum classes
*
* @return array<string>
*/
public static function toClasses(): array
{
return self::CLASSES;
}
}

View file

@ -1,73 +0,0 @@
<?php
namespace App\Enums\Invoice;
use Kwaadpepper\Enum\BaseEnumRoutable;
/**
* @method static self web()
* @method static self seo()
* @method static self package()
* @method static self arbitrary()
*/
class TaskType extends BaseEnumRoutable
{
/**
* Enum values
*
* @return array
*/
protected static function values(): array
{
return [
'web' => 1,
'seo' => 2,
'package' => 3,
'arbitrary' => 4,
];
}
/**
* Enum labels
*
* @return array
*/
protected static function labels(): array
{
return [
'web' => trans('Web'),
'seo' => trans('SEO'),
'package' => trans('Forfait'),
'arbitrary' => trans('Libre'),
];
}
/**
* Enum prices
*
* @return array<string,int>
*/
protected static function prices(): array
{
return [
'web' => 500,
'seo' => 690,
// * Linked to packages table
'package' => 0,
// * Arbitrary number
'arbitrary' => 0,
];
}
/**
* @param string $attribute
* @return integer|string
*/
public function __get(string $attribute)
{
if ($attribute === 'price') {
return $this->prices()[$this->getDefinition()];
}
return parent::__get($attribute);
}
}

View file

@ -0,0 +1,57 @@
<?php
namespace App\Enums\Invoice;
use App\Traits\Enums\BaseEnum;
enum TaskTypeEnum: int
{
use BaseEnum;
case web = 1;
case seo = 2;
case package = 3;
case arbitrary = 4;
/**
* Optionnal labels definition
*/
private const LABELS = [
self::web->name => "Web",
self::seo->name => "SEO",
self::package->name => "Forfait",
self::arbitrary->name => "Libre",
];
/**
* Custom added prices definition
*/
private const PRICES = [
self::web->name => 500,
self::seo->name => 690,
// * Linked to packages table
self::package->name => 0,
// * Arbitrary number
self::arbitrary->name => 0,
];
/**
* Get Price
*
* @return string
*/
public function price(): string
{
return self::PRICES[$this->name];
}
/**
* Get enum prices
*
* @return array<string>
*/
public static function toPrices(): array
{
return self::PRICES;
}
}

View file

@ -0,0 +1,16 @@
<?php
namespace App\Enums;
use App\Traits\Enums\BaseEnum;
enum ItemsPerPaginationEnum: int
{
use BaseEnum;
case five = 5;
case twelve = 12;
case twentytwo = 25;
case fifty = 50;
case onehundred = 100;
}

View file

@ -1,44 +0,0 @@
<?php
namespace App\Enums;
use Kwaadpepper\Enum\BaseEnumRoutable;
/**
* @method static self weak()
* @method static self stable()
* @method static self high()
* @method static self overload()
*/
class LoadLevel extends BaseEnumRoutable
{
/**
* Enum values
*
* @return array
*/
protected static function values(): array
{
return [
'weak' => 0,
'stable' => 1,
'high' => 2,
'overload' => 3
];
}
/**
* Enum labels
*
* @return array
*/
protected static function labels(): array
{
return [
'weak' => trans('Faible'),
'stable' => trans('Stable'),
'high' => trans('Élevée'),
'overload' => trans('Surcharge')
];
}
}

View file

@ -1,47 +0,0 @@
<?php
namespace App\Enums\MacroSchedule;
use Kwaadpepper\Enum\BaseEnum;
/**
* @method static self conception()
* @method static self development()
* @method static self recipe()
* @method static self production()
* @method static self meeting()
*/
final class Activity extends BaseEnum
{
/**
* Enum values
*
* @return array
*/
protected static function values(): array
{
return [
'conception' => 0,
'development' => 1,
'recipe' => 2,
'production' => 3,
'meeting' => 4
];
}
/**
* Enum labels
*
* @return array
*/
protected static function labels(): array
{
return [
'conception' => trans('Conception / Rédaction'),
'development' => trans('Développement'),
'recipe' => trans('Mise en recette'),
'production' => trans('Mise en production'),
'meeting' => trans('Réunion')
];
}
}

View file

@ -1,38 +0,0 @@
<?php
namespace App\Enums;
use Kwaadpepper\Enum\BaseEnumRoutable;
/**
* @method static self private()
* @method static self public()
*/
class MessageType extends BaseEnumRoutable
{
/**
* Enum values
*
* @return array
*/
protected static function values(): array
{
return [
'private' => 1,
'public' => 2
];
}
/**
* Enum labels
*
* @return array
*/
protected static function labels(): array
{
return [
'private' => trans('Privé'),
'public' => trans('Public'),
];
}
}

View file

@ -0,0 +1,21 @@
<?php
namespace App\Enums;
use App\Traits\Enums\BaseEnum;
enum MessageTypeEnum: int
{
use BaseEnum;
case private = 1;
case public = 2;
/**
* Optionnal labels definition
*/
private const LABELS = [
self::private->name => "Privé",
self::public->name => "Public",
];
}

View file

@ -1,57 +0,0 @@
<?php
namespace App\Enums\Planning;
use Kwaadpepper\Enum\BaseEnumRoutable;
/**
* This is an enumeration class,
* the following methods are its possible values
*
* @method static self support()
* @method static self rnd()
* @method static self dev()
* @method static self projects()
* @method static self management()
* @method static self absence()
* @method static self leaddev()
*
*/
class ActivityType extends BaseEnumRoutable
{
/**
* Enum labels
*
* @return array
*/
public static function labels()
{
return [
'support' => trans('Support'),
'rnd' => trans('R&D'),
'dev' => trans('Développement/Facturable'),
'projects' => trans('Projets & Réunions'),
'management' => trans('Organisation management'),
'absence' => trans('Absence'),
'leaddev' => trans('Lead Dev')
];
}
/**
* Enum colors
*
* @return array
*/
public static function colors(): array
{
return [
'support' => '#c6e0b4',
'rnd' => '#b4c6e7',
'dev' => '#00b0f0',
'projects' => '#ffe699',
'management' => '#f4b084',
'absence' => '#aeaaaa',
'leaddev' => '#ff7979'
];
}
}

View file

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

View file

@ -1,50 +0,0 @@
<?php
namespace App\Enums\Planning;
use App\Models\Project;
use App\Models\Site;
use App\Models\Ticket;
use Kwaadpepper\Enum\BaseEnumRoutable;
/**
* Décrit à quel modèle est lié
* la cellule
*
* @method static self ticket()
* \App\Models\Ticket
* @method static self site()
* \App\Models\Site
* @method static self project()
* \App\Models\Project
*/
class CellModel extends BaseEnumRoutable
{
/**
* Enum values
*
* @return array
*/
protected static function values(): array
{
return [
'ticket' => (new Ticket())->getTable(),
'site' => (new Site())->getTable(),
'project' => (new Project())->getTable(),
];
}
/**
* Enum labels
*
* @return array
*/
protected static function labels(): array
{
return [
'ticket' => trans('Ticket'),
'site' => trans('Site'),
'project' => trans('Projet')
];
}
}

View file

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

View file

@ -1,56 +0,0 @@
<?php
namespace App\Enums\Planning;
use Kwaadpepper\Enum\BaseEnumRoutable;
/**
* Décrit le type d'activitée que représente
* la cellule
*
* @method static self support()
* @method static self rnd()
* @method static self dev()
* @method static self projects()
* @method static self management()
* @method static self absence()
* @method static self leaddev()
*/
class CellType extends BaseEnumRoutable
{
/**
* Enum values
*
* @return array
*/
protected static function values(): array
{
return [
'support' => '#c6e0b4',
'rnd' => '#b4c6e7',
'dev' => '#00b0f0',
'projects' => '#ffe699',
'management' => '#f4b084',
'absence' => '#aeaaaa',
'leaddev' => '#ff7979'
];
}
/**
* Enum labels
*
* @return array
*/
protected static function labels(): array
{
return [
'support' => trans('Support'),
'rnd' => trans('R&D'),
'dev' => trans('Développement/Facturable'),
'projects' => trans('Projets & Réunions'),
'management' => trans('Organisation management'),
'absence' => trans('Absence'),
'leaddev' => trans('Lead Dev')
];
}
}

View file

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

View file

@ -1,58 +0,0 @@
<?php
namespace App\Enums\Planning;
use Kwaadpepper\Enum\BaseEnumRoutable;
/**
* Décrit à quel moment de la journée appartient la cellule
*
* @method static self matin1()
* @method static self matin2()
* @method static self matin3()
* @method static self matin4()
* @method static self apresmidi1()
* @method static self apresmidi2()
* @method static self apresmidi3()
* @method static self apresmidi4()
*/
class TableRow extends BaseEnumRoutable
{
/**
* Enum values
*
* @return array
*/
protected static function values(): array
{
return [
'matin1' => 1,
'matin2' => 2,
'matin3' => 3,
'matin4' => 4,
'apresmidi1' => 5,
'apresmidi2' => 6,
'apresmidi3' => 7,
'apresmidi4' => 8,
];
}
/**
* Enum labels
*
* @return array
*/
protected static function labels(): array
{
return [
'matin1' => trans('Matin 1'),
'matin2' => trans('Matin 2'),
'matin3' => trans('Matin 3'),
'matin4' => trans('Matin 4'),
'apresmidi1' => trans('Après-midi 1'),
'apresmidi2' => trans('Après-midi 2'),
'apresmidi3' => trans('Après-midi 3'),
'apresmidi4' => trans('Après-midi 4'),
];
}
}

View file

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

View file

@ -1,53 +0,0 @@
<?php
namespace App\Enums;
use Kwaadpepper\Enum\BaseEnum;
/**
* @method static self new()
* @method static self specification()
* @method static self validated()
* @method static self development()
* @method static self recipe()
* @method static self production()
* @method static self finished()
*/
final class ProjectStatus extends BaseEnum
{
/**
* Enum values
*
* @return array
*/
protected static function values(): array
{
return [
'new' => 0,
'specification' => 1,
'validated' => 2,
'development' => 3,
'recipe' => 4,
'production' => 5,
'finished' => 6
];
}
/**
* Enum labels
*
* @return array
*/
protected static function labels(): array
{
return [
'new' => trans('Nouveau'),
'specification' => trans('Spécifications'),
'validated' => trans('Validé'),
'development' => trans('En développement'),
'recipe' => trans('En recettage'),
'production' => trans('En production'),
'finished' => trans('Terminé')
];
}
}

View file

@ -0,0 +1,31 @@
<?php
namespace App\Enums\Projects;
use App\Traits\Enums\BaseEnum;
enum ProjectStatusEnum: int
{
use BaseEnum;
case new = 0;
case specification = 1;
case validated = 2;
case development = 3;
case recipe = 4;
case production = 5;
case finished = 6;
/**
* Optionnal labels definition
*/
private const LABELS = [
self::new->name => "Nouveau",
self::specification->name => "Spécifications",
self::validated->name => "Validé",
self::development->name => "En développement",
self::recipe->name => "En recettage",
self::production->name => "En production",
self::finished->name => "Terminé",
];
}

View file

@ -1,41 +0,0 @@
<?php
namespace App\Enums;
use Kwaadpepper\Enum\BaseEnumRoutable;
/**
* @method static self developper()
* @method static self admin()
* @method static self client()
*/
class Role extends BaseEnumRoutable
{
/**
* Enum values
*
* @return array
*/
protected static function values(): array
{
return [
'developper' => 0,
'admin' => 1,
'client' => 2
];
}
/**
* Enum labels
*
* @return array
*/
protected static function labels(): array
{
return [
'developper' => trans('Developpeur'),
'admin' => trans('Administrateur'),
'client' => trans('Client')
];
}
}

View file

@ -1,95 +0,0 @@
<?php
namespace App\Enums;
use Kwaadpepper\Enum\BaseEnumRoutable;
/**
* @method static self new()
* Nouveau ticket
* @method static self estimateTodo()
* Devis à faire.
* @method static self takenInAccount()
* Nouveau ticket à été pris en charge
* @method static self waiting()
* On attend que le client réponde dans le ticket
* @method static self waitingValidation()
* On attend que le client valide l'estimation
* @method static self recette()
* Est mis en recette
* @method static self production()
* Est mis en production
* @method static self archived()
* Ticket fermé
*/
class TicketStatus extends BaseEnumRoutable
{
/**
* Enum values
*
* @return array
*/
protected static function values(): array
{
return [
'new' => 1,
'estimateTodo' => 2,
'takenInAccount' => 3,
'waiting' => 4,
'waitingValidation' => 5,
'recette' => 6,
'production' => 7,
'archived' => 8,
];
}
/**
* Enum labels
*
* @return array
*/
protected static function labels(): array
{
return [
'new' => trans('Nouveau'),
'estimateTodo' => trans('Devis à faire'),
'takenInAccount' => trans('Pris en compte'),
'waiting' => trans('En attente de réponse'),
'waitingValidation' => trans('En attente de validation'),
'recette' => trans('En recettage'),
'production' => trans('En production'),
'archived' => trans('Archivé'),
];
}
/**
* Enum classes
*
* @return array
*/
protected static function classes(): array
{
return [
'new' => 'text-danger',
'estimateTodo' => 'text-info',
'takenInAccount' => 'text-info',
'waiting' => 'text-white bg-danger',
'waitingValidation' => 'text-warning bg-danger',
'recette' => 'text-primary',
'production' => 'text-success',
'archived' => 'text-secondary',
];
}
/**
* @param string $attribute
* @return integer|string
*/
public function __get(string $attribute)
{
if ($attribute === 'class') {
return $this->classes()[$this->getDefinition()];
}
return parent::__get($attribute);
}
}

View file

@ -1,79 +0,0 @@
<?php
namespace App\Enums;
use Kwaadpepper\Enum\BaseEnumRoutable;
/**
* @method static self bug()
* @method static self evolution()
* @method static self br()
* @method static self newsletter()
* @method static self qrcode()
* @method static self advice()
*/
class TicketTypeEnum extends BaseEnumRoutable
{
/**
* Enum values
*
* @return array
*/
protected static function values(): array
{
return [
'bug' => 0,
'evolution' => 1,
'br' => 2,
'newsletter' => 3,
'qrcode' => 4,
'advice' => 5
];
}
/**
* Enum labels
*
* @return array
*/
protected static function labels(): array
{
return [
'bug' => trans('Bug'),
'evolution' => trans('Évolution'),
'br' => trans('Demande BR'),
'newsletter' => trans('Demande newsletter'),
'qrcode' => trans('Demande de QR Code'),
'advice' => trans('Conseil - Accompagnement')
];
}
/**
* Enum classes
*
* @return array
*/
protected static function classes(): array
{
return [
'bug' => 'bg-danger',
'evolution' => 'bg-success',
'br' => 'bg-primary',
'newsletter' => 'bg-warning',
'qrcode' => 'bg-secondary',
'advice' => 'bg-info'
];
}
/**
* @param string $attribute
* @return integer|string
*/
public function __get(string $attribute)
{
if ($attribute === 'class') {
return $this->classes()[$this->getDefinition()];
}
return parent::__get($attribute);
}
}

View file

@ -0,0 +1,67 @@
<?php
namespace App\Enums\Tickets;
use App\Traits\Enums\BaseEnum;
enum TicketStatusEnum: int
{
use BaseEnum;
case new = 1;
case estimateTodo = 2;
case takenInAccount = 3;
case waiting = 4;
case waitingValidation = 5;
case recette = 6;
case production = 7;
case archived = 8;
/**
* Optionnal labels definition
*/
private const LABELS = [
self::new->name => "Nouveau",
self::estimateTodo->name => "Devis à faire",
self::takenInAccount->name => "Pris en compte",
self::waiting->name => "En attente de réponse",
self::waitingValidation->name => "En attente de validation",
self::recette->name => "En recettage",
self::production->name => "En production",
self::archived->name => "Archivé",
];
/**
* Custom added classes definition
*/
private const CLASSES = [
self::new->name => 'text-danger',
self::estimateTodo->name => 'text-info',
self::takenInAccount->name => 'text-info',
self::waiting->name => 'text-white bg-danger',
self::waitingValidation->name => 'text-warning bg-danger',
self::recette->name => 'text-primary',
self::production->name => 'text-success',
self::archived->name => 'text-secondary',
];
/**
* Get Class
*
* @return string
*/
public function class(): string
{
return self::CLASSES[$this->name];
}
/**
* Get enum classes
*
* @return array<string>
*/
public static function toClasses(): array
{
return self::CLASSES;
}
}

View file

@ -0,0 +1,61 @@
<?php
namespace App\Enums\Tickets;
use App\Traits\Enums\BaseEnum;
enum TicketTypeEnum: int
{
use BaseEnum;
case bug = 0;
case evolution = 1;
case br = 2;
case newsletter = 3;
case qrcode = 4;
case advice = 5;
/**
* Optionnal labels definition
*/
private const LABELS = [
self::bug->name => "Bug",
self::evolution->name => "Évolution",
self::br->name => "Demande BR",
self::newsletter->name => "Demande newsletter",
self::qrcode->name => "Demande de QR Code",
self::advice->name => "Conseil - Accompagnement",
];
/**
* Custom added classes definition
*/
private const CLASSES = [
self::bug->name => "bg-danger",
self::evolution->name => "bg-success",
self::br->name => "bg-primary",
self::newsletter->name => "bg-warning",
self::qrcode->name => "bg-secondary",
self::advice->name => "bg-info",
];
/**
* Get Class
*
* @return string
*/
public function class(): string
{
return self::CLASSES[$this->name];
}
/**
* Get enum classes
*
* @return array<string>
*/
public static function toClasses(): array
{
return self::CLASSES;
}
}

View file

@ -0,0 +1,23 @@
<?php
namespace App\Enums\Users;
use App\Traits\Enums\BaseEnum;
enum RoleEnum: int
{
use BaseEnum;
case developper = 0;
case admin = 1;
case client = 2;
/**
* Optionnal labels definition
*/
private const LABELS = [
self::developper->name => "Developpeur",
self::admin->name => "Administrateur",
self::client->name => "Client",
];
}

View file

@ -1,29 +0,0 @@
<?php
namespace App\Events;
use App\Models\File;
use App\Models\User;
class FileCreated extends Loggable
{
/** @var \App\Models\File */
public $file;
/**
* Create a new event instance.
*
* @param \App\Models\File $file
* @param \App\Models\User $user
* @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
]);
}
}

View file

@ -1,33 +0,0 @@
<?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 \App\Models\User */
public $user;
/** @var string */
public $message = '';
/**
* Create a new event instance.
*
* @param \App\Models\User $user
* @return void
*/
public function __construct(User $user)
{
$this->user = $user;
$this->message = trans(':username did someting', [
'username' => $user->name
]);
}
}

View file

@ -1,29 +0,0 @@
<?php
namespace App\Events;
use App\Models\Project;
use App\Models\User;
class ProjectUpdated extends Loggable
{
/** @var \App\Models\Project */
public $project;
/**
* Create a new event instance.
*
* @param \App\Models\Project $project
* @param \App\Models\User $user
* @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

@ -1,29 +0,0 @@
<?php
namespace App\Events;
use App\Models\Site;
use App\Models\User;
class SiteUpdated extends Loggable
{
/** @var \App\Models\Site */
public $site;
/**
* Create a new event instance.
*
* @param \App\Models\Site $site
* @param \App\Models\User $user
* @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,7 +2,7 @@
namespace App\Events;
use App\Enums\TicketStatus;
use App\Enums\Tickets\TicketStatusEnum;
use App\Models\Ticket;
use App\Models\User;
use Illuminate\Broadcasting\InteractsWithSockets;
@ -21,7 +21,7 @@ class TicketStatusChanged
/** @var \App\Models\User */
public $user;
/** @var \App\Enums\TicketStatus */
/** @var \App\Enums\Tickets\TicketStatusEnum */
public $status;
/** @var string */
@ -36,17 +36,17 @@ class TicketStatusChanged
/**
* Create a new event instance.
*
* @param \App\Models\Ticket $ticket
* @param \App\Enums\TicketStatus $status
* @param \App\Models\User|null $user
* @param string|null $message
* @param boolean $is_private
* @param boolean $status_changed
* @param \App\Models\Ticket $ticket
* @param \App\Enums\Tickets\TicketStatusEnum $status
* @param \App\Models\User|null $user
* @param string|null $message
* @param boolean $is_private
* @param boolean $status_changed
* @return void
*/
public function __construct(
Ticket $ticket,
TicketStatus $status,
TicketStatusEnum $status,
User $user = null,
string $message = null,
bool $is_private = false,

View file

@ -6,20 +6,27 @@ use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
class Handler extends ExceptionHandler
{
/**
* A list of exception types with their corresponding custom log levels.
*
* @var array<class-string<\Throwable>, \Psr\Log\LogLevel::*>
*/
protected $levels = [];
/**
* A list of the exception types that are not reported.
*
* @var array
* @var array<int, class-string<\Throwable>>
*/
protected $dontReport = [
];
protected $dontReport = [];
/**
* A list of the inputs that are never flashed for validation exceptions.
*
* @var array
* @var array<int, string>
*/
protected $dontFlash = [
'current_password',
'password',
'password_confirmation',
];

View file

@ -1,6 +1,6 @@
<?php
namespace App\Http\Controllers\Auth;
namespace App\Http\Controllers\Bo\Auth;
use App\Http\Controllers\Controller;
use App\Providers\RouteServiceProvider;

View file

@ -1,6 +1,6 @@
<?php
namespace App\Http\Controllers\Auth;
namespace App\Http\Controllers\Bo\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\SendsPasswordResetEmails;
@ -16,6 +16,6 @@ class ForgotPasswordController extends Controller
*/
public function __construct()
{
$this->middleware('guest:web');
$this->middleware('guest:backend');
}
}

View file

@ -1,6 +1,6 @@
<?php
namespace App\Http\Controllers\Auth;
namespace App\Http\Controllers\Bo\Auth;
use App\Http\Controllers\Controller;
use App\Providers\RouteServiceProvider;
@ -24,6 +24,6 @@ class LoginController extends Controller
*/
public function __construct()
{
$this->middleware('guest:web')->except('logout');
$this->middleware('guest:backend')->except('logout');
}
}

View file

@ -1,6 +1,6 @@
<?php
namespace App\Http\Controllers\Auth;
namespace App\Http\Controllers\Bo\Auth;
use App\Http\Controllers\Controller;
use App\Providers\RouteServiceProvider;
@ -30,7 +30,7 @@ class ResetPasswordController extends Controller
'email' => 'required|email',
'password' => [
'required', 'confirmed', Password::min(8)
->mixedCase()
->mixedCase()
->letters()
->numbers()
->symbols()

View file

@ -0,0 +1,186 @@
<?php
namespace App\Http\Controllers\Bo;
use App\Http\Controllers\Controller;
use App\Http\Requests\Bo\Brands\StoreBrandRequest;
use App\Http\Requests\Bo\Brands\UpdateBrandRequest;
use App\Models\Brand;
use App\Models\Site;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
class BrandController 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 $brandModels */
$brandModels = Brand::query();
/** @var string $search Search field */
$search = $request->search;
if ($search) {
$this->searchQuery(
$brandModels,
$search,
null,
'name',
);
}
$searchFields = trans('Nom');
/** Sort columns with a query */
$this->sortQuery($brandModels);
/** Custom pagination */
$brandModels = $this->customPaginate($brandModels, $request->pagination);
return view('bo.pages.brands.index', compact('brandModels', 'search', 'searchFields'));
}
/**
* Show model action.
*
* @param \App\Models\Brand $brand
* @return \Illuminate\Contracts\View\View
*/
public function show(Brand $brand): \Illuminate\Contracts\View\View
{
return view('bo.pages.brands.show', ['brandModel' => $brand]);
}
/**
* Show the form for creating a new resource.
*
* @param \App\Models\Brand $brand
* @return \Illuminate\Contracts\View\View
*/
public function create(Brand $brand): \Illuminate\Contracts\View\View
{
$siteModels = Site::orderBy('name', 'ASC')->get();
return view('bo.pages.brands.create', [
'brandModel' => $brand,
'siteModels' => $siteModels
]);
}
/**
* Store a newly created resource in storage.
*
* @param \App\Http\Requests\Bo\Brands\StoreBrandRequest $request
* @return \Illuminate\Http\RedirectResponse
*/
public function store(StoreBrandRequest $request): \Illuminate\Http\RedirectResponse
{
return DB::transaction(function () use ($request) {
$brand = new Brand();
$brand->fill($request->safe()->except('sites'));
if ($brand->saveOrFail()) {
$brand->updateSites($brand);
return redirect()
->route('bo.brands.edit', $brand)
->with('success', trans(
'crud.messages.has_been_created',
['model' => Str::singular(trans('models.classes.brands'))]
));
}
return redirect()
->back()
->with('error', trans(
'crud.messages.cannot_be_created',
['model' => Str::singular(trans('models.classes.brands'))]
));
});
}
/**
* Show the form for editing the specified resource.
*
* @param \App\Models\Brand $brand
* @return \Illuminate\Contracts\View\View
*/
public function edit(Brand $brand): \Illuminate\Contracts\View\View
{
$siteModels = Site::orderBy('name', 'ASC')->get();
return view('bo.pages.brands.edit', [
'brandModel' => $brand,
'siteModels' => $siteModels
]);
}
/**
* Update the specified resource in storage.
*
* @param \App\Http\Requests\Bo\Brands\UpdateBrandRequest $request
* @param \App\Models\Brand $brand
* @return \Illuminate\Http\RedirectResponse
*/
public function update(UpdateBrandRequest $request, Brand $brand): \Illuminate\Http\RedirectResponse
{
return DB::transaction(function () use ($request, $brand) {
$brand->fill($request->safe()->except(['sites']));
$brand->updateSites($brand);
if ($brand->saveOrFail()) {
return redirect()
->route('bo.brands.edit', $brand)
->with('success', trans(
'crud.messages.has_been_updated',
['model' => Str::singular(trans('models.classes.brands'))]
));
}
return redirect()
->back()
->with('error', trans(
'crud.messages.cannot_be_updated',
['model' => Str::singular(trans('models.classes.brands'))]
));
});
}
/**
* Remove the specified resource from storage.
*
* @param \App\Models\Brand $brand
* @return \Illuminate\Http\RedirectResponse
*/
public function destroy(Brand $brand): \Illuminate\Http\RedirectResponse
{
return DB::transaction(function () use ($brand) {
if (count($brand->accounts)) {
return redirect()
->route('bo.brands.index')
->with('error', __(
':model n\'as pas pu être supprimé car elle est encore associée avec des Sites.',
['model' => Str::singular(trans('models.classes.brands'))]
));
} else {
$brand->deleteSites($brand);
if ($brand->deleteOrFail()) {
return redirect()
->route('bo.brands.index')
->with('success', __(
'crud.messages.has_been_deleted',
['model' => Str::singular(trans('models.classes.brands'))]
));
}
return redirect()
->back()
->with('error', __(
':crud.messages.cannot_be_deleted',
['model' => Str::singular(trans('models.classes.brands'))]
));
} //end if
});
}
}

View file

@ -0,0 +1,166 @@
<?php
namespace App\Http\Controllers\Bo;
use App\Http\Controllers\Controller;
use App\Http\Requests\Bo\Companies\StoreCompanyRequest;
use App\Http\Requests\Bo\Companies\UpdateCompanyRequest;
use App\Models\Company;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
class CompanyController 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 $companyModels */
$companyModels = Company::query();
/** @var string $search Search field */
$search = $request->search;
if ($search) {
$this->searchQuery(
$companyModels,
$search,
null,
'name'
);
}
$searchFields = trans('Nom');
/** Sort columns with a query */
$this->sortQuery($companyModels);
/** Custom pagination */
$companyModels = $this->customPaginate($companyModels, $request->pagination);
return view('bo.pages.companies.index', compact('companyModels', 'search', 'searchFields'));
}
/**
* Show the form for creating a new resource.
*
* @param \App\Models\Company $company
* @return \Illuminate\Contracts\View\View
*/
public function create(Company $company): \Illuminate\Contracts\View\View
{
return view('bo.pages.companies.create', [
'companyModel' => $company,
]);
}
/**
* Store a newly created resource in storage.
*
* @param \App\Http\Requests\Bo\Companies\StoreCompanyRequest $request
* @return \Illuminate\Http\RedirectResponse
*/
public function store(StoreCompanyRequest $request): \Illuminate\Http\RedirectResponse
{
return DB::transaction(function () use ($request) {
$company = new Company();
$company->fill($request->validated());
if ($company->saveOrFail()) {
return redirect()
->route('bo.companies.edit', $company)
->with('success', trans(
'crud.messages.has_been_created',
['model' => Str::singular(trans('models.classes.companies'))]
));
}
return redirect()
->back()
->with('error', trans(
'crud.messages.cannot_be_created',
['model' => Str::singular(trans('models.classes.companies'))]
));
});
}
/**
* Show the form for editing the specified resource.
*
* @param \App\Models\Company $company
* @return \Illuminate\Contracts\View\View
*/
public function edit(Company $company): \Illuminate\Contracts\View\View
{
return view('bo.pages.companies.edit', [
'companyModel' => $company
]);
}
/**
* Update the specified resource in storage.
*
* @param \App\Http\Requests\Bo\Companies\UpdateCompanyRequest $request
* @param \App\Models\Company $company
* @return \Illuminate\Http\RedirectResponse
*/
public function update(UpdateCompanyRequest $request, Company $company): \Illuminate\Http\RedirectResponse
{
return DB::transaction(function () use ($request, $company) {
$company->fill($request->validated());
if ($company->saveOrFail()) {
return redirect()
->route('bo.companies.edit', $company)
->with('success', trans(
'crud.messages.has_been_updated',
['model' => Str::singular(trans('models.classes.companies'))]
));
} //end if
return redirect()
->back()
->with('error', trans(
'crud.messages.cannot_be_updated',
['model' => Str::singular(trans('models.classes.companies'))]
));
});
}
/**
* Remove the specified resource from storage.
*
* @param \App\Models\Company $company
* @return \Illuminate\Http\RedirectResponse
*/
public function destroy(Company $company): \Illuminate\Http\RedirectResponse
{
return DB::transaction(function () use ($company) {
if (count($company->invoices()->get()->toArray())) {
return redirect()
->back()
->with('error', trans(
'crud.messages.cannot_be_deleted_relationship',
[
'model' => Str::singular(trans('models.classes.companies')),
'relationship' => trans('models.classes.invoices')
]
));
}
if ($company->deleteOrFail()) {
return redirect()
->route('bo.companies.index')
->with('success', trans(
'crud.messages.has_been_deleted',
['model' => Str::singular(trans('models.classes.companies'))]
));
}
return redirect()
->back()
->with('error', trans(
'crud.messages.cannot_be_deleted',
['model' => Str::singular(trans('models.classes.companies'))]
));
});
}
}

View file

@ -0,0 +1,107 @@
<?php
namespace App\Http\Controllers\Bo\Credit;
use App\Http\Controllers\Controller;
use App\Http\Requests\Bo\CreditAccounts\StoreCreditAccountRequest;
use App\Models\Brand;
use App\Models\Credit\Account;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
class AccountController 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 \App\Models\User $user */
$user = auth()->user();
if (!$user->isAdmin()) {
$brandModels = $user->brands()->pluck('id');
} else {
$brandModels = $request->brand ?? Brand::all()->pluck('id');
}
/** @var \Illuminate\Database\Eloquent\Builder $credit_accountModels */
$credit_accountModels = Account::query()->whereIn('brand_id', $brandModels);
/** @var string $search Search field */
$search = $request->search;
if ($search) {
$this->searchQuery(
$credit_accountModels,
$search,
null,
'label',
'balance',
);
}
$searchFields = trans('Label, solde');
/** Sort columns with a query */
$this->sortQuery($credit_accountModels);
/** Custom pagination */
$credit_accountModels = $this->customPaginate($credit_accountModels, $request->pagination);
return view('bo.pages.credit_accounts.index', compact(
'credit_accountModels',
'brandModels',
'search',
'searchFields'
));
}
/**
* Show the form for creating a new resource.
*
* @param \App\Models\Brand $brand
* @param \App\Models\Account $account
* @return \Illuminate\Contracts\View\View
*/
public function create(Brand $brand, Account $account): \Illuminate\Contracts\View\View
{
return view('bo.pages.credit_accounts.create', [
'brandModel' => $brand,
'credit_accountModel' => $account
]);
}
/**
* Store a newly created resource in storage.
*
* @param \App\Models\Brand $brand
* @param \App\Http\Requests\Bo\CreditAccounts\StoreCreditAccountRequest $request
* @return \Illuminate\Http\RedirectResponse
*/
public function store(Brand $brand, StoreCreditAccountRequest $request): \Illuminate\Http\RedirectResponse
{
return DB::transaction(function () use ($brand, $request) {
$credit_accountModel = new Account();
$credit_accountModel->brand_id = $brand->id;
$credit_accountModel->fill($request->validated());
if ($credit_accountModel->saveOrFail()) {
return redirect()
->route('bo.brands.credit_accounts.index', $brand)
->with('success', trans(
'crud.messages.has_been_created',
['model' => Str::singular(trans('models.classes.accounts'))]
));
}
return redirect()
->back()
->with('error', trans(
'crud.messages.cannot_be_created',
['model' => Str::singular(trans('models.classes.accounts'))]
));
});
}
}

View file

@ -0,0 +1,108 @@
<?php
namespace App\Http\Controllers\Bo\Credit;
use App\Enums\Credit\BalanceOperationEnum;
use App\Http\Controllers\Controller;
use App\Http\Requests\Bo\CreditLogs\StoreCreditLogRequest;
use App\Models\Brand;
use App\Models\Credit\Account;
use App\Models\Credit\CreditLog;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
class CreditLogController 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
{
$brandModel = $request->brand;
$credit_accountModel = $request->account;
/** @var \Illuminate\Database\Eloquent\Builder $credit_logModels */
$credit_logModels = CreditLog::query()->where('credit_account_id', $credit_accountModel->id);
/** @var string $search Search field */
$search = $request->search;
if ($search) {
$this->searchQuery(
$credit_logModels,
$search,
null,
'amount',
);
}
$searchFields = trans('Montant');
/** Sort columns with a query */
$this->sortQuery($credit_logModels);
/** Custom pagination */
$credit_logModels = $this->customPaginate($credit_logModels, $request->pagination);
return view('bo.pages.credit_logs.index', compact(
'credit_logModels',
'credit_accountModel',
'brandModel',
'search',
'searchFields'
));
}
/**
* Show the form for creating a new resource.
*
* @param \App\Models\Brand $brand
* @param \App\Models\Account $account
* @return \Illuminate\Contracts\View\View
*/
public function create(Brand $brand, Account $account): \Illuminate\Contracts\View\View
{
return view('bo.pages.credit_logs.create', [
'brandModel' => $brand,
'credit_accountModel' => $account
]);
}
/**
* Store a newly created resource in storage.
*
* @param \App\Models\Brand $brand
* @param \App\Models\Account $account
* @param \App\Http\Requests\Bo\CreditLogs\StoreCreditLogRequest $request
* @return \Illuminate\Http\RedirectResponse
*/
public function store(
Brand $brand,
Account $account,
StoreCreditLogRequest $request
): \Illuminate\Http\RedirectResponse {
return DB::transaction(function () use ($brand, $account, $request) {
$credit_logModel = new CreditLog();
$credit_logModel->credit_account_id = $request->account->id;
$credit_logModel->type = BalanceOperationEnum::credit;
$credit_logModel->fill($request->validated());
if ($credit_logModel->saveOrFail()) {
return redirect()
->route('bo.brands.credit_accounts.index', ['brand' => $brand, 'account' => $account])
->with('success', trans(
':model a été crédité',
['model' => Str::singular(trans('models.classes.accounts'))]
));
}
return redirect()
->back()
->with('error', trans(
':model ne peut être crédité',
['model' => Str::singular(trans('models.classes.accounts'))]
));
});
}
}

View file

@ -1,15 +1,15 @@
<?php
namespace App\Http\Controllers\Credit;
namespace App\Http\Controllers\Bo\Credit;
use App\Enums\Credit\EstimationStatus;
use App\Enums\TicketStatus;
use App\Enums\Credit\EstimationStatusEnum;
use App\Enums\Tickets\TicketStatusEnum;
use App\Events\NotifyAdmin;
use App\Events\NotifySubscriptions;
use App\Events\TicketStatusChanged;
use App\Http\Controllers\Controller;
use App\Http\Requests\Credit\AnswerEstimateRequest;
use App\Http\Requests\Credit\CreateEstimateRequest;
use App\Http\Requests\Bo\Credit\AnswerEstimateRequest;
use App\Http\Requests\Bo\Credit\CreateEstimateRequest;
use App\Models\Credit\Estimation;
use App\Models\Ticket;
use Illuminate\Support\Facades\DB;
@ -32,8 +32,8 @@ class EstimationController extends Controller
/**
* Create Ticket estimation
*
* @param \App\Http\Requests\Credit\CreateEstimateRequest $request
* @param \App\Models\Ticket $ticket
* @param \App\Http\Requests\Bo\Credit\CreateEstimateRequest $request
* @param \App\Models\Ticket $ticket
* @return \Illuminate\Http\RedirectResponse
*/
public function estimateSubmit(CreateEstimateRequest $request, Ticket $ticket)
@ -44,19 +44,19 @@ class EstimationController extends Controller
$estimate = new Estimation($request->validated());
$estimate->ticket()->associate($ticket);
$estimate->estimator()->associate($user);
$ticket->status = TicketStatus::waitingValidation();
$ticket->status = TicketStatusEnum::waitingValidation;
$ticket->saveQuietly();
if ($estimate->saveOrFail()) {
$message = sprintf(
'<b>%s</b> a modifié le statut en <b>%s</b>, Une estimation de %s jours à été ajoutée',
$user->name,
$ticket->status->label,
$ticket->status->label(),
\number_format(\floatval($request->amount), 1, ',', '')
);
event(new TicketStatusChanged($ticket, $ticket->status, $user));
event(new NotifySubscriptions($ticket, $message));
event(new NotifyAdmin($ticket, $message));
return response()->redirectToRoute('ticket.show', $ticket)
return response()->redirectToRoute('bo.ticket.show', $ticket)
->with('info', trans('L\'estimation à bien été ajouté'));
}
return \back();
@ -66,8 +66,8 @@ class EstimationController extends Controller
/**
* Answer ticket estimation
*
* @param \App\Http\Requests\Credit\AnswerEstimateRequest $request
* @param \App\Models\Ticket $ticket
* @param \App\Http\Requests\Bo\Credit\AnswerEstimateRequest $request
* @param \App\Models\Ticket $ticket
* @return \Illuminate\Http\RedirectResponse
*/
public function estimatePendingSubmit(AnswerEstimateRequest $request, Ticket $ticket)
@ -77,11 +77,11 @@ class EstimationController extends Controller
/** @var \App\Models\Credit\Estimation */
$estimation = $ticket->estimation;
if ($request->answer) {
$ticket->status = TicketStatus::takenInAccount();
$estimation->status = EstimationStatus::accepted();
$ticket->status = TicketStatusEnum::takenInAccount;
$estimation->status = EstimationStatusEnum::accepted;
} else {
$ticket->status = TicketStatus::archived();
$estimation->status = EstimationStatus::refused();
$ticket->status = TicketStatusEnum::archived;
$estimation->status = EstimationStatusEnum::refused;
}
$estimation->validator()->associate($user);
if ($estimation->saveOrFail() and $ticket->saveOrFail()) {
@ -89,14 +89,34 @@ class EstimationController extends Controller
'Une réponse à été fourni par %s pour l\'estimation du ticket n°%d : %s',
$user->name,
$ticket->id,
$estimation->status->label
$estimation->status->label()
);
event(new TicketStatusChanged($ticket, $ticket->status, $user));
event(new NotifySubscriptions($ticket, $message));
event(new NotifyAdmin($ticket, $message));
return response()->redirectToRoute('ticket.show', $ticket)
return response()->redirectToRoute('bo.ticket.show', $ticket)
->with('info', trans('Votre réponse à été enregistrée'));
}
return \back();
}
/**
* Handle submit and cancel an estimate on ticket
*
* @param \App\Models\Ticket $ticket
* @return \Illuminate\Http\RedirectResponse
*/
public function estimateCancelSubmit(Ticket $ticket)
{
$this->authorize('cancelEstimate', $ticket);
/** @var \App\Models\Credit\Estimation */
$estimation = $ticket->estimation;
$ticket->status = TicketStatusEnum::estimateTodo;
if ($estimation->deleteOrFail() and $ticket->saveOrFail()) {
return response()->redirectToRoute('bo.ticket.show', $ticket)
->with('info', trans('L\'estimation a été supprimée.'));
}
return \back();
}
}

View file

@ -1,23 +1,29 @@
<?php
namespace App\Http\Controllers;
namespace App\Http\Controllers\Bo;
use App\Http\Controllers\Controller;
use App\Models\Dutyhour;
use Illuminate\Contracts\View\View;
class HomeController extends Controller
class DashboardController extends Controller
{
/**
* Show Home page
*
* @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory
*/
public function home()
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();
$dutyhourModels = Dutyhour::where('date', '>', now()->modify('-1 day'))
->orderBy('date', 'asc')
->limit(10)
->get();
return view('home', compact('dutyhourModels'));
}
}

View file

@ -0,0 +1,157 @@
<?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

@ -0,0 +1,158 @@
<?php
namespace App\Http\Controllers\Bo;
use App\Http\Controllers\Controller;
use App\Http\Requests\Bo\Informations\StoreInformationRequest;
use App\Http\Requests\Bo\Informations\UpdateInformationRequest;
use App\Models\Information;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
class InformationController 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 $informationModels */
$informationModels = Information::query();
/** @var string $search Search field */
$search = $request->search;
if ($search) {
$this->searchQuery(
$informationModels,
$search,
null,
'title',
'message'
);
}
$searchFields = trans('Titre, message');
/** Sort columns with a query */
$this->sortQuery($informationModels);
/** Custom pagination */
$informationModels = $this->customPaginate($informationModels, $request->pagination);
return view('bo.pages.informations.index', compact('informationModels', 'search', 'searchFields'));
}
/**
* Show the form for creating a new resource.
*
* @param \App\Models\Information $information
* @return \Illuminate\Contracts\View\View
*/
public function create(Information $information): \Illuminate\Contracts\View\View
{
return view('bo.pages.informations.create', [
'informationModel' => $information
]);
}
/**
* Store a newly created resource in storage.
*
* @param \App\Http\Requests\Bo\Informations\StoreInformationRequest $request
* @return \Illuminate\Http\RedirectResponse
*/
public function store(StoreInformationRequest $request): \Illuminate\Http\RedirectResponse
{
return DB::transaction(function () use ($request) {
$information = new Information();
$information->fill($request->validated());
if ($information->saveOrFail()) {
return redirect()
->route('bo.informations.edit', $information)
->with('success', trans(
'crud.messages.has_been_created',
['model' => Str::singular(trans('models.classes.informations'))]
));
}
return redirect()
->back()
->with('error', trans(
'crud.messages.cannot_be_created',
['model' => Str::singular(trans('models.classes.informations'))]
));
});
}
/**
* Show the form for editing the specified resource.
*
* @param \App\Models\Information $information
* @return \Illuminate\Contracts\View\View
*/
public function edit(Information $information): \Illuminate\Contracts\View\View
{
return view('bo.pages.informations.edit', [
'informationModel' => $information,
]);
}
/**
* Update the specified resource in storage.
*
* @param \App\Http\Requests\Bo\Informations\UpdateInformationRequest $request
* @param \App\Models\Information $information
* @return \Illuminate\Http\RedirectResponse
* @ignore phpcs:disable Generic.Files.LineLength.TooLong
*/
public function update(UpdateInformationRequest $request, Information $information): \Illuminate\Http\RedirectResponse
{
// phpcs:enable
return DB::transaction(function () use ($request, $information) {
$information->fill($request->validated());
if ($information->saveOrFail()) {
return redirect()
->route('bo.informations.edit', $information)
->with('success', trans(
'crud.messages.has_been_updated',
['model' => Str::singular(trans('models.classes.informations'))]
));
} //end if
return redirect()
->back()
->with('error', trans(
'crud.messages.cannot_be_updated',
['model' => Str::singular(trans('models.classes.informations'))]
));
});
}
/**
* Remove the specified resource from storage.
*
* @param \App\Models\Information $information
* @return \Illuminate\Http\RedirectResponse
*/
public function destroy(Information $information): \Illuminate\Http\RedirectResponse
{
return DB::transaction(function () use ($information) {
if ($information->deleteOrFail()) {
return redirect()
->route('bo.informations.index')
->with('success', trans(
'crud.messages.has_been_deleted',
['model' => Str::singular(trans('models.classes.informations'))]
));
}
return redirect()
->back()
->with('error', trans(
':crud.messages.cannot_be_deleted',
['model' => Str::singular(trans('models.classes.informations'))]
));
});
}
}

View file

@ -0,0 +1,205 @@
<?php
namespace App\Http\Controllers\Bo;
use App\Http\Controllers\Controller;
use App\Http\Requests\Bo\Invoices\StoreInvoiceRequest;
use App\Http\Requests\Bo\Invoices\UpdateInvoiceRequest;
use App\Models\Company;
use App\Models\Invoice;
use App\Models\Package;
use App\Models\Site;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Gate;
use Illuminate\Support\Str;
class InvoiceController 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 $invoiceModels */
$invoiceModels = Invoice::query();
/** @var string $search Search field */
$search = $request->search;
if ($search) {
$this->searchQuery(
$invoiceModels,
$search,
null,
'firstname',
'lastname',
);
}
$searchFields = trans('Nom, Prénom');
/** Sort columns with a query */
$this->sortQuery($invoiceModels);
/** Custom pagination */
$invoiceModels = $this->customPaginate($invoiceModels, $request->pagination);
return view('bo.pages.invoices.index', compact('invoiceModels', 'search', 'searchFields'));
}
/**
* Show model action.
*
* @param \App\Models\Invoice $invoice
* @return \Illuminate\Contracts\View\View
*/
public function show(Invoice $invoice): \Illuminate\Contracts\View\View
{
return view('bo.pages.invoices.show', ['invoiceModel' => $invoice]);
}
/**
* Show the form for creating a new resource.
*
* @param \App\Models\Invoice $invoice
* @return \Illuminate\Contracts\View\View
*/
public function create(Invoice $invoice): \Illuminate\Contracts\View\View
{
$packageModels = Package::get();
$taskRowModel = Invoice::getTaskStructure();
$siteModels = Site::orderBy('name', 'ASC')->get();
$companyModels = Company::get();
return view('bo.pages.invoices.create', [
'invoiceModel' => $invoice,
'taskRowModel' => $taskRowModel,
'packageModels' => $packageModels,
'siteModels' => $siteModels,
'companyModels' => $companyModels,
]);
}
/**
* Store a newly created resource in storage.
*
* @param \App\Http\Requests\Bo\Invoices\StoreInvoiceRequest $request
* @return \Illuminate\Http\RedirectResponse
*/
public function store(StoreInvoiceRequest $request): \Illuminate\Http\RedirectResponse
{
return DB::transaction(function () use ($request) {
$invoice = new Invoice();
$invoice->fill($request->validated());
if ($invoice->saveOrFail()) {
return redirect()
->route('bo.invoices.edit', $invoice)
->with('success', trans(
'crud.messages.has_been_created',
['model' => Str::singular(trans('models.classes.invoices'))]
));
}
return redirect()
->back()
->with('error', trans(
'crud.messages.cannot_be_created',
['model' => Str::singular(trans('models.classes.invoices'))]
));
});
}
/**
* Edit model action.
*
* @param Invoice $invoice
* @return \Illuminate\Contracts\View\View
*/
public function edit(Invoice $invoice): \Illuminate\Contracts\View\View
{
$packageModels = Package::get();
$taskRowModel = Invoice::getTaskStructure();
$siteModels = Site::orderBy('name', 'ASC')->get();
$companyModels = Company::get();
return view('bo.pages.invoices.edit', [
'invoiceModel' => $invoice,
'taskRowModel' => $taskRowModel,
'packageModels' => $packageModels,
'siteModels' => $siteModels,
'companyModels' => $companyModels,
]);
}
/**
* Update the specified resource in storage.
*
* @param \App\Http\Requests\Bo\Invoices\UpdateInvoiceRequest $request
* @param \App\Models\Invoice $invoice
* @return \Illuminate\Http\RedirectResponse
*/
public function update(UpdateInvoiceRequest $request, Invoice $invoice): \Illuminate\Http\RedirectResponse
{
return DB::transaction(function () use ($request, $invoice) {
if (isset($invoice->signed_date)) {
$fields = $request->safe()->only('signed_date', 'sent_client_date', 'sent_accounting_date');
} else {
$fields = $request->validated();
}
$invoice->fill($fields);
if ($invoice->saveOrFail()) {
return redirect()
->route('bo.invoices.edit', $invoice)
->with('success', __(
'crud.messages.has_been_updated',
['model' => Str::singular(__('models.classes.invoices'))]
));
} //end if
return redirect()
->back()
->with('error', __(
'crud.messages.cannot_be_updated',
['model' => Str::singular(__('models.classes.invoices'))]
));
});
}
/**
* Download Invoice.
*
* @param \App\Models\Invoice $invoice
* @return \Illuminate\Http\RedirectResponse|\Symfony\Component\HttpFoundation\Response
*/
public function download(Invoice $invoice)
{
if (Gate::allows('isAdmin')) {
return $invoice->generateInvoice()
->stream(Str::slug(trans('Devis :appname :date - ref :ref', [
'appname' => config('app.name'),
'date' => $invoice->created_at->isoFormat('YYYY-MM-DD'),
'ref' => $invoice->ref,
])) . '.pdf');
}
return redirect()->route('bo.invoices.index')
->with('error', __('crud.messages.cannot_be_updated', [
'model' => __('models.classes.invoices')
]));
}
/**
* Get a paginate resource.
*
* @param \Illuminate\Http\Request $request
* @return Illuminate\Http\JsonResponse
*/
public function jsonPaginate(Request $request): \Illuminate\Http\JsonResponse
{
$model = $request->targetModel;
return DB::transaction(function () use ($model) {
$models = $model::orderBy('name', 'ASC')->paginate(12);
return \response()->json($models ?? 500);
});
}
}

View file

@ -0,0 +1,157 @@
<?php
namespace App\Http\Controllers\Bo;
use App\Http\Controllers\Controller;
use App\Http\Requests\Bo\Labels\StoreLabelRequest;
use App\Http\Requests\Bo\Labels\UpdateLabelRequest;
use App\Models\Label;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
class LabelController 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 $labelModels */
$labelModels = Label::query();
/** @var string $search Search field */
$search = $request->search;
if ($search) {
$this->searchQuery(
$labelModels,
$search,
null,
'name'
);
}
$searchFields = trans('Nom');
/** Sort columns with a query */
$this->sortQuery($labelModels);
/** Custom pagination */
$labelModels = $this->customPaginate($labelModels, $request->pagination);
return view('bo.pages.labels.index', compact('labelModels', 'search', 'searchFields'));
}
/**
* Show the form for creating a new resource.
*
* @param \App\Models\Label $label
* @return \Illuminate\Contracts\View\View
*/
public function create(Label $label): \Illuminate\Contracts\View\View
{
return view('bo.pages.labels.create', [
'labelModel' => $label
]);
}
/**
* Store a newly created resource in storage.
*
* @param \App\Http\Requests\Bo\Labels\StoreLabelRequest $request
* @return \Illuminate\Http\RedirectResponse
*/
public function store(StoreLabelRequest $request): \Illuminate\Http\RedirectResponse
{
return DB::transaction(function () use ($request) {
$label = new Label();
$label->fill($request->validated());
if ($label->saveOrFail()) {
return redirect()
->route('bo.labels.edit', $label)
->with('success', trans(
'crud.messages.has_been_created',
['model' => Str::singular(trans('models.classes.labels'))]
));
}
return redirect()
->back()
->with('error', trans(
'crud.messages.cannot_be_created',
['model' => Str::singular(trans('models.classes.labels'))]
));
});
}
/**
* Show the form for editing the specified resource.
*
* @param \App\Models\Label $label
* @return \Illuminate\Contracts\View\View
*/
public function edit(Label $label): \Illuminate\Contracts\View\View
{
return view('bo.pages.labels.edit', [
'labelModel' => $label,
]);
}
/**
* Update the specified resource in storage.
*
* @param \App\Http\Requests\Bo\Labels\UpdateLabelRequest $request
* @param \App\Models\Label $label
* @return \Illuminate\Http\RedirectResponse
* @ignore phpcs:disable Generic.Files.LineLength.TooLong
*/
public function update(UpdateLabelRequest $request, Label $label): \Illuminate\Http\RedirectResponse
{
// phpcs:enable
return DB::transaction(function () use ($request, $label) {
$label->fill($request->validated());
if ($label->saveOrFail()) {
return redirect()
->route('bo.labels.edit', $label)
->with('success', trans(
'crud.messages.has_been_updated',
['model' => Str::singular(trans('models.classes.labels'))]
));
} //end if
return redirect()
->back()
->with('error', trans(
'crud.messages.cannot_be_updated',
['model' => Str::singular(trans('models.classes.labels'))]
));
});
}
/**
* Remove the specified resource from storage.
*
* @param \App\Models\Label $label
* @return \Illuminate\Http\RedirectResponse
*/
public function destroy(Label $label): \Illuminate\Http\RedirectResponse
{
return DB::transaction(function () use ($label) {
if ($label->deleteOrFail()) {
return redirect()
->route('bo.labels.index')
->with('success', trans(
'crud.messages.has_been_deleted',
['model' => Str::singular(trans('models.classes.labels'))]
));
}
return redirect()
->back()
->with('error', trans(
':crud.messages.cannot_be_deleted',
['model' => Str::singular(trans('models.classes.labels'))]
));
});
}
}

View file

@ -0,0 +1,156 @@
<?php
namespace App\Http\Controllers\Bo;
use App\Http\Controllers\Controller;
use App\Http\Requests\Bo\Packages\StorePackageRequest;
use App\Http\Requests\Bo\Packages\UpdatePackageRequest;
use App\Models\Package;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
class PackageController 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 $packageModels */
$packageModels = Package::query();
/** @var string $search Search field */
$search = $request->search;
if ($search) {
$this->searchQuery(
$packageModels,
$search,
null,
'name',
'amount'
);
}
$searchFields = trans('Nom, Montant');
/** Sort columns with a query */
$this->sortQuery($packageModels);
/** Custom pagination */
$packageModels = $this->customPaginate($packageModels, $request->pagination);
return view('bo.pages.packages.index', compact('packageModels', 'search', 'searchFields'));
}
/**
* Show the form for creating a new resource.
*
* @param \App\Models\Package $package
* @return \Illuminate\Contracts\View\View
*/
public function create(Package $package): \Illuminate\Contracts\View\View
{
return view('bo.pages.packages.create', [
'packageModel' => $package,
]);
}
/**
* Store a newly created resource in storage.
*
* @param \App\Http\Requests\Bo\Packages\StorePackageRequest $request
* @return \Illuminate\Http\RedirectResponse
*/
public function store(StorePackageRequest $request): \Illuminate\Http\RedirectResponse
{
return DB::transaction(function () use ($request) {
$package = new Package();
$package->fill($request->validated());
if ($package->saveOrFail()) {
return redirect()
->route('bo.packages.edit', $package)
->with('success', trans(
'crud.messages.has_been_created',
['model' => Str::singular(trans('models.classes.packages'))]
));
}
return redirect()
->back()
->with('error', trans(
'crud.messages.cannot_be_created',
['model' => Str::singular(trans('models.classes.packages'))]
));
});
}
/**
* Show the form for editing the specified resource.
*
* @param \App\Models\Package $package
* @return \Illuminate\Contracts\View\View
*/
public function edit(Package $package): \Illuminate\Contracts\View\View
{
return view('bo.pages.packages.edit', [
'packageModel' => $package,
]);
}
/**
* Update the specified resource in storage.
*
* @param \App\Http\Requests\Bo\Packages\UpdatePackageRequest $request
* @param \App\Models\Package $package
* @return \Illuminate\Http\RedirectResponse
*/
public function update(UpdatePackageRequest $request, Package $package): \Illuminate\Http\RedirectResponse
{
return DB::transaction(function () use ($request, $package) {
$package->fill($request->validated());
if ($package->saveOrFail()) {
return redirect()
->route('bo.packages.edit', $package)
->with('success', trans(
'crud.messages.has_been_updated',
['model' => Str::singular(trans('models.classes.packages'))]
));
} //end if
return redirect()
->back()
->with('error', trans(
'crud.messages.cannot_be_updated',
['model' => Str::singular(trans('models.classes.packages'))]
));
});
}
/**
* Remove the specified resource from storage.
*
* @param \App\Models\Package $package
* @return \Illuminate\Http\RedirectResponse
*/
public function destroy(Package $package): \Illuminate\Http\RedirectResponse
{
return DB::transaction(function () use ($package) {
if ($package->deleteOrFail()) {
return redirect()
->route('bo.packages.index')
->with('success', trans(
'crud.messages.has_been_deleted',
['model' => Str::singular(trans('models.classes.packages'))]
));
}
return redirect()
->back()
->with('error', trans(
':crud.messages.cannot_be_deleted',
['model' => Str::singular(trans('models.classes.packages'))]
));
});
}
}

View file

@ -0,0 +1,193 @@
<?php
namespace App\Http\Controllers\Bo;
use App\Http\Controllers\Controller;
use App\Http\Requests\Bo\Projects\StoreProjectRequest;
use App\Http\Requests\Bo\Projects\UpdateProjectRequest;
use App\Lib\Helpers\ToolboxHelper;
use App\Models\Project;
use App\Models\Site;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
class ProjectController 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 $projectModels */
$projectModels = Project::query();
/** @var string $search Search field */
$search = $request->search;
if ($search) {
$this->searchQuery(
$projectModels,
$search,
null,
'name',
);
}
$searchFields = trans('Nom');
/** Sort columns with a query */
$this->sortQuery($projectModels);
/** Custom pagination */
$projectModels = $this->customPaginate($projectModels, $request->pagination);
return view('bo.pages.projects.index', compact('projectModels', 'search', 'searchFields'));
}
/**
* Crud show view
*
* @param \App\Models\Project $project
* @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory
*/
public function show(Project $project)
{
return view('bo.pages.projects.show', [
'projectModel' => $project
]);
}
/**
* Show the form for creating a new resource.
*
* @param \App\Models\Project $project
* @return \Illuminate\Contracts\View\View
*/
public function create(Project $project): \Illuminate\Contracts\View\View
{
$siteModels = Site::orderBy('name', 'ASC')->get();
return view('bo.pages.projects.create', [
'projectModel' => $project,
'siteModels' => $siteModels
]);
}
/**
* Store a newly created resource in storage.
*
* @param \App\Http\Requests\Bo\Projects\StoreProjectRequest $request
* @return \Illuminate\Http\RedirectResponse
*/
public function store(StoreProjectRequest $request): \Illuminate\Http\RedirectResponse
{
return DB::transaction(function () use ($request) {
$project = new Project();
$project->fill($request->validated());
if ($project->saveOrFail()) {
return redirect()
->route('bo.projects.edit', $project)
->with('success', trans(
'crud.messages.has_been_created',
['model' => Str::singular(trans('models.classes.projects'))]
));
}
return redirect()
->back()
->with('error', trans(
'crud.messages.cannot_be_created',
['model' => Str::singular(trans('models.classes.projects'))]
));
});
}
/**
* Show the form for editing the specified resource.
*
* @param \App\Models\Project $project
* @return \Illuminate\Contracts\View\View
*/
public function edit(Project $project): \Illuminate\Contracts\View\View
{
$siteModels = Site::orderBy('name', 'ASC')->get();
return view('bo.pages.projects.edit', [
'projectModel' => $project,
'siteModels' => $siteModels
]);
}
/**
* Update the specified resource in storage.
*
* @param \App\Http\Requests\Bo\Projects\UpdateProjectRequest $request
* @param \App\Models\Project $project
* @return \Illuminate\Http\RedirectResponse
*/
public function update(UpdateProjectRequest $request, Project $project): \Illuminate\Http\RedirectResponse
{
return DB::transaction(function () use ($request, $project) {
$project->fill($request->validated());
if ($project->saveOrFail()) {
return redirect()
->route('bo.projects.edit', $project)
->with('success', trans(
'crud.messages.has_been_updated',
['model' => Str::singular(trans('models.classes.projects'))]
));
} //end if
return redirect()
->back()
->with('error', trans(
'crud.messages.cannot_be_updated',
['model' => Str::singular(trans('models.classes.projects'))]
));
});
}
/**
* Remove the specified resource from storage.
*
* @param \App\Models\Project $project
* @return \Illuminate\Http\RedirectResponse
*/
public function destroy(Project $project): \Illuminate\Http\RedirectResponse
{
return DB::transaction(function () use ($project) {
if ($project->deleteOrFail()) {
return redirect()
->route('bo.projects.index')
->with('success', trans(
'crud.messages.has_been_deleted',
['model' => Str::singular(trans('models.classes.projects'))]
));
}
return redirect()
->back()
->with('error', trans(
':crud.messages.cannot_be_deleted',
['model' => Str::singular(trans('models.classes.projects'))]
));
});
}
/**
* Get a paginate resource.
*
* @param \Illuminate\Http\Request $request
* @return Illuminate\Http\JsonResponse
*/
public function jsonPaginate(Request $request): \Illuminate\Http\JsonResponse
{
return DB::transaction(function () use ($request) {
$model = $request->targetModel;
$search = $request->search;
$models = $model::where("name", "LIKE", "%{$search}%")->orderBy("name", "ASC");
return ToolboxHelper::jsonPaginate($this->customPaginate($models, $request->pagination));
});
}
}

View file

@ -1,36 +1,22 @@
<?php
namespace App\Http\Controllers;
namespace App\Http\Controllers\Bo;
use App\Enums\Role;
use App\Http\Requests\StoreScheduleRequest;
use App\Enums\Users\RoleEnum;
use App\Http\Controllers\Controller;
use App\Http\Requests\Bo\StoreScheduleRequest;
use App\Models\Schedule;
use App\Models\Ticket;
use App\Models\User;
use Illuminate\Http\Request;
use Carbon\CarbonImmutable;
use Illuminate\Database\Eloquent\Builder;
/**
* Alternate planner for Dev Team
*
* TODO: Refactor this controller.
*
* @author Olivier Legat <olivier.legat@ldc.fr>
*
*/
class ScheduleController extends Controller
{
/**
* ScheduleController
*/
public function __construct()
{
parent::__construct();
$this->middleware('is-admin');
}
/**
* Create the date
*
* @param \Illuminate\Http\Request $request
* @return \Carbon\CarbonImmutable|false
*/
@ -45,6 +31,7 @@ class ScheduleController extends Controller
/**
* Create the users table.
*
* @param \Illuminate\Http\Request $request
* @return array
* @throws \Illuminate\Contracts\Container\BindingResolutionException BindingResolutionException.
@ -55,7 +42,7 @@ class ScheduleController extends Controller
if (!is_null($request->cookie('userAuthSchedule'))) {
$dbusers = User::where('id', auth()->user()->id)->get();
} else {
$dbusers = User::where('role', Role::developper())->get();
$dbusers = User::where('role', RoleEnum::developper)->get();
}
foreach ($dbusers as $user) {
@ -66,6 +53,7 @@ class ScheduleController extends Controller
/**
* Display schedule.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory|\Illuminate\Http\RedirectResponse
* @throws \Illuminate\Contracts\Container\BindingResolutionException BindingResolutionException.
@ -73,7 +61,7 @@ class ScheduleController extends Controller
*/
public function index(Request $request)
{
if (!\auth()->user()->role->equals(Role::developper()) && !is_null($request->cookie('userAuthSchedule'))) {
if (!\auth()->user()->role->equals(RoleEnum::developper) && !is_null($request->cookie('userAuthSchedule'))) {
return $this->showAllSchedules();
}
@ -83,34 +71,43 @@ class ScheduleController extends Controller
$schedules = Schedule::whereHas('user', function (Builder $query) use ($request) {
$query->where('deleted_at', null);
$query->where('role', Role::developper());
$query->where('role', RoleEnum::developper);
if (!is_null($request->cookie('userAuthSchedule'))) {
$query->where('id', auth()->user()->id);
}
})
->whereDate('date', '>=', $date)
->whereDate('date', '<=', $date->addDays($nbweeks * 7 - 1))
->orderBy('user_id')
->orderBy('slot')
->orderBy('date')
->get();
->whereDate('date', '>=', $date)
->whereDate('date', '<=', $date->addDays($nbweeks * 7 - 1))
->orderBy('user_id')
->orderBy('slot')
->orderBy('date')
->get();
$arSchedules = array();
$prevUserId = null;
$prevDate = null;
$prevSlot = null;
foreach ($schedules as $schedule) {
$id_lie = array('label' => null, 'value' => null);
$id_lie = ['label' => null, 'name' => null, 'value' => ''];
if (!is_null($schedule->model_lie)) {
if (isset($schedule->relatedModel->name)) {
$id_lie = array('label' => $schedule->relatedModel->name, 'value' => $schedule->id_lie);
$id_lie = [
'label' => $schedule->relatedModel->name,
'name' => $schedule->relatedModel->name,
'value' => $schedule->id_lie
];
} else {
$id_lie = array('label' => 'Ticket ' . $schedule->id_lie, 'value' => $schedule->id_lie);
$ticket = Ticket::find($schedule->id_lie);
$id_lie = [
'label' => 'Ticket ' . $schedule->id_lie,
'name' => $ticket->formatNameForSchedule($ticket),
'value' => $schedule->id_lie
];
}
$model_lie = $schedule->model_lie;
} else {
$model_lie = array('label' => null, 'value' => null);
}
$model_lie = ['label' => null, 'value' => null];
}//end if
if ($prevUserId != $schedule->user_id) {
// New user.
@ -150,28 +147,29 @@ class ScheduleController extends Controller
'model_lie' => $model_lie,
);
}
}//end if
}//end if
} //end if
} //end if
$prevUserId = $schedule->user_id;
$prevDate = $schedule->date;
$prevSlot = $schedule->slot;
}//end foreach
} //end foreach
$weekCells = array();
for ($i = 0; $i < $nbweeks; $i++) {
$weekCells[] = array(
"num" => $date->addDays($i * 7)->weekOfYear,
"month" => $date->addDays($i * 7)->shortLocaleMonth,
"year" => $date->addDays($i * 7)->format('Y')
);
"num" => $date->addDays($i * 7)->weekOfYear,
"month" => $date->addDays($i * 7)->shortLocaleMonth,
"year" => $date->addDays($i * 7)->format('Y')
);
}
return view('schedule.index', compact('users', 'date', 'weekCells', 'arSchedules'));
return view('bo.pages.schedule.index', compact('users', 'date', 'weekCells', 'arSchedules'));
}
/**
* Display cell content.
* @param \App\Http\Requests\StoreScheduleRequest $request
*
* @param \App\Http\Requests\Bo\StoreScheduleRequest $request
* @return \Illuminate\Http\JsonResponse
* @throws \Illuminate\Contracts\Container\BindingResolutionException BindingResolutionException.
*/
@ -184,16 +182,24 @@ class ScheduleController extends Controller
$schedule = Schedule::updateOrCreate(['id' => $request->id], $fill);
$schedule->saveOrFail();
$id_lie = array('label' => null, 'value' => null);
$id_lie = array('label' => null, 'name' => null, 'value' => null);
if (!is_null($schedule->model_lie)) {
if (isset($schedule->relatedModel->name)) {
$id_lie = array('label' => $schedule->relatedModel->name, 'value' => $schedule->id_lie);
$id_lie = array(
'label' => $schedule->relatedModel->name,
'name' => $schedule->relatedModel->name,
'value' => $schedule->id_lie
);
} else {
$id_lie = array('label' => 'Ticket ' . $schedule->id_lie, 'value' => $schedule->id_lie);
$id_lie = array(
'label' => 'Ticket ' . $schedule->id_lie,
'name' => Ticket::find($schedule->id_lie)->formatNameForSchedule(Ticket::find($schedule->id_lie)),
'value' => $schedule->id_lie
);
}
$model_lie = $schedule->model_lie;
} else {
$model_lie = array('label' => null, 'value' => null);
$model_lie = array('label' => null, 'name' => null, 'value' => null);
}
$arSchd = [
@ -212,6 +218,7 @@ class ScheduleController extends Controller
/**
* Delet cell content.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\JsonResponse
* @throws \Illuminate\Contracts\Container\BindingResolutionException BindingResolutionException.
@ -225,23 +232,25 @@ class ScheduleController extends Controller
/**
* Display the auth user schedule.
*
* @return \Illuminate\Http\RedirectResponse
* @throws \Illuminate\Contracts\Container\BindingResolutionException BindingResolutionException.
* @throws \Symfony\Component\Routing\Exception\RouteNotFoundException RouteNotFoundException.
*/
public function showMySchedule()
{
return \redirect()->route('schedule.index')->withCookie(cookie()->forever('userAuthSchedule', 'true'));
return \redirect()->route('bo.schedule.index')->withCookie(cookie()->forever('userAuthSchedule', 'true'));
}
/**
* Display all the dev schedule.
*
* @return \Illuminate\Http\RedirectResponse
* @throws \Illuminate\Contracts\Container\BindingResolutionException BindingResolutionException.
* @throws \Symfony\Component\Routing\Exception\RouteNotFoundException RouteNotFoundException.
*/
public function showAllSchedules()
{
return \redirect()->route('schedule.index')->withCookie(cookie()->forget('userAuthSchedule'));
return \redirect()->route('bo.schedule.index')->withCookie(cookie()->forget('userAuthSchedule'));
}
}

View file

@ -0,0 +1,193 @@
<?php
namespace App\Http\Controllers\Bo;
use App\Http\Controllers\Controller;
use App\Http\Requests\Bo\Sites\StoreSiteRequest;
use App\Http\Requests\Bo\Sites\UpdateSiteRequest;
use App\Lib\Helpers\ToolboxHelper;
use App\Models\Site;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
class SiteController 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 $siteModels */
$siteModels = Site::query();
/** @var string $search Search field */
$search = $request->search;
if ($search) {
$this->searchQuery(
$siteModels,
$search,
null,
'name',
);
}
$searchFields = trans('Nom');
/** Sort columns with a query */
$this->sortQuery($siteModels);
/** Custom pagination */
$siteModels = $this->customPaginate($siteModels, $request->pagination);
return view('bo.pages.sites.index', compact('siteModels', 'search', 'searchFields'));
}
/**
* Show model action.
*
* @param \App\Models\Site $site
* @return \Illuminate\Contracts\View\View
*/
public function show(Site $site): \Illuminate\Contracts\View\View
{
return view('bo.pages.sites.show', ['siteModel' => $site]);
}
/**
* Show the form for creating a new resource.
*
* @param \App\Models\Site $site
* @return \Illuminate\Contracts\View\View
*/
public function create(Site $site): \Illuminate\Contracts\View\View
{
$userModels = User::orderBy('name', 'ASC')->get();
return view('bo.pages.sites.create', [
'siteModel' => $site,
'userModels' => $userModels
]);
}
/**
* Store a newly created resource in storage.
*
* @param \App\Http\Requests\Bo\Sites\StoreSiteRequest $request
* @return \Illuminate\Http\RedirectResponse
*/
public function store(StoreSiteRequest $request): \Illuminate\Http\RedirectResponse
{
return DB::transaction(function () use ($request) {
$site = new Site();
$site->fill($request->validated());
$site->users()->attach(collect($request->validated('users'))->pluck('id'));
if ($site->saveOrFail()) {
return redirect()
->route('bo.sites.edit', $site)
->with('success', trans(
'crud.messages.has_been_created',
['model' => Str::singular(trans('models.classes.sites'))]
));
}
return redirect()
->back()
->with('error', trans(
'crud.messages.cannot_be_created',
['model' => Str::singular(trans('models.classes.sites'))]
));
});
}
/**
* Show the form for editing the specified resource.
*
* @param \App\Models\Site $site
* @return \Illuminate\Contracts\View\View
*/
public function edit(Site $site): \Illuminate\Contracts\View\View
{
$userModels = User::orderBy('name', 'ASC')->get();
return view('bo.pages.sites.edit', [
'siteModel' => $site,
'userModels' => $userModels
]);
}
/**
* Update the specified resource in storage.
*
* @param \App\Http\Requests\Bo\Sites\UpdateSiteRequest $request
* @param \App\Models\Site $site
* @return \Illuminate\Http\RedirectResponse
*/
public function update(UpdateSiteRequest $request, Site $site): \Illuminate\Http\RedirectResponse
{
return DB::transaction(function () use ($request, $site) {
$site->fill($request->validated());
$site->users()->attach(collect($request->validated('users'))->pluck('id'));
if ($site->saveOrFail()) {
return redirect()
->route('bo.sites.edit', $site)
->with('success', trans(
'crud.messages.has_been_updated',
['model' => Str::singular(trans('models.classes.sites'))]
));
} //end if
return redirect()
->back()
->with('error', trans(
'crud.messages.cannot_be_updated',
['model' => Str::singular(trans('models.classes.sites'))]
));
});
}
/**
* Remove the specified resource from storage.
*
* @param \App\Models\Site $site
* @return \Illuminate\Http\RedirectResponse
*/
public function destroy(Site $site): \Illuminate\Http\RedirectResponse
{
return DB::transaction(function () use ($site) {
if ($site->deleteOrFail()) {
$site->users()->detach();
return redirect()
->route('bo.sites.index')
->with('success', trans(
'crud.messages.has_been_deleted',
['model' => Str::singular(trans('models.classes.sites'))]
));
}
return redirect()
->back()
->with('error', trans(
':crud.messages.cannot_be_deleted',
['model' => Str::singular(trans('models.classes.sites'))]
));
});
}
/**
* Get a paginate resource.
*
* @param \Illuminate\Http\Request $request
* @return Illuminate\Http\JsonResponse
*/
public function jsonPaginate(Request $request): \Illuminate\Http\JsonResponse
{
return DB::transaction(function () use ($request) {
$model = $request->targetModel;
$search = $request->search;
$models = $model::where("name", "LIKE", "%{$search}%")->orderBy("name", "ASC");
return ToolboxHelper::jsonPaginate($this->customPaginate($models, $request->pagination));
});
}
}

View file

@ -1,19 +1,21 @@
<?php
namespace App\Http\Controllers;
namespace App\Http\Controllers\Bo;
use App\Enums\TicketStatus;
use App\Enums\TicketTypeEnum;
use App\Enums\Tickets\TicketStatusEnum;
use App\Enums\Tickets\TicketTypeEnum;
use App\Events\NotifySubscriptions;
use App\Events\TicketStatusChanged;
use App\Http\Requests\AssignTicketToUserRequest;
use App\Http\Requests\ChangeTicketStatus;
use App\Http\Requests\CreateMessage;
use App\Http\Requests\SortTickets;
use App\Http\Requests\StoreTicket;
use App\Http\Requests\UpdateMessage;
use App\Http\Requests\UpdateTicket;
use App\Lib\ToolboxHelper;
use App\Http\Controllers\Controller;
use App\Http\Requests\Bo\AssignTicketToUserRequest;
use App\Http\Requests\Bo\ChangeTicketStatus;
use App\Http\Requests\Bo\CreateMessage;
use App\Http\Requests\Bo\SortTickets;
use App\Http\Requests\Bo\StoreTicket;
use App\Http\Requests\Bo\UpdateMessage;
use App\Http\Requests\Bo\UpdateTicket;
use App\Lib\Helpers\FileStorageHelper;
use App\Lib\Helpers\ToolboxHelper;
use App\Mail\NewTicket;
use App\Models\Message;
use App\Models\Site;
@ -68,7 +70,7 @@ class TicketController extends Controller
'value' => $ticket->id
];
}));
}//end if
} //end if
/** @var \App\Models\User */
@ -87,18 +89,19 @@ class TicketController extends Controller
$tickets->where(
'status',
($request->st == TicketStatus::archived()) ? '=' : '<>',
TicketStatus::archived()
($request->st == TicketStatusEnum::archived->value) ? '=' : '<>',
TicketStatusEnum::archived
);
$tickets = $this->searchTicket($tickets, $request);
$tickets = $this->filterTickets($tickets, $request);
$tickets = $tickets->paginate();
/** Custom pagination */
$tickets = $this->customPaginate($tickets, $request->pagination);
$sites = Site::select('id', 'name')->orderBy('name')->get();
$status = TicketStatus::toArray();
$status = TicketStatusEnum::cases();
return view('ticket.index', compact('tickets', 'sites', 'status'));
return view('bo.pages.tickets.index', compact('tickets', 'sites', 'status'));
}
/**
@ -112,12 +115,7 @@ class TicketController extends Controller
{
if ($request->ajax()) {
return \response()->json([
'label' => sprintf(
'Ticket %d (%s): %s',
$ticket->id,
$ticket->user ? $ticket->user->email : __('Utilisateur supprimé'),
Str::limit(\preg_replace('/[[:cntrl:]]+/', '', $ticket->text), 35)
),
'label' => $ticket->formatNameForSchedule($ticket),
'value' => $ticket->id
]);
}
@ -135,7 +133,7 @@ class TicketController extends Controller
$messages = $ticket->messages()->orderBy('created_at', 'DESC')->get();
$isSubscribed = (bool)$ticket->subscriptions()->where('user_id', $user->id)->count();
return view('ticket.show', compact('ticket', 'messages', 'isSubscribed'));
return view('bo.pages.tickets.show', compact('ticket', 'messages', 'isSubscribed'));
}
/**
@ -154,10 +152,10 @@ class TicketController extends Controller
}
if (!count($sites)) {
return redirect()->route('sites.create')
->with('warning', trans('Vous devez tout d\'abord créer un site pour y ajouter un ticket'));
return redirect()->route('bo.sites.create')
->with('warning', trans('Vous devez tout d\'abord créer un site pour y ajouter un ticket'));
}
return view('ticket.create', compact('sites'));
return view('bo.pages.tickets.create', compact('sites'));
}
/**
@ -184,10 +182,10 @@ class TicketController extends Controller
$fileTicket2 = $request->file_ticket2;
if ($fileTicket) {
$ticket->file = ToolboxHelper::storeImage($ticket->getTable(), $fileTicket);
$ticket->file = FileStorageHelper::storeFile($ticket, $fileTicket);
}
if ($fileTicket2) {
$ticket->file2 = ToolboxHelper::storeImage($ticket->getTable(), $fileTicket2);
$ticket->file2 = FileStorageHelper::storeFile($ticket, $fileTicket2);
}
$ticket->user()->associate(auth()->user());
@ -206,7 +204,7 @@ class TicketController extends Controller
throw new \ErrorException('Missing MAIL_ADMIN in .env');
}
return redirect()->route('ticket.show', $ticket)
return redirect()->route('bo.ticket.show', $ticket)
->with('success', trans('Ticket enregistré !'));
});
} catch (\ErrorException $e) {
@ -233,7 +231,7 @@ class TicketController extends Controller
} else {
$sites = $user->sites;
}
return view('ticket.edit', compact('ticket', 'sites'));
return view('bo.pages.tickets.edit', compact('ticket', 'sites'));
}
/**
@ -258,10 +256,10 @@ class TicketController extends Controller
$fileTicket2 = $request->file_ticket2;
if ($fileTicket) {
$ticket->file = ToolboxHelper::storeImage($ticket->getTable(), $fileTicket);
$ticket->file = FileStorageHelper::storeFile($ticket, $fileTicket);
}
if ($fileTicket2) {
$ticket->file2 = ToolboxHelper::storeImage($ticket->getTable(), $fileTicket2);
$ticket->file2 = FileStorageHelper::storeFile($ticket, $fileTicket2);
}
@ -270,8 +268,8 @@ class TicketController extends Controller
$ticket->site()->associate($site);
$ticket->saveOrFail();
return redirect()->route('ticket.edit', $ticket->id)
->with('success', 'Modifications enregistrées !');
return redirect()->route('bo.ticket.edit', $ticket->id)
->with('success', 'Modifications enregistrées !');
});
} catch (\ErrorException $e) {
report($e);
@ -329,7 +327,7 @@ class TicketController extends Controller
$message->saveOrFail();
if ($fileMessage) {
$message->file = ToolboxHelper::storeImage($message->getTable(), $fileMessage);
$message->file = FileStorageHelper::storeFile($message, $fileMessage);
$message->saveOrFail();
}
return back()
@ -369,9 +367,9 @@ class TicketController extends Controller
*/
public function setToArchive(Ticket $ticket)
{
$ticket->status = TicketStatus::archived();
$ticket->status = TicketStatusEnum::archived;
$ticket->saveOrFail();
return redirect()->route('ticket.index')
return redirect()->route('bo.ticket.index')
->with('warning', trans('Le ticket est archivé'));
}
@ -405,9 +403,9 @@ class TicketController extends Controller
'ticketName' => $ticket->user->name,
'ticketNumber' => $ticket->id,
]);
/** @var \App\Enums\TicketStatus */
/** @var \App\Enums\Tickets\TicketStatusEnum */
$oldStatus = $ticket->status;
$ticket->status = TicketStatus::new();
$ticket->status = TicketStatusEnum::new;
$ticket->saveQuietly();
event(new TicketStatusChanged($ticket, $oldStatus, null, $message, false, false));
event(new NotifySubscriptions($ticket, $message, collect([$ticket->user])));
@ -452,7 +450,7 @@ class TicketController extends Controller
$ticket->saveQuietly();
/** @var \App\Enums\TicketStatus */
/** @var \App\Enums\Tickets\TicketStatusEnum */
$oldStatus = $ticket->status;
// * Notification systeme doit etre privée.
event(new TicketStatusChanged($ticket, $oldStatus, null, $message, true, false));
@ -478,9 +476,11 @@ class TicketController extends Controller
* @param Builder $tickets
* @param Request $request
* @return Builder
* @phpcs:disable Generic.Metrics.CyclomaticComplexity.TooHigh
*/
private function filterTickets(Builder $tickets, Request $request): Builder
{
//phpcs:enable
if ($request->rst) {
Session::remove('tickets.ass');
Session::remove('tickets.st');
@ -574,13 +574,13 @@ class TicketController extends Controller
if (!strlen($word)) {
continue;
}
$s = collect(TicketStatus::toArray())->filter(function (TicketStatus $t) use ($word) {
return Str::slug($t->label) === Str::slug($word);
})->map(function (TicketStatus $ticket) {
$s = collect(TicketStatusEnum::cases())->filter(function (TicketStatusEnum $t) use ($word) {
return Str::slug($t->label()) === Str::slug($word);
})->map(function (TicketStatusEnum $ticket) {
return $ticket->value;
});
$t = collect(TicketTypeEnum::toArray())->filter(function (TicketTypeEnum $s) use ($word) {
return Str::slug($s->label) === Str::slug($word);
$t = collect(TicketTypeEnum::cases())->filter(function (TicketTypeEnum $s) use ($word) {
return Str::slug($s->label()) === Str::slug($word);
})->map(function (TicketTypeEnum $ticket) {
return $ticket->value;
});
@ -594,4 +594,34 @@ class TicketController extends Controller
} //end if
}, 'text', 'file', 'file2');
}
/**
* Get a paginate resource.
*
* @param \Illuminate\Http\Request $request
* @return Illuminate\Http\JsonResponse
*/
public function jsonPaginate(Request $request): \Illuminate\Http\JsonResponse
{
return DB::transaction(function () use ($request) {
$model = $request->targetModel;
$search = $request->search;
// * Handle Ajax
$tickets = $model::with(['user', 'assignedUser']);
if ($search) {
$tickets = $tickets->where('text', 'LIKE', "%$search%")
->orWhere('id', $search)
->orWhereHas('user', function ($q) use ($search) {
$q->where('name', 'LIKE', "%$search%");
})
->orderBy("id", "ASC");
}
return ToolboxHelper::jsonPaginate(
$this->customPaginate($tickets, $request->pagination),
'formatNameForSchedule'
);
});
}
}

View file

@ -0,0 +1,81 @@
<?php
namespace App\Http\Controllers\Bo;
use App\Http\Controllers\Controller;
use App\Http\Requests\Bo\TicketTypes\UpdateTicketTypeRequest;
use App\Models\Ticket\TicketType;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
class TicketTypeController 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 $ticketTypeModels */
$ticketTypeModels = TicketType::query();
/** @var string $search Search field */
$search = $request->search;
if ($search) {
$this->searchQuery(
$ticketTypeModels,
$search,
null,
'type',
);
}
$searchFields = trans('Type');
/** Sort columns with a query */
$this->sortQuery($ticketTypeModels);
/** Custom pagination */
$ticketTypeModels = $this->customPaginate($ticketTypeModels, $request->pagination);
return view('bo.pages.ticket_types.index', compact('ticketTypeModels', 'search', 'searchFields'));
}
/**
* Show the form for editing the specified resource.
*
* @param App\Models\Ticket\TicketType $ticketType
* @return \Illuminate\Contracts\View\View
* @ignore phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClass
*/
public function edit(TicketType $ticketType): \Illuminate\Contracts\View\View
{
return view('bo.pages.ticket_types.edit', ['ticketTypeModel' => $ticketType]);
}
/**
* Update the specified resource in storage.
*
* @param \App\Http\Requests\Bo\TicketTypes\UpdateTicketTypeRequest $request
* @param \App\Models\Ticket\TicketType $ticketType
* @return \Illuminate\Http\RedirectResponse
*/
public function update(UpdateTicketTypeRequest $request, TicketType $ticketType): \Illuminate\Http\RedirectResponse
{
return DB::transaction(function () use ($request, $ticketType) {
$ticketType->fill($request->validated());
if ($ticketType->saveOrFail()) {
return redirect()->route('bo.ticket_types.edit', $ticketType->id)
->with('success', __('crud.messages.has_been_updated', [
'model' => trans_choice('models.classes.ticket_types', 1)
]));
}
return redirect()->route('bo.ticket_types.edit', $ticketType->id)
->with('error', __('crud.messages.cannot_be_updated', [
'model' => trans_choice('models.classes.ticket_types', 1)
]));
});
}
}

View file

@ -0,0 +1,235 @@
<?php
namespace App\Http\Controllers\Bo;
use App\Http\Controllers\Bo\Auth\ForgotPasswordController;
use App\Http\Controllers\Controller;
use App\Http\Requests\Bo\Users\StoreUserRequest;
use App\Http\Requests\Bo\Users\UpdateUserRequest;
use App\Models\Site;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
class UserController 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 $userModels */
$userModels = User::query();
/** @var string $search Search field */
$search = $request->search;
if ($search) {
$this->searchQuery(
$userModels,
$search,
null,
'name',
'email'
);
}
$searchFields = trans('Label, email');
/** Sort columns with a query */
$this->sortQuery($userModels);
/** Custom pagination */
$userModels = $this->customPaginate($userModels, $request->pagination);
return view('bo.pages.users.index', compact('userModels', 'search', 'searchFields'));
}
/**
* Show the form for creating a new resource.
*
* @param \App\Models\User $user
* @return \Illuminate\Contracts\View\View
*/
public function create(User $user): \Illuminate\Contracts\View\View
{
$siteModels = Site::orderBy('name', 'ASC')->get();
return view('bo.pages.users.create', [
'userModel' => $user,
'siteModels' => $siteModels
]);
}
/**
* Store a newly created resource in storage.
*
* @param \App\Http\Requests\Bo\Users\StoreUserRequest $request
* @return \Illuminate\Http\RedirectResponse
*/
public function store(StoreUserRequest $request): \Illuminate\Http\RedirectResponse
{
return DB::transaction(function () use ($request) {
$user = new User();
$user->fill($request->safe()->except('sites'));
if ($user->saveOrFail()) {
$user->sites()->attach(collect($request->validated('sites'))->pluck('id'));
return redirect()
->route('bo.users.edit', $user)
->with('success', trans(
'crud.messages.has_been_created',
['model' => Str::singular(trans('models.classes.users'))]
));
}
return redirect()
->back()
->with('error', trans(
'crud.messages.cannot_be_created',
['model' => Str::singular(trans('models.classes.users'))]
));
});
}
/**
* Show the form for editing the specified resource.
*
* @param \App\Models\User $user
* @return \Illuminate\Contracts\View\View
*/
public function edit(User $user): \Illuminate\Contracts\View\View
{
$siteModels = Site::orderBy('name', 'ASC')->get();
return view('bo.pages.users.edit', [
'userModel' => $user,
'siteModels' => $siteModels
]);
}
/**
* Update the specified resource in storage.
*
* @param \App\Http\Requests\Bo\Users\UpdateUserRequest $request
* @param \App\Models\User $user
* @return \Illuminate\Http\RedirectResponse
*/
public function update(UpdateUserRequest $request, User $user): \Illuminate\Http\RedirectResponse
{
return DB::transaction(function () use ($request, $user) {
$user->fill($request->safe()->except(['sites']));
$user->sites()->detach();
if (collect($request->validated('sites'))->pluck('id')) {
$user->sites()->attach(collect($request->validated('sites'))->pluck('id'));
}
if ($user->saveOrFail()) {
return redirect()
->route('bo.users.edit', $user)
->with('success', trans(
'crud.messages.has_been_updated',
['model' => Str::singular(trans('models.classes.users'))]
));
} //end if
return redirect()
->back()
->with('error', trans(
'crud.messages.cannot_be_updated',
['model' => Str::singular(trans('models.classes.users'))]
));
});
}
/**
* Remove the specified resource from storage.
*
* @param \App\Models\User $user
* @return \Illuminate\Http\RedirectResponse
*/
public function destroy(User $user): \Illuminate\Http\RedirectResponse
{
return DB::transaction(function () use ($user) {
if ($user->deleteOrFail()) {
$user->sites()->detach();
return redirect()
->route('bo.users.index')
->with('success', trans(
'crud.messages.has_been_deleted',
['model' => Str::singular(trans('models.classes.users'))]
));
}
return redirect()
->back()
->with('error', trans(
':crud.messages.cannot_be_deleted',
['model' => Str::singular(trans('models.classes.users'))]
));
});
}
/**
* Password reset form
*
* @return \Illuminate\Contracts\View\View
*/
public function passwordReset(): \Illuminate\Contracts\View\View
{
return view('bo.pages.users.passwordReset');
}
/**
* Password reset submit
*
* @return \Illuminate\Http\RedirectResponse
*/
public function passwordResetSubmit(): \Illuminate\Http\RedirectResponse
{
/** @var \App\Models\User */
$user = auth()->user();
$request = new Request(['email' => $user->email]);
return app(ForgotPasswordController::class)->sendResetLinkEmail($request);
}
/**
* Show stats
*
* @return \Illuminate\Contracts\View\View
*/
public function stats(): \Illuminate\Contracts\View\View
{
/** @var \App\Models\User */
$user = auth()->user();
$stats = [];
$curYear = date('Y');
for ($i = 2021; $i <= $curYear; $i++) {
$start = $i . '-03-01';
$end = $i + 1 . '-02-' . $this->getLastDayFebruary($i + 1);
$datas = $user->schedules()->selectRaw('count(id) as nb, activity')
->whereBetween('date', [$start, $end])
->groupBy('activity')
->orderBy('activity', 'ASC')
->get();
$stats[sprintf("%d/%d", $i, $i + 1)] = $datas;
}
return view('bo.pages.users.stats', ['stats' => array_reverse($stats)]);
}
/**
* Get february last day date of the year
*
* @param integer $year
* @return integer 28 or 29
*/
private function getLastDayFebruary(int $year): int
{
if ((is_int($year / 4) && !is_int($year / 100)) || is_int($year / 400)) {
return 29;
}
return 28;
}
}

View file

@ -1,51 +0,0 @@
<?php
namespace App\Http\Controllers;
use App\Models\Brand;
use Kwaadpepper\CrudPolicies\Http\Requests\CrudIndexRequest;
use Kwaadpepper\CrudPolicies\Traits\CrudController;
class BrandController extends Controller
{
use CrudController {
__construct as __CrudConstructor;
index as crudIndex;
}
/** @var Account */
public static $modelClass = Brand::class;
/**
* Crud Layout
*
* @var string
*/
public static $layout = 'layout.app';
/**
* ProjectController
*/
public function __construct()
{
parent::__construct();
$this->__CrudConstructor();
$this->authorizeResource(Brand::class, 'brand');
}
/**
* Crud index view
*
* @param \Kwaadpepper\CrudPolicies\Http\Requests\CrudIndexRequest $request
* @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory
*/
public function index(CrudIndexRequest $request)
{
/** @var \Illuminate\View\View */
$view = $this->crudIndex($request);
if ($request->ajax()) {
return $view;
}
return view('brands.index', $view->getData());
}
}

View file

@ -1,22 +0,0 @@
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use App\Models\Company;
use Kwaadpepper\CrudPolicies\Traits\CrudController;
class CompanyController extends Controller
{
use CrudController;
/** @var \App\Models\MacroSchedule\Marker */
public static $modelClass = Company::class;
/**
* Crud Layout
*
* @var string
*/
public static $layout = 'layout.app';
}

View file

@ -2,14 +2,16 @@
namespace App\Http\Controllers;
use App\Enums\Tickets\TicketStatusEnum;
use App\Models\Ticket;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Routing\Controller as BaseController;
use App\Enums\TicketStatus;
use App\Models\Ticket;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Facades\Session;
use Illuminate\Support\Facades\View;
@ -39,17 +41,17 @@ class Controller extends BaseController
55,
];
$ticketsNew = Ticket::where('status', TicketStatus::new());
$ticketsWaiting = Ticket::where('status', TicketStatus::waiting());
$ticketsNew = Ticket::where('status', TicketStatusEnum::new);
$ticketsWaiting = Ticket::where('status', TicketStatusEnum::waiting);
$ticketsInProgress = Ticket::whereNotIn(
'status',
[
TicketStatus::new(),
TicketStatus::estimateTodo(),
TicketStatus::waiting(),
TicketStatus::production(),
TicketStatus::archived(),
TicketStatus::takenInAccount()
TicketStatusEnum::new,
TicketStatusEnum::estimateTodo,
TicketStatusEnum::waiting,
TicketStatusEnum::production,
TicketStatusEnum::archived,
TicketStatusEnum::takenInAccount
]
);
@ -73,12 +75,13 @@ class Controller extends BaseController
* Build Search query on specified fields
* splitting search into words or using whole sentence
*
* @param Builder $query The eloquent query builder.
* @param string $search The query string.
* @param callable $searchQuery The query string.
* @param string ...$fields Either a simple array or a string
* in case of a string the two fields would be concatenate to make the search.
* @return Builder
* @param \Illuminate\Database\Eloquent\Builder $query The eloquent query builder.
* @param string $search The query string.
* @param callable $searchQuery The query string.
* @param string ...$fields Either a simple array or a string
* in case of a string the two fields
* would be concatenate to make the search.
* @return \Illuminate\Database\Eloquent\Builder
*/
protected function searchQuery(
Builder $query,
@ -109,10 +112,10 @@ class Controller extends BaseController
/**
* Build query search on all fields
*
* @param Builder $query
* @param string $search
* @param array $fields
* @return Builder
* @param \Illuminate\Database\Eloquent\Builder $query
* @param string $search
* @param array $fields
* @return \Illuminate\Database\Eloquent\Builder
*/
private function searchOnFields(Builder $query, string $search, array $fields): Builder
{
@ -124,10 +127,13 @@ class Controller extends BaseController
sprintf("UPPER(CONCAT(%s)) LIKE UPPER(?)", collect($f)->map(function ($q) use ($table) {
return "`$table`.`$q`";
})->implode(', \' \', ')),
["%$search%"]
['%' . filter_var($search, FILTER_SANITIZE_STRING) . '%']
);
} else {
$query->orWhereRaw("UPPER(`$table`.`$f`) LIKE UPPER(?)", ["%$search%"]);
$query->orWhereRaw(
"UPPER(`$table`.`$f`) LIKE UPPER(?)",
['%' . filter_var($search, FILTER_SANITIZE_STRING) . '%']
);
}
}
return $query;
@ -171,4 +177,22 @@ class Controller extends BaseController
}
return $query;
}
/**
* Customize pagination with cache or config (default).
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @param integer|null $pagination
* @return \Illuminate\Pagination\LengthAwarePaginator
*/
protected function customPaginate(Builder $query, $pagination): LengthAwarePaginator
{
if ($pagination) {
Cache::put('pagination', $pagination);
};
$query = $query->paginate(
(Cache::get('pagination')) ? intval(Cache::get('pagination')) : config('pagination.default')
);
return $query;
}
}

View file

@ -1,124 +0,0 @@
<?php
namespace App\Http\Controllers\Credit;
use App\Enums\Credit\BalanceOperation;
use App\Http\Controllers\Controller;
use App\Http\Requests\Credit\AddCreditToAccountRequest;
use App\Models\Brand;
use App\Models\Credit\Account;
use App\Models\Credit\CreditLog;
use Illuminate\Database\Eloquent\Builder;
use Kwaadpepper\CrudPolicies\Http\Requests\CrudIndexRequest;
use Kwaadpepper\CrudPolicies\Traits\CrudController;
class AccountController extends Controller
{
use CrudController {
__construct as __CrudConstructor;
index as crudIndex;
}
/** @var Account */
public static $modelClass = Account::class;
/**
* Crud Layout
*
* @var string
*/
public static $layout = 'layout.app';
/**
* Index query middleware
*
* @param Builder $query
* @return Builder
* @throws \ErrorException If account is missing in url.
*/
public function indexQuery(Builder $query): Builder
{
/** @var \App\Models\User */
$user = auth()->user();
if (!$user->isAdmin()) {
$userBrands = $user->brands();
return $query->whereHas('brand', function ($q) use ($userBrands) {
$q->whereIn('brand_id', $userBrands->pluck('id'));
});
}
/** @var \App\Models\Brand|null $brand */
if (!($brand = request()->brand)) {
abort(404, 'Cannot get brand');
}
return $query->whereHas('brand', function ($q) use ($brand) {
$q->where('id', $brand->id);
});
}
/**
* Crud index view
*
* @param \Kwaadpepper\CrudPolicies\Http\Requests\CrudIndexRequest $request
* @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory
*/
public function index(CrudIndexRequest $request)
{
/** @var \Illuminate\View\View */
$view = $this->crudIndex($request);
if ($request->ajax()) {
return $view;
}
return view('accounts.index', $view->getData());
}
/**
* Before store model middleware
*
* @param Account $model
* @return void
*/
public function storeModel(Account &$model)
{
$model->brand()->associate(\request()->brand);
}
/**
* Credit
*
* @param \App\Models\Brand $brand
* @param \App\Models\Account $account
* @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory
* @phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClassAfterLastUsed
*/
public function credit(Brand $brand, Account $account)
{
return view('accounts.credit', compact('brand', 'account'));
}
/**
* Credit Account
*
* @param \App\Http\Requests\Credit\AddCreditToAccountRequest $request
* @param \App\Models\Brand $brand
* @param \App\Models\Account $account
* @return \Illuminate\Http\RedirectResponse
* @phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClassBeforeLastUsed
*/
public function creditSubmit(AddCreditToAccountRequest $request, Brand $brand, Account $account)
{
$log = new CreditLog();
$log->account()->associate($account);
$log->type = BalanceOperation::credit();
$log->amount = \strval($request->amount);
if ($log->saveOrFail()) {
return \response()->redirectToRoute('brands.credit_accounts.index', $brand)
->with('info', trans('Le compte à bien été crédité'));
}
return back();
}
}

View file

@ -1,65 +0,0 @@
<?php
namespace App\Http\Controllers\Credit;
use App\Http\Controllers\Controller;
use App\Models\Credit\CreditLog;
use Illuminate\Database\Eloquent\Builder;
use Kwaadpepper\CrudPolicies\Http\Requests\CrudIndexRequest;
use Kwaadpepper\CrudPolicies\Traits\CrudController;
class CreditLogController extends Controller
{
use CrudController {
__construct as __CrudConstructor;
index as crudIndex;
}
/** @var CreditLog */
public static $modelClass = CreditLog::class;
/**
* Crud Layout
*
* @var string
*/
public static $layout = 'layout.app';
/**
* Index query middleware
*
* @param Builder $query
* @return Builder
* @throws \ErrorException If account is missing in url.
*/
public function indexQuery(Builder $query): Builder
{
$query->orderBy('created_at', 'DESC');
/** @var \App\Models\User */
$user = auth()->user();
/** @var \App\Models\Credit\Account $account */
$account = request()->account;
return $query->whereHas('account', function ($q) use ($account) {
$q->where('id', '=', $account->id);
});
}
/**
* Crud index view
*
* @param \Kwaadpepper\CrudPolicies\Http\Requests\CrudIndexRequest $request
* @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory
*/
public function index(CrudIndexRequest $request)
{
/** @var \Illuminate\View\View */
$view = $this->crudIndex($request);
if ($request->ajax()) {
return $view;
}
return view('credit_logs.index', $view->getData());
}
}

View file

@ -1,22 +0,0 @@
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use App\Models\Dutyhour;
use Kwaadpepper\CrudPolicies\Traits\CrudController;
class DutyhourController extends Controller
{
use CrudController;
/** @var \App\Models\MacroSchedule\Marker */
public static $modelClass = Dutyhour::class;
/**
* Crud Layout
*
* @var string
*/
public static $layout = 'layout.app';
}

View file

@ -1,83 +0,0 @@
<?php
namespace App\Http\Controllers;
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;
/**
* Crud Layout
*
* @var string
*/
public static $layout = 'layout.app';
/**
* Index query middleware
*
* @param Builder $query
* @return Builder
*/
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;
}
/**
* Crud index view
*
* @param \Kwaadpepper\CrudPolicies\Http\Requests\CrudIndexRequest $request
* @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory
*/
public function index(CrudIndexRequest $request)
{
/** @var \Illuminate\View\View */
$view = $this->crudIndex($request);
if ($request->ajax()) {
return $view;
}
return view('files.index', $view->getData());
}
/**
* Crud create view
*
* @param \Kwaadpepper\CrudPolicies\Http\Requests\CrudIndexRequest $request
* @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory
*/
public function create(CrudIndexRequest $request)
{
/** @var \Illuminate\View\View */
$view = $this->crudCreate($request);
return view('files.create', $view->getData());
}
/**
* Before store model middleware
*
* @param \App\Models\File $file
* @return void
*/
public function storeModel(File &$file)
{
$file->parent()->associate(request()->site ?? request()->project);
}
}

View file

@ -1,52 +0,0 @@
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use App\Models\Information;
use Kwaadpepper\CrudPolicies\Traits\CrudController;
class InformationController extends Controller
{
use CrudController;
/** @var \App\Models\MacroSchedule\Marker */
public static $modelClass = Information::class;
/**
* Crud Layout
*
* @var string
*/
public static $layout = 'layout.app';
/**
* After store model middleware
*
* @return void
*/
public function storedModel()
{
cache()->put('infos', Information::all(), 3600);
}
/**
* After update model middleware
*
* @return void
*/
public function updatedModel()
{
cache()->put('infos', Information::all(), 3600);
}
/**
* After delete model middleware
*
* @return void
*/
public function deletedModel()
{
cache()->put('infos', Information::all(), 3600);
}
}

View file

@ -1,282 +0,0 @@
<?php
namespace App\Http\Controllers;
use App\Enums\Invoice\TaskType;
use App\Http\Requests\Invoice\InvoiceSetDateRequest;
use App\Models\Company;
use App\Models\Invoice;
use App\Models\Package;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Str;
use Illuminate\Validation\ValidationException;
use Kwaadpepper\CrudPolicies\Http\Requests\CrudIndexRequest;
use Kwaadpepper\CrudPolicies\Traits\CrudController;
use Kwaadpepper\Enum\Rules\EnumIsValidRule;
/**
* * Because update is denied when invoice is sent to the client
* ForceUpdate On signed date
* ForceUpdate On compta sent date
*/
class InvoiceController extends Controller
{
use CrudController {
index as crudIndex;
show as crudShow;
create as crudCreate;
edit as crudEdit;
}
/** @var \App\Models\Invoice */
public static $modelClass = Invoice::class;
/**
* Crud Layout
*
* @var string
*/
public static $layout = 'layout.app';
/**
* Crud index view
*
* @param \Kwaadpepper\CrudPolicies\Http\Requests\CrudIndexRequest $request
* @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory
*/
public function index(CrudIndexRequest $request)
{
/** @var \Illuminate\View\View */
$view = $this->crudIndex($request);
if ($request->ajax()) {
return $view;
}
if ($request->search and ($models = $view->getData()['models'])->count() === 1) {
return \redirect()->route('invoices.edit', $models->first());
}
return view('invoices.index', $view->getData());
}
/**
* Index query middleware
*
* @param Builder $query
* @return Builder
* @throws \ErrorException If account is missing in url.
*/
public function indexQuery(Builder $query): Builder
{
$query->orderBy('created_at', 'DESC');
return $query->orWhere(function (Builder $q) {
$q->whereHas('site', function ($q) {
$q->where('name', 'LIKE', '%' . \filter_var(request()->search, \FILTER_SANITIZE_STRING) . '%');
})->orWhereHas('company', function ($q) {
$q->where('name', 'LIKE', '%' . \filter_var(request()->search, \FILTER_SANITIZE_STRING) . '%');
})->orWhereHas('companyInvoiced', function ($q) {
$q->where('name', 'LIKE', '%' . \filter_var(request()->search, \FILTER_SANITIZE_STRING) . '%');
});
});
}
/**
* Show model action
*
* @param \Illuminate\Http\Request $request
* @param mixed ...$params
* @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory|\Illuminate\Http\JsonResponse
*/
public function show(Request $request, ...$params)
{
/** @var \Illuminate\View\View|\Illuminate\Http\JsonResponse */
$view = call_user_func_array([$this, 'crudShow'], \array_merge([$request], $params));
if ($view instanceof \Illuminate\Http\JsonResponse) {
return $view;
}
/** @var \Illuminate\Database\Eloquent\Collection<\App\Models\Package> */
$packages = Package::get()->keyBy('id')->all();
return view('invoices.show', \array_merge($view->getData(), ['packages' => $packages]));
}
/**
* Crud create view
*
* @param \Kwaadpepper\CrudPolicies\Http\Requests\CrudIndexRequest $request
* @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory
*/
public function create(CrudIndexRequest $request)
{
/** @var \Illuminate\View\View */
$view = $this->crudCreate($request);
$companies = Company::get();
$packages = Package::get();
$taskRowModel = Invoice::getTaskStructure();
return view('invoices.create', \array_merge($view->getData(), [
'companies' => $companies,
'packages' => $packages,
'taskRowModel' => $taskRowModel,
]));
}
/**
* Before store model middleware
*
* @param \App\Models\Invoice $model
* @return void
*/
public function storeModel(Invoice &$model)
{
$this->validateTasks($model);
}
/**
* Before update model middleware
*
* @param \App\Models\Invoice $model
* @return void
* @throws \Illuminate\Validation\ValidationException If invoice is signed.
*/
public function updateModel(Invoice &$model)
{
if ($model->signed_date) {
throw ValidationException::withMessages([
'erreur' => trans('Il n\'est pas possible de mettre a jour un devis qui est signé')
]);
}
$this->validateTasks($model);
}
/**
* Edit model action
*
* @param mixed ...$params
* @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory
*/
public function edit(...$params)
{
/** @var \Illuminate\View\View */
$view = call_user_func_array([$this, 'crudEdit'], $params);
$companies = Company::get();
$packages = Package::get();
$taskRowModel = Invoice::getTaskStructure();
return view('invoices.edit', \array_merge($view->getData(), [
'companies' => $companies,
'packages' => $packages,
'taskRowModel' => $taskRowModel,
]));
}
/**
* Validate Tasks
*
* @param \App\Models\Invoice $invoice
* @return void
* @throws \Illuminate\Validation\ValidationException If tasks are not valid.
*/
private function validateTasks(Invoice $invoice): void
{
$tasks = \collect(\json_decode($invoice->tasks, true))
->map(function ($task) {
if (\is_array($task)) {
return \array_intersect_key($task, Invoice::getTaskStructure());
}
});
$invoice->tasks = Validator::make(['tasks' => $tasks->all()], [
'tasks' => 'required|array|min:1',
'tasks.*' => 'required|array',
'tasks.*.days' => 'required|numeric|min:0.125',
'tasks.*.amount' => 'required|numeric|min:0.125',
'tasks.*.desc' => 'required|string|min:10',
'tasks.*.type' => [
'required', new EnumIsValidRule(TaskType::class)
],
'tasks.*.package' => 'required_if:tasks.*.type,' .
TaskType::package()->value . '|nullable|exists:packages,id',
], [], [
'tasks' => trans('Tâches')
])->validated()['tasks'];
}
/**
* Download Invoice
*
* @param \App\Models\Invoice $invoice
* @return \Symfony\Component\HttpFoundation\Response
*/
public function download(Invoice $invoice)
{
$this->authorize($invoice, 'download');
return $invoice->generateInvoice()
->stream(Str::slug(trans('Devis :appname :date - ref :ref', [
'appname' => config('app.name'),
'date' => $invoice->created_at->isoFormat('YYYY-MM-DD'),
'ref' => $invoice->ref,
])) . '.pdf');
}
/**
* Set signed date
*
* @param \App\Http\Requests\Invoice\InvoiceSetDateRequest $request
* @param \App\Models\Invoice $invoice
* @return \Illuminate\Http\RedirectResponse
* @throws \Illuminate\Validation\ValidationException If already signed.
*/
public function setSignedDate(InvoiceSetDateRequest $request, Invoice $invoice)
{
if ($invoice->signed_date) {
throw ValidationException::withMessages([
'erreur' => trans('La date de signature est déjà actée.')
]);
}
$invoice->signed_date = $request->date;
$invoice->saveOrFail();
return \back()->with('success', trans('La date de signature à bien été enregistrée'));
}
/**
* Set client signed date
*
* @param \App\Http\Requests\Invoice\InvoiceSetDateRequest $request
* @param \App\Models\Invoice $invoice
* @return \Illuminate\Http\RedirectResponse
* @throws \Illuminate\Validation\ValidationException If already signed.
*/
public function setClientSentDate(InvoiceSetDateRequest $request, Invoice $invoice)
{
if ($invoice->sent_client_date) {
throw ValidationException::withMessages([
'erreur' => trans('La date de signature client est déjà actée.')
]);
}
$invoice->sent_client_date = $request->date;
$invoice->saveOrFail();
return \back()->with('success', trans('La date de signature client à bien été enregistrée'));
}
/**
* Set compta signed date
*
* @param \App\Http\Requests\Invoice\InvoiceSetDateRequest $request
* @param \App\Models\Invoice $invoice
* @return \Illuminate\Http\RedirectResponse
* @throws \Illuminate\Validation\ValidationException If already signed.
*/
public function setComptaSentDate(InvoiceSetDateRequest $request, Invoice $invoice)
{
if ($invoice->sent_accounting_date) {
throw ValidationException::withMessages([
'erreur' => trans('La date de signature compta est déjà actée.')
]);
}
$invoice->sent_accounting_date = $request->date;
$invoice->saveOrFail();
return \back()->with('success', trans('La date de signature compta à bien été enregistrée'));
}
}

View file

@ -1,21 +0,0 @@
<?php
namespace App\Http\Controllers;
use App\Models\Label;
use Kwaadpepper\CrudPolicies\Traits\CrudController;
class LabelController extends Controller
{
use CrudController;
/** @var Label */
public static $modelClass = Label::class;
/**
* Crud Layout
*
* @var string
*/
public static $layout = 'layout.app';
}

View file

@ -1,77 +0,0 @@
<?php
namespace App\Http\Controllers;
use App\Models\Log;
use Illuminate\Database\Eloquent\Builder;
use Kwaadpepper\CrudPolicies\Http\Requests\CrudIndexRequest;
use Kwaadpepper\CrudPolicies\Traits\CrudController;
class LogController extends Controller
{
use CrudController {
index as crudIndex;
}
/** @var Log */
public static $modelClass = Log::class;
/**
* Crud Layout
*
* @var string
*/
public static $layout = 'layout.app';
/**
* Index query middleware
*
* @param Builder $query
* @return Builder
*/
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;
}
/**
* Crud index view
*
* @param \Kwaadpepper\CrudPolicies\Http\Requests\CrudIndexRequest $request
* @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory
*/
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());
}
/**
* Before store model middleware
*
* @param \App\Models\Log $log
* @return void
*/
public function storeModel(Log &$log)
{
$log->parent()->associate(request()->site ?? request()->project);
}
}

View file

@ -1,87 +0,0 @@
<?php
namespace App\Http\Controllers;
use App\Models\MacroSchedule\Marker;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\View;
use Kwaadpepper\CrudPolicies\Traits\CrudController;
class MarkerController extends Controller
{
use CrudController;
/** @var \App\Models\MacroSchedule\Marker */
public static $modelClass = Marker::class;
/**
* Crud Layout
*
* @var string
*/
public static $layout = 'layout.app';
/**
* Crud index Hook
*
* @param Builder $query
* @return Builder
*/
public function indexQuery(Builder $query): Builder
{
$parent = request()->project;
if ($parent) {
$query->whereHas('project', function ($q) use ($parent) {
return $q->whereId($parent->id);
});
}
return $query;
}
/**
* Show create page middleware
*
* @return void
*/
public function createModel()
{
$this->shareLabelsToView();
}
/**
* Show edit model middleware
*
* @param Model $model
* @return void
* @phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClass
*/
public function editModel(Model &$model)
{
$this->shareLabelsToView();
}
/**
* Before store model middleware
*
* @param \App\Models\MacroSchedule\Marker $marker
* @return void
*/
public function storeModel(Marker &$marker)
{
$marker->project()->associate(request()->project);
}
/**
* Share Marker labels to view
*
* @return void
*/
protected function shareLabelsToView()
{
View::share('markerLabels', Cache::remember('markers_labels', 20, function () {
return Marker::pluck('label');
}));
}
}

View file

@ -1,22 +0,0 @@
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use App\Models\Package;
use Kwaadpepper\CrudPolicies\Traits\CrudController;
class PackageController extends Controller
{
use CrudController;
/** @var \App\Models\MacroSchedule\Marker */
public static $modelClass = Package::class;
/**
* Crud Layout
*
* @var string
*/
public static $layout = 'layout.app';
}

View file

@ -1,71 +0,0 @@
<?php
namespace App\Http\Controllers;
use App\Models\Project;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Kwaadpepper\CrudPolicies\Http\Requests\CrudIndexRequest;
use Kwaadpepper\CrudPolicies\Traits\CrudController;
class ProjectController extends Controller
{
use CrudController {
__construct as __CrudConstructor;
index as crudIndex;
show as crudShow;
}
/**
* ProjectController
*/
public function __construct()
{
parent::__construct();
$this->__CrudConstructor();
$this->authorizeResource(Project::class, 'project');
}
/** @var \App\Models\Project */
public static $modelClass = Project::class;
/**
* Crud Layout
*
* @var string
*/
public static $layout = 'layout.app';
/**
* Crud index view
*
* @param \Kwaadpepper\CrudPolicies\Http\Requests\CrudIndexRequest $request
* @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory
*/
public function index(CrudIndexRequest $request)
{
/** @var \Illuminate\View\View */
$view = $this->crudIndex($request);
if ($request->ajax()) {
return $view;
}
return view('projects.index', $view->getData());
}
/**
* Crud show view
*
* @param \Illuminate\Http\Request $request
* @param \App\Models\Project $model
* @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory
*/
public function show(Request $request, Project $model)
{
/** @var \Illuminate\View\View */
$view = $this->crudshow($request, $model);
if ($view instanceof JsonResponse) {
return $view;
}
return view('projects.show', $view->getData());
}
}

View file

@ -1,120 +0,0 @@
<?php
namespace App\Http\Controllers;
use App\Enums\ProjectStatus;
use App\Http\Requests\MacroSchedule\PostActivityRequest;
use App\Http\Requests\MacroSchedule\ShowMacroScheduleRequest;
use App\Models\MacroSchedule\Activity;
use App\Models\Project;
use Illuminate\Support\Carbon;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;
class ScheduleMacroController extends Controller
{
/**
* View Macro planning
*
* @param \App\Http\Requests\MacroSchedule\ShowMacroScheduleRequest $request
* @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory
*/
public function show(ShowMacroScheduleRequest $request)
{
$numberOfWeeksToShow = \config('macroschedule.numberOfWeeksToShow');
$date = Carbon::now();
if ($request->date) {
$date = Carbon::createFromFormat('d/m/Y', $request->date);
}
/** @var \Illuminate\Support\Carbon $date The date from which to take activities */
$date->startOfWeek();
/** @var \Illuminate\Support\Collection $projects */
$projects = Project::where('status', '>', ProjectStatus::new())
->where('status', '<', ProjectStatus::finished())
->with(['activities' => function ($q) use ($date, $numberOfWeeksToShow) {
$q->whereDate('start', '>=', $date->toDateString())
->OrWhereDate('end', '<=', $date->clone()->addWeeks($numberOfWeeksToShow)->toDateString());
}])->with('markers')->orderBy('status')->orderBy('name')->get()->keyBy('id');
// * Key by date activities relation
$projects->map(function (Project $project) {
$project->setRelation('activities', $project->activities->keyBy('id'));
});
// * Map activities by datetime
$activities = collect();
$projects->pluck('activities')->map(function (Collection $projectActivities) use (&$activities) {
$projectActivities->map(function (Activity $activity) use (&$activities) {
$activities->push($activity);
});
});
// * Disponibility calculation
$loadCollection = collect();
/** @var array<\Illuminate\Support\Carbon> */
$period = $date->toPeriod($date->clone()->addWeeks($numberOfWeeksToShow), 12, 'hour')->toArray();
foreach ($period as $day) {
/** @var \Illuminate\Support\Collection */
$dayActivities = $activities->filter(function (Activity $activity) use ($day) {
return $day->betweenIncluded($activity->start, $activity->end);
});
/** @var integer total activités / hommes / demi journées */
$totalLoad = $dayActivities->sum('load');
$loadCollection->put($day->format('Y-m-d H:i:s'), $totalLoad / config('macroschedule.totalAvailableDevs'));
}
return view('macroplanning.view', compact(
'date',
'projects',
'date',
'numberOfWeeksToShow',
'loadCollection'
));
}
/**
* Save activity.
*
* @param PostActivityRequest $request
* @return \Illuminate\Http\JsonResponse
*/
public function postActivity(PostActivityRequest $request)
{
return DB::transaction(function () use ($request) {
$hasOverLap = false;
/** @var \App\Models\Project */
$project = Project::whereId($request->project_id)
->with('activities')->firstOrFail();
/** @var \App\Models\MacroSchedule\Activity */
$activity = Activity::whereId($request->id)->firstOrNew();
$activity->fill($request->validated());
$activity->project()->associate($project);
if (!$activity->saveOrFail()) {
response()->json('Une erreur est survenue lors de \'enregistrement');
}
// * Overload activities if necessary
$project->activities->map(function (Activity $periodActivity) use ($activity, &$hasOverLap) {
if (
$activity->id !== $periodActivity->id and
$activity->doesPeriodCoverActivity($periodActivity->start, $periodActivity->end)
) {
$hasOverLap = true;
$periodActivity->overlapUsingActivity($activity);
}
});
return response()->json([
'id' => $activity->id,
'hasOverlap' => $hasOverLap
]);
});
}
}

View file

@ -1,51 +0,0 @@
<?php
namespace App\Http\Controllers;
use App\Models\Site;
use Kwaadpepper\CrudPolicies\Http\Requests\CrudIndexRequest;
use Kwaadpepper\CrudPolicies\Traits\CrudController;
class SiteController extends Controller
{
use CrudController {
__construct as __CrudConstructor;
index as crudIndex;
}
/**
* SiteController
*/
public function __construct()
{
parent::__construct();
$this->__CrudConstructor();
$this->authorizeResource(Site::class, 'site');
}
/** @var Site */
public static $modelClass = Site::class;
/**
* Crud Layout
*
* @var string
*/
public static $layout = 'layout.app';
/**
* Site.index crud
*
* @param CrudIndexRequest $request
* @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory
*/
public function index(CrudIndexRequest $request)
{
/** @var \Illuminate\View\View */
$view = $this->crudIndex($request);
if ($request->ajax()) {
return $view;
}
return view('sites.index', $view->getData());
}
}

View file

@ -1,37 +0,0 @@
<?php
namespace App\Http\Controllers;
use App\Models\Ticket\TicketType;
use Kwaadpepper\CrudPolicies\Traits\CrudController;
class TicketTypeController extends Controller
{
use CrudController {
edit as crudEdit;
}
/** @var \App\Models\MacroSchedule\Marker */
public static $modelClass = TicketType::class;
/**
* Crud Layout
*
* @var string
*/
public static $layout = 'layout.app';
/**
* Edit model action
*
* @param mixed ...$params
* @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory
*/
public function edit(...$params)
{
/** @var \Illuminate\View\View */
$view = call_user_func_array([$this, 'crudEdit'], $params);
return view('ticket_types.edit', \array_merge($view->getData()));
}
}

View file

@ -1,116 +0,0 @@
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Auth\ForgotPasswordController;
use App\Models\User;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Http\Request;
use Kwaadpepper\CrudPolicies\Traits\CrudController;
class UserController extends Controller
{
use CrudController {
__construct as __CrudConstructor;
}
/**
* UserController
*/
public function __construct()
{
parent::__construct();
$this->__CrudConstructor();
$this->authorizeResource(User::class, 'user');
}
/** @var User */
public static $modelClass = User::class;
/**
* Crud Layout
*
* @var string
*/
public static $layout = 'layout.app';
/**
* After store model middleware
*
* @param Model $model
* @return void
*/
public function storedModel(Model &$model)
{
/** @var \App\Models\User */
$model = $model;
$model->sendMailConfirm();
}
/**
* Password reset form
*
* @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory
*/
public function passwordReset()
{
return view('users.passwordReset');
}
/**
* Password reset submit
*
* @return \Illuminate\Http\RedirectResponse
*/
public function passwordResetSubmit()
{
/** @var \App\Models\User */
$user = auth()->user();
$request = new Request(['email' => $user->email]);
return app(ForgotPasswordController::class)->sendResetLinkEmail($request);
}
/**
* Show stats
*
* TODO: refator this using carbon.
*
* @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory
*/
public function stats()
{
/** @var \App\Models\User */
$user = auth()->user();
$stats = [];
$curYear = date('Y');
for ($i = 2021; $i <= $curYear; $i++) {
$start = $i . '-03-01';
$end = $i + 1 . '-02-' . $this->getLastDayFebruary($i + 1);
$datas = $user->schedules()->selectRaw('count(id) as nb, activity')
->whereBetween('date', [$start, $end])
->groupBy('activity')
->orderBy('activity', 'ASC')
->get();
$stats[sprintf("%d/%d", $i, $i + 1)] = $datas;
}
return view('users.stats', ['stats' => array_reverse($stats)]);
}
/**
* Get february last day date of the year
*
* @param integer $year
* @return integer 28 or 29
*/
private function getLastDayFebruary(int $year): int
{
if ((is_int($year / 4) && !is_int($year / 100)) || is_int($year / 400)) {
return 29;
}
return 28;
}
}

View file

@ -11,12 +11,12 @@ class Kernel extends HttpKernel
*
* These middleware are run during every request to your application.
*
* @var array
* @var array<int, class-string|string>
*/
protected $middleware = [
\App\Http\Middleware\TrustHosts::class,
\App\Http\Middleware\TrustProxies::class,
\Fruitcake\Cors\HandleCors::class,
\Illuminate\Http\Middleware\HandleCors::class,
\App\Http\Middleware\PreventRequestsDuringMaintenance::class,
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
\App\Http\Middleware\TrimStrings::class,
@ -26,19 +26,24 @@ class Kernel extends HttpKernel
/**
* The application's route middleware groups.
*
* @var array
* @var array<string, array<int, class-string|string>>
*/
protected $middlewareGroups = [
'web' => [
'htmlsanitize',
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\App\Http\Middleware\StartSession::class,
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
\App\Http\Middleware\SecureHeaders::class,
'htmlsanitize'
]
],
'api' => [
\Illuminate\Routing\Middleware\ThrottleRequests::class . ':api',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
];
/**
@ -46,17 +51,18 @@ class Kernel extends HttpKernel
*
* These middleware may be assigned to groups or used individually.
*
* @var array
* @var array<string, class-string|string>
*/
protected $routeMiddleware = [
'auth' => \App\Http\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'auth.session' => \Illuminate\Session\Middleware\AuthenticateSession::class,
'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
'is-admin' => \App\Http\Middleware\IsAdmin::class,
'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
'signed' => \App\Http\Middleware\ValidateSignature::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
'htmlsanitize' => \App\Http\Middleware\HtmlSanitizer::class,

View file

@ -3,20 +3,38 @@
namespace App\Http\Middleware;
use Illuminate\Auth\Middleware\Authenticate as Middleware;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Session;
class Authenticate extends Middleware
{
/**
* Get the path the user should be redirected to when they are not authenticated.
*
* @param mixed $request
* @param \Illuminate\Http\Request $request
* @return string|null
*/
protected function redirectTo($request)
protected function redirectTo(Request $request): ?string
{
/** @var \Illuminate\Http\Request $request */
if (! $request->expectsJson()) {
$logins = [
'backend' => route('login')
];
if (!$request->expectsJson()) {
// * Notify must login
Session::flash('warning', trans('Veuillez vous connecter pour continuer'));
foreach ($request->route()->gatherMiddleware() as $middleware) {
if (\is_string($middleware) and strpos($middleware, 'auth:') !== false) {
$route = $logins[str_replace('auth:', '', $middleware)] ?? null;
if ($route) {
return $route;
}
}
}
return route('login');
}
abort(401);
return null;
}
}

View file

@ -9,8 +9,7 @@ class EncryptCookies extends Middleware
/**
* The names of the cookies that should not be encrypted.
*
* @var array
* @var array<int, string>
*/
protected $except = [
];
protected $except = [];
}

View file

@ -2,8 +2,9 @@
namespace App\Http\Middleware;
use App\Lib\ToolboxHelper;
use App\Lib\Helpers\ToolboxHelper;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
class HtmlSanitizer
{
@ -12,15 +13,22 @@ class HtmlSanitizer
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @param mixed ...$params
* @return mixed
* @param string|array ...$params
* @return \Symfony\Component\HttpFoundation\Response
*/
public function handle(Request $request, \Closure $next, ...$params)
public function handle(Request $request, \Closure $next, string|array ...$params): Response
{
$inputs = $request->all();
/** @var callable|null */
$cleanInput = null;
$cleanInput = function (&$input, $name, $rootName = null) use ($params, &$cleanInput) {
$cleanInput = function (
null|string|array &$input,
string $name,
?string $rootName = null
) use (
$params,
&$cleanInput
): void {
// * Nested element array
if (is_array($input)) {
array_walk_recursive($input, $cleanInput, $name);
@ -32,7 +40,7 @@ class HtmlSanitizer
// ? Is a json input ?
if ($isJson = \json_decode($input, true) and is_array($isJson)) {
// ! Decode each json field recursive.
\array_walk_recursive($isJson, function (&$item) {
\array_walk_recursive($isJson, function (string|array &$item) {
if (\is_string($item)) {
$item = clean($item);
$item = ToolboxHelper::stripCkEditorSchemesOnMediaInputs($item);

View file

@ -21,6 +21,6 @@ class IsAdmin
if ($user->isAdmin()) {
return $next($request);
}
return redirect()->route('home');
return redirect()->route('bo.home');
}
}

View file

@ -9,7 +9,7 @@ class PreventRequestsDuringMaintenance extends Middleware
/**
* The URIs that should be reachable while maintenance mode is enabled.
*
* @var array
* @var array<int, string>
*/
protected $except = [];
}

View file

@ -2,28 +2,38 @@
namespace App\Http\Middleware;
use App\Providers\RouteServiceProvider;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Symfony\Component\HttpFoundation\Response;
class RedirectIfAuthenticated
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @param string|null ...$guards
* @return mixed
* @param \Illuminate\Http\Request $request
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
* @param string|null ...$guards
* @return \Symfony\Component\HttpFoundation\Response
* @throws \RuntimeException If guard is unhandled.
* @phpcs:disable Squiz.Commenting.FunctionComment.IncorrectTypeHint
*/
public function handle(Request $request, Closure $next, ...$guards)
public function handle(Request $request, \Closure $next, ...$guards): Response
{
// phpcs:enable phpcs:disable
$guards = empty($guards) ? [null] : $guards;
foreach ($guards as $guard) {
if (Auth::guard($guard)->check()) {
return redirect(RouteServiceProvider::HOME);
switch ($guard) {
case 'backend':
if (!$request->routeIs('bo.*')) {
continue;
}
return \redirect()->route('bo.dashboard');
default:
throw new \RuntimeException("Unhandled guard `{$guard}` .");
}
}
}

View file

@ -6,6 +6,8 @@ use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use Illuminate\Support\Facades\View;
use Illuminate\Support\Facades\Vite;
use Symfony\Component\HttpFoundation\Response;
class SecureHeaders
{
@ -24,17 +26,20 @@ class SecureHeaders
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse
* @param \Illuminate\Http\Request $request
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
* @return \Symfony\Component\HttpFoundation\Response
* @phpcs:disable Squiz.Commenting.FunctionComment.IncorrectTypeHint
*/
public function handle(Request $request, Closure $next)
public function handle(Request $request, Closure $next): Response
{
View::share('nonce', $nonce = \uniqid());
// phpcs:enable
View::share('nonce', $nonce = Vite::useCspNonce());
// * For VueJS dev tool to execute
$jsDev = config('app.debug') ? "'unsafe-eval' 'unsafe-inline'" : "'nonce-$nonce'";
$jsDev = config('app.debug') ? "'unsafe-eval' 'unsafe-inline'" : "'nonce-{$nonce}' 'strict-dynamic'";
$scheme = config('app.env') === 'local' ? 'http' : 'https';
$reportUri = Route::has('cspReportUri') ?
\sprintf('report-uri %s', \parse_url(route('cspReportUri'), \PHP_URL_PATH)) : '';
\sprintf(' report-uri %s ;', \parse_url(route('cspReportUri'), \PHP_URL_PATH)) : '';
$this->removeUnwantedHeaders($this->unwantedHeaderList);
$response = $next($request);
$response->headers->set('Referrer-Policy', 'no-referrer-when-downgrade');
@ -44,20 +49,37 @@ class SecureHeaders
$response->headers->set('Strict-Transport-Security', 'max-age=31536000; includeSubDomains;');
$cspPolicies = [
"default-src 'none';",
// * CKEDITOR Specific https://ckeditor.com/docs/ckeditor5/latest/installation/advanced/csp.html
"connect-src 'self';",
"img-src * data:;",
"frame-src *;",
"manifest-src 'self';",
"font-src 'self' https://fonts.gstatic.com;",
// ! Using CKEditor wiill must have unsafe-inline style
// * CKEDITOR Specific https://ckeditor.com/docs/ckeditor5/latest/installation/advanced/csp.html
"connect-src 'self' blob:;",
"img-src * data: blob:;",
"frame-src 'self' " . implode(' ', [
'https://www.google.com/recaptcha/',
'https://recaptcha.google.com/recaptcha/',
'https://www.google.com/maps/'
]) . ';',
"font-src 'self' data: https://fonts.gstatic.com;",
// ! Using CKEditor will must have unsafe-inline style
// phpcs:ignore Generic.Files.LineLength.TooLong
"style-src 'self' 'unsafe-inline' https://fonts.googleapis.com;",
"style-src 'self' 'unsafe-inline' " . \implode(' ', [
'https://cdnjs.cloudflare.com',
// * File Manager
'https://fonts.googleapis.com',
'https://cdn.jsdelivr.net',
'https://use.fontawesome.com',
'https://fonts.googleapis.com'
]) . ';',
// ! If you dont use ckeditor use this
// "style-src 'self' 'nonce-$nonce' https://fonts.googleapis.com;",
// "style-src 'self' 'nonce-$nonce';",
// phpcs:ignore Generic.Files.LineLength.TooLong
"script-src 'self' https: $jsDev https://cdnjs.cloudflare.com;"
"script-src 'self' {$jsDev} " . \implode(' ', [
'https: blob:',
'https://www.googletagmanager.com',
'https://cdnjs.cloudflare.com',
"$scheme://www.google-analytics.com",
]) . ';'
];
$response->headers->set(
'Content-Security-Policy',
implode(' ', $cspPolicies) . $reportUri

View file

@ -1,22 +0,0 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Session\Middleware\StartSession as MiddlewareStartSession;
class StartSession extends MiddlewareStartSession
{
/**
* Save the session data to storage.
*
* @param mixed $request
* @return void
*/
protected function saveSession($request)
{
/** @var \Illuminate\Http\Request $request */
if (!$request->is('/ping')) {
parent::saveSession($request);
}
}
}

Some files were not shown because too many files have changed in this diff Show more