diff --git a/modules/backend/assets/css/winter.css b/modules/backend/assets/css/winter.css index c2349a681a..ae48dbb44c 100644 --- a/modules/backend/assets/css/winter.css +++ b/modules/backend/assets/css/winter.css @@ -66,9 +66,9 @@ .sweet-alert p{margin:0} .sweet-alert p.text-muted{margin-bottom:20px;color:#555} .global-notice{position:sticky;top:0;display:flex;align-items:center;flex-wrap:wrap;gap:0.5em;justify-content:space-between;z-index:10500;background:#ab2a1c;color:#FFF;padding:0.5em 0.75em} -.global-notice .notice-icon{font-size:1.5em;vertical-align:bottom;display:inline-block;margin-right:.25em} +.global-notice .notice-icon{font-size:1.5em;vertical-align:bottom;display:inline-block;margin-right:0.25em} .global-notice .notice-text{display:inline-block;vertical-align:middle} -.control-simplelist{font-size:13px;padding:20px 20px 2px 20px;margin-bottom:20px;background:#fff;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px} +.control-simplelist{font-size:13px;padding:20px 20px 2px 20px;margin-bottom:20px;background:#FFF;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px} .control-simplelist ul{padding-left:15px} .control-simplelist.form-control ul{margin-bottom:0} .control-simplelist.form-control li{padding-top:5px;padding-bottom:5px} @@ -96,7 +96,7 @@ .control-simplelist.is-selectable li .heading, .control-simplelist.is-selectable-box li .heading{font-size:14px;font-weight:500} .control-simplelist.is-divided li, -.control-simplelist.is-selectable li{padding:5px 10px;border-bottom:1px solid #d4d8da} +.control-simplelist.is-selectable li{padding:5px 10px;border-bottom:1px solid #D4D8DA} .control-simplelist.is-divided li:last-child, .control-simplelist.is-selectable li:last-child{border-bottom:none} .control-simplelist.is-selectable li a{padding:5px 10px;margin:-5px -10px;display:block;color:#333} @@ -145,7 +145,7 @@ html.mobile .control-scrollbar{overflow:auto;-webkit-overflow-scrolling:touch} .no-touch .control-scrollbar>.scrollbar-scrollbar{opacity:0;-webkit-transition:opacity 0.3s;transition:opacity 0.3s} .no-touch .control-scrollbar:active>.scrollbar-scrollbar, .no-touch .control-scrollbar:hover>.scrollbar-scrollbar{opacity:1} -@media (max-width:768px){.responsive-sidebar>.layout-cell:last-child .control-scrollbar{overflow:visible;height:auto}.responsive-sidebar>.layout-cell:last-child .control-scrollbar .scrollbar-scrollbar{display:none !important}} +@media (max-width:768px){.responsive-sidebar>.layout-cell:last-child .control-scrollbar{overflow:visible;height:auto}.responsive-sidebar>.layout-cell:last-child .control-scrollbar .scrollbar-scrollbar{display:none!important}} .control-filelist p.no-data{padding:22px 0;margin:0;color:#666;font-size:14px;text-align:center;font-weight:normal;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px} .control-filelist ul{padding:0;margin:0} .control-filelist ul li{font-weight:normal;line-height:150%;position:relative;list-style:none} @@ -192,21 +192,21 @@ html.mobile .control-scrollbar{overflow:auto;-webkit-overflow-scrolling:touch} .control-filelist ul li.group[data-status=collapsed]>div.subitems{display:none} .control-filelist ul li>div.controls{position:absolute;right:19px;top:6px} .control-filelist ul li>div.controls .dropdown{width:14px;height:21px} -.control-filelist ul li>div.controls .dropdown.open a.control{display:block !important} +.control-filelist ul li>div.controls .dropdown.open a.control{display:block!important} .control-filelist ul li>div.controls .dropdown.open a.control:before{visibility:visible;display:block} .control-filelist ul li>div.controls a.control{color:#405261;font-size:14px;visibility:hidden;overflow:hidden;width:14px;height:21px;display:none;text-decoration:none;cursor:pointer;padding:0;opacity:0.5;filter:alpha(opacity=50)} .control-filelist ul li>div.controls a.control:before{visibility:visible;display:block;margin-right:0} .control-filelist ul li>div.controls a.control:hover{opacity:1;filter:alpha(opacity=100)} .control-filelist ul li:hover>div.controls, -.control-filelist ul li:hover>a.control{display:block !important} +.control-filelist ul li:hover>a.control{display:block!important} .control-filelist ul li:hover>div.controls>a.control, -.control-filelist ul li:hover>a.control>a.control{display:block !important} +.control-filelist ul li:hover>a.control>a.control{display:block!important} .control-filelist ul li .checkbox{position:absolute;top:-5px;right:0} .control-filelist ul li .checkbox label{margin-right:0} .control-filelist ul li .checkbox label:before{border-color:#ccc} .control-filelist.single-line ul li a span.title{text-overflow:ellipsis;overflow:hidden;white-space:nowrap} .control-filelist.filelist-hero ul li{background:#fff;border-bottom:none} -.control-filelist.filelist-hero ul li>a{padding:11px 45px 10px 50px;font-size:13px;border-bottom:1px solid #ecf0f1} +.control-filelist.filelist-hero ul li>a{padding:11px 45px 10px 50px;font-size:13px;border-bottom:1px solid #ECF0F1} .control-filelist.filelist-hero ul li>a span.title{font-size:14px;font-weight:normal;color:#2b3e50} .control-filelist.filelist-hero ul li>a span.description{font-size:13px} .control-filelist.filelist-hero ul li>a .list-icon{position:absolute;left:14px;top:50%;transform:translateY(-50%);font-size:22px;color:#b7c0c2} @@ -225,13 +225,13 @@ html.mobile .control-scrollbar{overflow:auto;-webkit-overflow-scrolling:touch} .control-filelist.filelist-hero ul li.active>a>span.borders:before{top:-1px} .control-filelist.filelist-hero ul li.active>a:hover>span.borders:before{background-color:#48b2ce} .control-filelist.filelist-hero ul li.active>a:active>span.borders:before{background-color:#6cc551} -.control-filelist.filelist-hero ul li>h4{padding-top:7px;padding-bottom:6px;border-bottom:1px solid #ecf0f1} +.control-filelist.filelist-hero ul li>h4{padding-top:7px;padding-bottom:6px;border-bottom:1px solid #ECF0F1} .control-filelist.filelist-hero ul li>div.controls{display:none;position:absolute;right:16px;top:15px} .control-filelist.filelist-hero ul li>div.controls>a.control{width:16px;height:23px;background:transparent;overflow:hidden;display:inline-block;color:#fff !important;padding:0} .control-filelist.filelist-hero ul li>div.controls>a.control:before{font-size:17px} .control-filelist.filelist-hero ul li:hover>div.controls{display:block} .control-filelist.filelist-hero ul li.separator{position:relative;border-bottom:1px solid #95a5a6;padding:12px 15px 13px 15px} -.control-filelist.filelist-hero ul li.separator:before{z-index:31;content:'';display:block;width:0;height:0;border-left:9.5px solid transparent;border-right:9.5px solid transparent;border-top:11px solid #fff;border-bottom-width:0;position:absolute;left:13px;bottom:-8px} +.control-filelist.filelist-hero ul li.separator:before{z-index:31;content:'';display:block;width:0;height:0;border-left:9.5px solid transparent;border-right:9.5px solid transparent;border-top:11px solid white;border-bottom-width:0;position:absolute;left:13px;bottom:-8px} .control-filelist.filelist-hero ul li.separator:after{z-index:30;content:'';display:block;width:0;height:0;border-left:8.5px solid transparent;border-right:8.5px solid transparent;border-top:9px solid #95a5a6;border-bottom-width:0;position:absolute;left:14px;bottom:-9px} .control-filelist.filelist-hero ul li.separator h5{color:#2b3e50;font-size:14px;margin:0;font-weight:normal;padding:0} .control-filelist.filelist-hero ul>li.group>ul>li>a{padding-left:66px} @@ -245,7 +245,7 @@ html.mobile .control-scrollbar{overflow:auto;-webkit-overflow-scrolling:touch} .control-filelist.filelist-hero.single-level ul li:active>a span.title, .control-filelist.filelist-hero.single-level ul li:active>a span.description{color:#fff !important} .control-filelist.filelist-hero.single-level ul li:active>a .list-icon{color:#fff !important} -.control-scrollpanel{position:relative;background:#ecf0f1} +.control-scrollpanel{position:relative;background:#ECF0F1} .control-scrollpanel .control-scrollbar.vertical>.scrollbar-scrollbar{right:0} .tooltip .tooltip-inner{text-align:left;padding:5px 8px} .tooltip.in{opacity:1;filter:alpha(opacity=100)} @@ -301,7 +301,7 @@ html.mobile .control-scrollbar{overflow:auto;-webkit-overflow-scrolling:touch} .control-treeview{margin-bottom:40px} .control-treeview ol{margin:0;padding:0;list-style:none;background:#fff} .control-treeview ol>li{-webkit-transition:width 1s;transition:width 1s} -.control-treeview ol>li>div{font-size:14px;font-weight:normal;background:#fff;border-bottom:1px solid #ecf0f1;position:relative} +.control-treeview ol>li>div{font-size:14px;font-weight:normal;background:#fff;border-bottom:1px solid #ECF0F1;position:relative} .control-treeview ol>li>div>a{color:#2b3e50;padding:11px 45px 10px 61px;display:block;line-height:150%;text-decoration:none;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box} .control-treeview ol>li>div:before{content:' ';background-image:url(../images/treeview-icons.png);background-position:0 -28px;background-repeat:no-repeat;background-size:42px auto;position:absolute;width:21px;height:22px;left:28px;top:15px} .control-treeview ol>li>div span.comment{display:block;font-weight:400;color:#95a5a6;font-size:13px;margin-top:2px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap} @@ -330,7 +330,7 @@ html.mobile .control-scrollbar{overflow:auto;-webkit-overflow-scrolling:touch} .control-treeview ol>li>div.popover-highlight>a{color:#fff !important;cursor:default} .control-treeview ol>li>div.popover-highlight span{color:#fff !important} .control-treeview ol>li>div.popover-highlight>ul.submenu, -.control-treeview ol>li>div.popover-highlight>span.drag-handle{display:none !important} +.control-treeview ol>li>div.popover-highlight>span.drag-handle{display:none!important} .control-treeview ol>li.dragged div, .control-treeview ol>li>div:hover{background-color:#48b2ce !important} .control-treeview ol>li.dragged div>a, @@ -347,10 +347,10 @@ html.mobile .control-scrollbar{overflow:auto;-webkit-overflow-scrolling:touch} .control-treeview ol>li>div:hover span.borders{display:none} .control-treeview ol>li>div:active{background-color:#6cc551 !important} .control-treeview ol>li>div:active>a{color:#fff !important} -.control-treeview ol>li[data-no-drag-mode] div:hover span.drag-handle{cursor:default !important;opacity:0.3 !important;filter:alpha(opacity=30) !important} +.control-treeview ol>li[data-no-drag-mode] div:hover span.drag-handle{cursor:default!important;opacity:0.3 !important;filter:alpha(opacity=30) !important} .control-treeview ol>li.dragged li.has-subitems>div:before, .control-treeview ol>li.dragged.has-subitems>div:before{background-position:0 -52px} -.control-treeview ol>li.dragged div>ul.submenu{display:none !important} +.control-treeview ol>li.dragged div>ul.submenu{display:none!important} .control-treeview ol>li>ol{padding-left:20px;padding-right:20px} .control-treeview ol>li[data-status=collapsed]>ol{display:none} .control-treeview ol>li.has-subitems>div:before{background-position:0 0;width:23px;height:26px;left:26px} @@ -447,7 +447,7 @@ body.dragging .control-treeview ol.dragging>li>div .custom-checkbox, body.dragging .control-treeview ol.dragging ol>li>div .custom-checkbox{-webkit-transition:opacity 0.5s;transition:opacity 0.5s;opacity:0;filter:alpha(opacity=0)} body.dragging .control-treeview.treeview-light ol.dragging>li>div, body.dragging .control-treeview.treeview-light ol.dragging ol>li>div{background-color:#f9f9f9} -@media only screen and (min--moz-device-pixel-ratio:1.5),only screen and (-o-min-device-pixel-ratio:3/2),only screen and (-webkit-min-device-pixel-ratio:1.5),only screen and (min-devicepixel-ratio:1.5),only screen and (min-resolution:1.5dppx){.control-treeview ol>li>div:before{background-position:0 -79px;background-size:21px auto}.control-treeview ol>li.has-subitems>div:before{background-position:0 -52px}.control-treeview ol>li.has-subitems>div:hover:before,.control-treeview ol>li.has-subitems>div.popover-highlight:before{background-position:0 -102px}.control-treeview ol>li.dragged>div:before,.control-treeview ol>li.dragged li>div:before,.control-treeview ol>li>div:hover:before,.control-treeview ol>li>div.popover-highlight:before{background-position:0 -129px}.control-treeview ol>li.dragged li.has-subitems>div:before,.control-treeview ol>li.dragged.has-subitems>div:before{background-position:0 -102px}.control-treeview ol>li.drop-target>div:before{background-position:0 -129px}.control-treeview ol>li.drop-target.has-subitems>div:before{background-position:0 -102px}} +@media only screen and (min--moz-device-pixel-ratio:1.5),only screen and (-o-min-device-pixel-ratio:1.5),only screen and (-webkit-min-device-pixel-ratio:1.5),only screen and (min-devicepixel-ratio:1.5),only screen and (min-resolution:1.5dppx){.control-treeview ol>li>div:before{background-position:0 -79px;background-size:21px auto}.control-treeview ol>li.has-subitems>div:before{background-position:0 -52px}.control-treeview ol>li.has-subitems>div:hover:before,.control-treeview ol>li.has-subitems>div.popover-highlight:before{background-position:0 -102px}.control-treeview ol>li.dragged>div:before,.control-treeview ol>li.dragged li>div:before,.control-treeview ol>li>div:hover:before,.control-treeview ol>li>div.popover-highlight:before{background-position:0 -129px}.control-treeview ol>li.dragged li.has-subitems>div:before,.control-treeview ol>li.dragged.has-subitems>div:before{background-position:0 -102px}.control-treeview ol>li.drop-target>div:before{background-position:0 -129px}.control-treeview ol>li.drop-target.has-subitems>div:before{background-position:0 -102px}} .sidenav-tree{width:300px} .sidenav-tree .control-toolbar{padding:0} .sidenav-tree .control-toolbar .toolbar-item{display:block} @@ -494,7 +494,7 @@ div.panel.border-right{border-right:1px solid #e8eaeb} div.panel.border-bottom{border-bottom:1px solid #e8eaeb} div.panel.border-top{border-top:1px solid #e8eaeb} div.panel.triangle-down{position:relative} -div.panel.triangle-down:after{content:'';display:block;width:0;height:0;border-left:7.5px solid transparent;border-right:7.5px solid transparent;border-top:8px solid #fff;border-bottom-width:0;position:absolute;left:15px;bottom:-8px;z-index:101} +div.panel.triangle-down:after{content:'';display:block;width:0;height:0;border-left:7.5px solid transparent;border-right:7.5px solid transparent;border-top:8px solid white;border-bottom-width:0;position:absolute;left:15px;bottom:-8px;z-index:101} div.panel.triangle-down:before{content:'';display:block;width:0;height:0;border-left:8.5px solid transparent;border-right:8.5px solid transparent;border-top:9px solid #e8eaeb;border-bottom-width:0;position:absolute;left:14px;bottom:-9px;z-index:100} div.panel h3.section, div.panel>label{text-transform:uppercase;color:#95a5a6;font-size:13px;font-weight:600;margin:0 0 15px 0} @@ -650,7 +650,7 @@ body.slim-container .layout .layout-container{padding-left:0 !important;padding- @supports (-moz-appearance:none){a:focus:not(:focus-visible){outline:none}} .flex-layout-column{display:-webkit-box;display:-webkit-flex;display:-moz-flex;display:-ms-flexbox;display:-ms-flex;display:flex;-webkit-flex-direction:column;-moz-flex-direction:column;-webkit-box-orient:vertical;-ms-flex-direction:column;flex-direction:column} .flex-layout-column.full-height-strict{height:100%} -.flex-layout-column.absolute{position:absolute !important} +.flex-layout-column.absolute{position:absolute!important} .flex-layout-column.fill-container{position:absolute;left:0;top:0;width:100%;height:100%} .flex-layout-row{display:-webkit-box;display:-webkit-flex;display:-moz-flex;display:-ms-flexbox;display:-ms-flex;display:flex;-webkit-flex-direction:row;-moz-flex-direction:row;-webkit-box-orient:horizontal;-ms-flex-direction:row;flex-direction:row} .flex-layout-column.justify-center, @@ -671,7 +671,7 @@ body.mainmenu-open{overflow:hidden;position:fixed} ul.mainmenu-nav{font-size:14px} ul.mainmenu-nav li{} ul.mainmenu-nav li .svg-icon{-webkit-backface-visibility:hidden;backface-visibility:hidden} -ul.mainmenu-nav li span.counter{display:block;position:absolute;top:.143em;right:0;padding:.143em .429em .214em .286em;background-color:#d9350f;color:#fff;font-size:.786em;line-height:100%;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;opacity:1;filter:alpha(opacity=100);-webkit-transform:scale(1,);-ms-transform:scale(1,);transform:scale(1,);-webkit-transition:all 0.3s;transition:all 0.3s} +ul.mainmenu-nav li span.counter{display:block;position:absolute;top:0.143em;right:0;padding:0.143em 0.429em 0.214em 0.286em;background-color:#d9350f;color:#fff;font-size:0.786em;line-height:100%;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;opacity:1;filter:alpha(opacity=100);-webkit-transform:scale(1,);-ms-transform:scale(1,);transform:scale(1,);-webkit-transition:all 0.3s;transition:all 0.3s} ul.mainmenu-nav li span.counter.empty{opacity:0;filter:alpha(opacity=0);-webkit-transform:scale(0,);-ms-transform:scale(0,);transform:scale(0,)} nav#layout-mainmenu{background-color:#151515;padding:0 0 0 20px;line-height:0;white-space:nowrap;display:flex} nav#layout-mainmenu a{text-decoration:none} @@ -758,7 +758,7 @@ nav#layout-mainmenu.navbar-mode-tile ul.mainmenu-nav li:first-child{margin-left: nav#layout-mainmenu.navbar-mode-tile ul.mainmenu-nav li:hover .nav-label{width:auto;min-width:100px;text-overflow:all;overflow:visible;z-index:2} nav#layout-mainmenu.navbar-mode-tile ul.mainmenu-nav li.active:first-child{margin-left:0} nav#layout-mainmenu .menu-toggle{height:45px;line-height:45px;font-size:16px;display:none} -nav#layout-mainmenu .menu-toggle .menu-toggle-icon{background:#333;display:inline-block;height:45px;line-height:45px;width:45px;text-align:center;opacity:.7} +nav#layout-mainmenu .menu-toggle .menu-toggle-icon{background:#333;display:inline-block;height:45px;line-height:45px;width:45px;text-align:center;opacity:0.7} nav#layout-mainmenu .menu-toggle .menu-toggle-icon i{line-height:45px;font-size:20px;vertical-align:bottom} nav#layout-mainmenu .menu-toggle .menu-toggle-title{margin-left:10px} nav#layout-mainmenu .menu-toggle:hover .menu-toggle-icon{opacity:1} @@ -820,7 +820,7 @@ body.drag .mainmenu-collapsed ul li:hover{color:rgba(255,255,255,0.6)} #layout-sidenav{position:absolute;height:100%;width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;font-size:14px} #layout-sidenav ul{position:relative;margin:0;padding:0;height:100%;overflow:hidden} #layout-sidenav ul li{display:block;text-align:center;position:relative} -#layout-sidenav ul li a{padding:1.429em .714em;display:block;font-size:.929em;color:rgba(255,255,255,0.6);font-weight:normal;position:relative} +#layout-sidenav ul li a{padding:1.429em 0.714em;display:block;font-size:0.929em;color:rgba(255,255,255,0.6);font-weight:normal;position:relative} #layout-sidenav ul li a:hover{text-decoration:none;background-color:transparent} #layout-sidenav ul li a:focus{background:transparent} #layout-sidenav ul li a i{color:rgba(255,255,255,0.6);display:block;margin-bottom:5px;font-size:2em} @@ -829,7 +829,7 @@ body.drag .mainmenu-collapsed ul li:hover{color:rgba(255,255,255,0.6)} #layout-sidenav ul li a:hover{color:#fff} #layout-sidenav ul li.active a i, #layout-sidenav ul li a:hover i{color:#fff} -#layout-sidenav ul li span.counter{display:block;position:absolute;top:1.071em;right:1.071em;padding:.143em .429em .214em .286em;background-color:#d9350f;color:#fff;font-size:.786em;line-height:100%;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;opacity:1;filter:alpha(opacity=100);-webkit-transform:scale(1,);-ms-transform:scale(1,);transform:scale(1,);-webkit-transition:all 0.3s;transition:all 0.3s} +#layout-sidenav ul li span.counter{display:block;position:absolute;top:1.071em;right:1.071em;padding:0.143em 0.429em 0.214em 0.286em;background-color:#d9350f;color:#fff;font-size:0.786em;line-height:100%;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;opacity:1;filter:alpha(opacity=100);-webkit-transform:scale(1,);-ms-transform:scale(1,);transform:scale(1,);-webkit-transition:all 0.3s;transition:all 0.3s} #layout-sidenav ul li span.counter.empty{opacity:0;filter:alpha(opacity=0);-webkit-transform:scale(0,);-ms-transform:scale(0,);transform:scale(0,)} @media (min-width:768px) and (max-width:991px){#layout-sidenav{font-size:12px}.layout-sidenav-container{width:100px}} @media (max-width:767px){#layout-sidenav{font-size:10px}.layout-sidenav-container{width:80px}} @@ -955,7 +955,7 @@ body.fancy-layout .master-tabs.control-tabs>.tab-content>.tab-pane.padded-pane, .fancy-layout *:not(.nested-form)>.form-widget>.layout-row>.control-tabs.primary-tabs.master-area>div>ul.nav-tabs, *:not(.nested-form)>.form-widget>.layout-row>.control-tabs.fancy-layout.primary-tabs.master-area>div>ul.nav-tabs{-webkit-transition:background-color 0.5s;transition:background-color 0.5s;background:#2da7c7} .fancy-layout *:not(.nested-form)>.form-widget>.layout-row>.control-tabs.primary-tabs>div>ul.nav-tabs, -*:not(.nested-form)>.form-widget>.layout-row>.control-tabs.fancy-layout.primary-tabs>div>ul.nav-tabs{background:#7f8c8d;margin-left:0 !important;margin-right:0 !important} +*:not(.nested-form)>.form-widget>.layout-row>.control-tabs.fancy-layout.primary-tabs>div>ul.nav-tabs{background:#7F8C8D;margin-left:0!important;margin-right:0!important} .fancy-layout *:not(.nested-form)>.form-widget>.layout-row>.control-tabs.primary-tabs>div>ul.nav-tabs:before, *:not(.nested-form)>.form-widget>.layout-row>.control-tabs.fancy-layout.primary-tabs>div>ul.nav-tabs:before{display:none} .fancy-layout *:not(.nested-form)>.form-widget>.layout-row>.control-tabs.primary-tabs>div>ul.nav-tabs>li, @@ -1011,7 +1011,7 @@ body.fancy-layout .master-tabs.control-tabs>.tab-content>.tab-pane.padded-pane, .fancy-layout *:not(.nested-form)>.form-widget>.layout-row>.control-tabs.secondary-tabs.secondary-content-tabs>div>ul.nav-tabs>li{margin-left:-19px} .fancy-layout *:not(.nested-form)>.form-widget>.layout-row>.control-tabs.secondary-tabs.secondary-content-tabs>div>ul.nav-tabs>li:first-child{margin-left:0;padding-left:8px} .fancy-layout *:not(.nested-form)>.form-widget>.layout-row>.control-tabs.secondary-tabs.secondary-content-tabs>div>ul.nav-tabs>li a{padding:8px 16px 0 16px;font-weight:400;height:36px;color:#2b3e50;opacity:0.6;filter:alpha(opacity=60)} -.fancy-layout *:not(.nested-form)>.form-widget>.layout-row>.control-tabs.secondary-tabs.secondary-content-tabs>div>ul.nav-tabs>li a>span.title{position:relative;display:inline-block;padding:8px 5px 9px 5px;font-size:14px;z-index:100;height:27px !important;background-color:transparent} +.fancy-layout *:not(.nested-form)>.form-widget>.layout-row>.control-tabs.secondary-tabs.secondary-content-tabs>div>ul.nav-tabs>li a>span.title{position:relative;display:inline-block;padding:8px 5px 9px 5px;font-size:14px;z-index:100;height:27px!important;background-color:transparent} .fancy-layout *:not(.nested-form)>.form-widget>.layout-row>.control-tabs.secondary-tabs.secondary-content-tabs>div>ul.nav-tabs>li a>span.title:before, .fancy-layout *:not(.nested-form)>.form-widget>.layout-row>.control-tabs.secondary-tabs.secondary-content-tabs>div>ul.nav-tabs>li a>span.title:after{content:' ';position:absolute;background-color:white;width:15px;height:28px;top:0;z-index:100;display:none} .fancy-layout *:not(.nested-form)>.form-widget>.layout-row>.control-tabs.secondary-tabs.secondary-content-tabs>div>ul.nav-tabs>li a>span.title:before{left:-11px;-webkit-border-radius:8px 0 0 0;-moz-border-radius:8px 0 0 0;border-radius:8px 0 0 0;-webkit-transform:skewX(-20deg);-ms-transform:skewX(-20deg);transform:skewX(-20deg)} @@ -1035,6 +1035,7 @@ body.fancy-layout .master-tabs.control-tabs>.tab-content>.tab-pane.padded-pane, .fancy-layout *:not(.nested-form)>.form-widget>.layout-row>.form-tabless-fields:after{content:" ";display:table} .fancy-layout *:not(.nested-form)>.form-widget>.layout-row>.form-tabless-fields:after{clear:both} .fancy-layout *:not(.nested-form)>.form-widget>.layout-row>.form-tabless-fields label{text-transform:uppercase;color:rgba(255,255,255,0.5);margin-bottom:0} +.fancy-layout *:not(.nested-form)>.form-widget>.layout-row>.form-tabless-fields .form-control[disabled]{background-color:rgba(29,29,29,0.11) !important} .fancy-layout *:not(.nested-form)>.form-widget>.layout-row>.form-tabless-fields input[type=text]{background:transparent;border:none;color:#fff;font-size:35px;font-weight:100;height:auto;padding:0;-webkit-box-shadow:none;box-shadow:none} .fancy-layout *:not(.nested-form)>.form-widget>.layout-row>.form-tabless-fields input[type=text]::-moz-placeholder{color:rgba(255,255,255,0.5);opacity:1} .fancy-layout *:not(.nested-form)>.form-widget>.layout-row>.form-tabless-fields input[type=text]:-ms-input-placeholder{color:rgba(255,255,255,0.5)} @@ -1059,11 +1060,11 @@ body.breadcrumb-fancy .control-breadcrumb, body.breadcrumb-fancy .control-breadcrumb li, .control-breadcrumb.breadcrumb-fancy li{background-color:#0e7d9a;color:rgba(255,255,255,0.5)} body.breadcrumb-fancy .control-breadcrumb li a, -.control-breadcrumb.breadcrumb-fancy li a{opacity:.5;-webkit-transition:all 0.3s ease;transition:all 0.3s ease} +.control-breadcrumb.breadcrumb-fancy li a{opacity:0.5;-webkit-transition:all 0.3s ease;transition:all 0.3s ease} body.breadcrumb-fancy .control-breadcrumb li a:hover, .control-breadcrumb.breadcrumb-fancy li a:hover{opacity:1} body.breadcrumb-fancy .control-breadcrumb li:not(:last-child)::before, -.control-breadcrumb.breadcrumb-fancy li:not(:last-child)::before{border-left-color:#2da7c7;opacity:.5} +.control-breadcrumb.breadcrumb-fancy li:not(:last-child)::before{border-left-color:#2da7c7;opacity:0.5} body.breadcrumb-fancy .control-breadcrumb li:after, .control-breadcrumb.breadcrumb-fancy li:after{border-left-color:#0e7d9a} body.breadcrumb-fancy .control-breadcrumb li:last-child, @@ -1097,7 +1098,7 @@ body.breadcrumb-fancy .control-breadcrumb li:last-child:before, body.side-panel-not-fixed .fancy-layout *:not(.nested-form)>.form-widget>.layout-row>.control-tabs>.tab-content>.tab-pane>.form-group>.field-richeditor, body.side-panel-not-fixed.fancy-layout *:not(.nested-form)>.form-widget>.layout-row>.control-tabs>.tab-content>.tab-pane>.form-group>.field-richeditor{border-left:none} html.cssanimations .fancy-layout *:not(.nested-form)>.form-widget>.layout-row>.form-tabless-fields .loading-indicator-container .loading-indicator>span{-webkit-animation:spin 1s linear infinite;animation:spin 1s linear infinite;background-image:url('../../../system/assets/ui/images/loader-white.svg');background-size:20px 20px} -.flyout-container>.flyout{overflow:hidden;width:0;left:0 !important;-webkit-transition:width 0.1s;transition:width 0.1s} +.flyout-container>.flyout{overflow:hidden;width:0;left:0!important;-webkit-transition:width 0.1s;transition:width 0.1s} .flyout-overlay{width:100%;height:100%;top:0;z-index:5000;position:absolute;background-color:rgba(0,0,0,0);-webkit-transition:background-color 0.3s;transition:background-color 0.3s} .flyout-toggle{position:absolute;top:20px;left:0;width:23px;height:25px;background:#2b3e50;cursor:pointer;border-bottom-right-radius:4px;border-top-right-radius:4px;color:#bdc3c7;font-size:10px} .flyout-toggle i{margin:7px 0 0 6px;display:inline-block} diff --git a/modules/backend/assets/less/layout/fancylayout.less b/modules/backend/assets/less/layout/fancylayout.less index 61681fdc40..3fa21146fb 100644 --- a/modules/backend/assets/less/layout/fancylayout.less +++ b/modules/backend/assets/less/layout/fancylayout.less @@ -493,6 +493,10 @@ body.fancy-layout .master-tabs.control-tabs, margin-bottom: 0; } + .form-control[disabled] { + background-color: rgba(29, 29, 29, 0.11) !important; + } + input[type=text] { background: transparent; border: none; diff --git a/modules/backend/behaviors/FormController.php b/modules/backend/behaviors/FormController.php index ae58bb475f..1b6c125296 100644 --- a/modules/backend/behaviors/FormController.php +++ b/modules/backend/behaviors/FormController.php @@ -191,7 +191,9 @@ public function initForm($model, $context = null) protected function prepareVars($model) { $this->controller->vars['formModel'] = $model; + $this->controller->vars['formConfig'] = $this->getConfig(); $this->controller->vars['formContext'] = $this->formGetContext(); + $this->controller->vars['formController'] = $this; $this->controller->vars['formRecordName'] = Lang::get($this->getConfig('name', 'backend::lang.model.name')); } @@ -473,6 +475,10 @@ public function makeRedirect($context = null, $model = null) return Redirect::refresh(); } + if (post('new', false)) { + return Redirect::to($this->controller->actionUrl('create')); + } + if (post('redirect', true)) { $redirectUrl = $this->controller->formGetRedirectUrl($context, $model); } @@ -882,4 +888,20 @@ public static function extendFormFields($callback) call_user_func_array($callback, [$widget, $widget->model, $widget->getContext()]); }); } + + /** + * Controller accessor for making partials within this behavior. + */ + public function formMakePartial(string $partial, array $params = []): string + { + $contents = $this->controller->makePartial('form_' . $this->context . '_' . $partial, $params + $this->vars, false); + if (!$contents) { + $contents = $this->controller->makePartial('form_' . $partial, $params + $this->vars, false); + } + if (!$contents) { + $contents = $this->makePartial($partial, $params); + } + + return $contents; + } } diff --git a/modules/backend/behaviors/ImportExportController.php b/modules/backend/behaviors/ImportExportController.php index 057a0758a3..d8a4a02360 100644 --- a/modules/backend/behaviors/ImportExportController.php +++ b/modules/backend/behaviors/ImportExportController.php @@ -1,21 +1,22 @@ -checkPermissionsForType('import')) { - return $response; + if (!$this->userHasAccess('import')) { + abort(403); } $this->addJs('js/winter.import.js', 'core'); @@ -161,8 +162,8 @@ public function import() public function export() { - if ($response = $this->checkPermissionsForType('export')) { - return $response; + if (!$this->userHasAccess('export')) { + abort(403); } if ($response = $this->checkUseListExportMode()) { @@ -697,18 +698,18 @@ public function importExportMakePartial($partial, $params = []) } /** - * Checks to see if the import/export is controlled by permissions - * and if the logged in user has permissions. - * @return \View + * Check if the current user has access to the provided import/export action */ - protected function checkPermissionsForType($type) + public function userHasAccess(string $type): bool { if ( ($permissions = $this->getConfig($type.'[permissions]')) && (!BackendAuth::getUser()->hasAnyAccess((array) $permissions)) ) { - return Response::make(View::make('backend::access_denied'), 403); + return false; } + + return true; } protected function makeOptionsFormWidgetForType($type) diff --git a/modules/backend/behaviors/formcontroller/partials/_toolbar.php b/modules/backend/behaviors/formcontroller/partials/_toolbar.php new file mode 100644 index 0000000000..64e67a637e --- /dev/null +++ b/modules/backend/behaviors/formcontroller/partials/_toolbar.php @@ -0,0 +1,81 @@ +name ?? ''; +?> + +
+ + + + + + +
+ +
+ + + + + + +
+ diff --git a/modules/backend/behaviors/formcontroller/views/create.php b/modules/backend/behaviors/formcontroller/views/create.php new file mode 100644 index 0000000000..12080a6fc8 --- /dev/null +++ b/modules/backend/behaviors/formcontroller/views/create.php @@ -0,0 +1,20 @@ +formLayout ?? $formConfig->formLayout ?? null; +if (!in_array($layout, ['standard', 'sidebar', 'fancy'])) { + $layout = 'standard'; +} + +// If required, set the appropriate body classes +$this->bodyClass = match ($layout) { + 'fancy' => 'fancy-layout compact-container breadcrumb-flush breadcrumb-fancy', + 'sidebar' => 'compact-container', + default => '', +}; + +// Define layout mode view path for inclusion +$this->appendViewPath(sprintf('%s/create/%s', __DIR__, $layout)); + +// Render the form layout +echo $this->makePartial(sprintf('create/%s.php', $layout)); diff --git a/modules/backend/behaviors/formcontroller/views/create/_fancy.php b/modules/backend/behaviors/formcontroller/views/create/_fancy.php new file mode 100644 index 0000000000..2358dfc9d0 --- /dev/null +++ b/modules/backend/behaviors/formcontroller/views/create/_fancy.php @@ -0,0 +1,20 @@ + + makeLayoutPartial('breadcrumb') ?> + + +fatalError): ?> +
+ 'layout', + 'data-change-monitor' => 'true', + 'data-window-close-confirm' => 'true', + ]) ?> +
+ formRender() ?> +
+ +
+ +

