first upload all files

This commit is contained in:
NW
2023-06-11 13:14:03 +01:00
parent f14dbc52b5
commit c08b36d1b6
1705 changed files with 106852 additions and 0 deletions

View File

@@ -0,0 +1,32 @@
export default class {
constructor(download) {
this.downloadHtml = this.getDownloadHtml(download);
}
getDownloadHtml(download) {
let template = _.template($('#product-download-template').html());
return $(template(download));
}
render() {
this.attachEventListeners();
return this.downloadHtml;
}
attachEventListeners() {
this.downloadHtml.find('.delete-row').on('click', () => {
this.downloadHtml.remove();
});
this.downloadHtml.find('.btn-choose-file').on('click', () => {
let picker = new MediaPicker();
picker.on('select', (file) => {
this.downloadHtml.find('.download-name').val(file.filename);
this.downloadHtml.find('.download-file').val(file.id);
});
});
}
}

View File

@@ -0,0 +1,44 @@
import Download from './Download';
export default class {
constructor() {
this.downloadsCount = 0;
this.addDownloads(FleetCart.data['product.downloads']);
if (this.downloadsCount === 0) {
this.addDownload();
}
this.attachEventListeners();
this.makeDownloadsSortable();
}
addDownloads(downloads) {
for (let attributes of downloads) {
this.addDownload(attributes);
}
}
addDownload(attributes = {}) {
let download = new Download({ download: attributes });
$('#downloads-wrapper').append(download.render());
this.downloadsCount++;
window.admin.tooltip();
}
attachEventListeners() {
$('#add-new-file').on('click', () => {
this.addDownload();
});
}
makeDownloadsSortable() {
Sortable.create(document.getElementById('downloads-wrapper'), {
handle: '.drag-icon',
animation: 150,
});
}
}

View File

@@ -0,0 +1,34 @@
export default class {
constructor() {
this.managerStock();
window.admin.removeSubmitButtonOffsetOn([
'#images', '#downloads', '#attributes', '#options',
'#related_products', '#up_sells', '#cross_sells', '#reviews',
]);
$('#product-create-form, #product-edit-form').on('submit', this.submit);
}
managerStock() {
$('#manage_stock').on('change', (e) => {
if (e.currentTarget.value === '1') {
$('#qty-field').removeClass('hide');
} else {
$('#qty-field').addClass('hide');
}
});
}
submit(e) {
e.preventDefault();
DataTable.removeLengthFields();
window.form.appendHiddenInputs('#product-create-form, #product-edit-form', 'up_sells', DataTable.getSelectedIds('#up_sells .table'));
window.form.appendHiddenInputs('#product-create-form, #product-edit-form', 'cross_sells', DataTable.getSelectedIds('#cross_sells .table'));
window.form.appendHiddenInputs('#product-create-form, #product-edit-form', 'related_products', DataTable.getSelectedIds('#related_products .table'));
e.currentTarget.submit();
}
}

View File

@@ -0,0 +1,5 @@
import Downloads from './Downloads';
import ProductForm from './ProductForm';
new ProductForm();
new Downloads();

View File

@@ -0,0 +1,22 @@
#images, #attachments {
margin-bottom: 15px;
}
.attachment-wrapper {
tr {
td {
&:nth-child(2),
&:nth-child(3) {
min-width: 200px;
}
&:nth-child(4) {
width: 59px;
}
}
}
.choose-file {
padding: 10px 15px;
}
}

View File

@@ -0,0 +1,25 @@
<?php
return [
'name' => 'Name',
'slug' => 'URL',
'description' => 'Description',
'short_description' => 'Short Description',
'brand_id' => 'Brand',
'categories' => 'Categories',
'tax_class_id' => 'Tax Class',
'tags' => 'Tags',
'is_virtual' => 'Virtual',
'is_active' => 'Status',
'price' => 'Price',
'special_price' => 'Special Price',
'special_price_type' => 'Special Price Type',
'special_price_start' => 'Special Price Start',
'special_price_end' => 'Special Price End',
'sku' => 'SKU',
'manage_stock' => 'Inventory Management',
'qty' => 'Qty',
'in_stock' => 'Stock Availability',
'new_from' => 'Product New From',
'new_to' => 'Product New To',
];

View File

@@ -0,0 +1,8 @@
<?php
return [
'index' => 'Index Products',
'create' => 'Create Products',
'edit' => 'Edit Products',
'destroy' => 'Delete Products',
];

View File

