Added Repository Pattern to User

This commit is contained in:
jitendra 2018-07-31 13:20:54 +05:30
parent e65aab372d
commit f236da61ab
38 changed files with 32562 additions and 133 deletions

View File

@ -34,7 +34,8 @@
"webkul/laravel-customer": "self.version", "webkul/laravel-customer": "self.version",
"webkul/laravel-category": "self.version", "webkul/laravel-category": "self.version",
"webkul/laravel-channel": "self.version", "webkul/laravel-channel": "self.version",
"webkul/laravel-product": "self.version" "webkul/laravel-product": "self.version",
"webkul/laravel-shop": "self.version"
}, },
"autoload": { "autoload": {
"classmap": [ "classmap": [

View File

@ -181,7 +181,9 @@ return [
Webkul\Customer\Providers\CustomerServiceProvider::class, Webkul\Customer\Providers\CustomerServiceProvider::class,
Webkul\Channel\Providers\ChannelServiceProvider::class, Webkul\Channel\Providers\ChannelServiceProvider::class,
Webkul\Inventory\Providers\InventoryServiceProvider::class, Webkul\Inventory\Providers\InventoryServiceProvider::class,
Webkul\Product\Providers\ProductServiceProvider::class Webkul\Product\Providers\ProductServiceProvider::class,
Webkul\Shop\Providers\ShopServiceProvider::class,
Webkul\Customer\Providers\CustomerServiceProvider::class
], ],
/* /*

View File

@ -53,6 +53,15 @@ Route::group(['middleware' => ['web']], function () {
'view' => 'admin::catalog.products.create' 'view' => 'admin::catalog.products.create'
])->name('admin.catalog.products.create'); ])->name('admin.catalog.products.create');
Route::post('/products/create', 'Webkul\Product\Http\Controllers\ProductController@store')->defaults('_config', [
'redirect' => 'admin.catalog.products.edit'
])->name('admin.catalog.products.store');
Route::get('/products/edit/{id}', 'Webkul\Product\Http\Controllers\ProductController@edit')->defaults('_config', [
'view' => 'admin::catalog.products.edit'
])->name('admin.catalog.products.edit');
// Catalog Category Routes // Catalog Category Routes
Route::get('/categories', 'Webkul\Category\Http\Controllers\CategoryController@index')->defaults('_config', [ Route::get('/categories', 'Webkul\Category\Http\Controllers\CategoryController@index')->defaults('_config', [
'view' => 'admin::catalog.categories.index' 'view' => 'admin::catalog.categories.index'

View File

@ -29,10 +29,6 @@ class AdminServiceProvider extends ServiceProvider
$this->composeView(); $this->composeView();
Blade::directive('continue', function () {
return "<?php continue; ?>";
});
$this->app->register(EventServiceProvider::class); $this->app->register(EventServiceProvider::class);
$this->app->register(ComposerServiceProvider::class); $this->app->register(ComposerServiceProvider::class);
} }
@ -74,13 +70,13 @@ class AdminServiceProvider extends ServiceProvider
* *
* @return void * @return void
*/ */
// public function register() public function register()
// { {
// $this->mergeConfigFrom( // $this->mergeConfigFrom(
// __DIR__ . '/../Config/auth.php', // __DIR__ . '/../Config/auth.php',
// 'auth' // 'auth'
// ); // );
// } }
/** /**
* Merge the given configuration with the existing configuration. * Merge the given configuration with the existing configuration.

View File

@ -4,25 +4,6 @@ window.VeeValidate = require("vee-validate");
Vue.use(VeeValidate); Vue.use(VeeValidate);
//register single file components here
// import VueFlatpickr from "vue-flatpickr";
// import "vue-flatpickr/theme/dark.css";
// Vue.use(VueFlatpickr);
Vue.component("datetime", require("./components/datetime"));
$(document).ready(function() {
const app = new Vue({
el: "#app",
mounted: function() {
this.addServerErrors();
this.addFlashMessages();
},
methods: {
onSubmit: function(e) {
this.$validator.validateAll().then(result => {
$(document).ready(function () { $(document).ready(function () {
Vue.config.ignoredElements = [ Vue.config.ignoredElements = [
'option-wrapper', 'option-wrapper',
@ -54,10 +35,6 @@ $(document).ready(function () {
addServerErrors () { addServerErrors () {
var scope = null; var scope = null;
for (var key in serverErrors) { for (var key in serverErrors) {
const field = this.$validator.fields.find({
name: key,
scope: scope
});
var inputName = key; var inputName = key;
if(key.indexOf('.') !== -1) { if(key.indexOf('.') !== -1) {
inputName = key.replace(".", "[") + ']'; inputName = key.replace(".", "[") + ']';

View File

@ -69,6 +69,15 @@ return [
'add-title' => 'Add Product', 'add-title' => 'Add Product',
'edit-title' => 'Edit Product', 'edit-title' => 'Edit Product',
'save-btn-title' => 'Save Product', 'save-btn-title' => 'Save Product',
'general' => 'General',
'product-type' => 'Product Type',
'simple' => 'Simple',
'configurable' => 'Configurable',
'familiy' => 'Attribute Family',
'sku' => 'SKU',
'configurable-attributes' => 'Configurable Attributes',
'attribute-header' => 'Attribute(s)',
'attribute-option-header' => 'Attribute Option(s)'
], ],
'attributes' => [ 'attributes' => [
'add-title' => 'Add Attribute', 'add-title' => 'Add Attribute',
@ -86,7 +95,7 @@ return [
'checkbox' => 'Checkbox', 'checkbox' => 'Checkbox',
'datetime' => 'Datetime', 'datetime' => 'Datetime',
'date' => 'Date', 'date' => 'Date',
'label' => 'label', 'label' => 'Label',
'admin' => 'Admin', 'admin' => 'Admin',
'options' => 'Options', 'options' => 'Options',
'position' => 'Position', 'position' => 'Position',

View File

@ -6,7 +6,7 @@
@section('content') @section('content')
<div class="content"> <div class="content">
<?php $locale = request()->get('channel_locale') ?: channel()->getDefaultChannelLocaleCode(); ?> <?php $locale = request()->get('locale') ?: app()->getLocale(); ?>
<form method="POST" action="" @submit.prevent="onSubmit"> <form method="POST" action="" @submit.prevent="onSubmit">
@ -16,17 +16,11 @@
<div class="control-group"> <div class="control-group">
<select class="control" id="locale-switcher" onChange="window.location.href = this.value"> <select class="control" id="locale-switcher" onChange="window.location.href = this.value">
@foreach(channel()->getChannelWithLocales() as $channel) @foreach(core()->allLocales() as $localeModel)
<optgroup label="{{ $channel->name }}">
@foreach($channel->locales as $channelLocale) <option value="{{ route('admin.catalog.categories.update', $category->id) . '?locale=' . $localeModel->code }}" {{ ($localeModel->code) == $locale ? 'selected' : '' }}>
<option value="{{ route('admin.catalog.categories.update', $category->id) . '?channel_locale=' . $channel->code . '-' . $channelLocale->code }}" {{ ($channel->code . '-' . $channelLocale->code) == $locale ? 'selected' : '' }}> {{ $localeModel->name }}
{{ $channelLocale->name }} </option>
</option>
@endforeach
</optgroup>
@endforeach @endforeach
</select> </select>

View File

@ -0,0 +1,137 @@
@extends('admin::layouts.content')
@section('css')
<style>
.table td .label {
margin-right: 10px;
}
.table td .label:last-child {
margin-right: 0;
}
.table td .label .icon {
vertical-align: middle;
cursor: pointer;
}
</style>
@stop
@section('content')
<div class="content">
<form method="POST" action="" @submit.prevent="onSubmit">
<div class="page-header">
<div class="page-title">
<h1>{{ __('admin::app.catalog.products.add-title') }}</h1>
</div>
<div class="page-action">
<button type="submit" class="btn btn-lg btn-primary">
{{ __('admin::app.catalog.products.save-btn-title') }}
</button>
</div>
</div>
<div class="page-content">
@csrf()
<?php $familyId = app('request')->input('family') ?>
<accordian :title="'{{ __('admin::app.catalog.products.general') }}'" :active="true">
<div slot="body">
<div class="control-group" :class="[errors.has('type') ? 'has-error' : '']">
<label for="type" class="required">{{ __('admin::app.catalog.products.product-type') }}</label>
<select class="control" v-validate="'required'" id="type" name="type" {{ $familyId ? 'disabled' : '' }}>
<option value="simple">{{ __('admin::app.catalog.products.simple') }}</option>
<option value="configurable" {{ $familyId ? 'selected' : '' }}>{{ __('admin::app.catalog.products.configurable') }}</option>
</select>
@if($familyId)
<input type="hidden" name="type" value="configurable"/>
@endif
<span class="control-error" v-if="errors.has('type')">@{{ errors.first('type') }}</span>
</div>
<div class="control-group" :class="[errors.has('attribute_family_id') ? 'has-error' : '']">
<label for="attribute_family_id" class="required">{{ __('admin::app.catalog.products.familiy') }}</label>
<select class="control" v-validate="'required'" id="attribute_family_id" name="attribute_family_id" {{ $familyId ? 'disabled' : '' }}>
<option value=""></option>
@foreach($families as $family)
<option value="{{ $family->id }}" {{ $familyId == $family->id ? 'selected' : '' }}>{{ $family->name }}</option>
@endforeach
</select>
@if($familyId)
<input type="hidden" name="attribute_family_id" value="{{ $familyId }}"/>
@endif
<span class="control-error" v-if="errors.has('attribute_family_id')">@{{ errors.first('attribute_family_id') }}</span>
</div>
@if($familyId)
<div class="control-group" :class="[errors.has('sku') ? 'has-error' : '']">
<label for="sku">{{ __('admin::app.catalog.products.sku') }}</label>
<input type="text" v-validate="'required'" class="control" id="sku" name="sku" value="{{ old('sku') }}"/>
<span class="control-error" v-if="errors.has('sku')">@{{ errors.first('sku') }}</span>
</div>
@endif
</div>
</accordian>
@if($familyId)
<accordian :title="'{{ __('admin::app.catalog.products.configurable-attributes') }}'" :active="true">
<div slot="body">
<div class="table">
<table>
<thead>
<tr>
<th>{{ __('admin::app.catalog.products.attribute-header') }}</th>
<th>{{ __('admin::app.catalog.products.attribute-option-header') }}</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach($configurableFamily->configurable_attributes as $attribute)
<tr>
<td>
{{ $attribute->name }}
</td>
<td>
@foreach($attribute->options as $option)
<span class="label">
<input type="hidden" name="super_attributes[{{$attribute->id}}][options][]" value="{{ $option->id }}"/>
{{ $option->label }}
<i class="icon cross-icon"></i>
</span>
@endforeach
</td>
<td class="actions">
<i class="icon trash-icon"></i>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
</accordian>
@endif
</div>
</form>
</div>
@stop
@section('javascript')
<script>
(function() {
})();
</script>
@stop

View File

@ -0,0 +1,27 @@
@extends('admin::layouts.content')
@section('content')
<div class="content">
<form method="POST" action="{{ route('admin.catalog.products.store') }}" @submit.prevent="onSubmit">
<div class="page-header">
<div class="page-title">
<h1>{{ __('admin::app.catalog.products.add-title') }}</h1>
</div>
<div class="page-action">
<button type="submit" class="btn btn-lg btn-primary">
{{ __('admin::app.catalog.products.save-btn-title') }}
</button>
</div>
</div>
<div class="page-content">
@csrf()
</div>
</form>
</div>
@stop

View File

@ -4,6 +4,7 @@ namespace Webkul\Attribute\Models;
use Webkul\Core\Eloquent\TranslatableModel; use Webkul\Core\Eloquent\TranslatableModel;
use Webkul\Attribute\Models\AttributeOption; use Webkul\Attribute\Models\AttributeOption;
use Webkul\Attribute\Models\AttributeGroup;
class Attribute extends TranslatableModel class Attribute extends TranslatableModel
{ {

View File

@ -3,7 +3,6 @@
namespace Webkul\Attribute\Models; namespace Webkul\Attribute\Models;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Webkul\Attribute\Models\Attribute;
use Webkul\Attribute\Models\AttributeGroup; use Webkul\Attribute\Models\AttributeGroup;
class AttributeFamily extends Model class AttributeFamily extends Model
@ -17,7 +16,19 @@ class AttributeFamily extends Model
*/ */
public function attributes() public function attributes()
{ {
return $this->hasManyThrough(Attribute::class, AttributeGroup::class); return Attribute::join('attribute_group_mappings', 'attributes.id', '=', 'attribute_group_mappings.attribute_id')
->join('attribute_groups', 'attribute_group_mappings.attribute_group_id', '=', 'attribute_groups.id')
->join('attribute_families', 'attribute_groups.attribute_family_id', '=', 'attribute_families.id')
->where('attribute_families.id', $this->id)
->select('attributes.*');
}
/**
* Get all of the attributes for the attribute groups.
*/
public function getAttributesAttribute()
{
return $this->attributes()->get();
} }
/** /**
@ -27,4 +38,12 @@ class AttributeFamily extends Model
{ {
return $this->hasMany(AttributeGroup::class)->orderBy('position'); return $this->hasMany(AttributeGroup::class)->orderBy('position');
} }
/**
* Get all of the attributes for the attribute groups.
*/
public function getConfigurableAttributesAttribute()
{
return $this->attributes()->where('attributes.is_configurable', 1)->where('attributes.type', 'select')->get();
}
} }

View File

@ -128,7 +128,7 @@ class AttributeFamilyRepository extends Repository
} }
if($attributeIds->count()) { if($attributeIds->count()) {
$attributeGroup->detach($attributeIds); $attributeGroup->attributes()->detach($attributeIds);
} }
} }
} }