fatalError) ?>

+

+ diff --git a/modules/backend/behaviors/formcontroller/views/create/_sidebar.php b/modules/backend/behaviors/formcontroller/views/create/_sidebar.php new file mode 100644 index 0000000000..f278789de0 --- /dev/null +++ b/modules/backend/behaviors/formcontroller/views/create/_sidebar.php @@ -0,0 +1,40 @@ + + makeLayoutPartial('breadcrumb') ?> + + +fatalError): ?> + +
+
+ formRenderOutsideFields() ?> + formRenderPrimaryTabs() ?> +
+ +
+ formMakePartial('toolbar') ?> +
+
+ + + +
formRenderSecondaryTabs() ?>
+ + + + 'layout stretch', + 'data-change-monitor' => 'true', + 'data-window-close-confirm' => 'true', + ]) ?> + makeLayout('form-with-sidebar') ?> + + + +
+ +
+
+

fatalError)) ?>

+

+
+ diff --git a/modules/backend/behaviors/formcontroller/views/create/_standard.php b/modules/backend/behaviors/formcontroller/views/create/_standard.php new file mode 100644 index 0000000000..7b88ff8b33 --- /dev/null +++ b/modules/backend/behaviors/formcontroller/views/create/_standard.php @@ -0,0 +1,22 @@ + + makeLayoutPartial('breadcrumb') ?> + + +fatalError): ?> + 'layout', + 'data-change-monitor' => 'true', + 'data-window-close-confirm' => 'true', + ]) ?> +
+ formRender() ?> +
+ +
+ formMakePartial('toolbar') ?> +
+ + +