@@ -0,0 +1,50 @@
<?php
return [
'product' => 'Product',
'products' => 'Products',
'table' => [
'thumbnail' => 'Thumbnail',
'name' => 'Name',
'price' => 'Price',
],
'tabs' => [
'group' => [
'basic_information' => 'Basic Information',
'advanced_information' => 'Advanced Information',
],
'general' => 'General',
'price' => 'Price',
'inventory' => 'Inventory',
'images' => 'Images',
'downloads' => 'Downloads',
'seo' => 'SEO',
'related_products' => 'Related Products',
'up_sells' => 'Up-Sells',
'cross_sells' => 'Cross-Sells',
'additional' => 'Additional',
],
'form' => [
'the_product_won\'t_be_shipped' => 'The product won\'t be shipped',
'enable_the_product' => 'Enable the product',
'price_types' => [
'fixed' => 'Fixed',
'percent' => 'Percent',
],
'manage_stock_states' => [
'0' => 'Don\'t Track Inventory',
'1' => 'Track Inventory',
],
'stock_availability_states' => [
'1' => 'In Stock',
'0' => 'Out of Stock',
],
'base_image' => 'Base Image',
'additional_images' => 'Additional Images',
'downloadable_files' => 'Downloadable Files',
'file' => 'File',
'choose' => 'Choose',
'delete_file' => 'Delete File',
'add_new_file' => 'Add New File',
],
];

View File

@@ -0,0 +1,6 @@
<?php
return [
'products' => 'Products',
'catalog' => 'Catalog',
];

View File

@@ -0,0 +1,18 @@
@extends('admin::layout')
@component('admin::components.page.header')
@slot('title', trans('admin::resource.create', ['resource' => trans('product::products.product')]))
<li><a href="{{ route('admin.products.index') }}">{{ trans('product::products.products') }}</a></li>
<li class="active">{{ trans('admin::resource.create', ['resource' => trans('product::products.product')]) }}</li>
@endcomponent
@section('content')
<form method="POST" action="{{ route('admin.products.store') }}" class="form-horizontal" id="product-create-form" enctype="multipart/form-data" novalidate>
{{ csrf_field() }}
{!! $tabs->render(compact('product')) !!}
</form>
@endsection
@include('product::admin.products.partials.shortcuts')

View File

@@ -0,0 +1,20 @@
@extends('admin::layout')
@component('admin::components.page.header')
@slot('title', trans('admin::resource.edit', ['resource' => trans('product::products.product')]))
@slot('subtitle', $product->name)
<li><a href="{{ route('admin.products.index') }}">{{ trans('product::products.products') }}</a></li>
<li class="active">{{ trans('admin::resource.edit', ['resource' => trans('product::products.product')]) }}</li>
@endcomponent
@section('content')
<form method="POST" action="{{ route('admin.products.update', $product) }}" class="form-horizontal" id="product-edit-form" enctype="multipart/form-data" novalidate>
{{ csrf_field() }}
{{ method_field('put') }}
{!! $tabs->render(compact('product')) !!}
</form>
@endsection
@include('product::admin.products.partials.shortcuts')

View File

@@ -0,0 +1,33 @@
@extends('admin::layout')
@component('admin::components.page.header')
@slot('title', trans('product::products.products'))
<li class="active">{{ trans('product::products.products') }}</li>
@endcomponent
@component('admin::components.page.index_table')
@slot('buttons', ['create'])
@slot('resource', 'products')
@slot('name', trans('product::products.product'))
@slot('thead')
@include('product::admin.products.partials.thead', ['name' => 'products-index'])
@endslot
@endcomponent
@push('scripts')
<script>
new DataTable('#products-table .table', {
columns: [
{ data: 'checkbox', orderable: false, searchable: false, width: '3%' },
{ data: 'id', width: '5%' },
{ data: 'thumbnail', orderable: false, searchable: false, width: '10%' },
{ data: 'name', name: 'translations.name', orderable: false, defaultContent: '' },
{ data: 'price', searchable: false },
{ data: 'status', name: 'is_active', searchable: false },
{ data: 'created', name: 'created_at' },
],
});
</script>
@endpush

View File

@@ -0,0 +1,14 @@
@push('shortcuts')
<dl class="dl-horizontal">
<dt><code>b</code></dt>
<dd>{{ trans('admin::admin.shortcuts.back_to_index', ['name' => trans('product::products.product')]) }}</dd>
</dl>
@endpush
@push('scripts')
<script>
keypressAction([
{ key: 'b', route: "{{ route('admin.products.index') }}" },
]);
</script>
@endpush

View File

