Merge pull request #5779 from devansh-webkul/s3-image-cache

This commit is contained in:
Devansh 2022-02-15 12:43:07 +05:30 committed by GitHub
commit 54a51c30d6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 564 additions and 396 deletions

View File

@ -3,29 +3,34 @@
namespace Webkul\Category\Models;
use Illuminate\Database\Eloquent\Factories\Factory;
use Webkul\Core\Eloquent\TranslatableModel;
use Kalnoy\Nestedset\NodeTrait;
use Illuminate\Support\Facades\Storage;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Webkul\Category\Database\Factories\CategoryFactory;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Support\Facades\Storage;
use Kalnoy\Nestedset\NodeTrait;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Webkul\Category\Contracts\Category as CategoryContract;
use Webkul\Attribute\Models\AttributeProxy;
use Webkul\Category\Contracts\Category as CategoryContract;
use Webkul\Category\Database\Factories\CategoryFactory;
use Webkul\Category\Repositories\CategoryRepository;
use Webkul\Core\Eloquent\TranslatableModel;
use Webkul\Product\Models\ProductProxy;
/**
* Class Category
* Category class.
*
* @package Webkul\Category\Models
*
* @property-read string $url_path maintained by database triggers
* @property-read string (`$url_path` maintained by database triggers.)
*/
class Category extends TranslatableModel implements CategoryContract
{
use NodeTrait, HasFactory;
/**
* Translated attributes.
*
* @var array
*/
public $translatedAttributes = [
'name',
'description',
@ -36,6 +41,11 @@ class Category extends TranslatableModel implements CategoryContract
'meta_keywords',
];
/**
* Fillables.
*
* @var array
*/
protected $fillable = [
'position',
'status',
@ -44,106 +54,64 @@ class Category extends TranslatableModel implements CategoryContract
'additional',
];
/**
* Eager loading.
*
* @var array
*/
protected $with = ['translations'];
/**
* Get image url for the category image.
* Appends.
*
* @var array
*/
public function image_url()
{
if (! $this->image) {
return;
}
return Storage::url($this->image);
}
protected $appends = ['image_url', 'category_icon_url'];
/**
* Get image url for the category image.
* The products that belong to the category.
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function getImageUrlAttribute()
public function products(): BelongsToMany
{
return $this->image_url();
return $this->belongsToMany(ProductProxy::modelClass(), 'product_categories');
}
/**
* The filterable attributes that belong to the category.
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function filterableAttributes(): BelongsToMany
{
return $this->belongsToMany(AttributeProxy::modelClass(), 'category_filterable_attributes')
->with([
'options' => function ($query) {
$query->orderBy('sort_order');
},
]);
->with([
'options' => function ($query) {
$query->orderBy('sort_order');
},
]);
}
/**
* Getting the root category of a category
* Finds and returns the category within a nested category tree.
*
* @return \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Eloquent\Model|object
*/
public function getRootCategory()
{
return self::query()
->where([
[
'parent_id',
'=',
null,
],
[
'_lft',
'<=',
$this->_lft,
],
[
'_rgt',
'>=',
$this->_rgt,
],
])
->first();
}
/**
* Returns all categories within the category's path
* Will search in root category by default.
*
* @return Category[]
*/
public function getPathCategories(): array
{
$category = $this->findInTree();
$categories = [$category];
while (isset($category->parent)) {
$category = $category->parent;
$categories[] = $category;
}
return array_reverse($categories);
}
/**
* Finds and returns the category within a nested category tree
* will search in root category by default
* is used to minimize the numbers of sql queries for it only uses the already cached tree
* Is used to minimize the numbers of sql queries for it only uses the already cached tree.
*
* @param Category[] $categoryTree
*
* @return Category
* @param \Webkul\Velocity\Contracts\Category[] $categoryTree
* @return \Webkul\Velocity\Contracts\Category
*/
public function findInTree($categoryTree = null): Category
{
if (!$categoryTree) {
if (! $categoryTree) {
$categoryTree = app(CategoryRepository::class)->getVisibleCategoryTree($this->getRootCategory()->id);
}
$category = $categoryTree->first();
if (!$category) {
if (! $category) {
throw new NotFoundHttpException('category not found in tree');
}
@ -155,20 +123,87 @@ class Category extends TranslatableModel implements CategoryContract
}
/**
* The products that belong to the category.
* Getting the root category of a category.
*
* @return \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Eloquent\Model|object
*/
public function products(): BelongsToMany
public function getRootCategory()
{
return $this->belongsToMany(ProductProxy::modelClass(), 'product_categories');
return self::query()
->where([
[
'parent_id',
'=',
null,
],
[
'_lft',
'<=',
$this->_lft,
],
[
'_rgt',
'>=',
$this->_rgt,
],
])
->first();
}
/**
* Returns all categories within the category's path.
*
* @return \Webkul\Velocity\Contracts\Category[]
*/
public function getPathCategories(): array
{
$category = $this->findInTree();
$categories = [$category];
while (isset($category->parent)) {
$category = $category->parent;
$categories[] = $category;
}
return array_reverse($categories);
}
/**
* Get image url for the category image.
*
* @return string
*/
public function getImageUrlAttribute()
{
if (! $this->image) {
return;
}
return Storage::url($this->image);
}
/**
* Get category icon url for the category icon image.
*
* @return string
*/
public function getCategoryIconUrlAttribute()
{
if (! $this->category_icon_path) {
return;
}
return Storage::url($this->category_icon_path);
}
/**
* Create a new factory instance for the model.
*
* @return Factory
* @return \Illuminate\Database\Eloquent\Factories\Factory
*/
protected static function newFactory(): Factory
{
return CategoryFactory::new();
return CategoryFactory::new ();
}
}
}

View File

@ -52,21 +52,11 @@ class ProductImage extends AbstractProduct
continue;
}
$images[] = [
'small_image_url' => url('cache/small/' . $image->path),
'medium_image_url' => url('cache/medium/' . $image->path),
'large_image_url' => url('cache/large/' . $image->path),
'original_image_url' => url('cache/original/' . $image->path),
];
$images[] = $this->getCachedImageUrls($image->path);
}
if (! $product->parent_id && ! count($images) && ! count($product->videos)) {
$images[] = [
'small_image_url' => asset('vendor/webkul/ui/assets/images/product/small-product-placeholder.webp'),
'medium_image_url' => asset('vendor/webkul/ui/assets/images/product/meduim-product-placeholder.webp'),
'large_image_url' => asset('vendor/webkul/ui/assets/images/product/large-product-placeholder.webp'),
'original_image_url' => asset('vendor/webkul/ui/assets/images/product/large-product-placeholder.webp'),
];
$images[] = $this->getFallbackImageUrls();
}
/*
@ -81,6 +71,27 @@ class ProductImage extends AbstractProduct
return $loadedGalleryImages[$product->id] = $images;
}
/**
* Get product varient image if available otherwise product base image.
*
* @param \Webkul\Customer\Contracts\Wishlist $item
* @return array
*/
public function getProductImage($item)
{
if ($item instanceof \Webkul\Customer\Contracts\Wishlist) {
if (isset($item->additional['selected_configurable_option'])) {
$product = $this->productRepository->find($item->additional['selected_configurable_option']);
} else {
$product = $item->product;
}
} else {
$product = $item->product;
}
return $this->getProductBaseImage($product);
}
/**
* This method will first check whether the gallery images are already
* present or not. If not then it will load from the product.
@ -104,27 +115,6 @@ class ProductImage extends AbstractProduct
}
}
/**
* Get product varient image if available otherwise product base image.
*
* @param \Webkul\Customer\Contracts\Wishlist $item
* @return array
*/
public function getProductImage($item)
{
if ($item instanceof \Webkul\Customer\Contracts\Wishlist) {
if (isset($item->additional['selected_configurable_option'])) {
$product = $this->productRepository->find($item->additional['selected_configurable_option']);
} else {
$product = $item->product;
}
} else {
$product = $item->product;
}
return $this->getProductBaseImage($product);
}
/**
* Load product's base image.
*
@ -135,22 +125,58 @@ class ProductImage extends AbstractProduct
{
$images = $product ? $product->images : null;
if ($images && $images->count()) {
$image = [
'small_image_url' => url('cache/small/' . $images[0]->path),
'medium_image_url' => url('cache/medium/' . $images[0]->path),
'large_image_url' => url('cache/large/' . $images[0]->path),
'original_image_url' => url('cache/original/' . $images[0]->path),
];
} else {
$image = [
'small_image_url' => asset('vendor/webkul/ui/assets/images/product/small-product-placeholder.webp'),
'medium_image_url' => asset('vendor/webkul/ui/assets/images/product/meduim-product-placeholder.webp'),
'large_image_url' => asset('vendor/webkul/ui/assets/images/product/large-product-placeholder.webp'),
'original_image_url' => asset('vendor/webkul/ui/assets/images/product/large-product-placeholder.webp'),
return $images && $images->count()
? $this->getCachedImageUrls($images[0]->path)
: $this->getFallbackImageUrls();
}
/**
* Get cached urls configured for intervention package.
*
* @param string $path
* @return array
*/
private function getCachedImageUrls($path): array
{
if (! $this->isDriverLocal()) {
return [
'small_image_url' => Storage::url($path),
'medium_image_url' => Storage::url($path),
'large_image_url' => Storage::url($path),
'original_image_url' => Storage::url($path),
];
}
return $image;
return [
'small_image_url' => url('cache/small/' . $path),
'medium_image_url' => url('cache/medium/' . $path),
'large_image_url' => url('cache/large/' . $path),
'original_image_url' => url('cache/original/' . $path),
];
}
/**
* Get fallback urls.
*
* @return array
*/
private function getFallbackImageUrls(): array
{
return [
'small_image_url' => asset('vendor/webkul/ui/assets/images/product/small-product-placeholder.webp'),
'medium_image_url' => asset('vendor/webkul/ui/assets/images/product/meduim-product-placeholder.webp'),
'large_image_url' => asset('vendor/webkul/ui/assets/images/product/large-product-placeholder.webp'),
'original_image_url' => asset('vendor/webkul/ui/assets/images/product/large-product-placeholder.webp'),
];
}
/**
* Is driver local.
*
* @return bool
*/
private function isDriverLocal(): bool
{
return Storage::getAdapter() instanceof \League\Flysystem\Adapter\Local;
}
}

