Egorka
7 years ago
41 changed files with 2225 additions and 5 deletions
@ -0,0 +1,32 @@
|
||||
<?php |
||||
/** |
||||
* Created by Error202 |
||||
* Date: 11.07.2018 |
||||
*/ |
||||
|
||||
namespace backend\components\menu\assets; |
||||
|
||||
|
||||
use yii\web\AssetBundle; |
||||
|
||||
class MenuAsset extends AssetBundle |
||||
{ |
||||
public $sourcePath = '@backend/components/menu'; |
||||
public $css = [ |
||||
'css/menu.css', |
||||
]; |
||||
|
||||
public $js = [ |
||||
'js/jquery.nestable.js', |
||||
'js/menu.js' |
||||
]; |
||||
|
||||
public $depends = [ |
||||
'yii\web\YiiAsset', |
||||
'yii\bootstrap\BootstrapPluginAsset', |
||||
]; |
||||
|
||||
public $publishOptions = [ |
||||
'forceCopy' => YII_ENV_DEV ? true : false, |
||||
]; |
||||
} |
File diff suppressed because one or more lines are too long
@ -0,0 +1,196 @@
|
||||
/*.cf:after { visibility: hidden; display: block; font-size: 0; content: " "; clear: both; height: 0; } |
||||
* html .cf { zoom: 1; } |
||||
*:first-child+html .cf { zoom: 1; } |
||||
|
||||
html { margin: 0; padding: 0; } |
||||
body { font-size: 100%; margin: 0; padding: 1.75em; font-family: 'Helvetica Neue', Arial, sans-serif; } |
||||
|
||||
h1 { font-size: 1.75em; margin: 0 0 0.6em 0; } |
||||
|
||||
a { color: #2996cc; } |
||||
a:hover { text-decoration: none; } |
||||
|
||||
p { line-height: 1.5em; } |
||||
.small { color: #666; font-size: 0.875em; } |
||||
.large { font-size: 1.25em; }*/ |
||||
|
||||
/** |
||||
* Nestable |
||||
*/ |
||||
|
||||
.dd { position: relative; display: block; margin: 0; padding: 0; max-width: 600px; list-style: none; font-size: 13px; line-height: 20px; } |
||||
|
||||
.dd-list { display: block; position: relative; margin: 0; padding: 0; list-style: none; } |
||||
|
||||
.dd-list .dd-list { |
||||
padding-left: 30px; |
||||
} |
||||
|
||||
.dd-collapsed .dd-list { |
||||
display: none; |
||||
} |
||||
|
||||
.dd-item, |
||||
.dd-empty, |
||||
.dd-placeholder { |
||||
display: block; |
||||
position: relative; |
||||
margin: 0; padding: 1px; |
||||
min-height: 20px; |
||||
font-size: 13px; |
||||
line-height: 10px; |
||||
} |
||||
|
||||
.dd-handle { |
||||
display: block; |
||||
height: 100%; |
||||
margin: 5px 0; |
||||
padding: 5px 10px; |
||||
color: #333; |
||||
text-decoration: none; |
||||
font-weight: bold; |
||||
/*border: 1px solid #ccc;*/ |
||||
background: #fafafa; |
||||
background: -webkit-linear-gradient(top, #fafafa 0%, #eee 100%); |
||||
background: -moz-linear-gradient(top, #fafafa 0%, #eee 100%); |
||||
background: linear-gradient(top, #fafafa 0%, #eee 100%); |
||||
-webkit-border-radius: 3px; |
||||
border-radius: 3px; |
||||
box-sizing: border-box; |
||||
-moz-box-sizing: border-box; |
||||
} |
||||
.dd-handle:hover { color: #2ea8e5; background: #fff; } |
||||
|
||||
.dd-item > button { |
||||
display: block; |
||||
position: relative; |
||||
cursor: pointer; |
||||
float: left; |
||||
width: 25px; height: 30px; |
||||
margin: 9px 0; padding: 0; |
||||
text-indent: 100%; |
||||
white-space: nowrap; |
||||
overflow: hidden; |
||||
border: 0; |
||||
background: transparent; |
||||
font-size: 20px; |
||||
line-height: 1; |
||||
text-align: center; |
||||
font-weight: bold; |
||||
z-index: 5; |
||||
color: #999; |
||||
} |
||||
.dd-item > button:before { |
||||
content: '+'; |
||||
display: block; |
||||
position: absolute; |
||||
width: 100%; |
||||
text-align: center; |
||||
text-indent: 0; |
||||
} |
||||
.dd-item > button[data-action="collapse"]:before { content: '-'; } |
||||
|
||||
.dd-placeholder, |
||||
.dd-empty { |
||||
margin: 5px 0; |
||||
padding: 0; |
||||
min-height: 30px; |
||||
background: #f2fbff; |
||||
border: 1px dashed #b6bcbf; |
||||
box-sizing: border-box; |
||||
-moz-box-sizing: border-box; |
||||
} |
||||
.dd-empty { |
||||
border: 1px dashed #bbb; |
||||
min-height: 100px; |
||||
background-color: #e5e5e5; |
||||
background-image: -webkit-linear-gradient(45deg, #fff 25%, transparent 25%, transparent 75%, #fff 75%, #fff), |
||||
-webkit-linear-gradient(45deg, #fff 25%, transparent 25%, transparent 75%, #fff 75%, #fff); |
||||
background-image: -moz-linear-gradient(45deg, #fff 25%, transparent 25%, transparent 75%, #fff 75%, #fff), |
||||
-moz-linear-gradient(45deg, #fff 25%, transparent 25%, transparent 75%, #fff 75%, #fff); |
||||
background-image: linear-gradient(45deg, #fff 25%, transparent 25%, transparent 75%, #fff 75%, #fff), |
||||
linear-gradient(45deg, #fff 25%, transparent 25%, transparent 75%, #fff 75%, #fff); |
||||
background-size: 60px 60px; |
||||
background-position: 0 0, 30px 30px; |
||||
} |
||||
|
||||
.dd-dragel { position: absolute; pointer-events: none; z-index: 9999; } |
||||
.dd-dragel > .dd-item .dd-handle { margin-top: 0; } |
||||
.dd-dragel .dd-handle { |
||||
-webkit-box-shadow: 2px 4px 6px 0 rgba(0,0,0,.1); |
||||
box-shadow: 2px 4px 6px 0 rgba(0,0,0,.1); |
||||
} |
||||
|
||||
|
||||
|
||||
|
||||
@media only screen and (min-width: 700px) { |
||||
|
||||
.dd { float: left; width: 48%; } |
||||
.dd + .dd { margin-left: 2%; } |
||||
|
||||
} |
||||
|
||||
.dd-hover > .dd-handle { background: #2ea8e5 !important; } |
||||
|
||||
/** |
||||
* Nestable Draggable Handles |
||||
*/ |
||||
|
||||
.dd3-content { |
||||
display: block; |
||||
margin: 5px 0; |
||||
padding: 0; |
||||
color: #333; |
||||
text-decoration: none; |
||||
font-weight: bold; |
||||
background: #fafafa; |
||||
background: -webkit-linear-gradient(top, #fafafa 0%, #eee 100%); |
||||
background: -moz-linear-gradient(top, #fafafa 0%, #eee 100%); |
||||
background: linear-gradient(top, #fafafa 0%, #eee 100%); |
||||
-webkit-border-radius: 3px; |
||||
border-radius: 3px; |
||||
box-sizing: border-box; -moz-box-sizing: border-box; |
||||
} |
||||
.dd3-content:hover { |
||||
color: #2ea8e5; |
||||
background: #fff; |
||||
} |
||||
|
||||
.dd-dragel > .dd3-item > .dd3-content { margin: 0; } |
||||
|
||||
.dd3-item > button { margin-left: 30px; } |
||||
|
||||
.dd3-handle { position: absolute; margin: 0; left: 0; top: 0; cursor: pointer; width: 30px; text-indent: 100%; white-space: nowrap; overflow: hidden; |
||||
border: 1px solid #aaa; |
||||
background: #ddd; |
||||
background: -webkit-linear-gradient(top, #ddd 0%, #bbb 100%); |
||||
background: -moz-linear-gradient(top, #ddd 0%, #bbb 100%); |
||||
background: linear-gradient(top, #ddd 0%, #bbb 100%); |
||||
border-top-right-radius: 0; |
||||
border-bottom-right-radius: 0; |
||||
} |
||||
.dd3-handle:before { |
||||
content: "\f047"; |
||||
font-family: FontAwesome; |
||||
display: block; |
||||
position: absolute; |
||||
left: 0; top: 10px; |
||||
width: 100%; |
||||
text-align: center; |
||||
text-indent: 0; |
||||
color: #fff; |
||||
font-size: 15px; |
||||
font-weight: normal; |
||||
} |
||||
.dd3-handle:hover { background: #ddd; } |
||||
|
||||
.panel-group { |
||||
margin-bottom: 0 !important; |
||||
} |
||||
.panel-heading { |
||||
position: relative; |
||||
} |
||||
.panel-heading h4 { |
||||
padding-left: 25px; |
||||
} |
File diff suppressed because one or more lines are too long
@ -0,0 +1,484 @@
|
||||
/*! |
||||
* Nestable jQuery Plugin - Copyright (c) 2012 David Bushell - http://dbushell.com/
|
||||
* Dual-licensed under the BSD or MIT licenses |
||||
*/ |
||||
;(function($, window, document, undefined) |
||||
{ |
||||
var hasTouch = 'ontouchstart' in document; |
||||
|
||||
/** |
||||
* Detect CSS pointer-events property |
||||
* events are normally disabled on the dragging element to avoid conflicts |
||||
* https://github.com/ausi/Feature-detection-technique-for-pointer-events/blob/master/modernizr-pointerevents.js
|
||||
*/ |
||||
var hasPointerEvents = (function() |
||||
{ |
||||
var el = document.createElement('div'), |
||||
docEl = document.documentElement; |
||||
if (!('pointerEvents' in el.style)) { |
||||
return false; |
||||
} |
||||
el.style.pointerEvents = 'auto'; |
||||
el.style.pointerEvents = 'x'; |
||||
docEl.appendChild(el); |
||||
var supports = window.getComputedStyle && window.getComputedStyle(el, '').pointerEvents === 'auto'; |
||||
docEl.removeChild(el); |
||||
return !!supports; |
||||
})(); |
||||
|
||||
var defaults = { |
||||
listNodeName : 'ol', |
||||
itemNodeName : 'li', |
||||
rootClass : 'dd', |
||||
listClass : 'dd-list', |
||||
itemClass : 'dd-item', |
||||
dragClass : 'dd-dragel', |
||||
handleClass : 'dd-handle', |
||||
collapsedClass : 'dd-collapsed', |
||||
placeClass : 'dd-placeholder', |
||||
noDragClass : 'dd-nodrag', |
||||
emptyClass : 'dd-empty', |
||||
expandBtnHTML : '<button data-action="expand" type="button">Expand</button>', |
||||
collapseBtnHTML : '<button data-action="collapse" type="button">Collapse</button>', |
||||
group : 0, |
||||
maxDepth : 5, |
||||
threshold : 20 |
||||
}; |
||||
|
||||
function Plugin(element, options) |
||||
{ |
||||
this.w = $(document); |
||||
this.el = $(element); |
||||
this.options = $.extend({}, defaults, options); |
||||
this.init(); |
||||
} |
||||
|
||||
Plugin.prototype = { |
||||
|
||||
init: function() |
||||
{ |
||||
var list = this; |
||||
|
||||
list.reset(); |
||||
|
||||
list.el.data('nestable-group', this.options.group); |
||||
|
||||
list.placeEl = $('<div class="' + list.options.placeClass + '"/>'); |
||||
|
||||
$.each(this.el.find(list.options.itemNodeName), function(k, el) { |
||||
list.setParent($(el)); |
||||
}); |
||||
|
||||
list.el.on('click', 'button', function(e) { |
||||
if (list.dragEl) { |
||||
return; |
||||
} |
||||
var target = $(e.currentTarget), |
||||
action = target.data('action'), |
||||
item = target.parent(list.options.itemNodeName); |
||||
if (action === 'collapse') { |
||||
list.collapseItem(item); |
||||
} |
||||
if (action === 'expand') { |
||||
list.expandItem(item); |
||||
} |
||||
}); |
||||
|
||||
var onStartEvent = function(e) |
||||
{ |
||||
var handle = $(e.target); |
||||
if (!handle.hasClass(list.options.handleClass)) { |
||||
if (handle.closest('.' + list.options.noDragClass).length) { |
||||
return; |
||||
} |
||||
handle = handle.closest('.' + list.options.handleClass); |
||||
} |
||||
|
||||
if (!handle.length || list.dragEl) { |
||||
return; |
||||
} |
||||
|
||||
list.isTouch = /^touch/.test(e.type); |
||||
if (list.isTouch && e.touches.length !== 1) { |
||||
return; |
||||
} |
||||
|
||||
e.preventDefault(); |
||||
list.dragStart(e.touches ? e.touches[0] : e); |
||||
}; |
||||
|
||||
var onMoveEvent = function(e) |
||||
{ |
||||
if (list.dragEl) { |
||||
e.preventDefault(); |
||||
list.dragMove(e.touches ? e.touches[0] : e); |
||||
} |
||||
}; |
||||
|
||||
var onEndEvent = function(e) |
||||
{ |
||||
if (list.dragEl) { |
||||
e.preventDefault(); |
||||
list.dragStop(e.touches ? e.touches[0] : e); |
||||
} |
||||
}; |
||||
|
||||
if (hasTouch) { |
||||
list.el[0].addEventListener('touchstart', onStartEvent, false); |
||||
window.addEventListener('touchmove', onMoveEvent, false); |
||||
window.addEventListener('touchend', onEndEvent, false); |
||||
window.addEventListener('touchcancel', onEndEvent, false); |
||||
} |
||||
|
||||
list.el.on('mousedown', onStartEvent); |
||||
list.w.on('mousemove', onMoveEvent); |
||||
list.w.on('mouseup', onEndEvent); |
||||
|
||||
}, |
||||
|
||||
serialize: function() |
||||
{ |
||||
var data, |
||||
depth = 0, |
||||
list = this; |
||||
step = function(level, depth) |
||||
{ |
||||
var array = [ ], |
||||
items = level.children(list.options.itemNodeName); |
||||
items.each(function() |
||||
{ |
||||
var li = $(this), |
||||
item = $.extend({}, li.data()), |
||||
sub = li.children(list.options.listNodeName); |
||||
if (sub.length) { |
||||
item.children = step(sub, depth + 1); |
||||
} |
||||
array.push(item); |
||||
}); |
||||
return array; |
||||
}; |
||||
data = step(list.el.find(list.options.listNodeName).first(), depth); |
||||
return data; |
||||
}, |
||||
|
||||
serialise: function() |
||||
{ |
||||
return this.serialize(); |
||||
}, |
||||
|
||||
reset: function() |
||||
{ |
||||
this.mouse = { |
||||
offsetX : 0, |
||||
offsetY : 0, |
||||
startX : 0, |
||||
startY : 0, |
||||
lastX : 0, |
||||
lastY : 0, |
||||
nowX : 0, |
||||
nowY : 0, |
||||
distX : 0, |
||||
distY : 0, |
||||
dirAx : 0, |
||||
dirX : 0, |
||||
dirY : 0, |
||||
lastDirX : 0, |
||||
lastDirY : 0, |
||||
distAxX : 0, |
||||
distAxY : 0 |
||||
}; |
||||
this.isTouch = false; |
||||
this.moving = false; |
||||
this.dragEl = null; |
||||
this.dragRootEl = null; |
||||
this.dragDepth = 0; |
||||
this.hasNewRoot = false; |
||||
this.pointEl = null; |
||||
}, |
||||
|
||||
expandItem: function(li) |
||||
{ |
||||
li.removeClass(this.options.collapsedClass); |
||||
li.children('[data-action="expand"]').hide(); |
||||
li.children('[data-action="collapse"]').show(); |
||||
li.children(this.options.listNodeName).show(); |
||||
}, |
||||
|
||||
collapseItem: function(li) |
||||
{ |
||||
var lists = li.children(this.options.listNodeName); |
||||
if (lists.length) { |
||||
li.addClass(this.options.collapsedClass); |
||||
li.children('[data-action="collapse"]').hide(); |
||||
li.children('[data-action="expand"]').show(); |
||||
li.children(this.options.listNodeName).hide(); |
||||
} |
||||
}, |
||||
|
||||
expandAll: function() |
||||
{ |
||||
var list = this; |
||||
list.el.find(list.options.itemNodeName).each(function() { |
||||
list.expandItem($(this)); |
||||
}); |
||||
}, |
||||
|
||||
collapseAll: function() |
||||
{ |
||||
var list = this; |
||||
list.el.find(list.options.itemNodeName).each(function() { |
||||
list.collapseItem($(this)); |
||||
}); |
||||
}, |
||||
|
||||
setParent: function(li) |
||||
{ |
||||
if (li.children(this.options.listNodeName).length) { |
||||
li.prepend($(this.options.expandBtnHTML)); |
||||
li.prepend($(this.options.collapseBtnHTML)); |
||||
} |
||||
li.children('[data-action="expand"]').hide(); |
||||
}, |
||||
|
||||
unsetParent: function(li) |
||||
{ |
||||
li.removeClass(this.options.collapsedClass); |
||||
li.children('[data-action]').remove(); |
||||
li.children(this.options.listNodeName).remove(); |
||||
}, |
||||
|
||||
dragStart: function(e) |
||||
{ |
||||
var mouse = this.mouse, |
||||
target = $(e.target), |
||||
dragItem = target.closest(this.options.itemNodeName); |
||||
|
||||
this.placeEl.css('height', dragItem.height()); |
||||
|
||||
mouse.offsetX = e.offsetX !== undefined ? e.offsetX : e.pageX - target.offset().left; |
||||
mouse.offsetY = e.offsetY !== undefined ? e.offsetY : e.pageY - target.offset().top; |
||||
mouse.startX = mouse.lastX = e.pageX; |
||||
mouse.startY = mouse.lastY = e.pageY; |
||||
|
||||
this.dragRootEl = this.el; |
||||
|
||||
this.dragEl = $(document.createElement(this.options.listNodeName)).addClass(this.options.listClass + ' ' + this.options.dragClass); |
||||
this.dragEl.css('width', dragItem.width()); |
||||
|
||||
dragItem.after(this.placeEl); |
||||
dragItem[0].parentNode.removeChild(dragItem[0]); |
||||
dragItem.appendTo(this.dragEl); |
||||
|
||||
$(document.body).append(this.dragEl); |
||||
this.dragEl.css({ |
||||
'left' : e.pageX - mouse.offsetX, |
||||
'top' : e.pageY - mouse.offsetY |
||||
}); |
||||
// total depth of dragging item
|
||||
var i, depth, |
||||
items = this.dragEl.find(this.options.itemNodeName); |
||||
for (i = 0; i < items.length; i++) { |
||||
depth = $(items[i]).parents(this.options.listNodeName).length; |
||||
if (depth > this.dragDepth) { |
||||
this.dragDepth = depth; |
||||
} |
||||
} |
||||
}, |
||||
|
||||
dragStop: function(e) |
||||
{ |
||||
var el = this.dragEl.children(this.options.itemNodeName).first(); |
||||
el[0].parentNode.removeChild(el[0]); |
||||
this.placeEl.replaceWith(el); |
||||
|
||||
this.dragEl.remove(); |
||||
this.el.trigger('change'); |
||||
if (this.hasNewRoot) { |
||||
this.dragRootEl.trigger('change'); |
||||
} |
||||
this.reset(); |
||||
}, |
||||
|
||||
dragMove: function(e) |
||||
{ |
||||
var list, parent, prev, next, depth, |
||||
opt = this.options, |
||||
mouse = this.mouse; |
||||
|
||||
this.dragEl.css({ |
||||
'left' : e.pageX - mouse.offsetX, |
||||
'top' : e.pageY - mouse.offsetY |
||||
}); |
||||
|
||||
// mouse position last events
|
||||
mouse.lastX = mouse.nowX; |
||||
mouse.lastY = mouse.nowY; |
||||
// mouse position this events
|
||||
mouse.nowX = e.pageX; |
||||
mouse.nowY = e.pageY; |
||||
// distance mouse moved between events
|
||||
mouse.distX = mouse.nowX - mouse.lastX; |
||||
mouse.distY = mouse.nowY - mouse.lastY; |
||||
// direction mouse was moving
|
||||
mouse.lastDirX = mouse.dirX; |
||||
mouse.lastDirY = mouse.dirY; |
||||
// direction mouse is now moving (on both axis)
|
||||
mouse.dirX = mouse.distX === 0 ? 0 : mouse.distX > 0 ? 1 : -1; |
||||
mouse.dirY = mouse.distY === 0 ? 0 : mouse.distY > 0 ? 1 : -1; |
||||
// axis mouse is now moving on
|
||||
var newAx = Math.abs(mouse.distX) > Math.abs(mouse.distY) ? 1 : 0; |
||||
|
||||
// do nothing on first move
|
||||
if (!mouse.moving) { |
||||
mouse.dirAx = newAx; |
||||
mouse.moving = true; |
||||
return; |
||||
} |
||||
|
||||
// calc distance moved on this axis (and direction)
|
||||
if (mouse.dirAx !== newAx) { |
||||
mouse.distAxX = 0; |
||||
mouse.distAxY = 0; |
||||
} else { |
||||
mouse.distAxX += Math.abs(mouse.distX); |
||||
if (mouse.dirX !== 0 && mouse.dirX !== mouse.lastDirX) { |
||||
mouse.distAxX = 0; |
||||
} |
||||
mouse.distAxY += Math.abs(mouse.distY); |
||||
if (mouse.dirY !== 0 && mouse.dirY !== mouse.lastDirY) { |
||||
mouse.distAxY = 0; |
||||
} |
||||
} |
||||
mouse.dirAx = newAx; |
||||
|
||||
/** |
||||
* move horizontal |
||||
*/ |
||||
if (mouse.dirAx && mouse.distAxX >= opt.threshold) { |
||||
// reset move distance on x-axis for new phase
|
||||
mouse.distAxX = 0; |
||||
prev = this.placeEl.prev(opt.itemNodeName); |
||||
// increase horizontal level if previous sibling exists and is not collapsed
|
||||
if (mouse.distX > 0 && prev.length && !prev.hasClass(opt.collapsedClass)) { |
||||
// cannot increase level when item above is collapsed
|
||||
list = prev.find(opt.listNodeName).last(); |
||||
// check if depth limit has reached
|
||||
depth = this.placeEl.parents(opt.listNodeName).length; |
||||
if (depth + this.dragDepth <= opt.maxDepth) { |
||||
// create new sub-level if one doesn't exist
|
||||
if (!list.length) { |
||||
list = $('<' + opt.listNodeName + '/>').addClass(opt.listClass); |
||||
list.append(this.placeEl); |
||||
prev.append(list); |
||||
this.setParent(prev); |
||||
} else { |
||||
// else append to next level up
|
||||
list = prev.children(opt.listNodeName).last(); |
||||
list.append(this.placeEl); |
||||
} |
||||
} |
||||
} |
||||
// decrease horizontal level
|
||||
if (mouse.distX < 0) { |
||||
// we can't decrease a level if an item preceeds the current one
|
||||
next = this.placeEl.next(opt.itemNodeName); |
||||
if (!next.length) { |
||||
parent = this.placeEl.parent(); |
||||
this.placeEl.closest(opt.itemNodeName).after(this.placeEl); |
||||
if (!parent.children().length) { |
||||
this.unsetParent(parent.parent()); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
var isEmpty = false; |
||||
|
||||
// find list item under cursor
|
||||
if (!hasPointerEvents) { |
||||
this.dragEl[0].style.visibility = 'hidden'; |
||||
} |
||||
this.pointEl = $(document.elementFromPoint(e.pageX - document.body.scrollLeft, e.pageY - (window.pageYOffset || document.documentElement.scrollTop))); |
||||
if (!hasPointerEvents) { |
||||
this.dragEl[0].style.visibility = 'visible'; |
||||
} |
||||
if (this.pointEl.hasClass(opt.handleClass)) { |
||||
this.pointEl = this.pointEl.parent(opt.itemNodeName); |
||||
} |
||||
if (this.pointEl.hasClass(opt.emptyClass)) { |
||||
isEmpty = true; |
||||
} |
||||
else if (!this.pointEl.length || !this.pointEl.hasClass(opt.itemClass)) { |
||||
return; |
||||
} |
||||
|
||||
// find parent list of item under cursor
|
||||
var pointElRoot = this.pointEl.closest('.' + opt.rootClass), |
||||
isNewRoot = this.dragRootEl.data('nestable-id') !== pointElRoot.data('nestable-id'); |
||||
|
||||
/** |
||||
* move vertical |
||||
*/ |
||||
if (!mouse.dirAx || isNewRoot || isEmpty) { |
||||
// check if groups match if dragging over new root
|
||||
if (isNewRoot && opt.group !== pointElRoot.data('nestable-group')) { |
||||
return; |
||||
} |
||||
// check depth limit
|
||||
depth = this.dragDepth - 1 + this.pointEl.parents(opt.listNodeName).length; |
||||
if (depth > opt.maxDepth) { |
||||
return; |
||||
} |
||||
var before = e.pageY < (this.pointEl.offset().top + this.pointEl.height() / 2); |
||||
parent = this.placeEl.parent(); |
||||
// if empty create new list to replace empty placeholder
|
||||
if (isEmpty) { |
||||
list = $(document.createElement(opt.listNodeName)).addClass(opt.listClass); |
||||
list.append(this.placeEl); |
||||
this.pointEl.replaceWith(list); |
||||
} |
||||
else if (before) { |
||||
this.pointEl.before(this.placeEl); |
||||
} |
||||
else { |
||||
this.pointEl.after(this.placeEl); |
||||
} |
||||
if (!parent.children().length) { |
||||
this.unsetParent(parent.parent()); |
||||
} |
||||
if (!this.dragRootEl.find(opt.itemNodeName).length) { |
||||
this.dragRootEl.append('<div class="' + opt.emptyClass + '"/>'); |
||||
} |
||||
// parent root list has changed
|
||||
if (isNewRoot) { |
||||
this.dragRootEl = pointElRoot; |
||||
this.hasNewRoot = this.el[0] !== this.dragRootEl[0]; |
||||
} |
||||
} |
||||
} |
||||
|
||||
}; |
||||
|
||||
$.fn.nestable = function(params) |
||||
{ |
||||
var lists = this, |
||||
retval = this; |
||||
|
||||
lists.each(function() |
||||
{ |
||||
var plugin = $(this).data("nestable"); |
||||
|
||||
if (!plugin) { |
||||
$(this).data("nestable", new Plugin(this, params)); |
||||
$(this).data("nestable-id", new Date().getTime()); |
||||
} else { |
||||
if (typeof params === 'string' && typeof plugin[params] === 'function') { |
||||
retval = plugin[params](); |
||||
} |
||||
} |
||||
}); |
||||
|
||||
return retval || lists; |
||||
}; |
||||
|
||||
})(window.jQuery || window.Zepto, window, document); |
@ -0,0 +1,60 @@
|
||||
$(document).ready(function() |
||||
{ |
||||
$('#nestable3').nestable(); |
||||
|
||||
$('#serialize').click(function(){ |
||||
serializeTree(); |
||||
}); |
||||
|
||||
//$('#nestable3').on('change', function() {
|
||||
/* on change event */ |
||||
//alert('Order changed');
|
||||
//});
|
||||
|
||||
//$('.panel-group').mouseover(function(ev) {
|
||||
// $(this).find('.dd-item').trigger(ev);
|
||||
//});
|
||||
//$('.panel-group, .panel, .panel-heading, .panel-title, .panel-collapse, .panel-body').trigger('mouseover');
|
||||
//$('.panel-group, .panel, .panel-heading, .panel-title, .panel-collapse, .panel-body, .dd-handle').mouseover();
|
||||
//$('.panel-group, .panel, .panel-heading, .panel-title, .panel-collapse, .panel-body, .dd-handle').mouseenter();
|
||||
}); |
||||
|
||||
function serializeTree() { |
||||
//if (window.JSON) {
|
||||
//var serialized = JSON.stringify($('#nestable3').nestable('serialize'));
|
||||
//$('#output').text(serialized+'\n\n');
|
||||
var arr = getPositions($('#nestable3').nestable('serialize')); |
||||
return JSON.stringify(arr); |
||||
//$('#output').text(JSON.stringify(arr));
|
||||
//} else {
|
||||
//$('#output').text('JSON browser support required for this demo.');
|
||||
//}
|
||||
} |
||||
|
||||
function getPositions(array, parent_id) { |
||||
parent_id = parent_id || 0; |
||||
var new_array = []; |
||||
for (var i = 0; i < array.length; i++) { |
||||
new_array.push([array[i].id, parent_id]); |
||||
if (array[i].hasOwnProperty('children')) { |
||||
new_array = new_array.concat(getPositions( array[i].children, array[i].id )); |
||||
} |
||||
} |
||||
return new_array; |
||||
} |
||||
|
||||
function sendTree(menu_id, url, redirect) { |
||||
var json = serializeTree(); |
||||
|
||||
$.ajax({ |
||||
url: url, |
||||
type: 'POST', |
||||
data: { json : json }, |
||||
success: function(){ |
||||
document.location.href = redirect; |
||||
}, |
||||
error: function(){ |
||||
alert('Error: ' + res.message); |
||||
} |
||||
}); |
||||
} |
@ -0,0 +1,48 @@
|
||||
<?php |
||||
/** |
||||
* Created by Error202 |
||||
* Date: 11.07.2018 |
||||
*/ |
||||
|
||||
namespace backend\components\menu\widgets; |
||||
|
||||
|
||||
use core\entities\menu\Menu; |
||||
use core\entities\menu\MenuItem; |
||||
use yii\base\Widget; |
||||
|
||||
class MenuEditorWidget extends Widget |
||||
{ |
||||
public $menu_id; |
||||
|
||||
public function run() |
||||
{ |
||||
$menu = Menu::findOne($this->menu_id); |
||||
$items = $menu->items; |
||||
|
||||
return $this->render('menu', [ |
||||
'items' => $this->getMenu($items), |
||||
'menu' => $menu, |
||||
]); |
||||
} |
||||
|
||||
/** |
||||
* @param $items MenuItem[] |
||||
* |
||||
* @return array |
||||
*/ |
||||
private function getMenu($items, $paren_id = null) |
||||
{ |
||||
$array = []; |
||||
foreach ($items as $item) { |
||||
if ($item->parent_id != $paren_id) { |
||||
continue; |
||||
} |
||||
$array[$item->id]['item'] = $item; |
||||
if ($children = $item->children) { |
||||
$array[$item->id]['children'] = $this->getMenu($children, $item->id); |
||||
} |
||||
} |
||||
return $array; |
||||
} |
||||
} |
@ -0,0 +1,41 @@
|
||||
<?php |
||||
/** |
||||
* Created by Error202 |
||||
* Date: 11.07.2018 |
||||
*/ |
||||
|
||||
/** |
||||
* @var $this \yii\web\View |
||||
* @var $item array |
||||
*/ |
||||
|
||||
/* @var $menu_item \core\entities\menu\MenuItem */ |
||||
$menu_item = $item['item']; |
||||
|
||||
?> |
||||
|
||||
<li class="dd-item dd3-item" data-id="<?= $menu_item->id ?>">
|
||||
<div class="dd3-content"> |
||||
<div class="panel-group" id="accordion"> |
||||
<div class="panel panel-default"> |
||||
<div class="panel-heading"> |
||||
<h4 class="panel-title"> |
||||
<div class="dd-handle dd3-handle"> </div> |
||||
<a data-toggle="collapse" data-parent="#accordion" href="#collapse<?= $menu_item->id ?>"><?= $menu_item->name ?> |
||||
<i class="fa fa-angle-down pull-right" aria-hidden="true"></i></a> |
||||
</h4> |
||||
</div> |
||||
<div id="collapse<?= $menu_item->id ?>" class="panel-collapse collapse">
|
||||
<div class="panel-body"> |
||||
Content Panel |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
|
||||
<?php if (isset($item['children'])): ?> |
||||
<?= menu_generate($item['children']) ?> |
||||
<?php endif; ?> |
||||
|
||||
</li> |
@ -0,0 +1,155 @@
|
||||
<?php |
||||
/** |
||||
* Created by Error202 |
||||
* Date: 11.07.2018 |
||||
*/ |
||||
|
||||
/** |
||||
* @var $this \yii\web\View |
||||
* @var $items array |
||||
* @var $menu \core\entities\menu\Menu |
||||
*/ |
||||
|
||||
use backend\components\menu\assets\MenuAsset; |
||||
use yii\helpers\Html; |
||||
use yii\helpers\Url; |
||||
use yii\web\JsExpression; |
||||
|
||||
MenuAsset::register($this); |
||||
|
||||
function menu_generate($items) { |
||||
$html = '<ol class="dd-list">'; |
||||
foreach ($items as $item) { |
||||
$html.=Yii::$app->getView()->render( '_item', [ |
||||
'item' => $item, |
||||
] ); |
||||
} |
||||
return $html . '</ol>'; |
||||
} |
||||
|
||||
$url = Url::to(['/menu/save-menu-items']); |
||||
$redirect = Url::to(['menu/index', 'id' => $menu->id]); |
||||
?> |
||||
|
||||
<div class="dd" id="nestable3"> |
||||
<?= menu_generate($items) ?> |
||||
</div> |
||||
|
||||
<!-- |
||||
<div class="dd" id="nestable2"> |
||||
<ol class="dd-list"> |
||||
|
||||
<li class="dd-item dd3-item" data-id="13"> |
||||
<div class="dd3-content"> |
||||
<div class="panel-group" id="accordion"> |
||||
<div class="panel panel-default"> |
||||
<div class="panel-heading"> |
||||
<h4 class="panel-title"> |
||||
<div class="dd-handle dd3-handle"> </div> |
||||
<a data-toggle="collapse" data-parent="#accordion" href="#collapse1">Item 13 |
||||
<i class="fa fa-angle-down pull-right" aria-hidden="true"></i></a> |
||||
</h4> |
||||
</div> |
||||
<div id="collapse1" class="panel-collapse collapse"> |
||||
<div class="panel-body"> |
||||
Content Panel |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</li> |
||||
|
||||
|
||||
<li class="dd-item dd3-item" data-id="14"> |
||||
<div class="dd3-content"> |
||||
<div class="panel-group" id="accordion"> |
||||
<div class="panel panel-default"> |
||||
<div class="panel-heading"> |
||||
<h4 class="panel-title"> |
||||
<div class="dd-handle dd3-handle"> </div> |
||||
<a data-toggle="collapse" data-parent="#accordion" href="#collapse2">Item 14 |
||||
<i class="fa fa-angle-down pull-right" aria-hidden="true"></i></a> |
||||
</h4> |
||||
</div> |
||||
<div id="collapse2" class="panel-collapse collapse"> |
||||
<div class="panel-body"> |
||||
Content Panel |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</li> |
||||
|
||||
<li class="dd-item dd3-item" data-id="15"> |
||||
<div class="dd3-content"> |
||||
<div class="panel-group" id="accordion"> |
||||
<div class="panel panel-default"> |
||||
<div class="panel-heading"> |
||||
<h4 class="panel-title"> |
||||
<div class="dd-handle dd3-handle"> </div> |
||||
<a data-toggle="collapse" data-parent="#accordion" href="#collapse3">Item 15 |
||||
<i class="fa fa-angle-down pull-right" aria-hidden="true"></i></a> |
||||
</h4> |
||||
</div> |
||||
<div id="collapse3" class="panel-collapse collapse"> |
||||
<div class="panel-body"> |
||||
Content Panel |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
|
||||
<ol class="dd-list"> |
||||
<li class="dd-item dd3-item" data-id="16"> |
||||
<div class="dd3-content"> |
||||
<div class="panel-group" id="accordion"> |
||||
<div class="panel panel-default"> |
||||
<div class="panel-heading"> |
||||
<h4 class="panel-title"> |
||||
<div class="dd-handle dd3-handle"> </div> |
||||
<a data-toggle="collapse" data-parent="#accordion" href="#collapse4">Item 16 |
||||
<i class="fa fa-angle-down pull-right" aria-hidden="true"></i></a> |
||||
</h4> |
||||
</div> |
||||
<div id="collapse4" class="panel-collapse collapse"> |
||||
<div class="panel-body"> |
||||
Content Panel |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</li> |
||||
</ol> |
||||
|
||||
</li> |
||||
|
||||
|
||||
|
||||
|
||||
</ol> |
||||
</div> |
||||
|
||||
</div> |
||||
|
||||
<div style="clear: both;"></div> |
||||
<hr> |
||||
|
||||
<button class="btn btn-primary" id="serialize">Serialize</button> |
||||
<hr> |
||||
<textarea class="form-control" id="output"></textarea> |
||||
|
||||
<hr> |
||||
<textarea class="form-control" id="output2"></textarea> |
||||
--> |
||||
|
||||
<div style="clear: both;"></div> |
||||
<hr> |
||||
|
||||
<?= Html::button(Yii::t('buttons', 'Save'), [ |
||||
'class' => 'btn btn-success pull-right', |
||||
'onclick' => new JsExpression('sendTree('.$menu->id.', "'.$url.'", "'.$redirect.'")'), |
||||
]) ?> |
@ -0,0 +1,195 @@
|
||||
<?php |
||||
/** |
||||
* Created by Error202 |
||||
* Date: 10.07.2018 |
||||
*/ |
||||
|
||||
namespace backend\controllers; |
||||
|
||||
|
||||
use common\modules\blog\BlogModule; |
||||
use core\entities\menu\Menu; |
||||
use core\entities\menu\MenuItem; |
||||
use core\entities\ModuleRecord; |
||||
use core\forms\menu\MenuForm; |
||||
use core\forms\menu\MenuItemForm; |
||||
use core\forms\menu\MenuSelectForm; |
||||
use core\services\menu\MenuItemManageService; |
||||
use core\services\menu\MenuManageService; |
||||
use yii\filters\AccessControl; |
||||
use yii\filters\VerbFilter; |
||||
use yii\helpers\Json; |
||||
use yii\web\Controller; |
||||
use yii\web\NotFoundHttpException; |
||||
use Yii; |
||||
|
||||
class MenuController extends Controller |
||||
{ |
||||
public $menu_service; |
||||
public $menu_item_service; |
||||
|
||||
public function __construct( string $id, $module, MenuManageService $menu_service, MenuItemManageService $menu_item_service, array $config = [] ) { |
||||
parent::__construct( $id, $module, $config ); |
||||
|
||||
$this->menu_service = $menu_service; |
||||
$this->menu_item_service = $menu_item_service; |
||||
} |
||||
|
||||
public function behaviors(): array |
||||
{ |
||||
return [ |
||||
'access' => [ |
||||
'class' => AccessControl::class, |
||||
'rules' => [ |
||||
[ |
||||
'actions' => ['create', 'update', 'delete', 'index', 'save-menu-items'], |
||||
'allow' => true, |
||||
'roles' => ['MenuManagement'], |
||||
], |
||||
[ // all the action are accessible to admin |
||||
'allow' => true, |
||||
'roles' => ['admin'], |
||||
], |
||||
], |
||||
], |
||||
'verbs' => [ |
||||
'class' => VerbFilter::class, |
||||
'actions' => [ |
||||
'delete' => ['POST'], |
||||
], |
||||
], |
||||
]; |
||||
} |
||||
|
||||
public function actionIndex($id = null) |
||||
{ |
||||
$menus = Menu::find()->all(); |
||||
|
||||
$form = new MenuSelectForm(); |
||||
if ($form->load(Yii::$app->request->get()) && $form->validate()) { |
||||
return $this->redirect(['menu/index', 'id' => $form->id]); |
||||
} |
||||
elseif ($id) { |
||||
$this->createMenuItem(); // create menu item if MenuItemForm sent |
||||
|
||||
$menu = $this->findModel($id); |
||||
|
||||
$creatorWidgets = $this->getCreatorWidgets($menu->id); |
||||
|
||||
return $this->render('menu', [ |
||||
'model' => $form, |
||||
'menus' => $menus, |
||||
'menu' => $menu, |
||||
'creator' => $creatorWidgets, |
||||
]); |
||||
} |
||||
else { |
||||
return $this->render('select_menu', [ |
||||
'model' => $form, |
||||
'menus' => $menus, |
||||
]); |
||||
} |
||||
} |
||||
|
||||
public function actionCreate() |
||||
{ |
||||
$form = new MenuForm(); |
||||
if ($form->load(Yii::$app->request->post()) && $form->validate()) { |
||||
try { |
||||
$menu = $this->menu_service->create($form); |
||||
return $this->redirect(['index', 'id' => $menu->id]); |
||||
} catch (\DomainException $e) { |
||||
Yii::$app->errorHandler->logException($e); |
||||
Yii::$app->session->setFlash('error', $e->getMessage()); |
||||
} |
||||
} |
||||
return $this->render('create', [ |
||||
'model' => $form, |
||||
]); |
||||
} |
||||
|
||||
public function actionUpdate($id) |
||||
{ |
||||
$menu = $this->findModel($id); |
||||
|
||||
$form = new MenuForm($menu); |
||||
if ($form->load(Yii::$app->request->post()) && $form->validate()) { |
||||
try { |
||||
$this->menu_service->edit($menu->id, $form); |
||||
return $this->redirect(['index', 'id' => $menu->id]); |
||||
} catch (\DomainException $e) { |
||||
Yii::$app->errorHandler->logException($e); |
||||
Yii::$app->session->setFlash('error', $e->getMessage()); |
||||
} |
||||
} |
||||
return $this->render('update', [ |
||||
'model' => $form, |
||||
'menu' => $menu, |
||||
]); |
||||
} |
||||
|
||||
public function actionDelete($id) |
||||
{ |
||||
try { |
||||
$this->menu_service->remove($id); |
||||
} catch (\DomainException $e) { |
||||
Yii::$app->errorHandler->logException($e); |
||||
Yii::$app->session->setFlash('error', $e->getMessage()); |
||||
} |
||||
return $this->redirect(['index']); |
||||
} |
||||
|
||||
public function actionSaveMenuItems() |
||||
{ |
||||
$json = Yii::$app->request->post('json'); |
||||
Yii::$app->response->format = \yii\web\Response::FORMAT_JSON; |
||||
if (Yii::$app->request->isAjax) { |
||||
try { |
||||
$order = []; |
||||
$items = Json::decode($json, true); |
||||
foreach ($items as $item) { |
||||
$order[$item[1]] = isset($order[$item[1]]) ? $order[$item[1]]+1 : 0; |
||||
$this->menu_item_service->setPosition($item, $order[$item[1]]); |
||||
} |
||||
return [ 'result' => 'success' ]; |
||||
} |
||||
catch (\RuntimeException $e) { |
||||
return [ 'result' => 'error', 'message' => $e->getMessage() ]; |
||||
} |
||||
} |
||||
return ['result' => 'error', 'message' => 'Request error']; |
||||
} |
||||
|
||||
private function getCreatorWidgets($menu_id): array |
||||
{ |
||||
$widgets = []; |
||||
$modules = ModuleRecord::find()->active()->all(); |
||||
foreach ($modules as $module) { |
||||
if (method_exists($module->class, 'getMenuItemCreator')) { |
||||
$module_widgets = call_user_func_array($module->class . '::getMenuItemCreator', [$menu_id]); |
||||
$widgets = is_array($module_widgets) ? array_merge($widgets, $module_widgets) : $widgets; |
||||
} |
||||
} |
||||
return $widgets; |
||||
} |
||||
|
||||
private function createMenuItem() |
||||
{ |
||||
$form = new MenuItemForm(); |
||||
if ($form->load(Yii::$app->request->post()) && $form->validate()) { |
||||
try { |
||||
$this->menu_item_service->create($form); |
||||
} catch (\DomainException $e) { |
||||
Yii::$app->errorHandler->logException($e); |
||||
} |
||||
} |
||||
} |
||||
|
||||
protected function findModel($id): Menu |
||||
{ |
||||
if (($model = Menu::findOne($id)) !== null) { |
||||
return $model; |
||||
} |
||||
throw new NotFoundHttpException('The requested menu does not exist.'); |
||||
} |
||||
} |
@ -0,0 +1,12 @@
|
||||
<?php |
||||
return [ |
||||
'Menu' => 'Меню', |
||||
'Select menu...' => 'Укажите меню', |
||||
'Create Menu' => 'Новое меню', |
||||
'Update Menu' => 'Изменить меню', |
||||
'Delete Menu' => 'Удалить меню', |
||||
'Update Menu: {name}' => 'Редактирование меню: {name}', |
||||
'Current Menu' => 'Текущее меню', |
||||
'Available Blocks' => 'Доступные блоки', |
||||
'Menu Items' => 'Элементы меню', |
||||
]; |
@ -0,0 +1,27 @@
|
||||
<?php |
||||
|
||||
use yii\helpers\Html; |
||||
use yii\widgets\ActiveForm; |
||||
|
||||
/* @var $this yii\web\View */ |
||||
/* @var $model \core\forms\menu\MenuForm */ |
||||
/* @var $form yii\widgets\ActiveForm */ |
||||
?> |
||||
|
||||
<div class="menu-form"> |
||||
|
||||
<?php $form = ActiveForm::begin(); ?> |
||||
|
||||
<div class="box box-default"> |
||||
<div class="box-body"> |
||||
<?= $form->field($model, 'name')->textInput(['maxlength' => true]) ?> |
||||
</div> |
||||
</div> |
||||
|
||||
<div class="form-group"> |
||||
<?= Html::submitButton(Yii::t('buttons', 'Save'), ['class' => 'btn btn-success']) ?> |
||||
</div> |
||||
|
||||
<?php ActiveForm::end(); ?> |
||||
|
||||
</div> |
@ -0,0 +1,16 @@
|
||||
<?php |
||||
|
||||
/* @var $this yii\web\View */ |
||||
/* @var $model \core\forms\menu\MenuForm */ |
||||
|
||||
$this->title = Yii::t('menu', 'Create Menu'); |
||||
$this->params['breadcrumbs'][] = ['label' => Yii::t('menu', 'Menu'), 'url' => ['index']]; |
||||
$this->params['breadcrumbs'][] = $this->title; |
||||
?> |
||||
<div class="menu-create"> |
||||
|
||||
<?= $this->render('_form', [ |
||||
'model' => $model, |
||||
]) ?> |
||||
|
||||
</div> |
@ -0,0 +1,114 @@
|
||||
<?php |
||||
/** |
||||
* Created by Error202 |
||||
* Date: 10.07.2018 |
||||
*/ |
||||
|
||||
use kartik\form\ActiveForm; |
||||
use yii\helpers\ArrayHelper; |
||||
use yii\helpers\Html; |
||||
|
||||
/** |
||||
* @var $this \yii\web\View |
||||
* @var $model \core\forms\menu\MenuSelectForm |
||||
* @var $menus \core\entities\menu\Menu[] |
||||
* @var $menu \core\entities\menu\Menu |
||||
* @var $creator array |
||||
*/ |
||||
|
||||
$this->title = Yii::t('menu', 'Menu'); |
||||
$this->params['breadcrumbs'][] = Html::encode($menu->name); |
||||
$this->params['breadcrumbs'][] = $this->title; |
||||
?> |
||||
|
||||
<div class="menu"> |
||||
<div class="box box-default"> |
||||
<div class="box-header with-border"><?= Yii::t('menu', 'Current Menu') ?></div>
|
||||
<div class="box-body"> |
||||
|
||||
<div class="row"> |
||||
<div class="col-md-6"> |
||||
<?php $form = ActiveForm::begin([ |
||||
'enableClientValidation' => false, |
||||
'method' => 'get', |
||||
'id' => 'select_menu', |
||||
]); ?> |
||||
|
||||
<?= $form->field($model, 'id')->dropDownList(ArrayHelper::map($menus, 'id', 'name'), [ |
||||
//'prompt' => Yii::t('menu', 'Select menu...'), |
||||
'value' => $menu->id, |
||||
'onchange' => 'this.form.submit()', |
||||
])->label(false) ?> |
||||
|
||||
<?php ActiveForm::end(); ?> |
||||
</div> |
||||
<div class="col-md-6"> |
||||
<?= Html::a(Yii::t('menu', 'Create Menu'), ['menu/create'], [ |
||||
'class' => 'btn btn-success', |
||||
]) ?> |
||||
|
||||
<?= Html::a(Yii::t('menu', 'Update Menu'), ['menu/update', 'id' => $menu->id], [ |
||||
'class' => 'btn btn-primary', |
||||
]) ?> |
||||
|
||||
<?= Html::a(Yii::t('menu', 'Delete Menu'), ['menu/delete', 'id' => $menu->id], [ |
||||
'class' => 'btn btn-danger', |
||||
'data' => [ |
||||
'confirm' => Yii::t('buttons', 'Are you sure you want to delete this item?'), |
||||
'method' => 'post', |
||||
], |
||||
]) ?> |
||||
</div> |
||||
</div> |
||||
|
||||
</div> |
||||
</div> |
||||
|
||||
<div class="row"> |
||||
<div class="col-md-3"> |
||||
<div class="box box-default"> |
||||
<div class="box-header with-border"><?= Yii::t('menu', 'Available Blocks') ?></div>
|
||||
<div class="box-body"> |
||||
|
||||
<div class="panel-group" id="accordion"> |
||||
|
||||
<?php foreach ($creator as $item): ?> |
||||
|
||||
<div class="panel panel-default"> |
||||
<div class="panel-heading"> |
||||
<h4 class="panel-title"> |
||||
<a data-toggle="collapse" data-parent="#accordion" href="#collapseOne"><?= $item['title'] ?> |
||||
<i class="fa fa-angle-down pull-right" aria-hidden="true"></i></a> |
||||
</h4> |
||||
</div> |
||||
<div id="collapseOne" class="panel-collapse collapse"> |
||||
<div class="panel-body"> |
||||
<?= $item['content'] ?> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
|
||||
<?php endforeach; ?> |
||||
|
||||
</div> |
||||
|
||||
</div> |
||||
</div> |
||||
</div> |
||||
<div class="col-md-9"> |
||||
<div class="box box-default"> |
||||
<div class="box-header with-border"><?= Yii::t('menu', 'Menu Items') ?></div>
|
||||
<div class="box-body"> |
||||
|
||||
<?= \backend\components\menu\widgets\MenuEditorWidget::widget([ |
||||
'menu_id' => $menu->id |
||||
]) ?> |
||||
|
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
|
||||
|
||||
</div> |
||||
|
@ -0,0 +1,51 @@
|
||||
<?php |
||||
/** |
||||
* Created by Error202 |
||||
* Date: 10.07.2018 |
||||
*/ |
||||
|
||||
use kartik\form\ActiveForm; |
||||
use yii\helpers\ArrayHelper; |
||||
use yii\helpers\Html; |
||||
|
||||
/** |
||||
* @var $this \yii\web\View |
||||
* @var $model \core\forms\menu\MenuSelectForm |
||||
* @var $menus \core\entities\menu\Menu[] |
||||
*/ |
||||
|
||||
$this->title = Yii::t('menu', 'Menu'); |
||||
$this->params['breadcrumbs'][] = $this->title; |
||||
?> |
||||
|
||||
<div class="menu"> |
||||
<div class="box box-default"> |
||||
<div class="box-header with-border"><?= Yii::t('menu', 'Current Menu') ?></div>
|
||||
<div class="box-body"> |
||||
|
||||
<div class="row"> |
||||
<div class="col-md-6"> |
||||
<?php $form = ActiveForm::begin([ |
||||
'enableClientValidation' => false, |
||||
'method' => 'get', |
||||
'id' => 'select_menu', |
||||
]); ?> |
||||
|
||||
<?= $form->field($model, 'id')->dropDownList(ArrayHelper::map($menus, 'id', 'name'), [ |
||||
'prompt' => Yii::t('menu', 'Select menu...'), |
||||
'onchange' => 'this.form.submit()', |
||||
])->label(false) ?> |
||||
|
||||
<?php ActiveForm::end(); ?> |
||||
</div> |
||||
<div class="col-md-2"> |
||||
<?= Html::a(Yii::t('menu', 'Create Menu'), ['menu/create'], [ |
||||
'class' => 'btn btn-success', |
||||
]) ?> |
||||
</div> |
||||
</div> |
||||
|
||||
</div> |
||||
</div> |
||||
</div> |
||||
|
@ -0,0 +1,18 @@
|
||||
<?php |
||||
|
||||
/* @var $this yii\web\View */ |
||||
/* @var $menu \core\entities\menu\Menu */ |
||||
/* @var $model \core\forms\menu\MenuForm */ |
||||
|
||||
$this->title = Yii::t('menu', 'Update Menu: {name}', ['name' => $menu->name]); |
||||
$this->params['breadcrumbs'][] = ['label' => Yii::t('menu', 'Menu'), 'url' => ['index']]; |
||||
$this->params['breadcrumbs'][] = ['label' => $menu->name, 'url' => ['index', 'id' => $menu->id]]; |
||||
$this->params['breadcrumbs'][] = Yii::t('buttons', 'Editing'); |
||||
?> |
||||
<div class="menu-update"> |
||||
|
||||
<?= $this->render('_form', [ |
||||
'model' => $model, |
||||
]) ?> |
||||
|
||||
</div> |
@ -0,0 +1,30 @@
|
||||
<?php |
||||
/** |
||||
* Created by Error202 |
||||
* Date: 10.07.2018 |
||||
*/ |
||||
|
||||
namespace common\modules\blog\widgets; |
||||
|
||||
|
||||
use core\forms\menu\MenuItemForm; |
||||
use yii\base\Widget; |
||||
|
||||
class MenuItemCreatorWidget extends Widget |
||||
{ |
||||
public $menu_id; |
||||
|
||||
public function run() |
||||
{ |
||||
$form = new MenuItemForm(); |
||||
$form->module = \Yii::t('blog', 'Blog'); |
||||
$form->name = \Yii::t('blog', 'Blog'); |
||||
$form->title_attr = \Yii::t('blog', 'Blog'); |
||||
$form->menu_id = $this->menu_id; |
||||
$form->url = '/blog/post/index'; |
||||
|
||||
return $this->render('menu-item/creator', [ |
||||
'model' => $form, |
||||
]); |
||||
} |
||||
} |
@ -0,0 +1,117 @@
|
||||
<?php |
||||
/** |
||||
* Created by Error202 |
||||
* Date: 10.07.2018 |
||||
*/ |
||||
|
||||
/** |
||||
* @var $this \yii\web\View |
||||
* @var $model \core\forms\menu\MenuItemForm |
||||
*/ |
||||
|
||||
use yii\widgets\ActiveForm; |
||||
use yii\helpers\Html; |
||||
use yii\web\JsExpression; |
||||
use yii\helpers\Url; |
||||
|
||||
$js = <<<JS |
||||
function selectBlogPostOn() { |
||||
$("#post_select").removeAttr('disabled'); |
||||
updateUrl('post') |
||||
} |
||||
|
||||
function selectBlogPostOff() { |
||||
$("#post_select").attr('disabled', 'disabled'); |
||||
updateUrl('blog') |
||||
} |
||||
|
||||
function updateUrl(type) { |
||||
if (type === 'blog') { |
||||
$("#blog_menu_item_url").val('/blog/post/index'); |
||||
$("#blog_menu_item_url_params").val(''); |
||||
} |
||||
else { |
||||
var selected_post = $("#post_select").val(); |
||||
$("#blog_menu_item_url").val('/blog/post/post/'); |
||||
$("#blog_menu_item_url_params").val('{"id":'+selected_post+'}'); |
||||
} |
||||
} |
||||
JS; |
||||
$this->registerJs($js, $this::POS_HEAD); |
||||
|
||||
$fetchUrl = Url::to( [ '/blog/manage/post/post-search' ] ); |
||||
?> |
||||
|
||||
<div class="menu_item_widget"> |
||||
|
||||
<div class="form-group"> |
||||
<div class="radio"> |
||||
<?= Html::label(Html::radio('blog_item_type', true, [ |
||||
'value' => 'blog_home', |
||||
'onclick' => new JsExpression('selectBlogPostOff()'), |
||||
]) . Yii::t('blog', 'Blog Home')) ?> |
||||
</div> |
||||
|
||||
<div class="radio"> |
||||
<?= Html::label(Html::radio('blog_item_type', false, [ |
||||
'value' => 'blog_post', |
||||
'onclick' => new JsExpression('selectBlogPostOn()'), |
||||
]) . Yii::t('blog', 'Blog Post')) ?> |
||||
</div> |
||||
|
||||
<div> |
||||
<?= \kartik\widgets\Select2::widget([ |
||||
'name' => 'post_select', |
||||
'value' => '', |
||||
'options' => [ |
||||
'placeholder' => Yii::t('blog', 'Select post...'), |
||||
'id' => 'post_select', |
||||
'onchange' => new JsExpression("updateUrl('post')"), |
||||
], |
||||
'pluginOptions' => [ |
||||
'disabled' => true, |
||||
'ajax' => [ |
||||
'url' => $fetchUrl, |
||||
'dataType' => 'json', |
||||
'data' => new JsExpression('function(params) { return {q:params.term}; }') |
||||
], |
||||
'escapeMarkup' => new JsExpression('function (markup) { return markup; }'), |
||||
'templateResult' => new JsExpression('function(tag) { return tag.text; }'), |
||||
'templateSelection' => new JsExpression('function (tag) { return tag.text; }'), |
||||
], |
||||
]) ?> |
||||
</div> |
||||
</div> |
||||
|
||||
<?php $form = ActiveForm::begin(); ?> |
||||
|
||||
<?= $form->field($model, 'name')->hiddenInput([ |
||||
])->label(false) ?> |
||||
|
||||
<?= $form->field($model, 'title_attr')->hiddenInput([ |
||||
])->label(false) ?> |
||||
|
||||
<?= $form->field($model, 'module')->hiddenInput([ |
||||
])->label(false) ?> |
||||
|
||||
<?= $form->field($model, 'menu_id')->hiddenInput([ |
||||
])->label(false) ?> |
||||
|
||||
<?= $form->field($model, 'url')->hiddenInput([ |
||||
'id' => 'blog_menu_item_url', |
||||
])->label(false) ?> |
||||
|
||||
<?= $form->field($model, 'url_params')->hiddenInput([ |
||||
'value' => '', |
||||
'id' => 'blog_menu_item_url_params', |
||||
])->label(false) ?> |
||||
|
||||
<div class="form-group"> |
||||
<?= Html::submitButton(Yii::t('buttons', 'Add to menu'), [ |
||||
'class' => 'btn btn-info btn-sm pull-right' |
||||
]) ?> |
||||
</div> |
||||
|
||||
<?php ActiveForm::end(); ?> |
||||
|
||||
</div> |
@ -0,0 +1,33 @@
|
||||
<?php |
||||
|
||||
use yii\db\Migration; |
||||
|
||||
/** |
||||
* Handles the creation of table `menu`. |
||||
*/ |
||||
class m180709_202649_create_menu_table extends Migration |
||||
{ |
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function safeUp() |
||||
{ |
||||
$tableOptions = null; |
||||
if ($this->db->driverName === 'mysql') { |
||||
$tableOptions = 'CHARACTER SET utf8 COLLATE utf8_general_ci ENGINE=InnoDB'; |
||||
} |
||||
|
||||
$this->createTable('{{%menu}}', [ |
||||
'id' => $this->primaryKey(), |
||||
'name' => $this->string(255)->notNull(), |
||||
], $tableOptions); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function safeDown() |
||||
{ |
||||
$this->dropTable('{{%menu}}'); |
||||
} |
||||
} |
@ -0,0 +1,55 @@
|
||||
<?php |
||||
|
||||
use yii\db\Migration; |
||||
|
||||
/** |
||||
* Handles the creation of table `menu_items`. |
||||
*/ |
||||
class m180709_202659_create_menu_items_table extends Migration |
||||
{ |
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function safeUp() |
||||
{ |
||||
$tableOptions = null; |
||||
if ($this->db->driverName === 'mysql') { |
||||
$tableOptions = 'CHARACTER SET utf8 COLLATE utf8_general_ci ENGINE=InnoDB'; |
||||
} |
||||
|
||||
$this->createTable('{{%menu_items}}', [ |
||||
'id' => $this->primaryKey(), |
||||
'menu_id' => $this->integer()->notNull(), |
||||
'parent_id' => $this->integer(), |
||||
'name' => $this->string(255)->notNull(), |
||||
'title_attr' => $this->string(255), |
||||
'target' => $this->string(20), |
||||
'css' => $this->string(255), |
||||
'style' => $this->string(255), |
||||
'module' => $this->string(255), |
||||
'url' => $this->string(255), |
||||
'url_params' => $this->text(), // json id=>1, ... |
||||
'sort' => $this->integer()->notNull()->defaultValue(1), |
||||
], $tableOptions); |
||||
|
||||
$this->createIndex('idx_menu_item_sort', '{{%menu_items}}', ['menu_id', 'sort']); |
||||
$this->createIndex('idx_menu_items_menu_id', '{{%menu_items}}', 'menu_id'); |
||||
$this->createIndex('idx_menu_items_parent_id', '{{%menu_items}}', 'parent_id'); |
||||
|
||||
$this->addForeignKey('frg_menu_items_menu_id', '{{%menu_items}}', 'menu_id', '{{%menu}}', 'id', 'CASCADE'); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function safeDown() |
||||
{ |
||||
$this->dropForeignKey('frg_menu_items_menu_id', '{{%menu_items}}'); |
||||
|
||||
$this->dropIndex('idx_menu_items_parent_id', '{{%menu_items}}'); |
||||
$this->dropIndex('idx_menu_items_menu_id', '{{%menu_items}}'); |
||||
$this->dropIndex('idx_menu_item_sort', '{{%menu_items}}'); |
||||
|
||||
$this->dropTable('{{%menu_items}}'); |
||||
} |
||||
} |
@ -0,0 +1,44 @@
|
||||
<?php |
||||
/** |
||||
* Created by Error202 |
||||
* Date: 09.07.2018 |
||||
*/ |
||||
|
||||
namespace core\entities\menu; |
||||
|
||||
use yii\db\ActiveRecord; |
||||
|
||||
/** |
||||
* Class Menu |
||||
* @package core\entities |
||||
* |
||||
* @property integer $id |
||||
* @property string $name |
||||
* |
||||
* @property MenuItem[] $items |
||||
*/ |
||||
|
||||
class Menu extends ActiveRecord |
||||
{ |
||||
public static function create($name): self |
||||
{ |
||||
$menu = new static(); |
||||
$menu->name = $name; |
||||
return $menu; |
||||
} |
||||
|
||||
public function edit($name): void |
||||
{ |
||||
$this->name = $name; |
||||
} |
||||
|
||||
public static function tableName(): string |
||||
{ |
||||
return '{{%menu}}'; |
||||
} |
||||
|
||||
public function getItems() |
||||
{ |
||||
return $this->hasMany(MenuItem::class, ['menu_id' => 'id'])->orderBy(['sort' => SORT_ASC]); |
||||
} |
||||
} |
@ -0,0 +1,103 @@
|
||||
<?php |
||||
/** |
||||
* Created by Error202 |
||||
* Date: 09.07.2018 |
||||
*/ |
||||
|
||||
namespace core\entities\menu; |
||||
|
||||
use paulzi\sortable\SortableBehavior; |
||||
use yii\db\ActiveRecord; |
||||
|
||||
/** |
||||
* Class MenuItem |
||||
* @package core\entities\menu |
||||
* |
||||
* @property integer $id |
||||
* @property integer $menu_id |
||||
* @property integer $parent_id |
||||
* @property string $name |
||||
* @property string $title_attr |
||||
* @property string $target |
||||
* @property string $css |
||||
* @property string $style |
||||
* @property string $module |
||||
* @property string $url |
||||
* @property string $url_params |
||||
* @property integer $sort |
||||
* |
||||
* @property MenuItem $parent |
||||
* @property MenuItem[] $children |
||||
*/ |
||||
|
||||
class MenuItem extends ActiveRecord |
||||
{ |
||||
public static function create($menu_id, $parent_id, $name, $title_attr, $target, $css, $style, $module, $url, $url_params): self |
||||
{ |
||||
$menu = new static(); |
||||
$menu->menu_id = $menu_id; |
||||
$menu->parent_id = $parent_id; |
||||
$menu->name = $name; |
||||
$menu->title_attr = $title_attr; |
||||
$menu->target = $target; |
||||
$menu->css = $css; |
||||
$menu->style = $style; |
||||
$menu->module = $module; |
||||
$menu->url = $url; |
||||
$menu->url_params = $url_params; |
||||
return $menu; |
||||
} |
||||
|
||||
public function edit($menu_id, $parent_id, $name, $title_attr, $target, $css, $style, $module, $url, $url_params): void |
||||
{ |
||||
$this->menu_id = $menu_id; |
||||
$this->parent_id = $parent_id; |
||||
$this->name = $name; |
||||
$this->title_attr = $title_attr; |
||||
$this->target = $target; |
||||
$this->css = $css; |
||||
$this->style = $style; |
||||
$this->module = $module; |
||||
$this->url = $url; |
||||
$this->url_params = $url_params; |
||||
} |
||||
|
||||
public static function tableName(): string |
||||
{ |
||||
return '{{%menu_items}}'; |
||||
} |
||||
|
||||
/*public function behaviors() |
||||
{ |
||||
return [ |
||||
[ |
||||
'class' => SortableBehavior::class, |
||||
'query' => ['menu_id'], |
||||
], |
||||
]; |
||||
}*/ |
||||
|
||||
public function beforeSave( $insert ) { |
||||
if (parent::beforeSave($insert)) { |
||||
if (!isset($this->sort)) { |
||||
$count = MenuItem::find() |
||||
->andWhere( [ 'menu_id' => $this->menu_id ] ) |
||||
->andWhere( [ 'parent_id' => $this->parent_id ] ) |
||||
->count(); |
||||
$this->sort = $count; |
||||
} |
||||
return true; |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
public function getChildren() |
||||
{ |
||||
return $this->hasMany(MenuItem::class, ['parent_id' => 'id'])->orderBy(['sort' => SORT_ASC]); |
||||
} |
||||
|
||||
public function getParent() |
||||
{ |
||||
return $this->hasOne(MenuItem::class, ['id' => 'parent_id']); |
||||
} |
||||
} |
@ -0,0 +1,15 @@
|
||||
<?php |
||||
|
||||
namespace core\entities\queries; |
||||
|
||||
use yii\db\ActiveQuery; |
||||
|
||||
class ModuleRecordQuery extends ActiveQuery |
||||
{ |
||||
public function active() |
||||
{ |
||||
return $this->andWhere([ |
||||
'active' => 1, |
||||
]); |
||||
} |
||||
} |
@ -0,0 +1,37 @@
|
||||
<?php |
||||
|
||||
namespace core\forms\menu; |
||||
|
||||
use core\entities\menu\Menu; |
||||
use yii\base\Model; |
||||
use Yii; |
||||
|
||||
class MenuForm extends Model |
||||
{ |
||||
public $name; |
||||
|
||||
private $_menu; |
||||
|
||||
public function __construct(Menu $menu = null, $config = []) |
||||
{ |
||||
if ($menu) { |
||||
$this->name = $menu->name; |
||||
$this->_menu = $menu; |
||||
} |
||||
parent::__construct($config); |
||||
} |
||||
|
||||
public function rules(): array |
||||
{ |
||||
return [ |
||||
[['name'], 'required'], |
||||
[['name'], 'string', 'max' => 255], |
||||
]; |
||||
} |
||||
|
||||
public function attributeLabels() { |
||||
return [ |
||||
'name' => Yii::t('main', 'Name'), |
||||
]; |
||||
} |
||||
} |
@ -0,0 +1,68 @@
|
||||
<?php |
||||
|
||||
namespace core\forms\menu; |
||||
|
||||
use core\entities\menu\MenuItem; |
||||
use yii\base\Model; |
||||
use Yii; |
||||
|
||||
class MenuItemForm extends Model |
||||
{ |
||||
public $menu_id; |
||||
public $parent_id; |
||||
public $name; |
||||
public $title_attr; |
||||
public $target; |
||||
public $css; |
||||
public $style; |
||||
public $module; |
||||
public $url; |
||||
public $url_params; |
||||
|
||||
private $_menu; |
||||
|
||||
public function __construct(MenuItem $menu = null, $config = []) |
||||
{ |
||||
if ($menu) { |
||||
$this->menu_id = $menu->menu_id; |
||||
$this->parent_id = $menu->parent_id; |
||||
$this->name = $menu->name; |
||||
$this->title_attr = $menu->title_attr; |
||||
$this->target = $menu->target; |
||||
$this->css = $menu->css; |
||||
$this->style = $menu->style; |
||||
$this->module = $menu->module; |
||||
$this->url = $menu->url; |
||||
$this->url_params = $menu->url_params; |
||||
|
||||
$this->_menu = $menu; |
||||
} |
||||
parent::__construct($config); |
||||
} |
||||
|
||||
public function rules(): array |
||||
{ |
||||
return [ |
||||
[['name', 'menu_id', 'url'], 'required'], |
||||
[['name', 'title_attr', 'css', 'style', 'module', 'url'], 'string', 'max' => 255], |
||||
[['target'], 'string', 'max' => 20], |
||||
['url_params', 'string'], |
||||
[['parent_id', 'menu_id'], 'integer'], |
||||
]; |
||||
} |
||||
|
||||
public function attributeLabels() { |
||||
return [ |
||||
'menu_id' => Yii::t('main', 'Menu'), |
||||
'parent id' => Yii::t('main', 'Parent menu item'), |
||||
'name' => Yii::t('main', 'Name'), |
||||
'title_attr' => Yii::t('main', 'Title attribute'), |
||||
'target' => Yii::t('main', 'Target'), |
||||
'css' => Yii::t('main', 'CSS Classes'), |
||||
'style' => Yii::t('main', 'CSS Style'), |
||||
'module' => Yii::t('main', 'Module'), |
||||
'url' => Yii::t('main', 'Url'), |
||||
'url_params' => Yii::t('main', 'Url Params'), |
||||
]; |
||||
} |
||||
} |
@ -0,0 +1,25 @@
|
||||
<?php |
||||
|
||||
namespace core\forms\menu; |
||||
|
||||
use yii\base\Model; |
||||
use Yii; |
||||
|
||||
class MenuSelectForm extends Model |
||||
{ |
||||
public $id; |
||||
|
||||
public function rules(): array |
||||
{ |
||||
return [ |
||||
[['id'], 'required'], |
||||
[['id'], 'integer'], |
||||
]; |
||||
} |
||||
|
||||
public function attributeLabels() { |
||||
return [ |
||||
'id' => Yii::t('menu', 'Menu'), |
||||
]; |
||||
} |
||||
} |
@ -0,0 +1,31 @@
|
||||
<?php |
||||
|
||||
namespace core\repositories\menu; |
||||
|
||||
use core\entities\menu\MenuItem; |
||||
use core\repositories\NotFoundException; |
||||
|
||||
class MenuItemRepository |
||||
{ |
||||
public function get($id): MenuItem |
||||
{ |
||||
if (!$item = MenuItem::findOne($id)) { |
||||
throw new NotFoundException('Menu is not found.'); |
||||
} |
||||
return $item; |
||||
} |
||||
|
||||
public function save(MenuItem $item): void |
||||
{ |
||||
if (!$item->save()) { |
||||
throw new \RuntimeException('Saving error.'); |
||||
} |
||||
} |
||||
|
||||
public function remove(MenuItem $item): void |
||||
{ |
||||
if (!$item->delete()) { |
||||
throw new \RuntimeException('Removing error.'); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,31 @@
|
||||
<?php |
||||
|
||||
namespace core\repositories\menu; |
||||
|
||||
use core\entities\menu\Menu; |
||||
use core\repositories\NotFoundException; |
||||
|
||||
class MenuRepository |
||||
{ |
||||
public function get($id): Menu |
||||
{ |
||||
if (!$menu = Menu::findOne($id)) { |
||||
throw new NotFoundException('Menu is not found.'); |
||||
} |
||||
return $menu; |
||||
} |
||||
|
||||
public function save(Menu $menu): void |
||||
{ |
||||
if (!$menu->save()) { |
||||
throw new \RuntimeException('Saving error.'); |
||||
} |
||||
} |
||||
|
||||
public function remove(Menu $menu): void |
||||
{ |
||||
if (!$menu->delete()) { |
||||
throw new \RuntimeException('Removing error.'); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,67 @@
|
||||
<?php |
||||
|
||||
namespace core\services\menu; |
||||
|
||||
use core\entities\menu\MenuItem; |
||||
use core\forms\menu\MenuItemForm; |
||||
use core\repositories\menu\MenuItemRepository; |
||||
|
||||
class MenuItemManageService |
||||
{ |
||||
private $repository; |
||||
|
||||
public function __construct(MenuItemRepository $repository) |
||||
{ |
||||
$this->repository = $repository; |
||||
} |
||||
|
||||
public function create(MenuItemForm $form): MenuItem |
||||
{ |
||||
$menu = MenuItem::create( |
||||
$form->menu_id, |
||||
$form->parent_id, |
||||
$form->name, |
||||
$form->title_attr, |
||||
$form->target, |
||||
$form->css, |
||||
$form->style, |
||||
$form->module, |
||||
$form->url, |
||||
$form->url_params |
||||
); |
||||
$this->repository->save($menu); |
||||
return $menu; |
||||
} |
||||
|
||||
public function edit($id, MenuItemForm $form): void |
||||
{ |
||||
$menu = $this->repository->get($id); |
||||
$menu->edit( |
||||
$form->menu_id, |
||||
$form->parent_id, |
||||
$form->name, |
||||
$form->title_attr, |
||||
$form->target, |
||||
$form->css, |
||||
$form->style, |
||||
$form->module, |
||||
$form->url, |
||||
$form->url_params |
||||
); |
||||
$this->repository->save($menu); |
||||
} |
||||
|
||||
public function remove($id): void |
||||
{ |
||||
$menu = $this->repository->get($id); |
||||
$this->repository->remove($menu); |
||||
} |
||||
|
||||
public function setPosition(array $position, $sort): void |
||||
{ |
||||
$item = $this->repository->get($position[0]); |
||||
$item->parent_id = $position[1] ? $position[1] : null; |
||||
$item->sort = $sort; |
||||
$this->repository->save($item); |
||||
} |
||||
} |
@ -0,0 +1,41 @@
|
||||
<?php |
||||
|
||||
namespace core\services\menu; |
||||
|
||||
use core\entities\menu\Menu; |
||||
use core\forms\menu\MenuForm; |
||||
use core\repositories\menu\MenuRepository; |
||||
|
||||
class MenuManageService |
||||
{ |
||||
private $repository; |
||||
|
||||
public function __construct(MenuRepository $repository) |
||||
{ |
||||
$this->repository = $repository; |
||||
} |
||||
|
||||
public function create(MenuForm $form): Menu |
||||
{ |
||||
$menu = Menu::create( |
||||
$form->name |
||||
); |
||||
$this->repository->save($menu); |
||||
return $menu; |
||||
} |
||||
|
||||
public function edit($id, MenuForm $form): void |
||||
{ |
||||
$menu = $this->repository->get($id); |
||||
$menu->edit( |
||||
$form->name |
||||
); |
||||
$this->repository->save($menu); |
||||
} |
||||
|
||||
public function remove($id): void |
||||
{ |
||||
$menu = $this->repository->get($id); |
||||
$this->repository->remove($menu); |
||||
} |
||||
} |
Loading…
Reference in new issue