fatalError) ?>

+

+ diff --git a/modules/backend/behaviors/formcontroller/views/create/fancy/_toolbar.php b/modules/backend/behaviors/formcontroller/views/create/fancy/_toolbar.php new file mode 100644 index 0000000000..df4540d560 --- /dev/null +++ b/modules/backend/behaviors/formcontroller/views/create/fancy/_toolbar.php @@ -0,0 +1,36 @@ +
+ + + + + +
diff --git a/modules/backend/behaviors/formcontroller/views/preview.php b/modules/backend/behaviors/formcontroller/views/preview.php new file mode 100644 index 0000000000..1429909ce1 --- /dev/null +++ b/modules/backend/behaviors/formcontroller/views/preview.php @@ -0,0 +1,21 @@ +formLayout ?? $formConfig->formLayout ?? null; +if (!in_array($layout, ['standard', 'sidebar', 'fancy'])) { + $layout = 'standard'; +} + +// If required, set the appropriate body classes +$this->bodyClass = match ($layout) { + 'fancy' => 'fancy-layout compact-container breadcrumb-flush breadcrumb-fancy', + 'sidebar' => 'compact-container', + default => '', +}; + +// Define layout mode view path for inclusion +$this->appendViewPath(sprintf('%s/preview/%s', __DIR__, $layout)); + +// Render the form layout +echo $this->makePartial(sprintf('preview/%s.php', $layout)); diff --git a/modules/backend/behaviors/formcontroller/views/preview/_fancy.php b/modules/backend/behaviors/formcontroller/views/preview/_fancy.php new file mode 100644 index 0000000000..e7f9176c01 --- /dev/null +++ b/modules/backend/behaviors/formcontroller/views/preview/_fancy.php @@ -0,0 +1,14 @@ + + makeLayoutPartial('breadcrumb') ?> + + +fatalError): ?> + 'layout']) ?> +
+ formRenderPreview() ?> +
+ + +