View File

@ -106,7 +106,7 @@ class CategoryController extends Controller
*/ */
public function update(Request $request, $id) public function update(Request $request, $id)
{ {
$locale = request()->get('channel_locale') ?: channel()->getDefaultChannelLocaleCode(); $locale = request()->get('locale') ?: app()->getLocale();
$this->validate(request(), [ $this->validate(request(), [
$locale . '.slug' => ['required', new \Webkul\Core\Contracts\Validations\Slug, function ($attribute, $value, $fail) use ($id) { $locale . '.slug' => ['required', new \Webkul\Core\Contracts\Validations\Slug, function ($attribute, $value, $fail) use ($id) {
if (!$this->category->isSlugUnique($id, $value)) { if (!$this->category->isSlugUnique($id, $value)) {

View File

@ -12,12 +12,4 @@ class Category extends TranslatableModel
public $translatedAttributes = ['name', 'description', 'slug', 'meta_title', 'meta_description', 'meta_keywords']; public $translatedAttributes = ['name', 'description', 'slug', 'meta_title', 'meta_description', 'meta_keywords'];
protected $fillable = ['position', 'status', 'parent_id']; protected $fillable = ['position', 'status', 'parent_id'];
/**
* @return boolean
*/
protected function isChannelBased()
{
return true;
}
} }

View File

@ -44,14 +44,10 @@ class CategoryRepository extends Repository
if(isset($data['locale']) && $data['locale'] == 'all') { if(isset($data['locale']) && $data['locale'] == 'all') {
$model = app()->make($this->model()); $model = app()->make($this->model());
$channels = channel()->getChannelWithLocales(); foreach(core()->allLocales() as $locale) {
foreach ($model->translatedAttributes as $attribute) {
foreach($channels as $channel) { if(isset($data[$attribute])) {
foreach($channel->locales as $locale) { $data[$locale->code][$attribute] = $data[$attribute];
foreach ($model->translatedAttributes as $attribute) {
if(isset($data[$attribute])) {
$data[$channel->code . '.' . $locale->code][$attribute] = $data[$attribute];
}
} }
} }
} }

View File

@ -30,13 +30,9 @@ class ChannelRepository extends Repository
{ {
$channel = $this->model->create($data); $channel = $this->model->create($data);
foreach ($data['locales'] as $locale) { $channel->locales()->sync($data['locales']);
$channel->locales()->attach($locale);
}
foreach ($data['currencies'] as $currency) { $channel->currencies()->sync($data['currencies']);
$channel->currencies()->attach($currency);
}
return $channel; return $channel;
} }
@ -53,32 +49,9 @@ class ChannelRepository extends Repository
$channel->update($data); $channel->update($data);
$previousLocaleIds = $channel->locales()->pluck('id'); $channel->locales()->sync($data['locales']);
foreach ($data['locales'] as $locale) { $channel->currencies()->sync($data['currencies']);
if(is_numeric($index = $previousLocaleIds->search($locale))) {
$previousLocaleIds->forget($index);
} else {
$channel->locales()->attach($locale);
}
}
if($previousLocaleIds->count()) {
$channel->locales()->detach($previousLocaleIds);
}
$previousCurrencyIds = $channel->currencies()->pluck('id');
foreach ($data['currencies'] as $currency) {
if(is_numeric($index = $previousCurrencyIds->search($currency))) {
$previousCurrencyIds->forget($index);
} else {
$channel->currencies()->attach($currency);
}
}
if($previousCurrencyIds->count()) {
$channel->currencies()->detach($previousCurrencyIds);
}
return $channel; return $channel;
} }

View File

@ -4,7 +4,7 @@ namespace Webkul\Core\Http\Controllers;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Http\Response; use Illuminate\Http\Response;
use Webkul\Core\Models\Country; use Webkul\Core\Repositories\CountryRepository as Country;
/** /**
* Country controller * Country controller
@ -20,14 +20,24 @@ class CountryController extends Controller
* @var array * @var array
*/ */
protected $_config; protected $_config;
/**
* CountryRepository object
*
* @var array
*/
protected $country;
/** /**
* Create a new controller instance. * Create a new controller instance.
* *
* @param Webkul\Core\Repositories\CountryRepository $country
* @return void * @return void
*/ */
public function __construct() public function __construct(Country $country)
{ {
$this->country = $country;
$this->_config = request('_config'); $this->_config = request('_config');
} }
@ -64,7 +74,7 @@ class CountryController extends Controller
'name' => 'required' 'name' => 'required'
]); ]);
Country::create(request(['code','name'])); $this->country->create(request()->all());
session()->flash('success', 'Country created successfully.'); session()->flash('success', 'Country created successfully.');

View File

@ -31,7 +31,7 @@ class CurrencyController extends Controller
/** /**
* Create a new controller instance. * Create a new controller instance.
* *
* @param Webkul\Core\Repositories\CurrencyRepository $currency * @param Webkul\Core\Repositories\CurrencyRepository $currency
* @return void * @return void
*/ */
public function __construct(Currency $currency) public function __construct(Currency $currency)

View File

@ -4,7 +4,7 @@ namespace Webkul\Core\Http\Controllers;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Http\Response; use Illuminate\Http\Response;
use Webkul\Core\Models\Locale; use Webkul\Core\Repositories\LocaleRepository as Locale;
/** /**
* Locale controller * Locale controller
@ -20,14 +20,24 @@ class LocaleController extends Controller
* @var array * @var array
*/ */
protected $_config; protected $_config;
/**
* LocaleRepository object
*
* @var array
*/
protected $locale;
/** /**
* Create a new controller instance. * Create a new controller instance.
* *
* @param Webkul\Core\Repositories\LocaleRepository $locale
* @return void * @return void
*/ */
public function __construct() public function __construct(Locale $locale)
{ {
$this->locale = $locale;
$this->_config = request('_config'); $this->_config = request('_config');
} }
@ -64,7 +74,7 @@ class LocaleController extends Controller
'name' => 'required' 'name' => 'required'
]); ]);
Locale::create(request(['code','name'])); $this->locale->create(request()->all());
session()->flash('success', 'Locale created successfully.'); session()->flash('success', 'Locale created successfully.');

View File

@ -17,14 +17,23 @@ class CreateProductsTable extends Migration
$table->increments('id'); $table->increments('id');
$table->string('sku')->unique(); $table->string('sku')->unique();
$table->string('type'); $table->string('type');
$table->integer('parent_id')->unsigned()->nullable();
$table->timestamps(); $table->timestamps();
$table->integer('parent_id')->unsigned()->nullable();
$table->integer('attribute_family_id')->unsigned()->nullable();
$table->foreign('attribute_family_id')->references('id')->on('attribute_families')->onDelete('cascade');
}); });
Schema::table('products', function (Blueprint $table) { Schema::table('products', function (Blueprint $table) {
$table->foreign('parent_id')->references('id')->on('products')->onDelete('cascade'); $table->foreign('parent_id')->references('id')->on('products')->onDelete('cascade');
}); });
Schema::create('product_inventories', function (Blueprint $table) {
$table->integer('product_id')->unsigned();
$table->integer('inventory_source_id')->unsigned();
$table->foreign('product_id')->references('id')->on('products')->onDelete('cascade');
$table->foreign('inventory_source_id')->references('id')->on('inventory_sources')->onDelete('cascade');
});
Schema::create('product_categories', function (Blueprint $table) { Schema::create('product_categories', function (Blueprint $table) {
$table->integer('product_id')->unsigned(); $table->integer('product_id')->unsigned();
$table->integer('category_id')->unsigned(); $table->integer('category_id')->unsigned();
@ -39,6 +48,13 @@ class CreateProductsTable extends Migration
$table->foreign('child_id')->references('id')->on('products')->onDelete('cascade'); $table->foreign('child_id')->references('id')->on('products')->onDelete('cascade');
}); });
Schema::create('product_super_attributes', function (Blueprint $table) {
$table->integer('product_id')->unsigned();
$table->integer('attribute_id')->unsigned();
$table->foreign('product_id')->references('id')->on('products')->onDelete('cascade');
$table->foreign('attribute_id')->references('id')->on('attributes')->onDelete('cascade');
});
Schema::create('product_up_sells', function (Blueprint $table) { Schema::create('product_up_sells', function (Blueprint $table) {
$table->integer('parent_id')->unsigned(); $table->integer('parent_id')->unsigned();
$table->integer('child_id')->unsigned(); $table->integer('child_id')->unsigned();

View File

@ -15,6 +15,7 @@ class CreateProductAttributeValueTable extends Migration
{ {
Schema::create('product_attribute_value', function (Blueprint $table) { Schema::create('product_attribute_value', function (Blueprint $table) {
$table->increments('id'); $table->increments('id');
$table->string('locale')->nullable();
$table->text('text_value')->nullable(); $table->text('text_value')->nullable();
$table->boolean('boolean_value')->nullable(); $table->boolean('boolean_value')->nullable();
$table->integer('integer_value')->nullable(); $table->integer('integer_value')->nullable();
@ -26,6 +27,7 @@ class CreateProductAttributeValueTable extends Migration
$table->integer('attribute_id')->unsigned(); $table->integer('attribute_id')->unsigned();
$table->foreign('product_id')->references('id')->on('products')->onDelete('cascade'); $table->foreign('product_id')->references('id')->on('products')->onDelete('cascade');
$table->foreign('attribute_id')->references('id')->on('attributes')->onDelete('cascade'); $table->foreign('attribute_id')->references('id')->on('attributes')->onDelete('cascade');
$table->unique(['locale', 'attribute_id', 'product_id']);
}); });
} }

View File

@ -0,0 +1,34 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateProductImagesTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('product_images', function (Blueprint $table) {
$table->increments('id');
$table->string('type');
$table->string('path');
$table->integer('product_id')->unsigned()->nullable();
$table->foreign('product_id')->references('id')->on('products')->onDelete('cascade');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('product_images');
}
}

View File

@ -5,6 +5,7 @@ namespace Webkul\Product\Http\Controllers;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Http\Response; use Illuminate\Http\Response;
use Webkul\Product\Repositories\ProductRepository as Product; use Webkul\Product\Repositories\ProductRepository as Product;
use Webkul\Attribute\Repositories\AttributeFamilyRepository as AttributeFamily;
/** /**
* Product controller * Product controller
@ -21,6 +22,13 @@ class ProductController extends Controller
*/ */
protected $_config; protected $_config;
/**
* AttributeFamilyRepository object
*
* @var array
*/
protected $attributeFamily;
/** /**
* ProductRepository object * ProductRepository object
* *
@ -31,11 +39,14 @@ class ProductController extends Controller
/** /**
* Create a new controller instance. * Create a new controller instance.
* *
* @param Webkul\Product\Repositories\ProductRepository $product * @param Webkul\Attribute\Repositories\AttributeFamilyRepository $attributeFamily
* @param Webkul\Product\Repositories\ProductRepository $product
* @return void * @return void
*/ */
public function __construct(Product $product) public function __construct(AttributeFamily $attributeFamily, Product $product)
{ {
$this->attributeFamily = $attributeFamily;
$this->product = $product; $this->product = $product;
$this->_config = request('_config'); $this->_config = request('_config');
@ -58,7 +69,13 @@ class ProductController extends Controller
*/ */
public function create() public function create()
{ {
return view($this->_config['view']); $families = $this->attributeFamily->all();
if($familyId = request()->get('family')) {
$configurableFamily = $this->attributeFamily->findOrFail($familyId);
}
return view($this->_config['view'], compact('families', 'configurableFamily'));
} }
/** /**
@ -68,15 +85,22 @@ class ProductController extends Controller
*/ */
public function store() public function store()
{ {
if(!request()->get('family') && request()->input('type') == 'configurable') {
return redirect(url()->current() . '?family=' . request()->input('attribute_family_id'));
}
$this->validate(request(), [ $this->validate(request(), [
'name' => 'required' 'type' => 'required',
'attribute_family_id' => 'required',
'sku' => ['required', 'unique:products,sku', new \Webkul\Core\Contracts\Validations\Slug],
'super_attributes' => 'required|array|min:1'
]); ]);
$this->product->create(request()->all()); $product = $this->product->create(request()->all());
session()->flash('success', 'Product created successfully.'); session()->flash('success', 'Product created successfully.');
return redirect()->route($this->_config['redirect']); return redirect()->route($this->_config['redirect'], ['id' => $product->id]);
} }
/** /**

View File

@ -3,11 +3,13 @@
namespace Webkul\Product\Models; namespace Webkul\Product\Models;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Webkul\Attribute\Models\Attribute;
use Webkul\Category\Models\Category; use Webkul\Category\Models\Category;
use Webkul\Inventory\Models\InventorySource;
class Product extends Model class Product extends Model
{ {
protected $guarded = ['_token']; protected $fillable = ['type', 'attribute_family_id', 'sku'];
/** /**
* The categories that belong to the product. * The categories that belong to the product.
@ -16,4 +18,44 @@ class Product extends Model
{ {
return $this->belongsToMany(Category::class, 'product_categories'); return $this->belongsToMany(Category::class, 'product_categories');
} }
/**
* The inventories that belong to the product.
*/
public function inventories()
{
return $this->belongsToMany(InventorySource::class, 'product_inventories');
}
/**
* The super attributes that belong to the product.
*/
public function super_attributes()
{
return $this->belongsToMany(Attribute::class, 'product_super_attributes');
}
/**
* The related products that belong to the product.
*/
public function related_products()
{
return $this->belongsToMany(self::class, 'product_relations');
}
/**
* The up sells that belong to the product.
*/
public function up_sells()
{
return $this->belongsToMany(self::class, 'product_up_sells');
}
/**
* The cross sells that belong to the product.
*/
public function cross_sells()
{
return $this->belongsToMany(self::class, 'product_cross_sells');
}
} }

View File

@ -0,0 +1,26 @@
<?php
namespace Webkul\Product\Models;
use Illuminate\Database\Eloquent\Model;
use Webkul\Attribute\Models\Attribute;
use Webkul\Product\Models\Product;
class ProductAttributeValue extends Model
{
/**
* Get the attribue that owns the attribute value.
*/
public function attribue()
{
return $this->belongsTo(Attribue::class);
}
/**
* Get the product that owns the attribute value.
*/
public function product()
{
return $this->belongsTo(Product::class);
}
}

View File

@ -0,0 +1,39 @@
<?php
namespace Webkul\Product\Repositories;
use Webkul\Core\Eloquent\Repository;
/**
* Product Attribute Value Reposotory
*
* @author Jitendra Singh <jitendra@webkul.com>
* @copyright 2018 Webkul Software Pvt Ltd (http://www.webkul.com)
*/
class ProductAttributeValueRepository extends Repository
{
/**
* Specify Model class name
*
* @return mixed
*/
function model()
{
return 'Webkul\Product\Models\ProductAttributeValue';
}
/**
* @param array $data
* @return mixed
*/
public function create(array $data)
{
$product = $this->model->create($data);
foreach ($data['super_attributes'] as $attributeId => $attribute) {
$product->super_attributes()->attach($attributeId);
}
return $product;
}
}

View File

@ -21,4 +21,19 @@ class ProductRepository extends Repository
{ {
return 'Webkul\Product\Models\Product'; return 'Webkul\Product\Models\Product';
} }
/**
* @param array $data
* @return mixed
*/
public function create(array $data)
{
$product = $this->model->create($data);
foreach ($data['super_attributes'] as $attributeId => $attribute) {
$product->super_attributes()->attach($attributeId);
}
return $product;
}
} }

View File

@ -225,6 +225,7 @@ h2 {
.icon { .icon {
cursor: pointer; cursor: pointer;
vertical-align: middle;
} }
} }
} }
@ -918,3 +919,28 @@ h2 {
} }
} }
} }
.label {
background: #E7E7E7;
border-radius: 2px;
padding: 8px;
color: #000311;
display: inline-block;
&.label-sm {
padding: 5px;
}
&.label-md {
padding: 8px;
}
&.label-lg {
padding: 11px;
}
&.label-xl {
padding: 14px;
}
}