@@ -0,0 +1,10 @@
<tr>
@include('admin::partials.table.select_all')
<th>{{ trans('admin::admin.table.id') }}</th>
<th>{{ trans('product::products.table.thumbnail') }}</th>
<th>{{ trans('product::products.table.name') }}</th>
<th>{{ trans('product::products.table.price') }}</th>
<th>{{ trans('admin::admin.table.status') }}</th>
<th data-sort>{{ trans('admin::admin.table.created') }}</th>
</tr>

View File

@@ -0,0 +1,7 @@
<div class="row">
<div class="col-md-8">
{{ Form::textarea('short_description', trans('product::attributes.short_description'), $errors, $product) }}
{{ Form::text('new_from', trans('product::attributes.new_from'), $errors, $product, ['class' => 'datetime-picker']) }}
{{ Form::text('new_to', trans('product::attributes.new_to'), $errors, $product, ['class' => 'datetime-picker'] ) }}
</div>
</div>

View File

@@ -0,0 +1,111 @@
<style>
.slide {
border: 1px solid #e9e9e9;
border-radius: 3px;
margin-bottom: 15px;
}
.slide .slide-header {
padding: 15px;
background: #f6f6f7;
border-bottom: 1px solid #e9e9e9;
}
.slide .slide-header span {
font-size: 16px;
}
.slide .slide-body {
position: relative;
padding: 15px;
}
.product-downloads-wrapper .slide {
margin-bottom: 20px;
}
.product-downloads-wrapper .table > tbody > tr > td {
vertical-align: middle;
}
.product-downloads-wrapper .options .drag-icon {
margin-top: 3px;
}
.product-downloads-wrapper .choose-file-group {
display: flex;
}
.product-downloads-wrapper .download-name {
flex-grow: 1;
}
.product-downloads-wrapper .btn-choose-file {
margin-left: 8px;
}
@media screen and (max-width: 767px) {
.product-downloads-wrapper .table > tbody > tr {
border-top: 1px solid #e9e9e9;
}
.product-downloads-wrapper .table > tbody > tr > td:nth-child(2),
.product-downloads-wrapper .table > tbody > tr > td:nth-child(3) {
display: block;
border: none;
width: auto;
padding-left: 15px;
padding-right: 15px;
text-align: left;
vertical-align: initial;
}
.product-downloads-wrapper .table > tbody > tr > td:nth-child(3) {
padding-bottom: 15px;
}
.product-downloads-wrapper .options .drag-icon {
margin-top: 0;
}
}
</style>
<div id="product-downloads-wrapper" class="product-downloads-wrapper clearfix">
<div class="slide">
<div class="slide-header clearfix">
<span class="pull-left">
{{ trans('product::products.form.downloadable_files') }}
</span>
</div>
<div class="slide-body">
<div class="table-responsive">
<table class="options table table-bordered">
<thead class="hidden-xs">
<tr>
<th></th>
<th>{{ trans('product::products.form.file') }}</th>
<th></th>
</tr>
</thead>
<tbody id="downloads-wrapper">
{{-- Downloadable file will be added here dynamically using JS --}}
</tbody>
</table>
</div>
<button type="button" class="btn btn-default" id="add-new-file">
{{ trans('product::products.form.add_new_file') }}
</button>
</div>
</div>
</div>
@include('product::admin.products.tabs.templates.download')
@push('globals')
<script>
FleetCart.data['product.downloads'] = {!! old_json('downloads', $product->downloads ?? []) !!};
</script>
@endpush

View File

@@ -0,0 +1,13 @@
{{ Form::text('name', trans('product::attributes.name'), $errors, $product, ['labelCol' => 2, 'required' => true]) }}
{{ Form::wysiwyg('description', trans('product::attributes.description'), $errors, $product, ['labelCol' => 2, 'required' => true]) }}
<div class="row">
<div class="col-md-8">
{{ Form::select('brand_id', trans('product::attributes.brand_id'), $errors, $brands, $product) }}
{{ Form::select('categories', trans('product::attributes.categories'), $errors, $categories, $product, ['class' => 'selectize prevent-creation', 'multiple' => true]) }}
{{ Form::select('tax_class_id', trans('product::attributes.tax_class_id'), $errors, $taxClasses, $product) }}
{{ Form::select('tags', trans('product::attributes.tags'), $errors, $tags, $product, ['class' => 'selectize prevent-creation', 'multiple' => true]) }}
{{ Form::checkbox('is_virtual', trans('product::attributes.is_virtual'), trans('product::products.form.the_product_won\'t_be_shipped'), $errors, $product) }}
{{ Form::checkbox('is_active', trans('product::attributes.is_active'), trans('product::products.form.enable_the_product'), $errors, $product, ['checked' => true]) }}
</div>
</div>

View File