fatalError) ?>

+

+ diff --git a/modules/backend/behaviors/formcontroller/views/preview/_sidebar.php b/modules/backend/behaviors/formcontroller/views/preview/_sidebar.php new file mode 100644 index 0000000000..ab51d25c0f --- /dev/null +++ b/modules/backend/behaviors/formcontroller/views/preview/_sidebar.php @@ -0,0 +1,32 @@ + + makeLayoutPartial('breadcrumb') ?> + + +fatalError): ?> + +
+
+ formRenderOutsideFields() ?> + formRenderPrimaryTabs() ?> +
+
+ + + +
formRenderSecondaryTabs() ?>
+ + + + 'layout stretch']) ?> + makeLayout('form-with-sidebar') ?> + + + +
+ +
+
+

fatalError)) ?>

+

+
+ diff --git a/modules/backend/behaviors/formcontroller/views/preview/_standard.php b/modules/backend/behaviors/formcontroller/views/preview/_standard.php new file mode 100644 index 0000000000..4098a0fe0d --- /dev/null +++ b/modules/backend/behaviors/formcontroller/views/preview/_standard.php @@ -0,0 +1,12 @@ + + makeLayoutPartial('breadcrumb') ?> + + +fatalError): ?> +
+ formRenderPreview() ?> +
+ +

fatalError) ?>

+

+ diff --git a/modules/backend/behaviors/formcontroller/views/preview/fancy/_toolbar.php b/modules/backend/behaviors/formcontroller/views/preview/fancy/_toolbar.php new file mode 100644 index 0000000000..94212553b3 --- /dev/null +++ b/modules/backend/behaviors/formcontroller/views/preview/fancy/_toolbar.php @@ -0,0 +1 @@ +
diff --git a/modules/backend/behaviors/formcontroller/views/update.php b/modules/backend/behaviors/formcontroller/views/update.php new file mode 100644 index 0000000000..eb439c1f9a --- /dev/null +++ b/modules/backend/behaviors/formcontroller/views/update.php @@ -0,0 +1,20 @@ +formLayout ?? $formConfig->formLayout ?? null; +if (!in_array($layout, ['standard', 'sidebar', 'fancy'])) { + $layout = 'standard'; +} + +// If required, set the appropriate body classes +$this->bodyClass .= match ($layout) { + 'fancy' => ' fancy-layout compact-container breadcrumb-flush breadcrumb-fancy', + 'sidebar' => ' compact-container', + default => '', +}; + +// Define layout mode view path for inclusion +$this->appendViewPath(sprintf('%s/update/%s', __DIR__, $layout)); + +// Render the form layout +echo $this->makePartial(sprintf('update/%s.php', $layout)); diff --git a/modules/backend/behaviors/formcontroller/views/update/_fancy.php b/modules/backend/behaviors/formcontroller/views/update/_fancy.php new file mode 100644 index 0000000000..2358dfc9d0 --- /dev/null +++ b/modules/backend/behaviors/formcontroller/views/update/_fancy.php @@ -0,0 +1,20 @@ + + makeLayoutPartial('breadcrumb') ?> + + +fatalError): ?> +
+ 'layout', + 'data-change-monitor' => 'true', + 'data-window-close-confirm' => 'true', + ]) ?> +
+ formRender() ?> +
+ +
+ +

fatalError) ?>

+

+ diff --git a/modules/backend/behaviors/formcontroller/views/update/_sidebar.php b/modules/backend/behaviors/formcontroller/views/update/_sidebar.php new file mode 100644 index 0000000000..f278789de0 --- /dev/null +++ b/modules/backend/behaviors/formcontroller/views/update/_sidebar.php @@ -0,0 +1,40 @@ + + makeLayoutPartial('breadcrumb') ?> + + +fatalError): ?> + +
+
+ formRenderOutsideFields() ?> + formRenderPrimaryTabs() ?> +
+ +
+ formMakePartial('toolbar') ?> +
+
+ + + +
formRenderSecondaryTabs() ?>
+ + + + 'layout stretch', + 'data-change-monitor' => 'true', + 'data-window-close-confirm' => 'true', + ]) ?> + makeLayout('form-with-sidebar') ?> + + + +
+ +
+
+

fatalError)) ?>

+

+
+ diff --git a/modules/backend/behaviors/formcontroller/views/update/_standard.php b/modules/backend/behaviors/formcontroller/views/update/_standard.php new file mode 100644 index 0000000000..7b88ff8b33 --- /dev/null +++ b/modules/backend/behaviors/formcontroller/views/update/_standard.php @@ -0,0 +1,22 @@ + + makeLayoutPartial('breadcrumb') ?> + + +fatalError): ?> + 'layout', + 'data-change-monitor' => 'true', + 'data-window-close-confirm' => 'true', + ]) ?> +
+ formRender() ?> +
+ +
+ formMakePartial('toolbar') ?> +
+ + +

fatalError) ?>

+