View File

@ -1,11 +1,11 @@
@php
$attributeRepository = app('\Webkul\Attribute\Repositories\AttributeFamilyRepository');
$comparableAttributes = $attributeRepository->getComparableAttributesBelongsToFamily();
$locale = core()->getRequestedLocaleCode();
$attributeOptionTranslations = DB::table('attribute_option_translations')->where('locale', $locale)->get()->toJson();
$attributeOptionTranslations = DB::table('attribute_option_translations')->where('locale', $locale)->get();
@endphp
@push('scripts')
@ -129,7 +129,7 @@
<a :href="`${baseUrl}/${product.url_key}`" class="unset">
<img
class="image-wrapper"
:src="'storage/' + product.product['{{ $attribute['code'] }}']"
:src="storageUrl + product.product['{{ $attribute['code'] }}']"
:onerror="`this.src='${baseUrl}/vendor/webkul/ui/assets/images/product/large-product-placeholder.png'`" alt="" />
</a>
@break;
@ -162,11 +162,12 @@
data: function () {
return {
'products': [],
'baseUrl': '{{ url()->to('/') }}',
'storageUrl': '{{ Storage::url('/') }}',
'isCustomer': '{{ auth()->guard('customer')->user() ? "true" : "false" }}' == 'true',
'isProductListLoaded': false,
'baseUrl': "{{ url()->to('/') }}",
'attributeOptions': JSON.parse(@json($attributeOptionTranslations)),
'isCustomer': '{{ auth()->guard('customer')->user() ? "true" : "false" }}' == "true",
}
'attributeOptions': @json($attributeOptionTranslations),
};
},
mounted: function () {
@ -211,7 +212,6 @@
} else {
this.isProductListLoaded = true;
}
},
'removeProductCompare': function (productId) {
@ -363,4 +363,4 @@
}
});
</script>
@endpush
@endpush

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,9 +1,9 @@
{
"/js/jquery-ez-plus.js": "/js/jquery-ez-plus.js?id=ba3c7cada62de152fd8f",
"/js/velocity-core.js": "/js/velocity-core.js?id=8010dfb021a49555afa7",
"/js/velocity.js": "/js/velocity.js?id=ac05caeb5e4b0566a4ab",
"/js/velocity.js": "/js/velocity.js?id=b7d7f53b5f50b56ea3d2",
"/js/manifest.js": "/js/manifest.js?id=3cded37ef514b0fb89b1",
"/js/components.js": "/js/components.js?id=d16d70d3905f32644901",
"/js/components.js": "/js/components.js?id=187f9cabca320d6d5194",
"/css/velocity.css": "/css/velocity.css?id=2b60cf92b982570c9ea9",
"/css/velocity-admin.css": "/css/velocity-admin.css?id=b67a82956e53163b5e3f",
"/images/icon-calendar.svg": "/images/icon-calendar.svg?id=870d0f733a5837742276",

View File

@ -2,16 +2,12 @@
namespace Webkul\Velocity\Http\Controllers\Shop;
use Illuminate\Http\Request;
use Webkul\Product\Facades\ProductImage;
use Webkul\Velocity\Http\Shop\Controllers;
use Webkul\Checkout\Contracts\Cart as CartModel;
use Cart;
class ShopController extends Controller
{
/**
* Index to handle the view loaded with the search results
* Index to handle the view loaded with the search results.
*
* @return \Illuminate\View\View
*/
@ -22,6 +18,12 @@ class ShopController extends Controller
return view($this->_config['view'])->with('results', $results ? $results : null);
}
/**
* Fetch product details.
*
* @param string $slug
* @return \Illuminate\Http\Response
*/
public function fetchProductDetails($slug)
{
$product = $this->productRepository->findBySlug($slug);
@ -40,7 +42,7 @@ class ShopController extends Controller
'totalReviews' => $productReviewHelper->getTotalReviews($product),
'rating' => ceil($productReviewHelper->getAverageRating($product)),
'image' => $galleryImages['small_image_url'],
]
],
];
} else {
$response = [
@ -53,6 +55,8 @@ class ShopController extends Controller
}
/**
* Fetch category details.
*
* @return \Illuminate\Http\Response
*/
public function categoryDetails()
@ -62,15 +66,15 @@ class ShopController extends Controller
if (! $slug) {
abort(404);
}
switch ($slug) {
case 'new-products':
case 'featured-products':
$count = request()->get('count');
if ($slug == "new-products") {
if ($slug == 'new-products') {
$products = $this->velocityProductRepository->getNewProducts($count);
} else if ($slug == "featured-products") {
} else if ($slug == 'featured-products') {
$products = $this->velocityProductRepository->getFeaturedProducts($count);
}
@ -123,24 +127,28 @@ class ShopController extends Controller
}
/**
* Fetch categories.
*
* @return array
*/
public function fetchCategories()
{
$formattedCategories = [];
$categories = $this->categoryRepository->getVisibleCategoryTree(core()->getCurrentChannel()->root_category_id);
foreach ($categories as $category) {
array_push($formattedCategories, $this->getCategoryFilteredData($category));
$formattedCategories[] = $this->getCategoryFilteredData($category);
}
return [
'status' => true,
'categories' => $formattedCategories,
];
}
/**
* Fetch fancy category.
*
* @param string $slug
* @return array
*/
@ -151,7 +159,7 @@ class ShopController extends Controller
if ($categoryDetails) {
$response = [
'status' => true,
'categoryDetails' => $this->getCategoryFilteredData($categoryDetails)
'categoryDetails' => $this->getCategoryFilteredData($categoryDetails),
];
}
@ -161,28 +169,8 @@ class ShopController extends Controller
}
/**
* @param \Webkul\Category\Contracts\Category $category
* @return array
*/
private function getCategoryFilteredData($category)
{
$formattedChildCategory = [];
foreach ($category->children as $child) {
array_push($formattedChildCategory, $this->getCategoryFilteredData($child));
}
return [
'id' => $category->id,
'slug' => $category->slug,
'name' => $category->name,
'children' => $formattedChildCategory,
'category_icon_path' => $category->category_icon_path,
'image' => $category->image
];
}
/**
* Get wishlist.
*
* @return \Illuminate\View\View
*/
public function getWishlistList()
@ -191,7 +179,7 @@ class ShopController extends Controller
}
/**
* this function will provide the count of wishlist and comparison for logged in user
* This function will provide the count of wishlist and comparison for logged in user.
*
* @return \Illuminate\Http\Response
*/
@ -206,10 +194,10 @@ class ShopController extends Controller
->where(function ($qb) {
$qb
->WhereIn('ps.type', ['configurable', 'grouped', 'downloadable', 'bundle', 'booking'])
->orwhereIn('ps.type', ['simple', 'virtual'])->where('pv.qty' , '>' , 0);
->orwhereIn('ps.type', ['simple', 'virtual'])->where('pv.qty', '>', 0);
})
->where('wishlist.customer_id' , $customer->id)
->where('wishlist.channel_id' , core()->getCurrentChannel()->id)
->where('wishlist.customer_id', $customer->id)
->where('wishlist.channel_id', core()->getCurrentChannel()->id)
->count('wishlist.id');
} else {
$wishlistItemsCount = $this->wishlistRepository->count([
@ -223,25 +211,24 @@ class ShopController extends Controller
]);
$response = [
'status' => true,
'status' => true,
'compareProductsCount' => $comparedItemsCount,
'wishlistedProductsCount' => $wishlistItemsCount,
];
}
return response()->json($response ?? [
'status' => false
'status' => false,
]);
}
/**
* This function will provide details of multiple product
* This method will provide details of multiple product.
*
* @return \Illuminate\Http\Response
*/
public function getDetailedProducts()
{
// for product details
if ($items = request()->get('items')) {
$moveToCart = request()->get('moveToCart');
@ -254,7 +241,7 @@ class ShopController extends Controller
}
return response()->json($response ?? [
'status' => false
'status' => false,
]);
}
@ -273,8 +260,8 @@ class ShopController extends Controller
/* if category not found then return empty response */
if (! $categoryDetails) {
return response()->json([
'products' => [],
'paginationHTML' => ''
'products' => [],
'paginationHTML' => '',
]);
}
@ -284,10 +271,34 @@ class ShopController extends Controller
/* sending response */
return response()->json([
'products' => collect($products->items())->map(function ($product) {
'products' => collect($products->items())->map(function ($product) {
return $this->velocityHelper->formatProduct($product);
}),
'paginationHTML' => $products->appends(request()->input())->links()->toHtml()
'paginationHTML' => $products->appends(request()->input())->links()->toHtml(),
]);
}
}
/**
* Get category filtered data.
*
* @param \Webkul\Category\Contracts\Category $category
* @return array
*/
private function getCategoryFilteredData($category)
{
$formattedChildCategory = [];
foreach ($category->children as $child) {
$formattedChildCategory[] = $this->getCategoryFilteredData($child);
}
return [
'id' => $category->id,
'slug' => $category->slug,
'name' => $category->name,
'children' => $formattedChildCategory,
'category_icon_url' => $category->category_icon_url,
'image_url' => $category->image_url,
];
}
}

