Compare commits
20 Commits
2ba5677c45
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| ba137edd1d | |||
| 4297363cea | |||
| efc648bcd7 | |||
| a28f552f96 | |||
| ac2c25bd06 | |||
| 6937deecbe | |||
| 92227fd5f0 | |||
| e1f79a58ec | |||
| 0254b616a9 | |||
| b9856f4bf8 | |||
| a11b9c9100 | |||
| b8a4efadc2 | |||
| 290dd2dddb | |||
| 79304de97a | |||
| 285be8edea | |||
| 519f97debf | |||
| 9cfa2e1664 | |||
| 0bf99a5e26 | |||
| bb733d14c1 | |||
| 3aa4601229 |
@@ -2,87 +2,79 @@
|
||||
|
||||
namespace App\Api;
|
||||
|
||||
use App\Support\Uploads;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Intervention\Image\Facades\Image as Imagee;
|
||||
|
||||
class ImageResize
|
||||
{
|
||||
/**
|
||||
* @param string $type
|
||||
* @return string
|
||||
* @return string relative path used as S3 key, e.g. uploads/posters/thumbs/2024/01/01
|
||||
*/
|
||||
private function mkdir(string $type)
|
||||
private function thumbFolder(string $type): string
|
||||
{
|
||||
$folder = Carbon::now()->format('Y/m/d');
|
||||
$path = "uploads/{$type}/thumbs/{$folder}";
|
||||
|
||||
if (!file_exists(public_path($path))) {
|
||||
mkdir(public_path($path), 0775, true);
|
||||
}
|
||||
|
||||
return $path;
|
||||
return "uploads/{$type}/thumbs/{$folder}";
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $path
|
||||
* @param $size
|
||||
* @param $type
|
||||
* @param bool $deleteOriginal
|
||||
* @return string
|
||||
* @throws \Exception
|
||||
* Resize an image and upload to S3/MinIO (or save locally).
|
||||
*
|
||||
* @param string $path Relative path of the source image (from 'public' disk = storage/app/public/)
|
||||
* @param int $size Target width in pixels
|
||||
* @param string $type Subfolder name (posters, screens, brands …)
|
||||
* @param bool $deleteOriginal Delete the source file after resizing
|
||||
* @return string Relative path (S3 key) of the generated thumb
|
||||
*/
|
||||
public function resize($path, $size, $type, $deleteOriginal = false)
|
||||
public function resize(string $path, int $size, string $type, bool $deleteOriginal = false): string
|
||||
{
|
||||
// 1. Resolve source path
|
||||
$srcPath = file_exists(public_path($path))
|
||||
? public_path($path)
|
||||
: storage_path('app/public/' . $path);
|
||||
// 1. Locate the source file (stored via ->store('temp', 'public'))
|
||||
$srcPath = storage_path('app/public/' . $path);
|
||||
|
||||
if (!file_exists($srcPath)) {
|
||||
if (file_exists($path)) {
|
||||
$srcPath = $path;
|
||||
} else {
|
||||
// Last ditch effort: try to get from S3 if it's not local
|
||||
if (env('FILESYSTEM_DISK') == 's3' && Storage::disk('s3')->exists($path)) {
|
||||
$fileContent = Storage::disk('s3')->get($path);
|
||||
$tmpLocal = storage_path('app/public/temp_' . basename($path));
|
||||
file_put_contents($tmpLocal, $fileContent);
|
||||
$srcPath = $tmpLocal;
|
||||
$deleteOriginal = true; // Clean up the temp download
|
||||
} else {
|
||||
throw new \Exception("Source image not found: " . $path);
|
||||
}
|
||||
}
|
||||
throw new \Exception("Source image not found: {$srcPath}");
|
||||
}
|
||||
|
||||
// 2. Prepare thumb destination
|
||||
$name = basename($path);
|
||||
$folder = $this->mkdir($type);
|
||||
$path_thumb = "{$folder}/{$name}";
|
||||
$absPathThumb = public_path($path_thumb);
|
||||
// 2. Resize into a temp file in storage/app/public/tmp/
|
||||
$tmpDir = storage_path('app/public/tmp');
|
||||
if (!is_dir($tmpDir)) {
|
||||
mkdir($tmpDir, 0775, true);
|
||||
}
|
||||
|
||||
$thumbFilename = basename($path);
|
||||
$tmpThumb = "{$tmpDir}/{$thumbFilename}";
|
||||
|
||||
// 3. Resize and Save Thumb
|
||||
$img = Imagee::make($srcPath);
|
||||
$img->resize($size, null, function ($constraint) {
|
||||
$constraint->aspectRatio();
|
||||
});
|
||||
$img->save($absPathThumb, 100);
|
||||
$img->save($tmpThumb, 90);
|
||||
|
||||
// 4. Handle S3 Upload
|
||||
if (env('FILESYSTEM_DISK') == 's3') {
|
||||
Storage::disk('s3')->put($path_thumb, file_get_contents($absPathThumb));
|
||||
// Remove local thumb after S3 upload
|
||||
if (file_exists($absPathThumb)) {
|
||||
unlink($absPathThumb);
|
||||
// 3. Upload thumb to S3/MinIO
|
||||
$thumbKey = $this->thumbFolder($type) . '/' . $thumbFilename;
|
||||
|
||||
if (config('filesystems.default') === 's3') {
|
||||
Uploads::put($thumbKey, file_get_contents($tmpThumb), 's3');
|
||||
} else {
|
||||
// Local: move to public/uploads/…/thumbs/…
|
||||
$localDir = public_path(dirname($thumbKey));
|
||||
if (!is_dir($localDir)) {
|
||||
mkdir($localDir, 0775, true);
|
||||
}
|
||||
rename($tmpThumb, public_path($thumbKey));
|
||||
}
|
||||
|
||||
// 5. Cleanup original if requested
|
||||
// 4. Clean up tmp thumb
|
||||
if (file_exists($tmpThumb)) {
|
||||
unlink($tmpThumb);
|
||||
}
|
||||
|
||||
// 5. Clean up original temp file if requested
|
||||
if ($deleteOriginal && file_exists($srcPath)) {
|
||||
unlink($srcPath);
|
||||
}
|
||||
|
||||
return $path_thumb;
|
||||
return $thumbKey;
|
||||
}
|
||||
}
|
||||
|
||||
56
app/Console/Commands/StorageHealthCheck.php
Normal file
56
app/Console/Commands/StorageHealthCheck.php
Normal file
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Throwable;
|
||||
|
||||
class StorageHealthCheck extends Command
|
||||
{
|
||||
protected $signature = 'storage:health-check
|
||||
{disk? : Disk name, defaults to filesystems.default}
|
||||
{--keep : Keep the test file so the public URL can be checked in a browser}';
|
||||
|
||||
protected $description = 'Check current storage disk, write/read/delete a test file, and print its public URL.';
|
||||
|
||||
public function handle(): int
|
||||
{
|
||||
$disk = $this->argument('disk') ?: config('filesystems.default');
|
||||
$path = 'healthcheck/' . now()->format('YmdHis') . '-' . uniqid() . '.txt';
|
||||
|
||||
$this->line('default=' . config('filesystems.default'));
|
||||
$this->line('disk=' . $disk);
|
||||
$this->line('endpoint=' . (config("filesystems.disks.{$disk}.endpoint") ?: '-'));
|
||||
$this->line('url=' . (config("filesystems.disks.{$disk}.url") ?: '-'));
|
||||
$this->line('bucket=' . (config("filesystems.disks.{$disk}.bucket") ?: '-'));
|
||||
$this->line('path_style=' . json_encode(config("filesystems.disks.{$disk}.use_path_style_endpoint")));
|
||||
|
||||
try {
|
||||
$stored = Storage::disk($disk)->put($path, 'ok');
|
||||
|
||||
if (!$stored) {
|
||||
$this->error("put=false path={$path}");
|
||||
return self::FAILURE;
|
||||
}
|
||||
|
||||
$exists = Storage::disk($disk)->exists($path);
|
||||
$this->line('put=ok');
|
||||
$this->line('exists=' . ($exists ? 'yes' : 'no'));
|
||||
$this->line('public_url=' . Storage::disk($disk)->url($path));
|
||||
|
||||
if ($this->option('keep')) {
|
||||
$this->warn('delete=skipped');
|
||||
$this->warn('Open public_url in browser or curl it from outside the container.');
|
||||
} else {
|
||||
Storage::disk($disk)->delete($path);
|
||||
$this->line('delete=ok');
|
||||
}
|
||||
} catch (Throwable $e) {
|
||||
$this->error(get_class($e) . ': ' . $e->getMessage());
|
||||
return self::FAILURE;
|
||||
}
|
||||
|
||||
return self::SUCCESS;
|
||||
}
|
||||
}
|
||||
@@ -54,17 +54,8 @@ class Controller extends ExController
|
||||
}
|
||||
|
||||
if ($request->hasFile('image')) {
|
||||
if (env('FILESYSTEM_DISK') == 's3') {
|
||||
// delete old image from s3
|
||||
Storage::disk('s3')->delete($brand->image);
|
||||
$path = $this->storeImageToS3($request->file('image'));
|
||||
} else {
|
||||
// detele old image
|
||||
if (is_file($brand->image)) {
|
||||
unlink($brand->image);
|
||||
}
|
||||
$path = $request->file('image')->store('uploads/brands');
|
||||
}
|
||||
Storage::delete($brand->image);
|
||||
$path = $this->storeImageToS3($request->file('image'));
|
||||
} else {
|
||||
$path = $brand->image;
|
||||
}
|
||||
@@ -87,12 +78,7 @@ class Controller extends ExController
|
||||
}
|
||||
|
||||
if ($request->hasFile('image')) {
|
||||
$file = $request->file('image');
|
||||
if (env('FILESYSTEM_DISK') == 's3') {
|
||||
$path = $this->storeImageToS3($file);
|
||||
} else {
|
||||
$path = $file->store('uploads/brands');
|
||||
}
|
||||
$path = $this->storeImageToS3($request->file('image'));
|
||||
}
|
||||
|
||||
$this->dispatchSync(StoreJob::fromRequest($request, $path));
|
||||
@@ -109,14 +95,7 @@ class Controller extends ExController
|
||||
{
|
||||
$this->authorize('delete', 'brands');
|
||||
|
||||
if (is_file($brand->image)) {
|
||||
unlink($brand->image);
|
||||
}
|
||||
|
||||
// delete image from s3
|
||||
if (env('FILESYSTEM_DISK') == 's3') {
|
||||
Storage::disk('s3')->delete($brand->image);
|
||||
}
|
||||
Storage::delete($brand->image);
|
||||
|
||||
Product::where('brand_id', $brand->id)->withTrashed()->update([
|
||||
'brand_id' => null
|
||||
|
||||
@@ -13,7 +13,10 @@ use App\Jobs\Dashboard\Category\Store as StoreJob;
|
||||
use App\Jobs\Dashboard\Category\Update as UpdateJob;
|
||||
use App\Models\Characteristic;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Throwable;
|
||||
|
||||
class Controller extends ExController
|
||||
{
|
||||
@@ -24,17 +27,46 @@ class Controller extends ExController
|
||||
public function index()
|
||||
{
|
||||
$this->authorize('view', 'categories');
|
||||
$categories = Category::select('id', 'name->ru as category', 'position', 'parent_id', 'image')
|
||||
->where('parent_id', null)
|
||||
->with(['children' => function ($parent) {
|
||||
return $parent->select('id', 'name->ru as category', 'parent_id', 'position', 'image')->orderBy('position', 'asc')->with(['children' => function ($parent) {
|
||||
return $parent->select('id', 'name->ru as category', 'parent_id', 'position', 'image')->orderBy('position', 'asc');
|
||||
}]);
|
||||
}])->orderBy('position', 'asc')->get();
|
||||
$categories = $this->categoryTree();
|
||||
|
||||
return view('dashboard.category.index', compact('categories'));
|
||||
}
|
||||
|
||||
private function categoryTree($parentId = null, array $visited = [])
|
||||
{
|
||||
return Category::select('id', 'name', 'position', 'parent_id', 'image')
|
||||
->when($parentId === null, function ($query) {
|
||||
$query->whereNull('parent_id');
|
||||
}, function ($query) use ($parentId) {
|
||||
$query->where('parent_id', $parentId);
|
||||
})
|
||||
->orderBy('position', 'asc')
|
||||
->get()
|
||||
->map(function (Category $category) use ($visited) {
|
||||
if (in_array($category->id, $visited, true)) {
|
||||
return [
|
||||
'id' => $category->id,
|
||||
'category' => $category->name['ru'] ?? $category->name['uz'] ?? '',
|
||||
'position' => $category->position,
|
||||
'parent_id' => $category->parent_id,
|
||||
'image' => $category->image,
|
||||
'image_url' => $category->image_url,
|
||||
'children' => [],
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
'id' => $category->id,
|
||||
'category' => $category->name['ru'] ?? $category->name['uz'] ?? '',
|
||||
'position' => $category->position,
|
||||
'parent_id' => $category->parent_id,
|
||||
'image' => $category->image,
|
||||
'image_url' => $category->image_url,
|
||||
'children' => $this->categoryTree($category->id, [...$visited, $category->id]),
|
||||
];
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param StoreRequest $request
|
||||
* @return \Illuminate\Contracts\View\Factory|\Illuminate\Http\JsonResponse|\Illuminate\View\View
|
||||
@@ -54,20 +86,39 @@ class Controller extends ExController
|
||||
return view('dashboard.category.store', compact('brands', 'parent_categories'));
|
||||
}
|
||||
|
||||
$category = $this->dispatchSync(new StoreJob($request));
|
||||
try {
|
||||
$category = DB::transaction(function () use ($request) {
|
||||
$category = $this->dispatchSync(new StoreJob($request));
|
||||
|
||||
if (!empty($request->char)) {
|
||||
foreach ($request->char as $char) {
|
||||
Characteristic::create([
|
||||
'name' => $char['name'],
|
||||
'type' => $char['type'],
|
||||
'category_id' => $category->id,
|
||||
'filter' => $char['filter'] == 'true' ? 1 : 0
|
||||
]);
|
||||
}
|
||||
if (!empty($request->char)) {
|
||||
foreach ($request->char as $char) {
|
||||
Characteristic::create([
|
||||
'name' => $char['name'] ?? ['ru' => '', 'uz' => ''],
|
||||
'type' => $char['type'] ?? 'text',
|
||||
'category_id' => $category->id,
|
||||
'filter' => filter_var($char['filter'] ?? false, FILTER_VALIDATE_BOOLEAN)
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
return $category;
|
||||
});
|
||||
} catch (Throwable $exception) {
|
||||
Log::error('Category store failed', [
|
||||
'message' => $exception->getMessage(),
|
||||
'trace' => $exception->getTraceAsString(),
|
||||
]);
|
||||
|
||||
return response()->json([
|
||||
'status' => false,
|
||||
'message' => 'Category could not be saved.',
|
||||
'error' => config('app.debug') ? $exception->getMessage() : null,
|
||||
], 500);
|
||||
}
|
||||
|
||||
$this->success(trans('admin.messages.created'));
|
||||
if ($category) {
|
||||
$this->success(trans('admin.messages.created'));
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'status' => true
|
||||
@@ -102,39 +153,52 @@ class Controller extends ExController
|
||||
return view('dashboard.category.update', compact('parent_categories', 'category', 'brands'));
|
||||
}
|
||||
|
||||
$image = $request->getImage($category);
|
||||
try {
|
||||
$image = $request->getImage($category);
|
||||
|
||||
$this->dispatchSync(new UpdateJob($category, $request, $image));
|
||||
DB::transaction(function () use ($category, $request, $image) {
|
||||
$this->dispatchSync(new UpdateJob($category, $request, $image));
|
||||
|
||||
if (!empty($request->char)) {
|
||||
foreach ($request->char as $char) {
|
||||
if ($char['id'] == null || $char['id'] == 'null') {
|
||||
Characteristic::create([
|
||||
'name' => $char['name'],
|
||||
'type' => $char['type'],
|
||||
'category_id' => $category->id,
|
||||
'filter' => $char['filter'] == 'true' ? 1 : 0
|
||||
]);
|
||||
} else {
|
||||
Characteristic::where('id', $char['id'])->update([
|
||||
'name' => $char['name'],
|
||||
'type' => $char['type'],
|
||||
'filter' => $char['filter'] == 'true' ? 1 : 0
|
||||
]);
|
||||
if (!empty($request->char)) {
|
||||
foreach ($request->char as $char) {
|
||||
if ($char['id'] == null || $char['id'] == 'null') {
|
||||
Characteristic::create([
|
||||
'name' => $char['name'] ?? ['ru' => '', 'uz' => ''],
|
||||
'type' => $char['type'] ?? 'text',
|
||||
'category_id' => $category->id,
|
||||
'filter' => filter_var($char['filter'] ?? false, FILTER_VALIDATE_BOOLEAN)
|
||||
]);
|
||||
} else {
|
||||
Characteristic::where('id', $char['id'])->update([
|
||||
'name' => $char['name'] ?? ['ru' => '', 'uz' => ''],
|
||||
'type' => $char['type'] ?? 'text',
|
||||
'filter' => filter_var($char['filter'] ?? false, FILTER_VALIDATE_BOOLEAN)
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($request->deletes['char'])) {
|
||||
$chars = Characteristic::whereIn('id', $request->deletes['char'])->get();
|
||||
if (!empty($request->deletes['char'])) {
|
||||
$chars = Characteristic::whereIn('id', $request->deletes['char'])->get();
|
||||
|
||||
foreach ($chars as $char) {
|
||||
$char->values()->detach();
|
||||
// foreach ($char->values as $value) {
|
||||
// $value->delete();
|
||||
// }
|
||||
$char->delete();
|
||||
}
|
||||
foreach ($chars as $char) {
|
||||
$char->values()->detach();
|
||||
$char->delete();
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (Throwable $exception) {
|
||||
Log::error('Category update failed', [
|
||||
'category_id' => $category->id,
|
||||
'message' => $exception->getMessage(),
|
||||
'trace' => $exception->getTraceAsString(),
|
||||
]);
|
||||
|
||||
return response()->json([
|
||||
'status' => false,
|
||||
'message' => 'Category could not be saved.',
|
||||
'error' => config('app.debug') ? $exception->getMessage() : null,
|
||||
], 500);
|
||||
}
|
||||
|
||||
$this->success(trans('admin.messages.updated'));
|
||||
@@ -144,7 +208,6 @@ class Controller extends ExController
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param Category $category
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
@@ -155,14 +218,7 @@ class Controller extends ExController
|
||||
$this->authorize('delete', 'categories');
|
||||
$category = Category::findOrFail($category);
|
||||
|
||||
if (is_file($category->image)) {
|
||||
unlink($category->image);
|
||||
}
|
||||
|
||||
// delete image from s3
|
||||
if (env('FILESYSTEM_DISK') == 's3') {
|
||||
Storage::disk('s3')->delete($category->image);
|
||||
}
|
||||
Storage::delete($category->image);
|
||||
|
||||
$category->delete();
|
||||
$this->info(trans('admin.messages.deleted'));
|
||||
@@ -175,29 +231,9 @@ class Controller extends ExController
|
||||
*/
|
||||
public function position_save(Request $request)
|
||||
{
|
||||
foreach ($request->categories as $category) {
|
||||
$cat = Category::find($category['id']);
|
||||
$cat->parent_id = $category['parent_id'] === 'null' ? null : $category['parent_id'];
|
||||
$cat->position = $category['position'];
|
||||
$cat->save();
|
||||
if (!empty($category['children'])) {
|
||||
foreach ($category['children'] as $c) {
|
||||
$cc = Category::find($c['id']);
|
||||
$cc->parent_id = $c['parent_id'] === 'null' ? null : $c['parent_id'];
|
||||
$cc->position = $c['position'];
|
||||
$cc->save();
|
||||
|
||||
if (!empty($c['children'])) {
|
||||
foreach ($c['children'] as $ccc) {
|
||||
$cccc = Category::find($ccc['id']);
|
||||
$cccc->parent_id = $ccc['parent_id'] === 'null' ? null : $ccc['parent_id'];
|
||||
$cccc->position = $ccc['position'];
|
||||
$cccc->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
DB::transaction(function () use ($request) {
|
||||
$this->saveCategoryPositions($request->input('categories', []), null);
|
||||
});
|
||||
|
||||
$this->info(trans('admin.messages.updated'));
|
||||
|
||||
@@ -206,6 +242,34 @@ class Controller extends ExController
|
||||
]);
|
||||
}
|
||||
|
||||
private function saveCategoryPositions(array $categories, $parentId = null): void
|
||||
{
|
||||
foreach (array_values($categories) as $index => $category) {
|
||||
$cat = Category::find($category['id'] ?? null);
|
||||
|
||||
if (!$cat) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$cat->parent_id = $this->normalizeParentId($parentId);
|
||||
$cat->position = $index + 1;
|
||||
$cat->save();
|
||||
|
||||
if (!empty($category['children']) && is_array($category['children'])) {
|
||||
$this->saveCategoryPositions($category['children'], $cat->id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function normalizeParentId($parentId)
|
||||
{
|
||||
if (in_array($parentId, [null, '', 'null', 'NULL', 0, '0'], true)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $parentId;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return array
|
||||
|
||||
@@ -45,23 +45,22 @@ class Controller extends ExController
|
||||
return view('dashboard.compilations.index', compact('compilations'));
|
||||
}
|
||||
|
||||
// public function store(StoreRequest $request)
|
||||
// {
|
||||
// if ($request->isMethod('get')) {
|
||||
// $this->authorize('create', 'compilations');
|
||||
//
|
||||
//// $this->authorize('content-manager');
|
||||
// $categories = $this->categories->where('parent_id', null)->get();
|
||||
// return view('dashboard.compilations.store', compact('categories'));
|
||||
// }
|
||||
//
|
||||
// $this->dispatchSync(new StoreJob($request));
|
||||
//
|
||||
// $this->success(trans('admin.messages.created'));
|
||||
// return response()->json([
|
||||
// 'status' => true
|
||||
// ]);
|
||||
// }
|
||||
public function store(StoreRequest $request)
|
||||
{
|
||||
if ($request->isMethod('get')) {
|
||||
$this->authorize('create', 'compilations');
|
||||
|
||||
$categories = $this->categoryOptions();
|
||||
return view('dashboard.compilations.store', compact('categories'));
|
||||
}
|
||||
|
||||
$this->dispatchSync(new StoreJob($request));
|
||||
|
||||
$this->success(trans('admin.messages.created'));
|
||||
return response()->json([
|
||||
'status' => true
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Compilation $compilation
|
||||
@@ -74,17 +73,20 @@ class Controller extends ExController
|
||||
if ($request->isMethod('get')) {
|
||||
// $this->authorize('content-manager');
|
||||
|
||||
$compilation->loadMissing(['products:id,name,poster']);
|
||||
|
||||
$this->authorize('update', 'compilations');
|
||||
|
||||
foreach ($compilation->products as $product) {
|
||||
$product->poster = '/'. $product->poster;
|
||||
$products = $compilation->dashboardProducts()
|
||||
->select('products.id', 'products.name', 'products.poster')
|
||||
->get();
|
||||
|
||||
foreach ($products as $product) {
|
||||
$product->poster = $product->getPoster();
|
||||
$product->name = $product->name['ru'];
|
||||
}
|
||||
|
||||
$compilation->setRelation('products', $products);
|
||||
|
||||
$categories = $this->categories->where('parent_id', false)->get();
|
||||
$categories = $this->categoryOptions();
|
||||
|
||||
|
||||
return view('dashboard.compilations.update', compact('compilation', 'categories'));
|
||||
@@ -104,12 +106,39 @@ class Controller extends ExController
|
||||
*/
|
||||
public function search(Request $request)
|
||||
{
|
||||
$query = $request->name;
|
||||
$query = trim((string) $request->name);
|
||||
$categoryId = (int) $request->get('category_id');
|
||||
|
||||
$product = $this->products->published()->where('name->ru', 'like', $query . '%')->get()->map(function ($product) {
|
||||
$product = $this->products
|
||||
->newQuery()
|
||||
->whereNull('child_id')
|
||||
->when($categoryId > 0, function ($builder) use ($categoryId) {
|
||||
$categoryIds = $this->categoryIdsWithChildren($categoryId);
|
||||
|
||||
if (empty($categoryIds)) {
|
||||
$builder->whereRaw('1 = 0');
|
||||
return;
|
||||
}
|
||||
|
||||
$builder->whereHas('categories', function ($category) use ($categoryIds) {
|
||||
$category->whereIn('categories.id', $categoryIds);
|
||||
});
|
||||
})
|
||||
->when($query !== '', function ($builder) use ($query) {
|
||||
$builder->where(function ($search) use ($query) {
|
||||
$search
|
||||
->where('name->ru', 'like', '%' . $query . '%')
|
||||
->orWhere('name->uz', 'like', '%' . $query . '%')
|
||||
->orWhere('article_number', 'like', '%' . $query . '%');
|
||||
});
|
||||
})
|
||||
->orderBy('id', 'desc')
|
||||
->limit(30)
|
||||
->get()
|
||||
->map(function ($product) {
|
||||
return [
|
||||
'id' => $product->id,
|
||||
'poster' => '/' . $product->poster,
|
||||
'poster' => $product->getPoster(),
|
||||
'name' => $product->name['ru']
|
||||
];
|
||||
});
|
||||
@@ -120,6 +149,59 @@ class Controller extends ExController
|
||||
]);
|
||||
}
|
||||
|
||||
private function categoryIdsWithChildren(int $categoryId): array
|
||||
{
|
||||
if (!Category::whereKey($categoryId)->exists()) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return $this->collectCategoryIds($categoryId);
|
||||
}
|
||||
|
||||
private function collectCategoryIds(int $categoryId, array $visited = []): array
|
||||
{
|
||||
if (in_array($categoryId, $visited, true)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$visited[] = $categoryId;
|
||||
$ids = [$categoryId];
|
||||
|
||||
$children = Category::where('parent_id', $categoryId)
|
||||
->orderBy('position')
|
||||
->pluck('id');
|
||||
|
||||
foreach ($children as $childId) {
|
||||
$ids = array_merge($ids, $this->collectCategoryIds((int) $childId, $visited));
|
||||
}
|
||||
|
||||
return array_values(array_unique($ids));
|
||||
}
|
||||
|
||||
private function categoryOptions($parentId = null, string $prefix = '')
|
||||
{
|
||||
return Category::select('id', 'name', 'parent_id')
|
||||
->when($parentId === null, function ($query) {
|
||||
$query->whereNull('parent_id');
|
||||
}, function ($query) use ($parentId) {
|
||||
$query->where('parent_id', $parentId);
|
||||
})
|
||||
->orderBy('position')
|
||||
->get()
|
||||
->flatMap(function (Category $category) use ($prefix) {
|
||||
$ru = $category->name['ru'] ?? $category->name['uz'] ?? '';
|
||||
$uz = $category->name['uz'] ?? $ru;
|
||||
|
||||
return collect([[
|
||||
'id' => $category->id,
|
||||
'name' => [
|
||||
'ru' => $prefix . $ru,
|
||||
'uz' => $prefix . $uz,
|
||||
],
|
||||
]])->merge($this->categoryOptions($category->id, $prefix . '- '));
|
||||
})
|
||||
->values();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Compilation $compilation
|
||||
|
||||
@@ -10,7 +10,6 @@ use App\Http\Requests\Dashboard\Partner\Store as StoreRequest;
|
||||
|
||||
use App\Jobs\Dashboard\Partner\Store as StoreJob;
|
||||
use App\Jobs\Dashboard\Partner\Update as UpdateJob;
|
||||
use Illuminate\Support\Facades\File;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
class Controller extends ExController
|
||||
@@ -48,19 +47,8 @@ class Controller extends ExController
|
||||
public function update(UpdateRequest $request, Partner $partner)
|
||||
{
|
||||
if ($request->hasFile('image')) {
|
||||
if (env('FILESYSTEM_DISK') == 's3') {
|
||||
// delete old image from s3
|
||||
Storage::disk('s3')->delete($partner->image);
|
||||
} else {
|
||||
// detele old image
|
||||
$imagePath = public_path($partner->image);
|
||||
|
||||
if (File::exists($imagePath)) {
|
||||
File::delete($imagePath);
|
||||
}
|
||||
}
|
||||
|
||||
$path = $request->file('image')->store('uploads/partners');
|
||||
Storage::delete($partner->image);
|
||||
$path = $request->file('image')->store('uploads/partners');
|
||||
} else {
|
||||
$path = $partner->image;
|
||||
}
|
||||
@@ -75,17 +63,7 @@ class Controller extends ExController
|
||||
{
|
||||
$this->authorize('delete', 'partners');
|
||||
|
||||
if (env('FILESYSTEM_DISK') == 's3') {
|
||||
// delete old image from s3
|
||||
Storage::disk('s3')->delete($partner->image);
|
||||
} else {
|
||||
$imagePath = public_path($partner->image);
|
||||
|
||||
if (File::exists($imagePath)) {
|
||||
File::delete($imagePath);
|
||||
}
|
||||
}
|
||||
|
||||
Storage::delete($partner->image);
|
||||
$partner->delete();
|
||||
|
||||
$this->info(trans('admin.messages.deleted'));
|
||||
|
||||
@@ -57,14 +57,8 @@ class Controller extends ExController
|
||||
}
|
||||
|
||||
if ($request->hasFile('image')) {
|
||||
if (env('FILESYSTEM_DISK') == 's3') {
|
||||
Storage::disk('s3')->delete($post->image);
|
||||
} else {
|
||||
if (is_file($post->image)) {
|
||||
unlink($post->image);
|
||||
}
|
||||
}
|
||||
$path = $request->file('image')->store('uploads/posts');
|
||||
Storage::delete($post->image);
|
||||
$path = $request->file('image')->store('uploads/posts');
|
||||
} else {
|
||||
$path = $post->image;
|
||||
}
|
||||
@@ -122,14 +116,7 @@ class Controller extends ExController
|
||||
public function delete(Post $post)
|
||||
{
|
||||
$this->authorize('delete', 'posts');
|
||||
if (env('FILESYSTEM_DISK') == 's3') {
|
||||
Storage::disk('s3')->delete($post->image);
|
||||
} else {
|
||||
if (is_file($post->image)) {
|
||||
unlink($post->image);
|
||||
}
|
||||
}
|
||||
|
||||
Storage::delete($post->image);
|
||||
$post->delete();
|
||||
$this->info(trans('admin.messages.deleted'));
|
||||
return redirect()->back();
|
||||
|
||||
@@ -24,11 +24,12 @@ use App\Jobs\Dashboard\Product\Child as ChildJob;
|
||||
use App\Jobs\Dashboard\Product\ChildUpdate as ChildUpdateJob;
|
||||
use App\Jobs\Dashboard\Product\Update as UpdateJob;
|
||||
use App\Jobs\Dashboard\Product\Deletes as DeletesJob;
|
||||
use Exception;
|
||||
use Illuminate\Support\Facades\Date;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Response;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Maatwebsite\Excel\Facades\Excel;
|
||||
use Throwable;
|
||||
|
||||
class Controller extends ExController
|
||||
{
|
||||
@@ -82,17 +83,7 @@ class Controller extends ExController
|
||||
{
|
||||
if ($request->isMethod('get')) {
|
||||
$this->authorize('create', 'products');
|
||||
$categories = $this->categories->select('id', 'name->ru as category')
|
||||
->where('parent_id', null)
|
||||
->with([
|
||||
'parents' => function ($parent) {
|
||||
return $parent->select('id', 'name->ru as category', 'parent_id')->with([
|
||||
'parents' => function ($parent) {
|
||||
return $parent->select('id', 'name->ru as category', 'parent_id');
|
||||
}
|
||||
]);
|
||||
}
|
||||
])->get();
|
||||
$categories = $this->categoryTree();
|
||||
$brands = $this->brands->get();
|
||||
$colors = $this->colors->get();
|
||||
$measurement = Measurement::query()->get();
|
||||
@@ -100,12 +91,26 @@ class Controller extends ExController
|
||||
return view('dashboard.products.store', compact('categories', 'brands', 'colors', 'measurement'));
|
||||
}
|
||||
|
||||
$product = $this->dispatchSync(StoreJob::fromRequest($request));
|
||||
try {
|
||||
$product = $this->dispatchSync(StoreJob::fromRequest($request));
|
||||
|
||||
$product->categories()->attach([$request->getCategoryID()]);
|
||||
$product->categories()->attach([$request->getCategoryID()]);
|
||||
|
||||
$this->charSync($product, $request->characteristics);
|
||||
$this->dispatchSync(new ChildJob($request, $product));
|
||||
$this->charSync($product, $request->characteristics);
|
||||
$this->dispatchSync(new ChildJob($request, $product));
|
||||
} catch (Throwable $e) {
|
||||
Log::error('Product store failed', [
|
||||
'message' => $e->getMessage(),
|
||||
'category_id' => $request->get('category_id'),
|
||||
'trace' => $e->getTraceAsString(),
|
||||
]);
|
||||
|
||||
return Response::json([
|
||||
'status' => false,
|
||||
'messages' => 'Product could not be saved.',
|
||||
'error' => config('app.debug') ? $e->getMessage() : null,
|
||||
], 500);
|
||||
}
|
||||
|
||||
$this->success(trans('admin.messages.created'));
|
||||
|
||||
@@ -139,14 +144,52 @@ class Controller extends ExController
|
||||
}
|
||||
}
|
||||
|
||||
private function categoryTree($parentId = null, array $visited = [])
|
||||
{
|
||||
return Category::select('id', 'name', 'parent_id')
|
||||
->when($parentId === null, function ($query) {
|
||||
$query->whereNull('parent_id');
|
||||
}, function ($query) use ($parentId) {
|
||||
$query->where('parent_id', $parentId);
|
||||
})
|
||||
->orderBy('position', 'asc')
|
||||
->get()
|
||||
->map(function (Category $category) use ($visited) {
|
||||
$children = in_array($category->id, $visited, true)
|
||||
? collect()
|
||||
: $this->categoryTree($category->id, [...$visited, $category->id]);
|
||||
|
||||
return [
|
||||
'id' => $category->id,
|
||||
'category' => $category->name['ru'] ?? $category->name['uz'] ?? '',
|
||||
'parent_id' => $category->parent_id,
|
||||
'parents' => $children,
|
||||
'$isDisabled' => false,
|
||||
];
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $id
|
||||
* @return array
|
||||
*/
|
||||
public function characteristics($id)
|
||||
{
|
||||
if (!ctype_digit((string) $id)) {
|
||||
return [
|
||||
'status' => false,
|
||||
'characteristics' => []
|
||||
];
|
||||
}
|
||||
|
||||
$category = Category::find($id);
|
||||
|
||||
if (empty($category)) {
|
||||
return [
|
||||
'status' => false,
|
||||
'characteristics' => []
|
||||
];
|
||||
}
|
||||
|
||||
if (!empty($category->characteristics) && count($category->characteristics) > 0) {
|
||||
$characteristics = $category->characteristics;
|
||||
@@ -187,7 +230,7 @@ class Controller extends ExController
|
||||
$arr[] = [
|
||||
'id' => $cat['id'],
|
||||
'category' => $cat['name']['ru'],
|
||||
'$isDisabled' => true
|
||||
'$isDisabled' => false
|
||||
];
|
||||
|
||||
foreach ($cat['parents'] as $parent) {
|
||||
@@ -196,7 +239,7 @@ class Controller extends ExController
|
||||
$arr[] = [
|
||||
'id' => $parent['id'],
|
||||
'category' => $parent['name']['ru'],
|
||||
'$isDisabled' => true
|
||||
'$isDisabled' => false
|
||||
];
|
||||
|
||||
foreach ($parent['parents'] as $paren) {
|
||||
@@ -283,27 +326,13 @@ class Controller extends ExController
|
||||
foreach ($product->childrens as $children) {
|
||||
foreach ($children->screens as $screen) {
|
||||
$screen->sizeText = $screen->size / 1024 . 'Kb';
|
||||
if (env('FILESYSTEM_DISK') == 's3') {
|
||||
$screen->url = Storage::url($screen->path);
|
||||
} else {
|
||||
$screen->url = '/' . $screen->path;
|
||||
}
|
||||
$screen->url = Storage::url($screen->path);
|
||||
$screen->type = "image/jpeg";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$categories = $this->categories->select('id', 'name->ru as category')
|
||||
->where('parent_id', null)
|
||||
->with([
|
||||
'parents' => function ($parent) {
|
||||
return $parent->select('id', 'name->ru as category', 'parent_id')->with([
|
||||
'parents' => function ($parent) {
|
||||
return $parent->select('id', 'name->ru as category', 'parent_id');
|
||||
}
|
||||
]);
|
||||
}
|
||||
])->get();
|
||||
$categories = $this->categoryTree();
|
||||
|
||||
$brands = $this->brands->get();
|
||||
$measurement = Measurement::query()->get();
|
||||
@@ -318,15 +347,23 @@ class Controller extends ExController
|
||||
try {
|
||||
$this->dispatchSync(new UpdateJob($product, $request));
|
||||
$this->dispatchSync(new ChildUpdateJob($request, $product));
|
||||
} catch (Exception $e) {
|
||||
return Response::json([
|
||||
"messages" => $e->getMessage()
|
||||
$this->charSync($product, $request->characteristics);
|
||||
$this->dispatchSync(new DeletesJob($request));
|
||||
} catch (Throwable $e) {
|
||||
Log::error('Product update failed', [
|
||||
'product_id' => $product->id,
|
||||
'message' => $e->getMessage(),
|
||||
'category_id' => $request->get('category_id'),
|
||||
'trace' => $e->getTraceAsString(),
|
||||
]);
|
||||
|
||||
return Response::json([
|
||||
'status' => false,
|
||||
'messages' => 'Product could not be saved.',
|
||||
'error' => config('app.debug') ? $e->getMessage() : null,
|
||||
], 500);
|
||||
}
|
||||
|
||||
$this->charSync($product, $request->characteristics);
|
||||
|
||||
$this->dispatchSync(new DeletesJob($request));
|
||||
$this->info(trans('admin.messages.updated'));
|
||||
|
||||
return response()->json([
|
||||
@@ -395,7 +432,11 @@ class Controller extends ExController
|
||||
|
||||
if ($category) {
|
||||
$categoryFind = Category::find($category);
|
||||
list($categoryFind, $category_id) = $this->categoryQuery->getCategoriesAndCategoryMainId($categoryFind);
|
||||
if ($categoryFind) {
|
||||
list($categoryFind, $category_id) = $this->categoryQuery->getCategoriesAndCategoryMainId($categoryFind);
|
||||
} else {
|
||||
$category_id = [];
|
||||
}
|
||||
} else {
|
||||
$category_id = [];
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@ use App\Jobs\Dashboard\Service\Store as StoreJob;
|
||||
use App\Jobs\Dashboard\Service\Update as UpdateJob;
|
||||
use App\Models\Problem;
|
||||
use App\Models\ServiceProblem;
|
||||
use Illuminate\Support\Facades\File;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
class Controller extends ExController
|
||||
@@ -62,18 +61,8 @@ class Controller extends ExController
|
||||
public function update(UpdateRequest $request, Service $service)
|
||||
{
|
||||
if ($request->hasFile('image')) {
|
||||
if (env('FILESYSTEM_DISK') == 's3') {
|
||||
$imagePath = $service->image;
|
||||
Storage::disk('s3')->delete($imagePath);
|
||||
} else {
|
||||
$imagePath = public_path($service->image);
|
||||
|
||||
if (File::exists($imagePath)) {
|
||||
File::delete($imagePath);
|
||||
}
|
||||
}
|
||||
|
||||
$path = $request->file('image')->store('uploads/services');
|
||||
Storage::delete($service->image);
|
||||
$path = $request->file('image')->store('uploads/services');
|
||||
} else {
|
||||
$path = $service->image;
|
||||
}
|
||||
@@ -106,17 +95,7 @@ class Controller extends ExController
|
||||
{
|
||||
$this->authorize('delete', 'services');
|
||||
|
||||
if (env('FILESYSTEM_DISK') == 's3') {
|
||||
$imagePath = $service->image;
|
||||
Storage::disk('s3')->delete($imagePath);
|
||||
} else {
|
||||
$imagePath = public_path($service->image);
|
||||
|
||||
if (File::exists($imagePath)) {
|
||||
File::delete($imagePath);
|
||||
}
|
||||
}
|
||||
|
||||
Storage::delete($service->image);
|
||||
ServiceProblem::where('service_id', $service->id)->delete();
|
||||
|
||||
$service->delete();
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace App\Http\Controllers\Dashboard\Slider;
|
||||
|
||||
use App\Models\Slider;
|
||||
use App\Support\Uploads;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Http\Controllers\Controller as ExController;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
@@ -53,7 +54,7 @@ class Controller extends ExController
|
||||
}
|
||||
|
||||
if ($request->hasFile('image')) {
|
||||
$path = $request->file('image')->store('uploads/sliders');
|
||||
$path = Uploads::store($request->file('image'), 'uploads/sliders');
|
||||
} else {
|
||||
$path = $slider->image;
|
||||
}
|
||||
@@ -77,7 +78,7 @@ class Controller extends ExController
|
||||
|
||||
|
||||
if ($request->hasFile('image')) {
|
||||
$path = $request->file('image')->store('uploads/sliders');
|
||||
$path = Uploads::store($request->file('image'), 'uploads/sliders');
|
||||
}
|
||||
|
||||
$this->dispatchSync(StoreJob::fromRequest($request, $path));
|
||||
|
||||
@@ -49,18 +49,8 @@ class Controller extends ExController
|
||||
public function update(UpdateRequest $request, UsefulInfo $usefulinfo)
|
||||
{
|
||||
if ($request->hasFile('image')) {
|
||||
if (env('FILESYSTEM_DISK') == 's3') {
|
||||
$imagePath = $usefulinfo->image;
|
||||
Storage::disk('s3')->delete($imagePath);
|
||||
} else {
|
||||
$imagePath = public_path($usefulinfo->image);
|
||||
|
||||
if (File::exists($imagePath)) {
|
||||
File::delete($imagePath);
|
||||
}
|
||||
}
|
||||
|
||||
$path = $request->file('image')->store('uploads/usefulinfos');
|
||||
Storage::delete($usefulinfo->image);
|
||||
$path = $request->file('image')->store('uploads/usefulinfos');
|
||||
} else {
|
||||
$path = $usefulinfo->image;
|
||||
}
|
||||
@@ -84,17 +74,7 @@ class Controller extends ExController
|
||||
$item->delete();
|
||||
}
|
||||
|
||||
if (env('FILESYSTEM_DISK') == 's3') {
|
||||
$imagePath = $usefulinfo->image;
|
||||
Storage::disk('s3')->delete($imagePath);
|
||||
} else {
|
||||
$imagePath = public_path($usefulinfo->image);
|
||||
|
||||
if (File::exists($imagePath)) {
|
||||
File::delete($imagePath);
|
||||
}
|
||||
}
|
||||
|
||||
Storage::delete($usefulinfo->image);
|
||||
$usefulinfo->delete();
|
||||
|
||||
$this->info(trans('admin.messages.deleted'));
|
||||
|
||||
@@ -3,11 +3,19 @@
|
||||
namespace App\Http\Requests\Dashboard\Category;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Http\UploadedFile;
|
||||
use Illuminate\Support\Str;
|
||||
use RuntimeException;
|
||||
|
||||
class Request extends FormRequest
|
||||
{
|
||||
protected function prepareForValidation()
|
||||
{
|
||||
if (in_array($this->get('parent_id'), [0, '0', '', 'null', 'NULL'], true)) {
|
||||
$this->merge(['parent_id' => null]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
@@ -22,7 +30,7 @@ class Request extends FormRequest
|
||||
'name' => 'required|array',
|
||||
'name.*' => 'required|string',
|
||||
'image' => 'nullable|mimes:jpg,jpeg,png',
|
||||
'parent_id' => 'nullable',
|
||||
'parent_id' => 'nullable|integer|exists:categories,id',
|
||||
'brands' => 'nullable|array',
|
||||
'position' => 'nullable|numeric'
|
||||
];
|
||||
@@ -41,18 +49,31 @@ class Request extends FormRequest
|
||||
public function getImage(): string
|
||||
{
|
||||
if ($this->hasFile('image')) {
|
||||
if (env('FILESYSTEM_DISK') == 's3') {
|
||||
$folder = "uploads/categories";
|
||||
|
||||
return (string) $this->file('image')->store($folder);
|
||||
} else {
|
||||
return $this->file('image')->store('uploads/categories', 'local');
|
||||
}
|
||||
return $this->storeCategoryImage($this->file('image'));
|
||||
} else {
|
||||
return 'null';
|
||||
}
|
||||
}
|
||||
|
||||
private function storeCategoryImage(UploadedFile $file): string
|
||||
{
|
||||
$relativeDirectory = 'uploads/categories';
|
||||
$directory = public_path($relativeDirectory);
|
||||
|
||||
if (!is_dir($directory) && !mkdir($directory, 0775, true) && !is_dir($directory)) {
|
||||
throw new RuntimeException("Category upload directory could not be created: {$directory}");
|
||||
}
|
||||
|
||||
if (!is_writable($directory)) {
|
||||
throw new RuntimeException("Category upload directory is not writable: {$directory}");
|
||||
}
|
||||
|
||||
$fileName = $file->hashName();
|
||||
$file->move($directory, $fileName);
|
||||
|
||||
return "{$relativeDirectory}/{$fileName}";
|
||||
}
|
||||
|
||||
public function getPublished()
|
||||
{
|
||||
if ($this->get('published') == 'true') {
|
||||
@@ -82,15 +103,16 @@ class Request extends FormRequest
|
||||
|
||||
public function getParentId()
|
||||
{
|
||||
if ($this->get('parent_id') > 0)
|
||||
return $this->get('parent_id');
|
||||
if ((int) $this->get('parent_id') > 0) {
|
||||
return (int) $this->get('parent_id');
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getPosition(): int
|
||||
{
|
||||
return $this->get('position');
|
||||
return (int) $this->get('position');
|
||||
}
|
||||
|
||||
public function getPopular(): bool
|
||||
|
||||
@@ -4,11 +4,20 @@ namespace App\Http\Requests\Dashboard\Category;
|
||||
|
||||
use App\Models\Category;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Http\UploadedFile;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Str;
|
||||
use RuntimeException;
|
||||
|
||||
class Update extends FormRequest
|
||||
{
|
||||
protected function prepareForValidation()
|
||||
{
|
||||
if (in_array($this->get('parent_id'), [0, '0', '', 'null', 'NULL'], true)) {
|
||||
$this->merge(['parent_id' => null]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
@@ -23,7 +32,7 @@ class Update extends FormRequest
|
||||
'name' => 'required|array',
|
||||
'name.*' => 'required|string',
|
||||
'image' => 'nullable',
|
||||
'parent_id' => 'nullable',
|
||||
'parent_id' => 'nullable|integer|exists:categories,id',
|
||||
'popular' => 'nullable',
|
||||
'brands' => 'nullable|array',
|
||||
'position' => 'nullable|numeric'
|
||||
@@ -40,26 +49,33 @@ class Update extends FormRequest
|
||||
return Str::slug($this->get('name')['uz']);
|
||||
}
|
||||
|
||||
public function getImage(Category $category): string
|
||||
public function getImage(Category $category): ?string
|
||||
{
|
||||
if ($this->hasFile('image')) {
|
||||
if (env('FILESYSTEM_DISK') == 's3') {
|
||||
// delete old image from s3
|
||||
Storage::disk('s3')->delete($category->image);
|
||||
|
||||
$folder = "uploads/categories";
|
||||
|
||||
return (string) $this->file('image')->store($folder);
|
||||
} else {
|
||||
// detele old image
|
||||
if (is_file($category->image)) {
|
||||
unlink($category->image);
|
||||
}
|
||||
return $this->file('image')->store('uploads/categories', 'local');
|
||||
}
|
||||
} else {
|
||||
return 'null';
|
||||
Storage::disk('local')->delete($category->image);
|
||||
return $this->storeCategoryImage($this->file('image'));
|
||||
}
|
||||
|
||||
return $category->image;
|
||||
}
|
||||
|
||||
private function storeCategoryImage(UploadedFile $file): string
|
||||
{
|
||||
$relativeDirectory = 'uploads/categories';
|
||||
$directory = public_path($relativeDirectory);
|
||||
|
||||
if (!is_dir($directory) && !mkdir($directory, 0775, true) && !is_dir($directory)) {
|
||||
throw new RuntimeException("Category upload directory could not be created: {$directory}");
|
||||
}
|
||||
|
||||
if (!is_writable($directory)) {
|
||||
throw new RuntimeException("Category upload directory is not writable: {$directory}");
|
||||
}
|
||||
|
||||
$fileName = $file->hashName();
|
||||
$file->move($directory, $fileName);
|
||||
|
||||
return "{$relativeDirectory}/{$fileName}";
|
||||
}
|
||||
|
||||
public function getFilterPower()
|
||||
@@ -91,15 +107,16 @@ class Update extends FormRequest
|
||||
|
||||
public function getParentId()
|
||||
{
|
||||
if ($this->get('parent_id') > 0)
|
||||
return $this->get('parent_id');
|
||||
if ((int) $this->get('parent_id') > 0) {
|
||||
return (int) $this->get('parent_id');
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getPosition(): int
|
||||
{
|
||||
return $this->get('position');
|
||||
return (int) $this->get('position');
|
||||
}
|
||||
|
||||
public function getPopular(): bool
|
||||
|
||||
@@ -22,7 +22,8 @@ class Store extends FormRequest
|
||||
return [
|
||||
'title' => 'array',
|
||||
'title.*' => 'required',
|
||||
'published' => 'required',
|
||||
'published' => 'nullable',
|
||||
'products' => 'nullable|array',
|
||||
//'category_id' => 'required'
|
||||
];
|
||||
}
|
||||
@@ -40,7 +41,7 @@ class Store extends FormRequest
|
||||
*/
|
||||
public function getPublished(): bool
|
||||
{
|
||||
return $this->get('published');
|
||||
return filter_var($this->get('published', false), FILTER_VALIDATE_BOOLEAN);
|
||||
}
|
||||
|
||||
|
||||
@@ -49,8 +50,8 @@ class Store extends FormRequest
|
||||
*/
|
||||
public function getCategory()
|
||||
{
|
||||
if ($this->get('category_id')) {
|
||||
$this->get('category_id');
|
||||
if ($this->get('category_id') && $this->get('category_id') != 0) {
|
||||
return $this->get('category_id');
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
@@ -22,7 +22,8 @@ class Update extends FormRequest
|
||||
return [
|
||||
'title' => 'array',
|
||||
'title.*' => 'required',
|
||||
'published' => 'required',
|
||||
'published' => 'nullable',
|
||||
'products' => 'nullable|array',
|
||||
//'category_id' => 'required',
|
||||
];
|
||||
}
|
||||
@@ -40,14 +41,14 @@ class Update extends FormRequest
|
||||
*/
|
||||
public function getPublished(): bool
|
||||
{
|
||||
return $this->get('published');
|
||||
return filter_var($this->get('published', false), FILTER_VALIDATE_BOOLEAN);
|
||||
}
|
||||
|
||||
|
||||
public function getCategory()
|
||||
{
|
||||
if ($this->get('category_id')) {
|
||||
$this->get('category_id');
|
||||
if ($this->get('category_id') && $this->get('category_id') != 0) {
|
||||
return $this->get('category_id');
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
namespace App\Http\Requests\Dashboard\Product;
|
||||
|
||||
use App\Support\Uploads;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use App\Api\ImageResize;
|
||||
|
||||
class Store extends FormRequest
|
||||
@@ -38,7 +38,7 @@ class Store extends FormRequest
|
||||
'brand_id' => 'required',
|
||||
'measurement_id' => 'nullable|exists:measurements,id',
|
||||
|
||||
'category_id' => 'required',
|
||||
'category_id' => 'required|integer|exists:categories,id',
|
||||
'colors' => 'array|required',
|
||||
'colors.*.color_id' => 'nullable',
|
||||
'colors.*.sizes' => 'nullable|array',
|
||||
@@ -71,7 +71,7 @@ class Store extends FormRequest
|
||||
{
|
||||
$folder = "uploads/posters/" . Carbon::now()->format('Y/m/d');
|
||||
|
||||
return (string) $this->file('poster')->store($folder);
|
||||
return Uploads::store($this->file('poster'), $folder);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -81,7 +81,7 @@ class Store extends FormRequest
|
||||
{
|
||||
if ($this->hasFile('calc')) {
|
||||
$folder = "uploads/calc/" . Carbon::now()->format('Y/m/d');
|
||||
return (string) $this->file('calc')->store($folder);
|
||||
return Uploads::store($this->file('calc'), $folder);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -90,7 +90,7 @@ class Store extends FormRequest
|
||||
{
|
||||
if ($this->hasFile('data_sheet')) {
|
||||
$folder = "uploads/datasheet/" . Carbon::now()->format('Y/m/d');
|
||||
return (string) $this->file('data_sheet')->store($folder);
|
||||
return Uploads::store($this->file('data_sheet'), $folder);
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -102,7 +102,7 @@ class Store extends FormRequest
|
||||
public function getPosterThumb()
|
||||
{
|
||||
$image = $this->file('poster');
|
||||
$tempPath = $image->store('temp', 'public');
|
||||
$tempPath = Uploads::store($image, 'temp', 'public');
|
||||
|
||||
$resizer = new ImageResize();
|
||||
return $resizer->resize($tempPath, 322, 'posters', true);
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Http\Requests\Dashboard\Product;
|
||||
|
||||
use App\Support\Uploads;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
@@ -27,7 +28,7 @@ class Update extends FormRequest
|
||||
'price' => 'required|numeric',
|
||||
'price_discount' => 'nullable',
|
||||
'brand_id' => 'required',
|
||||
'category_id' => 'required',
|
||||
'category_id' => 'required|integer|exists:categories,id',
|
||||
'popular' => 'nullable',
|
||||
"calc" => [],
|
||||
'leader_of_sales' => 'nullable',
|
||||
@@ -63,17 +64,9 @@ class Update extends FormRequest
|
||||
public function getPoster(Product $product): string
|
||||
{
|
||||
if ($this->hasFile('poster')) {
|
||||
if (env('FILESYSTEM_DISK') == 's3') {
|
||||
// delete old file from s3
|
||||
Storage::disk('s3')->delete($product->poster);
|
||||
} else {
|
||||
// delete old file
|
||||
$oldPath = public_path($product->poster);
|
||||
if (is_file($oldPath)) unlink($oldPath);
|
||||
}
|
||||
|
||||
Storage::delete($product->poster);
|
||||
$folder = "uploads/posters/" . Carbon::now()->format('Y/m/d');
|
||||
return (string) $this->file('poster')->store($folder);
|
||||
return Uploads::store($this->file('poster'), $folder);
|
||||
}
|
||||
|
||||
return $product->poster;
|
||||
@@ -85,15 +78,11 @@ class Update extends FormRequest
|
||||
public function getCalc(Product $product): string|null
|
||||
{
|
||||
if ($this->hasFile('calc')) {
|
||||
if (env('FILESYSTEM_DISK') == 's3' and $product->calc) {
|
||||
// delete old file from s3
|
||||
Storage::disk('s3')->delete($product->calc);
|
||||
} elseif($product->calc) {
|
||||
unlink($product->calc);
|
||||
if ($product->calc) {
|
||||
Storage::delete($product->calc);
|
||||
}
|
||||
|
||||
$folder = "uploads/calc/" . Carbon::now()->format('Y/m/d');
|
||||
return (string) $this->file('calc')->store($folder);
|
||||
return Uploads::store($this->file('calc'), $folder);
|
||||
}
|
||||
return $product->calc;
|
||||
}
|
||||
@@ -101,13 +90,11 @@ class Update extends FormRequest
|
||||
public function getDataSheet(Product $product)
|
||||
{
|
||||
if ($this->hasFile('data_sheet')) {
|
||||
|
||||
if (is_file($this->get('data_sheet'))) {
|
||||
unlink($this->get("data_sheet"));
|
||||
if ($product->data_sheet) {
|
||||
Storage::delete($product->data_sheet);
|
||||
}
|
||||
|
||||
$folder = "uploads/datasheet/" . Carbon::now()->format('Y/m/d');
|
||||
return (string) $this->file('data_sheet')->store($folder);
|
||||
return Uploads::store($this->file('data_sheet'), $folder);
|
||||
}
|
||||
|
||||
return $product->data_sheet;
|
||||
@@ -119,18 +106,8 @@ class Update extends FormRequest
|
||||
public function getPosterThumb(Product $product): string
|
||||
{
|
||||
if ($this->hasFile('poster')) {
|
||||
if (env('FILESYSTEM_DISK') == 's3') {
|
||||
// delete old file from s3
|
||||
Storage::disk('s3')->delete($product->poster_thumb);
|
||||
} else {
|
||||
// delete old file local
|
||||
$oldPath = public_path($product->poster_thumb);
|
||||
if (is_file($oldPath)) unlink($oldPath);
|
||||
}
|
||||
|
||||
$image = $this->file('poster');
|
||||
$tempPath = $image->store('temp', 'public');
|
||||
|
||||
Storage::delete($product->poster_thumb);
|
||||
$tempPath = Uploads::store($this->file('poster'), 'temp', 'public');
|
||||
$resizer = new ImageResize();
|
||||
return $resizer->resize($tempPath, 322, 'posters', true);
|
||||
}
|
||||
|
||||
@@ -38,12 +38,13 @@ class Store
|
||||
$category->published = $request->getPublished();
|
||||
$category->is_filter_power = $request->getFilterPower();
|
||||
$category->credit = $request->getCredit();
|
||||
$category->keywords = $request->keywords;
|
||||
$category->title_seo = $request->title_seo;
|
||||
$category->descriptions = $request->descriptions ?? ['ru' => '', 'uz' => ''];
|
||||
$category->keywords = $request->keywords ?? ['ru' => '', 'uz' => ''];
|
||||
$category->title_seo = $request->title_seo ?? ['ru' => '', 'uz' => ''];
|
||||
|
||||
$category->save();
|
||||
|
||||
$category->brands()->sync($request->brands, false);
|
||||
$category->brands()->sync($request->brands ?? [], false);
|
||||
|
||||
return $category;
|
||||
}
|
||||
|
||||
@@ -35,8 +35,8 @@ class Update
|
||||
$category->name = $request->getName();
|
||||
$category->slug = $request->getSlug();
|
||||
$category->position = $request->getPosition();
|
||||
$category->image = $request->getImage($category);
|
||||
// $category->parent_id = $request->getParentId();
|
||||
$category->image = $this->image;
|
||||
$category->parent_id = $request->getParentId();
|
||||
// $category->popular = $request->getPopular();
|
||||
$category->published = $request->getPublished();
|
||||
$category->is_filter_power = $request->getFilterPower();
|
||||
@@ -45,8 +45,6 @@ class Update
|
||||
$category->keywords = $request->keywords;
|
||||
$category->title_seo = $request->title_seo;
|
||||
|
||||
$category->image = $this->image;
|
||||
|
||||
$category->save();
|
||||
|
||||
if (isset($request->brands)) {
|
||||
|
||||
@@ -36,8 +36,10 @@ class Store
|
||||
|
||||
$map = array_map(function ($product) {
|
||||
return $product['id'];
|
||||
}, $this->request->products);
|
||||
}, $this->request->products ?? []);
|
||||
|
||||
$compilation->products()->attach($map);
|
||||
if (!empty($map)) {
|
||||
$compilation->products()->attach($map);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,20 +35,12 @@ class Update
|
||||
'category_id' => $this->request->getCategory()
|
||||
]);
|
||||
|
||||
$detach = Compilation::find($this->compilation->id);
|
||||
$detach->loadMissing(['products:id']);
|
||||
|
||||
$compilation = Compilation::find($this->compilation->id);
|
||||
|
||||
$map = array_map(function ($product) {
|
||||
return $product['id'];
|
||||
}, $this->request->products);
|
||||
}, $this->request->products ?? []);
|
||||
|
||||
$detach = array_map(function ($product) {
|
||||
return $product['id'];
|
||||
}, $detach->products->toArray());
|
||||
|
||||
$compilation->products()->detach($detach);
|
||||
$compilation->products()->attach($map);
|
||||
$compilation->products()->sync($map);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ namespace App\Jobs\Dashboard\Product;
|
||||
|
||||
use App\Models\Product;
|
||||
use App\Models\Screen;
|
||||
use App\Support\Uploads;
|
||||
use Carbon\Carbon;
|
||||
use App\Api\ImageResize;
|
||||
use App\Http\Requests\Dashboard\Product\Store as StoreRequest;
|
||||
@@ -54,18 +55,13 @@ class Child
|
||||
$folder = Carbon::now()->format('Y/m/d');
|
||||
|
||||
// Store original
|
||||
$path = $screen['image']->store("uploads/screens/{$folder}");
|
||||
$path = Uploads::store($screen['image'], "uploads/screens/{$folder}");
|
||||
|
||||
// Store and resize thumb
|
||||
$tempPath = $screen['image']->store('temp', 'public');
|
||||
$tempPath = Uploads::store($screen['image'], 'temp', 'public');
|
||||
$thumbPath = $this->image->resize($tempPath, 322, 'screens', true);
|
||||
|
||||
// Get screen size (local or s3)
|
||||
if (env('FILESYSTEM_DISK') == 's3') {
|
||||
$this->size = Storage::disk('s3')->size($path);
|
||||
} else {
|
||||
$this->size = filesize(public_path($path));
|
||||
}
|
||||
$this->size = Storage::size($path);
|
||||
|
||||
Screen::create([
|
||||
'path' => $path,
|
||||
|
||||
@@ -4,6 +4,7 @@ namespace App\Jobs\Dashboard\Product;
|
||||
|
||||
use App\Models\Product;
|
||||
use App\Models\Screen;
|
||||
use App\Support\Uploads;
|
||||
use Carbon\Carbon;
|
||||
|
||||
use App\Api\ImageResize;
|
||||
@@ -83,10 +84,10 @@ class ChildUpdate
|
||||
$folder = Carbon::now()->format('Y/m/d');
|
||||
if ($screen['image']) {
|
||||
// 1. Store original (S3 if enabled)
|
||||
$path = $screen['image']->store("uploads/screens/{$folder}");
|
||||
$path = Uploads::store($screen['image'], "uploads/screens/{$folder}");
|
||||
|
||||
// 2. Local temp for resizing
|
||||
$tempPath = $screen['image']->store('temp', 'public');
|
||||
$tempPath = Uploads::store($screen['image'], 'temp', 'public');
|
||||
$thumbPath = $this->image->resize($tempPath, 322, 'screens', true);
|
||||
|
||||
Screen::create([
|
||||
@@ -94,7 +95,7 @@ class ChildUpdate
|
||||
'path_thumb' => $thumbPath,
|
||||
'name' => basename($path),
|
||||
'product_id' => $child_id,
|
||||
'size' => Storage::disk(env('FILESYSTEM_DISK'))->size($path)
|
||||
'size' => Storage::size($path)
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ namespace App\Jobs\Dashboard\Product;
|
||||
use App\Http\Requests\Dashboard\Product\Update as Request;
|
||||
use App\Models\Screen;
|
||||
use App\Models\Product;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
class Deletes
|
||||
{
|
||||
@@ -29,14 +30,7 @@ class Deletes
|
||||
foreach ($this->request->deletes['screens'] as $screen) {
|
||||
$sc = Screen::where('id', $screen)->first();
|
||||
if (!empty($sc)) {
|
||||
if (is_file($sc->path)) {
|
||||
unlink($sc->path);
|
||||
}
|
||||
|
||||
if (is_file($sc->path_thumb)) {
|
||||
unlink($sc->path_thumb);
|
||||
}
|
||||
|
||||
Storage::delete([$sc->path, $sc->path_thumb]);
|
||||
$sc->delete();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Jobs\Dashboard\Product;
|
||||
|
||||
use App\Support\Uploads;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Support\Arr;
|
||||
use App\Models\Screen as Screens;
|
||||
@@ -38,17 +39,17 @@ class Screen
|
||||
$folder = Carbon::now()->format('Y/m/d');
|
||||
|
||||
// 1. Store original (S3 if enabled)
|
||||
$path = $screen->store("uploads/screens/original/{$folder}");
|
||||
$path = Uploads::store($screen, "uploads/screens/original/{$folder}");
|
||||
|
||||
// 2. Local temp for resizing
|
||||
$tempPath = $screen->store('temp', 'public');
|
||||
$tempPath = Uploads::store($screen, 'temp', 'public');
|
||||
$thumb = $this->img->resize($tempPath, 350, 'screens', true);
|
||||
|
||||
$screens = new Screens();
|
||||
$screens->name = basename($path);
|
||||
$screens->path = $path;
|
||||
$screens->path_thumb = $thumb;
|
||||
$screens->size = Storage::disk(env('FILESYSTEM_DISK'))->size($path);
|
||||
$screens->size = Storage::size($path);
|
||||
$screens->product_id = $this->id;
|
||||
$screens->save();
|
||||
}
|
||||
|
||||
@@ -58,13 +58,6 @@ class Update
|
||||
|
||||
private function syncCategories()
|
||||
{
|
||||
$cats = $this->product->categories()->get();
|
||||
|
||||
$cats = array_map(function ($cat) {
|
||||
return $cat['id'];
|
||||
}, $cats->toArray());
|
||||
|
||||
$this->product->categories()->detach($cats);
|
||||
$this->product->categories()->attach([$this->request->getCategoryID()]);
|
||||
$this->product->categories()->sync([$this->request->getCategoryID()]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,12 +62,7 @@ class Brand extends Model
|
||||
public function getImage(): string
|
||||
{
|
||||
if (!empty($this->image)) {
|
||||
if (in_array(config('filesystems.default'), ['s3', 'minio'])) {
|
||||
return Storage::url($this->image);
|
||||
}
|
||||
;
|
||||
|
||||
return (string) '/' . $this->image;
|
||||
return Storage::url($this->image);
|
||||
}
|
||||
|
||||
return (string) 'images/no_brend.png';
|
||||
|
||||
@@ -147,11 +147,11 @@ class Category extends Model
|
||||
public function getImage(): string
|
||||
{
|
||||
if (!in_array($this->image, ['null', null])) {
|
||||
if (in_array(config('filesystems.default'), ['s3', 'minio'])) {
|
||||
return Storage::url($this->image);
|
||||
if (Str::startsWith($this->image, 'uploads/categories/') && file_exists(public_path($this->image))) {
|
||||
return asset($this->image);
|
||||
}
|
||||
|
||||
return config('app.url') . '/' . $this->image;
|
||||
return Storage::url($this->image);
|
||||
}
|
||||
|
||||
return config('app.url') . '/images/nophoto.jpg';
|
||||
|
||||
@@ -58,6 +58,11 @@ class Compilation extends Model
|
||||
return $this->belongsToMany(Product::class, 'compilation_products')->where('published', true)->limit(10);
|
||||
}
|
||||
|
||||
public function dashboardProducts()
|
||||
{
|
||||
return $this->belongsToMany(Product::class, 'compilation_products');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@@ -30,12 +30,9 @@ class ContractTemplate extends Model
|
||||
public function full_path(): string
|
||||
{
|
||||
if (!empty($this->path)) {
|
||||
if (in_array(env('FILESYSTEM_DISK'), ['s3', 'minio'])) {
|
||||
return Storage::url($this->path);
|
||||
}
|
||||
return '/' . $this->path;
|
||||
return Storage::url($this->path);
|
||||
}
|
||||
|
||||
return asset('storage/' . $this->path);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,10 +47,7 @@ class File extends Model
|
||||
public function getPath()
|
||||
{
|
||||
if (!empty($this->path)) {
|
||||
if (in_array(env('FILESYSTEM_DISK'), ['s3', 'minio'])) {
|
||||
return Storage::url($this->path);
|
||||
}
|
||||
return (string) $this->path;
|
||||
return Storage::url($this->path);
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -62,10 +59,7 @@ class File extends Model
|
||||
public function getPathThumb()
|
||||
{
|
||||
if (!empty($this->path_thumb)) {
|
||||
if (in_array(env('FILESYSTEM_DISK'), ['s3', 'minio'])) {
|
||||
return Storage::url($this->path_thumb);
|
||||
}
|
||||
return (string) $this->path_thumb;
|
||||
return Storage::url($this->path_thumb);
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
@@ -36,11 +36,7 @@ class OrderContract extends Model
|
||||
public function getPath()
|
||||
{
|
||||
if (!empty($this->path)) {
|
||||
if (in_array(env('FILESYSTEM_DISK'), ['s3', 'minio'])) {
|
||||
return Storage::url($this->path);
|
||||
}
|
||||
|
||||
return env('APP_URL') . '/storage/' . $this->path;
|
||||
return Storage::url($this->path);
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
@@ -52,11 +52,7 @@ class Partner extends Model
|
||||
public function getImage(): string
|
||||
{
|
||||
if (!empty($this->image)) {
|
||||
if (in_array(env('FILESYSTEM_DISK'), ['s3', 'minio'])) {
|
||||
return Storage::url($this->image);
|
||||
}
|
||||
|
||||
return (string) $this->image;
|
||||
return Storage::url($this->image);
|
||||
}
|
||||
|
||||
return (string) 'images/no_brend.png';
|
||||
|
||||
@@ -70,11 +70,7 @@ class PaymentSystemItem extends Model
|
||||
public function getLogo(): string
|
||||
{
|
||||
if (!empty($this->logo)) {
|
||||
if (in_array(env('FILESYSTEM_DISK'), ['s3', 'minio'])) {
|
||||
return Storage::url($this->logo);
|
||||
}
|
||||
|
||||
return env('APP_URL').'/'.$this->logo;
|
||||
return Storage::url($this->logo);
|
||||
}
|
||||
|
||||
return '/images/nophoto.jpg';
|
||||
|
||||
@@ -56,11 +56,7 @@ class Post extends Model
|
||||
public function getImage(): string
|
||||
{
|
||||
if (!empty($this->image)) {
|
||||
if (in_array(env('FILESYSTEM_DISK'), ['s3', 'minio'])) {
|
||||
return Storage::url($this->image);
|
||||
}
|
||||
|
||||
return $this->image;
|
||||
return Storage::url($this->image);
|
||||
}
|
||||
|
||||
return '/images/nophoto.jpg';
|
||||
|
||||
@@ -236,10 +236,11 @@ class Product extends Model
|
||||
public function getPoster(): string
|
||||
{
|
||||
if (!empty($this->poster)) {
|
||||
if (in_array(config('filesystems.default'), ['s3', 'minio'])) {
|
||||
return Storage::url($this->poster);
|
||||
if (str_starts_with($this->poster, 'uploads/') && file_exists(public_path($this->poster))) {
|
||||
return asset($this->poster);
|
||||
}
|
||||
return config('app.url') . '/' . $this->poster;
|
||||
|
||||
return Storage::url($this->poster);
|
||||
}
|
||||
|
||||
return config('app.url') . '/images/no_product.jpg';
|
||||
@@ -248,10 +249,11 @@ class Product extends Model
|
||||
public function getDataSheet()
|
||||
{
|
||||
if (!empty($this->data_sheet) and ($this->data_sheet != null and $this->data_sheet != "null")) {
|
||||
if (in_array(config('filesystems.default'), ['s3', 'minio'])) {
|
||||
return Storage::url($this->data_sheet);
|
||||
if (str_starts_with($this->data_sheet, 'uploads/') && file_exists(public_path($this->data_sheet))) {
|
||||
return asset($this->data_sheet);
|
||||
}
|
||||
return config('app.url') . '/' . $this->data_sheet;
|
||||
|
||||
return Storage::url($this->data_sheet);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -259,10 +261,11 @@ class Product extends Model
|
||||
public function getPosterThumb(): string
|
||||
{
|
||||
if (!empty($this->poster_thumb)) {
|
||||
if (in_array(config('filesystems.default'), ['s3', 'minio'])) {
|
||||
return Storage::url($this->poster_thumb);
|
||||
if (str_starts_with($this->poster_thumb, 'uploads/') && file_exists(public_path($this->poster_thumb))) {
|
||||
return asset($this->poster_thumb);
|
||||
}
|
||||
return config('app.url') . '/' . $this->poster_thumb;
|
||||
|
||||
return Storage::url($this->poster_thumb);
|
||||
}
|
||||
|
||||
return config('app.url') . '/images/no_product.jpg';
|
||||
|
||||
@@ -58,10 +58,11 @@ class Screen extends Model
|
||||
public function getPath(): string
|
||||
{
|
||||
if (!empty($this->path)) {
|
||||
if (in_array(env('FILESYSTEM_DISK'), ['s3', 'minio'])) {
|
||||
return Storage::url($this->path);
|
||||
if (str_starts_with($this->path, 'uploads/') && file_exists(public_path($this->path))) {
|
||||
return asset($this->path);
|
||||
}
|
||||
return (string) $this->path;
|
||||
|
||||
return Storage::url($this->path);
|
||||
}
|
||||
|
||||
return (string) 'image/no_screen.png';
|
||||
@@ -73,10 +74,11 @@ class Screen extends Model
|
||||
public function getPathThumb(): string
|
||||
{
|
||||
if (!empty($this->path_thumb)) {
|
||||
if (in_array(env('FILESYSTEM_DISK'), ['s3', 'minio'])) {
|
||||
return Storage::url($this->path_thumb);
|
||||
if (str_starts_with($this->path_thumb, 'uploads/') && file_exists(public_path($this->path_thumb))) {
|
||||
return asset($this->path_thumb);
|
||||
}
|
||||
return (string) $this->path_thumb;
|
||||
|
||||
return Storage::url($this->path_thumb);
|
||||
}
|
||||
|
||||
return (string) 'image/no_screen_thumb.png';
|
||||
|
||||
@@ -61,10 +61,7 @@ class Service extends Model
|
||||
public function getImage(): string
|
||||
{
|
||||
if (!empty($this->image)) {
|
||||
if (in_array(env('FILESYSTEM_DISK'), ['s3', 'minio'])) {
|
||||
return Storage::url($this->image);
|
||||
}
|
||||
return (string) $this->image;
|
||||
return Storage::url($this->image);
|
||||
}
|
||||
|
||||
return (string) 'images/no_brend.png';
|
||||
|
||||
@@ -45,10 +45,7 @@ class Slider extends Model
|
||||
public function getImage(): string
|
||||
{
|
||||
if (!empty($this->image)) {
|
||||
if (in_array(env('FILESYSTEM_DISK'), ['s3', 'minio'])) {
|
||||
return Storage::url($this->image);
|
||||
}
|
||||
return $this->image;
|
||||
return Storage::url($this->image);
|
||||
}
|
||||
|
||||
return '/images/nophoto.jpg';
|
||||
|
||||
@@ -47,10 +47,7 @@ class SpecialOffer extends Model
|
||||
public function getImage(): string
|
||||
{
|
||||
if (!empty($this->image)) {
|
||||
if (in_array(env('FILESYSTEM_DISK'), ['s3', 'minio'])) {
|
||||
return Storage::url($this->image);
|
||||
}
|
||||
return (string) $this->image;
|
||||
return Storage::url($this->image);
|
||||
}
|
||||
|
||||
return (string) 'images/nophoto.png';
|
||||
|
||||
@@ -44,10 +44,7 @@ class UsefulInfo extends Model
|
||||
public function getImage(): string
|
||||
{
|
||||
if (!empty($this->image)) {
|
||||
if (in_array(env('FILESYSTEM_DISK'), ['s3', 'minio'])) {
|
||||
return Storage::url($this->image);
|
||||
}
|
||||
return (string) $this->image;
|
||||
return Storage::url($this->image);
|
||||
}
|
||||
|
||||
return (string) 'images/no_brend.png';
|
||||
|
||||
@@ -63,10 +63,7 @@ class UsefulInfoItem extends Model
|
||||
public function getFile(): string
|
||||
{
|
||||
if (!empty($this->file_url)) {
|
||||
if (in_array(env('FILESYSTEM_DISK'), ['s3', 'minio'])) {
|
||||
return Storage::url($this->file_url);
|
||||
}
|
||||
return '/' . $this->file_url;
|
||||
return Storage::url($this->file_url);
|
||||
}
|
||||
|
||||
return '/images/no_product.jpg';
|
||||
|
||||
@@ -96,13 +96,10 @@ class ContractService
|
||||
// 1 - store temp file
|
||||
$path = storage_path('app/public/' . $oldPath);
|
||||
|
||||
// Store the image on S3 or keep local
|
||||
if (in_array(env('FILESYSTEM_DISK'), ['s3', 'minio'])) {
|
||||
Storage::disk('s3')->put($oldPath, file_get_contents($path));
|
||||
}
|
||||
Storage::put($oldPath, file_get_contents($path));
|
||||
|
||||
// 3 - delete resized file
|
||||
if (in_array(env('FILESYSTEM_DISK'), ['s3', 'minio']) && is_file($path)) {
|
||||
if (is_file($path)) {
|
||||
unlink($path);
|
||||
}
|
||||
}
|
||||
|
||||
42
app/Support/Uploads.php
Normal file
42
app/Support/Uploads.php
Normal file
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace App\Support;
|
||||
|
||||
use Illuminate\Http\UploadedFile;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use RuntimeException;
|
||||
|
||||
class Uploads
|
||||
{
|
||||
public static function store(UploadedFile $file, string $path, ?string $disk = null): string
|
||||
{
|
||||
$diskName = $disk ?: config('filesystems.default');
|
||||
$storedPath = $disk ? $file->store($path, $disk) : $file->store($path);
|
||||
|
||||
if (!$storedPath) {
|
||||
throw new RuntimeException("File upload failed: {$path}");
|
||||
}
|
||||
|
||||
if (!Storage::disk($diskName)->exists($storedPath)) {
|
||||
throw new RuntimeException("Uploaded file was not found on disk [{$diskName}]: {$storedPath}");
|
||||
}
|
||||
|
||||
return $storedPath;
|
||||
}
|
||||
|
||||
public static function put(string $path, string $contents, ?string $disk = null): void
|
||||
{
|
||||
$stored = $disk
|
||||
? Storage::disk($disk)->put($path, $contents)
|
||||
: Storage::put($path, $contents);
|
||||
|
||||
if (!$stored) {
|
||||
throw new RuntimeException("File upload failed: {$path}");
|
||||
}
|
||||
|
||||
$diskName = $disk ?: config('filesystems.default');
|
||||
if (!Storage::disk($diskName)->exists($path)) {
|
||||
throw new RuntimeException("Uploaded file was not found on disk [{$diskName}]: {$path}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,7 @@ return [
|
||||
|
|
||||
*/
|
||||
|
||||
'default' => env('FILESYSTEM_DISK', 'local'),
|
||||
'default' => env('FILESYSTEM_DISK', env('FILESYSTEM_DRIVER', 's3')),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
@@ -62,10 +62,15 @@ return [
|
||||
'region' => env('MINIO_REGION', 'us-east-1'),
|
||||
'bucket' => env('MINIO_BUCKET'),
|
||||
'endpoint' => env('MINIO_ENDPOINT'),
|
||||
'url' => env('MINIO_PUBLIC_URL', env('MINIO_ENDPOINT')),
|
||||
'url' => env('MINIO_PUBLIC_URL')
|
||||
? (str_ends_with(rtrim(env('MINIO_PUBLIC_URL'), '/'), '/' . trim(env('MINIO_BUCKET'), '/'))
|
||||
? rtrim(env('MINIO_PUBLIC_URL'), '/')
|
||||
: rtrim(env('MINIO_PUBLIC_URL'), '/') . '/' . trim(env('MINIO_BUCKET'), '/'))
|
||||
: env('MINIO_ENDPOINT'),
|
||||
'use_path_style_endpoint' => env('MINIO_USE_PATH_STYLE', true),
|
||||
'visibility' => 'public',
|
||||
'signature_version' => 'v4',
|
||||
'throw' => true,
|
||||
],
|
||||
|
||||
|
||||
|
||||
@@ -9,15 +9,28 @@ server {
|
||||
root /quyoshli/public;
|
||||
index index.php;
|
||||
|
||||
location = /quyoshli {
|
||||
return 301 /quyoshli/;
|
||||
}
|
||||
|
||||
# MinIO bucket public files. The ^~ prefix keeps image/css regex blocks from catching these URLs.
|
||||
location ^~ /quyoshli/ {
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $proxy_host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_pass http://minio:9100;
|
||||
proxy_request_buffering off;
|
||||
proxy_buffering off;
|
||||
add_header X-Storage-Proxy minio always;
|
||||
}
|
||||
|
||||
# try to serve file directly, fallback to start.php
|
||||
location / {
|
||||
try_files $uri /$uri /index.php$is_args$args;
|
||||
}
|
||||
|
||||
if (!-e $request_filename) {
|
||||
rewrite ^.*$ /index.php last;
|
||||
}
|
||||
|
||||
location ~ \.php$ {
|
||||
fastcgi_pass quyoshli:9000;
|
||||
fastcgi_index index.php;
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 17 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 61 KiB |
@@ -49,6 +49,10 @@
|
||||
}
|
||||
}
|
||||
menu = document.querySelector('.main-menu-content');
|
||||
if (!activeEl || !menu) {
|
||||
this.obj.update();
|
||||
return;
|
||||
}
|
||||
activeEl = activeEl.getBoundingClientRect().top + menu.scrollTop;
|
||||
// If active element's top position is less than 2/3 (66%) of menu height than do not scroll
|
||||
if (activeEl > parseInt((menu.clientHeight * 2) / 3)) {
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
<div class="col-md-12">
|
||||
<div class="form-group">
|
||||
<label for="category">Категория</label>
|
||||
<select id="category" class="form-control" v-model="category_id">
|
||||
<select id="category" class="form-control" v-model="category_id" @change="SearchProduct('')">
|
||||
<option value="0">Все</option>
|
||||
<option v-for="category in categories" :value="category.id">
|
||||
{{ category.name.ru }}
|
||||
@@ -50,7 +50,7 @@
|
||||
<multiselect v-model="compilations"
|
||||
placeholder="Искать"
|
||||
label="name"
|
||||
track-by="name"
|
||||
track-by="id"
|
||||
:options="products"
|
||||
:option-height="104"
|
||||
:custom-label="customLabel"
|
||||
@@ -168,7 +168,7 @@
|
||||
}),
|
||||
|
||||
mounted() {
|
||||
|
||||
this.SearchProduct('');
|
||||
},
|
||||
|
||||
methods: {
|
||||
@@ -194,19 +194,17 @@
|
||||
async SearchProduct(query) {
|
||||
let name = query;
|
||||
|
||||
if (name.length > 0) {
|
||||
axios.post('/dashboard/compilations/product/search', { name: name})
|
||||
.then((response) => {
|
||||
if (response.data.status) {
|
||||
this.products = response.data.products;
|
||||
}
|
||||
}).catch((error) => {
|
||||
if (error.response) {
|
||||
this.error = true;
|
||||
this.errors = error.response.data.errors;
|
||||
axios.post('/dashboard/compilations/product/search', { name: name, category_id: this.category_id})
|
||||
.then((response) => {
|
||||
if (response.data.status) {
|
||||
this.products = response.data.products;
|
||||
}
|
||||
});
|
||||
}
|
||||
}).catch((error) => {
|
||||
if (error.response) {
|
||||
this.error = true;
|
||||
this.errors = error.response.data.errors;
|
||||
}
|
||||
});
|
||||
|
||||
console.log(query);
|
||||
},
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
<div class="col-md-12">
|
||||
<div class="form-group">
|
||||
<label for="category">Категория</label>
|
||||
<select id="category" class="form-control" v-model="category_id">
|
||||
<select id="category" class="form-control" v-model="category_id" @change="SearchProduct('')">
|
||||
<option value="0">Все</option>
|
||||
<option v-for="category in categories" :value="category.id">
|
||||
{{ category.name.ru }}
|
||||
@@ -50,7 +50,7 @@
|
||||
<multiselect v-model="compilations"
|
||||
placeholder="Искать"
|
||||
label="name"
|
||||
track-by="name"
|
||||
track-by="id"
|
||||
:options="products"
|
||||
:option-height="104"
|
||||
:custom-label="customLabel"
|
||||
@@ -171,7 +171,7 @@
|
||||
},
|
||||
|
||||
mounted() {
|
||||
|
||||
this.SearchProduct('');
|
||||
},
|
||||
|
||||
methods: {
|
||||
@@ -196,19 +196,17 @@
|
||||
async SearchProduct(query) {
|
||||
let name = query;
|
||||
|
||||
if (name.length > 0) {
|
||||
axios.post('/dashboard/compilations/product/search', { name: name})
|
||||
.then((response) => {
|
||||
if (response.data.status) {
|
||||
this.products = response.data.products;
|
||||
}
|
||||
}).catch((error) => {
|
||||
if (error.response) {
|
||||
this.error = true;
|
||||
this.errors = error.response.data.errors;
|
||||
axios.post('/dashboard/compilations/product/search', { name: name, category_id: this.category_id})
|
||||
.then((response) => {
|
||||
if (response.data.status) {
|
||||
this.products = response.data.products;
|
||||
}
|
||||
});
|
||||
}
|
||||
}).catch((error) => {
|
||||
if (error.response) {
|
||||
this.error = true;
|
||||
this.errors = error.response.data.errors;
|
||||
}
|
||||
});
|
||||
|
||||
console.log(query);
|
||||
},
|
||||
|
||||
@@ -137,168 +137,67 @@ export default {
|
||||
subCategories: [],
|
||||
category: null,
|
||||
subCategory: null,
|
||||
currentParentId: null,
|
||||
};
|
||||
},
|
||||
|
||||
methods: {
|
||||
async SendForm() {
|
||||
const formData = new FormData();
|
||||
for (var i = 0; i < this.categories.length; i++) {
|
||||
formData.append(
|
||||
"categories[" + i + "][id]",
|
||||
this.categories[i].id
|
||||
);
|
||||
formData.append(
|
||||
"categories[" + i + "][position]",
|
||||
this.categories[i].position
|
||||
);
|
||||
formData.append(
|
||||
"categories[" + i + "][parent_id]",
|
||||
this.categories[i].parent_id
|
||||
);
|
||||
if (this.categories[i].children.length > 0) {
|
||||
for (
|
||||
var c = 0;
|
||||
c < this.categories[i].children.length;
|
||||
c++
|
||||
) {
|
||||
formData.append(
|
||||
"categories[" + i + "][children][" + c + "][id]",
|
||||
this.categories[i].children[c].id
|
||||
);
|
||||
formData.append(
|
||||
"categories[" +
|
||||
i +
|
||||
"][children][" +
|
||||
c +
|
||||
"][position]",
|
||||
this.categories[i].children[c].position
|
||||
);
|
||||
formData.append(
|
||||
"categories[" +
|
||||
i +
|
||||
"][children][" +
|
||||
c +
|
||||
"][parent_id]",
|
||||
this.categories[i].children[c].parent_id
|
||||
);
|
||||
if (
|
||||
this.categories[i].children[c].children.length > 0
|
||||
) {
|
||||
for (
|
||||
var w = 0;
|
||||
w <
|
||||
this.categories[i].children[c].children.length;
|
||||
w++
|
||||
) {
|
||||
formData.append(
|
||||
"categories[" +
|
||||
i +
|
||||
"][children][" +
|
||||
c +
|
||||
"][children][" +
|
||||
w +
|
||||
"][id]",
|
||||
this.categories[i].children[c].children[w]
|
||||
.id
|
||||
);
|
||||
formData.append(
|
||||
"categories[" +
|
||||
i +
|
||||
"][children][" +
|
||||
c +
|
||||
"][children][" +
|
||||
w +
|
||||
"][position]",
|
||||
this.categories[i].children[c].children[w]
|
||||
.position
|
||||
);
|
||||
formData.append(
|
||||
"categories[" +
|
||||
i +
|
||||
"][children][" +
|
||||
c +
|
||||
"][children][" +
|
||||
w +
|
||||
"][parent_id]",
|
||||
this.categories[i].children[c].children[w]
|
||||
.parent_id
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const { data } = await axios.post(
|
||||
"/dashboard/categories/position",
|
||||
formData
|
||||
{
|
||||
categories: this.normalizeTree(this.categoriesData, null, 0),
|
||||
}
|
||||
);
|
||||
|
||||
if (data.status) {
|
||||
// window.location.href = "/dashboard/categories";
|
||||
window.location.reload();
|
||||
}
|
||||
},
|
||||
|
||||
Change() {
|
||||
for (var i = 0; i < this.categories.length; i++) {
|
||||
var num = i + 1;
|
||||
this.normalizeTree(this.categoriesData, null, 0);
|
||||
},
|
||||
|
||||
this.categories[i].position = num;
|
||||
this.categories[i].droppable = true;
|
||||
normalizeTree(categories, parentId, level) {
|
||||
return categories.map((category, index) => {
|
||||
category.position = index + 1;
|
||||
category.parent_id = parentId;
|
||||
category.droppable = level < 2;
|
||||
|
||||
if (this.categories[i].children.length > 0) {
|
||||
for (
|
||||
var c = 0;
|
||||
c < this.categories[i].children.length;
|
||||
c++
|
||||
) {
|
||||
var numm = c + 1;
|
||||
this.categories[i].children[c].position = numm;
|
||||
this.categories[i].children[c].parent_id =
|
||||
this.categories[i].id;
|
||||
this.categories[i].children[c].droppable = true;
|
||||
const children = Array.isArray(category.children)
|
||||
? this.normalizeTree(category.children, category.id, level + 1)
|
||||
: [];
|
||||
|
||||
if (
|
||||
this.categories[i].children[c].children.length > 0
|
||||
) {
|
||||
for (
|
||||
var w = 0;
|
||||
w <
|
||||
this.categories[i].children[c].children.length;
|
||||
w++
|
||||
) {
|
||||
var nummm = w + 1;
|
||||
|
||||
this.categories[i].children[c].children[
|
||||
w
|
||||
].position = nummm;
|
||||
this.categories[i].children[c].children[
|
||||
w
|
||||
].parent_id = this.categories[i].children[c].id;
|
||||
this.categories[i].children[c].children[
|
||||
w
|
||||
].droppable = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return {
|
||||
id: category.id,
|
||||
position: category.position,
|
||||
parent_id: category.parent_id,
|
||||
children,
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
handleMainCategory() {
|
||||
if (this.category) {
|
||||
this.categories = this.category.children;
|
||||
this.subCategories = this.category.children;
|
||||
this.currentParentId = this.category.id;
|
||||
} else {
|
||||
this.categories = this.categoriesData;
|
||||
this.subCategories = null;
|
||||
this.currentParentId = null;
|
||||
}
|
||||
},
|
||||
|
||||
handleSubCategory() {
|
||||
if (this.subCategory) this.categories = this.subCategory.children;
|
||||
else this.categories = this.category.children;
|
||||
if (this.subCategory) {
|
||||
this.categories = this.subCategory.children;
|
||||
this.currentParentId = this.subCategory.id;
|
||||
} else {
|
||||
this.categories = this.category.children;
|
||||
this.currentParentId = this.category ? this.category.id : null;
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -111,7 +111,6 @@
|
||||
type="file"
|
||||
name="image"
|
||||
@change="ImageFile($event)"
|
||||
onchange="PreviewImage();"
|
||||
/>
|
||||
<label
|
||||
class="custom-file-label"
|
||||
@@ -126,6 +125,7 @@
|
||||
<div class="text-center">
|
||||
<img
|
||||
id="uploadPreview"
|
||||
:src="category.imagePreview"
|
||||
style="
|
||||
width: 300px;
|
||||
height: auto;
|
||||
@@ -356,6 +356,7 @@
|
||||
id="remove_cat"
|
||||
type="button"
|
||||
class="btn btn-secondary w-100"
|
||||
@click="category.parent_id = 0"
|
||||
>
|
||||
{{
|
||||
$t(
|
||||
@@ -707,6 +708,7 @@ export default {
|
||||
},
|
||||
|
||||
image: null,
|
||||
imagePreview: null,
|
||||
},
|
||||
|
||||
char: [],
|
||||
@@ -791,13 +793,28 @@ export default {
|
||||
.catch((error) => {
|
||||
if (error.response) {
|
||||
this.error = true;
|
||||
this.errors = error.response.data.errors;
|
||||
this.errors =
|
||||
error.response.data.errors ||
|
||||
error.response.data.details ||
|
||||
[
|
||||
[
|
||||
error.response.data.error ||
|
||||
error.response.data.message ||
|
||||
"Server error",
|
||||
],
|
||||
];
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
ImageFile(event) {
|
||||
this.category.image = event.target.files[0];
|
||||
|
||||
if (this.category.image) {
|
||||
this.category.imagePreview = URL.createObjectURL(
|
||||
this.category.image
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
addChar() {
|
||||
|
||||
@@ -111,7 +111,6 @@
|
||||
type="file"
|
||||
name="image"
|
||||
@change="ImageFile($event)"
|
||||
onchange="PreviewImage();"
|
||||
/>
|
||||
<label
|
||||
class="custom-file-label"
|
||||
@@ -360,6 +359,7 @@
|
||||
id="remove_cat"
|
||||
type="button"
|
||||
class="btn btn-secondary w-100"
|
||||
@click="category.parent_id = 0"
|
||||
>
|
||||
{{
|
||||
$t(
|
||||
@@ -804,13 +804,26 @@ export default {
|
||||
.catch((error) => {
|
||||
if (error.response) {
|
||||
this.error = true;
|
||||
this.errors = error.response.data.errors;
|
||||
this.errors =
|
||||
error.response.data.errors ||
|
||||
error.response.data.details ||
|
||||
[
|
||||
[
|
||||
error.response.data.error ||
|
||||
error.response.data.message ||
|
||||
"Server error",
|
||||
],
|
||||
];
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
ImageFile(event) {
|
||||
this.file = event.target.files[0];
|
||||
|
||||
if (this.file) {
|
||||
this.category.image_url = URL.createObjectURL(this.file);
|
||||
}
|
||||
},
|
||||
|
||||
addChar() {
|
||||
|
||||
@@ -63,51 +63,28 @@
|
||||
|
||||
<multiselect
|
||||
:options="categories"
|
||||
v-model="category.first"
|
||||
v-model="category.path[0]"
|
||||
label="category"
|
||||
@change="
|
||||
DetectCategory($event)
|
||||
"
|
||||
track-by="category"
|
||||
@input="selectCategoryLevel(0)"
|
||||
track-by="id"
|
||||
></multiselect>
|
||||
<!-- //@change="getCharacteristics($event)"-->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="col-4"
|
||||
v-if="category.two_view"
|
||||
v-for="level in categoryLevels"
|
||||
:key="'category-level-' + level"
|
||||
>
|
||||
<div class="form-group">
|
||||
<label>Суб категория *</label>
|
||||
|
||||
<multiselect
|
||||
:options="
|
||||
category.first.parents
|
||||
"
|
||||
v-model="category.two"
|
||||
:options="categoryOptions(level)"
|
||||
v-model="category.path[level]"
|
||||
label="category"
|
||||
@change="DetectCategoryTwo"
|
||||
track-by="category"
|
||||
></multiselect>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="col-4"
|
||||
v-if="category.three_view"
|
||||
>
|
||||
<div class="form-group">
|
||||
<label>Под категория *</label>
|
||||
|
||||
<multiselect
|
||||
:options="
|
||||
category.two.parents
|
||||
"
|
||||
v-model="category.three"
|
||||
label="category"
|
||||
@change="DetectCategory"
|
||||
track-by="category"
|
||||
@input="selectCategoryLevel(level)"
|
||||
track-by="id"
|
||||
></multiselect>
|
||||
</div>
|
||||
</div>
|
||||
@@ -309,7 +286,6 @@
|
||||
<input
|
||||
class="form-control"
|
||||
@change="posterFile($event)"
|
||||
onchange="PreviewImage();"
|
||||
type="file"
|
||||
id="poster"
|
||||
/>
|
||||
@@ -670,6 +646,7 @@
|
||||
:theme="'default'"
|
||||
:multiple="true"
|
||||
:deletable="true"
|
||||
:linkable="true"
|
||||
:meta="true"
|
||||
:accept="'image/*'"
|
||||
:maxSize="'10MB'"
|
||||
@@ -679,10 +656,13 @@
|
||||
type: 'Invalid file type. Only images or zip Allowed',
|
||||
size: 'Files should not exceed 10MB in size',
|
||||
}"
|
||||
@select="
|
||||
filesSelected($event, index)
|
||||
"
|
||||
@beforedelete="
|
||||
onBeforeDelete(
|
||||
$event,
|
||||
index
|
||||
)
|
||||
"
|
||||
@delete="
|
||||
fileDeleted($event, index)
|
||||
"
|
||||
v-model="color.screens"
|
||||
@@ -1030,7 +1010,9 @@ export default {
|
||||
|
||||
watch: {
|
||||
"products.category_id": function (newVal) {
|
||||
this.getCharacteristics(newVal);
|
||||
if (newVal) {
|
||||
this.getCharacteristics(newVal);
|
||||
}
|
||||
},
|
||||
|
||||
"category.first": function (newVal) {
|
||||
@@ -1043,13 +1025,15 @@ export default {
|
||||
|
||||
"category.two": function (newVal) {
|
||||
if (this.watch_count.two > 1) {
|
||||
if (newVal.parents.length > 0) {
|
||||
if (!newVal || !newVal.id) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (newVal.parents && newVal.parents.length > 0) {
|
||||
this.DetectCategoryTwo();
|
||||
} else {
|
||||
if (newVal.id) {
|
||||
this.product.category_id = newVal.id;
|
||||
this.getCharacteristics(newVal);
|
||||
}
|
||||
this.products.category_id = newVal.id;
|
||||
this.getCharacteristics(newVal.id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1058,11 +1042,31 @@ export default {
|
||||
|
||||
"category.three": function (newVal) {
|
||||
if (this.watch_count.three > 1) {
|
||||
if (!newVal || !newVal.id) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.DetectCategoryThree();
|
||||
}
|
||||
|
||||
this.watch_count.three = 2;
|
||||
},
|
||||
|
||||
"category.path": {
|
||||
deep: true,
|
||||
handler() {
|
||||
const selected = this.lastSelectedCategory();
|
||||
|
||||
if (!selected) {
|
||||
this.products.category_id = null;
|
||||
this.characteristics = [];
|
||||
return;
|
||||
}
|
||||
|
||||
this.products.category_id = selected.id;
|
||||
this.getCharacteristics(selected.id);
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
data: function () {
|
||||
@@ -1095,6 +1099,7 @@ export default {
|
||||
three: {},
|
||||
two_view: false,
|
||||
three_view: false,
|
||||
path: [],
|
||||
},
|
||||
|
||||
watch_count: {
|
||||
@@ -1125,6 +1130,22 @@ export default {
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
categoryLevels() {
|
||||
const levels = [];
|
||||
let current = this.category.path[0];
|
||||
let level = 1;
|
||||
|
||||
while (current && current.parents && current.parents.length > 0) {
|
||||
levels.push(level);
|
||||
current = this.category.path[level];
|
||||
level++;
|
||||
}
|
||||
|
||||
return levels;
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
getPosterPreview() {
|
||||
if (this.products.poster instanceof File) {
|
||||
@@ -1134,35 +1155,58 @@ export default {
|
||||
},
|
||||
setCategory() {
|
||||
if (this.products.categories[0]) {
|
||||
if (this.products.categories[0].parent) {
|
||||
if (this.products.categories[0].parent.parent) {
|
||||
this.category.two_view = true;
|
||||
this.category.three_view = true;
|
||||
this.products.category_id =
|
||||
this.products.categories[0].id;
|
||||
|
||||
this.category.first =
|
||||
this.products.categories[0].parent.parent;
|
||||
this.category.two = this.products.categories[0].parent;
|
||||
this.category.three = this.products.categories[0];
|
||||
} else {
|
||||
this.products.category_id =
|
||||
this.products.categories[0].id;
|
||||
|
||||
this.category.first =
|
||||
this.products.categories[0].parent;
|
||||
this.category.two = this.products.categories[0];
|
||||
this.category.two_view = true;
|
||||
}
|
||||
} else {
|
||||
this.products.category_id = this.products.categories[0].id;
|
||||
this.category.first = this.products.categories[0];
|
||||
}
|
||||
this.products.category_id = this.products.categories[0].id;
|
||||
this.category.path = this.findCategoryPath(
|
||||
this.categories,
|
||||
this.products.categories[0].id
|
||||
);
|
||||
|
||||
this.getCharacteristics(this.product.categories[0].id);
|
||||
}
|
||||
},
|
||||
|
||||
findCategoryPath(categories, id, path = []) {
|
||||
for (const category of categories || []) {
|
||||
const currentPath = [...path, category];
|
||||
|
||||
if (category.id === id) {
|
||||
return currentPath;
|
||||
}
|
||||
|
||||
const childPath = this.findCategoryPath(
|
||||
category.parents || [],
|
||||
id,
|
||||
currentPath
|
||||
);
|
||||
|
||||
if (childPath.length > 0) {
|
||||
return childPath;
|
||||
}
|
||||
}
|
||||
|
||||
return [];
|
||||
},
|
||||
|
||||
categoryOptions(level) {
|
||||
const parent = this.category.path[level - 1];
|
||||
|
||||
return parent && parent.parents ? parent.parents : [];
|
||||
},
|
||||
|
||||
selectCategoryLevel(level) {
|
||||
this.category.path.splice(level + 1);
|
||||
},
|
||||
|
||||
lastSelectedCategory() {
|
||||
for (let i = this.category.path.length - 1; i >= 0; i--) {
|
||||
if (this.category.path[i] && this.category.path[i].id) {
|
||||
return this.category.path[i];
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
|
||||
DetectCategory() {
|
||||
this.category.two = {
|
||||
parents: [],
|
||||
@@ -1171,11 +1215,16 @@ export default {
|
||||
this.category.three = {};
|
||||
this.category.three_view = false;
|
||||
|
||||
if (this.category.first.parents.length > 0) {
|
||||
if (!this.category.first || !this.category.first.id) {
|
||||
this.products.category_id = null;
|
||||
return;
|
||||
}
|
||||
|
||||
this.products.category_id = this.category.first.id;
|
||||
this.getCharacteristics(this.category.first.id);
|
||||
|
||||
if (this.category.first.parents && this.category.first.parents.length > 0) {
|
||||
this.category.two_view = true;
|
||||
} else {
|
||||
this.getCharacteristics(this.category.first.id);
|
||||
this.product.category_id = this.category.first.id;
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1183,17 +1232,35 @@ export default {
|
||||
this.category.three = {};
|
||||
this.category.three_view = false;
|
||||
|
||||
if (this.category.two.parents.length > 0) {
|
||||
if (!this.category.two || !this.category.two.id) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.products.category_id = this.category.two.id;
|
||||
this.getCharacteristics(this.category.two.id);
|
||||
|
||||
if (this.category.two.parents && this.category.two.parents.length > 0) {
|
||||
this.category.three_view = true;
|
||||
}
|
||||
},
|
||||
|
||||
DetectCategoryThree() {
|
||||
if (!this.category.three || !this.category.three.id) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.getCharacteristics(this.category.three.id);
|
||||
this.product.category_id = this.category.three.id;
|
||||
this.products.category_id = this.category.three.id;
|
||||
},
|
||||
|
||||
async getCharacteristics(id) {
|
||||
id = id && id.id ? id.id : id;
|
||||
|
||||
if (!id) {
|
||||
this.characteristics = [];
|
||||
return;
|
||||
}
|
||||
|
||||
const { data } = await axios.get(
|
||||
"/dashboard/products/characteristics/" + id
|
||||
);
|
||||
@@ -1352,18 +1419,6 @@ export default {
|
||||
}
|
||||
}
|
||||
|
||||
if (this.products.childrens[i].filesDataForUpload) {
|
||||
for (
|
||||
let f = 0;
|
||||
f < this.products.childrens[i].filesDataForUpload.length;
|
||||
f++
|
||||
) {
|
||||
formData.append(
|
||||
"colors[" + i + "][screens][new_" + f + "][image]",
|
||||
this.products.childrens[i].filesDataForUpload[f].file
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (let i = 0; i < this.deletes.childrens.length; i++) {
|
||||
@@ -1394,7 +1449,13 @@ export default {
|
||||
.catch((error) => {
|
||||
if (error.response) {
|
||||
this.error = true;
|
||||
this.errors = error.response.data.errors;
|
||||
this.errors = error.response.data.errors || {
|
||||
product: [
|
||||
error.response.data.error ||
|
||||
error.response.data.messages ||
|
||||
"Ошибка при сохранении",
|
||||
],
|
||||
};
|
||||
}
|
||||
});
|
||||
},
|
||||
@@ -1488,26 +1549,19 @@ export default {
|
||||
this.products.childrens[index].sizes.splice(indexx, 1);
|
||||
},
|
||||
|
||||
filesSelected: function (filesDataNewlySelected, index) {
|
||||
let validFilesData = filesDataNewlySelected.filter(
|
||||
(fileData) => !fileData.error
|
||||
);
|
||||
this.products.childrens[index].filesDataForUpload =
|
||||
this.products.childrens[index].filesDataForUpload.concat(
|
||||
validFilesData
|
||||
);
|
||||
onBeforeDelete: function (fileData, index) {
|
||||
const agent = Array.isArray(this.$refs.vueFileAgent)
|
||||
? this.$refs.vueFileAgent[index]
|
||||
: this.$refs.vueFileAgent;
|
||||
|
||||
if (agent) {
|
||||
agent.deleteFileRecord(fileData);
|
||||
}
|
||||
},
|
||||
|
||||
fileDeleted: function (fileData, index) {
|
||||
let i = this.products.childrens[index].screens.indexOf(fileData);
|
||||
|
||||
if (i !== -1) {
|
||||
this.products.childrens[index].screens.splice(i, 1);
|
||||
let id = fileData.id ? fileData.id : null;
|
||||
|
||||
if (fileData.id) {
|
||||
this.deletes.screens.push(id);
|
||||
}
|
||||
fileDeleted: function (fileData) {
|
||||
if (fileData.id && !this.deletes.screens.includes(fileData.id)) {
|
||||
this.deletes.screens.push(fileData.id);
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
@@ -59,51 +59,28 @@
|
||||
|
||||
<multiselect
|
||||
:options="categories"
|
||||
v-model="category.first"
|
||||
v-model="category.path[0]"
|
||||
label="category"
|
||||
@change="
|
||||
DetectCategory($event)
|
||||
"
|
||||
track-by="category"
|
||||
@input="selectCategoryLevel(0)"
|
||||
track-by="id"
|
||||
></multiselect>
|
||||
<!-- //@change="getCharacteristics($event)"-->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="col-4"
|
||||
v-if="category.two_view"
|
||||
v-for="level in categoryLevels"
|
||||
:key="'category-level-' + level"
|
||||
>
|
||||
<div class="form-group">
|
||||
<label>Суб категория *</label>
|
||||
|
||||
<multiselect
|
||||
:options="
|
||||
category.first.parents
|
||||
"
|
||||
v-model="category.two"
|
||||
:options="categoryOptions(level)"
|
||||
v-model="category.path[level]"
|
||||
label="category"
|
||||
@change="DetectCategoryTwo"
|
||||
track-by="category"
|
||||
></multiselect>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="col-4"
|
||||
v-if="category.three_view"
|
||||
>
|
||||
<div class="form-group">
|
||||
<label>Под категория *</label>
|
||||
|
||||
<multiselect
|
||||
:options="
|
||||
category.two.parents
|
||||
"
|
||||
v-model="category.three"
|
||||
label="category"
|
||||
@change="DetectCategory"
|
||||
track-by="category"
|
||||
@input="selectCategoryLevel(level)"
|
||||
track-by="id"
|
||||
></multiselect>
|
||||
</div>
|
||||
</div>
|
||||
@@ -324,7 +301,6 @@
|
||||
<input
|
||||
class="form-control"
|
||||
@change="posterFile($event)"
|
||||
onchange="PreviewImage();"
|
||||
required
|
||||
type="file"
|
||||
id="poster"
|
||||
@@ -684,6 +660,7 @@
|
||||
:theme="'default'"
|
||||
:multiple="true"
|
||||
:deletable="true"
|
||||
:linkable="true"
|
||||
:meta="true"
|
||||
:accept="'image/*'"
|
||||
:maxSize="'10MB'"
|
||||
@@ -693,10 +670,13 @@
|
||||
type: 'Invalid file type. Only images or zip Allowed',
|
||||
size: 'Files should not exceed 10MB in size',
|
||||
}"
|
||||
@select="
|
||||
filesSelected($event, index)
|
||||
"
|
||||
@beforedelete="
|
||||
onBeforeDelete(
|
||||
$event,
|
||||
index
|
||||
)
|
||||
"
|
||||
@delete="
|
||||
fileDeleted($event, index)
|
||||
"
|
||||
v-model="color.screens"
|
||||
@@ -1133,6 +1113,7 @@ export default {
|
||||
three: {},
|
||||
two_view: false,
|
||||
three_view: false,
|
||||
path: [],
|
||||
},
|
||||
|
||||
characteristic: false,
|
||||
@@ -1146,11 +1127,27 @@ export default {
|
||||
uploadDisabled() {
|
||||
return this.files.length === 0;
|
||||
},
|
||||
|
||||
categoryLevels() {
|
||||
const levels = [];
|
||||
let current = this.category.path[0];
|
||||
let level = 1;
|
||||
|
||||
while (current && current.parents && current.parents.length > 0) {
|
||||
levels.push(level);
|
||||
current = this.category.path[level];
|
||||
level++;
|
||||
}
|
||||
|
||||
return levels;
|
||||
},
|
||||
},
|
||||
|
||||
watch: {
|
||||
"product.category_id": function (newVal) {
|
||||
this.getCharacteristics(newVal);
|
||||
if (newVal) {
|
||||
this.getCharacteristics(newVal);
|
||||
}
|
||||
},
|
||||
|
||||
"category.first": function (newVal) {
|
||||
@@ -1158,18 +1155,40 @@ export default {
|
||||
},
|
||||
|
||||
"category.two": function (newVal) {
|
||||
if (newVal.parents.length > 0) {
|
||||
if (!newVal || !newVal.id) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (newVal.parents && newVal.parents.length > 0) {
|
||||
this.DetectCategoryTwo();
|
||||
} else {
|
||||
if (newVal.id) {
|
||||
this.product.category_id = newVal.id;
|
||||
}
|
||||
this.product.category_id = newVal.id;
|
||||
}
|
||||
},
|
||||
|
||||
"category.three": function (newVal) {
|
||||
if (!newVal || !newVal.id) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.DetectCategoryThree();
|
||||
},
|
||||
|
||||
"category.path": {
|
||||
deep: true,
|
||||
handler() {
|
||||
const selected = this.lastSelectedCategory();
|
||||
|
||||
if (!selected) {
|
||||
this.product.category_id = null;
|
||||
this.characteristics = [];
|
||||
return;
|
||||
}
|
||||
|
||||
this.product.category_id = selected.id;
|
||||
this.getCharacteristics(selected.id);
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
@@ -1278,18 +1297,6 @@ export default {
|
||||
}
|
||||
}
|
||||
|
||||
if (this.product.colors[i].filesDataForUpload) {
|
||||
for (
|
||||
let f = 0;
|
||||
f < this.product.colors[i].filesDataForUpload.length;
|
||||
f++
|
||||
) {
|
||||
formData.append(
|
||||
"colors[" + i + "][screens][new_" + f + "][image]",
|
||||
this.product.colors[i].filesDataForUpload[f].file
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0; i < this.characteristics.length; i++) {
|
||||
@@ -1313,11 +1320,38 @@ export default {
|
||||
.catch((error) => {
|
||||
if (error.response) {
|
||||
this.error = true;
|
||||
this.errors = error.response.data.errors;
|
||||
this.errors = error.response.data.errors || {
|
||||
product: [
|
||||
error.response.data.error ||
|
||||
error.response.data.messages ||
|
||||
error.response.data.message ||
|
||||
"Ошибка при сохранении",
|
||||
],
|
||||
};
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
categoryOptions(level) {
|
||||
const parent = this.category.path[level - 1];
|
||||
|
||||
return parent && parent.parents ? parent.parents : [];
|
||||
},
|
||||
|
||||
selectCategoryLevel(level) {
|
||||
this.category.path.splice(level + 1);
|
||||
},
|
||||
|
||||
lastSelectedCategory() {
|
||||
for (let i = this.category.path.length - 1; i >= 0; i--) {
|
||||
if (this.category.path[i] && this.category.path[i].id) {
|
||||
return this.category.path[i];
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
|
||||
remaincharRUCount: function () {
|
||||
if (this.product.short_body.ru.length > 300) {
|
||||
this.short_limit.ru = "Превышен лимит в 300 символов.";
|
||||
@@ -1376,6 +1410,13 @@ export default {
|
||||
},
|
||||
|
||||
async getCharacteristics(id) {
|
||||
id = id && id.id ? id.id : id;
|
||||
|
||||
if (!id) {
|
||||
this.characteristics = [];
|
||||
return;
|
||||
}
|
||||
|
||||
const { data } = await axios.get(
|
||||
"/dashboard/products/characteristics/" + id
|
||||
);
|
||||
@@ -1391,10 +1432,16 @@ export default {
|
||||
this.category.three = {};
|
||||
this.category.three_view = false;
|
||||
|
||||
if (this.category.first.parents.length > 0) {
|
||||
if (!this.category.first || !this.category.first.id) {
|
||||
this.product.category_id = null;
|
||||
return;
|
||||
}
|
||||
|
||||
this.product.category_id = this.category.first.id;
|
||||
this.getCharacteristics(this.category.first.id);
|
||||
|
||||
if (this.category.first.parents && this.category.first.parents.length > 0) {
|
||||
this.category.two_view = true;
|
||||
} else {
|
||||
this.product.category_id = this.category.first.id;
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1402,12 +1449,23 @@ export default {
|
||||
this.category.three = {};
|
||||
this.category.three_view = false;
|
||||
|
||||
if (this.category.two.parents.length > 0) {
|
||||
if (!this.category.two || !this.category.two.id) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.product.category_id = this.category.two.id;
|
||||
this.getCharacteristics(this.category.two.id);
|
||||
|
||||
if (this.category.two.parents && this.category.two.parents.length > 0) {
|
||||
this.category.three_view = true;
|
||||
}
|
||||
},
|
||||
|
||||
DetectCategoryThree() {
|
||||
if (!this.category.three || !this.category.three.id) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.product.category_id = this.category.three.id;
|
||||
},
|
||||
|
||||
@@ -1442,25 +1500,17 @@ export default {
|
||||
// this.$refs.vueFileAgent.deleteUpload(this.uploadUrl, this.uploadHeaders, fileData);
|
||||
// },
|
||||
|
||||
filesSelected: function (filesDataNewlySelected, index) {
|
||||
var validFilesData = filesDataNewlySelected.filter(
|
||||
(fileData) => !fileData.error
|
||||
);
|
||||
this.product.colors[index].filesDataForUpload =
|
||||
this.product.colors[index].filesDataForUpload.concat(
|
||||
validFilesData
|
||||
);
|
||||
},
|
||||
onBeforeDelete: function (fileData, index) {
|
||||
const agent = Array.isArray(this.$refs.vueFileAgent)
|
||||
? this.$refs.vueFileAgent[index]
|
||||
: this.$refs.vueFileAgent;
|
||||
|
||||
fileDeleted: function (fileData, index) {
|
||||
var i =
|
||||
this.product.colors[index].filesDataForUpload.indexOf(fileData);
|
||||
if (i !== -1) {
|
||||
this.product.colors[index].filesDataForUpload.splice(i, 1);
|
||||
} else {
|
||||
this.deleteUploadedFile(fileData);
|
||||
if (agent) {
|
||||
agent.deleteFileRecord(fileData);
|
||||
}
|
||||
},
|
||||
|
||||
fileDeleted: function () {},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -21,6 +21,23 @@
|
||||
|
||||
<!-- JavaScript for delete confirmation -->
|
||||
<script>
|
||||
window.PreviewImage = window.PreviewImage || function(event) {
|
||||
var input = event && event.target
|
||||
? event.target
|
||||
: document.activeElement || document.getElementById('uploadImage') || document.getElementById('poster');
|
||||
var preview = document.getElementById('uploadPreview');
|
||||
|
||||
if (!input || !input.files || !input.files[0] || !preview) {
|
||||
return;
|
||||
}
|
||||
|
||||
var reader = new FileReader();
|
||||
reader.onload = function(readerEvent) {
|
||||
preview.src = readerEvent.target.result;
|
||||
};
|
||||
reader.readAsDataURL(input.files[0]);
|
||||
};
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const deleteForms = document.querySelectorAll('.delete-alert');
|
||||
|
||||
|
||||
@@ -118,6 +118,17 @@
|
||||
</li>
|
||||
@endif
|
||||
|
||||
@can('view', 'sliders')
|
||||
<li class="nav-item {{ active([route('dashboard.sliders'), route('dashboard.sliders') . '/*']) }}">
|
||||
<a href="{{ route('dashboard.sliders') }}">
|
||||
<i class="feather icon-image"></i>
|
||||
<span class="menu-title">
|
||||
@lang('admin.slider.title')
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
@endcan
|
||||
|
||||
@can('view', 'users')
|
||||
<li class="nav-item {{ active([route('dashboard.users'), route('dashboard.users') . '/*']) }}"><a
|
||||
href="{{ route('dashboard.users') }}">
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
<div id="app">
|
||||
<product-edit :product="{{ json_encode($product) }}" :brands="{{ json_encode($brands) }}"
|
||||
:categories="{{ json_encode($categories) }}" :colors="{{ json_encode($colors) }}"
|
||||
:back-url="{{ json_encode(url()->previous()) }}" :measurement="{{ json_encode($measurement) }}"></product-edit>
|
||||
:back-url="{{ json_encode(route('dashboard.products')) }}" :measurement="{{ json_encode($measurement) }}"></product-edit>
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
|
||||
@@ -50,25 +50,14 @@ Route::get('/', function () {
|
||||
return view('welcome');
|
||||
});
|
||||
|
||||
Route::middleware('locale')->group(function () {
|
||||
// Route::get('/', [SiteMainPageController::class, 'index'])->name('site.main.page');
|
||||
// Route::get('locale/{lang}', [SiteLocaleController::class, 'setLocale'])->name('site.setLocale');
|
||||
// Route::get('pages/{slug}', [SitePageController::class, 'getPage'])->name('site.default-page');
|
||||
// Route::get('search', [SiteProductController::class, 'search'])->name('search');
|
||||
|
||||
// Route::middleware('authProfile')->group(function () {
|
||||
// Route::get('favorites', [SiteFavoriteController::class, 'index'])->name('favorites');
|
||||
// Route::get('favorites/store/{product}', [SiteFavoriteController::class, 'store']);
|
||||
// Route::get('favorites/delete/{product}', [SiteFavoriteController::class, 'delete']);
|
||||
// });
|
||||
|
||||
Route::prefix('category')->group(function () {
|
||||
Route::get('/', 'CategoryController@all')->name('categories');
|
||||
Route::get('/{category}', 'CategoryController@index')->name('category.view');
|
||||
Route::get('/{category}/{Category}', 'CategoryController@show')->name('category.show');
|
||||
Route::get('/{category}/{slug}/{Category}', 'CategoryController@showCatalog')->name('category.showParent');
|
||||
Route::post('/filter/{category}', 'CategoryController@filter')->name('category.filter');
|
||||
});
|
||||
// Public site category controllers were removed. Keep the route names for legacy
|
||||
// link generation, but avoid old string-controller routes that break Laravel 11.
|
||||
Route::middleware('locale')->prefix('category')->group(function () {
|
||||
Route::get('/', fn () => abort(404))->name('categories');
|
||||
Route::get('/{category}', fn () => abort(404))->name('category.view');
|
||||
Route::get('/{category}/{Category}', fn () => abort(404))->name('category.show');
|
||||
Route::get('/{category}/{slug}/{Category}', fn () => abort(404))->name('category.showParent');
|
||||
Route::post('/filter/{category}', fn () => abort(404))->name('category.filter');
|
||||
});
|
||||
|
||||
// Route::get('/sitemap.xml', 'Site\MainPageController@sitemap')->name('sitemap');
|
||||
|
||||
Reference in New Issue
Block a user