@@ -0,0 +1,13 @@
@include('media::admin.image_picker.single', [
'title' => trans('product::products.form.base_image'),
'inputName' => 'files[base_image]',
'file' => $product->base_image,
])
<div class="media-picker-divider"></div>
@include('media::admin.image_picker.multiple', [
'title' => trans('product::products.form.additional_images'),
'inputName' => 'files[additional_images][]',
'files' => $product->additional_images,
])

View File

@@ -0,0 +1,12 @@
<div class="row">
<div class="col-md-8">
{{ Form::text('sku', trans('product::attributes.sku'), $errors, $product) }}
{{ Form::select('manage_stock', trans('product::attributes.manage_stock'), $errors, trans('product::products.form.manage_stock_states'), $product) }}
<div class="{{ old('manage_stock', $product->manage_stock) ? '' : 'hide' }}" id="qty-field">
{{ Form::number('qty', trans('product::attributes.qty'), $errors, $product, ['required' => true]) }}
</div>
{{ Form::select('in_stock', trans('product::attributes.in_stock'), $errors, trans('product::products.form.stock_availability_states'), $product) }}
</div>
</div>

View File

@@ -0,0 +1,9 @@
<div class="row">
<div class="col-md-8">
{{ Form::number('price', trans('product::attributes.price'), $errors, $product, ['min' => 0, 'required' => true]) }}
{{ Form::number('special_price', trans('product::attributes.special_price'), $errors, $product, ['min' => 0]) }}
{{ Form::select('special_price_type', trans('product::attributes.special_price_type'), $errors, trans('product::products.form.price_types'), $product) }}
{{ Form::text('special_price_start', trans('product::attributes.special_price_start'), $errors, $product, ['class' => 'datetime-picker']) }}
{{ Form::text('special_price_end', trans('product::attributes.special_price_end'), $errors, $product, ['class' => 'datetime-picker']) }}
</div>
</div>

View File

@@ -0,0 +1,36 @@
@component('admin::components.table')
@slot('thead')
@include('product::admin.products.partials.thead')
@endslot
@endcomponent
@push('scripts')
<script>
@if ($name === 'related_products')
DataTable.setSelectedIds('#related_products .table', {!! old_json('related_products', $product->relatedProductList(), JSON_NUMERIC_CHECK) !!});
@elseif ($name === 'up_sells')
DataTable.setSelectedIds('#up_sells .table', {!! old_json('up_sells', $product->upSellProductList(), JSON_NUMERIC_CHECK) !!});
@elseif ($name === 'cross_sells')
DataTable.setSelectedIds('#cross_sells .table', {!! old_json('cross_sells', $product->crossSellProductList(), JSON_NUMERIC_CHECK) !!});
@endif
DataTable.setRoutes('#{{ $name }} .table', {
index: { name: 'admin.products.index', params: { except: {!! $product->id ?? "''" !!} } },
edit: 'admin.products.edit',
destroy: 'admin.products.destroy',
});
new DataTable('#{{ $name }} .table', {
pageLength: 10,
columns: [
{ data: 'checkbox', orderable: false, searchable: false, width: '3%' },
{ data: 'id', width: '5%' },
{ data: 'thumbnail', orderable: false, searchable: false, width: '10%' },
{ data: 'name', name: 'translations.name', orderable: false, defaultContent: '' },
{ data: 'price', searchable: false },
{ data: 'status', name: 'is_active', searchable: false },
{ data: 'created', name: 'created_at' },
],
});
</script>
@endpush

View File

@@ -0,0 +1,5 @@
<div class="row">
<div class="col-md-8">
@include('meta::admin.meta_fields', ['entity' => $product])
</div>
</div>

View File

@@ -0,0 +1,49 @@
<script type="text/html" id="product-download-template">
<tr>
<td class="text-center">
<span class="drag-icon">
<i class="fa">&#xf142;</i>
<i class="fa">&#xf142;</i>
</span>
</td>
<td>
<div class="form-group">
<label class="visible-xs">
{{ trans('product::products.form.file') }}
</label>
<div class="choose-file-group">
<input
type="text"
value="<%- download.filename %>"
class="form-control download-name"
readonly
>
<span class="btn btn-default btn-choose-file">
{{ trans('product::products.form.choose') }}
</span>
<input
type="hidden"
name="files[downloads][]"
value="<%- download.id %>"
class="download-file"
>
</div>
</div>
</td>
<td class="text-center">
<button
type="button"
class="btn btn-default delete-row"
data-toggle="tooltip"
data-title="{{ trans('product::products.form.delete_file') }}"
>
<i class="fa fa-trash"></i>
</button>
</td>
</tr>
</script>