View File

@ -44,6 +44,7 @@
v-for="(
category, index
) in rootCategoriesCollection"
:key="index"
>
<a
class="unset"
@ -52,8 +53,8 @@
<div class="category-logo">
<img
class="category-icon"
v-if="category.category_icon_path"
:src="`${$root.baseUrl}/storage/${category.category_icon_path}`"
v-if="category.category_icon_url"
:src="category.category_icon_url"
alt=""
width="20"
height="20"
@ -143,14 +144,17 @@
<img
class="category-icon"
v-if="
nestedSubCategory.category_icon_path
nestedSubCategory.category_icon_url
"
:src="
nestedSubCategory.category_icon_url
"
:src="`${$root.baseUrl}/storage/${nestedSubCategory.category_icon_path}`"
alt=""
width="20"
height="20"
/>
</div>
<span v-text="nestedSubCategory.name"></span>
</a>
@ -163,7 +167,7 @@
"
>
<li
:key="`index-${Math.random()}`"
:key="`index-${index}`"
v-for="(
thirdLevelCategory, index
) in nestedSubCategory.children"
@ -176,9 +180,11 @@
<img
class="category-icon"
v-if="
thirdLevelCategory.category_icon_path
thirdLevelCategory.category_icon_url
"
:src="
thirdLevelCategory.category_icon_url
"
:src="`${$root.baseUrl}/storage/${thirdLevelCategory.category_icon_path}`"
alt=""
width="20"
height="20"
@ -201,10 +207,12 @@
class="rango-arrow-left fs24 text-down-4"
@click="toggleMetaInfo('languages')"
></i>
<h4
class="display-inbl"
v-text="__('responsive.header.languages')"
></h4>
<i
class="material-icons float-right text-dark"
@click="closeDrawer()"
@ -238,10 +246,12 @@
class="rango-arrow-left fs24 text-down-4"
@click="toggleMetaInfo('currencies')"
></i>
<h4
class="display-inbl"
v-text="__('shop.general.currencies')"
></h4>
<i
class="material-icons float-right text-dark"
@click="closeDrawer()"
@ -348,6 +358,7 @@ export default {
created: function () {
this.getMiniCartDetails();
this.updateHeaderItemsCount();
},

View File

@ -1,9 +1,12 @@
<template>
<div class="col-lg-3 col-md-12 hot-category-wrapper" v-if="hotCategoryDetails">
<div
class="col-lg-3 col-md-12 hot-category-wrapper"
v-if="hotCategoryDetails"
>
<div class="card">
<div class="row velocity-divide-page">
<div class="left">
<img :src="`${$root.baseUrl}/storage/${hotCategoryDetails.category_icon_path}`" alt="" />
<img :src="hotCategoryDetails.category_icon_url" alt="" />
</div>
<div class="right">
@ -14,8 +17,16 @@
</h3>
<ul type="none">
<li :key="index" v-for="(subCategory, index) in hotCategoryDetails.children">
<a :href="`${slug}/${subCategory.slug}`" class="remove-decoration normal-text">
<li
:key="index"
v-for="(
subCategory, index
) in hotCategoryDetails.children"
>
<a
:href="`${slug}/${subCategory.slug}`"
class="remove-decoration normal-text"
>
{{ subCategory.name }}
</a>
</li>
@ -27,32 +38,31 @@
</template>
<script>
export default {
props: [
'slug'
],
export default {
props: ['slug'],
data: function () {
return {
'hotCategoryDetails': null
}
},
data: function () {
return {
hotCategoryDetails: null,
};
},
mounted: function () {
this.getHotCategories();
},
mounted: function () {
this.getHotCategories();
},
methods: {
'getHotCategories': function () {
this.$http.get(`${this.baseUrl}/fancy-category-details/${this.slug}`)
.then(response => {
methods: {
getHotCategories: function () {
this.$http
.get(`${this.baseUrl}/fancy-category-details/${this.slug}`)
.then((response) => {
if (response.data.status)
this.hotCategoryDetails = response.data.categoryDetails;
})
.catch(error => {
.catch((error) => {
console.log('something went wrong');
})
}
}
}
</script>
});
},
},
};
</script>

View File

@ -1,16 +1,31 @@
<template>
<div class="col-lg-3 col-md-12 popular-category-wrapper" v-if="popularCategoryDetails">
<div
class="col-lg-3 col-md-12 popular-category-wrapper"
v-if="popularCategoryDetails"
>
<div class="card col-12 no-padding">
<div class="category-image">
<img :data-src="`${$root.baseUrl}/storage/${popularCategoryDetails.image}`" class="lazyload" alt="" />
<img
:data-src="popularCategoryDetails.image_url"
class="lazyload"
alt=""
/>
</div>
<div class="card-description">
<h3 class="fs20">{{ popularCategoryDetails.name }}</h3>
<ul class="font-clr pl30">
<li :key="index" v-for="(subCategory, index) in popularCategoryDetails.children">
<a :href="`${slug}/${subCategory.slug}`" class="remove-decoration normal-text">
<li
:key="index"
v-for="(
subCategory, index
) in popularCategoryDetails.children"
>
<a
:href="`${slug}/${subCategory.slug}`"
class="remove-decoration normal-text"
>
{{ subCategory.name }}
</a>
</li>
@ -21,33 +36,33 @@
</template>
<script>
export default {
props: [
'slug'
],
export default {
props: ['slug'],
data: function () {
return {
'popularCategoryDetails': null
}
},
data: function () {
return {
popularCategoryDetails: null,
};
},
mounted: function () {
this.getPopularCategories();
},
mounted: function () {
this.getPopularCategories();
},
methods: {
'getPopularCategories': function () {
this.$http.get(`${this.baseUrl}/fancy-category-details/${this.slug}`)
.then(response => {
methods: {
getPopularCategories: function () {
this.$http
.get(`${this.baseUrl}/fancy-category-details/${this.slug}`)
.then((response) => {
if (response.data.status) {
this.popularCategoryDetails = response.data.categoryDetails;
this.popularCategoryDetails =
response.data.categoryDetails;
}
})
.catch(error => {
console.log('something went wrong');
})
}
}
}
</script>
.catch((error) => {
console.log('Something went wrong!');
});
},
},
};
</script>

View File

@ -1,11 +1,10 @@
<template>
<!-- categories list -->
<nav
:id="id"
@mouseover="remainBar(id)"
:class="`sidebar ${addClass ? addClass : ''}`"
v-if="slicedCategories && slicedCategories.length > 0">
v-if="slicedCategories && slicedCategories.length > 0"
>
<ul type="none">
<li
:key="categoryIndex"
@ -13,21 +12,25 @@
class="category-content cursor-pointer"
@mouseout="toggleSidebar(id, $event, 'mouseout')"
@mouseover="toggleSidebar(id, $event, 'mouseover')"
v-for="(category, categoryIndex) in slicedCategories">
v-for="(category, categoryIndex) in slicedCategories"
>
<a
:href="`${$root.baseUrl}/${category.slug}`"
:class="`category unset ${(category.children.length > 0) ? 'fw6' : ''}`">
:class="`category unset ${
category.children.length > 0 ? 'fw6' : ''
}`"
>
<div
class="category-icon"
@mouseout="toggleSidebar(id, $event, 'mouseout')"
@mouseover="toggleSidebar(id, $event, 'mouseover')">
@mouseover="toggleSidebar(id, $event, 'mouseover')"
>
<img
v-if="category.category_icon_path"
:src="`${$root.baseUrl}/storage/${category.category_icon_path}`"
width="20" height="20" />
v-if="category.category_icon_url"
:src="category.category_icon_url"
width="20"
height="20"
/>
</div>
<span class="category-title">{{ category['name'] }}</span>
@ -36,57 +39,119 @@
class="rango-arrow-right pr15 float-right"
@mouseout="toggleSidebar(id, $event, 'mouseout')"
@mouseover="toggleSidebar(id, $event, 'mouseover')"
v-if="category.children.length && category.children.length > 0">
v-if="
category.children.length &&
category.children.length > 0
"
>
</i>
</a>
<div
class="sub-category-container"
v-if="category.children.length && category.children.length > 0">
v-if="
category.children.length && category.children.length > 0
"
>
<div
@mouseout="toggleSidebar(id, $event, 'mouseout')"
@mouseover="remainBar(`sidebar-level-${sidebarLevel+categoryIndex}`)"
:class="`sub-categories sub-category-${sidebarLevel+categoryIndex} cursor-default`">
@mouseover="
remainBar(
`sidebar-level-${sidebarLevel + categoryIndex}`
)
"
:class="`sub-categories sub-category-${
sidebarLevel + categoryIndex
} cursor-default`"
>
<nav
class="sidebar"
:id="`sidebar-level-${sidebarLevel+categoryIndex}`"
@mouseover="remainBar(`sidebar-level-${sidebarLevel+categoryIndex}`)">
:id="`sidebar-level-${
sidebarLevel + categoryIndex
}`"
@mouseover="
remainBar(
`sidebar-level-${
sidebarLevel + categoryIndex
}`
)
"
>
<ul type="none">
<li
:key="`${subCategoryIndex}-${categoryIndex}`"
v-for="(subCategory, subCategoryIndex) in category.children">
v-for="(
subCategory, subCategoryIndex
) in category.children"
>
<a
:id="`sidebar-level-link-2-${subCategoryIndex}`"
@mouseout="toggleSidebar(id, $event, 'mouseout')"
@mouseout="
toggleSidebar(
id,
$event,
'mouseout'
)
"
:href="`${$root.baseUrl}/${category.slug}/${subCategory.slug}`"
:class="`category sub-category unset ${(subCategory.children.length > 0) ? 'fw6' : ''}`">
:class="`category sub-category unset ${
subCategory.children.length > 0
? 'fw6'
: ''
}`"
>
<div
class="category-icon"
@mouseout="toggleSidebar(id, $event, 'mouseout')"
@mouseover="toggleSidebar(id, $event, 'mouseover')">
@mouseout="
toggleSidebar(
id,
$event,
'mouseout'
)
"
@mouseover="
toggleSidebar(
id,
$event,
'mouseover'
)
"
>
<img
v-if="subCategory.category_icon_path"
:src="`${$root.baseUrl}/storage/${subCategory.category_icon_path}`" />
v-if="
subCategory.category_icon_url
"
:src="
subCategory.category_icon_url
"
/>
</div>
<span class="category-title">{{ subCategory['name'] }}</span>
<span class="category-title">{{
subCategory['name']
}}</span>
</a>
<ul type="none" class="nested">
<li
:key="`${childSubCategoryIndex}-${subCategoryIndex}-${categoryIndex}`"
v-for="(childSubCategory, childSubCategoryIndex) in subCategory.children">
v-for="(
childSubCategory,
childSubCategoryIndex
) in subCategory.children"
>
<a
:id="`sidebar-level-link-3-${childSubCategoryIndex}`"
:class="`category unset ${(subCategory.children.length > 0) ? 'fw6' : ''}`"
:href="`${$root.baseUrl}/${category.slug}/${subCategory.slug}/${childSubCategory.slug}`">
<span class="category-title">{{ childSubCategory.name }}</span>
:class="`category unset ${
subCategory.children
.length > 0
? 'fw6'
: ''
}`"
:href="`${$root.baseUrl}/${category.slug}/${subCategory.slug}/${childSubCategory.slug}`"
>
<span class="category-title">{{
childSubCategory.name
}}</span>
</a>
</li>
</ul>
@ -101,60 +166,55 @@
</template>
<script type="text/javascript">
export default {
props: [
'id',
'addClass',
'parentSlug',
'mainSidebar',
'categoryCount'
],
export default {
props: ['id', 'addClass', 'parentSlug', 'mainSidebar', 'categoryCount'],
data: function () {
return {
slicedCategories: [],
sidebarLevel: Math.floor(Math.random() * 1000),
data: function () {
return {
slicedCategories: [],
sidebarLevel: Math.floor(Math.random() * 1000),
};
},
watch: {
'$root.sharedRootCategories': function (categories) {
this.formatCategories(categories);
},
},
methods: {
remainBar: function (id) {
let sidebar = $(`#${id}`);
if (sidebar && sidebar.length > 0) {
sidebar.show();
let actualId = id.replace('sidebar-level-', '');
let sidebarContainer = sidebar.closest(
`.sub-category-${actualId}`
);
if (sidebarContainer && sidebarContainer.length > 0) {
sidebarContainer.show();
}
}
},
watch: {
'$root.sharedRootCategories': function (categories) {
this.formatCategories(categories);
formatCategories: function (categories) {
let slicedCategories = categories;
let categoryCount = this.categoryCount ? this.categoryCount : 9;
if (slicedCategories && slicedCategories.length > categoryCount) {
slicedCategories = categories.slice(0, categoryCount);
}
if (this.parentSlug) {
slicedCategories['parentSlug'] = this.parentSlug;
}
this.slicedCategories = slicedCategories;
},
methods: {
remainBar: function (id) {
let sidebar = $(`#${id}`);
if (sidebar && sidebar.length > 0) {
sidebar.show();
let actualId = id.replace('sidebar-level-', '');
let sidebarContainer = sidebar.closest(`.sub-category-${actualId}`)
if (sidebarContainer && sidebarContainer.length > 0) {
sidebarContainer.show();
}
}
},
formatCategories: function (categories) {
let slicedCategories = categories;
let categoryCount = this.categoryCount ? this.categoryCount : 9;
if (
slicedCategories
&& slicedCategories.length > categoryCount
) {
slicedCategories = categories.slice(0, categoryCount);
}
if (this.parentSlug)
slicedCategories['parentSlug'] = this.parentSlug;
this.slicedCategories = slicedCategories;
},
}
}
</script>
},
};
</script>