+ diff --git a/modules/backend/behaviors/formcontroller/views/update/fancy/_toolbar.php b/modules/backend/behaviors/formcontroller/views/update/fancy/_toolbar.php new file mode 100644 index 0000000000..a7eaf55ec0 --- /dev/null +++ b/modules/backend/behaviors/formcontroller/views/update/fancy/_toolbar.php @@ -0,0 +1,53 @@ +
+ + + + + + + + + + + url): ?> + + + + + + + + + + +
diff --git a/modules/backend/behaviors/importexportcontroller/views/export.php b/modules/backend/behaviors/importexportcontroller/views/export.php new file mode 100644 index 0000000000..6c0be77f72 --- /dev/null +++ b/modules/backend/behaviors/importexportcontroller/views/export.php @@ -0,0 +1,24 @@ + + makeLayoutPartial('breadcrumb') ?> + + + 'layout']) ?> + +
+ exportRender() ?> +
+ +
+
+ +
+
+ + diff --git a/modules/backend/behaviors/importexportcontroller/views/import.php b/modules/backend/behaviors/importexportcontroller/views/import.php new file mode 100644 index 0000000000..f40d5b8d23 --- /dev/null +++ b/modules/backend/behaviors/importexportcontroller/views/import.php @@ -0,0 +1,24 @@ + + makeLayoutPartial('breadcrumb') ?> + + + 'layout']) ?> + +
+ importRender() ?> +
+ +
+
+ +
+
+ + diff --git a/modules/backend/behaviors/listcontroller/views/_list_toolbar.php b/modules/backend/behaviors/listcontroller/views/_list_toolbar.php new file mode 100644 index 0000000000..f1dbb6f822 --- /dev/null +++ b/modules/backend/behaviors/listcontroller/views/_list_toolbar.php @@ -0,0 +1,59 @@ +getClassExtension(\Backend\Behaviors\ListController::class); +$listConfig = $listController->getConfig(); +?> + +
+ isClassExtendedWith(\Backend\Behaviors\FormController::class)): ?> + + trans(\Winter\Storm\Support\Str::before($listConfig->title, '_plural'))])); ?> + + + + showCheckboxes) && $listConfig->showCheckboxes != false): ?> + + + + isClassExtendedWith(\Backend\Behaviors\ReorderController::class)): ?> + + trans($listConfig->title)])); ?> + + + + isClassExtendedWith(\Backend\Behaviors\ImportExportController::class)): ?> +
+ asExtension(\Backend\Behaviors\ImportExportController::class); ?> + userHasAccess('export')): ?> + + + + + userHasAccess('import')): ?> + + + + +
+ +
diff --git a/modules/backend/controllers/users/index.php b/modules/backend/behaviors/listcontroller/views/index.php similarity index 100% rename from modules/backend/controllers/users/index.php rename to modules/backend/behaviors/listcontroller/views/index.php diff --git a/modules/backend/behaviors/reordercontroller/views/_reorder_toolbar.php b/modules/backend/behaviors/reordercontroller/views/_reorder_toolbar.php new file mode 100644 index 0000000000..6320a60db7 --- /dev/null +++ b/modules/backend/behaviors/reordercontroller/views/_reorder_toolbar.php @@ -0,0 +1,5 @@ +
+ + + +
diff --git a/modules/backend/behaviors/reordercontroller/views/reorder.php b/modules/backend/behaviors/reordercontroller/views/reorder.php new file mode 100644 index 0000000000..fc56b60337 --- /dev/null +++ b/modules/backend/behaviors/reordercontroller/views/reorder.php @@ -0,0 +1,5 @@ + + makeLayoutPartial('breadcrumb') ?> + + +reorderRender() ?> diff --git a/modules/backend/classes/BackendController.php b/modules/backend/classes/BackendController.php index 1dfb370d4e..9f73346d24 100644 --- a/modules/backend/classes/BackendController.php +++ b/modules/backend/classes/BackendController.php @@ -1,17 +1,22 @@ -cmsHandling = true; - return App::make('Cms\Classes\Controller')->run($url); - } else { - return Response::make(View::make('backend::404'), 404); + $response = App::make('Cms\Classes\Controller')->run($url); + if ($response->getStatusCode() !== 404 || !BackendAuth::check()) { + return $response; + } } + + return Response::make(View::make('backend::404'), 404); } /** @@ -142,8 +150,17 @@ public function run($url = null) { // Handle NotFoundHttpExceptions in the backend (usually triggered by abort(404)) Event::listen('exception.beforeRender', function ($exception, $httpCode, $request) { - if (!$this->cmsHandling && $exception instanceof \Symfony\Component\HttpKernel\Exception\NotFoundHttpException) { + if ($this->cmsHandling) { + return; + } + + if ($exception instanceof NotFoundHttpException) { return View::make('backend::404'); + } elseif ( + $exception instanceof HttpException + && $exception->getStatusCode() === 403 + ) { + return View::make('backend::access_denied'); } }, 1); diff --git a/modules/backend/classes/Controller.php b/modules/backend/classes/Controller.php index 6616c44006..a4d8a9b151 100644 --- a/modules/backend/classes/Controller.php +++ b/modules/backend/classes/Controller.php @@ -4,6 +4,7 @@ use Backend\Facades\Backend; use Backend\Facades\BackendAuth; +use Backend\Facades\BackendMenu; use Backend\Models\Preference as BackendPreference; use Backend\Models\UserPreference; use Backend\Widgets\MediaManager; @@ -95,7 +96,7 @@ class Controller extends ControllerBase /** * @var string Body class property used for customising the layout on a controller basis. */ - public $bodyClass; + public $bodyClass = ''; /** * @var array Default methods which cannot be called as actions. @@ -199,6 +200,26 @@ public static function __callStatic($name, $params) return self::extendableCallStatic($name, $params); } + /** + * Set the navigation context based on the current action & parameters + */ + protected function setNavigationContext(?string $action = null, array $params = []): void + { + $context = BackendMenu::getContext(); + + // @TODO: Support detecting module controllers as well + $currentClass = explode('\\', get_class($this)); + $author = $currentClass[0]; + $plugin = $currentClass[1]; + $controller = $currentClass[count($currentClass) - 1]; + + $owner = $context->owner ?? "$author.$plugin"; + $mainMenuCode = $context->mainMenuCode ?? strtolower($plugin); + $sideMenuCode = $context->sideMenuCode ?? strtolower($controller); + + BackendMenu::setContext($owner, $mainMenuCode, $sideMenuCode); + } + /** * Execute the controller action. * @param string $action The action name. @@ -248,7 +269,7 @@ public function run($action = null, $params = []) * Check access groups against the page definition */ if ($this->requiredPermissions && !$this->user->hasAnyAccess($this->requiredPermissions)) { - return Response::make(View::make('backend::access_denied'), 403); + abort(403); } } @@ -281,6 +302,11 @@ public function run($action = null, $params = []) BackendPreference::setAppLocale(); BackendPreference::setAppFallbackLocale(); + /* + * Set the navigation context + */ + $this->setNavigationContext($action, $params); + /* * Execute AJAX event */ @@ -671,7 +697,7 @@ protected function runAjaxHandler($handler) */ protected function runAjaxHandlerForWidget($widget, $handler) { - $this->addViewPath($widget->getViewPaths()); + $this->prependViewPath($widget->getViewPaths()); $result = call_user_func_array([$widget, $handler], array_values($this->params)); diff --git a/modules/backend/classes/ControllerBehavior.php b/modules/backend/classes/ControllerBehavior.php index 9b7dbee165..9effeb7285 100644 --- a/modules/backend/classes/ControllerBehavior.php +++ b/modules/backend/classes/ControllerBehavior.php @@ -68,6 +68,9 @@ public function __construct($controller) if (is_array($this->actions)) { $this->hideAction(array_diff(get_class_methods(get_class($this)), $this->actions)); } + + // Include this behavior's default views in the controller's view paths + $this->controller->appendViewPath($this->guessViewPath('/views')); } /** diff --git a/modules/backend/console/CreateController.php b/modules/backend/console/CreateController.php index 1528815323..107e1a3cce 100644 --- a/modules/backend/console/CreateController.php +++ b/modules/backend/console/CreateController.php @@ -20,9 +20,10 @@ class CreateController extends BaseScaffoldCommand protected $signature = 'create:controller {plugin : The name of the plugin. (eg: Winter.Blog)} {controller : The name of the controller to generate. (eg: Posts)} + {--stubs : Create view files for local overwrites.} {--force : Overwrite existing files with generated files.} {--model= : Defines the model name to use. If not provided, the singular name of the controller is used.} - {--sidebar : Create stubs for form-with-sidebar layout} + {--l|layout=standard : Set the formLayout to use (standard, sidebar, fancy)} {--uninspiring : Disable inspirational quotes} '; @@ -41,14 +42,17 @@ class CreateController extends BaseScaffoldCommand */ protected $nameFrom = 'controller'; + /** + * @var bool Allows the process to continue if an existing file is detected + */ + protected bool $throwOverwriteException = false; + /** * @var array A mapping of stub to generated file. */ protected $stubs = [ - 'scaffold/controller/_list_toolbar.stub' => 'controllers/{{lower_name}}/_list_toolbar.php', 'scaffold/controller/config_form.stub' => 'controllers/{{lower_name}}/config_form.yaml', 'scaffold/controller/config_list.stub' => 'controllers/{{lower_name}}/config_list.yaml', - 'scaffold/controller/index.stub' => 'controllers/{{lower_name}}/index.php', 'scaffold/controller/controller.stub' => 'controllers/{{studly_name}}.php', ]; @@ -58,6 +62,7 @@ class CreateController extends BaseScaffoldCommand protected function prepareVars(): array { $vars = parent::prepareVars(); + $layout = $this->option('layout'); /* * Determine the model name to use, * either supplied or singular from the controller name. @@ -67,13 +72,21 @@ protected function prepareVars(): array $model = Str::singular($vars['name']); } $vars['model'] = $model; - $vars['sidebar'] = $this->option('sidebar'); + $vars['sidebar'] = $layout === 'sidebar'; + $vars['fancy'] = $layout === 'fancy'; + $vars['stubs'] = $this->option('stubs'); - $layout = $this->option('sidebar') ? 'sidebar' : 'standard'; + if ($this->option('stubs')) { + $this->stubs['scaffold/controller/index.stub'] = 'controllers/{{lower_name}}/index.php'; + $this->stubs['scaffold/controller/_list_toolbar.stub'] = 'controllers/{{lower_name}}/_list_toolbar.php'; + $this->stubs["scaffold/controller/{$layout}/create.stub"] = 'controllers/{{lower_name}}/create.php'; + $this->stubs["scaffold/controller/{$layout}/update.stub"] = 'controllers/{{lower_name}}/update.php'; + $this->stubs["scaffold/controller/{$layout}/preview.stub"] = 'controllers/{{lower_name}}/preview.php'; - $this->stubs["scaffold/controller/{$layout}/create.stub"] = 'controllers/{{lower_name}}/create.php'; - $this->stubs["scaffold/controller/{$layout}/update.stub"] = 'controllers/{{lower_name}}/update.php'; - $this->stubs["scaffold/controller/{$layout}/preview.stub"] = 'controllers/{{lower_name}}/preview.php'; + if ($layout === 'fancy') { + $this->stubs['scaffold/controller/fancy/_toolbar.stub'] = 'controllers/{{lower_name}}/_toolbar.php'; + } + } return $vars; } diff --git a/modules/backend/console/scaffold/controller/controller.stub b/modules/backend/console/scaffold/controller/controller.stub index 4d1522c387..aacd5dc755 100644 --- a/modules/backend/console/scaffold/controller/controller.stub +++ b/modules/backend/console/scaffold/controller/controller.stub @@ -24,15 +24,31 @@ class {{ studly_name }} extends Controller protected $requiredPermissions = [ '{{ lower_author }}.{{ lower_plugin }}.{{ lower_name }}.manage_all', ]; +{% if sidebar %} - public function __construct() - { - parent::__construct(); + /** + * @var string The form layout to use. One of standard, sidebar, fancy + */ + protected $formLayout = 'sidebar'; +{% if stubs %} - BackendMenu::setContext('{{ plugin_code }}', '{{ lower_plugin }}', '{{ lower_name }}'); - {% if sidebar %} + /** + * @var string Classes to be added to the body element + */ + public $bodyClass = 'compact-container'; +{% endif -%} +{% elseif fancy %} - $this->bodyClass = 'compact-container'; - {% endif -%} - } + /** + * @var string The form layout to use. One of standard, sidebar, fancy + */ + protected $formLayout = 'fancy'; +{% if stubs %} + + /** + * @var string Classes to be added to the body element + */ + public $bodyClass = 'fancy-layout compact-container breadcrumb-flush breadcrumb-fancy'; +{% endif -%} +{% endif -%} } diff --git a/modules/backend/console/scaffold/controller/fancy/_toolbar.stub b/modules/backend/console/scaffold/controller/fancy/_toolbar.stub new file mode 100644 index 0000000000..ffcac9fea0 --- /dev/null +++ b/modules/backend/console/scaffold/controller/fancy/_toolbar.stub @@ -0,0 +1,95 @@ +
+ + + + + + + + + + + + + + + + + + + + + + + url): ?> + + + + + + + + + + + +
diff --git a/modules/backend/console/scaffold/controller/fancy/create.stub b/modules/backend/console/scaffold/controller/fancy/create.stub new file mode 100644 index 0000000000..2358dfc9d0 --- /dev/null +++ b/modules/backend/console/scaffold/controller/fancy/create.stub @@ -0,0 +1,20 @@ + + makeLayoutPartial('breadcrumb') ?> + + +fatalError): ?> +
+ 'layout', + 'data-change-monitor' => 'true', + 'data-window-close-confirm' => 'true', + ]) ?> +
+ formRender() ?> +
+ +
+ +

fatalError) ?>

+

+ diff --git a/modules/backend/console/scaffold/controller/fancy/preview.stub b/modules/backend/console/scaffold/controller/fancy/preview.stub new file mode 100644 index 0000000000..e7f9176c01 --- /dev/null +++ b/modules/backend/console/scaffold/controller/fancy/preview.stub @@ -0,0 +1,14 @@ + + makeLayoutPartial('breadcrumb') ?> + + +fatalError): ?> + 'layout']) ?> +
+ formRenderPreview() ?> +
+ + +

fatalError) ?>

+

+ diff --git a/modules/backend/console/scaffold/controller/fancy/update.stub b/modules/backend/console/scaffold/controller/fancy/update.stub new file mode 100644 index 0000000000..2358dfc9d0 --- /dev/null +++ b/modules/backend/console/scaffold/controller/fancy/update.stub @@ -0,0 +1,20 @@ + + makeLayoutPartial('breadcrumb') ?> + + +fatalError): ?> +
+ 'layout', + 'data-change-monitor' => 'true', + 'data-window-close-confirm' => 'true', + ]) ?> +
+ formRender() ?> +
+ +
+ +

fatalError) ?>

+

+ diff --git a/modules/backend/console/scaffold/controller/sidebar/create.stub b/modules/backend/console/scaffold/controller/sidebar/create.stub index cfce78fa9c..fcdcfafeca 100644 --- a/modules/backend/console/scaffold/controller/sidebar/create.stub +++ b/modules/backend/console/scaffold/controller/sidebar/create.stub @@ -1,45 +1,18 @@ - + makeLayoutPartial('breadcrumb') ?> fatalError): ?> -
-
formRenderOutsideFields() ?> formRenderPrimaryTabs() ?>
-
- - - - or - -
+ formMakePartial('toolbar') ?>
-
@@ -52,7 +25,6 @@ makeLayout('form-with-sidebar') ?> -
diff --git a/modules/backend/console/scaffold/controller/sidebar/preview.stub b/modules/backend/console/scaffold/controller/sidebar/preview.stub index 6014bd4585..952038c6ac 100644 --- a/modules/backend/console/scaffold/controller/sidebar/preview.stub +++ b/modules/backend/console/scaffold/controller/sidebar/preview.stub @@ -1,8 +1,5 @@ - + makeLayoutPartial('breadcrumb') ?> fatalError): ?> diff --git a/modules/backend/console/scaffold/controller/sidebar/update.stub b/modules/backend/console/scaffold/controller/sidebar/update.stub index bd5677411b..5d1ef6f7bd 100644 --- a/modules/backend/console/scaffold/controller/sidebar/update.stub +++ b/modules/backend/console/scaffold/controller/sidebar/update.stub @@ -1,53 +1,17 @@ - + makeLayoutPartial('breadcrumb') ?> fatalError): ?> -
-
formRenderOutsideFields() ?> formRenderPrimaryTabs() ?>
-
-
- - - - - or - -
+ formMakePartial('toolbar') ?>
-
@@ -60,7 +24,6 @@ makeLayout('form-with-sidebar') ?> -
diff --git a/modules/backend/console/scaffold/controller/standard/create.stub b/modules/backend/console/scaffold/controller/standard/create.stub index 8836705591..2a936e607a 100644 --- a/modules/backend/console/scaffold/controller/standard/create.stub +++ b/modules/backend/console/scaffold/controller/standard/create.stub @@ -1,48 +1,18 @@ - + makeLayoutPartial('breadcrumb') ?> fatalError): ?> - 'layout']) ?> -
formRender() ?>
-
- - - - or - -
+ formMakePartial('toolbar') ?>
- - -

fatalError) ?>

