mirror of
https://github.com/Poniverse/Pony.fm.git
synced 2025-01-31 03:16:42 +01:00
Things
This commit is contained in:
parent
a80de5ea8f
commit
d349fa1e6e
23 changed files with 274 additions and 88 deletions
|
@ -51,6 +51,7 @@
|
||||||
|
|
||||||
public function getIndex() {
|
public function getIndex() {
|
||||||
$page = 1;
|
$page = 1;
|
||||||
|
$perPage = 60;
|
||||||
|
|
||||||
if (Input::has('page'))
|
if (Input::has('page'))
|
||||||
$page = Input::get('page');
|
$page = Input::get('page');
|
||||||
|
@ -63,7 +64,7 @@
|
||||||
$this->applyFilters($query);
|
$this->applyFilters($query);
|
||||||
|
|
||||||
$totalCount = $query->count();
|
$totalCount = $query->count();
|
||||||
$query->take(30)->skip(30 * ($page - 1));
|
$query->take($perPage)->skip(30 * ($page - 1));
|
||||||
|
|
||||||
$tracks = [];
|
$tracks = [];
|
||||||
$ids = [];
|
$ids = [];
|
||||||
|
@ -73,7 +74,7 @@
|
||||||
$ids[] = $track->id;
|
$ids[] = $track->id;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Response::json(["tracks" => $tracks, "current_page" => $page, "total_pages" => ceil($totalCount / 30)], 200);
|
return Response::json(["tracks" => $tracks, "current_page" => $page, "total_pages" => ceil($totalCount / $perPage)], 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getOwned() {
|
public function getOwned() {
|
||||||
|
|
|
@ -47,6 +47,7 @@
|
||||||
new FileAsset('scripts/base/jquery-ui.js'),
|
new FileAsset('scripts/base/jquery-ui.js'),
|
||||||
new FileAsset('scripts/base/jquery.cookie.js'),
|
new FileAsset('scripts/base/jquery.cookie.js'),
|
||||||
new FileAsset('scripts/base/jquery.colorbox.js'),
|
new FileAsset('scripts/base/jquery.colorbox.js'),
|
||||||
|
new FileAsset('scripts/base/jquery.viewport.js'),
|
||||||
new FileAsset('scripts/base/underscore.js'),
|
new FileAsset('scripts/base/underscore.js'),
|
||||||
new FileAsset('scripts/base/moment.js'),
|
new FileAsset('scripts/base/moment.js'),
|
||||||
new FileAsset('scripts/base/soundmanager2-nodebug.js'),
|
new FileAsset('scripts/base/soundmanager2-nodebug.js'),
|
||||||
|
|
|
@ -11,16 +11,16 @@
|
||||||
<div class="site-body">
|
<div class="site-body">
|
||||||
<ul class="sidebar" ng-controller="sidebar">
|
<ul class="sidebar" ng-controller="sidebar">
|
||||||
@if (Auth::check())
|
@if (Auth::check())
|
||||||
<li ng-class="{selected: $state.includes('home')}"><a href="/">Dashboard <i class="icon-home"></i></a></li>
|
<li ng-class="{selected: stateIncludes('home')}"><a href="/">Dashboard <i class="icon-home"></i></a></li>
|
||||||
@else
|
@else
|
||||||
<li ng-class="{selected: $state.includes('home')}"><a href="/">Home <i class="icon-home"></i></a></li>
|
<li ng-class="{selected: stateIncludes('home')}"><a href="/">Home <i class="icon-home"></i></a></li>
|
||||||
@endif
|
@endif
|
||||||
<li ng-class="{selected: $state.includes('content')}">
|
<li ng-class="{selected: stateIncludes('content')}">
|
||||||
<a href="/tracks">Discover <i class="icon-music"></i></a>
|
<a href="/tracks">Discover <i class="icon-music"></i></a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
@if (Auth::check())
|
@if (Auth::check())
|
||||||
<li ng-class="{selected: $state.includes('account-content') || isActive('/account')}"><a href="/account/tracks">Account <i class="icon-user"></i></a></li>
|
<li ng-class="{selected: stateIncludes('account-content') || isActive('/account')}"><a href="/account/tracks">Account <i class="icon-user"></i></a></li>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
<li ng-class="{selected: isActive('/about')}"><a href="/about">Meta <i class="icon-info"></i></a></li>
|
<li ng-class="{selected: isActive('/about')}"><a href="/about">Meta <i class="icon-info"></i></a></li>
|
||||||
|
|
|
@ -5,6 +5,7 @@ angular.module('ponyfm').controller "application", [
|
||||||
$scope.$state = $state
|
$scope.$state = $state
|
||||||
$scope.$stateParams = $stateParams
|
$scope.$stateParams = $stateParams
|
||||||
$loadingElement = null
|
$loadingElement = null
|
||||||
|
loadingStateName = null
|
||||||
|
|
||||||
$rootScope.safeApply = (fn) ->
|
$rootScope.safeApply = (fn) ->
|
||||||
phase = $rootScope.$$phase
|
phase = $rootScope.$$phase
|
||||||
|
@ -25,8 +26,20 @@ angular.module('ponyfm').controller "application", [
|
||||||
$loadingElement.removeClass 'loading'
|
$loadingElement.removeClass 'loading'
|
||||||
$loadingElement = null
|
$loadingElement = null
|
||||||
|
|
||||||
|
$scope.stateIncludes = (state) ->
|
||||||
|
if $loadingElement
|
||||||
|
newParts = state.split '.'
|
||||||
|
oldParts = loadingStateName.split '.'
|
||||||
|
for i in [0..newParts.length]
|
||||||
|
continue if !newParts[i]
|
||||||
|
return false if newParts[i] != oldParts[i]
|
||||||
|
|
||||||
|
return true
|
||||||
|
else
|
||||||
|
$state.includes(state)
|
||||||
|
|
||||||
statesPreloaded = {}
|
statesPreloaded = {}
|
||||||
$scope.$on '$stateChangeStart', (e, newState, newParams, oldState) ->
|
$scope.$on '$stateChangeStart', (e, newState, newParams, oldState, oldParams) ->
|
||||||
return if !oldState || !newState.controller
|
return if !oldState || !newState.controller
|
||||||
|
|
||||||
preloader = window.pfm.preloaders[newState.controller]
|
preloader = window.pfm.preloaders[newState.controller]
|
||||||
|
@ -37,6 +50,7 @@ angular.module('ponyfm').controller "application", [
|
||||||
return
|
return
|
||||||
|
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
|
loadingStateName = newState.name
|
||||||
|
|
||||||
selector = ''
|
selector = ''
|
||||||
newParts = newState.name.split '.'
|
newParts = newState.name.split '.'
|
||||||
|
|
|
@ -9,7 +9,6 @@ angular.module('ponyfm').controller "track", [
|
||||||
($scope, tracks, $state, playlists, auth, favourites, $dialog) ->
|
($scope, tracks, $state, playlists, auth, favourites, $dialog) ->
|
||||||
tracks.fetch($state.params.id).done (trackResponse) ->
|
tracks.fetch($state.params.id).done (trackResponse) ->
|
||||||
$scope.track = trackResponse.track
|
$scope.track = trackResponse.track
|
||||||
$scope.trackArray = [$scope.track]
|
|
||||||
|
|
||||||
$scope.playlists = []
|
$scope.playlists = []
|
||||||
|
|
||||||
|
|
|
@ -2,10 +2,8 @@ window.pfm.preloaders['tracks-list'] = [
|
||||||
'tracks', '$state'
|
'tracks', '$state'
|
||||||
(tracks, $state) ->
|
(tracks, $state) ->
|
||||||
tracks.loadFilters().then(->
|
tracks.loadFilters().then(->
|
||||||
if !tracks.mainQuery.hasLoadedFilters
|
tracks.mainQuery.fromFilterString($state.params.filter)
|
||||||
tracks.mainQuery.fromFilterString($state.params.filter)
|
tracks.mainQuery.setPage $state.params.page || 1
|
||||||
if $state.params.page
|
|
||||||
tracks.mainQuery.setPage $state.params.page
|
|
||||||
|
|
||||||
tracks.mainQuery.fetch()
|
tracks.mainQuery.fetch()
|
||||||
)
|
)
|
||||||
|
|
|
@ -23,6 +23,10 @@ angular.module('ponyfm').controller "tracks", [
|
||||||
$scope.query.setListFilter filter, id
|
$scope.query.setListFilter filter, id
|
||||||
$state.transitionTo 'content.tracks.list', {filter: $scope.query.toFilterString()}
|
$state.transitionTo 'content.tracks.list', {filter: $scope.query.toFilterString()}
|
||||||
|
|
||||||
|
$scope.clearFilter = (filter) ->
|
||||||
|
$scope.query.clearFilter filter
|
||||||
|
$state.transitionTo 'content.tracks.list', {filter: $scope.query.toFilterString()}
|
||||||
|
|
||||||
tracks.mainQuery.listen (searchResults) ->
|
tracks.mainQuery.listen (searchResults) ->
|
||||||
$scope.tracks = searchResults.tracks
|
$scope.tracks = searchResults.tracks
|
||||||
$scope.currentPage = parseInt(searchResults.current_page)
|
$scope.currentPage = parseInt(searchResults.current_page)
|
||||||
|
|
|
@ -4,6 +4,7 @@ angular.module('ponyfm').directive 'pfmPlayer', () ->
|
||||||
restrict: 'E'
|
restrict: 'E'
|
||||||
templateUrl: '/templates/directives/player.html'
|
templateUrl: '/templates/directives/player.html'
|
||||||
scope: {}
|
scope: {}
|
||||||
|
replace: true
|
||||||
|
|
||||||
compile: (element) ->
|
compile: (element) ->
|
||||||
$element = element
|
$element = element
|
||||||
|
|
28
public/scripts/app/directives/scroll-recorder.coffee
Normal file
28
public/scripts/app/directives/scroll-recorder.coffee
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
angular.module('ponyfm').directive 'pfmScrollRecorder', () ->
|
||||||
|
(scope, element, attrs) ->
|
||||||
|
timeout = null
|
||||||
|
onScroll = null
|
||||||
|
lastInView = null
|
||||||
|
|
||||||
|
element.scroll (e) ->
|
||||||
|
(window.clearTimeout timeout) if timeout
|
||||||
|
timeout = window.setTimeout (-> onScroll e), 500
|
||||||
|
|
||||||
|
onScroll = (e) -> scope.safeApply ->
|
||||||
|
items = element.find 'li:not(.empty)'
|
||||||
|
itemHeight = (items.eq 0).height()
|
||||||
|
itemsArray = items.get()
|
||||||
|
|
||||||
|
elementViewTop = element.offset().top
|
||||||
|
elementViewBottom = elementViewTop + element.height()
|
||||||
|
|
||||||
|
for i in [itemsArray.length - 1..0]
|
||||||
|
listItem = $ itemsArray[i]
|
||||||
|
|
||||||
|
listItemTop = listItem.offset().top + itemHeight
|
||||||
|
isInView = listItemTop > elementViewTop && listItemTop < elementViewBottom
|
||||||
|
if isInView
|
||||||
|
lastInView = listItem
|
||||||
|
break
|
||||||
|
|
||||||
|
scope.$emit 'element-in-view', angular.element(lastInView).scope()
|
13
public/scripts/app/directives/track-player.coffee
Normal file
13
public/scripts/app/directives/track-player.coffee
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
angular.module('ponyfm').directive 'pfmTrackPlayer', () ->
|
||||||
|
restrict: 'E'
|
||||||
|
templateUrl: '/templates/directives/track-player.html'
|
||||||
|
scope:
|
||||||
|
track: '=track',
|
||||||
|
class: '@class'
|
||||||
|
|
||||||
|
controller: [
|
||||||
|
'$scope', 'player'
|
||||||
|
($scope, player) ->
|
||||||
|
$scope.play = () ->
|
||||||
|
player.playTracks [$scope.track], 0
|
||||||
|
]
|
|
@ -12,7 +12,9 @@ angular.module('ponyfm').factory('tracks', [
|
||||||
constructor: (@availableFilters) ->
|
constructor: (@availableFilters) ->
|
||||||
@filters = {}
|
@filters = {}
|
||||||
@hasLoadedFilters = false
|
@hasLoadedFilters = false
|
||||||
|
@resetFilters()
|
||||||
|
|
||||||
|
resetFilters: ->
|
||||||
_.each @availableFilters, (filter, name) =>
|
_.each @availableFilters, (filter, name) =>
|
||||||
if filter.type == 'single'
|
if filter.type == 'single'
|
||||||
@filters[name] = _.find filter.values, (f) -> f.isDefault
|
@filters[name] = _.find filter.values, (f) -> f.isDefault
|
||||||
|
@ -38,6 +40,19 @@ angular.module('ponyfm').factory('tracks', [
|
||||||
filter.selectedObject[id] = filterToAdd
|
filter.selectedObject[id] = filterToAdd
|
||||||
filter.title = filterToAdd.title
|
filter.title = filterToAdd.title
|
||||||
|
|
||||||
|
clearFilter: (type) ->
|
||||||
|
@cachedDef = null
|
||||||
|
@page = 1
|
||||||
|
filter = @availableFilters[type]
|
||||||
|
|
||||||
|
if filter.type == 'single'
|
||||||
|
@filters[type] = _.find filter.values, (f) -> f.isDefault
|
||||||
|
else
|
||||||
|
currentFilter = @filters[type]
|
||||||
|
currentFilter.selectedArray = []
|
||||||
|
currentFilter.selectedObject = {}
|
||||||
|
currentFilter.title = 'Any'
|
||||||
|
|
||||||
toggleListFilter: (type, id) ->
|
toggleListFilter: (type, id) ->
|
||||||
@cachedDef = null
|
@cachedDef = null
|
||||||
@page = 1
|
@page = 1
|
||||||
|
@ -82,8 +97,10 @@ angular.module('ponyfm').factory('tracks', [
|
||||||
|
|
||||||
fromFilterString: (str) ->
|
fromFilterString: (str) ->
|
||||||
@hasLoadedFilters = true
|
@hasLoadedFilters = true
|
||||||
return if !str
|
@cachedDef = null
|
||||||
filters = str.split '!'
|
@resetFilters()
|
||||||
|
|
||||||
|
filters = (str || "").split '!'
|
||||||
for filter in filters
|
for filter in filters
|
||||||
parts = filter.split '-'
|
parts = filter.split '-'
|
||||||
name = parts[0]
|
name = parts[0]
|
||||||
|
@ -91,7 +108,8 @@ angular.module('ponyfm').factory('tracks', [
|
||||||
|
|
||||||
if @availableFilters[name].type == 'single'
|
if @availableFilters[name].type == 'single'
|
||||||
filterToSet = _.find @availableFilters[name].values, (f) -> f.query == parts[1]
|
filterToSet = _.find @availableFilters[name].values, (f) -> f.query == parts[1]
|
||||||
filterToSet = _.find @availableFilters[name].values, (f) -> f.isDefault if filterToSet == null
|
filterToSet = (_.find @availableFilters[name].values, (f) -> f.isDefault) if filterToSet == null
|
||||||
|
@setFilter name, filterToSet
|
||||||
else
|
else
|
||||||
@toggleListFilter name, id for id in _.rest parts, 1
|
@toggleListFilter name, id for id in _.rest parts, 1
|
||||||
|
|
||||||
|
@ -116,6 +134,7 @@ angular.module('ponyfm').factory('tracks', [
|
||||||
for listener in @listeners
|
for listener in @listeners
|
||||||
listener tracks
|
listener tracks
|
||||||
|
|
||||||
|
|
||||||
trackDef.resolve tracks
|
trackDef.resolve tracks
|
||||||
|
|
||||||
trackDef.promise()
|
trackDef.promise()
|
||||||
|
@ -150,7 +169,7 @@ angular.module('ponyfm').factory('tracks', [
|
||||||
type: 'single'
|
type: 'single'
|
||||||
values: [
|
values: [
|
||||||
{title: 'Newest to Oldest', query: '', isDefault: true, filter: 'order=created_at,desc'},
|
{title: 'Newest to Oldest', query: '', isDefault: true, filter: 'order=created_at,desc'},
|
||||||
{title: 'Oldest to Newest', query: 'created_at,asc', isDefault: true, filter: 'order=created_at,asc'}
|
{title: 'Oldest to Newest', query: 'created_at,asc', isDefault: false, filter: 'order=created_at,asc'}
|
||||||
]
|
]
|
||||||
|
|
||||||
self.filters.genres =
|
self.filters.genres =
|
||||||
|
|
58
public/scripts/base/jquery.viewport.js
Normal file
58
public/scripts/base/jquery.viewport.js
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
/*
|
||||||
|
* Viewport - jQuery selectors for finding elements in viewport
|
||||||
|
*
|
||||||
|
* Copyright (c) 2008-2009 Mika Tuupola
|
||||||
|
*
|
||||||
|
* Licensed under the MIT license:
|
||||||
|
* http://www.opensource.org/licenses/mit-license.php
|
||||||
|
*
|
||||||
|
* Project home:
|
||||||
|
* http://www.appelsiini.net/projects/viewport
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
(function($) {
|
||||||
|
|
||||||
|
$.belowthefold = function(element, settings) {
|
||||||
|
var fold = $(window).height() + $(window).scrollTop();
|
||||||
|
return fold <= $(element).offset().top - settings.threshold;
|
||||||
|
};
|
||||||
|
|
||||||
|
$.abovethetop = function(element, settings) {
|
||||||
|
var top = $(window).scrollTop();
|
||||||
|
return top >= $(element).offset().top + $(element).height() - settings.threshold;
|
||||||
|
};
|
||||||
|
|
||||||
|
$.rightofscreen = function(element, settings) {
|
||||||
|
var fold = $(window).width() + $(window).scrollLeft();
|
||||||
|
return fold <= $(element).offset().left - settings.threshold;
|
||||||
|
};
|
||||||
|
|
||||||
|
$.leftofscreen = function(element, settings) {
|
||||||
|
var left = $(window).scrollLeft();
|
||||||
|
return left >= $(element).offset().left + $(element).width() - settings.threshold;
|
||||||
|
};
|
||||||
|
|
||||||
|
$.inviewport = function(element, settings) {
|
||||||
|
return !$.rightofscreen(element, settings) && !$.leftofscreen(element, settings) && !$.belowthefold(element, settings) && !$.abovethetop(element, settings);
|
||||||
|
};
|
||||||
|
|
||||||
|
$.extend($.expr[':'], {
|
||||||
|
"below-the-fold": function(a, i, m) {
|
||||||
|
return $.belowthefold(a, {threshold : 0});
|
||||||
|
},
|
||||||
|
"above-the-top": function(a, i, m) {
|
||||||
|
return $.abovethetop(a, {threshold : 0});
|
||||||
|
},
|
||||||
|
"left-of-screen": function(a, i, m) {
|
||||||
|
return $.leftofscreen(a, {threshold : 0});
|
||||||
|
},
|
||||||
|
"right-of-screen": function(a, i, m) {
|
||||||
|
return $.rightofscreen(a, {threshold : 0});
|
||||||
|
},
|
||||||
|
"in-viewport": function(a, i, m) {
|
||||||
|
return $.inviewport(a, {threshold : 0});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
})(jQuery);
|
|
@ -20,6 +20,34 @@
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
line-height: normal;
|
line-height: normal;
|
||||||
|
|
||||||
|
> .btn {
|
||||||
|
float: left;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
> .btn + .btn {
|
||||||
|
.transition(background 300ms ease-out);
|
||||||
|
|
||||||
|
display: none;
|
||||||
|
margin: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.has-filter {
|
||||||
|
> .btn {
|
||||||
|
background: @pfm-purple;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
> .btn + .btn {
|
||||||
|
display: block;
|
||||||
|
background: darken(@pfm-purple, 20%);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: darken(@pfm-purple, 40%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
&.open {
|
&.open {
|
||||||
> .btn {
|
> .btn {
|
||||||
background: @pfm-purple;
|
background: @pfm-purple;
|
||||||
|
@ -320,7 +348,7 @@ html {
|
||||||
|
|
||||||
li.active a {
|
li.active a {
|
||||||
background: @pfm-purple;
|
background: @pfm-purple;
|
||||||
color: #ddd;
|
color: #fff;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,14 +7,12 @@ html, body {
|
||||||
|
|
||||||
html body {
|
html body {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
background: @pfm-dark-grey;
|
background: #444;
|
||||||
font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
|
font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
header, .site-body {
|
header, .site-body {
|
||||||
.box-shadow(0 0 7px rgba(0, 0, 0, .3));
|
.box-shadow(0 0 7px rgba(0, 0, 0, .6));
|
||||||
max-width: 1200px;
|
|
||||||
margin: auto;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
header {
|
header {
|
||||||
|
@ -50,9 +48,9 @@ header {
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar {
|
.sidebar {
|
||||||
|
background: @pfm-light-grey;
|
||||||
width: @pfm-sidebar-size;
|
width: @pfm-sidebar-size;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
background: @pfm-light-grey;
|
|
||||||
float: left;
|
float: left;
|
||||||
list-style: none;
|
list-style: none;
|
||||||
padding: 0px;
|
padding: 0px;
|
||||||
|
@ -68,6 +66,7 @@ header {
|
||||||
background: #fff;
|
background: #fff;
|
||||||
|
|
||||||
> a {
|
> a {
|
||||||
|
cursor: default;
|
||||||
color: #000;
|
color: #000;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
@import-once 'mixins';
|
@import-once 'mixins';
|
||||||
@import-once 'variables';
|
@import-once 'variables';
|
||||||
|
|
||||||
|
@icon-size: 42px;
|
||||||
|
|
||||||
.tracks-listing.four-columns {
|
.tracks-listing.four-columns {
|
||||||
li {
|
li {
|
||||||
float: left;
|
float: left;
|
||||||
|
@ -23,9 +25,40 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.tracks-listing {
|
.single-player, .tracks-listing li .image {
|
||||||
@icon-size: 42px;
|
float: left;
|
||||||
|
width: @icon-size;
|
||||||
|
height: @icon-size;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.play-button {
|
||||||
|
.transition(background 250ms ease-out);
|
||||||
|
|
||||||
|
position: absolute;
|
||||||
|
top: 0px;
|
||||||
|
left: 0px;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
line-height: 38px;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 12pt;
|
||||||
|
color: #fff;
|
||||||
|
text-decoration: none;
|
||||||
|
background: rgba(0, 0, 0, .4);
|
||||||
|
display: none;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: rgba(0, 0, 0, .8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tracks-listing {
|
||||||
margin: 0px;
|
margin: 0px;
|
||||||
padding: 0px;
|
padding: 0px;
|
||||||
list-style: none;
|
list-style: none;
|
||||||
|
@ -34,44 +67,28 @@
|
||||||
.clearfix();
|
.clearfix();
|
||||||
.box-sizing(border-box);
|
.box-sizing(border-box);
|
||||||
|
|
||||||
|
&.empty {
|
||||||
|
.border-radius(0px);
|
||||||
|
background: lighten(@pfm-purple, 30%);
|
||||||
|
border: 1px solid lighten(@pfm-purple, 10%);
|
||||||
|
color: lighten(@pfm-purple, 3%);
|
||||||
|
float: none !important;
|
||||||
|
width: auto !important;
|
||||||
|
display: block;
|
||||||
|
margin-top: 5px;
|
||||||
|
padding: 5px;
|
||||||
|
font-size: 9pt;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: lighten(@pfm-purple, 30%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
line-height: normal;
|
line-height: normal;
|
||||||
margin: 5px 0px;
|
margin: 5px 0px;
|
||||||
padding: 0px;
|
padding: 0px;
|
||||||
padding-right: 10px;
|
padding-right: 10px;
|
||||||
|
|
||||||
.image {
|
|
||||||
float: left;
|
|
||||||
width: @icon-size;
|
|
||||||
height: @icon-size;
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
.play-button {
|
|
||||||
.transition(background 250ms ease-out);
|
|
||||||
|
|
||||||
position: absolute;
|
|
||||||
top: 0px;
|
|
||||||
left: 0px;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
line-height: 38px;
|
|
||||||
text-align: center;
|
|
||||||
font-size: 12pt;
|
|
||||||
color: #fff;
|
|
||||||
text-decoration: none;
|
|
||||||
background: rgba(0, 0, 0, .4);
|
|
||||||
display: none;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background: rgba(0, 0, 0, .8);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
img {
|
|
||||||
display: block;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.icons {
|
.icons {
|
||||||
float: right;
|
float: right;
|
||||||
display: block;
|
display: block;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<div>
|
<div>
|
||||||
<ul class="tabs">
|
<ul class="tabs">
|
||||||
<li ng-class="{active: $state.includes('account-content.tracks')}"><a href="/account/tracks">Tracks</a></li>
|
<li ng-class="{active: stateIncludes('account-content.tracks')}"><a href="/account/tracks">Tracks</a></li>
|
||||||
<li ng-class="{active: $state.includes('account-content.albums')}"><a href="/account/albums">Albums</a></li>
|
<li ng-class="{active: stateIncludes('account-content.albums')}"><a href="/account/albums">Albums</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<ui-view></ui-view>
|
<ui-view></ui-view>
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
<div>
|
<div>
|
||||||
<ul class="tabs">
|
<ul class="tabs">
|
||||||
<li ng-class="{active: $state.includes('account-favourites.tracks')}"><a href="/account/favourites">Tracks</a></li>
|
<li ng-class="{active: stateIncludes('account-favourites.tracks')}"><a href="/account/favourites">Tracks</a></li>
|
||||||
<li ng-class="{active: $state.includes('account-favourites.albums')}"><a href="/account/favourites/albums">Albums</a></li>
|
<li ng-class="{active: stateIncludes('account-favourites.albums')}"><a href="/account/favourites/albums">Albums</a></li>
|
||||||
<li ng-class="{active: $state.includes('account-favourites.playlists')}"><a href="/account/favourites/playlists">Playlists</a></li>
|
<li ng-class="{active: stateIncludes('account-favourites.playlists')}"><a href="/account/favourites/playlists">Playlists</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<ui-view></ui-view>
|
<ui-view></ui-view>
|
||||||
|
|
|
@ -22,9 +22,9 @@
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
<ul class="tabs">
|
<ul class="tabs">
|
||||||
<li ng-class="{active: $state.includes('artist.profile')}"><a href="{{artist.slug}}">Profile</a></li>
|
<li ng-class="{active: stateIncludes('artist.profile')}"><a href="{{artist.slug}}">Profile</a></li>
|
||||||
<li ng-class="{active: $state.includes('artist.content')}"><a href="{{artist.slug}}/content">Content</a></li>
|
<li ng-class="{active: stateIncludes('artist.content')}"><a href="{{artist.slug}}/content">Content</a></li>
|
||||||
<li ng-class="{active: $state.includes('artist.favourites')}"><a href="{{artist.slug}}/favourites">Favourites</a></li>
|
<li ng-class="{active: stateIncludes('artist.favourites')}"><a href="{{artist.slug}}/favourites">Favourites</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
<ul class="tabs">
|
<ul class="tabs">
|
||||||
<li ng-class="{active: $state.includes('content.tracks') || $state.includes('content.track')}"><a href="/tracks">Tracks</a></li>
|
<li ng-class="{active: stateIncludes('content.tracks') || stateIncludes('content.track')}"><a href="/tracks">Tracks</a></li>
|
||||||
<li ng-class="{active: $state.includes('content.artists') || $state.includes('content.artist')}"><a href="/artists">Artists</a></li>
|
<li ng-class="{active: stateIncludes('content.artists') || stateIncludes('content.artist')}"><a href="/artists">Artists</a></li>
|
||||||
<li ng-class="{active: $state.includes('content.albums') || $state.includes('content.album')}"><a href="/albums">Albums</a></li>
|
<li ng-class="{active: stateIncludes('content.albums') || stateIncludes('content.album')}"><a href="/albums">Albums</a></li>
|
||||||
<li ng-class="{active: $state.includes('content.playlists') || $state.includes('content.playlist')}"><a href="/playlists">Playlists</a></li>
|
<li ng-class="{active: stateIncludes('content.playlists') || stateIncludes('content.playlist')}"><a href="/playlists">Playlists</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<ui-view></ui-view>
|
<ui-view></ui-view>
|
7
public/templates/directives/track-player.html
Normal file
7
public/templates/directives/track-player.html
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
<div class="single-player">
|
||||||
|
<a href="#" class="play-button" pfm-eat-click ng-click="play()">
|
||||||
|
<i class="icon-play" ng-show="!track.isPlaying"></i>
|
||||||
|
<i class="icon-pause" ng-hide="!track.isPlaying"></i>
|
||||||
|
</a>
|
||||||
|
<img ng-src="{{track.covers.thumbnail}}" />
|
||||||
|
</div>
|
|
@ -1,3 +1,3 @@
|
||||||
<div class="stretch-to-bottom">
|
<div class="stretch-to-bottom">
|
||||||
<pfm-tracks-list tracks="tracks" class="two-columns"></pfm-tracks-list>
|
<pfm-tracks-list tracks="tracks" class="three-columns"></pfm-tracks-list>
|
||||||
</div>
|
</div>
|
|
@ -1,8 +1,9 @@
|
||||||
<ul class="dropdowns">
|
<ul class="dropdowns">
|
||||||
<li class="dropdown">
|
<li class="dropdown" ng-class="{'has-filter': query.filters.trackTypes.selectedArray.length}">
|
||||||
<a class="dropdown-toggle btn" ng-class="{'btn-info': query.filters.trackTypes.selectedArray.length}">
|
<a class="dropdown-toggle btn">
|
||||||
Type: <strong class="ng-cloak">{{query.filters.trackTypes.title}}</strong>
|
Type: <strong>{{query.filters.trackTypes.title}}</strong>
|
||||||
</a>
|
</a>
|
||||||
|
<a class="btn" pfm-eat-click ng-click="clearFilter('trackTypes')"><i class="icon-remove"></i></a>
|
||||||
<ul class="dropdown-menu">
|
<ul class="dropdown-menu">
|
||||||
<li ng-repeat="type in filters.trackTypes.values" ng-class="{selected: query.isIdSelected('trackTypes', type.id)}">
|
<li ng-repeat="type in filters.trackTypes.values" ng-class="{selected: query.isIdSelected('trackTypes', type.id)}">
|
||||||
<a class="dont-close" pfm-eat-click href="#" ng-click="toggleListFilter('trackTypes', type.id); $event.stopPropagation();"><i class="icon-plus"></i></a>
|
<a class="dont-close" pfm-eat-click href="#" ng-click="toggleListFilter('trackTypes', type.id); $event.stopPropagation();"><i class="icon-plus"></i></a>
|
||||||
|
@ -10,10 +11,11 @@
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li class="dropdown">
|
<li class="dropdown" ng-class="{'has-filter': query.filters.showSongs.selectedArray.length}">
|
||||||
<a class="dropdown-toggle btn" ng-class="{'btn-info': query.filters.showSongs.selectedArray.length}">
|
<a class="dropdown-toggle btn">
|
||||||
Show Songs: <strong>{{query.filters.showSongs.title}}</strong>
|
Show Songs: <strong>{{query.filters.showSongs.title}}</strong>
|
||||||
</a>
|
</a>
|
||||||
|
<a class="btn" pfm-eat-click ng-click="clearFilter('showSongs')"><i class="icon-remove"></i></a>
|
||||||
<ul class="dropdown-menu">
|
<ul class="dropdown-menu">
|
||||||
<li ng-repeat="song in filters.showSongs.values" ng-class="{selected: query.isIdSelected('showSongs', song.id)}">
|
<li ng-repeat="song in filters.showSongs.values" ng-class="{selected: query.isIdSelected('showSongs', song.id)}">
|
||||||
<a class="dont-close" pfm-eat-click href="#" ng-click="toggleListFilter('showSongs', song.id); $event.stopPropagation();"><i class="icon-plus"></i></a>
|
<a class="dont-close" pfm-eat-click href="#" ng-click="toggleListFilter('showSongs', song.id); $event.stopPropagation();"><i class="icon-plus"></i></a>
|
||||||
|
@ -21,10 +23,11 @@
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li class="dropdown">
|
<li class="dropdown" ng-class="{'has-filter': query.filters.genres.selectedArray.length}">
|
||||||
<a class="dropdown-toggle btn" ng-class="{'btn-info': query.filters.genres.selectedArray.length}">
|
<a class="dropdown-toggle btn">
|
||||||
Genre: <strong>{{query.filters.genres.title}}</strong>
|
Genre: <strong>{{query.filters.genres.title}}</strong>
|
||||||
</a>
|
</a>
|
||||||
|
<a class="btn" pfm-eat-click ng-click="clearFilter('genres')"><i class="icon-remove"></i></a>
|
||||||
<ul class="dropdown-menu">
|
<ul class="dropdown-menu">
|
||||||
<li ng-repeat="genre in filters.genres.values" ng-class="{selected: query.isIdSelected('genres', genre.id)}">
|
<li ng-repeat="genre in filters.genres.values" ng-class="{selected: query.isIdSelected('genres', genre.id)}">
|
||||||
<a class="dont-close" pfm-eat-click href="#" ng-click="toggleListFilter('genres', genre.id); $event.stopPropagation();"><i class="icon-plus"></i></a>
|
<a class="dont-close" pfm-eat-click href="#" ng-click="toggleListFilter('genres', genre.id); $event.stopPropagation();"><i class="icon-plus"></i></a>
|
||||||
|
@ -32,20 +35,22 @@
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li class="dropdown">
|
<li class="dropdown" ng-class="{'has-filter': !query.filters.isVocal.isDefault}">
|
||||||
<a class="dropdown-toggle btn" ng-class="{'btn-info': !query.filters.isVocal.isDefault}">
|
<a class="dropdown-toggle btn">
|
||||||
Is Vocal: <strong>{{query.filters.isVocal.title}}</strong>
|
Is Vocal: <strong>{{query.filters.isVocal.title}}</strong>
|
||||||
</a>
|
</a>
|
||||||
|
<a class="btn" pfm-eat-click ng-click="clearFilter('isVocal')"><i class="icon-remove"></i></a>
|
||||||
<ul class="dropdown-menu">
|
<ul class="dropdown-menu">
|
||||||
<li ng-repeat="item in filters.isVocal.values" ng-class="{selected: item == query.filters.isVocal}">
|
<li ng-repeat="item in filters.isVocal.values" ng-class="{selected: item == query.filters.isVocal}">
|
||||||
<a pfm-eat-click href="#" ng-click="setFilter('isVocal', item);">{{item.title}}</a>
|
<a pfm-eat-click href="#" ng-click="setFilter('isVocal', item);">{{item.title}}</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li class="dropdown">
|
<li class="dropdown" ng-class="{'has-filter': !query.filters.sort.isDefault}">
|
||||||
<a class="dropdown-toggle btn" ng-class="{'btn-info': !query.filters.sort.isDefault}">
|
<a class="dropdown-toggle btn">
|
||||||
Order: <strong>{{query.filters.sort.title}}</strong>
|
Order: <strong>{{query.filters.sort.title}}</strong>
|
||||||
</a>
|
</a>
|
||||||
|
<a class="btn" pfm-eat-click ng-click="clearFilter('sort')"><i class="icon-remove"></i></a>
|
||||||
<ul class="dropdown-menu">
|
<ul class="dropdown-menu">
|
||||||
<li ng-repeat="filter in filters.sort.values" ng-class="{selected: filter == query.filters.sort}">
|
<li ng-repeat="filter in filters.sort.values" ng-class="{selected: filter == query.filters.sort}">
|
||||||
<a pfm-eat-click href="#" ng-click="setFilter('sort', filter)">{{filter.title}}</a>
|
<a pfm-eat-click href="#" ng-click="setFilter('sort', filter)">{{filter.title}}</a>
|
||||||
|
|
|
@ -1,10 +1,4 @@
|
||||||
<div class="track-details" xmlns="http://www.w3.org/1999/html">
|
<div class="track-details" xmlns="http://www.w3.org/1999/html">
|
||||||
<ul class="breadcrumb">
|
|
||||||
<li><a href="/tracks">Tracks</a> <span class="divider">/</span></li>
|
|
||||||
<li><a href="/tracks?filter=genres-{{track.genre.id}}">{{track.genre.name}}</a> <span class="divider">/</span></li>
|
|
||||||
<li class="active">{{track.title}}</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<div class="track-toolbar btn-group pull-right">
|
<div class="track-toolbar btn-group pull-right">
|
||||||
<pfm-favourite-button resource="track" type="track"></pfm-favourite-button>
|
<pfm-favourite-button resource="track" type="track"></pfm-favourite-button>
|
||||||
<div class="dropdown">
|
<div class="dropdown">
|
||||||
|
@ -31,7 +25,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<pfm-tracks-list tracks="trackArray"></pfm-tracks-list>
|
<pfm-track-player track="track"></pfm-track-player>
|
||||||
<h1>
|
<h1>
|
||||||
{{track.title}}
|
{{track.title}}
|
||||||
<span class="subtitle">
|
<span class="subtitle">
|
||||||
|
|
Loading…
Reference in a new issue