View File

@ -347,12 +347,13 @@ $(function() {
.get(`${this.baseUrl}/categories`)
.then(response => {
this.sharedRootCategories = response.data.categories;
$(
`<style type='text/css'> .sub-categories{ min-height:${ response.data.categories.length * 30 }px;} </style>`
).appendTo('head');
})
.catch(error => {
console.error(`failed to load categories:`, error);
console.error(`Failed to load categories:`, error);
});
},

View File

@ -1,18 +1,18 @@
<div class="control-group">
<label>{{ __('velocity::app.admin.meta-data.category-logo') }}</label>
@if (isset($category) && $category->category_icon_path)
@if (isset($category) && $category->category_icon_url)
<image-wrapper
:multiple="false"
input-name="category_icon_path"
:images='"{{ url()->to('/') . '/storage/' . $category->category_icon_path }}"'
:button-label="'{{ __('admin::app.catalog.products.add-image-btn-title') }}'">
images="{{ $category->category_icon_url }}"
button-label="{{ __('admin::app.catalog.products.add-image-btn-title') }}">
</image-wrapper>
@else
<image-wrapper
:multiple="false"
input-name="category_icon_path"
:button-label="'{{ __('admin::app.catalog.products.add-image-btn-title') }}'">
button-label="{{ __('admin::app.catalog.products.add-image-btn-title') }}">
</image-wrapper>
@endif

View File

@ -6,21 +6,25 @@
@php
$locale = core()->checkRequestedLocaleCodeInRequestedChannel();
$channel = core()->getRequestedChannelCode();
$channelLocales = core()->getAllLocalesByRequestedChannel()['locales'];
$metaRoute = $metaData
? route('velocity.admin.store.meta-data', ['id' => $metaData->id])
: route('velocity.admin.store.meta-data', ['id' => 'new']);
@endphp
@push('css')
<style>
@media only screen and (max-width: 680px){
.content-container .content .page-header .page-title {
float: left;
width: 100%;
margin-bottom: 12px;
}
.content-container .content .page-header .page-action button {
position: absolute;
right: 2px;
@ -34,22 +38,16 @@
}
}
</style>
@endpush
@section('content')
<div class="content">
<form
method="POST"
@submit.prevent="onSubmit"
enctype="multipart/form-data"
@if ($metaData)
action="{{ route('velocity.admin.store.meta-data', ['id' => $metaData->id]) }}"
@else
action="{{ route('velocity.admin.store.meta-data', ['id' => 'new']) }}"
@endif
action="{{ $metaRoute }}"
@submit.prevent="onSubmit"
>
@csrf
<div class="page-header">
@ -58,6 +56,7 @@
</div>
<input type="hidden" name="locale" value="{{ $locale }}" />
<input type="hidden" name="channel" value="{{ $channel }}" />
<div class="control-group">
@ -229,7 +228,7 @@
@php
$images[4][] = [
'id' => 'image_' . $index,
'url' => asset('/storage/' . $image),
'url' => Storage::url($image),
];
@endphp
@endforeach
@ -273,7 +272,7 @@
@php
$images[3][] = [
'id' => 'image_' . $index,
'url' => asset('/storage/' . $image),
'url' => Storage::url($image),
];
@endphp
@endforeach
@ -312,7 +311,7 @@
@php
$images[2][] = [
'id' => 'image_' . $index,
'url' => asset('/storage/' . $image),
'url' => Storage::url($image),
];
@endphp
@endforeach

View File

@ -4,7 +4,7 @@
$locale = core()->getRequestedLocaleCode();
$attributeOptionTranslations = app('\Webkul\Attribute\Repositories\AttributeOptionTranslationRepository')->where('locale', $locale)->get()->toJson();
$attributeOptionTranslations = app('\Webkul\Attribute\Repositories\AttributeOptionTranslationRepository')->where('locale', $locale)->get();
@endphp
@push('scripts')
@ -127,7 +127,7 @@
<img
class="image-wrapper"
onload="window.updateHeight ? window.updateHeight() : ''"
:src="'storage/' + product.product['{{ $attribute['code'] }}']"
:src="storageUrl + product.product['{{ $attribute['code'] }}']"
:onerror="`this.src='${$root.baseUrl}/vendor/webkul/ui/assets/images/product/large-product-placeholder.png'`"
alt=""/>
</a>
@ -162,10 +162,11 @@
data: function () {
return {
'products': [],
'isProductListLoaded': false,
'attributeOptions': JSON.parse(@json($attributeOptionTranslations)),
'storageUrl': '{{ Storage::url('/') }}',
'isCustomer': '{{ auth()->guard('customer')->user() ? "true" : "false" }}' == "true",
}
'isProductListLoaded': false,
'attributeOptions': @json($attributeOptionTranslations),
};
},
mounted: function () {
@ -208,7 +209,6 @@
} else {
this.isProductListLoaded = true;
}
},
'removeProductCompare': function (productId) {
@ -340,4 +340,4 @@
}
});
</script>
@endpush
@endpush

