Fix minicrud usage + add Video on concepts bloc
This commit is contained in:
parent
05ec9be065
commit
ee09078cc2
17 changed files with 408 additions and 239 deletions
|
|
@ -22,4 +22,5 @@ enum InputType: int
|
|||
case text = 12;
|
||||
case url = 13;
|
||||
case videoVimeo = 14;
|
||||
case videoYoutube = 15;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@ class SecureHeaders
|
|||
]) . ';',
|
||||
"img-src * data: blob:;",
|
||||
'frame-src ' . implode(' ', [
|
||||
'https://www.youtube.com',
|
||||
'https://www.google.com/recaptcha/',
|
||||
'https://recaptcha.google.com/recaptcha/',
|
||||
'https://www.google.com/maps/'
|
||||
|
|
|
|||
|
|
@ -11,6 +11,13 @@ class StoreConceptRequest extends UpdateMiniCrudRequest
|
|||
{
|
||||
use HasPicture;
|
||||
|
||||
/**
|
||||
* The model parameter name
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $modelName = 'concept';
|
||||
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
|
|
@ -57,6 +64,7 @@ class StoreConceptRequest extends UpdateMiniCrudRequest
|
|||
'picture_title' => 'required|min:3|max:255',
|
||||
];
|
||||
return \array_merge(
|
||||
parent::rules(),
|
||||
$rules,
|
||||
$this->pictureRules('picture', 1512, 354, 1512, 354, false),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -11,6 +11,13 @@ class StoreSliderRequest extends UpdateMiniCrudRequest
|
|||
{
|
||||
use HasPicture;
|
||||
|
||||
/**
|
||||
* The model parameter name
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $modelName = 'slider';
|
||||
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
|
|
@ -60,6 +67,7 @@ class StoreSliderRequest extends UpdateMiniCrudRequest
|
|||
];
|
||||
return \array_merge(
|
||||
$rules,
|
||||
parent::rules(),
|
||||
$this->pictureRules('picture', 1270, 930, 1270, 930, false),
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,6 +45,11 @@ abstract class UpdateMiniCrudRequest extends FormRequest
|
|||
"data.$iptName.value" => $this->compileValidate('required|numeric', $input)
|
||||
]);
|
||||
break;
|
||||
case InputType::videoYoutube->value:
|
||||
$rules = array_merge($rules, [
|
||||
"data.$iptName.value" => $this->compileValidate('regex:%([^"&?\/\s]{11})%i', $input)
|
||||
]);
|
||||
break;
|
||||
case InputType::string->value:
|
||||
$rules = array_merge($rules, [
|
||||
"data.$iptName.value" => $this->compileValidate('required|string|min:3', $input)
|
||||
|
|
@ -65,37 +70,53 @@ abstract class UpdateMiniCrudRequest extends FormRequest
|
|||
return $rule;
|
||||
});
|
||||
$rules = array_merge($rules, [
|
||||
"data.$iptName.text" => $mergeRules
|
||||
"data.$iptName.value" => $mergeRules
|
||||
]);
|
||||
break;
|
||||
case InputType::image->value:
|
||||
$ipt = $this->data[$iptName];
|
||||
$max = isset($ipt['dimensionsMax']);
|
||||
$dim = collect(explode(
|
||||
$required = $this->isUpdate() ? 'sometimes' : 'required';
|
||||
|
||||
$ipt = $this->data[$iptName];
|
||||
$max = isset($ipt['dimensionsMax']);
|
||||
$dim = \is_string($input['dimensions']) ? collect(explode(
|
||||
',',
|
||||
$ipt['dimensionsMax'] ?? $input['dimensions']
|
||||
(isset($ipt['dimensionsMax']) and is_string($ipt['dimensionsMax'])) ?
|
||||
$ipt['dimensionsMax'] : $input['dimensions']
|
||||
))->mapWithKeys(function ($v) {
|
||||
$v = explode(' ', $v);
|
||||
return [$v[0] => $v[1]];
|
||||
});
|
||||
}) : $input['dimensions'];
|
||||
|
||||
// * Adapt dimensions
|
||||
$sizes = (object)[
|
||||
'minHeight' => $dim['height'],
|
||||
'maxHeight' => $dim['height'],
|
||||
'minWith' => $dim['width'],
|
||||
'maxWith' => $dim['width'],
|
||||
];
|
||||
$rules = array_merge($rules, [
|
||||
"data.$iptName.value" => $this->compileValidate(
|
||||
"data.$iptName.value" => [
|
||||
function (string $attribute, $value, callable $fail) use ($sizes) {
|
||||
return ToolboxHelper::validatePicture($attribute, $value, $fail, $sizes);
|
||||
}
|
||||
],
|
||||
$this->compileValidate(
|
||||
implode('|', [
|
||||
'required',
|
||||
$required,
|
||||
'image',
|
||||
'mimes:png,jpg,jpeg',
|
||||
sprintf(
|
||||
'dimensions:%s=%d,%s=%d',
|
||||
$max ? 'max_height' : 'height',
|
||||
$dim['hauteur'],
|
||||
$dim['height'],
|
||||
$max ? 'max_width' : 'width',
|
||||
$dim['largeur']
|
||||
$dim['width']
|
||||
)
|
||||
]),
|
||||
$input
|
||||
),
|
||||
"data.$iptName.alt" => $this->compileValidate('required|string|min:5', $input),
|
||||
"data.$iptName.title" => $this->compileValidate('required|string|min:5', $input)
|
||||
"data.$iptName.alt" => $this->compileValidate("$required|string|min:5", $input),
|
||||
"data.$iptName.title" => $this->compileValidate("$required|string|min:5", $input)
|
||||
]);
|
||||
break;
|
||||
case InputType::url->value:
|
||||
|
|
@ -153,4 +174,14 @@ abstract class UpdateMiniCrudRequest extends FormRequest
|
|||
}
|
||||
return \implode('|', $out);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this request an update request ?
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
private function isUpdate(): bool
|
||||
{
|
||||
return $this->isMethod('PUT');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,9 @@ namespace App\Lib\Helpers;
|
|||
use Illuminate\Contracts\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\File;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
|
|
@ -321,4 +323,88 @@ class ToolboxHelper
|
|||
throw new \RuntimeException('Cannot handle $input of type ' . \gettype($input));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate picture
|
||||
*
|
||||
* @param string $attribute
|
||||
* @param string|null $value
|
||||
* @param callback $fail
|
||||
* @param object $sizes
|
||||
* @return void
|
||||
*/
|
||||
public static function validatePicture(string $attribute, string|null $value, callable $fail, object $sizes)
|
||||
{
|
||||
if (!($useStorage = Storage::exists($value)) and !File::exists($value)) {
|
||||
$fail(trans(':attribute n\'existe pas dans le système de fichier', [
|
||||
'attribute' => $attribute
|
||||
]));
|
||||
return;
|
||||
}
|
||||
/** @var string */
|
||||
$fileFullPath = self::getUploadedFileFullPath($value, $useStorage);
|
||||
if (
|
||||
!\in_array(self::getUploadedFileMimeType($value, $useStorage), [
|
||||
'image/jpeg', 'image/jpg', 'image/png', 'image/gif'
|
||||
])
|
||||
) {
|
||||
$fail(trans(':attribute doit être une image de type \'image/jpeg,image/jpg,image/png,image/gif\'', [
|
||||
'attribute' => $attribute
|
||||
]));
|
||||
}
|
||||
if (!($dimensions = \getimagesize($fileFullPath)) or !isset($dimensions[0]) or !isset($dimensions[1])) {
|
||||
$fail(trans(':attribute impossible de valider les dimensions', [
|
||||
'attribute' => $attribute
|
||||
]));
|
||||
} else {
|
||||
$width = intval($dimensions[0]);
|
||||
$height = intval($dimensions[1]);
|
||||
|
||||
$xMessage = trans(
|
||||
":attribute la largeur doit être comprise entre {$sizes->minWith}px et {$sizes->maxWith}px"
|
||||
);
|
||||
if ($sizes->minWith === $sizes->maxWith) {
|
||||
$xMessage = trans(":attribute la largeur doit être de {$sizes->minWith}px");
|
||||
}
|
||||
$yMessage = trans(
|
||||
":attribute la hauteur doit être comprise entre {$sizes->minWith}px et {$sizes->maxWith}px"
|
||||
);
|
||||
if ($sizes->minHeight === $sizes->maxHeight) {
|
||||
$yMessage = trans(":attribute la hauteur doit être de {$sizes->minWith}px");
|
||||
}
|
||||
|
||||
if (($width < $sizes->minWith) or ($width > $sizes->maxWith)) {
|
||||
$fail($xMessage);
|
||||
}
|
||||
if (($height < $sizes->minHeight) or ($height > $sizes->maxHeight)) {
|
||||
$fail($yMessage);
|
||||
}
|
||||
} //end if
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the file full path
|
||||
*
|
||||
* @param string $value
|
||||
* @param boolean $useStorage
|
||||
* @return string
|
||||
*/
|
||||
private static function getUploadedFileFullPath(string $value, bool $useStorage): string
|
||||
{
|
||||
/** @var \Illuminate\Filesystem\FilesystemAdapter */
|
||||
$disk = Storage::disk();
|
||||
return !$useStorage ? (realpath($value) ?: $value) : $disk->path($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the file mimetype
|
||||
*
|
||||
* @param string $value
|
||||
* @param boolean $useStorage
|
||||
* @return string|false
|
||||
*/
|
||||
private static function getUploadedFileMimeType(string $value, bool $useStorage)
|
||||
{
|
||||
return !$useStorage ? File::mimeType($value) : Storage::mimeType($value);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -199,115 +199,50 @@ class Concept extends Model
|
|||
string $imgTitle = ''
|
||||
) {
|
||||
$color = $color ?: \collect(ColorsEnum::cases())->random()->value;
|
||||
return [
|
||||
// * BLOC 1
|
||||
"bloc_1_title" => [
|
||||
"label" => "Bloc 1 - Title",
|
||||
"inputType" => InputType::string->value,
|
||||
"value" => $title,
|
||||
"validate" => "required|min:4|max:100"
|
||||
],
|
||||
"bloc_1_color" => [
|
||||
"label" => "Bloc 1 - Color",
|
||||
"inputType" => InputType::selectEnum->value,
|
||||
"value" => $color,
|
||||
"validate" => ["required", "integer", new Enum(ColorsEnum::class)]
|
||||
],
|
||||
"bloc_1_text" => [
|
||||
"label" => "Bloc 1 - Text",
|
||||
"inputType" => InputType::text->value,
|
||||
"value" => $text,
|
||||
"validate" => "string|min:10"
|
||||
],
|
||||
"bloc_1_image" => [
|
||||
"label" => "Bloc 1 - Image",
|
||||
"dimensions" => ["width" => 1140, "height" => 795],
|
||||
"inputType" => InputType::image->value,
|
||||
"alt" => $imgAlt,
|
||||
"title" => $imgTitle,
|
||||
"value" => $img,
|
||||
],
|
||||
// * BLOC 2
|
||||
"bloc_2_title" => [
|
||||
"label" => "Bloc 2 - Title",
|
||||
"inputType" => InputType::string->value,
|
||||
"value" => $title,
|
||||
"validate" => "required|min:4|max:100"
|
||||
],
|
||||
"bloc_2_color" => [
|
||||
"label" => "Bloc 2 - Color",
|
||||
"inputType" => InputType::selectEnum->value,
|
||||
"value" => $color,
|
||||
"validate" => ["required", "integer", new Enum(ColorsEnum::class)]
|
||||
],
|
||||
"bloc_2_text" => [
|
||||
"label" => "Bloc 2 - Text",
|
||||
"inputType" => InputType::text->value,
|
||||
"value" => $text,
|
||||
"validate" => "string|min:10"
|
||||
],
|
||||
"bloc_2_image" => [
|
||||
"label" => "Bloc 2 - Image",
|
||||
"dimensions" => ["width" => 1140, "height" => 795],
|
||||
"inputType" => InputType::image->value,
|
||||
"alt" => $imgAlt,
|
||||
"title" => $imgTitle,
|
||||
"value" => $img,
|
||||
],
|
||||
// * BLOC 3
|
||||
"bloc_3_title" => [
|
||||
"label" => "Bloc 3 - Title",
|
||||
"inputType" => InputType::string->value,
|
||||
"value" => $title,
|
||||
"validate" => "required|min:4|max:100"
|
||||
],
|
||||
"bloc_3_color" => [
|
||||
"label" => "Bloc 3 - Color",
|
||||
"inputType" => InputType::selectEnum->value,
|
||||
"value" => $color,
|
||||
"validate" => ["required", "integer", new Enum(ColorsEnum::class)]
|
||||
],
|
||||
"bloc_3_text" => [
|
||||
"label" => "Bloc 3 - Text",
|
||||
"inputType" => InputType::text->value,
|
||||
"value" => $text,
|
||||
"validate" => "string|min:10"
|
||||
],
|
||||
"bloc_3_image" => [
|
||||
"label" => "Bloc 3 - Image",
|
||||
"dimensions" => ["width" => 1140, "height" => 795],
|
||||
"inputType" => InputType::image->value,
|
||||
"alt" => $imgAlt,
|
||||
"title" => $imgTitle,
|
||||
"value" => $img,
|
||||
],
|
||||
// * BLOC 4
|
||||
"bloc_4_title" => [
|
||||
"label" => "Bloc 4 - Title",
|
||||
"inputType" => InputType::string->value,
|
||||
"value" => $title,
|
||||
"validate" => "required|min:4|max:100"
|
||||
],
|
||||
"bloc_4_color" => [
|
||||
"label" => "Bloc 4 - Color",
|
||||
"inputType" => InputType::selectEnum->value,
|
||||
"value" => $color,
|
||||
"validate" => ["required", "integer", new Enum(ColorsEnum::class)]
|
||||
],
|
||||
"bloc_4_text" => [
|
||||
"label" => "Bloc 4 - Text",
|
||||
"inputType" => InputType::text->value,
|
||||
"value" => $text,
|
||||
"validate" => "string|min:10"
|
||||
],
|
||||
"bloc_4_image" => [
|
||||
"label" => "Bloc 4 - Image",
|
||||
"dimensions" => ["width" => 1140, "height" => 795],
|
||||
"inputType" => InputType::image->value,
|
||||
"alt" => $imgAlt,
|
||||
"title" => $imgTitle,
|
||||
"value" => $img,
|
||||
],
|
||||
];
|
||||
$data = [];
|
||||
for ($i = 1; $i <= 4; $i++) {
|
||||
$data["bloc_{$i}_title"] = [
|
||||
'label' => "Bloc {$i} - Title",
|
||||
'inputType' => InputType::string->value,
|
||||
'value' => $title,
|
||||
'validate' => 'required|min:4|max:100'
|
||||
];
|
||||
$data["bloc_{$i}_color"] = [
|
||||
'label' => "Bloc {$i} - Color",
|
||||
'inputType' => InputType::selectEnum->value,
|
||||
'value' => $color,
|
||||
'validate' => ['required', 'integer', new Enum(ColorsEnum::class)]
|
||||
];
|
||||
$data["bloc_{$i}_text"] = [
|
||||
'label' => "Bloc {$i} - Text",
|
||||
'inputType' => InputType::text->value,
|
||||
'value' => $text,
|
||||
'validate' => 'string|min:10'
|
||||
];
|
||||
$data["bloc_{$i}_image"] = [
|
||||
'label' => "Bloc {$i} - Image",
|
||||
'dimensions' => ['width' => 1140, 'height' => 795],
|
||||
'inputType' => InputType::image->value,
|
||||
'alt' => $imgAlt,
|
||||
'title' => $imgTitle,
|
||||
'value' => $img,
|
||||
'validate' => "required_if:data.bloc_{$i}_has_video.value,false",
|
||||
];
|
||||
|
||||
$data["bloc_{$i}_video_youtube"] = [
|
||||
'label' => "Bloc {$i} - Video",
|
||||
'inputType' => InputType::videoYoutube->value,
|
||||
'value' => '',
|
||||
'validate' => "required_if:data.bloc_{$i}_has_video.value,true|nullable|regex:%([^\"&?\/\s]{11})%i",
|
||||
'required' => false
|
||||
];
|
||||
|
||||
$data["bloc_{$i}_has_video"] = [
|
||||
'label' => "Bloc {$i} - Display video",
|
||||
'inputType' => InputType::boolean->value,
|
||||
'value' => false,
|
||||
];
|
||||
} //end for
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -151,18 +151,19 @@ trait MiniCrudModel
|
|||
$data[$o]['value'] = \preg_replace(
|
||||
'/^\/|^/',
|
||||
'',
|
||||
FileStorageHelper::storeFile($this, $input['value'])
|
||||
FileStorageHelper::storeFile($this, $input['value'], true)
|
||||
);
|
||||
break;
|
||||
case InputType::selectEnum->value:
|
||||
case InputType::boolean->value:
|
||||
case InputType::text->value:
|
||||
case InputType::password->value:
|
||||
case InputType::email->value:
|
||||
case InputType::number->value:
|
||||
case InputType::string->value:
|
||||
case InputType::videoVimeo->value:
|
||||
case InputType::videoYoutube->value:
|
||||
break;
|
||||
case InputType::string->value:
|
||||
case InputType::text->value:
|
||||
case InputType::url->value:
|
||||
ToolboxHelper::assertNoInternalBoUrls('content', $input['value']);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -2,8 +2,7 @@
|
|||
|
||||
namespace App\Traits\Requests;
|
||||
|
||||
use Illuminate\Support\Facades\File;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use App\Lib\Helpers\ToolboxHelper;
|
||||
|
||||
/**
|
||||
* ! This assumes file system is using local storage
|
||||
|
|
@ -67,7 +66,7 @@ trait HasPicture
|
|||
$name => [
|
||||
!$nullable ? 'required' : 'nullable',
|
||||
function (string $attribute, $value, callable $fail) use ($sizes) {
|
||||
return $this->validatePicture($attribute, $value, $fail, $sizes);
|
||||
return ToolboxHelper::validatePicture($attribute, $value, $fail, $sizes);
|
||||
}
|
||||
]
|
||||
];
|
||||
|
|
@ -108,59 +107,6 @@ trait HasPicture
|
|||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate picture
|
||||
*
|
||||
* @param string $attribute
|
||||
* @param string|null $value
|
||||
* @param callback $fail
|
||||
* @param object $sizes
|
||||
* @return void
|
||||
* @phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundBeforeLastUsed
|
||||
*/
|
||||
private function validatePicture(string $attribute, string|null $value, callable $fail, object $sizes)
|
||||
{
|
||||
if (!($useStorage = Storage::exists($value)) and !File::exists($value)) {
|
||||
$fail(trans(":attribute n'existe pas dans le système de fichier"));
|
||||
return;
|
||||
}
|
||||
/** @var string */
|
||||
$fileFullPath = $this->getUploadedFileFullPath($value, $useStorage);
|
||||
if (
|
||||
!\in_array($this->getUploadedFileMimeType($value, $useStorage), [
|
||||
'image/jpeg', 'image/jpg', 'image/png', 'image/gif'
|
||||
])
|
||||
) {
|
||||
$fail(trans(":attribute doit être une image de type 'image/jpeg,image/jpg,image/png,image/gif'"));
|
||||
}
|
||||
if (!($dimensions = \getimagesize($fileFullPath)) or !isset($dimensions[0]) or !isset($dimensions[1])) {
|
||||
$fail(trans(":attribute impossible de valider les dimensions"));
|
||||
} else {
|
||||
$width = intval($dimensions[0]);
|
||||
$height = intval($dimensions[1]);
|
||||
|
||||
$xMessage = trans(
|
||||
":attribute la largeur doit être comprise entre {$sizes->minWith}px et {$sizes->maxWith}px"
|
||||
);
|
||||
if ($sizes->minWith === $sizes->maxWith) {
|
||||
$xMessage = trans(":attribute la largeur doit être de {$sizes->minWith}px");
|
||||
}
|
||||
$yMessage = trans(
|
||||
":attribute la hauteur doit être comprise entre {$sizes->minWith}px et {$sizes->maxWith}px"
|
||||
);
|
||||
if ($sizes->minHeight === $sizes->maxHeight) {
|
||||
$yMessage = trans(":attribute la hauteur doit être de {$sizes->minWith}px");
|
||||
}
|
||||
|
||||
if (($width < $sizes->minWith) or ($width > $sizes->maxWith)) {
|
||||
$fail($xMessage);
|
||||
}
|
||||
if (($height < $sizes->minHeight) or ($height > $sizes->maxHeight)) {
|
||||
$fail($yMessage);
|
||||
}
|
||||
} //end if
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges products pictures fields with request data
|
||||
*
|
||||
|
|
@ -225,30 +171,4 @@ trait HasPicture
|
|||
}
|
||||
} //end if
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the file full path
|
||||
*
|
||||
* @param string $value
|
||||
* @param boolean $useStorage
|
||||
* @return string
|
||||
*/
|
||||
private function getUploadedFileFullPath(string $value, bool $useStorage): string
|
||||
{
|
||||
/** @var \Illuminate\Filesystem\FilesystemAdapter */
|
||||
$disk = Storage::disk();
|
||||
return !$useStorage ? (realpath($value) ?: $value) : $disk->path($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the file mimetype
|
||||
*
|
||||
* @param string $value
|
||||
* @param boolean $useStorage
|
||||
* @return string|false
|
||||
*/
|
||||
private function getUploadedFileMimeType(string $value, bool $useStorage)
|
||||
{
|
||||
return !$useStorage ? File::mimeType($value) : Storage::mimeType($value);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
7
package-lock.json
generated
7
package-lock.json
generated
|
|
@ -32,6 +32,7 @@
|
|||
"eslint": "^8.35.0",
|
||||
"eslint-import-resolver-alias": "^1.1.2",
|
||||
"eslint-plugin-vue": "^9.4.0",
|
||||
"fslightbox": "^3.4.1",
|
||||
"laravel-vite-plugin": "^0.7.2",
|
||||
"postcss": "^8.4.23",
|
||||
"postcss-discard-comments": "^5.1.2",
|
||||
|
|
@ -5178,6 +5179,12 @@
|
|||
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/fslightbox": {
|
||||
"version": "3.4.1",
|
||||
"resolved": "https://registry.npmjs.org/fslightbox/-/fslightbox-3.4.1.tgz",
|
||||
"integrity": "sha512-/YkPP9jCnZMIlPuJPUo10JTCOCntU0vHeIKe0cB5ruR0ss2QCLhzxY5h24grZ2gUsF//0NXik7iGMU05RV/jcg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/function-bind": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@
|
|||
"eslint": "^8.35.0",
|
||||
"eslint-import-resolver-alias": "^1.1.2",
|
||||
"eslint-plugin-vue": "^9.4.0",
|
||||
"fslightbox": "^3.4.1",
|
||||
"laravel-vite-plugin": "^0.7.2",
|
||||
"postcss": "^8.4.23",
|
||||
"postcss-discard-comments": "^5.1.2",
|
||||
|
|
|
|||
|
|
@ -1 +1,8 @@
|
|||
// Empty.
|
||||
|
||||
.youtube-play-button {
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
font-size: 3rem;
|
||||
transform: translateX(-50%) translateY(-50%);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
// ASSETS
|
||||
import.meta.glob(["./../assets/images/**", "./../assets/fonts/**"]);
|
||||
|
||||
import "fslightbox";
|
||||
|
||||
// UTILITIES
|
||||
import "./utilities/bootstrap";
|
||||
import "./utilities/fontawesome";
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ import {
|
|||
faHeader,
|
||||
faCircleCheck,
|
||||
} from "@fortawesome/free-solid-svg-icons";
|
||||
import { faCircleXmark } from "@fortawesome/free-regular-svg-icons";
|
||||
import { faCircleXmark, faCirclePlay } from "@fortawesome/free-regular-svg-icons";
|
||||
|
||||
config.autoReplaceSvg = false;
|
||||
library.add(faEraser);
|
||||
|
|
@ -83,5 +83,6 @@ library.add(faCircleXmark);
|
|||
library.add(faCircleNotch);
|
||||
library.add(faSliders);
|
||||
library.add(faCircleCheck);
|
||||
library.add(faCirclePlay);
|
||||
|
||||
dom.watch();
|
||||
|
|
|
|||
|
|
@ -1,15 +1,37 @@
|
|||
{{-- MINI CRUD EDIT WHEN JSON IS TRANSLATABLE --}}
|
||||
@php
|
||||
$data = (isset($model->data)) ? $model->getEmptyData() : $conceptData;
|
||||
if (isset($model->data)) {
|
||||
($model->data = $model->getTranslation('data', App::currentLocale()));
|
||||
}
|
||||
@endphp
|
||||
@foreach ($data as $k => $input)
|
||||
@php
|
||||
$input = json_decode(json_encode($input), true);
|
||||
@endphp
|
||||
@switch(intval($input['inputType']))
|
||||
@case(intval(App\Enums\InputType::videoYoutube->value))
|
||||
<div class="col-12 col-md-6 mb-3">
|
||||
<fieldset class="border h-100 bg-white p-3">
|
||||
<legend>{{ $input['label'] }} *</legend>
|
||||
<div class="row">
|
||||
<div class="col-12 mb-3">
|
||||
@include('bo.partials.inputs.varchar', [
|
||||
'id' => Str::slug($input['label']),
|
||||
'label' => $input['label'],
|
||||
'hasWordCounter' => true,
|
||||
'name' => 'data['.$k.'][value]',
|
||||
'value' => old("data.{$k}.value", $model->data[$k]['value'] ?? null),
|
||||
'required' => isset($input['required']) ? !empty($input['required']) : true,
|
||||
'model' => $model ?? null,
|
||||
'helper' => __('video id eg: keZURbOo4-M')
|
||||
])
|
||||
@include('modules.input-error', [
|
||||
'inputName' => "data.{$k}.value"
|
||||
])
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
@break
|
||||
|
||||
@case(intval(App\Enums\InputType::url->value))
|
||||
@case(intval(App\Enums\InputType::string->value))
|
||||
<div class="col-12 col-md-6 mb-3">
|
||||
|
|
@ -18,32 +40,60 @@ if (isset($model->data)) {
|
|||
<div class="row">
|
||||
<div class="col-12 mb-3">
|
||||
@include('bo.partials.inputs.varchar', [
|
||||
'id' => Str::slug($input["label"]),
|
||||
'label' => $input['label'] . ' of the ' . __('models.classes.concepts'),
|
||||
'id' => Str::slug($input['label']),
|
||||
'label' => $input['label'],
|
||||
'hasWordCounter' => true,
|
||||
'name' => 'data['.$k.'][value]',
|
||||
'value' => old("data.{$k}.value", $model->data[$k]["value"] ?? null),
|
||||
'required' => true,
|
||||
'value' => old("data.{$k}.value", $model->data[$k]['value'] ?? null),
|
||||
'required' => isset($input['required']) ? !empty($input['required']) : true,
|
||||
'model' => $model ?? null,
|
||||
'helper' => __('validation.between.string', [
|
||||
'attribute' => $input['label'] . ' of the ' . __('models.classes.concepts'),
|
||||
'attribute' => $input['label'],
|
||||
'min' => 3,
|
||||
'max' => 255
|
||||
])
|
||||
])
|
||||
@include('modules.input-error', [
|
||||
'inputName' => "data.{$k}.value"
|
||||
])
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
@break
|
||||
@break
|
||||
|
||||
@case(intval(App\Enums\InputType::number->value))
|
||||
<div class="form-group">
|
||||
<label for="{{ $k }}"><small>{{ $input['label'] }}*</small></label>
|
||||
<input id="{{ $k }}" type="number" step="0.01" class="form-control"
|
||||
name="data[{{ $k }}][value]" placeholder="{{ $input['label'] }}"
|
||||
value="{{ old("data.{$k}.value", ($input['value'] ?? '')) }}" required>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<fieldset class="border p-3 mb-3">
|
||||
<div class="d-flex flex-row justify-content-start align-items-center mb-2">
|
||||
<legend class="w-auto m-0">
|
||||
<label for="number{{$k}}" class="col-form-label">
|
||||
<b>{{ $input['label'] }}</b>
|
||||
</label>
|
||||
</legend>
|
||||
@if(!empty($input['tooltip']))
|
||||
<span class="ms-1" data-bs-toggle="tooltip" data-bs-html="true" title="{{ $input['tooltip'] }}">
|
||||
<i class="fa fa-question-circle"></i>
|
||||
</span>
|
||||
@endif
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<div class="form-group">
|
||||
<input id="number{{$k}}" type="number" step="0.01" class="form-control"
|
||||
aria-describedby="NumberHelp{{$k}}"
|
||||
name="data[{{ $k }}][value]" placeholder="{{ $input['label'] }}"
|
||||
value="{{ old("data.{$k}.value") ?? ($input['value'] ?? '') }}" @if(!isset($input['required']) or $input['required']) required @endif>
|
||||
@include('back::modules.input-error', [
|
||||
'inputName' => "data.{$k}.value",
|
||||
'helperId' => "NumberHelp{$k}",
|
||||
'helper' => $input['helper'] ?? '',
|
||||
])
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
</div>
|
||||
@break
|
||||
|
||||
@case(intval(App\Enums\InputType::text->value))
|
||||
|
|
@ -53,23 +103,49 @@ if (isset($model->data)) {
|
|||
<div class="row mb-3">
|
||||
<div class="col-12">
|
||||
@include('bo.partials.inputs.text-html', [
|
||||
'id' => Str::slug($input["label"]),
|
||||
'name' => 'data['.$k.'][value]',
|
||||
'value' =>old("data.{$k}.value", $model->data[$k]["value"] ?? null),
|
||||
'id' => Str::slug($input['label']),
|
||||
'name' => "data[{$k}][value]",
|
||||
'value' =>old("data.{$k}.value", $model->data[$k]['value'] ?? null),
|
||||
'model' => $model ?? null,
|
||||
'helper' => __('crud.minicrud.text_warning') . '. ' . __('validation.min.string', [
|
||||
'attribute' => $input['label'],
|
||||
'min' => 3
|
||||
]),
|
||||
])
|
||||
@include('modules.input-error', [
|
||||
'inputName' => "data.{$k}.value"
|
||||
])
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
@include('modules.input-error', ['inputName' => 'data['.$k.'][value]'])
|
||||
@break
|
||||
|
||||
@case(intval(App\Enums\InputType::boolean->value))
|
||||
<div class="col-12 col-md-6 mb-3">
|
||||
<fieldset class="border bg-white p-3">
|
||||
<legend>{{ $input['label'] }} *</legend>
|
||||
<div class="row mb-3">
|
||||
<div class="col-12">
|
||||
<label class="col-form-label" for="{{ Str::slug($input['label']) }}"><b>{{ __('crud.minicrud.visibility_label') }}</b></label>
|
||||
<div class="form-check form-switch ms-2">
|
||||
<input
|
||||
id="{{ Str::slug($input['label']) }}"
|
||||
aria-describedby="{{ Str::slug($input['label']) }}Help"
|
||||
name="data[{{ $k }}][value]"
|
||||
type="checkbox"
|
||||
class="ml-2 form-check-input"
|
||||
value="1"
|
||||
@if(old("data.{$k}.value", (old('_token') ? false : ($model->data[$k]['value'] ?? null ?? false)))) checked @endif>
|
||||
</div>
|
||||
@include('modules.input-error', [
|
||||
'inputName' => "data.{$k}.value", 'helperId' => Str::slug($input['label']). 'Help' , 'helper' => __('crud.minicrud.visibility_helper')
|
||||
])
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
@break
|
||||
@case(intval(App\Enums\InputType::image->value))
|
||||
<div class="col-12 mb-3">
|
||||
<fieldset class="border h-100 bg-white p-3">
|
||||
|
|
@ -78,11 +154,11 @@ if (isset($model->data)) {
|
|||
{{-- PICTURE_ALT --}}
|
||||
<div class="col-12 col-md-6 mb-3">
|
||||
@include('bo.partials.inputs.varchar', [
|
||||
'id' => Str::slug($input["label"]) . '-alt',
|
||||
'id' => Str::slug($input['label']) . '-alt',
|
||||
'label' => __('crud.minicrud.picture_alt_label'),
|
||||
'hasWordCounter' => true,
|
||||
'name' => 'data['.$k.'][alt]',
|
||||
'value' => old("data.{$k}.alt", $model->data[$k]["alt"] ?? null),
|
||||
'value' => old("data.{$k}.alt", $model->data[$k]['alt'] ?? null),
|
||||
'required' => true,
|
||||
'model' => $model ?? null,
|
||||
'helper' => __('crud.minicrud.picture_alt_helper') . '. ' . __('validation.min.string', [
|
||||
|
|
@ -90,15 +166,18 @@ if (isset($model->data)) {
|
|||
'min' => 3
|
||||
]),
|
||||
])
|
||||
@include('modules.input-error', [
|
||||
'inputName' => "data.{$k}.alt"
|
||||
])
|
||||
</div>
|
||||
{{-- PICTURE_TITLE --}}
|
||||
<div class="col-12 col-md-6 mb-3">
|
||||
@include('bo.partials.inputs.varchar', [
|
||||
'id' => Str::slug($input["label"]) . '-title',
|
||||
'id' => Str::slug($input['label']) . '-title',
|
||||
'label' => __('crud.minicrud.picture_title_label'),
|
||||
'hasWordCounter' => true,
|
||||
'name' => 'data['.$k.'][title]',
|
||||
'value' => old("data.{$k}.title", $model->data[$k]["title"] ?? null),
|
||||
'value' => old("data.{$k}.title", $model->data[$k]['title'] ?? null),
|
||||
'required' => true,
|
||||
'model' => $model ?? null,
|
||||
'helper' => __('crud.minicrud.picture_title_helper') . '. ' . __('validation.min.string', [
|
||||
|
|
@ -106,16 +185,19 @@ if (isset($model->data)) {
|
|||
'min' => 3
|
||||
]),
|
||||
])
|
||||
@include('modules.input-error', [
|
||||
'inputName' => "data.{$k}.title"
|
||||
])
|
||||
</div>
|
||||
{{-- PICTURE --}}
|
||||
<div class="col-12 mb-3">
|
||||
@include('bo.partials.inputs.varchar-picture', [
|
||||
'id' => Str::slug($input["label"]),
|
||||
'name' => 'data['.$k.'][value]',
|
||||
'id' => Str::slug($input['label']),
|
||||
'name' => "data[{$k}][value]",
|
||||
'width' => $input['dimensions']['width'],
|
||||
'height' => $input['dimensions']['height'],
|
||||
'model' => $model ?? null,
|
||||
'value' => old("data.{$k}.value", $model->data[$k]["value"] ?? null),
|
||||
'value' => old("data.{$k}.value", $model->data[$k]['value'] ?? null),
|
||||
'helper' => __('crud.minicrud.dimensions_must_be', [
|
||||
'width' => $input['dimensions']['width'],
|
||||
'height' => $input['dimensions']['height'],
|
||||
|
|
@ -123,11 +205,45 @@ if (isset($model->data)) {
|
|||
'required' => true,
|
||||
'preview' => true,
|
||||
])
|
||||
@include('modules.input-error', [
|
||||
'inputName' => "data.{$k}.value"
|
||||
])
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
@break
|
||||
@case(App\Enums\InputType::email->value)
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<fieldset class="border p-3 mb-3">
|
||||
<div class="d-flex flex-row justify-content-start align-items-center mb-2">
|
||||
<legend class="w-auto m-0">
|
||||
<label for="title{{$k}}" class="col-form-label">
|
||||
<b>{{ $input['label'] }}</b>
|
||||
</label>
|
||||
</legend>
|
||||
@if(!empty($input['tooltip']))
|
||||
<span class="ms-1" data-bs-toggle="tooltip" data-bs-html="true" title="{{ $input['tooltip'] }}">
|
||||
<i class="fa fa-question-circle"></i>
|
||||
</span>
|
||||
@endif
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<div class="form-group">
|
||||
<input id="title{{$k}}" type="email" class="form-control" name="data[{{$k}}][value]"
|
||||
placeholder="{{ $input['label'] }}" value="{{ old("data.{$k}.value") ?? ($input['value'] ?? '') }}" @if(!isset($input['required']) or $input['required']) required @endif>
|
||||
@include('modules.input-error', [
|
||||
'inputName' => "data.{$k}.value",
|
||||
'helperId' => "{$k}StringHelp",
|
||||
'helper' => $input['helper'] ?? '',
|
||||
])
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
</div>
|
||||
@break
|
||||
@case(intval(App\Enums\InputType::imageArray->value))
|
||||
@case(intval(App\Enums\InputType::labelArray->value))
|
||||
@case(intval(App\Enums\InputType::selectEnum->value))
|
||||
|
|
@ -139,13 +255,16 @@ if (isset($model->data)) {
|
|||
@include('bo.partials.inputs.tinyint-enum', [
|
||||
'id' => Str::slug($input["label"]),
|
||||
'label' => __('crud.minicrud.associated_enum', ['enum' => $input['label']]),
|
||||
'name' => 'data['.$k.'][value]',
|
||||
'name' => "data[{$k}][value]",
|
||||
'model' => $model ?? null,
|
||||
'value' => old("data.{$k}.value", $model->data[$k]["value"] ?? null),
|
||||
'value' => old("data.{$k}.value", $model->data[$k]['value'] ?? null),
|
||||
'required' => true,
|
||||
'associatedModels' => $selectedEnum ?? [],
|
||||
'helper' => __('crud.minicrud.enum_select', ['enum' => $input['label']]),
|
||||
])
|
||||
@include('modules.input-error', [
|
||||
'inputName' => "data.{$k}.value"
|
||||
])
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
|
@ -156,3 +275,21 @@ if (isset($model->data)) {
|
|||
@php throw new Exception('Input type not handled'); @endphp
|
||||
@endswitch
|
||||
@endforeach
|
||||
|
||||
@push('scripts')
|
||||
<script nonce="{{ $nonce }}">
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
let minicrud = document.getElementById('minicrud').closest('form');
|
||||
if (minicrud) {
|
||||
minicrud.addEventListener('submit', function(e) {
|
||||
document.querySelectorAll('input[type="file"]').forEach(function(input) {
|
||||
if (input.dataset['old-value'] && !input.value) {
|
||||
input.setAttribute('type', 'text');
|
||||
input.value = input.getAttribute('old-value');
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@endpush
|
||||
|
|
|
|||
|
|
@ -143,15 +143,15 @@
|
|||
</div>
|
||||
{{-- MINICRUD --}}
|
||||
<div class="col-12 mb-3">
|
||||
<button class="btn btn-primary col-form-label rounded-0 dropdown-toggle w-100" type="button" data-bs-toggle="collapse" data-bs-target="#collapseExample" aria-expanded="false" aria-controls="collapseExample">
|
||||
<button class="btn btn-primary col-form-label rounded-0 dropdown-toggle w-100" type="button" data-bs-toggle="collapse" data-bs-target="#minicrud" aria-expanded="false" aria-controls="minicrud">
|
||||
<b>{{ __('ALL BLOCS') }}</b>
|
||||
</button>
|
||||
<div class="collapse" id="collapseExample">
|
||||
<div class="collapse" id="minicrud">
|
||||
<div class="card card-body bg-light rounded-0">
|
||||
<div class="row">
|
||||
@include('bo.modules.minicrud-form-inputs', [
|
||||
'model' => $conceptModel ?? $conceptData,
|
||||
'selectedEnum' => \App\Enums\Concepts\ColorsEnum::toArray()
|
||||
'model' => $conceptModel ?? $conceptData,
|
||||
'selectedEnum' => \App\Enums\Concepts\ColorsEnum::toArray()
|
||||
])
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -3,9 +3,32 @@ $color = \App\Enums\Concepts\ColorsEnum::make($conceptModel->data["bloc_{$number
|
|||
@endphp
|
||||
|
||||
<div class="flex flex-wrap flex-row my-3 sm:my-0 sm:even:flex-row sm:odd:flex-row-reverse">
|
||||
@if(!empty($conceptModel->data["bloc_{$number}_has_video"]['value']))
|
||||
<div class="basis-full sm:basis-1/2 flex">
|
||||
<a
|
||||
class="relative w-full"
|
||||
data-fslightbox="https://www.youtube.com/watch?v={{ $conceptModel->data["bloc_{$number}_video_youtube"]['value'] }}"
|
||||
href="https://www.youtube.com/watch?v={{ $conceptModel->data["bloc_{$number}_video_youtube"]['value'] }}"
|
||||
target="_blank"
|
||||
class="position-absolute top-50 start-50 translate-middle"
|
||||
data-fancybox>
|
||||
<img
|
||||
class="w-full"
|
||||
@if(!empty($conceptModel->data["bloc_{$number}_image"]['value']))
|
||||
src="{{ asset($conceptModel->data["bloc_{$number}_image"]['value']) }}"
|
||||
@else
|
||||
src="{{ 'https://i.ytimg.com/vi/' . $conceptModel->data["bloc_{$number}_video_youtube"]['value'] . '/hqdefault.jpg' }}"
|
||||
@endif
|
||||
alt="{{ $conceptModel->data["bloc_{$number}_image"]['alt'] }}"
|
||||
title="{{ $conceptModel->data["bloc_{$number}_image"]['title'] }}">
|
||||
<i class="youtube-play-button absolute top-50 left-50 fa-regular fa-circle-play"></i>
|
||||
</a>
|
||||
</div>
|
||||
@else
|
||||
<div class="basis-full sm:basis-1/2 flex">
|
||||
<img src="{{ asset($conceptModel->data["bloc_{$number}_image"]['value']) }}" alt="{{ $conceptModel->data["bloc_{$number}_image"]['alt'] }}" title="{{ $conceptModel->data["bloc_{$number}_image"]['title'] }}">
|
||||
</div>
|
||||
@endif
|
||||
<div class="basis-full sm:basis-1/2 order-2 text-weiss flex items-center" style="background-color: {{ \App\Enums\Concepts\ColorsEnum::make($color)->color() }}">
|
||||
<div class="p-6 sm:pl-6 sm:py-4 lg:pl-16 lg:py-8 xl:pl-32 xl:py-12 max-w-xl">
|
||||
<h3 class="text-h2-sm md:text-h2-md lg:text-h2-lg xl:text-h2 mb-2 lg:mb-4 font-scarletwood">{{ $conceptModel->data["bloc_{$number}_title"]['value'] }}</h3>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue