From 9cedf253b9c8df7d08c271dec8d5d17777c0c7e1 Mon Sep 17 00:00:00 2001 From: Vincent Vanwaelscappel Date: Tue, 1 Nov 2022 19:06:38 +0100 Subject: [PATCH] . --- app/Field/Collection.php | 21 ++++++ app/Field/CollectionList.php | 32 +++++---- app/Field/Mode.php | 4 +- app/Http/Controllers/FrontController.php | 18 ++--- app/Models/Collection.php | 24 +++++++ app/Models/Song.php | 70 ++++++++++++++----- app/Models/User.php | 46 +++++++++++- resources/css/app.sass | 3 + resources/js/bootstrap.js | 2 + resources/js/mmenu.js | 20 +++--- resources/js/modernizr.js | 3 + resources/views/menu.blade.php | 2 +- .../base/inc/sidebar_content.blade.php | 18 ++--- 13 files changed, 201 insertions(+), 62 deletions(-) create mode 100644 app/Field/Collection.php create mode 100644 resources/js/modernizr.js diff --git a/app/Field/Collection.php b/app/Field/Collection.php new file mode 100644 index 0000000..63d1129 --- /dev/null +++ b/app/Field/Collection.php @@ -0,0 +1,21 @@ +where('created_ok', '1')->get() as $item) { + $___options[$item->id] = $item->name; + } + } + return self::$___options; + } +} diff --git a/app/Field/CollectionList.php b/app/Field/CollectionList.php index 38fdc6b..68312fc 100644 --- a/app/Field/CollectionList.php +++ b/app/Field/CollectionList.php @@ -7,24 +7,28 @@ use Cubist\Backpack\Magic\Fields\SelectFromArrayMultiple; class CollectionList extends SelectFromArrayMultiple { + protected static $___options = null; + public function getOptions() { - $res = []; - $lists = \App\Models\CollectionList::where('created_ok', '1')->get(); - foreach (Collection::where('created_ok', '1')->get() as $item) { - $thisLists = []; - foreach ($lists as $list) { - if ($list->collection == $item->id) { - $thisLists[$item->id . '_' . $list->id] = $item->name . ' - ' . $list->name; + if (null === self::$___options) { + self::$___options = []; + $lists = \App\Models\CollectionList::where('created_ok', '1')->get(); + foreach (Collection::where('created_ok', '1')->get() as $item) { + $thisLists = []; + foreach ($lists as $list) { + if ($list->collection == $item->id) { + $thisLists[$item->id . '_' . $list->id] = $item->name . ' - ' . $list->name; + } + } + self::$___options[$item->id] = $item->name; + if (count($thisLists)) { + self::$___options[$item->id] .= ' - ' . __('Liste principale'); + self::$___options = array_merge(self::$___options, $thisLists); } - } - $res[$item->id] = $item->name; - if (count($thisLists)) { - $res[$item->id] .= ' - ' . __('Liste principale'); - $res = array_merge($res, $thisLists); - } + } } - return $res; + return self::$___options; } } diff --git a/app/Field/Mode.php b/app/Field/Mode.php index 4ef5994..ca59fde 100644 --- a/app/Field/Mode.php +++ b/app/Field/Mode.php @@ -6,10 +6,10 @@ use Cubist\Backpack\Magic\Fields\SelectFromArray; class Mode extends SelectFromArray { - protected $_allowNull=false; + protected $_allowNull = false; public function getOptions() { - return ['' => 'Major', 'm' => 'minor']; + return ['' => 'M', 'm' => 'm']; } } diff --git a/app/Http/Controllers/FrontController.php b/app/Http/Controllers/FrontController.php index b815951..f8bb936 100644 --- a/app/Http/Controllers/FrontController.php +++ b/app/Http/Controllers/FrontController.php @@ -14,19 +14,19 @@ class FrontController extends Controller { public static function defaultCollection() { - return redirect('/' . Collection::find(1)->slug); + return redirect('/' . Collection::withoutGlobalScope('ownerclause')->find(1)->slug); } public function collection($name) { - $collection = Collection::where('slug', $name)->first(); + $collection = Collection::withoutGlobalScope('ownerclause')->where('slug', $name)->first(); if (null === $collection) { return self::defaultCollection(); } if ($p = $this->checkPassword($collection)) { return $p; } - $lists = CollectionList::where('collection', $collection->id)->get(); + $lists = CollectionList::withoutGlobalScope('ownerclause')->where('collection', $collection->id)->get(); $songs = $this->_getSongsOfCollection($collection->id, $lists); return view('collection', ['menu' => true, 'songs' => $songs, 'collection' => $collection, 'collection_songs' => $songs, 'collection_lists' => $lists]); @@ -54,19 +54,19 @@ class FrontController extends Controller public function song($collection, $song) { /** @var Collection $collection */ - $collection = Collection::where('slug', $collection)->first(); + $collection = Collection::withoutGlobalScope('ownerclause')->where('slug', $collection)->first(); if (null === $collection) { abort(404); } /** @var Song $song */ - $song = Song::where('slug', $song)->first(); + $song = Song::withoutGlobalScope('ownerclause')->where('slug', $song)->first(); if (null === $song) { abort(404); } if ($p = $this->checkPassword($collection)) { return $p; } - $lists = CollectionList::where('collection', $collection->id)->get(); + $lists = CollectionList::withoutGlobalScope('ownerclause')->where('collection', $collection->id)->get(); $partition=false; $lyrics_html=''; @@ -105,7 +105,7 @@ class FrontController extends Controller protected function _getSongsOfCollection($id, $lists) { /** @var Song $q */ - $q = Song::whereRaw('json_contains(collections, \'["' . $id . '"]\')'); + $q = Song::withoutGlobalScope('ownerclause')->whereRaw('json_contains(collections, \'["' . $id . '"]\')'); foreach ($lists as $list) { $q->orWhereRaw('json_contains(collections, \'["' . $id . '_' . $list->id . '"]\')'); } @@ -115,7 +115,7 @@ class FrontController extends Controller public function manifest($collection) { - $collection = Collection::where('slug', $collection)->first(); + $collection = Collection::withoutGlobalScope('ownerclause')->where('slug', $collection)->first(); if (null === $collection) { abort(404); } @@ -149,7 +149,7 @@ class FrontController extends Controller public function downloadAssets($songId) { /** @var Song $song */ - $song = Song::find($songId); + $song = Song::withoutGlobalScope('ownerclause')->find($songId); $fields = ['partition', 'lyrics_doc']; $files = []; $tmp = Files::tempnam() . '.zip'; diff --git a/app/Models/Collection.php b/app/Models/Collection.php index 7af371a..a552b87 100644 --- a/app/Models/Collection.php +++ b/app/Models/Collection.php @@ -6,10 +6,13 @@ use Cubist\Backpack\Http\Controllers\CubistPWAController; use Cubist\Backpack\Magic\Fields\Checkbox; use Cubist\Backpack\Magic\Fields\Color; use Cubist\Backpack\Magic\Fields\Images; +use Cubist\Backpack\Magic\Fields\SelectFromModel; use Cubist\Backpack\Magic\Fields\Slug; use Cubist\Backpack\Magic\Fields\Table; use Cubist\Backpack\Magic\Fields\Text; use Cubist\Backpack\Magic\Models\CubistMagicAbstractModel; +use Illuminate\Database\Eloquent\Builder; +use Illuminate\Support\Facades\Auth; use Spatie\MediaLibrary\MediaCollections\Models\Media; class Collection extends CubistMagicAbstractModel @@ -19,11 +22,32 @@ class Collection extends CubistMagicAbstractModel 'singular' => 'collection', 'plural' => 'collections']; + public static function addOwnerClause(Builder $builder) + { + if (backpack_user() === null || Auth::guest()) { + return; + } + if (Auth::user()->hasPermissionTo('song:admin')) { + return; + } + + //$builder->whereIn('id', Auth::user()->getOwnedCollections()); + +// $cols=backpack_user()->collections; +// if(!$cols){ + +// $cols=[]; +// } +// $builder->whereIn('id', $cols); + + + } public function setfields() { parent::setFields(); $this->addField('name', 'Text', 'Name', ['column' => true]); + $this->addField('owners', SelectFromModel::class, 'Éditeurs', ['optionsmodel' => User::class, 'allows_multiple' => true]); $this->addField('shortname', 'Text', 'Short name', ['column' => true]); $this->addField('slug', Slug::class, 'Slug', ['column' => true]); $this->addField('icon', Images::class, 'Icône'); diff --git a/app/Models/Song.php b/app/Models/Song.php index 3f72445..850cf5f 100644 --- a/app/Models/Song.php +++ b/app/Models/Song.php @@ -12,9 +12,10 @@ use App\SubForm\SongPortion; use Cubist\Backpack\Magic\Fields\BunchOfFieldsMultiple; use Cubist\Backpack\Magic\Fields\Checkbox; use Cubist\Backpack\Magic\Fields\Files; -use Cubist\Backpack\Magic\Fields\SelectFromArray; -use Cubist\Backpack\Magic\Fields\SelectFromModel; use Cubist\Backpack\Magic\Models\CubistMagicAbstractModel; +use Cubist\Util\Str; +use Illuminate\Database\Eloquent\Builder; +use Illuminate\Support\Facades\Auth; class Song extends CubistMagicAbstractModel { @@ -22,6 +23,8 @@ class Song extends CubistMagicAbstractModel protected $_operations = [ImportOperation::class]; protected $table = 'songs'; + protected static $_permissionBase = 'song'; + protected static $_ownerAttribute = 'owner'; protected $_options = ['name' => 'song', 'singular' => 'song', @@ -30,30 +33,65 @@ class Song extends CubistMagicAbstractModel protected $_enableBulk = false; protected $_enableClone = false; + public static function addOwnerClause(Builder $builder) + { + $user = backpack_user(); + if (null === $user) { + return; + } + if ($user->hasPermissionTo('song:admin')) { + return; + } + $builder->where('owner', $user->id); + $lists = $user->getOwnedLists(); + foreach ($lists as $list) { + $builder->orWhere('collections', 'like', '%"' . $list . '"%'); + } + } + public function setFields() { parent::setFields(); - $this->addField('slug', 'Slug', 'Slug', ['column' => true]); - $this->addField('title', 'Text', 'Song title', ['column' => true]); - $this->addField('artist', 'Text', 'Artist', ['column' => true]); - $this->addField('key', Tone::class, 'Key', ['column' => true]); - $this->addField('mode', Mode::class, 'Mode', ['column' => true]); - $this->addField('chorale', Checkbox::class, 'Chorale', ['default' => false, 'database_default' => false]); + // $this->addField('slug', 'Slug', 'Slug', ['column' => true]); + $this->addField('title', 'Text', __('Titre de la chanson'), ['column' => true]); + $this->addField('artist', 'Text', __('Artiste'), ['column' => true]); + $this->addField([ + 'name' => 'owner', + 'label' => __('Ajouté par'), + 'type' => \Cubist\Backpack\Magic\Fields\User::class, + 'column' => true, + 'can' => 'song:admin', + 'column_attribute' => 'companyWithNameOnTwoLines', + 'column_escape' => false, + 'attribute' => 'companyWithName', + 'default' => Auth::id(), + 'non_default_tracking' => false, + ]); + $this->addField('key', Tone::class, __('Key'), ['column' => true]); + $this->addField('mode', Mode::class, __('Mode'), ['column' => true]); + $this->addField('chorale', Checkbox::class, __('Chorale'), ['default' => false, 'database_default' => false]); $this->addField('collections', \App\Field\CollectionList::class, 'Collections'); - $this->addField('tempo', Tempo::class, 'Suggested tempo', ['column' => true, 'default' => 80]); - $this->addField('partition', Files::class, 'Partition', ['acceptedFiles' => 'application/pdf', 'when' => ['chorale' => 1]]); - $this->addField('lyrics_doc', Files::class, 'Paroles', ['acceptedFiles' => 'application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document,text/plain,text/html', 'when' => ['chorale' => 1]]); - $this->addField('audio', BunchOfFieldsMultiple::class, 'Audio tracks', ['bunch' => AudioTrack::class, 'new_label' => 'New audio track']); - $this->addField('lyrics', BunchOfFieldsMultiple::class, 'Song Parts', ['bunch' => SongPortion::class, 'new_label' => 'New song part', 'when' => ['chorale' => 0]]); -// $this->addField('youtube', URL::class, 'Youtube link'); -// $this->addField('spotify', URL::class, 'Spotify link'); -// $this->addField('credits', 'Textarea', 'Credits'); + $this->addField('tempo', Tempo::class, __('Suggested tempo'), ['column' => true, 'default' => 80]); + $this->addField('partition', Files::class, __('Partition'), ['acceptedFiles' => 'application/pdf', 'when' => ['chorale' => 1]]); + $this->addField('lyrics_doc', Files::class, __('Paroles'), ['acceptedFiles' => 'application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document,text/plain,text/html', 'when' => ['chorale' => 1]]); + $this->addField('audio', BunchOfFieldsMultiple::class, __('Audio tracks'), ['bunch' => AudioTrack::class, 'new_label' => 'New audio track']); + $this->addField('lyrics', BunchOfFieldsMultiple::class, __('Song Parts'), ['bunch' => SongPortion::class, 'new_label' => 'New song part', 'when' => ['chorale' => 0]]); + $this->addField('credits', 'Textarea', __('Credits')); + } + + public function preSave() + { + parent::preSave(); + if (!$this->slug) { + $this->slug = Str::slug($this->id . '-' . $this->title); + } } public function postSave() { DownloadAudioTracks::dispatch(); + parent::postSave(); } diff --git a/app/Models/User.php b/app/Models/User.php index 83ee9bf..50901a3 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -3,11 +3,14 @@ namespace App\Models; use Cubist\Backpack\Magic\Models\CubistMagicAuthenticatable; +use Illuminate\Support\Facades\Cache; class User extends CubistMagicAuthenticatable { protected $table = 'users'; + protected $_ownedCollections = null; + protected $_ownedLists = null; protected $_options = ['name' => 'users', 'singular' => 'utilisateur', @@ -17,7 +20,46 @@ class User extends CubistMagicAuthenticatable { parent::setFields(); - $this->addField('name', 'Text', 'Name'); - $this->addField('collections', \App\Field\CollectionList::class, 'Collections'); + $this->addField('name', 'Text', 'Name', ['column' => true]); + } + + public function getOwnedCollections() + { + if (null === $this->_ownedCollections) { + $user = $this; + $this->_ownedCollections = Cache::remember('ownedCollections_' . $this->id, 120, function () use ($user) { + $res = []; + $collections = Collection::withoutGlobalScope('ownerclause')->get(); + foreach ($collections as $collection) { + if (null !== $collection->owners && in_array($user->id, $collection->owners)) { + $res[] = $collection->id; + } + } + return $res; + }); + } + return $this->_ownedCollections; + } + + public function getOwnedLists() + { + if (null === $this->_ownedLists) { + $user = $this; + $this->_ownedLists = Cache::remember('ownedLists_' . $this->id, 120, function () use ($user) { + $res = []; + $lists = CollectionList::withoutGlobalScope('ownerclause')->get(); + $collections = $user->getOwnedCollections(); + foreach ($collections as $collection) { + $res[] = $collection; + foreach ($lists as $list) { + if ($list->collection == $collection) { + $res[] = $collection . '_' . $list->id; + } + } + } + return $res; + }); + } + return $this->_ownedLists; } } diff --git a/resources/css/app.sass b/resources/css/app.sass index fd3f8bc..54a9a9d 100644 --- a/resources/css/app.sass +++ b/resources/css/app.sass @@ -44,6 +44,9 @@ $slab: 'Roboto Slab', sans-serif +.phpdebugbar + display: none + a:focus, button:focus, input:focus, diff --git a/resources/js/bootstrap.js b/resources/js/bootstrap.js index 22b5c05..9e8deb2 100644 --- a/resources/js/bootstrap.js +++ b/resources/js/bootstrap.js @@ -1,5 +1,7 @@ window._ = require('lodash'); +require('./modernizr'); + /** * We'll load the axios HTTP library which allows us to easily issue requests * to our Laravel back-end. This library automatically handles sending the diff --git a/resources/js/mmenu.js b/resources/js/mmenu.js index 0a03266..2b34144 100644 --- a/resources/js/mmenu.js +++ b/resources/js/mmenu.js @@ -18,15 +18,17 @@ document.addEventListener("DOMContentLoaded", () => { }); - var mc = new Hammer(document.getElementsByTagName('main').item(0), {touchAction: "auto"}) - - mc.on('swiperight', function (e) { - if (e.distance > 100 && e.overallVelocityX > 0.4) { - drawer.open(); - return false; - } - return true; - }); + if (Modernizr.touchevents) { + var mc = new Hammer(document.getElementsByTagName('main').item(0), {touchAction: "auto"}) + + mc.on('swiperight', function (e) { + if (e.distance > 100 && e.overallVelocityX > 0.4) { + drawer.open(); + return false; + } + return true; + }); + } } $('body').addClass('init'); diff --git a/resources/js/modernizr.js b/resources/js/modernizr.js new file mode 100644 index 0000000..79f2663 --- /dev/null +++ b/resources/js/modernizr.js @@ -0,0 +1,3 @@ +/*! modernizr 3.6.0 (Custom Build) | MIT * + * https://modernizr.com/download/?-touchevents-addtest-atrule-domprefixes-hasevent-mq-prefixed-prefixedcss-prefixedcssvalue-prefixes-printshiv-setclasses-testallprops-testprop-teststyles !*/ +!function(e,t,n){function r(e,t){return typeof e===t}function o(){var e,t,n,o,i,a,s;for(var u in E)if(E.hasOwnProperty(u)){if(e=[],t=E[u],t.name&&(e.push(t.name.toLowerCase()),t.options&&t.options.aliases&&t.options.aliases.length))for(n=0;nc;c++)if(m=e[c],h=L.style[m],d(m,"-")&&(m=u(m)),L.style[m]!==n){if(i||r(o,"undefined"))return a(),"pfx"==t?m:!0;try{L.style[m]=o}catch(y){}if(L.style[m]!=h)return a(),"pfx"==t?m:!0}return a(),!1}function y(e,t,n,o,i){var a=e.charAt(0).toUpperCase()+e.slice(1),s=(e+" "+z.join(a+" ")+a).split(" ");return r(t,"string")||r(t,"undefined")?g(s,t,o,i):(s=(e+" "+N.join(a+" ")+a).split(" "),m(s,t,n))}function S(e,t,r){return y(e,n,n,t,r)}var C=[],E=[],b={_version:"3.6.0",_config:{classPrefix:"",enableClasses:!0,enableJSClass:!0,usePrefixes:!0},_q:[],on:function(e,t){var n=this;setTimeout(function(){t(n[e])},0)},addTest:function(e,t,n){E.push({name:e,fn:t,options:n})},addAsyncTest:function(e){E.push({name:null,fn:e})}},Modernizr=function(){};Modernizr.prototype=b,Modernizr=new Modernizr;var _=b._config.usePrefixes?" -webkit- -moz- -o- -ms- ".split(" "):["",""];b._prefixes=_;var x=t.documentElement,w="svg"===x.nodeName.toLowerCase();w||!function(e,t){function n(e,t){var n=e.createElement("p"),r=e.getElementsByTagName("head")[0]||e.documentElement;return n.innerHTML="x",r.insertBefore(n.lastChild,r.firstChild)}function r(){var e=x.elements;return"string"==typeof e?e.split(" "):e}function o(e,t){var n=x.elements;"string"!=typeof n&&(n=n.join(" ")),"string"!=typeof e&&(e=e.join(" ")),x.elements=n+" "+e,l(t)}function i(e){var t=_[e[E]];return t||(t={},b++,e[E]=b,_[b]=t),t}function a(e,n,r){if(n||(n=t),v)return n.createElement(e);r||(r=i(n));var o;return o=r.cache[e]?r.cache[e].cloneNode():C.test(e)?(r.cache[e]=r.createElem(e)).cloneNode():r.createElem(e),!o.canHaveChildren||S.test(e)||o.tagUrn?o:r.frag.appendChild(o)}function s(e,n){if(e||(e=t),v)return e.createDocumentFragment();n=n||i(e);for(var o=n.frag.cloneNode(),a=0,s=r(),u=s.length;u>a;a++)o.createElement(s[a]);return o}function u(e,t){t.cache||(t.cache={},t.createElem=e.createElement,t.createFrag=e.createDocumentFragment,t.frag=t.createFrag()),e.createElement=function(n){return x.shivMethods?a(n,e,t):t.createElem(n)},e.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+r().join().replace(/[\w\-:]+/g,function(e){return t.createElem(e),t.frag.createElement(e),'c("'+e+'")'})+");return n}")(x,t.frag)}function l(e){e||(e=t);var r=i(e);return!x.shivCSS||h||r.hasCSS||(r.hasCSS=!!n(e,"article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}")),v||u(e,r),e}function f(e){for(var t,n=e.getElementsByTagName("*"),o=n.length,i=RegExp("^(?:"+r().join("|")+")$","i"),a=[];o--;)t=n[o],i.test(t.nodeName)&&a.push(t.applyElement(c(t)));return a}function c(e){for(var t,n=e.attributes,r=n.length,o=e.ownerDocument.createElement(T+":"+e.nodeName);r--;)t=n[r],t.specified&&o.setAttribute(t.nodeName,t.nodeValue);return o.style.cssText=e.style.cssText,o}function d(e){for(var t,n=e.split("{"),o=n.length,i=RegExp("(^|[\\s,>+~])("+r().join("|")+")(?=[[\\s,>+~#.:]|$)","gi"),a="$1"+T+"\\:$2";o--;)t=n[o]=n[o].split("}"),t[t.length-1]=t[t.length-1].replace(i,a),n[o]=t.join("}");return n.join("{")}function p(e){for(var t=e.length;t--;)e[t].removeNode()}function m(e){function t(){clearTimeout(a._removeSheetTimer),r&&r.removeNode(!0),r=null}var r,o,a=i(e),s=e.namespaces,u=e.parentWindow;return!N||e.printShived?e:("undefined"==typeof s[T]&&s.add(T),u.attachEvent("onbeforeprint",function(){t();for(var i,a,s,u=e.styleSheets,l=[],c=u.length,p=Array(c);c--;)p[c]=u[c];for(;s=p.pop();)if(!s.disabled&&w.test(s.media)){try{i=s.imports,a=i.length}catch(m){a=0}for(c=0;a>c;c++)p.push(i[c]);try{l.push(s.cssText)}catch(m){}}l=d(l.reverse().join("")),o=f(e),r=n(e,l)}),u.attachEvent("onafterprint",function(){p(o),clearTimeout(a._removeSheetTimer),a._removeSheetTimer=setTimeout(t,500)}),e.printShived=!0,e)}var h,v,g="3.7.3",y=e.html5||{},S=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,C=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,E="_html5shiv",b=0,_={};!function(){try{var e=t.createElement("a");e.innerHTML="",h="hidden"in e,v=1==e.childNodes.length||function(){t.createElement("a");var e=t.createDocumentFragment();return"undefined"==typeof e.cloneNode||"undefined"==typeof e.createDocumentFragment||"undefined"==typeof e.createElement}()}catch(n){h=!0,v=!0}}();var x={elements:y.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video",version:g,shivCSS:y.shivCSS!==!1,supportsUnknownElements:v,shivMethods:y.shivMethods!==!1,type:"default",shivDocument:l,createElement:a,createDocumentFragment:s,addElements:o};e.html5=x,l(t);var w=/^$|\b(?:all|print)\b/,T="html5shiv",N=!v&&function(){var n=t.documentElement;return!("undefined"==typeof t.namespaces||"undefined"==typeof t.parentWindow||"undefined"==typeof n.applyElement||"undefined"==typeof n.removeNode||"undefined"==typeof e.attachEvent)}();x.type+=" print",x.shivPrint=m,m(t),"object"==typeof module&&module.exports&&(module.exports=x)}("undefined"!=typeof e?e:this,t);var T="Moz O ms Webkit",N=b._config.usePrefixes?T.toLowerCase().split(" "):[];b._domPrefixes=N;var j;!function(){var e={}.hasOwnProperty;j=r(e,"undefined")||r(e.call,"undefined")?function(e,t){return t in e&&r(e.constructor.prototype[t],"undefined")}:function(t,n){return e.call(t,n)}}(),b._l={},b.on=function(e,t){this._l[e]||(this._l[e]=[]),this._l[e].push(t),Modernizr.hasOwnProperty(e)&&setTimeout(function(){Modernizr._trigger(e,Modernizr[e])},0)},b._trigger=function(e,t){if(this._l[e]){var n=this._l[e];setTimeout(function(){var e,r;for(e=0;ea;a++){var s=_[a],u=s.toUpperCase()+"_"+r;if(u in i)return"@-"+s.toLowerCase()+"-"+t}return!1};b.atRule=P;var k=function(){function e(e,t){var o;return e?(t&&"string"!=typeof t||(t=s(t||"div")),e="on"+e,o=e in t,!o&&r&&(t.setAttribute||(t=s("div")),t.setAttribute(e,""),o="function"==typeof t[e],t[e]!==n&&(t[e]=n),t.removeAttribute(e)),o):!1}var r=!("onblur"in t.documentElement);return e}();b.hasEvent=k;var A=function(e,t){var n=!1,r=s("div"),o=r.style;if(e in o){var i=N.length;for(o[e]=t,n=o[e];i--&&!n;)o[e]="-"+N[i]+"-"+t,n=o[e]}return""===n&&(n=!1),n};b.prefixedCSSValue=A;var F=function(){var t=e.matchMedia||e.msMatchMedia;return t?function(e){var n=t(e);return n&&n.matches||!1}:function(t){var n=!1;return c("@media "+t+" { #modernizr { position: absolute; } }",function(t){n="absolute"==(e.getComputedStyle?e.getComputedStyle(t,null):t.currentStyle).position}),n}}();b.mq=F;var M=b.testStyles=c;Modernizr.addTest("touchevents",function(){var n;if("ontouchstart"in e||e.DocumentTouch&&t instanceof DocumentTouch)n=!0;else{var r=["@media (",_.join("touch-enabled),("),"heartz",")","{#modernizr{top:9px;position:absolute}}"].join("");M(r,function(e){n=9===e.offsetTop})}return n});var D={elem:s("modernizr")};Modernizr._q.push(function(){delete D.elem});var L={style:D.elem.style};Modernizr._q.unshift(function(){delete L.style});b.testProp=function(e,t,r){return g([e],n,t,r)};b.testAllProps=y;var $=b.prefixed=function(e,t,n){return 0===e.indexOf("@")?P(e):(-1!=e.indexOf("-")&&(e=u(e)),t?y(e,t,n):y(e,"pfx"))};b.prefixedCSS=function(e){var t=$(e);return t&&l(t)};b.testAllProps=S,o(),i(C),delete b.addTest,delete b.addAsyncTest;for(var q=0;q🔒 {{__('Edit this song')}} @else -
  • 🔒 {{__('Edit this collection')}}
  • +
  • 🔒 {{__('Edit songs')}}
  • @endif diff --git a/resources/views/vendor/backpack/base/inc/sidebar_content.blade.php b/resources/views/vendor/backpack/base/inc/sidebar_content.blade.php index b33533a..b92f581 100644 --- a/resources/views/vendor/backpack/base/inc/sidebar_content.blade.php +++ b/resources/views/vendor/backpack/base/inc/sidebar_content.blade.php @@ -6,16 +6,16 @@ class='nav-icon la la-music'>Songbook @@ -25,12 +25,12 @@