Merge pull request #1 from bagisto/master

This commit is contained in:
Glenn Hermans 2020-10-14 11:05:55 +02:00 committed by GitHub
commit 96b1074f79
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
161 changed files with 831 additions and 367 deletions

45
.gitignore vendored
View File

@ -1,28 +1,29 @@
/docker-compose-collection
/storage/dcc-data/
/node_modules
/public/hot
/public/storage
/public/css
/public/js
/public/vendor
/public/themes
/public/fonts
/vendor
.env
.idea
.php_cs.cache
.vscode
.vagrant
/data
/.idea
/.vscode
/.vagrant
/docker-compose-collection
Homestead.json
Homestead.yaml
npm-debug.log
yarn-error.log
.env
/ignorables/*
yarn.lock
/node_modules
npm-debug.log
package-lock.json
yarn.lock
.php_cs.cache
storage/*.key
/public/css
/public/fonts
/public/js
/public/hot
/public/storage
/public/themes
/public/vendor
/resources/themes/velocity/*
/resources/lang/vendor/webkul/admin/*
/resources/lang/vendor/admin/*
/resources/lang/vendor/shop/*
/resources/lang/vendor/velocity/*
/storage/*.key
/storage/dcc-data/
/vendor
yarn.lock
yarn-error.log

View File

@ -17,7 +17,5 @@ return [
// Return neither true nor false but null by default to not interrupt the default chain that
// defines if a product is saleable. It depends on the isSaleable() method of the product
// type if this callable is obeyed.
'isSaleable' => function (Product $product): ?bool {
return null;
},
'isSaleable' => null,
];

View File

@ -69,10 +69,18 @@ class AddressController extends Controller
{
$customer = auth($this->guard)->user();
request()->merge([
'address1' => implode(PHP_EOL, array_filter(request()->input('address1'))),
'customer_id' => $customer->id,
]);
if (request()->input('address1') && ! is_array(json_decode(request()->input('address1')))) {
return response()->json([
'message' => 'address1 must be an array.',
]);
}
if (request()->input('address1')) {
request()->merge([
'address1' => implode(PHP_EOL, array_filter(json_decode(request()->input('address1')))),
'customer_id' => $customer->id,
]);
}
$this->validate(request(), [
'address1' => 'string|required',

View File

@ -4,6 +4,8 @@ namespace Webkul\API\Http\Controllers\Shop;
use Cart;
use Exception;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Event;
@ -142,22 +144,28 @@ class CartController extends Controller
*
* @return \Illuminate\Http\JsonResponse
*/
public function update()
public function update(Request $request)
{
foreach (request()->get('qty') as $qty) {
$this->validate($request, [
'qty' => 'required|array',
]);
$requestedQuantity = $request->get('qty');
foreach ($requestedQuantity as $qty) {
if ($qty <= 0) {
return response()->json([
'message' => trans('shop::app.checkout.cart.quantity.illegal'),
], 401);
], Response::HTTP_UNAUTHORIZED);
}
}
foreach (request()->get('qty') as $itemId => $qty) {
foreach ($requestedQuantity as $itemId => $qty) {
$item = $this->cartItemRepository->findOneByField('id', $itemId);
Event::dispatch('checkout.cart.item.update.before', $itemId);
Cart::updateItems(request()->all());
Cart::updateItems(['qty' => $requestedQuantity]);
Event::dispatch('checkout.cart.item.update.after', $item);
}

View File

@ -2,6 +2,7 @@
namespace Webkul\API\Http\Controllers\Shop;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Event;
use Webkul\Customer\Repositories\CustomerRepository;
@ -69,24 +70,25 @@ class CustomerController extends Controller
*
* @return \Illuminate\Http\Response
*/
public function create()
public function create(Request $request)
{
request()->validate([
$this->validate($request, [
'first_name' => 'required',
'last_name' => 'required',
'email' => 'email|required|unique:customers,email',
'password' => 'confirmed|min:6|required',
]);
$data = request()->input();
$data = array_merge($data, [
'password' => bcrypt($data['password']),
'channel_id' => core()->getCurrentChannel()->id,
'is_verified' => 1,
]);
$data['customer_group_id'] = $this->customerGroupRepository->findOneWhere(['code' => 'general'])->id;
$data = [
'first_name' => $request->get('first_name'),
'last_name' => $request->get('last_name'),
'email' => $request->get('email'),
'password' => $request->get('password'),
'password' => bcrypt($request->get('password')),
'channel_id' => core()->getCurrentChannel()->id,
'is_verified' => 1,
'customer_group_id' => $this->customerGroupRepository->findOneWhere(['code' => 'general'])->id
];
Event::dispatch('customer.registration.before');

View File

@ -9,21 +9,21 @@ use Webkul\API\Http\Resources\Catalog\ProductReview as ProductReviewResource;
class ReviewController extends Controller
{
/**
* Contains current guard
* Contains current guard.
*
* @var array
*/
protected $guard;
/**
* ProductReviewRepository object
* ProductReviewRepository $reviewRepository
*
* @var \Webkul\Product\Repositories\ProductReviewRepository
*/
protected $reviewRepository;
/**
* Controller instance
* Controller instance.
*
* @param Webkul\Product\Repositories\ProductReviewRepository $reviewRepository
*/
@ -47,24 +47,25 @@ class ReviewController extends Controller
{
$customer = auth($this->guard)->user();
$this->validate(request(), [
$this->validate($request, [
'comment' => 'required',
'rating' => 'required|numeric|min:1|max:5',
'title' => 'required',
]);
$data = array_merge(request()->all(), [
$productReview = $this->reviewRepository->create([
'customer_id' => $customer ? $customer->id : null,
'name' => $customer ? $customer->name : request()->input('name'),
'name' => $customer ? $customer->name : $request->get('name'),
'status' => 'pending',
'product_id' => $id,
'comment' => $request->comment,
'rating' => $request->rating,
'title' => $request->title
]);
$productReview = $this->reviewRepository->create($data);
return response()->json([
'message' => 'Your review submitted successfully.',
'data' => new ProductReviewResource($this->reviewRepository->find($productReview->id)),
'data' => new ProductReviewResource($productReview),
]);
}
}

View File

@ -103,23 +103,19 @@ class SessionController extends Controller
'password' => 'confirmed|min:6',
]);
$data = request()->all();
$data = request()->only('first_name', 'last_name', 'gender', 'date_of_birth', 'email', 'password');
if (! $data['date_of_birth']) {
unset($data['date_of_birth']);
}
if (!isset($data['password']) || ! $data['password']) {
if (! isset($data['password']) || ! $data['password']) {
unset($data['password']);
} else {
$data['password'] = bcrypt($data['password']);
}
$this->customerRepository->update($data, $customer->id);
$updatedCustomer = $this->customerRepository->update($data, $customer->id);
return response()->json([
'message' => 'Your account has been created successfully.',
'data' => new CustomerResource($this->customerRepository->find($customer->id)),
'message' => 'Your account has been updated successfully.',
'data' => new CustomerResource($updatedCustomer),
]);
}
@ -136,4 +132,4 @@ class SessionController extends Controller
'message' => 'Logged out successfully.',
]);
}
}
}

View File

@ -158,13 +158,13 @@ return [
'name' => 'no_of_new_product_homepage',
'title' => 'admin::app.admin.system.allow-no-of-new-product-homepage',
'type' => 'number',
'validation' => 'required|min:0',
'validation' => 'min:0',
],
[
'name' => 'no_of_featured_product_homepage',
'title' => 'admin::app.admin.system.allow-no-of-featured-product-homepage',
'type' => 'number',
'validation' => 'required|min:0',
'validation' => 'min:0',
],
],
], [

View File

@ -170,7 +170,7 @@ class AddressController extends Controller
session()->flash('success', trans('admin::app.customers.addresses.success-delete'));
return redirect()->back();
return redirect()->route($this->_config['redirect']);
}
/**

View File

@ -17,7 +17,7 @@ class AdminServiceProvider extends ServiceProvider
$this->loadRoutesFrom(__DIR__ . '/../Http/routes.php');
$this->loadTranslationsFrom(__DIR__ . '/../Resources/lang', 'admin');
$this->publishes([__DIR__.'/../Resources/lang' => resource_path('lang/vendor/webkul/admin')]);
$this->publishes([__DIR__.'/../Resources/lang' => resource_path('lang/vendor/admin')]);
$this->publishes([
__DIR__ . '/../../publishable/assets' => public_path('vendor/webkul/admin/assets'),

View File

@ -938,6 +938,7 @@ return [
'gender' => 'Gender',
'email' => 'Email',
'date_of_birth' => 'Date of Birth',
'date_of_birth_placeholder' => 'yyyy-mm-dd',
'phone' => 'Phone',
'customer_group' => 'Customer Group',
'save-btn-title' => 'Save Customer',

View File

@ -359,7 +359,7 @@
<tbody>
<tr v-for="(row, index) in optionRows">
<tr v-for="(row, index) in optionRows" :key="row.id">
<td v-if="show_swatch && swatch_type == 'color'">
<swatch-picker :input-name="'options[' + row.id + '][swatch_value]'" :color="row.swatch_value" colors="text-advanced" show-fallback />
</td>

View File

@ -72,7 +72,7 @@
<div class="control-group" :class="[errors.has('date_of_birth') ? 'has-error' : '']">
<label for="dob">{{ __('admin::app.customers.customers.date_of_birth') }}</label>
<input type="date" class="control" name="date_of_birth" v-validate="" value="{{ old('date_of_birth') }}" data-vv-as="&quot;{{ __('admin::app.customers.customers.date_of_birth') }}&quot;">
<input type="date" class="control" name="date_of_birth" v-validate="" value="{{ old('date_of_birth') }}" placeholder="{{ __('admin::app.customers.customers.date_of_birth_placeholder') }}" data-vv-as="&quot;{{ __('admin::app.customers.customers.date_of_birth') }}&quot;">
<span class="control-error" v-if="errors.has('date_of_birth')">@{{ errors.first('date_of_birth') }}</span>
</div>

View File

@ -1,16 +1,14 @@
{!! view_render_event('bagisto.admin.customer.edit.before', ['customer' => $customer]) !!}
<form method="POST" action="{{ route('admin.customer.update', $customer->id) }}">
<div class="page-content">
<div class="form-container">
@csrf()
<input name="_method" type="hidden" value="PUT">
<div class="style:overflow: auto;">&nbsp;</div>
<div slot="body">
{!! view_render_event('bagisto.admin.customer.edit.form.before', ['customer' => $customer]) !!}
<div class="control-group" :class="[errors.has('first_name') ? 'has-error' : '']">
<label for="first_name" class="required"> {{ __('admin::app.customers.customers.first_name') }}</label>
<input type="text" class="control" name="first_name" v-validate="'required'" value="{{old('first_name') ?:$customer->first_name}}"
@ -19,7 +17,7 @@
</div>
{!! view_render_event('bagisto.admin.customer.edit.first_name.after', ['customer' => $customer]) !!}
<div class="control-group" :class="[errors.has('last_name') ? 'has-error' : '']">
<label for="last_name" class="required"> {{ __('admin::app.customers.customers.last_name') }}</label>
<input type="text" class="control" name="last_name" v-validate="'required'" value="{{old('last_name') ?:$customer->last_name}}" data-vv-as="&quot;{{ __('shop::app.customer.signup-form.lastname') }}&quot;">
@ -95,11 +93,13 @@
@endforeach
</select>
</div>
{!! view_render_event('bagisto.admin.customer.edit.form.after', ['customer' => $customer]) !!}
</div>
<button type="submit" class="btn btn-lg btn-primary">
{{ __('admin::app.customers.customers.save-btn-title') }}
</button>
</div>
</div>
</form>
{!! view_render_event('bagisto.admin.customer.edit.after', ['customer' => $customer]) !!}
</form>

View File

@ -1,7 +1,7 @@
{{ $address->company_name ?? '' }}</br>
<b>{{ $address->name }}</b></br>
{{ $address->address1 }}</br>
{{ $address->city }}</br>
{{ $address->state }}</br>
{{ core()->country_name($address->country) }} {{ $address->postcode }}</br></br>
{{ __('shop::app.checkout.onepage.contact') }} : {{ $address->phone }}
{{ $address->company_name ?? '' }}<br>
<b>{{ $address->name }}</b><br>
{{ $address->address1 }}<br>
{{ $address->postcode }} {{ $address->city }}<br>
{{ $address->state }}<br>
{{ core()->country_name($address->country) }}<br></br>
{{ __('shop::app.checkout.onepage.contact') }} : {{ $address->phone }}

View File

@ -78,7 +78,7 @@
<div class="control-group" :class="[errors.has('tax_rate') ? 'has-error' : '']">
<label for="tax_rate" class="required">{{ __('admin::app.configuration.tax-rates.tax_rate') }}</label>
<input v-validate="'required|min_value:0.0001'" class="control" id="tax_rate" name="tax_rate" data-vv-as="&quot;{{ __('admin::app.configuration.tax-rates.tax_rate') }}&quot;" value="{{ old('tax_rate') }}"/>
<input v-validate="'required|decimal|min_value:0.0001'" class="control" id="tax_rate" name="tax_rate" data-vv-as="&quot;{{ __('admin::app.configuration.tax-rates.tax_rate') }}&quot;" value="{{ old('tax_rate') }}"/>
<span class="control-error" v-if="errors.has('tax_rate')">@{{ errors.first('tax_rate') }}</span>
</div>
</div>

View File

@ -62,7 +62,7 @@
<div class="control-group" :class="[errors.has('tax_rate') ? 'has-error' : '']">
<label for="tax_rate" class="required">{{ __('admin::app.configuration.tax-rates.tax_rate') }}</label>
<input v-validate="'required|min_value:0.0001'" class="control" id="tax_rate" name="tax_rate" data-vv-as="&quot;{{ __('admin::app.configuration.tax-rates.tax_rate') }}&quot;" value="{{ old('tax_rate') ?: $taxRate->tax_rate }}" />
<input v-validate="'required|decimal|min_value:0.0001'" class="control" id="tax_rate" name="tax_rate" data-vv-as="&quot;{{ __('admin::app.configuration.tax-rates.tax_rate') }}&quot;" value="{{ old('tax_rate') ?: $taxRate->tax_rate }}" />
<span class="control-error" v-if="errors.has('tax_rate')">@{{ errors.first('tax_rate') }}</span>
</div>

View File

@ -537,6 +537,7 @@ class CartRule
}
$coupons = $this->cartRuleCouponRepository->where(['code' => $cart->coupon_code])->get();
foreach ($coupons as $coupon) {
if (in_array($coupon->cart_rule_id, explode(',', $cart->applied_cart_rule_ids))) {
return true;

View File

@ -159,7 +159,11 @@ class CatalogRuleRepository extends Repository
if ($attribute->code == 'tax_category_id') {
$options = $this->getTaxCategories();
} else {
$options = $attribute->options;
if ($attribute->type === 'select') {
$options = $attribute->options()->orderBy('sort_order')->get();
} else {
$options = $attribute->options;
}
}
if ($attribute->validation == 'decimal')

View File

@ -0,0 +1,56 @@
<?php
namespace Webkul\Category\Database\Seeders;
use Faker\Generator as Faker;
use Illuminate\Database\Seeder;
use Webkul\Category\Repositories\CategoryRepository;
/*
* CategoryBulkTableSeeder
*
* Command: php artisan db:seed --class=Webkul\\Category\\Database\\Seeders\\CategoryBulkTableSeeder
*
* This seeder has not included anywhere just for development purpose.
*/
class CategoryBulkTableSeeder extends Seeder
{
private $numberOfParentCategories = 10;
private $numberOfChildCategories = 50;
public function __construct(
Faker $faker,
CategoryRepository $categoryRepository
)
{
$this->faker = $faker;
$this->categoryRepository = $categoryRepository;
}
public function run()
{
for ($i = 0; $i < $this->numberOfParentCategories; ++$i) {
$createdCategory = $this->categoryRepository->create([
'slug' => $this->faker->slug,
'name' => $this->faker->firstName,
'description' => $this->faker->text(),
'parent_id' => 1,
'status' => 1,
]);
if ($createdCategory) {
for ($j = 0; $j < $this->numberOfChildCategories; ++$j) {
$this->categoryRepository->create([
'slug' => $this->faker->slug,
'name' => $this->faker->firstName,
'description' => $this->faker->text(),
'parent_id' => $createdCategory->id,
'status' => 1
]);
}
}
}
}
}