View File

@ -25,8 +25,8 @@
<a @if (isset($one)) href="{{ $one }}" @endif aria-label="Advertisement">
<img
class="{{ $isLazyLoad ? 'lazyload' : '' }}"
@if (! $isLazyLoad) src="{{ asset('/storage/' . $advertisementFour[0]) }}" @endif
data-src="{{ asset('/storage/' . $advertisementFour[0]) }}" alt="" />
@if (! $isLazyLoad) src="{{ Storage::url($advertisementFour[0]) }}" @endif
data-src="{{ Storage::url($advertisementFour[0]) }}" alt="" />
</a>
@endif
</div>
@ -36,8 +36,8 @@
<a @if (isset($two)) href="{{ $two }}" @endif class="row col-12 remove-padding-margin" aria-label="Advertisement">
<img
class="offers-ct-top {{ $isLazyLoad ? 'lazyload' : '' }}"
@if (! $isLazyLoad) src="{{ asset('/storage/' . $advertisementFour[1]) }}" @endif
data-src="{{ asset('/storage/' . $advertisementFour[1]) }}" alt="" />
@if (! $isLazyLoad) src="{{ Storage::url($advertisementFour[1]) }}" @endif
data-src="{{ Storage::url($advertisementFour[1]) }}" alt="" />
</a>
@endif
@ -47,8 +47,8 @@
<a @if (isset($three)) href="{{ $three }}" @endif class="row col-12 remove-padding-margin" aria-label="Advertisement">
<img
class="offers-ct-bottom {{ $isLazyLoad ? 'lazyload' : '' }}"
@if (! $isLazyLoad) src="{{ asset('/storage/' . $advertisementFour[2]) }}" @endif
data-src="{{ asset('/storage/' . $advertisementFour[2]) }}" alt="" />
@if (! $isLazyLoad) src="{{ Storage::url($advertisementFour[2]) }}" @endif
data-src="{{ Storage::url($advertisementFour[2]) }}" alt="" />
</a>
@endif
</div>
@ -58,8 +58,8 @@
<a @if (isset($four)) href="{{ $four }}" @endif aria-label="Advertisement">
<img
class="{{ $isLazyLoad ? 'lazyload' : '' }}"
@if (! $isLazyLoad) src="{{ asset('/storage/' . $advertisementFour[3]) }}" @endif
data-src="{{ asset('/storage/' . $advertisementFour[3]) }}" alt="" />
@if (! $isLazyLoad) src="{{ Storage::url($advertisementFour[3]) }}" @endif
data-src="{{ Storage::url($advertisementFour[3]) }}" alt="" />
</a>
@endif
</div>

