--- /dev/null
+<?php
+
+namespace App\Field;
+
+use Cubist\Backpack\Magic\Fields\SelectFromArrayMultiple;
+
+class Collection extends SelectFromArrayMultiple
+{
+ protected static $___options = null;
+
+ public function getOptions()
+ {
+ if (null === self::$___options) {
+ $___options = [];
+ foreach (\App\Models\Collection::withoutGlobalScope('owner')->where('created_ok', '1')->get() as $item) {
+ $___options[$item->id] = $item->name;
+ }
+ }
+ return self::$___options;
+ }
+}
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;
}
}
class Mode extends SelectFromArray
{
- protected $_allowNull=false;
+ protected $_allowNull = false;
public function getOptions()
{
- return ['' => 'Major', 'm' => 'minor'];
+ return ['' => 'M', 'm' => 'm'];
}
}
{
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]);
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='';
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 . '"]\')');
}
public function manifest($collection)
{
- $collection = Collection::where('slug', $collection)->first();
+ $collection = Collection::withoutGlobalScope('ownerclause')->where('slug', $collection)->first();
if (null === $collection) {
abort(404);
}
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';
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
'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');
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
{
protected $_operations = [ImportOperation::class];
protected $table = 'songs';
+ protected static $_permissionBase = 'song';
+ protected static $_ownerAttribute = 'owner';
protected $_options = ['name' => 'song',
'singular' => 'song',
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();
}
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',
{
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;
}
}
$slab: 'Roboto Slab', sans-serif
+.phpdebugbar
+ display: none
+
a:focus,
button:focus,
input:focus,
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
});
- 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');
--- /dev/null
+/*! 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;n<t.options.aliases.length;n++)e.push(t.options.aliases[n].toLowerCase());for(o=r(t.fn,"function")?t.fn():t.fn,i=0;i<e.length;i++)a=e[i],s=a.split("."),1===s.length?Modernizr[s[0]]=o:(!Modernizr[s[0]]||Modernizr[s[0]]instanceof Boolean||(Modernizr[s[0]]=new Boolean(Modernizr[s[0]])),Modernizr[s[0]][s[1]]=o),C.push((o?"":"no-")+s.join("-"))}}function i(e){var t=x.className,n=Modernizr._config.classPrefix||"";if(w&&(t=t.baseVal),Modernizr._config.enableJSClass){var r=new RegExp("(^|\\s)"+n+"no-js(\\s|$)");t=t.replace(r,"$1"+n+"js$2")}Modernizr._config.enableClasses&&(t+=" "+n+e.join(" "+n),w?x.className.baseVal=t:x.className=t)}function a(e,t){if("object"==typeof e)for(var n in e)j(e,n)&&a(n,e[n]);else{e=e.toLowerCase();var r=e.split("."),o=Modernizr[r[0]];if(2==r.length&&(o=o[r[1]]),"undefined"!=typeof o)return Modernizr;t="function"==typeof t?t():t,1==r.length?Modernizr[r[0]]=t:(!Modernizr[r[0]]||Modernizr[r[0]]instanceof Boolean||(Modernizr[r[0]]=new Boolean(Modernizr[r[0]])),Modernizr[r[0]][r[1]]=t),i([(t&&0!=t?"":"no-")+r.join("-")]),Modernizr._trigger(e,t)}return Modernizr}function s(){return"function"!=typeof t.createElement?t.createElement(arguments[0]):w?t.createElementNS.call(t,"http://www.w3.org/2000/svg",arguments[0]):t.createElement.apply(t,arguments)}function u(e){return e.replace(/([a-z])-([a-z])/g,function(e,t,n){return t+n.toUpperCase()}).replace(/^-/,"")}function l(e){return e.replace(/([A-Z])/g,function(e,t){return"-"+t.toLowerCase()}).replace(/^ms-/,"-ms-")}function f(){var e=t.body;return e||(e=s(w?"svg":"body"),e.fake=!0),e}function c(e,n,r,o){var i,a,u,l,c="modernizr",d=s("div"),p=f();if(parseInt(r,10))for(;r--;)u=s("div"),u.id=o?o[r]:c+(r+1),d.appendChild(u);return i=s("style"),i.type="text/css",i.id="s"+c,(p.fake?p:d).appendChild(i),p.appendChild(d),i.styleSheet?i.styleSheet.cssText=e:i.appendChild(t.createTextNode(e)),d.id=c,p.fake&&(p.style.background="",p.style.overflow="hidden",l=x.style.overflow,x.style.overflow="hidden",x.appendChild(p)),a=n(d,e),p.fake?(p.parentNode.removeChild(p),x.style.overflow=l,x.offsetHeight):d.parentNode.removeChild(d),!!a}function d(e,t){return!!~(""+e).indexOf(t)}function p(e,t){return function(){return e.apply(t,arguments)}}function m(e,t,n){var o;for(var i in e)if(e[i]in t)return n===!1?e[i]:(o=t[e[i]],r(o,"function")?p(o,n||t):o);return!1}function h(t,n,r){var o;if("getComputedStyle"in e){o=getComputedStyle.call(e,t,n);var i=e.console;if(null!==o)r&&(o=o.getPropertyValue(r));else if(i){var a=i.error?"error":"log";i[a].call(i,"getComputedStyle returning null, its possible modernizr test results are inaccurate")}}else o=!n&&t.currentStyle&&t.currentStyle[r];return o}function v(t,r){var o=t.length;if("CSS"in e&&"supports"in e.CSS){for(;o--;)if(e.CSS.supports(l(t[o]),r))return!0;return!1}if("CSSSupportsRule"in e){for(var i=[];o--;)i.push("("+l(t[o])+":"+r+")");return i=i.join(" or "),c("@supports ("+i+") { #modernizr { position: absolute; } }",function(e){return"absolute"==h(e,null,"position")})}return n}function g(e,t,o,i){function a(){f&&(delete L.style,delete L.modElem)}if(i=r(i,"undefined")?!1:i,!r(o,"undefined")){var l=v(e,o);if(!r(l,"undefined"))return l}for(var f,c,p,m,h,g=["modernizr","tspan","samp"];!L.style&&g.length;)f=!0,L.modElem=s(g.shift()),L.style=L.modElem.style;for(p=e.length,c=0;p>c;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<style>"+t+"</style>",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="<xyz></xyz>",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;e<n.length;e++)(r=n[e])(t)},0),delete this._l[e]}},Modernizr._q.push(function(){b.addTest=a});var z=b._config.usePrefixes?T.split(" "):[];b._cssomPrefixes=z;var P=function(t){var r,o=_.length,i=e.CSSRule;if("undefined"==typeof i)return n;if(!t)return!1;if(t=t.replace(/^@/,""),r=t.replace(/-/g,"_").toUpperCase()+"_RULE",r in i)return"@"+t;for(var a=0;o>a;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<Modernizr._q.length;q++)Modernizr._q[q]();e.Modernizr=Modernizr}(window,document);
@if(isset($song))
<li><a href="/admin/song/{{$song->id}}/edit">🔒 {{__('Edit this song')}}</a></li>
@else
- <li><a href="/admin/collection/{{$collection->id}}/edit">🔒 {{__('Edit this collection')}}</a></li>
+ <li><a href="/admin/song">🔒 {{__('Edit songs')}}</a></li>
@endif
</ul>
</nav>
class='nav-icon la la-music'></i>Songbook</a>
<ul class='nav-dropdown-items'>
<li class='nav-item'><a class='nav-link' href='{{ backpack_url('song') }}'><i
- class='nav-icon la la-music'></i><span>Songs</span></a></li>
+ class='nav-icon la la-music'></i><span>{{__('Songs')}}</span></a></li>
@can('maintenance')
<li class='nav-item'><a class='nav-link' href='{{ backpack_url('instrument') }}'><i
- class='nav-icon la la-music'></i><span>Instruments</span></a></li>
+ class='nav-icon la la-music'></i><span>{{__('Instruments')}}</span></a></li>
<li class='nav-item'><a class='nav-link' href='{{ backpack_url('chord') }}'><i
- class='nav-icon la la-music'></i><span>Chords</span></a></li>
+ class='nav-icon la la-music'></i><span>{{__('Chords')}}</span></a></li>
<li class='nav-item'><a class='nav-link' href='{{ backpack_url('collection') }}'><i
- class='nav-icon la la-music'></i><span>Collections</span></a></li>
+ class='nav-icon la la-music'></i><span>{{__('Collections')}}</span></a></li>
<li class='nav-item'><a class='nav-link' href='{{ backpack_url('collection_list') }}'><i
- class='nav-icon la la-music'></i><span>Listes</span></a></li>
+ class='nav-icon la la-music'></i><span>{{__('Lists')}}</span></a></li>
@endcan
</ul>
</li>
<li class='nav-item nav-dropdown'><a class='nav-link nav-dropdown-toggle' href='#'><i
class='nav-icon la la-group'></i>Authentication</a>
<ul class='nav-dropdown-items'>
- <li class='nav-item'><a class='nav-link' href='{{ backpack_url('user') }}'><i
- class='nav-icon la la-user'></i><span>Users</span></a></li>
+ <li class='nav-item'><a class='nav-link' href='{{ backpack_url('users') }}'><i
+ class='nav-icon la la-user'></i><span>{{__('Users')}}</span></a></li>
<li class='nav-item'><a class='nav-link' href='{{ backpack_url('role') }}'><i
- class='nav-icon la la-group'></i> <span>Roles</span></a></li>
+ class='nav-icon la la-group'></i> <span>{{__('Roles')}}</span></a></li>
<li class='nav-item'><a class='nav-link' href='{{ backpack_url('permission') }}'><i
- class='nav-icon la la-key'></i><span>Permissions</span></a></li>
+ class='nav-icon la la-key'></i><span>{{__('Permissions')}}</span></a></li>
</ul>
</li>
<li class='nav-item nav-dropdown'><a class='nav-link nav-dropdown-toggle' href='#'><i