- diff --git a/modules/backend/console/scaffold/controller/standard/preview.stub b/modules/backend/console/scaffold/controller/standard/preview.stub index fbd3d7457d..d50dd41212 100644 --- a/modules/backend/console/scaffold/controller/standard/preview.stub +++ b/modules/backend/console/scaffold/controller/standard/preview.stub @@ -1,8 +1,5 @@ - + makeLayoutPartial('breadcrumb') ?> fatalError): ?> diff --git a/modules/backend/console/scaffold/controller/standard/update.stub b/modules/backend/console/scaffold/controller/standard/update.stub index 61e9a0d1c5..b4da197e06 100644 --- a/modules/backend/console/scaffold/controller/standard/update.stub +++ b/modules/backend/console/scaffold/controller/standard/update.stub @@ -1,56 +1,17 @@ - + makeLayoutPartial('breadcrumb') ?> fatalError): ?> - 'layout']) ?> -
formRender() ?>
-
-
- - - - - or - -
+ formMakePartial('toolbar') ?>
- - -

fatalError) ?>

- diff --git a/modules/backend/controllers/UserRoles.php b/modules/backend/controllers/UserRoles.php index 7aa23d0458..765063a067 100644 --- a/modules/backend/controllers/UserRoles.php +++ b/modules/backend/controllers/UserRoles.php @@ -1,9 +1,9 @@ -bindEvent('page.beforeDisplay', function () { if (!$this->user->isSuperUser()) { - return Response::make(View::make('backend::access_denied'), 403); + abort(403); } }); } diff --git a/modules/backend/controllers/Users.php b/modules/backend/controllers/Users.php index 9151933e76..172b13771f 100644 --- a/modules/backend/controllers/Users.php +++ b/modules/backend/controllers/Users.php @@ -39,6 +39,8 @@ class Users extends Controller */ public $bodyClass = 'compact-container'; + public $formLayout = 'sidebar'; + /** * Constructor. */ diff --git a/modules/backend/controllers/usergroups/index.php b/modules/backend/controllers/usergroups/index.php deleted file mode 100644 index ee75b8527c..0000000000 --- a/modules/backend/controllers/usergroups/index.php +++ /dev/null @@ -1,8 +0,0 @@ - - - - -listRender() ?> diff --git a/modules/backend/controllers/userroles/index.php b/modules/backend/controllers/userroles/index.php deleted file mode 100644 index ee75b8527c..0000000000 --- a/modules/backend/controllers/userroles/index.php +++ /dev/null @@ -1,8 +0,0 @@ - - - - -listRender() ?> diff --git a/modules/backend/controllers/users/create.php b/modules/backend/controllers/users/create.php deleted file mode 100644 index 4638a6a2d9..0000000000 --- a/modules/backend/controllers/users/create.php +++ /dev/null @@ -1,66 +0,0 @@ - - - - -fatalError): ?> - - -
- -
- formRenderOutsideFields() ?> - formRenderPrimaryTabs() ?> -
- -
-
- - - - - -
-
- -
- - - -
formRenderSecondaryTabs() ?>
- - - - 'layout stretch']) ?> - makeLayout('form-with-sidebar') ?> - - - - -
- -
-
-

fatalError)) ?>

-