View File

@ -65,12 +65,14 @@ class Category extends TranslatableModel implements CategoryContract
*/
public function filterableAttributes()
{
return $this->belongsToMany(AttributeProxy::modelClass(), 'category_filterable_attributes')->with('options');
return $this->belongsToMany(AttributeProxy::modelClass(), 'category_filterable_attributes')->with(['options' => function($query) {
$query->orderBy('sort_order');
}]);
}
/**
* Getting the root category of a category
*
*
* @return Category
*/
public function getRootCategory(): Category
@ -124,7 +126,7 @@ class Category extends TranslatableModel implements CategoryContract
if ($category->id === $this->id) {
return $category;
}
return $this->findInTree($category->children);
}
}

View File

@ -293,6 +293,7 @@ class Cart
public function getItemByProduct($data)
{
$items = $this->getCart()->all_items;
foreach ($items as $item) {
if ($item->product->getTypeInstance()->compareOptions($item->additional, $data['additional'])) {
if (isset($data['additional']['parent_id'])) {
@ -402,6 +403,7 @@ class Cart
public function getCart(): ?\Webkul\Checkout\Contracts\Cart
{
$cart = null;
if ($this->getCurrentCustomer()->check()) {
$cart = $this->cartRepository->findOneWhere([
'customer_id' => $this->getCurrentCustomer()->user()->id,
@ -591,6 +593,7 @@ class Cart
if (! $cart = $this->getCart()) {
return false;
}
if (count($cart->items) === 0) {
$this->cartRepository->delete($cart->id);
@ -604,7 +607,9 @@ class Cart
if ($validationResult->isItemInactive()) {
$this->removeItem($item->id);
$isInvalid = true;
session()->flash('info', __('shop::app.checkout.cart.item.inactive'));
}
@ -703,6 +708,7 @@ class Cart
$item->save();
}
Event::dispatch('checkout.cart.calculate.items.tax.after', $cart);
}

View File

@ -38,7 +38,7 @@ class Install extends Command
public function handle()
{
$this->checkForEnvFile();
sleep(3);
// running `php artisan migrate`
$this->warn('Step: Migrating all tables into database...');
$migrate = $this->call('migrate:fresh');
@ -90,6 +90,7 @@ class Install extends Command
$this->info('Creating the environment configuration file.');
$this->createEnvFile();
} else {
$this->call('key:generate');
$this->info('Great! your environment configuration file already exists.');
}
}

View File

@ -17,7 +17,11 @@ class ChannelTableSeeder extends Seeder
'name' => 'Default',
'theme' => 'velocity',
'root_category_id' => 1,
'home_page_content' => '<p>@include("shop::home.slider") @include("shop::home.featured-products") @include("shop::home.new-products")</p><div class="banner-container"><div class="left-banner"><img src="https://s3-ap-southeast-1.amazonaws.com/cdn.uvdesk.com/website/1/201902045c581f9494b8a1.png" /></div><div class="right-banner"><img src="https://s3-ap-southeast-1.amazonaws.com/cdn.uvdesk.com/website/1/201902045c581fb045cf02.png" /> <img src="https://s3-ap-southeast-1.amazonaws.com/cdn.uvdesk.com/website/1/201902045c581fc352d803.png" /></div></div>',
'home_page_content' => '<p>@include("shop::home.slider") @include("shop::home.featured-products") @include("shop::home.new-products")</p>
<div class="banner-container">
<div class="left-banner"><img data-src="themes/default/assets/images/1.webp" class="lazyload" alt="test" width="720" height="720" /></div>
<div class="right-banner"><img data-src="themes/default/assets/images/2.webp" class="lazyload" alt="test" width="460" height="330" /> <img data-src="themes/default/assets/images/3.webp" class="lazyload" alt="test" width="460" height="330" /></div>
</div>',
'footer_content' => '<div class="list-container"><span class="list-heading">Quick Links</span><ul class="list-group"><li><a href="@php echo route(\'shop.cms.page\', \'about-us\') @endphp">About Us</a></li><li><a href="@php echo route(\'shop.cms.page\', \'return-policy\') @endphp">Return Policy</a></li><li><a href="@php echo route(\'shop.cms.page\', \'refund-policy\') @endphp">Refund Policy</a></li><li><a href="@php echo route(\'shop.cms.page\', \'terms-conditions\') @endphp">Terms and conditions</a></li><li><a href="@php echo route(\'shop.cms.page\', \'terms-of-use\') @endphp">Terms of Use</a></li><li><a href="@php echo route(\'shop.cms.page\', \'contact-us\') @endphp">Contact Us</a></li></ul></div><div class="list-container"><span class="list-heading">Connect With Us</span><ul class="list-group"><li><a href="#"><span class="icon icon-facebook"></span>Facebook </a></li><li><a href="#"><span class="icon icon-twitter"></span> Twitter </a></li><li><a href="#"><span class="icon icon-instagram"></span> Instagram </a></li><li><a href="#"> <span class="icon icon-google-plus"></span>Google+ </a></li><li><a href="#"> <span class="icon icon-linkedin"></span>LinkedIn </a></li></ul></div>',
'name' => 'Default',
'default_locale_id' => 1,

View File

@ -55,7 +55,7 @@ class Handler extends AppExceptionHandler
return response()->json(['error' => $this->jsonErrorMessages[401]], 401);
}
return redirect()->guest(route('auth.login'));
return redirect()->guest(route('customer.session.index'));
}
private function isAdminUri()

View File

@ -153,6 +153,10 @@ class ChannelController extends Controller
$channel = $this->channelRepository->update($data, $id);
if ($channel->base_currency->code !== session()->get('currency')) {
session()->put('currency', $channel->base_currency->code);
}
Event::dispatch('core.channel.update.after', $channel);
session()->flash('success', trans('admin::app.settings.channels.update-success'));

View File

@ -15,6 +15,7 @@ return [
'code' => 'paypal_smart_button',
'title' => 'Paypal Smart Button',
'description' => 'Paypal Smart Button',
'client_id' => 'sb',
'class' => 'Webkul\Paypal\Payment\SmartButton',
'sandbox' => true,
'active' => true,

View File

@ -1,4 +1,11 @@
<script src="https://www.paypal.com/sdk/js?client-id={{core()->getConfigData('sales.paymentmethods.paypal_smart_button.client_id')}}"></script>
@if (request()->route()->getName() == 'shop.checkout.onepage.index')
<script src="https://www.paypal.com/sdk/js?client-id={{core()->getConfigData('sales.paymentmethods.paypal_smart_button.client_id')}}" data-partner-attribution-id="Bagisto_Cart"></script>
<style>
.component-frame.visible {
z-index: 1 !important;
}
</style>
<script>
window.onload = (function() {
@ -27,6 +34,8 @@
// Finalize the transaction
onApprove: function(data, actions) {
app.showLoader();
return actions.order.capture().then(function(details) {
return window.axios.post("{{ route('paypal.smart_button.save_order') }}", {
'_token': "{{ csrf_token() }}",
@ -40,6 +49,8 @@
window.location.href = "{{ route('shop.checkout.success') }}";
}
}
app.hideLoader()
})
.catch(function (error) {
window.location.href = "{{ route('shop.checkout.cart.index') }}";
@ -51,4 +62,5 @@
paypal.Buttons(options).render(".paypal-button-container");
});
});
</script>
</script>
@endif

View File

@ -3,9 +3,30 @@
namespace Webkul\Product\Helpers;
use Illuminate\Support\Facades\Storage;
use Webkul\Product\Repositories\ProductRepository;
class ProductImage extends AbstractProduct
{
/**
* ProductRepository instance
*
* @var \Webkul\Product\Repositories\ProductRepository
*/
protected $productRepository;
/**
* Create a new helper instance.
*
* @param \Webkul\Product\Repositories\ProductRepository $productRepository
* @return void
*/
public function __construct(
ProductRepository $productRepository
)
{
$this->productRepository = $productRepository;
}
/**
* Retrieve collection of gallery images
*
@ -35,10 +56,10 @@ class ProductImage extends AbstractProduct
if (! $product->parent_id && ! count($images)) {
$images[] = [
'small_image_url' => asset('vendor/webkul/ui/assets/images/product/small-product-placeholder.png'),
'medium_image_url' => asset('vendor/webkul/ui/assets/images/product/meduim-product-placeholder.png'),
'large_image_url' => asset('vendor/webkul/ui/assets/images/product/large-product-placeholder.png'),
'original_image_url' => asset('vendor/webkul/ui/assets/images/product/large-product-placeholder.png'),
'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'),
];
}
@ -64,13 +85,34 @@ class ProductImage extends AbstractProduct
];
} else {
$image = [
'small_image_url' => asset('vendor/webkul/ui/assets/images/product/small-product-placeholder.png'),
'medium_image_url' => asset('vendor/webkul/ui/assets/images/product/meduim-product-placeholder.png'),
'large_image_url' => asset('vendor/webkul/ui/assets/images/product/large-product-placeholder.png'),
'original_image_url' => asset('vendor/webkul/ui/assets/images/product/large-product-placeholder.png'),
'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 $image;
}
/**
* 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);
}
}

View File

@ -87,6 +87,42 @@ class ProductFlatRepository extends Repository
return $filterAttributes;
}
/**
* filter attributes according to products
*
* @param array $category
* @return \Illuminate\Support\Collection
*/
public function getProductsRelatedFilterableAttributes($category) {
$products = app('Webkul\Product\Repositories\ProductRepository')->getProductsRelatedToCategory($category->id);
$filterAttributes = $this->getFilterableAttributes($category, $products);
$allProductAttributeOptionsCode = [];
foreach ($products as $key => $product) {
foreach ($filterAttributes as $attribute) {
if ($attribute->code <> 'price') {
if (isset($product[$attribute->code])) {
if (! in_array($product[$attribute->code], $allProductAttributeOptionsCode)) {
array_push($allProductAttributeOptionsCode, $product[$attribute->code]);
}
}
}
}
}
foreach ($filterAttributes as $attribute) {
foreach ($attribute->options as $key => $option) {
if (! in_array($option->id, $allProductAttributeOptionsCode)) {
unset($attribute->options[$key]);
}
}
}
return $filterAttributes;
}
/**
* update product_flat custom column

View File

@ -110,6 +110,23 @@ class ProductRepository extends Repository
Event::dispatch('catalog.product.delete.after', $id);
}
/**
* @param int $categoryId
*
* @return \Illuminate\Support\Collection
*/
public function getProductsRelatedToCategory($categoryId = null)
{
$qb = $this->model
->leftJoin('product_categories', 'products.id', '=', 'product_categories.product_id');
if ($categoryId) {
$qb->where('product_categories.category_id', $categoryId);
}
return $qb->get();
}
/**
* @param int $categoryId
*

View File

@ -1,3 +1,4 @@
/node_modules
/package-lock.json
npm-debug.log
/resources/lang/vendor/shop/*
npm-debug.log

View File

@ -23,6 +23,7 @@
"dependencies": {
"accounting": "^0.4.1",
"ez-plus": "^1.2.1",
"lazysizes": "^5.2.2",
"vee-validate": "^2.2.15",
"vue-flatpickr": "^2.3.0",
"vue-slider-component": "^3.1.0"

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 936 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 694 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 338 B

File diff suppressed because one or more lines are too long

View File

@ -1,4 +1,4 @@
{
"/js/shop.js": "/js/shop.js?id=e8a8f56c4e7037f09d9f",
"/css/shop.css": "/css/shop.css?id=5921caa0500dc820d23f"
"/js/shop.js": "/js/shop.js?id=73723ffa31b9e1876375",
"/css/shop.css": "/css/shop.css?id=4d6a80790b697b2dc931"
}

View File

@ -13,6 +13,13 @@ return [
'locale_based' => true,
'channel_based' => true,
],
[
'name' => 'image_search',
'title' => 'shop::app.search.image-search-option',
'type' => 'boolean',
'locale_based' => true,
'channel_based' => true,
],
],
]
];

View File

@ -24,6 +24,7 @@ class ShopServiceProvider extends ServiceProvider
$this->loadRoutesFrom(__DIR__ . '/../Http/routes.php');
$this->loadTranslationsFrom(__DIR__ . '/../Resources/lang', 'shop');
$this->publishes([__DIR__.'/../Resources/lang' => resource_path('lang/vendor/shop')]);
$this->publishes([
__DIR__ . '/../../publishable/assets' => public_path('themes/default/assets'),
@ -86,4 +87,4 @@ class ShopServiceProvider extends ServiceProvider
dirname(__DIR__) . '/Config/system.php', 'core'
);
}
}
}

View File

@ -7,11 +7,13 @@ import axios from 'axios';
import VueSlider from 'vue-slider-component';
import accounting from 'accounting';
import ImageSlider from './components/image-slider';
import 'lazysizes';
window.jQuery = window.$ = $;
window.Vue = Vue;
window.VeeValidate = VeeValidate;
window.axios = axios;
require("./bootstrap");
require("ez-plus/src/jquery.ez-plus.js");
@ -127,4 +129,6 @@ $(document).ready(function () {
}
}
});
window.app = app;
});

View File

@ -1,22 +1,24 @@
<template>
<transition name="slide">
<div class="slider-content" v-if="images.length>0">
<transition name="slide">
<div class="slider-content" v-if="images.length > 0">
<ul class="slider-images">
<li v-for="(image, index) in images" :key="index" v-bind:class="{'show': index==currentIndex}">
<img class="slider-item" :src="image" />
<div class="show-content" v-bind:class="{'show': index==currentIndex}" :key="index" v-html="content[index]"></div>
</li>
</ul>
<ul class="slider-images">
<li v-for="(image, index) in images" :key="index" v-bind:class="{'show': index==currentIndex}">
<a :href="image.slider_path">
<img class="slider-item" :alt="image.title" :src="image.path" />
<div class="show-content" v-bind:class="{'show': index==currentIndex}" :key="index" v-html="content[index]"></div>
</a>
</li>
</ul>
<div class="slider-control" v-if="images_loaded">
<span class="icon dark-left-icon slider-left" @click="changeIndexLeft"></span>
<span class="icon light-right-icon slider-right" @click="changeIndexRight"></span>
<div class="slider-control" v-if="images_loaded">
<span class="icon dark-left-icon slider-left" @click="changeIndexLeft"></span>
<span class="icon light-right-icon slider-right" @click="changeIndexRight"></span>
</div>
</div>
</div>
</transition>
</transition>
</template>
<script>
export default {
@ -37,11 +39,14 @@ export default {
return {
images: [],
currentIndex: -1,
content: [],
current: false,
images_loaded: false,
currentIndex: -1,
content: [],
current: false,
images_loaded: false,
};
},
@ -56,17 +61,22 @@ export default {
},
setProps() {
var this_this = this;
var self = this;
this.slides.forEach(function(slider) {
this_this.images.push(this_this.public_path+'/storage/'+slider.path);
self.images.push({
'path': self.public_path + '/storage/' + slider.path,
'title' : slider.title,
'slider_path': slider.slider_path ? slider.slider_path : null
});
this_this.content.push(slider.content);
self.content.push(slider.content);
});
this.currentIndex = 0;
if(this.images.length == 0) {
this.images.push = "vendor/webkul/shop/assets/images/banner.png";
if (this.images.length == 0) {
this.images.push = {'path': 'vendor/webkul/shop/assets/images/banner.png'};
} else {
this.images_loaded = true;
}
@ -90,24 +100,19 @@ export default {
}
};
</script>
<style>
.slide-enter-active {
transition: all 0.2s cubic-bezier(0.55, 0.085, 0.68, 0.53);
}
.slide-leave-active {
transition: all 0.25s cubic-bezier(0.25, 0.46, 0.45, 0.94);
}
.slide-enter, .slide-leave-to {
-webkit-transform: scaleY(0) translateZ(0);
transform: scaleY(0) translateZ(0);
opacity: 0;
}
</style>

View File

@ -1,4 +1,4 @@
@import url("https://fonts.googleapis.com/css?family=Montserrat:400,500");
@import url("https://fonts.googleapis.com/css?family=Montserrat:400,500&display=swap");
//shop variables
$brand-color: #0031F0;

View File

@ -72,7 +72,8 @@ return [
'page-title' => 'بحث',
'found-results' => 'تم العثور على نتائج البحث',
'found-result' => 'تم العثور على نتيجة البحث',
'analysed-keywords' => 'Analysed Keywords'
'analysed-keywords' => 'Analysed Keywords',
'image-search-option' => 'Image Search Option'
],
'reviews' => [

View File

@ -72,7 +72,8 @@ return [
'page-title' => config('app.name') . ' - Suchen',
'found-results' => 'Suchergebnisse gefunden',
'found-result' => 'Suchergebnis gefunden',
'analysed-keywords' => 'Analysed Keywords'
'analysed-keywords' => 'Analysed Keywords',
'image-search-option' => 'Image Search Option'
],
'reviews' => [

View File

@ -72,7 +72,8 @@ return [
'page-title' => config('app.name') . ' - Search',
'found-results' => 'Search Results Found',
'found-result' => 'Search Result Found',
'analysed-keywords' => 'Analysed Keywords'
'analysed-keywords' => 'Analysed Keywords',
'image-search-option' => 'Image Search Option'
],
'reviews' => [

View File

@ -69,7 +69,8 @@ return [
'page-title' => 'Búsqueda',
'found-results' => 'No hay resultados de búsqueda',
'found-result' => 'Resultados de la búsqueda',
'analysed-keywords' => 'Analysed Keywords'
'analysed-keywords' => 'Analysed Keywords',
'image-search-option' => 'Image Search Option'
],
'reviews' => [

View File

@ -72,7 +72,8 @@ return [
'page-title' => 'فروشگاه - جستجو',
'found-results' => 'نتایج جستجو یافت شد',
'found-result' => 'نتیجه جستجو یافت شد',
'analysed-keywords' => 'Analysed Keywords'
'analysed-keywords' => 'Analysed Keywords',
'image-search-option' => 'Image Search Option'
],
'reviews' => [

View File

@ -72,7 +72,8 @@ return [
'page-title' => config('app.name') . ' - Cerca',
'found-results' => 'Risultati trovati',
'found-result' => 'Risultato trovato',
'analysed-keywords' => 'Analysed Keywords'
'analysed-keywords' => 'Analysed Keywords',
'image-search-option' => 'Image Search Option'
],
'reviews' => [

View File

@ -69,7 +69,8 @@ return [
'page-title' => '検索',
'found-results' => '検索結果',
'found-result' => '検索結果',
'analysed-keywords' => 'Analysed Keywords'
'analysed-keywords' => 'Analysed Keywords',
'image-search-option' => 'Image Search Option'
],
'reviews' => [

View File

@ -71,7 +71,8 @@ return [
'page-title' => config('app.name') . ' - Search',
'found-results' => 'Search Results Found',
'found-result' => 'Search Result Found',
'analysed-keywords' => 'Analysed Keywords'
'analysed-keywords' => 'Analysed Keywords',
'image-search-option' => 'Image Search Option'
],
'reviews' => [

View File

@ -72,7 +72,8 @@ return [
'page-title' => config('app.name') . ' - Szukaj',
'found-results' => 'Dostępne wyniki wyszukiwania',
'found-result' => 'Dostępny wynik wyszukiwania',
'analysed-keywords' => 'Analysed Keywords'
'analysed-keywords' => 'Analysed Keywords',
'image-search-option' => 'Image Search Option'
],
'reviews' => [

View File

@ -72,7 +72,8 @@ return [
'page-title' => 'Buscar',
'found-results' => 'Resultados da pesquisa encontrados',
'found-result' => 'Resultado da pesquisa encontrado',
'analysed-keywords' => 'Analysed Keywords'
'analysed-keywords' => 'Analysed Keywords',
'image-search-option' => 'Image Search Option'
],
'reviews' => [

View File

@ -69,7 +69,8 @@ return [
'no-results' => 'Sonuç Bulunamadı',
'page-title' => config('app.name') . ' - Arama',
'found-results' => 'Arama Sonuçları',
'found-result' => 'Arama Sonuçları'
'found-result' => 'Arama Sonuçları',
'image-search-option' => 'Image Search Option'
],
'reviews' => [

View File

@ -33,7 +33,7 @@
<div class="item mt-5">
<div class="item-image" style="margin-right: 15px;">
<a href="{{ route('shop.productOrCategory.index', $url_key) }}"><img src="{{ $productBaseImage['medium_image_url'] }}" /></a>
<a href="{{ route('shop.productOrCategory.index', $url_key) }}"><img src="{{ $productBaseImage['medium_image_url'] }}" alt="" /></a>
</div>
<div class="item-details">

View File

@ -41,7 +41,7 @@
@php
$images = $item->product->getTypeInstance()->getBaseImage($item);
@endphp
<img src="{{ $images['small_image_url'] }}" />
<img src="{{ $images['small_image_url'] }}" alt=""/>
</div>
<div class="item-details">

View File

@ -78,7 +78,7 @@
<div class="item mb-5" style="margin-bottom: 5px;">
<div class="item-image">
<img src="{{ $productBaseImage['medium_image_url'] }}" />
<img src="{{ $productBaseImage['medium_image_url'] }}" alt=""/>
</div>
<div class="item-details">

View File

@ -111,7 +111,7 @@
</div>
@if (core()->getConfigData('sales.orderSettings.invoice_slip_design.logo'))
<div class="image">
<img class="logo" src="{{ Storage::url(core()->getConfigData('sales.orderSettings.invoice_slip_design.logo')) }}"/>
<img class="logo" src="{{ Storage::url(core()->getConfigData('sales.orderSettings.invoice_slip_design.logo')) }}" alt=""/>
</div>
@endif
<div class="merchant-details">

View File

@ -36,7 +36,7 @@
<div class="media-info">
<?php $image = $productImageHelper->getProductBaseImage($review->product); ?>
<a href="{{ route('shop.productOrCategory.index', $review->product->url_key) }}" title="{{ $review->product->name }}">
<img class="media" src="{{ $image['small_image_url'] }}"/>
<img class="media" src="{{ $image['small_image_url'] }}" alt=""/>
</a>
<div class="info">

View File

@ -22,7 +22,7 @@
<div class="account-item-card mt-15 mb-15">
<div class="media-info">
<?php $image = $productImageHelper->getGalleryImages($review->product); ?>
<img class="media" src="{{ $image[0]['small_image_url'] }}" />
<img class="media" src="{{ $image[0]['small_image_url'] }}" alt="" />
<div class="info mt-20">
<div class="product-name">{{$review->product->name}}</div>

View File

@ -38,7 +38,7 @@
$image = $item->product->getTypeInstance()->getBaseImage($item);
@endphp
<img class="media" src="{{ $image['small_image_url'] }}" />
<img class="media" src="{{ $image['small_image_url'] }}" alt="" />
<div class="info">
<div class="product-name">

View File

@ -1,5 +1,5 @@
@if ($logo = core()->getCurrentChannel()->logo_url)
<img src="{{ $logo }}" alt="{{ config('app.name') }}" style="height: 40px; width: 110px;"/>
@else
<img src="{{ bagisto_asset('images/logo.svg') }}">
<img src="{{ bagisto_asset('images/logo.svg') }}" alt="">
@endif

View File

@ -58,7 +58,7 @@
<img
class="image-wrapper"
:src="product['{{ $attribute['code'] }}']"
:onerror="`this.src='${baseUrl}/vendor/webkul/ui/assets/images/product/large-product-placeholder.png'`" />
:onerror="`this.src='${baseUrl}/vendor/webkul/ui/assets/images/product/large-product-placeholder.png'`" alt="" />
</a>
@break
@ -112,7 +112,7 @@
<img
class="image-wrapper"
:src="'storage/' + product.product['{{ $attribute['code'] }}']"
:onerror="`this.src='${baseUrl}/vendor/webkul/ui/assets/images/product/large-product-placeholder.png'`" />
:onerror="`this.src='${baseUrl}/vendor/webkul/ui/assets/images/product/large-product-placeholder.png'`" alt="" />
</a>
@break;
@default

View File

@ -1,10 +1,10 @@
@if (app('Webkul\Product\Repositories\ProductRepository')->getFeaturedProducts())
@if (count(app('Webkul\Product\Repositories\ProductRepository')->getFeaturedProducts()))
<section class="featured-products">
<div class="featured-heading">
{{ __('shop::app.home.featured-products') }}<br/>
<span class="featured-seperator" style="color:lightgrey;">_____</span>
<span class="featured-seperator" style="color: #d7dfe2;">_____</span>
</div>
<div class="featured-grid product-grid-4">

View File

@ -1,10 +1,10 @@
@if (app('Webkul\Product\Repositories\ProductRepository')->getNewProducts())
@if (count(app('Webkul\Product\Repositories\ProductRepository')->getNewProducts()))
<section class="featured-products">
<div class="featured-heading">
{{ __('shop::app.home.new-products') }}<br/>
<span class="featured-seperator" style="color:lightgrey;">_____</span>
<span class="featured-seperator" style="color: #d7dfe2;">_____</span>
</div>
<div class="product-grid-4">

View File

@ -1,14 +1,14 @@
<section class="news-update">
<div class="news-update-grid">
<div class="block1">
<img src="vendor/webkul/shop/assets/images/1.png" />
<img src="vendor/webkul/shop/assets/images/1.png" alt="" />
</div>
<div class="block2">
<div class="sub-block1">
<img src="vendor/webkul/shop/assets/images/2.png" />
<img src="vendor/webkul/shop/assets/images/2.png" alt="" />
</div>
<div class="sub-block2">
<img src="vendor/webkul/shop/assets/images/3.png" />
<img src="vendor/webkul/shop/assets/images/3.png" alt="" />
</div>
</div>
</div>

View File

@ -1,3 +1,5 @@
<section class="slider-block">
<image-slider :slides='@json($sliderData)' public_path="{{ url()->to('/') }}"></image-slider>
</section>
@if (count($sliderData))
<section class="slider-block" style="height: 500px">
<image-slider :slides='@json($sliderData)' public_path="{{ url()->to('/') }}"></image-slider>
</section>
@endif

View File

@ -29,11 +29,11 @@
<div class="list-container">
@if(core()->getConfigData('customer.settings.newsletter.subscription'))
<span class="list-heading">{{ __('shop::app.footer.subscribe-newsletter') }}</span>
<label class="list-heading" for="subscribe-field">{{ __('shop::app.footer.subscribe-newsletter') }}</label>
<div class="form-container">
<form action="{{ route('shop.subscribe') }}">
<div class="control-group" :class="[errors.has('subscriber_email') ? 'has-error' : '']">
<input type="email" class="control subscribe-field" name="subscriber_email" placeholder="Email Address" required><br/>
<input type="email" id="subscribe-field" class="control subscribe-field" name="subscriber_email" placeholder="Email Address" required><br/>
<button class="btn btn-md btn-primary">{{ __('shop::app.subscription.subscribe') }}</button>
</div>
@ -49,10 +49,10 @@
}
?>
<span class="list-heading">{{ __('shop::app.footer.locale') }}</span>
<label class="list-heading" for="locale-switcher">{{ __('shop::app.footer.locale') }}</label>
<div class="form-container">
<div class="control-group">
<select class="control locale-switcher" onchange="window.location.href = this.value" @if (count(core()->getCurrentChannel()->locales) == 1) disabled="disabled" @endif>
<select class="control locale-switcher" id="locale-switcher" onchange="window.location.href = this.value" @if (count(core()->getCurrentChannel()->locales) == 1) disabled="disabled" @endif>
@foreach (core()->getCurrentChannel()->locales as $locale)
@if (isset($serachQuery))
@ -67,10 +67,10 @@
</div>
<div class="currency">
<span class="list-heading">{{ __('shop::app.footer.currency') }}</span>
<label class="list-heading" for="currency-switcher">{{ __('shop::app.footer.currency') }}</label>
<div class="form-container">
<div class="control-group">
<select class="control locale-switcher" onchange="window.location.href = this.value">
<select class="control locale-switcher" id="currency-switcher" onchange="window.location.href = this.value">
@foreach (core()->getCurrentChannel()->currencies as $currency)
@if (isset($serachQuery))

View File

@ -1,5 +1,6 @@
<?php
$term = request()->input('term');
$image_search = request()->input('image-search');
if (! is_null($term)) {
$serachQuery = 'term='.request()->input('term');
@ -11,11 +12,11 @@
<div class="left-content">
<ul class="logo-container">
<li>
<a href="{{ route('shop.home.index') }}">
<a href="{{ route('shop.home.index') }}" aria-label="Logo">
@if ($logo = core()->getCurrentChannel()->logo_url)
<img class="logo" src="{{ $logo }}" />
<img class="logo" src="{{ $logo }}" alt="" />
@else
<img class="logo" src="{{ bagisto_asset('images/logo.svg') }}" />
<img class="logo" src="{{ bagisto_asset('images/logo.svg') }}" alt="" />
@endif
</a>
</li>
@ -24,12 +25,14 @@
<ul class="search-container">
<li class="search-group">
<form role="search" action="{{ route('shop.search.index') }}" method="GET" style="display: inherit;">
<label for="search-bar" style="position: absolute; z-index: -1;">Search</label>
<input
required
name="term"
type="search"
value="{{ $term }}"
value="{{ ! $image_search ? $term : '' }}"
class="search-field"
id="search-bar"
placeholder="{{ __('shop::app.header.search-text') }}"
>
@ -37,7 +40,7 @@
<div class="search-icon-wrapper">
<button class="" class="background: none;">
<button class="" class="background: none;" aria-label="Search">
<i class="icon icon-search"></i>
</button>
</div>
@ -217,17 +220,17 @@
</div>
@push('scripts')
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs"></script>
<script src="https://cdn.jsdelivr.net/npm/@tensorflow-models/mobilenet"></script>
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs" defer></script>
<script src="https://cdn.jsdelivr.net/npm/@tensorflow-models/mobilenet" defer></script>
<script type="text/x-template" id="image-search-component-template">
<div>
<label class="image-search-container" for="image-search-container">
<div v-if="image_search_status">
<label class="image-search-container" :for="'image-search-container-' + _uid">
<i class="icon camera-icon"></i>
<input type="file" id="image-search-container" ref="image_search_input" v-on:change="uploadImage()"/>
<input type="file" :id="'image-search-container-' + _uid" ref="image_search_input" v-on:change="uploadImage()"/>
<img id="uploaded-image-url" :src="uploaded_image_url"/>
<img :id="'uploaded-image-url-' + + _uid" :src="uploaded_image_url" alt=""/>
</label>
</div>
</script>
@ -240,7 +243,8 @@
data: function() {
return {
uploaded_image_url: ''
uploaded_image_url: '',
image_search_status: "{{core()->getConfigData('general.content.shop.image_search') == '1' ? true : false}}"
}
},
@ -271,7 +275,7 @@
net = await mobilenet.load();
const imgElement = document.getElementById('uploaded-image-url');
const imgElement = document.getElementById('uploaded-image-url-' + + self._uid);
try {
const result = await net.classify(imgElement);

View File

@ -5,8 +5,9 @@
$categories = [];
foreach (app('Webkul\Category\Repositories\CategoryRepository')->getVisibleCategoryTree(core()->getCurrentChannel()->root_category_id) as $category) {
if ($category->slug)
if ($category->slug) {
array_push($categories, $category);
}
}
?>

View File

@ -10,9 +10,9 @@
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="csrf-token" content="{{ csrf_token() }}">
<meta http-equiv="content-language" content="{{ app()->getLocale() }}">
<link rel="stylesheet" href="{{ asset('vendor/webkul/ui/assets/css/ui.css') }}">
<link rel="stylesheet" href="{{ bagisto_asset('css/shop.css') }}">
<link rel="stylesheet" href="{{ asset('vendor/webkul/ui/assets/css/ui.css') }}">
@if ($favicon = core()->getCurrentChannel()->favicon_url)
<link rel="icon" sizes="16x16" href="{{ $favicon }}" />
@ -56,7 +56,7 @@
@yield('slider')
<div class="content-container">
<main class="content-container">
{!! view_render_event('bagisto.shop.layout.content.before') !!}
@ -64,7 +64,7 @@
{!! view_render_event('bagisto.shop.layout.content.after') !!}
</div>
</main>
</div>

View File

@ -8,7 +8,7 @@
title="{{ __('shop::app.customer.compare.add-tooltip') }}"
@click="addProductToCompare"
style="cursor: pointer">
<img src="{{ asset('themes/default/assets/images/compare_arrows.png') }}" />
<img src="{{ asset('themes/default/assets/images/compare_arrows.png') }}" alt="" />
</a>
</script>

View File

@ -31,7 +31,7 @@
<div class="category-block" @if ($category->display_mode == 'description_only') style="width: 100%" @endif>
<div class="hero-image mb-35">
@if (!is_null($category->image))
<img class="logo" src="{{ $category->image_url }}" />
<img class="logo" src="{{ $category->image_url }}" alt="" />
@endif
</div>

View File

@ -14,7 +14,7 @@
<div class="product-image">
<a href="{{ route('shop.productOrCategory.index', $product->url_key) }}" title="{{ $product->name }}">
<img src="{{ $productBaseImage['medium_image_url'] }}" onerror="this.src='{{ asset('vendor/webkul/ui/assets/images/product/meduim-product-placeholder.png') }}'"/>
<img src="{{ $productBaseImage['medium_image_url'] }}" onerror="this.src='{{ asset('vendor/webkul/ui/assets/images/product/meduim-product-placeholder.png') }}'" alt="" height="500"/>
</a>
</div>

View File

@ -11,7 +11,7 @@
if (isset($category)) {
$products = $productRepository->getAll($category->id);
$filterAttributes = $productFlatRepository->getFilterableAttributes($category, $products);
$filterAttributes = $productFlatRepository->getProductsRelatedFilterableAttributes($category);
$maxPrice = core()->convertPrice($productFlatRepository->getCategoryProductMaximumPrice($category));
}

View File

@ -23,7 +23,7 @@
<i class="icon grid-view-icon"></i>
</span>
@else
<a href="{{ $toolbarHelper->getModeUrl('grid') }}" class="grid-view">
<a href="{{ $toolbarHelper->getModeUrl('grid') }}" class="grid-view" aria-label="Grid">
<i class="icon grid-view-icon"></i>
</a>
@endif
@ -33,16 +33,16 @@
<i class="icon list-view-icon"></i>
</span>
@else
<a href="{{ $toolbarHelper->getModeUrl('list') }}" class="list-view">
<a href="{{ $toolbarHelper->getModeUrl('list') }}" class="list-view" aria-label="list">
<i class="icon list-view-icon"></i>
</a>
@endif
</div>
<div class="sorter">
<label>{{ __('shop::app.products.sort-by') }}</label>
<label for="sort-by-toolbar">{{ __('shop::app.products.sort-by') }}</label>
<select onchange="window.location.href = this.value">
<select onchange="window.location.href = this.value" id="sort-by-toolbar">
@foreach ($toolbarHelper->getAvailableOrders() as $key => $order)
@ -56,9 +56,9 @@
</div>
<div class="limiter">
<label>{{ __('shop::app.products.show') }}</label>
<label for="show-toolbar">{{ __('shop::app.products.show') }}</label>
<select onchange="window.location.href = this.value">
<select onchange="window.location.href = this.value" id="show-toolbar">
@foreach ($toolbarHelper->getAvailableLimits() as $limit)

View File

@ -16,7 +16,7 @@
<div class="product-image">
<a href="{{ route('shop.productOrCategory.index', $product->url_key) }}" title="{{ $product->name }}">
<img src="{{ $productBaseImage['medium_image_url'] }}" />
<img src="{{ $productBaseImage['medium_image_url'] }}" alt="" />
</a>
</div>

View File

@ -18,7 +18,7 @@
<div class="product-info">
<div class="product-image">
<a href="{{ route('shop.productOrCategory.index', $product->url_key) }}" title="{{ $product->name }}">
<img src="{{ $productBaseImage['medium_image_url'] }}" />
<img src="{{ $productBaseImage['medium_image_url'] }}" alt="" />
</a>
</div>

View File

@ -11,7 +11,7 @@
@if (core()->getConfigData('catalog.rich_snippets.products.enable'))
<script type="application/ld+json">
{!! app('Webkul\Product\Helpers\SEO')->getProductJsonLd($product) !!}
{{ app('Webkul\Product\Helpers\SEO')->getProductJsonLd($product) }}
</script>
@endif
@ -21,7 +21,7 @@
<meta name="twitter:title" content="{{ $product->name }}" />
<meta name="twitter:description" content="{{ $product->description }}" />
<meta name="twitter:description" content="{!! $product->description !!}" />
<meta name="twitter:image:alt" content="" />
@ -33,7 +33,7 @@
<meta property="og:image" content="{{ $productBaseImage['medium_image_url'] }}" />
<meta property="og:description" content="{{ $product->description }}" />
<meta property="og:description" content="{!! $product->description !!}" />
<meta property="og:url" content="{{ route('shop.productOrCategory.index', $product->url_key) }}" />
@stop
@ -287,4 +287,4 @@
}
};
</script>
@endpush
@endpush

View File

@ -28,7 +28,7 @@
@elseif ($attribute['type'] == 'image' && $attribute['value'])
<td>
<a href="{{ route('shop.product.file.download', [$product->product_id, $attribute['id']])}}">
<img src="{{ Storage::url($attribute['value']) }}" style="height: 20px; width: 20px;"/>
<img src="{{ Storage::url($attribute['value']) }}" style="height: 20px; width: 20px;" alt=""/>
</a>
</td>
@else

View File

@ -50,7 +50,7 @@
<span v-if="attribute.swatch_type == 'color'" :style="{ background: option.swatch_value }"></span>
<img v-if="attribute.swatch_type == 'image'" :src="option.swatch_value" />
<img v-if="attribute.swatch_type == 'image'" :src="option.swatch_value" alt="" />
<span v-if="attribute.swatch_type == 'text'">
@{{ option.label }}

View File

@ -30,7 +30,7 @@
</li>
<li class="thumb-frame" v-for='(thumb, index) in thumbs' @mouseover="changeImage(thumb)" :class="[thumb.large_image_url == currentLargeImageUrl ? 'active' : '']" id="thumb-frame">
<img :src="thumb.small_image_url"/>
<img :src="thumb.small_image_url" alt=""/>
</li>
<li class="gallery-control bottom" @click="moveThumbs('bottom')" v-if="(thumbs.length > 4) && this.is_move.down">
@ -40,7 +40,7 @@
</ul>
<div class="product-hero-image" id="product-hero-image">
<img :src="currentLargeImageUrl" id="pro-img" :data-image="currentOriginalImageUrl"/>
<img :src="currentLargeImageUrl" id="pro-img" :data-image="currentOriginalImageUrl" alt=""/>
@auth('customer')
<a @if ($wishListHelper->getWishlistProduct($product)) class="add-to-wishlist already" @else class="add-to-wishlist" @endif href="{{ route('customer.wishlist.add', $product->product_id) }}">
@ -163,7 +163,7 @@
var wishlist = " <?php echo $wishListHelper->getWishlistProduct($product); ?> ";
$(document).mousemove(function(event) {
if ($('.add-to-wishlist').length && wishlist != 1) {
if ($('.add-to-wishlist').length || wishlist != 1) {
if (event.pageX > $('.add-to-wishlist').offset().left && event.pageX < $('.add-to-wishlist').offset().left+32 && event.pageY > $('.add-to-wishlist').offset().top && event.pageY < $('.add-to-wishlist').offset().top+32) {
$(".zoomContainer").addClass("show-wishlist");

View File

@ -50,7 +50,7 @@
<script type="text/x-template" id="image-search-result-component-template">
<div class="image-search-result">
<div class="searched-image">
<img :src="searched_image_url"/>
<img :src="searched_image_url" alt=""/>
</div>
<div class="searched-terms">

Binary file not shown.

After

Width:  |  Height:  |  Size: 936 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 694 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 338 B

View File

@ -1,6 +1,7 @@
@php
$locale = request()->get('locale') ?: app()->getLocale();
$channel = request()->get('channel') ?: (core()->getCurrentChannelCode() ?: core()->getDefaultChannelCode());
$customer_group = request()->get('customer_group');
@endphp
<div class="table">
@ -27,7 +28,7 @@
@foreach ($results['extraFilters']['channels'] as $channelModel)
<option
value="{{ $channelModel->id }}"
{{ (isset($channel) && ($channelModel->code) == $channel) ? 'selected' : '' }}>
{{ (isset($channel) && ($channelModel->id) == $channel) ? 'selected' : '' }}>
{{ $channelModel->name }}
</option>
@endforeach

View File

@ -1 +1,2 @@
/node_modules/*
/node_modules/*
/resources/lang/vendor/velocity/*

View File

@ -22,6 +22,7 @@
"accounting": "^0.4.1",
"bootstrap-sass": "^3.4.1",
"font-awesome": "^4.7.0",
"lazysizes": "^5.2.2",
"material-icons": "^0.3.1",
"vee-validate": "^2.2.15",
"vue-slider-component": "^3.1.0",

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

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