View File

@ -70,8 +70,8 @@
.cross-icon { .cross-icon {
background-image: url("../images/Icon-Crossed.svg"); background-image: url("../images/Icon-Crossed.svg");
width: 24px; width: 18px;
height: 24px; height: 18px;
} }
.trash-icon { .trash-icon {

View File

@ -269,6 +269,14 @@
</div> </div>
</div> </div>
<label class="styleguide-label">Labels</label>
<div class="styleguide-wrapper">
<span class="label label-sm">Label Small</span>
<span class="label label-md">Label Medium</span>
<span class="label label-lg">Label Large</span>
<span class="label label-xl">Label Extra Large</span>
</div>
<label class="styleguide-label">Table</label> <label class="styleguide-label">Table</label>
<div class="styleguide-wrapper"> <div class="styleguide-wrapper">
<div class="table"> <div class="table">

View File

@ -4,7 +4,7 @@ namespace Webkul\User\Http\Controllers;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Http\Response; use Illuminate\Http\Response;
use Webkul\User\Models\Role; use Webkul\User\Repositories\RoleRepository as Role;
/** /**
* Admin user role controller * Admin user role controller
@ -20,14 +20,24 @@ class RoleController extends Controller
* @var array * @var array
*/ */
protected $_config; protected $_config;
/**
* RoleRepository object
*
* @var array
*/
protected $role;
/** /**
* Create a new controller instance. * Create a new controller instance.
* *
* @param Webkul\User\Repositories\RoleRepository $role
* @return void * @return void
*/ */
public function __construct() public function __construct(Role $role)
{ {
$this->role = $role;
$this->_config = request('_config'); $this->_config = request('_config');
} }
@ -64,7 +74,7 @@ class RoleController extends Controller
'permission_type' => 'required', 'permission_type' => 'required',
]); ]);
Role::create(request()->all()); $this->role->create(request()->all());
session()->flash('success', 'Role created successfully.'); session()->flash('success', 'Role created successfully.');
@ -79,7 +89,7 @@ class RoleController extends Controller
*/ */
public function edit($id) public function edit($id)
{ {
$role = Role::findOrFail($id); $role = $this->role->findOrFail($id);
return view($this->_config['view'], compact('role')); return view($this->_config['view'], compact('role'));
} }
@ -98,9 +108,7 @@ class RoleController extends Controller
'permission_type' => 'required', 'permission_type' => 'required',
]); ]);
$role = Role::findOrFail($id); $this->role->update(request()->all(), $id);
$role->update(request()->all());
session()->flash('success', 'Role updated successfully.'); session()->flash('success', 'Role updated successfully.');