-
- diff --git a/modules/backend/formwidgets/codeeditor/assets/css/codeeditor.css b/modules/backend/formwidgets/codeeditor/assets/css/codeeditor.css index 59cfa51420..8f8aaa18b5 100644 --- a/modules/backend/formwidgets/codeeditor/assets/css/codeeditor.css +++ b/modules/backend/formwidgets/codeeditor/assets/css/codeeditor.css @@ -8,7 +8,7 @@ .field-codeeditor.size-giant{min-height:350px} .field-codeeditor .ace_search{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";font-size:14px;color:#333;z-index:13} .field-codeeditor .ace_search .ace_search_form.ace_nomatch{outline:none !important} -.field-codeeditor .ace_search .ace_search_form.ace_nomatch .ace_search_field{border:.0625rem solid red;-webkit-box-shadow:0 0 .1875rem .125rem red;box-shadow:0 0 .1875rem .125rem red;z-index:1;position:relative} +.field-codeeditor .ace_search .ace_search_form.ace_nomatch .ace_search_field{border:0.0625rem solid red;-webkit-box-shadow:0 0 0.1875rem 0.125rem red;box-shadow:0 0 0.1875rem 0.125rem red;z-index:1;position:relative} .field-codeeditor .editor-code{-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px} .field-codeeditor .editor-toolbar{position:absolute;padding:0 5px;bottom:10px;right:25px;z-index:10;background:rgba(0,0,0,0.8);border-radius:5px} .field-codeeditor .editor-toolbar>ul, diff --git a/modules/backend/formwidgets/fileupload/assets/css/fileupload.css b/modules/backend/formwidgets/fileupload/assets/css/fileupload.css index 32570fc62f..1f1ed08881 100644 --- a/modules/backend/formwidgets/fileupload/assets/css/fileupload.css +++ b/modules/backend/formwidgets/fileupload/assets/css/fileupload.css @@ -1,6 +1,6 @@ .field-fileupload .upload-object{-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;position:relative;outline:none;overflow:hidden;display:inline-block;vertical-align:top} .field-fileupload .upload-object img{width:100%;height:100%} -.field-fileupload .upload-object .icon-container{display:table;opacity:.6} +.field-fileupload .upload-object .icon-container{display:table;opacity:0.6} .field-fileupload .upload-object .icon-container i{color:#95a5a6;display:inline-block} .field-fileupload .upload-object .icon-container div{display:table-cell;text-align:center;vertical-align:middle} .field-fileupload .upload-object .icon-container.image>div.icon-wrapper{display:none} @@ -17,7 +17,7 @@ .field-fileupload .upload-object.is-success .icon-container{opacity:1} .field-fileupload .upload-object.is-success .icon-container:after{opacity:0;-webkit-transition:opacity 0.3s ease;transition:opacity 0.3s ease} .field-fileupload .upload-object.is-error .icon-container:after{content:"";background:none;font-family:"Font Awesome 6 Free";font-weight:900;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-style:normal;font-variant:normal;text-rendering:auto;content:"\f071";-webkit-animation:none;animation:none;font-size:40px;color:#e01346;margin-top:-20px;margin-left:-20px;text-shadow:2px 2px 0 #fff} -.field-fileupload .upload-object.is-loading .icon-container{opacity:.6} +.field-fileupload .upload-object.is-loading .icon-container{opacity:0.6} .field-fileupload .upload-object.is-loading .icon-container:after{opacity:1;-webkit-transition:opacity 0.3s ease;transition:opacity 0.3s ease} .field-fileupload .upload-object.is-success{cursor:pointer} .field-fileupload .upload-object.is-success .progress-bar{opacity:0;-webkit-transition:opacity 0.3s ease;transition:opacity 0.3s ease} @@ -27,7 +27,7 @@ .field-fileupload .upload-object.is-error{cursor:pointer} .field-fileupload .upload-object.is-error .icon-container{opacity:1} .field-fileupload .upload-object.is-error .icon-container>img, -.field-fileupload .upload-object.is-error .icon-container>i{opacity:.5} +.field-fileupload .upload-object.is-error .icon-container>i{opacity:0.5} .field-fileupload .upload-object.is-error .info h4{color:#e01346} .field-fileupload .upload-object.is-error .info h4 a{display:none} .field-fileupload .upload-object.is-error .meta{display:none} @@ -41,12 +41,12 @@ @media (max-width:1024px){.field-fileupload .upload-object.is-success h4 a,.field-fileupload .upload-object.is-success .meta .upload-remove-button,.field-fileupload .upload-object.is-success .meta .drag-handle{display:block !important}} .fileupload-config-form .fileupload-url-button{padding-left:0} .fileupload-config-form .fileupload-url-button>i{color:#666} -.fileupload-config-form .file-upload-modal-image-header{background-color:#FEFEFE;background-image:-webkit-linear-gradient(45deg,#cbcbcb 25%,transparent 25%,transparent 75%,#cbcbcb 75%,#cbcbcb),-webkit-linear-gradient(45deg,#cbcbcb 25%,transparent 25%,transparent 75%,#cbcbcb 75%,#cbcbcb);background-image:-moz-linear-gradient(45deg,#cbcbcb 25%,transparent 25%,transparent 75%,#cbcbcb 75%,#cbcbcb),-moz-linear-gradient(45deg,#cbcbcb 25%,transparent 25%,transparent 75%,#cbcbcb 75%,#cbcbcb);background-image:-o-linear-gradient(45deg,#cbcbcb 25%,transparent 25%,transparent 75%,#cbcbcb 75%,#cbcbcb),-o-linear-gradient(45deg,#cbcbcb 25%,transparent 25%,transparent 75%,#cbcbcb 75%,#cbcbcb);background-image:-ms-linear-gradient(45deg,#cbcbcb 25%,transparent 25%,transparent 75%,#cbcbcb 75%,#cbcbcb),-ms-linear-gradient(45deg,#cbcbcb 25%,transparent 25%,transparent 75%,#cbcbcb 75%,#cbcbcb);background-image:linear-gradient(45deg,#cbcbcb 25%,transparent 25%,transparent 75%,#cbcbcb 75%,#cbcbcb),linear-gradient(45deg,#cbcbcb 25%,transparent 25%,transparent 75%,#cbcbcb 75%,#cbcbcb);-webkit-background-size:20px 20px;-moz-background-size:20px 20px;background-size:20px 20px;background-position:0 0,10px 10px} +.fileupload-config-form .file-upload-modal-image-header{background-color:#FEFEFE;background-image:-webkit-linear-gradient(45deg,#CBCBCB 25%,transparent 25%,transparent 75%,#CBCBCB 75%,#CBCBCB),-webkit-linear-gradient(45deg,#CBCBCB 25%,transparent 25%,transparent 75%,#CBCBCB 75%,#CBCBCB);background-image:-moz-linear-gradient(45deg,#CBCBCB 25%,transparent 25%,transparent 75%,#CBCBCB 75%,#CBCBCB),-moz-linear-gradient(45deg,#CBCBCB 25%,transparent 25%,transparent 75%,#CBCBCB 75%,#CBCBCB);background-image:-o-linear-gradient(45deg,#CBCBCB 25%,transparent 25%,transparent 75%,#CBCBCB 75%,#CBCBCB),-o-linear-gradient(45deg,#CBCBCB 25%,transparent 25%,transparent 75%,#CBCBCB 75%,#CBCBCB);background-image:-ms-linear-gradient(45deg,#CBCBCB 25%,transparent 25%,transparent 75%,#CBCBCB 75%,#CBCBCB),-ms-linear-gradient(45deg,#CBCBCB 25%,transparent 25%,transparent 75%,#CBCBCB 75%,#CBCBCB);background-image:linear-gradient(45deg,#CBCBCB 25%,transparent 25%,transparent 75%,#CBCBCB 75%,#CBCBCB),linear-gradient(45deg,#CBCBCB 25%,transparent 25%,transparent 75%,#CBCBCB 75%,#CBCBCB);-webkit-background-size:20px 20px;-moz-background-size:20px 20px;background-size:20px 20px;background-position:0 0,10px 10px} .fileupload-config-form .file-upload-modal-image-header, .fileupload-config-form .file-upload-modal-image-header img{border-top-right-radius:2px;border-top-left-radius:2px} -.fileupload-config-form .file-upload-modal-image-header .close{position:absolute;top:20px;right:20px;background:#BDC3C7;opacity:.7;height:24px;width:22px;z-index:1} +.fileupload-config-form .file-upload-modal-image-header .close{position:absolute;top:20px;right:20px;background:#BDC3C7;opacity:0.7;height:24px;width:22px;z-index:1} .fileupload-config-form .file-upload-modal-image-header .close:hover, -.fileupload-config-form .file-upload-modal-image-header .close:focus{opacity:.9} +.fileupload-config-form .file-upload-modal-image-header .close:focus{opacity:0.9} .fileupload-config-form .file-upload-modal-image-header + .modal-body{padding-top:20px} .field-fileupload.style-image-multi .upload-button, .field-fileupload.style-image-multi .upload-object{margin:0 10px 10px 0} diff --git a/modules/backend/formwidgets/permissioneditor/assets/css/permissioneditor.css b/modules/backend/formwidgets/permissioneditor/assets/css/permissioneditor.css index 20c2df7e25..65f737bd23 100644 --- a/modules/backend/formwidgets/permissioneditor/assets/css/permissioneditor.css +++ b/modules/backend/formwidgets/permissioneditor/assets/css/permissioneditor.css @@ -2,10 +2,10 @@ .permissioneditor.control-disabled .permissions-overlay{position:absolute;left:0;top:0;width:100%;height:100%;background:rgba(255,255,255,0.01);cursor:not-allowed} .permissioneditor.control-disabled table{opacity:0.5;filter:alpha(opacity=50)} .permissioneditor table{width:100%} -.permissioneditor table th{padding:30px 4px 8px 4px;color:#2a3e51;font-weight:normal;border-bottom:1px solid #dbe1e3} +.permissioneditor table th{padding:30px 4px 8px 4px;color:#2A3E51;font-weight:normal;border-bottom:1px solid #DBE1E3} .permissioneditor table th.tab{font-size:13px} .permissioneditor table th.permission-type{text-transform:uppercase;font-size:11px;text-align:center;cursor:pointer} -.permissioneditor table td{padding:10px 4px;vertical-align:top;border-bottom:1px solid #ecf0f1;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none} +.permissioneditor table td{padding:10px 4px;vertical-align:top;border-bottom:1px solid #ECF0F1;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none} .permissioneditor table td.permission-value{text-align:center} .permissioneditor table td.permission-name{font-size:13px;cursor:pointer;color:#777} .permissioneditor table td p.comment{margin-top:5px;margin-bottom:0} diff --git a/modules/backend/formwidgets/repeater/assets/css/repeater.css b/modules/backend/formwidgets/repeater/assets/css/repeater.css index 5162497b11..abe19da38b 100644 --- a/modules/backend/formwidgets/repeater/assets/css/repeater.css +++ b/modules/backend/formwidgets/repeater/assets/css/repeater.css @@ -2,7 +2,7 @@ .field-repeater .field-repeater-items{counter-reset:repeater-index-counter} .field-repeater ul.field-repeater-items, .field-repeater li.field-repeater-item{padding:0;margin:0;list-style:none} -.field-repeater ul.field-repeater-items>li.dragged{opacity:.7;position:absolute;padding-top:15px;padding-right:15px;z-index:2000;background-color:#f9f9f9;border:1px dashed #dbdee0} +.field-repeater ul.field-repeater-items>li.dragged{opacity:0.7;position:absolute;padding-top:15px;padding-right:15px;z-index:2000;background-color:#f9f9f9;border:1px dashed #dbdee0} .field-repeater ul.field-repeater-items>li.dragged .repeater-item-remove{opacity:0} .field-repeater ul.field-repeater-items>li.dragged .repeater-item-collapsed-title{top:5px} .field-repeater ul.field-repeater-items>li.placeholder{display:block;position:relative;height:25px;margin-bottom:5px} diff --git a/modules/backend/lang/en/lang.php b/modules/backend/lang/en/lang.php index 5c1a96f55b..ee4e5bd019 100644 --- a/modules/backend/lang/en/lang.php +++ b/modules/backend/lang/en/lang.php @@ -252,6 +252,7 @@ 'form' => [ 'create_title' => 'New :name', 'update_title' => 'Edit :name', + 'preview' => 'Preview', 'preview_title' => 'Preview :name', 'create_success' => ':name created', 'update_success' => ':name updated', @@ -264,6 +265,7 @@ 'not_found' => 'Form record with an ID of :id could not be found.', 'action_confirm' => 'Are you sure?', 'create' => 'Create', + 'create_and_new' => 'Create and new', 'create_and_close' => 'Create and close', 'creating' => 'Creating...', 'creating_name' => 'Creating :name...', @@ -358,6 +360,7 @@ ], 'reorder' => [ 'default_title' => 'Reorder records', + 'reorder_title' => 'Reorder :name', 'no_records' => 'There are no records available to sort.', ], 'model' => [ @@ -518,6 +521,8 @@ 'number_all' => 'all numbers', ], 'import_export' => [ + 'export' => 'Export', + 'import' => 'Import', 'upload_csv_file' => '1. Upload a CSV file', 'import_file' => 'Import file', 'row' => 'Row :row', diff --git a/modules/backend/lang/es/lang.php b/modules/backend/lang/es/lang.php index c10026cf7f..9a06c3719a 100644 --- a/modules/backend/lang/es/lang.php +++ b/modules/backend/lang/es/lang.php @@ -195,6 +195,7 @@ 'not_found' => 'El registro del formulario con un ID de :id no se pudo encontrar.', 'action_confirm' => '¿Está usted seguro?', 'create' => 'Crear', + 'create_and_new' => 'Crear y nuevo', 'create_and_close' => 'Crear y cerrar', 'creating' => 'Creando...', 'creating_name' => 'Creando :name...', diff --git a/modules/backend/lang/fr/lang.php b/modules/backend/lang/fr/lang.php index 251d800c18..ef499132bf 100644 --- a/modules/backend/lang/fr/lang.php +++ b/modules/backend/lang/fr/lang.php @@ -263,6 +263,7 @@ 'not_found' => 'Aucun enregistrement de formulaire ne correspond à l\'ID :id.', 'action_confirm' => 'Confirmer l\'action ?', 'create' => 'Créer', + 'create_and_new' => 'Créer et nouveau', 'create_and_close' => 'Créer et fermer', 'creating' => 'Création en cours…', 'creating_name' => 'Création d\'un(e) :name en cours…', diff --git a/modules/backend/lang/nl/lang.php b/modules/backend/lang/nl/lang.php index 425a3f4c10..52495bb734 100644 --- a/modules/backend/lang/nl/lang.php +++ b/modules/backend/lang/nl/lang.php @@ -259,6 +259,7 @@ 'not_found' => 'Het formulier met record ID :id is niet gevonden.', 'action_confirm' => 'Weet je het zeker?', 'create' => 'Maken', + 'create_and_new' => 'Maken en nieuw', 'create_and_close' => 'Maken en sluiten', 'creating' => 'Maken...', 'creating_name' => ':name maken...', diff --git a/modules/backend/lang/pl/lang.php b/modules/backend/lang/pl/lang.php index 1e9a18a5d0..8d47307cd1 100644 --- a/modules/backend/lang/pl/lang.php +++ b/modules/backend/lang/pl/lang.php @@ -253,6 +253,7 @@ 'not_found' => 'Rekord formularza o ID :id nie został znaleziony.', 'action_confirm' => 'Czy jesteś pewny?', 'create' => 'Stwórz', + 'create_and_new' => 'Utwórz i nowe', 'create_and_close' => 'Stwórz i zamknij', 'creating' => 'Tworzenie...', 'creating_name' => 'Tworzenie :name...', diff --git a/modules/backend/lang/ru/lang.php b/modules/backend/lang/ru/lang.php index 828f5e1b52..ec071a9590 100644 --- a/modules/backend/lang/ru/lang.php +++ b/modules/backend/lang/ru/lang.php @@ -264,6 +264,7 @@ 'not_found' => 'Форма записи с идентификатором :ID не найдена.', 'action_confirm' => 'Вы уверены, что хотите сделать это?', 'create' => 'Создать', + 'create_and_new' => 'Создать и новый', 'create_and_close' => 'Создать и закрыть', 'creating' => 'Создание...', 'creating_name' => 'Создание :name...', diff --git a/modules/backend/layouts/_breadcrumb.php b/modules/backend/layouts/_breadcrumb.php new file mode 100644 index 0000000000..cc56ddfda8 --- /dev/null +++ b/modules/backend/layouts/_breadcrumb.php @@ -0,0 +1,22 @@ +sideMenu[$context->sideMenuCode ?? null] ?? null; +$settingsManager = \System\Classes\SettingsManager::instance(); +$settingsContext = $settingsManager->getContext(); +$settingsItem = null; +if ($settingsContext) { + $settingsItem = $settingsManager->findSettingItem($settingsContext->owner, $settingsContext->itemCode); +} +?> + + + diff --git a/modules/backend/widgets/Lists.php b/modules/backend/widgets/Lists.php index a2a3273095..2b3aa59b80 100644 --- a/modules/backend/widgets/Lists.php +++ b/modules/backend/widgets/Lists.php @@ -238,7 +238,7 @@ public function init() } if ($this->customViewPath) { - $this->addViewPath($this->customViewPath); + $this->prependViewPath($this->customViewPath); } $this->validateModel(); diff --git a/modules/backend/widgets/mediamanager/assets/css/mediamanager.css b/modules/backend/widgets/mediamanager/assets/css/mediamanager.css index c3287a1afa..9d943e4beb 100644 --- a/modules/backend/widgets/mediamanager/assets/css/mediamanager.css +++ b/modules/backend/widgets/mediamanager/assets/css/mediamanager.css @@ -61,7 +61,7 @@ div[data-control="media-manager"] .media-list.list li .icon-container{border-rig div[data-control="media-manager"] .media-list.list li .icon-container img{max-height:75px} div[data-control="media-manager"] .media-list.list li .icon-container i{font-size:35px} div[data-control="media-manager"] .media-list.list li .icon-container svg{max-height:44px} -div[data-control="media-manager"] .media-list.list li .icon-container.image{border-right:1px solid #ecf0f1!important} +div[data-control="media-manager"] .media-list.list li .icon-container.image{border-right:1px solid #ecf0f1 !important} div[data-control="media-manager"] .media-list.list li .icon-container p.thumbnail-error-message{display:none} div[data-control="media-manager"] .media-list.list .icon-wrapper{width:75px} div[data-control="media-manager"] .media-list.list li .info{margin-left:90px} @@ -129,12 +129,12 @@ div[data-control="media-manager"] .upload-progress h5{margin:0 0 10px 0;font-siz div[data-control="media-manager"] .upload-progress h5 span{display:inline-block;margin-left:10px;color:#95a5a6;font-size:15px} div[data-control="media-manager"] .upload-progress .progress-controls{padding-right:30px;position:relative} div[data-control="media-manager"] .upload-progress .progress-controls .controls{position:absolute;right:0;bottom:0} -div[data-control="media-manager"] .upload-progress .progress-controls .controls a{display:block;position:relative;top:7px;right:3px;color:#95a5a6;font-size:16px;cursor:pointer !important} +div[data-control="media-manager"] .upload-progress .progress-controls .controls a{display:block;position:relative;top:7px;right:3px;color:#95a5a6;font-size:16px;cursor:pointer!important} div[data-control="media-manager"] .upload-progress .progress-controls .controls a:hover{text-decoration:none;color:#2da7c7} div[data-control="media-manager"] .dz-preview{display:none} div[data-control="media-manager"] button[data-command="toggle-sidebar"].sidebar-hidden{-webkit-transform:rotate(180deg) translate(0,0);-ms-transform:rotate(180deg) translate(0,0);transform:rotate(180deg) translate(0,0)} [data-control="media-manager-crop-tool"] .image_area{position:absolute;width:100%;height:100%;overflow:auto} -[data-control="media-manager-crop-tool"] .image_area .jcrop-holder{background-color:transparent !important} +[data-control="media-manager-crop-tool"] .image_area .jcrop-holder{background-color:transparent!important} [data-control="media-manager-crop-tool"] img{cursor:crosshair;display:block} [data-control="media-manager-crop-tool"].has-rulers .ruler-container .layout-relative{overflow:hidden} [data-control="media-manager-crop-tool"].has-rulers .ruler-container.horizontal .layout-cell{height:20px} @@ -165,5 +165,5 @@ body:not(.no-select) div[data-control="media-manager"] .media-list.list li:hover body:not(.no-select) div[data-control="media-manager"] .media-list li:hover h4 a{display:block} @media (max-width:1280px){div[data-control="media-manager"] .media-list.list li{width:230px}} @media (max-width:1024px){div[data-control="media-manager"] .media-list.list li{display:block;width:auto}} -@media (max-width:768px){div[data-control="media-manager"] [data-control="preview-sidebar"],div[data-control="media-manager"] [data-command="toggle-sidebar"]{display:none !important}div[data-control="media-manager"] .media-list.list{padding:0}div[data-control="media-manager"] .media-list.list li{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;margin:0;border-right:none;border-left:none;border-bottom:none}} -@media (max-width:480px){div[data-control="media-manager"] [data-control="left-sidebar"]{display:none !important}} \ No newline at end of file +@media (max-width:768px){div[data-control="media-manager"] [data-control="preview-sidebar"],div[data-control="media-manager"] [data-command="toggle-sidebar"]{display:none!important}div[data-control="media-manager"] .media-list.list{padding:0}div[data-control="media-manager"] .media-list.list li{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;margin:0;border-right:none;border-left:none;border-bottom:none}} +@media (max-width:480px){div[data-control="media-manager"] [data-control="left-sidebar"]{display:none!important}} \ No newline at end of file diff --git a/modules/backend/widgets/table/assets/css/table.css b/modules/backend/widgets/table/assets/css/table.css index c652196c6e..bca48e7238 100644 --- a/modules/backend/widgets/table/assets/css/table.css +++ b/modules/backend/widgets/table/assets/css/table.css @@ -51,7 +51,7 @@ .control-table .pagination ul li a{display:inline-block;text-decoration:none;color:#95a5a6;padding:4px 6px;background:#ecf0f1;-webkit-border-radius:2px;-moz-border-radius:2px;border-radius:2px;outline:none;line-height:100%} .control-table .pagination ul li a:focus-visible{outline:auto} .control-table .pagination ul li.active a{background:#6cc551;color:#fff} -@media only screen and (-moz-min-device-pixel-ratio:1.5),only screen and (-o-min-device-pixel-ratio:3/2),only screen and (-webkit-min-device-pixel-ratio:1.5),only screen and (min-devicepixel-ratio:1.5),only screen and (min-resolution:1.5dppx){.control-table .toolbar a:before{background-position:0 -9px;background-size:16px auto}.control-table .toolbar a.add-table-row-above:before{background-position:0 -39px}.control-table .toolbar a.delete-table-row:before{background-position:0 -66px}}.control-table td[data-column-type=string] input[type=text], +@media only screen and (-moz-min-device-pixel-ratio:1.5),only screen and (-o-min-device-pixel-ratio:1.5),only screen and (-webkit-min-device-pixel-ratio:1.5),only screen and (min-devicepixel-ratio:1.5),only screen and (min-resolution:1.5dppx){.control-table .toolbar a:before{background-position:0 -9px;background-size:16px auto}.control-table .toolbar a.add-table-row-above:before{background-position:0 -39px}.control-table .toolbar a.delete-table-row:before{background-position:0 -66px}}.control-table td[data-column-type=string] input[type=text], .control-table td[data-column-type=autocomplete] input[type=text]{width:100%;height:100%;display:block;outline:none;border:none;padding:6px 10px 7px} html.chrome .control-table td[data-column-type=string] input[type=text], html.chrome .control-table td[data-column-type=autocomplete] input[type=text]{padding:6px 10px 7px!important} diff --git a/modules/cms/ServiceProvider.php b/modules/cms/ServiceProvider.php index f114cb9238..6f3a03aeea 100644 --- a/modules/cms/ServiceProvider.php +++ b/modules/cms/ServiceProvider.php @@ -94,6 +94,10 @@ protected function registerConsole() protected function registerErrorHandler() { $this->app->error(function (HttpExceptionInterface $exception, $code, $fromConsole) { + if ($this->app->runningInBackend() && BackendAuth::check()) { + return; + } + $theme = Theme::getActiveTheme(); $controller = new CmsController($theme); if ($code === 404) { diff --git a/modules/cms/assets/css/winter.components.css b/modules/cms/assets/css/winter.components.css index 620ab4904d..22163f82c7 100644 --- a/modules/cms/assets/css/winter.components.css +++ b/modules/cms/assets/css/winter.components.css @@ -6,7 +6,7 @@ div.control-componentlist div.components div.layout-cell{font-size:11px;cursor:p div.control-componentlist div.components div.layout-cell:hover{background:#6cc551} .draggable-component-item>div, .component-list .components div.layout-cell>div, -div.control-componentlist div.components div.layout-cell>div{white-space:normal;color:#475354;position:relative;border-right:1px solid #ecf0f1} +div.control-componentlist div.components div.layout-cell>div{white-space:normal;color:#475354;position:relative;border-right:1px solid #ECF0F1} .draggable-component-item>div:before, .component-list .components div.layout-cell>div:before, div.control-componentlist div.components div.layout-cell>div:before{position:absolute;font-size:16px;left:15px;top:7px;opacity:0.7;filter:alpha(opacity=70)} @@ -73,7 +73,7 @@ div.control-componentlist div.components div.layout-cell.adding>div{-webkit-tran .draggable-component-item{opacity:0.6;filter:alpha(opacity=60)} .draggable-component-item span.alias{display:none} .draggable-component-item a.remove{display:none} -.component-list .components div.layout div.layout-row div.layout-cell{border-top:1px solid #ecf0f1} +.component-list .components div.layout div.layout-row div.layout-cell{border-top:1px solid #ECF0F1} .component-list .components div.layout div.layout-row div.layout-cell span.alias{display:none} .component-list .components div.layout div.layout-row div.layout-cell a.remove{display:none} .component-list .components div.layout div.layout-row div.layout-cell:last-child>div{border-right:none} diff --git a/modules/cms/assets/css/winter.theme-selector.css b/modules/cms/assets/css/winter.theme-selector.css index 6ee752e38c..6f139595d4 100644 --- a/modules/cms/assets/css/winter.theme-selector.css +++ b/modules/cms/assets/css/winter.theme-selector.css @@ -30,4 +30,4 @@ .theme-selector-layout .find-more-themes{background:#ecf0f1;color:#2b3e50;text-decoration:none;display:block;padding:20px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px} .theme-selector-layout .create-new-theme:hover, .theme-selector-layout .find-more-themes:hover{background:#2da7c7;color:white} -@media (max-width:768px){.theme-selector-layout .layout-cell,.theme-selector-layout .layout-row{display:block !important;width:auto !important;height:auto !important}.theme-selector-layout .theme-thumbnail img{width:100%}.theme-selector-layout .layout-row.links .theme-thumbnail{background:transparent;padding:0}} \ No newline at end of file +@media (max-width:768px){.theme-selector-layout .layout-cell,.theme-selector-layout .layout-row{display:block!important;width:auto!important;height:auto!important}.theme-selector-layout .theme-thumbnail img{width:100%}.theme-selector-layout .layout-row.links .theme-thumbnail{background:transparent;padding:0}} \ No newline at end of file diff --git a/modules/cms/widgets/assetlist/assets/css/assetlist.css b/modules/cms/widgets/assetlist/assets/css/assetlist.css index 3985272d9a..f9123bedd3 100644 --- a/modules/cms/widgets/assetlist/assets/css/assetlist.css +++ b/modules/cms/widgets/assetlist/assets/css/assetlist.css @@ -44,16 +44,16 @@ .control-assetlist ul li.active a.link:after{position:absolute;height:100%;width:4px;left:0;top:0;background:#2da7c7;display:block;content:' '} .control-assetlist ul li div.controls{position:absolute;right:45px;top:10px} .control-assetlist ul li div.controls .dropdown{width:14px;height:21px} -.control-assetlist ul li div.controls .dropdown.open a.control{display:block !important} +.control-assetlist ul li div.controls .dropdown.open a.control{display:block!important} .control-assetlist ul li div.controls .dropdown.open a.control:before{visibility:visible;display:block} .control-assetlist ul li div.controls a.control{color:#405261;font-size:14px;visibility:hidden;overflow:hidden;width:14px;height:21px;display:none;text-decoration:none;cursor:pointer;opacity:0.5;filter:alpha(opacity=50)} .control-assetlist ul li div.controls a.control:before{visibility:visible;display:block;margin-right:0} .control-assetlist ul li div.controls a.control:hover{opacity:1;filter:alpha(opacity=100)} .control-assetlist ul li:hover{background:#ddd} .control-assetlist ul li:hover div.controls, -.control-assetlist ul li:hover a.control{display:block !important} +.control-assetlist ul li:hover a.control{display:block!important} .control-assetlist ul li:hover div.controls>a.control, -.control-assetlist ul li:hover a.control>a.control{display:block !important} +.control-assetlist ul li:hover a.control>a.control{display:block!important} .control-assetlist ul li .checkbox{position:absolute;top:-5px;right:-5px} .control-assetlist ul li .checkbox label{margin-right:0} .control-assetlist ul li .checkbox label:before{border-color:#ccc} diff --git a/modules/system/console/BaseScaffoldCommand.php b/modules/system/console/BaseScaffoldCommand.php index 5f8187d6a8..514862039e 100644 --- a/modules/system/console/BaseScaffoldCommand.php +++ b/modules/system/console/BaseScaffoldCommand.php @@ -89,18 +89,19 @@ public function makeStubs(): void . DIRECTORY_SEPARATOR . 'lang.php' ); + if (!file_exists($langFilePath)) { $this->makeDirectory($langFilePath); - $comment = 'File generated: ' . str_replace(base_path(), '', $langFilePath); + $comment = 'File generated: ' . str_replace(base_path(), '', $langFilePath); } else { - $comment = 'File updated: ' . str_replace(base_path(), '', $langFilePath); + $comment = 'File updated: ' . str_replace(base_path(), '', $langFilePath); } // Store the localization messages to the determined file path ArrayFile::open($langFilePath)->set($langKeys)->write(); // Inform the user - $this->comment($comment); + $this->output->writeLn($comment); } /** diff --git a/modules/system/controllers/maillayouts/create.php b/modules/system/controllers/maillayouts/create.php deleted file mode 100644 index fcde00a9d3..0000000000 --- a/modules/system/controllers/maillayouts/create.php +++ /dev/null @@ -1,50 +0,0 @@ - -
    -
  • -
  • pageTitle)) ?>
  • -
