first upload all files
This commit is contained in:
180
Modules/Category/Resources/assets/admin/js/CategoryForm.js
Normal file
180
Modules/Category/Resources/assets/admin/js/CategoryForm.js
Normal file
@@ -0,0 +1,180 @@
|
||||
import CategoryTree from './CategoryTree';
|
||||
|
||||
export default class {
|
||||
constructor() {
|
||||
let tree = $('.category-tree');
|
||||
|
||||
new CategoryTree(this, tree);
|
||||
|
||||
this.collapseAll(tree);
|
||||
this.expandAll(tree);
|
||||
this.addRootCategory();
|
||||
this.addSubCategory();
|
||||
|
||||
$('#category-form').on('submit', this.submit);
|
||||
|
||||
window.admin.removeSubmitButtonOffsetOn('#image', '.category-details-tab li > a');
|
||||
}
|
||||
|
||||
collapseAll(tree) {
|
||||
$('.collapse-all').on('click', (e) => {
|
||||
e.preventDefault();
|
||||
|
||||
tree.jstree('close_all');
|
||||
});
|
||||
}
|
||||
|
||||
expandAll(tree) {
|
||||
$('.expand-all').on('click', (e) => {
|
||||
e.preventDefault();
|
||||
|
||||
tree.jstree('open_all');
|
||||
});
|
||||
}
|
||||
|
||||
addRootCategory() {
|
||||
$('.add-root-category').on('click', () => {
|
||||
this.loading(true);
|
||||
|
||||
$('.add-sub-category').addClass('disabled');
|
||||
|
||||
$('.category-tree').jstree('deselect_all');
|
||||
|
||||
this.clear();
|
||||
|
||||
// Intentionally delay 150ms so that user feel new form is loaded.
|
||||
setTimeout(this.loading, 150, false);
|
||||
});
|
||||
}
|
||||
|
||||
addSubCategory() {
|
||||
$('.add-sub-category').on('click', () => {
|
||||
let selectedId = $('.category-tree').jstree('get_selected')[0];
|
||||
|
||||
if (selectedId === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.clear();
|
||||
this.loading(true);
|
||||
|
||||
window.form.appendHiddenInput('#category-form', 'parent_id', selectedId);
|
||||
|
||||
// Intentionally delay 150ms so that user feel new form is loaded.
|
||||
setTimeout(this.loading, 150, false);
|
||||
});
|
||||
}
|
||||
|
||||
fetchCategory(id) {
|
||||
this.loading(true);
|
||||
|
||||
$('.add-sub-category').removeClass('disabled');
|
||||
|
||||
$.ajax({
|
||||
type: 'GET',
|
||||
url: route('admin.categories.show', id),
|
||||
success: (category) => {
|
||||
this.update(category);
|
||||
|
||||
this.loading(false);
|
||||
},
|
||||
error: (xhr) => {
|
||||
error(xhr.responseJSON.message);
|
||||
|
||||
this.loading(false);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
update(category) {
|
||||
window.form.removeErrors();
|
||||
|
||||
$('.btn-delete').removeClass('hide');
|
||||
$('.form-group .help-block').remove();
|
||||
|
||||
$('#confirmation-form').attr('action', route('admin.categories.destroy', category.id));
|
||||
|
||||
$('#id-field').removeClass('hide');
|
||||
|
||||
$('#id').val(category.id);
|
||||
$('#name').val(category.name);
|
||||
|
||||
$('#slug').val(category.slug);
|
||||
$('#slug-field').removeClass('hide');
|
||||
$('.category-details-tab .seo-tab').removeClass('hide');
|
||||
|
||||
$('#is_searchable').prop('checked', category.is_searchable);
|
||||
$('#is_active').prop('checked', category.is_active);
|
||||
|
||||
$('.logo .image-holder-wrapper').html(this.categoryImage('logo', category.logo));
|
||||
$('.banner .image-holder-wrapper').html(this.categoryImage('banner', category.banner));
|
||||
|
||||
$('#category-form input[name="parent_id"]').remove();
|
||||
}
|
||||
|
||||
categoryImage(fieldName, file) {
|
||||
if (! file.exists) {
|
||||
return this.imagePlaceholder();
|
||||
}
|
||||
|
||||
return `
|
||||
<div class="image-holder">
|
||||
<img src="${file.path}">
|
||||
<button type="button" class="btn remove-image" data-input-name="files[${fieldName}]"></button>
|
||||
<input type="hidden" name="files[${fieldName}]" value="${file.id}">
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
clear() {
|
||||
$('#id-field').addClass('hide');
|
||||
|
||||
$('#id').val('');
|
||||
$('#name').val('');
|
||||
|
||||
$('#slug').val('');
|
||||
$('#slug-field').addClass('hide');
|
||||
$('.category-details-tab .seo-tab').addClass('hide');
|
||||
|
||||
$('#is_searchable').prop('checked', false);
|
||||
$('#is_active').prop('checked', false);
|
||||
|
||||
$('.logo .image-holder-wrapper').html(this.imagePlaceholder());
|
||||
$('.banner .image-holder-wrapper').html(this.imagePlaceholder());
|
||||
|
||||
$('.btn-delete').addClass('hide');
|
||||
$('.form-group .help-block').remove();
|
||||
|
||||
$('#category-form input[name="parent_id"]').remove();
|
||||
|
||||
$('.general-information-tab a').click();
|
||||
}
|
||||
|
||||
imagePlaceholder() {
|
||||
return `
|
||||
<div class="image-holder placeholder">
|
||||
<i class="fa fa-picture-o"></i>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
loading(state) {
|
||||
if (state === true) {
|
||||
$('.overlay.loader').removeClass('hide');
|
||||
} else {
|
||||
$('.overlay.loader').addClass('hide');
|
||||
}
|
||||
}
|
||||
|
||||
submit(e) {
|
||||
let selectedId = $('.category-tree').jstree('get_selected')[0];
|
||||
|
||||
if (! $('#slug-field').hasClass('hide')) {
|
||||
window.form.appendHiddenInput('#category-form', '_method', 'put');
|
||||
|
||||
$('#category-form').attr('action', route('admin.categories.update', selectedId));
|
||||
}
|
||||
|
||||
e.currentTarget.submit();
|
||||
}
|
||||
}
|
||||
73
Modules/Category/Resources/assets/admin/js/CategoryTree.js
Normal file
73
Modules/Category/Resources/assets/admin/js/CategoryTree.js
Normal file
@@ -0,0 +1,73 @@
|
||||
export default class {
|
||||
constructor(categoryForm, selector) {
|
||||
this.selector = selector;
|
||||
|
||||
$.jstree.defaults.dnd.touch = true;
|
||||
$.jstree.defaults.dnd.copy = false;
|
||||
|
||||
this.fetchCategoryTree();
|
||||
|
||||
// On selecting a category.
|
||||
selector.on('select_node.jstree', (e, node) => categoryForm.fetchCategory(node.selected[0]));
|
||||
|
||||
// Expand categories when jstree is loaded.
|
||||
selector.on('loaded.jstree', () => selector.jstree('open_all'));
|
||||
|
||||
// On updating category tree.
|
||||
this.selector.on('move_node.jstree', (e, data) => {
|
||||
this.updateCategoryTree(data);
|
||||
});
|
||||
}
|
||||
|
||||
fetchCategoryTree() {
|
||||
this.selector.jstree({
|
||||
core: {
|
||||
data: { url: route('admin.categories.tree') },
|
||||
check_callback: true,
|
||||
},
|
||||
plugins: ['dnd'],
|
||||
});
|
||||
}
|
||||
|
||||
updateCategoryTree(data) {
|
||||
this.loading(data.node, true);
|
||||
|
||||
$.ajax({
|
||||
type: 'PUT',
|
||||
url: route('admin.categories.tree.update'),
|
||||
data: { category_tree: this.getCategoryTree() },
|
||||
success: (message) => {
|
||||
success(message);
|
||||
|
||||
this.loading(data.node, false);
|
||||
},
|
||||
error: (xhr) => {
|
||||
error(xhr.responseJSON.message);
|
||||
|
||||
this.loading(data.node, false);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
getCategoryTree() {
|
||||
let categories = this.selector.jstree(true).get_json('#', { flat: true });
|
||||
|
||||
return categories.reduce((formatted, category) => {
|
||||
return formatted.concat({
|
||||
id: category.id,
|
||||
parent_id: (category.parent === '#') ? null : category.parent,
|
||||
position: category.data.position,
|
||||
});
|
||||
}, []);
|
||||
}
|
||||
|
||||
loading(node, state) {
|
||||
let nodeElement = this.selector.jstree().get_node(node, true);
|
||||
|
||||
if (state) {
|
||||
$(nodeElement).addClass('jstree-loading');
|
||||
} else {
|
||||
$(nodeElement).removeClass('jstree-loading');
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Modules/Category/Resources/assets/admin/js/main.js
Normal file
3
Modules/Category/Resources/assets/admin/js/main.js
Normal file
@@ -0,0 +1,3 @@
|
||||
import CategoryForm from './CategoryForm';
|
||||
|
||||
new CategoryForm();
|
||||
37
Modules/Category/Resources/assets/admin/sass/main.scss
Normal file
37
Modules/Category/Resources/assets/admin/sass/main.scss
Normal file
@@ -0,0 +1,37 @@
|
||||
@import '~jstree/dist/themes/default/style';
|
||||
|
||||
.category-tree {
|
||||
margin-left: -10px;
|
||||
}
|
||||
|
||||
.add-root-category {
|
||||
display: table;
|
||||
}
|
||||
|
||||
.add-sub-category {
|
||||
display: table;
|
||||
margin: 5px 0 10px;
|
||||
}
|
||||
|
||||
.rtl {
|
||||
.jstree-default {
|
||||
&.jstree-rtl .jstree-node {
|
||||
background-position: 0% 1px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#category-form .loading-spinner {
|
||||
margin-top: 15px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.category-details-tab {
|
||||
margin: 0 -15px 0 15px;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 991px) {
|
||||
.category-details-tab {
|
||||
margin: 30px 0 0 -15px;
|
||||
}
|
||||
}
|
||||
9
Modules/Category/Resources/lang/en/attributes.php
Normal file
9
Modules/Category/Resources/lang/en/attributes.php
Normal file
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'id' => 'ID',
|
||||
'name' => 'Name',
|
||||
'slug' => 'URL',
|
||||
'is_searchable' => 'Searchable',
|
||||
'is_active' => 'Status',
|
||||
];
|
||||
23
Modules/Category/Resources/lang/en/categories.php
Normal file
23
Modules/Category/Resources/lang/en/categories.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'category' => 'Category',
|
||||
'categories' => 'Categories',
|
||||
'tree' => [
|
||||
'add_root_category' => 'Add Root Category',
|
||||
'add_sub_category' => 'Add Subcategory',
|
||||
'collapse_all' => 'Collapse All',
|
||||
'expand_all' => 'Expand All',
|
||||
],
|
||||
'tabs' => [
|
||||
'general' => 'General',
|
||||
'image' => 'Image',
|
||||
'seo' => 'SEO',
|
||||
],
|
||||
'form' => [
|
||||
'show_this_category_in_search_box' => 'Show this category in search box category list',
|
||||
'enable_the_category' => 'Enable the category',
|
||||
'logo' => 'Logo',
|
||||
'banner' => 'Banner',
|
||||
],
|
||||
];
|
||||
5
Modules/Category/Resources/lang/en/messages.php
Normal file
5
Modules/Category/Resources/lang/en/messages.php
Normal file
@@ -0,0 +1,5 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'category_order_saved' => 'Category order has been saved.',
|
||||
];
|
||||
8
Modules/Category/Resources/lang/en/permissions.php
Normal file
8
Modules/Category/Resources/lang/en/permissions.php
Normal file
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'index' => 'Index Categories',
|
||||
'create' => 'Create Categories',
|
||||
'edit' => 'Edit Categories',
|
||||
'destroy' => 'Delete Categories',
|
||||
];
|
||||
5
Modules/Category/Resources/lang/en/sidebar.php
Normal file
5
Modules/Category/Resources/lang/en/sidebar.php
Normal file
@@ -0,0 +1,5 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'categories' => 'Categories',
|
||||
];
|
||||
@@ -0,0 +1,107 @@
|
||||
@extends('admin::layout')
|
||||
|
||||
@component('admin::components.page.header')
|
||||
@slot('title', trans('category::categories.categories'))
|
||||
|
||||
<li class="active">{{ trans('category::categories.categories') }}</li>
|
||||
@endcomponent
|
||||
|
||||
@section('content')
|
||||
<div class="box box-default">
|
||||
<div class="box-body clearfix">
|
||||
<div class="col-lg-2 col-md-3">
|
||||
<div class="row">
|
||||
<button class="btn btn-default add-root-category">{{ trans('category::categories.tree.add_root_category') }}</button>
|
||||
<button class="btn btn-default add-sub-category disabled">{{ trans('category::categories.tree.add_sub_category') }}</button>
|
||||
|
||||
<div class="m-b-10">
|
||||
<a href="#" class="collapse-all">{{ trans('category::categories.tree.collapse_all') }}</a> |
|
||||
<a href="#" class="expand-all">{{ trans('category::categories.tree.expand_all') }}</a>
|
||||
</div>
|
||||
|
||||
<div class="category-tree"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-10 col-md-9">
|
||||
<div class="tab-wrapper category-details-tab">
|
||||
<ul class="nav nav-tabs">
|
||||
<li class="general-information-tab active"><a data-toggle="tab" href="#general-information">{{ trans('category::categories.tabs.general') }}</a></li>
|
||||
|
||||
@hasAccess('admin.media.index')
|
||||
<li class="image-tab"><a data-toggle="tab" href="#image">{{ trans('category::categories.tabs.image') }}</a></li>
|
||||
@endHasAccess
|
||||
|
||||
<li class="seo-tab hide"><a data-toggle="tab" href="#seo">{{ trans('category::categories.tabs.seo') }}</a></li>
|
||||
</ul>
|
||||
|
||||
<form method="POST" action="{{ route('admin.categories.store') }}" class="form-horizontal" id="category-form" novalidate>
|
||||
{{ csrf_field() }}
|
||||
|
||||
<div class="tab-content">
|
||||
<div id="general-information" class="tab-pane fade in active">
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<div id="id-field" class="hide">
|
||||
{{ Form::text('id', trans('category::attributes.id'), $errors, null, ['disabled' => true]) }}
|
||||
</div>
|
||||
|
||||
{{ Form::text('name', trans('category::attributes.name'), $errors, null, ['required' => true]) }}
|
||||
{{ Form::checkbox('is_searchable', trans('category::attributes.is_searchable'), trans('category::categories.form.show_this_category_in_search_box'), $errors) }}
|
||||
{{ Form::checkbox('is_active', trans('category::attributes.is_active'), trans('category::categories.form.enable_the_category'), $errors) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if (auth()->user()->hasAccess('admin.media.index'))
|
||||
<div id="image" class="tab-pane fade">
|
||||
<div class="logo">
|
||||
@include('media::admin.image_picker.single', [
|
||||
'title' => trans('category::categories.form.logo'),
|
||||
'inputName' => 'files[logo]',
|
||||
'file' => (object) ['exists' => false],
|
||||
])
|
||||
</div>
|
||||
|
||||
<div class="banner">
|
||||
@include('media::admin.image_picker.single', [
|
||||
'title' => trans('category::categories.form.banner'),
|
||||
'inputName' => 'files[banner]',
|
||||
'file' => (object) ['exists' => false],
|
||||
])
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div id="seo" class="tab-pane fade">
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<div class="hide" id="slug-field">
|
||||
{{ Form::text('slug', trans('category::attributes.slug'), $errors) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="col-md-offset-2 col-md-10">
|
||||
<button type="submit" class="btn btn-primary" data-loading>
|
||||
{{ trans('admin::admin.buttons.save') }}
|
||||
</button>
|
||||
|
||||
<button type="button" class="btn btn-link text-red btn-delete p-l-0 hide" data-confirm>
|
||||
{{ trans('admin::admin.buttons.delete') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="overlay loader hide">
|
||||
<i class="fa fa-refresh fa-spin"></i>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
Reference in New Issue
Block a user