View File

@ -20,7 +20,7 @@
<div class="row">
<div
class="col offers-lt-panel bg-image"
style="background-image: url('{{ asset('/storage/' . $advertisementOne['image_1']) }}')">
style="background-image: url('{{ Storage::url($advertisementOne['image_1']) }}')">
</div>
<div class="col offers-ct-panel">
@ -28,14 +28,14 @@
<div class="row pb10">
<div
class="col-12 offers-ct-top"
style="background-image: url('{{ asset('/storage/' . $advertisementOne['image_2']) }}')">
style="background-image: url('{{ Storage::url($advertisementOne['image_2']) }}')">
</div>
</div>
<div class="row">
<div
class="col-12 offers-ct-bottom"
style="background-image: url('{{ asset('/storage/' . $advertisementOne['image_3']) }}')">
style="background-image: url('{{ Storage::url($advertisementOne['image_3']) }}')">
</div>
</div>
@ -43,7 +43,7 @@
<div
class="col offers-rt-panel"
style="background-image: url('{{ asset('/storage/' . $advertisementOne['image_4']) }}')">
style="background-image: url('{{ Storage::url($advertisementOne['image_4']) }}')">
</div>
</div>
</div>

View File

@ -24,8 +24,8 @@
<a @if (isset($one)) href="{{ $one }}" @endif class="col-lg-6 col-md-12 no-padding">
<img
class="full-width {{ $isLazyLoad ? 'lazyload' : '' }}"
@if (! $isLazyLoad) src="{{ asset('/storage/' . $advertisementThree[0]) }}" @endif
data-src="{{ asset('/storage/' . $advertisementThree[0]) }}" alt="" />
@if (! $isLazyLoad) src="{{ Storage::url($advertisementThree[0]) }}" @endif
data-src="{{ Storage::url($advertisementThree[0]) }}" alt="" />
</a>
@endif
@ -34,16 +34,16 @@
<a @if (isset($two)) href="{{ $two }}" @endif class="row top-container">
<img
class="col-12 pr0 {{ $isLazyLoad ? 'lazyload' : '' }}"
@if (! $isLazyLoad) src="{{ asset('/storage/' . $advertisementThree[1]) }}" @endif
data-src="{{ asset('/storage/' . $advertisementThree[1]) }}" alt="" />
@if (! $isLazyLoad) src="{{ Storage::url($advertisementThree[1]) }}" @endif
data-src="{{ Storage::url($advertisementThree[1]) }}" alt="" />
</a>
@endif
@if ( isset($advertisementThree[2]))
<a @if (isset($three)) href="{{ $three }}" @endif class="row bottom-container">
<img
class="col-12 pr0 {{ $isLazyLoad ? 'lazyload' : '' }}"
@if (! $isLazyLoad) src="{{ asset('/storage/' . $advertisementThree[2]) }}" @endif
data-src="{{ asset('/storage/' . $advertisementThree[2]) }}" alt="" />
@if (! $isLazyLoad) src="{{ Storage::url($advertisementThree[2]) }}" @endif
data-src="{{ Storage::url($advertisementThree[2]) }}" alt="" />
</a>
@endif
</div>