View File

@ -4,8 +4,8 @@ namespace Webkul\User\Http\Controllers;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Http\Response; use Illuminate\Http\Response;
use Webkul\User\Models\Admin; use Webkul\User\Repositories\AdminRepository as Admin;
use Webkul\User\Models\Role; use Webkul\User\Repositories\RoleRepository as Role;
use Webkul\User\Http\Requests\UserForm; use Webkul\User\Http\Requests\UserForm;
/** /**
@ -22,14 +22,34 @@ class UserController extends Controller
* @var array * @var array
*/ */
protected $_config; protected $_config;
/**
* AdminRepository object
*
* @var array
*/
protected $admin;
/**
* RoleRepository object
*
* @var array
*/
protected $role;
/** /**
* Create a new controller instance. * Create a new controller instance.
* *
* @param Webkul\User\Repositories\AdminRepository $admin
* @param Webkul\User\Repositories\RoleRepository $role
* @return void * @return void
*/ */
public function __construct() public function __construct(Admin $admin, Role $role)
{ {
$this->admin = $admin;
$this->role = $role;
$this->_config = request('_config'); $this->_config = request('_config');
$this->middleware('guest', ['except' => 'destroy']); $this->middleware('guest', ['except' => 'destroy']);
@ -52,7 +72,7 @@ class UserController extends Controller
*/ */
public function create() public function create()
{ {
$roles = Role::all(); $roles = $this->role->all();
return view($this->_config['view'], compact('roles')); return view($this->_config['view'], compact('roles'));
} }
@ -65,7 +85,7 @@ class UserController extends Controller
*/ */
public function store(UserForm $request) public function store(UserForm $request)
{ {
Admin::create(request()->all()); $this->admin->create(request()->all());
session()->flash('success', 'User created successfully.'); session()->flash('success', 'User created successfully.');
@ -80,8 +100,9 @@ class UserController extends Controller
*/ */
public function edit($id) public function edit($id)
{ {
$user = Admin::findOrFail($id); $user = $this->admin->findOrFail($id);
$roles = Role::all();
$roles = $this->role->all();
return view($this->_config['view'], compact('user', 'roles')); return view($this->_config['view'], compact('user', 'roles'));
} }
@ -95,9 +116,7 @@ class UserController extends Controller
*/ */
public function update(UserForm $request, $id) public function update(UserForm $request, $id)
{ {
$user = Admin::findOrFail($id); $this->admin->update(request()->all(), $id);
$user->update(request(['name', 'email', 'password']));
session()->flash('success', 'User updated successfully.'); session()->flash('success', 'User updated successfully.');

View File

@ -0,0 +1,24 @@
<?php
namespace Webkul\User\Repositories;
use Webkul\Core\Eloquent\Repository;
/**
* Admin Reposotory
*
* @author Jitendra Singh <jitendra@webkul.com>
* @copyright 2018 Webkul Software Pvt Ltd (http://www.webkul.com)
*/
class AdminRepository extends Repository
{
/**
* Specify Model class name
*
* @return mixed
*/
function model()
{
return 'Webkul\User\Models\Admin';
}
}

View File

@ -0,0 +1,24 @@
<?php
namespace Webkul\User\Repositories;
use Webkul\Core\Eloquent\Repository;
/**
* Role Reposotory
*
* @author Jitendra Singh <jitendra@webkul.com>
* @copyright 2018 Webkul Software Pvt Ltd (http://www.webkul.com)
*/
class RoleRepository extends Repository
{
/**
* Specify Model class name
*
* @return mixed
*/
function model()
{
return 'Webkul\User\Models\Role';
}
}

View File

@ -0,0 +1,191 @@
@import url(https://fonts.googleapis.com/css?family=Montserrat:400,500);body {
margin: 0;
color: #3A3A3A;
font-family: "Montserrat", sans-serif;
font-size: 14px;
font-weight: 500;
position: static;
min-height: 100%;
}
.navbar-top {
height: 60px;
background: #ffffff;
font-size: 0;
-webkit-box-shadow: 0 3px 6px 0 rgba(0, 0, 0, 0.05);
box-shadow: 0 3px 6px 0 rgba(0, 0, 0, 0.05);
border-bottom: 1px solid rgba(162, 162, 162, 0.2);
position: fixed;
left: 0;
right: 0;
z-index: 5;
}
.navbar-top .navbar-top-left {
width: 50%;
height: 60px;
display: inline-block;
vertical-align: middle;
}
.navbar-top .navbar-top-left .brand-logo {
padding: 10px;
}
.navbar-top .navbar-top-right {
width: 50%;
height: 60px;
text-align: right;
display: inline-block;
vertical-align: middle;
}
.navbar-top .navbar-top-right .profile-info {
display: inline-block;
vertical-align: middle;
text-align: left;
min-width: 50px;
position: relative;
padding: 12px 0px;
margin: 0px 25px 0px 30px;
font-size: 15px;
cursor: pointer;
position: relative;
}
.navbar-top .navbar-top-right .profile-info .dropdown-list {
top: 63px;
}
.navbar-top .navbar-top-right .profile-info .name {
color: #000311;
display: block;
text-align: left;
}
.navbar-top .navbar-top-right .profile-info .role {
font-size: 14px;
color: #8e8e8e;
display: block;
text-align: left;
}
.navbar-top .navbar-top-right .profile-info i.icon {
margin-left: 10px;
}
.navbar-left {
position: absolute;
top: 60px;
bottom: 0;
width: 90px;
padding-top: 20px;
height: auto;
border-right: 1px solid rgba(162, 162, 162, 0.2);
z-index: 2;
}
.navbar-left ul.menubar li.menu-item {
height: 90px;
padding: 10px 5px;
font-size: 11px;
text-align: center;
text-transform: uppercase;
}
.navbar-left ul.menubar li.menu-item a {
color: #a2a2a2;
}
.navbar-left ul.menubar li.menu-item.active a {
color: #0041ff;
}
.content-container {
padding-left: 90px;
position: absolute;
margin-top: 60px;
top: 0px;
right: 0;
left: 0;
bottom: 0px;
overflow-x: hidden;
overflow-y: auto;
}
.content-container .aside-nav {
width: 280px;
position: fixed;
top: 60px;
bottom: 0;
border-right: 1px solid rgba(162, 162, 162, 0.2);
background: #f8f9fa;
padding-top: 10px;
overflow-y: auto;
z-index: 4;
}
.content-container .aside-nav a {
padding: 15px;
display: block;
color: #000311;
}
.content-container .aside-nav .active a {
background: #ffffff;
border-top: 1px solid rgba(162, 162, 162, 0.2);
border-bottom: 1px solid rgba(162, 162, 162, 0.2);
}
.content-container .aside-nav .active i {
float: right;
}
.content-container .content-wrapper {
padding: 25px 25px 25px 305px;
}
.content-container .content {
padding: 25px 0;
}
.content-container .content.full-page {
padding: 25px;
}
.content-container .content .page-header {
display: inline-block;
margin-bottom: 20px;
width: 100%;
}
.content-container .content .page-header .page-title {
float: left;
}
.content-container .content .page-header .page-title h1 {
margin-bottom: 0;
vertical-align: middle;
display: inline-block;
}
.content-container .content .page-header .page-action {
float: right;
}
.content-container .content .page-header .control-group {
width: 180px;
display: inline-block;
margin-bottom: 0;
margin-left: 20px;
}
.content-container .content .page-header .control {
width: 100%;
margin: 0;
}
.content-container .content .page-content {
width: 100%;
display: inline-block;
}

File diff suppressed because it is too large Load Diff

1236
public/vendor/webkul/ui/assets/css/ui.css vendored Normal file

File diff suppressed because it is too large Load Diff

1588
public/vendor/webkul/ui/assets/js/ui.js vendored Normal file

File diff suppressed because it is too large Load Diff