¨4.0.1¨
This commit is contained in:
@@ -3,13 +3,14 @@
|
||||
namespace Modules\Option\Admin;
|
||||
|
||||
use Modules\Admin\Ui\AdminTable;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
|
||||
class OptionTable extends AdminTable
|
||||
{
|
||||
/**
|
||||
* Make table response for the resource.
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function make()
|
||||
{
|
||||
|
||||
@@ -15,6 +15,7 @@ class OptionTabs extends Tabs
|
||||
->add($this->values());
|
||||
}
|
||||
|
||||
|
||||
private function general()
|
||||
{
|
||||
return tap(new Tab('general', trans('option::options.tabs.general')), function (Tab $tab) {
|
||||
@@ -25,6 +26,7 @@ class OptionTabs extends Tabs
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private function values()
|
||||
{
|
||||
return tap(new Tab('values', trans('option::options.tabs.values')), function (Tab $tab) {
|
||||
|
||||
@@ -24,6 +24,7 @@ class CreateOptionsTable extends Migration
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
|
||||
@@ -24,6 +24,7 @@ class CreateOptionTranslationsTable extends Migration
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
|
||||
@@ -25,6 +25,7 @@ class CreateOptionValuesTable extends Migration
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
|
||||
@@ -24,6 +24,7 @@ class CreateOptionValueTranslationsTable extends Migration
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
|
||||
@@ -23,6 +23,7 @@ class CreateProductOptionsTable extends Migration
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
|
||||
@@ -4,6 +4,7 @@ namespace Modules\Option\Entities;
|
||||
|
||||
use Modules\Support\Eloquent\Model;
|
||||
use Modules\Option\Admin\OptionTable;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Modules\Support\Eloquent\Translatable;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
||||
@@ -20,8 +21,7 @@ class Option extends Model
|
||||
'field', 'textarea', 'dropdown', 'checkbox', 'checkbox_custom',
|
||||
'radio', 'radio_custom', 'multiple_select', 'date', 'date_time', 'time',
|
||||
];
|
||||
|
||||
/**
|
||||
/*
|
||||
* The relations to eager load on every query.
|
||||
*
|
||||
* @var array
|
||||
@@ -59,6 +59,7 @@ class Option extends Model
|
||||
*/
|
||||
protected $translatedAttributes = ['name'];
|
||||
|
||||
|
||||
/**
|
||||
* Perform any actions required after the model boots.
|
||||
*
|
||||
@@ -73,11 +74,34 @@ class Option extends Model
|
||||
});
|
||||
}
|
||||
|
||||
public function isFieldType()
|
||||
|
||||
/**
|
||||
* Save values for the option.
|
||||
*
|
||||
* @param array $values
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function saveValues($values = [])
|
||||
{
|
||||
return in_array($this->type, ['field', 'textarea', 'dropdown', 'radio', 'date', 'date_time', 'time']);
|
||||
$ids = $this->getDeleteCandidates($values);
|
||||
|
||||
if ($ids->isNotEmpty()) {
|
||||
$this->values()->whereIn('id', $ids)->delete();
|
||||
}
|
||||
|
||||
$counter = 0;
|
||||
|
||||
foreach (array_reset_index($values) as $attributes) {
|
||||
$attributes += ['position' => ++$counter];
|
||||
|
||||
$this->values()->updateOrCreate([
|
||||
'id' => array_get($attributes, 'id'),
|
||||
], $attributes);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the values for the option.
|
||||
*
|
||||
@@ -88,49 +112,36 @@ class Option extends Model
|
||||
return $this->hasMany(OptionValue::class)->orderBy('position');
|
||||
}
|
||||
|
||||
|
||||
public function isFieldType()
|
||||
{
|
||||
return in_array($this->type, ['field', 'textarea', 'dropdown', 'radio', 'date', 'date_time', 'time']);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Scope a query to only include global options.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
* @param Builder $query
|
||||
*
|
||||
* @return Builder
|
||||
*/
|
||||
public function scopeGlobals($query)
|
||||
{
|
||||
return $query->where('is_global', true);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get table data for the resource
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
* @return OptionTable
|
||||
*/
|
||||
public function table()
|
||||
public function table(): OptionTable
|
||||
{
|
||||
return new OptionTable($this->newQuery()->globals());
|
||||
}
|
||||
|
||||
/**
|
||||
* Save values for the option.
|
||||
*
|
||||
* @param array $values
|
||||
* @return void
|
||||
*/
|
||||
public function saveValues($values = [])
|
||||
{
|
||||
$ids = $this->getDeleteCandidates($values);
|
||||
|
||||
if ($ids->isNotEmpty()) {
|
||||
$this->values()->whereIn('id', $ids)->delete();
|
||||
}
|
||||
|
||||
foreach (array_reset_index($values) as $index => $attributes) {
|
||||
$attributes += ['position' => $index];
|
||||
|
||||
$this->values()->updateOrCreate([
|
||||
'id' => array_get($attributes, 'id'),
|
||||
], $attributes);
|
||||
}
|
||||
}
|
||||
|
||||
private function getDeleteCandidates($values)
|
||||
{
|
||||
|
||||
@@ -32,6 +32,7 @@ class OptionValue extends Model
|
||||
*/
|
||||
protected $translatedAttributes = ['label'];
|
||||
|
||||
|
||||
public function getPriceAttribute($price)
|
||||
{
|
||||
if ($this->priceIsPercent()) {
|
||||
@@ -41,29 +42,12 @@ class OptionValue extends Model
|
||||
return Money::inDefaultCurrency($price);
|
||||
}
|
||||
|
||||
|
||||
public function priceIsPercent()
|
||||
{
|
||||
return $this->price_type === 'percent';
|
||||
}
|
||||
|
||||
public function priceIsFixed()
|
||||
{
|
||||
return $this->price_type === 'fixed';
|
||||
}
|
||||
|
||||
public function priceForProduct(Product $product)
|
||||
{
|
||||
if ($this->priceIsFixed()) {
|
||||
return $this->price;
|
||||
}
|
||||
|
||||
return $this->getPercentOf($product->selling_price->amount());
|
||||
}
|
||||
|
||||
private function getPercentOf($productPrice)
|
||||
{
|
||||
return Money::inDefaultCurrency(($this->price / 100) * $productPrice);
|
||||
}
|
||||
|
||||
public function formattedPriceForProduct(Product $product, $forSelectOption = false)
|
||||
{
|
||||
@@ -81,4 +65,28 @@ class OptionValue extends Model
|
||||
|
||||
return "<span class='extra-price'>+ {$formattedPrice}</span>";
|
||||
}
|
||||
|
||||
|
||||
public function priceForProduct(Product $product)
|
||||
{
|
||||
if ($this->priceIsFixed()) {
|
||||
return $this->price;
|
||||
}
|
||||
|
||||
return $this->getPercentOf(($product->variant ?? $product)
|
||||
->selling_price
|
||||
->amount());
|
||||
}
|
||||
|
||||
|
||||
public function priceIsFixed()
|
||||
{
|
||||
return $this->price_type === 'fixed';
|
||||
}
|
||||
|
||||
|
||||
private function getPercentOf($productPrice)
|
||||
{
|
||||
return Money::inDefaultCurrency(($this->price / 100) * $productPrice);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ namespace Modules\Option\Http\Controllers\Admin;
|
||||
|
||||
use Modules\Option\Entities\Option;
|
||||
use Modules\Admin\Traits\HasCrudActions;
|
||||
use Modules\Option\Transformers\OptionResource;
|
||||
use Modules\Option\Http\Requests\SaveOptionRequest;
|
||||
|
||||
class OptionController
|
||||
@@ -37,4 +38,12 @@ class OptionController
|
||||
* @var array|string
|
||||
*/
|
||||
protected $validation = SaveOptionRequest::class;
|
||||
|
||||
|
||||
public function show($id): OptionResource
|
||||
{
|
||||
$entity = $this->getEntity($id);
|
||||
|
||||
return new OptionResource($entity);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ class SaveOptionRequest extends Request
|
||||
*/
|
||||
protected $availableAttributes = 'option::attributes';
|
||||
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
@@ -32,6 +33,7 @@ class SaveOptionRequest extends Request
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
public function validationData()
|
||||
{
|
||||
return request()->merge([
|
||||
@@ -39,14 +41,15 @@ class SaveOptionRequest extends Request
|
||||
])->all();
|
||||
}
|
||||
|
||||
|
||||
private function filter($values = [])
|
||||
{
|
||||
return array_filter($values, function ($value) {
|
||||
if (! array_has($value, 'label')) {
|
||||
if (!array_has($value, 'label')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return ! is_null($value['label']);
|
||||
return !is_null($value['label']);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ class SaveProductOptionsRequest extends Request
|
||||
*/
|
||||
protected $availableAttributes = 'option::attributes';
|
||||
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
|
||||
@@ -2,12 +2,15 @@
|
||||
|
||||
namespace Modules\Option\Listeners;
|
||||
|
||||
use Modules\Product\Entities\Product;
|
||||
|
||||
class SaveProductOptions
|
||||
{
|
||||
/**
|
||||
* Handle the event.
|
||||
*
|
||||
* @param \Modules\Product\Entities\Product $product
|
||||
* @param Product $product
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function handle($product)
|
||||
@@ -21,6 +24,7 @@ class SaveProductOptions
|
||||
$this->saveOptions($product);
|
||||
}
|
||||
|
||||
|
||||
private function getDeleteCandidates($product)
|
||||
{
|
||||
return $product->options()
|
||||
@@ -28,21 +32,31 @@ class SaveProductOptions
|
||||
->diff(array_pluck($this->options(), 'id'));
|
||||
}
|
||||
|
||||
|
||||
private function options()
|
||||
{
|
||||
return array_filter(request('options', []), function ($option) {
|
||||
return !is_null($option['name']);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private function saveOptions($product)
|
||||
{
|
||||
foreach (array_reset_index($this->options()) as $index => $attributes) {
|
||||
$attributes += ['is_global' => false, 'position' => $index];
|
||||
$counter = 0;
|
||||
|
||||
foreach (array_reset_index($this->options()) as $attributes) {
|
||||
#if it's a global option make the id null to render it creatable
|
||||
if ($attributes['is_global'] === true) {
|
||||
$attributes['id'] = null;
|
||||
}
|
||||
|
||||
$attributes['is_global'] = false;
|
||||
$attributes['position'] = ++$counter;
|
||||
|
||||
$option = $product->options()->updateOrCreate(['id' => $attributes['id'] ?? null], $attributes);
|
||||
|
||||
$option->saveValues($attributes['values'] ?? []);
|
||||
}
|
||||
}
|
||||
|
||||
private function options()
|
||||
{
|
||||
return array_filter(request('options', []), function ($option) {
|
||||
return ! is_null($option['name']);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ namespace Modules\Option\Providers;
|
||||
|
||||
use Modules\Product\Entities\Product;
|
||||
use Modules\Option\Listeners\SaveProductOptions;
|
||||
use Modules\Option\Http\Requests\SaveProductOptionsRequest;
|
||||
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
|
||||
|
||||
class EventServiceProvider extends ServiceProvider
|
||||
@@ -18,10 +17,6 @@ class EventServiceProvider extends ServiceProvider
|
||||
{
|
||||
parent::boot();
|
||||
|
||||
Product::saving(function () {
|
||||
resolve(SaveProductOptionsRequest::class);
|
||||
});
|
||||
|
||||
Product::saved(SaveProductOptions::class);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,15 +3,11 @@
|
||||
namespace Modules\Option\Providers;
|
||||
|
||||
use Modules\Option\Admin\OptionTabs;
|
||||
use Modules\Support\Traits\AddsAsset;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use Modules\Admin\Ui\Facades\TabManager;
|
||||
use Modules\Option\Admin\ProductTabsExtender;
|
||||
|
||||
class OptionServiceProvider extends ServiceProvider
|
||||
{
|
||||
use AddsAsset;
|
||||
|
||||
/**
|
||||
* Bootstrap the application services.
|
||||
*
|
||||
@@ -20,8 +16,5 @@ class OptionServiceProvider extends ServiceProvider
|
||||
public function boot()
|
||||
{
|
||||
TabManager::register('options', OptionTabs::class);
|
||||
TabManager::extend('products', ProductTabsExtender::class);
|
||||
|
||||
$this->addAdminAssets('admin.(options|products).(create|edit)', ['admin.option.css', 'admin.option.js']);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ export default class {
|
||||
for (let key in errors) {
|
||||
let inputField = this.getInputFieldForErrorKey(key);
|
||||
|
||||
inputField.closest('.option').addClass('option-has-errors');
|
||||
inputField.closest(".option").addClass("option-has-errors");
|
||||
|
||||
let parent = inputField.parent();
|
||||
|
||||
@@ -12,7 +12,7 @@ export default class {
|
||||
}
|
||||
|
||||
getRowTemplate(data) {
|
||||
let template = _.template($('#option-select-values-template').html());
|
||||
let template = _.template($("#option-select-values-template").html());
|
||||
|
||||
return $(template(data));
|
||||
}
|
||||
@@ -20,13 +20,16 @@ export default class {
|
||||
changeOptionType({ optionId, type, values = [] }) {
|
||||
let optionValuesElement = this.getOptionValuesElement(optionId);
|
||||
let templateType = this.getTemplateType(type, optionValuesElement);
|
||||
let optionValuesData = { optionId, value: { id: '', label: '', price: '', price_type: 'fixed' } };
|
||||
let optionValuesData = {
|
||||
optionId,
|
||||
value: { id: "", label: "", price: "", price_type: "fixed" },
|
||||
};
|
||||
|
||||
if (this.shouldNotChangeTemplate(templateType, optionValuesElement)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (values.length !== 0 && templateType === 'text') {
|
||||
if (values.length !== 0 && templateType === "text") {
|
||||
optionValuesData.value = values[0];
|
||||
}
|
||||
|
||||
@@ -34,13 +37,13 @@ export default class {
|
||||
|
||||
optionValuesElement.html(template(optionValuesData));
|
||||
|
||||
if (templateType === 'select') {
|
||||
if (templateType === "select") {
|
||||
this.addOptionRowEventListener(optionId);
|
||||
|
||||
this.addOptionRows({ optionId, values });
|
||||
|
||||
if (values.length === 0) {
|
||||
this.getAddNewRowButton(optionId).trigger('click');
|
||||
this.getAddNewRowButton(optionId).trigger("click");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -57,41 +60,53 @@ export default class {
|
||||
|
||||
getTemplateType(type) {
|
||||
if (this.templateTypeIsText(type)) {
|
||||
return 'text';
|
||||
return "text";
|
||||
}
|
||||
|
||||
if (this.templateTypeIsSelect(type)) {
|
||||
return 'select';
|
||||
return "select";
|
||||
}
|
||||
}
|
||||
|
||||
templateTypeIsText(type) {
|
||||
return ['field', 'textarea', 'date', 'date_time', 'time'].includes(type);
|
||||
return ["field", "textarea", "date", "date_time", "time"].includes(
|
||||
type
|
||||
);
|
||||
}
|
||||
|
||||
templateTypeIsSelect(type) {
|
||||
return ['dropdown', 'checkbox', 'checkbox_custom', 'radio', 'radio_custom', 'multiple_select'].includes(type);
|
||||
return [
|
||||
"dropdown",
|
||||
"checkbox",
|
||||
"checkbox_custom",
|
||||
"radio",
|
||||
"radio_custom",
|
||||
"multiple_select",
|
||||
].includes(type);
|
||||
}
|
||||
|
||||
shouldNotChangeTemplate(templateType, optionValuesElement) {
|
||||
return templateType === undefined || this.alreadyHasCurrentTemplate(templateType, optionValuesElement);
|
||||
return (
|
||||
templateType === undefined ||
|
||||
this.alreadyHasCurrentTemplate(templateType, optionValuesElement)
|
||||
);
|
||||
}
|
||||
|
||||
alreadyHasCurrentTemplate(templateType, optionValuesElement) {
|
||||
if (templateType === 'text') {
|
||||
return optionValuesElement.children().hasClass('option-text');
|
||||
if (templateType === "text") {
|
||||
return optionValuesElement.children().hasClass("option-text");
|
||||
}
|
||||
|
||||
if (templateType === 'select') {
|
||||
return optionValuesElement.children().hasClass('option-select');
|
||||
if (templateType === "select") {
|
||||
return optionValuesElement.children().hasClass("option-select");
|
||||
}
|
||||
}
|
||||
|
||||
initOptionRow(template, selectValues) {
|
||||
if (selectValues.length !== 0 && ! selectValues.is('.sortable')) {
|
||||
if (selectValues.length !== 0 && !selectValues.is(".sortable")) {
|
||||
this.makeSortable(selectValues[0]);
|
||||
|
||||
selectValues.addClass('sortable');
|
||||
selectValues.addClass("sortable");
|
||||
}
|
||||
|
||||
this.deleteOptionRowEventListener(template);
|
||||
@@ -100,14 +115,14 @@ export default class {
|
||||
}
|
||||
|
||||
deleteOptionRowEventListener(row) {
|
||||
row.find('.delete-row').on('click', (e) => {
|
||||
$(e.currentTarget).closest('.option-row').remove();
|
||||
row.find(".delete-row").on("click", (e) => {
|
||||
$(e.currentTarget).closest(".option-row").remove();
|
||||
});
|
||||
}
|
||||
|
||||
makeSortable(el) {
|
||||
Sortable.create(el, {
|
||||
handle: '.drag-icon',
|
||||
handle: ".drag-handle",
|
||||
animation: 150,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,10 +1,5 @@
|
||||
import Option from './Option';
|
||||
import ProductOption from './ProductOption';
|
||||
import Option from "./Option";
|
||||
|
||||
if ($('#option-create-form, #option-edit-form').length !== 0) {
|
||||
if ($("#option-create-form, #option-edit-form").length !== 0) {
|
||||
new Option();
|
||||
}
|
||||
|
||||
if ($('#product-create-form, #product-edit-form').length !== 0) {
|
||||
new ProductOption();
|
||||
}
|
||||
|
||||
@@ -1,37 +1,64 @@
|
||||
.new-option {
|
||||
.checkbox {
|
||||
margin: 30px 0 0;
|
||||
display: inline-block;
|
||||
.options-group {
|
||||
.option-values {
|
||||
margin-top: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
.delete-option {
|
||||
margin-top: 25px;
|
||||
padding: 10px 15px;
|
||||
.new-option {
|
||||
overflow: hidden;
|
||||
margin-bottom: -15px;
|
||||
|
||||
.checkbox {
|
||||
margin: 26px 0 0;
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
||||
.options-group-wrapper {
|
||||
.panel-title a {
|
||||
.panel-title [data-toggle="collapse"] {
|
||||
font-size: 14px;
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 9px 15px;
|
||||
text-decoration: none;
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
|
||||
> .drag-icon {
|
||||
&:after {
|
||||
top: 11px !important;
|
||||
}
|
||||
|
||||
.drag-handle {
|
||||
font-size: 16px;
|
||||
color: #737881;
|
||||
cursor: move;
|
||||
vertical-align: top;
|
||||
margin: 4px 10px 0 0;
|
||||
margin-right: 11px;
|
||||
white-space: nowrap;
|
||||
display: inline-block;
|
||||
i {
|
||||
float: left;
|
||||
cursor: move;
|
||||
|
||||
i {
|
||||
&:nth-child(2) {
|
||||
margin-left: 1px;
|
||||
margin-left: -3px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.delete-option {
|
||||
width: 30px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
align-self: stretch;
|
||||
justify-content: center;
|
||||
margin-right: 20px;
|
||||
color: #4d4d4d;
|
||||
transition: 150ms ease-in-out;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
color: #333333;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.form-group {
|
||||
@@ -47,7 +74,7 @@
|
||||
|
||||
thead th {
|
||||
&:first-child {
|
||||
width: 40px;
|
||||
width: 35px;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
@@ -76,39 +103,8 @@
|
||||
}
|
||||
}
|
||||
|
||||
.add-global-option {
|
||||
.form-group {
|
||||
margin-left: 0 !important;
|
||||
margin-right: 10px !important;
|
||||
}
|
||||
|
||||
> button {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@media screen and (max-width: 1199px) {
|
||||
.add-global-option {
|
||||
float: none !important;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.new-option {
|
||||
.checkbox {
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.delete-option {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.p-l-0 {
|
||||
padding-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.options-group-wrapper {
|
||||
.options-group {
|
||||
.option-values {
|
||||
.option-text,
|
||||
.option-select {
|
||||
@@ -120,8 +116,82 @@
|
||||
|
||||
@media screen and (max-width: 991px) {
|
||||
.new-option {
|
||||
.form-group {
|
||||
label {
|
||||
margin-bottom: 6px;
|
||||
padding-top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.checkbox {
|
||||
padding-top: 7px;
|
||||
padding-top: 8px;
|
||||
|
||||
label {
|
||||
padding-top: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: 768px) {
|
||||
.new-option {
|
||||
> .row {
|
||||
> .col-sm-6 {
|
||||
padding-right: 10px;
|
||||
}
|
||||
|
||||
> .col-sm-3 {
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 767px) {
|
||||
.options-group {
|
||||
.option-values {
|
||||
margin-top: 20px;
|
||||
|
||||
.option-select {
|
||||
.table {
|
||||
> tbody {
|
||||
> tr {
|
||||
> td {
|
||||
&:nth-child(2) {
|
||||
min-width: 160px;
|
||||
}
|
||||
|
||||
&:nth-child(3) {
|
||||
min-width: 145px;
|
||||
}
|
||||
|
||||
&:nth-child(4) {
|
||||
min-width: 110px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.new-option {
|
||||
margin-bottom: -10px;
|
||||
|
||||
> .row {
|
||||
> div {
|
||||
&:nth-child(3) {
|
||||
.form-group {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.checkbox {
|
||||
margin-top: -3px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,8 +3,7 @@
|
||||
return [
|
||||
'option' => 'Option',
|
||||
'options' => 'Options',
|
||||
'select_global_option' => 'Select Global Option',
|
||||
'please_select_a_option_type' => 'Please select a option type.',
|
||||
'please_select_a_option_type' => 'Please select a option type',
|
||||
'table' => [
|
||||
'name' => 'Name',
|
||||
'type' => 'Type',
|
||||
@@ -15,15 +14,9 @@ return [
|
||||
],
|
||||
'general' => 'General',
|
||||
'values' => 'Values',
|
||||
'product' => [
|
||||
'options' => 'Options',
|
||||
],
|
||||
],
|
||||
'form' => [
|
||||
'this_option_is_required' => 'This option is required',
|
||||
'add_new_option' => 'Add New Option',
|
||||
'add_global_option' => 'Add Global Option',
|
||||
'new_option' => 'New Option',
|
||||
'option_types' => [
|
||||
'please_select' => 'Please Select',
|
||||
'text' => 'Text',
|
||||
@@ -46,7 +39,7 @@ return [
|
||||
'fixed' => 'Fixed',
|
||||
'percent' => 'Percent',
|
||||
],
|
||||
'add_new_row' => 'Add New Row',
|
||||
'add_row' => 'Add Row',
|
||||
'delete_row' => 'Delete Row',
|
||||
],
|
||||
];
|
||||
|
||||
@@ -16,3 +16,10 @@
|
||||
@endsection
|
||||
|
||||
@include('option::admin.options.partials.scripts')
|
||||
|
||||
@push('globals')
|
||||
@vite([
|
||||
'Modules/Option/Resources/assets/admin/sass/main.scss',
|
||||
'Modules/Option/Resources/assets/admin/js/main.js',
|
||||
])
|
||||
@endpush
|
||||
@@ -18,3 +18,10 @@
|
||||
@endsection
|
||||
|
||||
@include('option::admin.options.partials.scripts')
|
||||
|
||||
@push('globals')
|
||||
@vite([
|
||||
'Modules/Option/Resources/assets/admin/sass/main.scss',
|
||||
'Modules/Option/Resources/assets/admin/js/main.js',
|
||||
])
|
||||
@endpush
|
||||
@@ -24,7 +24,7 @@
|
||||
@endcomponent
|
||||
|
||||
@push('scripts')
|
||||
<script>
|
||||
<script type="module">
|
||||
new DataTable('#options-table .table', {
|
||||
columns: [
|
||||
{ data: 'checkbox', orderable: false, searchable: false, width: '3%' },
|
||||
|
||||
@@ -1,10 +1,3 @@
|
||||
@push('globals')
|
||||
<script>
|
||||
FleetCart.data['option.values'] = {!! old_json('values', $option->values) !!};
|
||||
FleetCart.errors['option.values'] = @json($errors->get('values.*'), JSON_FORCE_OBJECT);
|
||||
</script>
|
||||
@endpush
|
||||
|
||||
@push('shortcuts')
|
||||
<dl class="dl-horizontal">
|
||||
<dt><code>b</code></dt>
|
||||
@@ -12,8 +5,15 @@
|
||||
</dl>
|
||||
@endpush
|
||||
|
||||
@push('scripts')
|
||||
@push('globals')
|
||||
<script>
|
||||
FleetCart.data['option.values'] = {!! old_json('values', $option->values) !!};
|
||||
FleetCart.errors['option.values'] = @json($errors->get('values.*'), JSON_FORCE_OBJECT);
|
||||
</script>
|
||||
@endpush
|
||||
|
||||
@push('scripts')
|
||||
<script type="module">
|
||||
keypressAction([
|
||||
{ key: 'b', route: "{{ route('admin.options.index') }}" },
|
||||
]);
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
id="option-<%- optionId %>-add-new-row"
|
||||
<% } %>
|
||||
>
|
||||
{{ trans('option::options.form.add_new_row') }}
|
||||
{{ trans('option::options.form.add_row') }}
|
||||
</button>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script type="text/html" id="option-select-values-template">
|
||||
<tr class="option-row">
|
||||
<td class="text-center">
|
||||
<span class="drag-icon">
|
||||
<span class="drag-handle">
|
||||
<i class="fa"></i>
|
||||
<i class="fa"></i>
|
||||
</span>
|
||||
|
||||
@@ -43,3 +43,9 @@ Route::delete('options/{ids}', [
|
||||
'uses' => 'OptionController@destroy',
|
||||
'middleware' => 'can:admin.options.destroy',
|
||||
]);
|
||||
|
||||
Route::get('options/index/table', [
|
||||
'as' => 'admin.options.table',
|
||||
'uses' => 'OptionController@table',
|
||||
'middleware' => 'can:admin.options.index',
|
||||
]);
|
||||
|
||||
@@ -14,7 +14,7 @@ class SidebarExtender extends BaseSidebarExtender
|
||||
$menu->group(trans('admin::sidebar.content'), function (Group $group) {
|
||||
$group->item(trans('product::sidebar.products'), function (Item $item) {
|
||||
$item->item(trans('option::sidebar.options'), function (Item $item) {
|
||||
$item->weight(25);
|
||||
$item->weight(30);
|
||||
$item->route('admin.options.index');
|
||||
$item->authorize(
|
||||
$this->auth->hasAccess('admin.options.index')
|
||||
|
||||
28
Modules/Option/Transformers/OptionResource.php
Normal file
28
Modules/Option/Transformers/OptionResource.php
Normal file
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Option\Transformers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
class OptionResource extends JsonResource
|
||||
{
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*
|
||||
* @param Request
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($request)
|
||||
{
|
||||
return [
|
||||
'id' => $this->id,
|
||||
'name' => $this->name,
|
||||
'type' => $this->type,
|
||||
'is_global' => $this->is_global,
|
||||
'is_required' => $this->is_required,
|
||||
'values' => OptionValueResource::collection($this->values),
|
||||
];
|
||||
}
|
||||
}
|
||||
27
Modules/Option/Transformers/OptionValueResource.php
Normal file
27
Modules/Option/Transformers/OptionValueResource.php
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Option\Transformers;
|
||||
|
||||
use Modules\Support\Money;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
class OptionValueResource extends JsonResource
|
||||
{
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*
|
||||
* @param Request
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($request)
|
||||
{
|
||||
return [
|
||||
'id' => $this->id,
|
||||
'price' => $this->price instanceof Money ? $this->price->amount() : $this->price,
|
||||
'price_type' => $this->price_type,
|
||||
'label' => $this->label,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
<?php
|
||||
|
||||
if (! defined('FOR_SELECT_OPTION')) {
|
||||
if (!defined('FOR_SELECT_OPTION')) {
|
||||
define('FOR_SELECT_OPTION', true);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user