View File

@ -24,8 +24,8 @@
<a class="col-lg-9 col-md-12 no-padding">
<img
class="{{ $isLazyLoad ? 'lazyload' : '' }}"
@if (! $isLazyLoad) src="{{ asset('/storage/' . $advertisementTwo[0]) }}" @endif
data-src="{{ asset('/storage/' . $advertisementTwo[0]) }}" alt="" />
@if (! $isLazyLoad) src="{{ Storage::url($advertisementTwo[0]) }}" @endif
data-src="{{ Storage::url($advertisementTwo[0]) }}" alt="" />
</a>
@endif
@ -33,8 +33,8 @@
<a class="col-lg-3 col-md-12 pr0">
<img
class="{{ $isLazyLoad ? 'lazyload' : '' }}"
@if (! $isLazyLoad) src="{{ asset('/storage/' . $advertisementTwo[1]) }}" @endif
data-src="{{ asset('/storage/' . $advertisementTwo[1]) }}" alt="" />
@if (! $isLazyLoad) src="{{ Storage::url($advertisementTwo[1]) }}" @endif
data-src="{{ Storage::url($advertisementTwo[1]) }}" alt="" />
</a>
@endif
</div>

View File

@ -10,7 +10,7 @@
<div class="container-fluid category-with-custom-options">
<div class="row">
<div class="col pr15">
<img data-src="{{ asset ('/storage/' . $category['2']->image) }}" class="lazyload" alt="" />
<img data-src="{{ $category['2']->image_url }}" class="lazyload" alt="" />
</div>
<div class="col">
@ -39,7 +39,7 @@
</div>
<div class="col pr15">
<img data-src="{{ asset ('/storage/' . $category['0']->image) }}" class="lazyload" alt=""/>
<img data-src="{{ $category['0']->image_url }}" class="lazyload" alt=""/>
</div>
<div class="col">
@ -94,7 +94,7 @@
</div>
</div>
<div class="col mt15">
<img data-src="{{ asset ('/storage/' . $category['3']->image) }}" class="lazyload" alt="" />
<img data-src="{{ $category['3']->image_url }}" class="lazyload" alt="" />
</div>
<div class="col mt15 mr15">
@ -123,7 +123,7 @@
</div>
<div class="col">
<img data-src="{{ asset ('/storage/' . $category['1']->image) }}" class="lazyload" alt="" />
<img data-src="{{ $category['1']->image_url }}" class="lazyload" alt="" />
</div>
</div>
@ -133,7 +133,7 @@
@foreach ($category as $categoryItem)
<div class="smart-category-container">
<div class="col-12">
<img data-src="{{ asset ('/storage/' . $categoryItem->image) }}" class="lazyload" alt="" />
<img data-src="{{ $categoryItem->image_url }}" class="lazyload" alt="" />
</div>
<div class="col-12">

View File

@ -40,11 +40,11 @@
@push('css')
@if (! empty($sliderData))
<link rel="preload" as="image" href="{{ asset('/storage/' . $sliderData[0]['path']) }}">
<link rel="preload" as="image" href="{{ Storage::url($sliderData[0]['path']) }}">
@else
<link rel="preload" as="image" href="{{ asset('/themes/velocity/assets/images/banner.webp') }}">
@endif
<style type="text/css">
.product-price span:first-child, .product-price span:last-child {
font-size: 18px;

View File

@ -7,7 +7,7 @@
{{-- this is default content if js is not loaded --}}
@if(! empty($sliderData))
<img class="col-12 no-padding banner-icon" src="{{ asset('/storage/' . $sliderData[0]['path']) }}" alt=""/>
<img class="col-12 no-padding banner-icon" src="{{ Storage::url($sliderData[0]['path']) }}" alt=""/>
@else
<img class="col-12 no-padding banner-icon" src="{{ asset('/themes/velocity/assets/images/banner.webp') }}" alt=""/>
@endif