- - -fatalError): ?> - - 'layout']) ?> - -
- formRender() ?> -
- -
-
- - - - - -
-
- - - - - -

fatalError)) ?>

-

- - diff --git a/modules/system/controllers/mailpartials/create.php b/modules/system/controllers/mailpartials/create.php deleted file mode 100644 index 78942e0c18..0000000000 --- a/modules/system/controllers/mailpartials/create.php +++ /dev/null @@ -1,50 +0,0 @@ - -
    -
  • -
  • pageTitle)) ?>
  • -
- - -fatalError): ?> - - 'layout']) ?> - -
- formRender() ?> -
- -
-
- - - - - -
-
- - - - - -

fatalError)) ?>

-

- - diff --git a/modules/system/controllers/mailtemplates/create.php b/modules/system/controllers/mailtemplates/create.php deleted file mode 100644 index 19995235af..0000000000 --- a/modules/system/controllers/mailtemplates/create.php +++ /dev/null @@ -1,50 +0,0 @@ - -
    -
  • -
  • pageTitle)) ?>
  • -
- - -fatalError): ?> - - 'layout']) ?> - -
- formRender() ?> -
- -
-
- - - - - -
-
- - - - - -

fatalError)) ?>

-

- - diff --git a/modules/system/tests/traits/ViewMakerTest.php b/modules/system/tests/traits/ViewMakerTest.php index 3dab780e76..ca32d757df 100644 --- a/modules/system/tests/traits/ViewMakerTest.php +++ b/modules/system/tests/traits/ViewMakerTest.php @@ -47,9 +47,9 @@ public function testViewPaths() $this->normalizePath($path) ); - // Test addViewPath() & getViewPaths() + // Test prependViewPath() & getViewPaths() $overridePath = "~/{$this->relativePath}override"; - $this->stub->addViewPath($overridePath); + $this->stub->prependViewPath($overridePath); $this->assertEquals( [ $this->normalizePath($overridePath), diff --git a/modules/system/traits/ViewMaker.php b/modules/system/traits/ViewMaker.php index 8407e4e033..627e780dd9 100644 --- a/modules/system/traits/ViewMaker.php +++ b/modules/system/traits/ViewMaker.php @@ -43,8 +43,11 @@ trait ViewMaker /** * Prepends a path on the available view path locations. + * + * @param array|string $path + * @return void */ - public function addViewPath(string|array $path): void + public function prependViewPath(array|string $path): void { $this->viewPath = (array) $this->viewPath; @@ -55,6 +58,33 @@ public function addViewPath(string|array $path): void } } + /** + * Append a path on the available view path locations. + * + * @param array|string $path + * @return void + */ + public function appendViewPath(array|string $path): void + { + $this->viewPath = (array) $this->viewPath; + + if (is_array($path)) { + $this->viewPath = array_merge($this->viewPath, $path); + } else { + $this->viewPath[] = $path; + } + } + + /** + * Prepends a path on the available view path locations. + * + * @deprecated Use prependViewPath() + */ + public function addViewPath(string|array $path): void + { + $this->prependViewPath($path); + } + /** * Returns the active view path locations. */