summaryrefslogtreecommitdiff
path: root/static
diff options
context:
space:
mode:
authorMichaël Ball <michael.ball@gmail.com>2014-12-28 12:24:22 +0000
committerMichaël Ball <michael.ball@gmail.com>2015-11-27 20:02:04 +0000
commit75beec91a8526fbbc0a90134140b9dff6af15c0c (patch)
tree02414e46da3e08000384c40c27b7aab9748de0fe /static
parenta2964845e3c03b9cf5f01583f53f7553c7d67caf (diff)
Initial frontend work
Diffstat (limited to 'static')
-rw-r--r--static/partials/albums/list.html28
-rw-r--r--static/partials/artists/detail.html12
-rw-r--r--static/partials/artists/list.html28
-rw-r--r--static/partials/artists/tracks.html7
-rw-r--r--static/scripts/app/app.js63
-rw-r--r--static/scripts/app/controllers.js148
-rw-r--r--static/scripts/app/filters.js48
-rw-r--r--static/scripts/app/services.js97
8 files changed, 431 insertions, 0 deletions
diff --git a/static/partials/albums/list.html b/static/partials/albums/list.html
new file mode 100644
index 0000000..01ac2a8
--- /dev/null
+++ b/static/partials/albums/list.html
@@ -0,0 +1,28 @@
+<div class="row">
+ <div class="col-sm-offset-1 col-sm-11 col-xs-12">
+ <h2>Albums</h2>
+ </div>
+</div>
+<div class="row">
+ <div class="col-sm-offset-1 col-sm-6 col-xs-12">
+ <input type="text" class="form-control" data-ng-model="search" placeholder="Search for...">
+ </div>
+</div>
+<div class="row" data-ng-hide="search">
+ <div class="col-sm-1 hidden-xs text-center">
+ <div class="btn-group-vertical" role="group">
+ <label data-ng-repeat="i in indices" data-ng-model="$parent.selectedIndex" class="btn btn-default btn-sm" uib-btn-radio="'{{ i }}'" uncheckable>{{ i }}</label>
+ </div>
+ </div>
+ <div class="visible-xs-block col-xs-12">
+ <select data-ng-model="selectedIndex">
+ <option data-ng-repeat="i in indices" value="{{ i }}">{{ i }}</option>
+ </select>
+ </div>
+ <div class="col-sm-11 col-xs-12">
+ <p data-ng-repeat="album in albums | dateFilter:selectedIndex"><a data-ui-sref="albums.detail({ albumId: album.id })">{{ album.name }}<span ng-show="album.date"> ({{ album.date | amDateFormat: 'YYYY':'':'':'YYYY-MM-DD' }})</span></a></p>
+ </div>
+</div>
+<div class="row" data-ng-show="search">
+ <p data-ng-repeat="album in albums | filter:search"><a data-ui-sref="albums.detail({ albumId: album.id })">{{ album.name }}<span ng-show="album.date"> ({{ album.date | amDateFormat: 'YYYY':'':'':'YYYY-MM-DD' }})</span></a></p>
+</div>
diff --git a/static/partials/artists/detail.html b/static/partials/artists/detail.html
new file mode 100644
index 0000000..991633a
--- /dev/null
+++ b/static/partials/artists/detail.html
@@ -0,0 +1,12 @@
+<div class="col-xs-12">
+ <h3>{{ artist.name }}</h3>
+
+ <h4>Albums</h4>
+ <ul>
+ <li data-ng-repeat="album in albums">{{album.name}} ({{ album.date | amDateFormat: 'YYYY':'':'':'YYYY-MM-DD' }})</li>
+ </ul>
+
+ <p><a data-ui-sref="artistdetail.tracks({ artistId: artist.id })">View artist tracks</a></p>
+</div>
+<div class="row" data-ui-view>
+</div> \ No newline at end of file
diff --git a/static/partials/artists/list.html b/static/partials/artists/list.html
new file mode 100644
index 0000000..7c48e57
--- /dev/null
+++ b/static/partials/artists/list.html
@@ -0,0 +1,28 @@
+<div class="row">
+ <div class="col-sm-offset-1 col-sm-11 col-xs-12">
+ <h2>Artists</h2>
+ </div>
+</div>
+<div class="row">
+ <div class="col-sm-offset-1 col-sm-6 col-xs-12">
+ <input type="text" class="form-control" data-ng-model="search" placeholder="Search for...">
+ </div>
+</div>
+<div class="row" data-ng-hide="search">
+ <div class="col-sm-1 hidden-xs text-center">
+ <div class="btn-group-vertical" role="group">
+ <label data-ng-repeat="i in indices" data-ng-model="$parent.selectedIndex" class="btn btn-default btn-sm" uib-btn-radio="'{{ i }}'" uncheckable>{{ i }}</label>
+ </div>
+ </div>
+ <div class="visible-xs-block col-xs-12">
+ <select data-ng-model="selectedIndex">
+ <option data-ng-repeat="i in indices" value="{{ i }}">{{ i }}</option>
+ </select>
+ </div>
+ <div class="col-sm-11 col-xs-12">
+ <p data-ng-repeat="artist in totalArtists | alphabetFilter:{attrs: ['sortname', 'name'], param: selectedIndex }"><a data-ui-sref="artistdetail({ artistId: artist.id })">{{ artist.name }}</a></p>
+ </div>
+</div>
+<div class="row" data-ng-show="search">
+ <p data-ng-repeat="artist in totalArtists | filter:search"><a data-ui-sref="artistdetail({ artistId: artist.id })">{{ artist.name }}</a></p>
+</div> \ No newline at end of file
diff --git a/static/partials/artists/tracks.html b/static/partials/artists/tracks.html
new file mode 100644
index 0000000..8d05b1d
--- /dev/null
+++ b/static/partials/artists/tracks.html
@@ -0,0 +1,7 @@
+<div class="col-xs-12">
+ <h3>{{ artist.name }}'s Tracks</h3>
+
+ <ul>
+ <li data-ng-repeat="track in tracks"><a href="/tracks/{{track.id}}">{{ track.name }}</a></li>
+ </ul>
+</div> \ No newline at end of file
diff --git a/static/scripts/app/app.js b/static/scripts/app/app.js
new file mode 100644
index 0000000..b0d3738
--- /dev/null
+++ b/static/scripts/app/app.js
@@ -0,0 +1,63 @@
+var mach2App = angular.module(
+ 'mach2App',
+ [
+ 'ui.router',
+ 'mach2Services',
+ 'mach2Controllers',
+ 'mach2Filters',
+ 'ui.bootstrap',
+ 'angularMoment'
+ ]
+);
+
+mach2App.config(
+ [
+ '$stateProvider',
+ '$urlRouterProvider',
+ function($stateProvider, $urlRouterProvider) {
+ $stateProvider.state('artists', {
+ url: '/artists',
+ templateUrl: 'static/partials/artists/list.html',
+ controller: 'ArtistCtrl',
+ });
+
+ $stateProvider.state('artistdetail', {
+ url: '/artists/{artistId:int}',
+ templateUrl: 'static/partials/artists/detail.html',
+ controller: 'ArtistDetailCtrl',
+ resolve: {
+ artistId: ['$stateParams', function($stateParams) {
+ return $stateParams.artistId;
+ }]
+ },
+ });
+
+ $stateProvider.state('artistdetail.tracks', {
+ url: '/tracks',
+ templateUrl: 'static/partials/artists/tracks.html',
+ controller: 'ArtistTracksCtrl'
+ });
+
+ $stateProvider.state('albums', {
+ url: '/albums',
+ templateUrl: 'static/partials/albums/list.html',
+ controller: 'AlbumCtrl'
+ });
+
+ $stateProvider.state('albums.detail', {
+ url: '/{albumId:int}',
+ templateUrl: 'static/partials/album/detail.html',
+ controller: 'AlbumDetailCtrl'
+ });
+
+ $urlRouterProvider.otherwise('/artists');
+ }
+ ]
+);
+
+mach2App.constant(
+ 'angularMomentConfig',
+ {
+ timezone: 'utc'
+ }
+); \ No newline at end of file
diff --git a/static/scripts/app/controllers.js b/static/scripts/app/controllers.js
new file mode 100644
index 0000000..35340e6
--- /dev/null
+++ b/static/scripts/app/controllers.js
@@ -0,0 +1,148 @@
+var mach2Controllers = angular.module(
+ 'mach2Controllers',
+ [
+ 'ui.bootstrap',
+ 'angularMoment'
+ ]
+);
+
+mach2Controllers.controller('NavCtrl', ['$scope', function($scope) {
+}]);
+
+mach2Controllers.controller(
+ 'ArtistCtrl',
+ [
+ '$scope',
+ 'ArtistSearch',
+ function($scope, ArtistSearch) {
+ $scope.totalArtists = ArtistSearch.query();
+ $scope.indices = [
+ 'A',
+ 'B',
+ 'C',
+ 'D',
+ 'E',
+ 'F',
+ 'G',
+ 'H',
+ 'I',
+ 'J',
+ 'K',
+ 'L',
+ 'M',
+ 'N',
+ 'O',
+ 'P',
+ 'Q',
+ 'R',
+ 'S',
+ 'T',
+ 'U',
+ 'V',
+ 'W',
+ 'X',
+ 'Y',
+ 'Z',
+ '0-9',
+ 'Other'
+ ];
+ $scope.selectedIndex = $scope.indices[0];
+ }
+ ]
+);
+
+mach2Controllers.controller(
+ 'ArtistDetailCtrl',
+ [
+ '$scope',
+ '$stateParams',
+ 'Artist',
+ 'ArtistAlbums',
+ 'ArtistTracks',
+ function(
+ $scope,
+ $stateParams,
+ Artist,
+ ArtistAlbums,
+ ArtistTracks
+ ) {
+ console.log('Am I here?');
+ $scope.artist = Artist.query({
+ artistId: $stateParams.artistId
+ });
+
+ $scope.albums = ArtistAlbums.query({
+ artistId: $stateParams.artistId
+ });
+
+ $scope.tracks = ArtistTracks.query({
+ artistId: $stateParams.artistId
+ });
+ }
+ ]
+);
+
+mach2Controllers.controller(
+ 'ArtistTracksCtrl',
+ [
+ '$scope',
+ '$stateParams',
+ 'Artist',
+ 'ArtistTracks',
+ function($scope, $stateParams, Artist, ArtistTracks) {
+ $scope.artist = Artist.query({
+ artistId: $stateParams.artistId
+ });
+
+ $scope.tracks = ArtistTracks.query({
+ artistId: $stateParams.artistId
+ });
+ }
+ ]
+);
+
+mach2Controllers.controller(
+ 'AlbumCtrl',
+ [
+ '$scope',
+ 'AlbumArtists',
+ 'AlbumSearch',
+ function($scope, AlbumArtists, AlbumSearch) {
+ // horrible way of calculating decades
+ var currentYear = moment().format('YYYY');
+ var startDecade = 1940;
+
+ var decades = [];
+
+ for (i = (startDecade/10); i <= (currentYear/10); i++) {
+ decades.push(i * 10);
+ }
+
+ $scope.albums = AlbumSearch.query();
+ $scope.indices = decades;
+ $scope.selectedIndex = $scope.indices[0];
+ $scope.albumArtists = AlbumArtists;
+ }
+ ]
+);
+
+mach2Controllers.controller(
+ 'AlbumDetailCtrl',
+ [
+ '$scope',
+ '$stateParams',
+ 'Album',
+ 'AlbumTracks',
+ function(
+ $scope,
+ $stateParams,
+ Album,
+ AlbumTracks
+ ) {
+
+ }
+ ]
+);
+
+mach2Controllers.controller('TrackCtrl', ['$scope', function($scope) {
+}]);
diff --git a/static/scripts/app/filters.js b/static/scripts/app/filters.js
new file mode 100644
index 0000000..ed1f537
--- /dev/null
+++ b/static/scripts/app/filters.js
@@ -0,0 +1,48 @@
+var mach2Filters = angular.module('mach2Filters',[]);
+
+mach2Filters.filter('alphabetFilter', function() {
+ return function(items, search) {
+ if (!search) {
+ return items;
+ }
+
+ return items.filter(function(element, index, array) {
+ var searchTerm = search.param;
+ var searchAttrs = search.attrs;
+ var regexp = new RegExp(searchTerm, 'i');
+
+ var searchString = null;
+
+ for(i = 0; i < searchAttrs.length; i++) {
+ if (element[searchAttrs[i]]) {
+ searchString = element[searchAttrs[i]];
+ break;
+ }
+ }
+
+ if (searchTerm === '0-9') {
+ regexp = /[0-9]/;
+ } else if (searchTerm === 'Other') {
+ regexp = /\W/;
+ }
+
+ if (searchString.charAt(0).match(regexp) !== null) {
+ return true;
+ } else {
+ return false;
+ }
+ });
+ };
+});
+
+mach2Filters.filter('dateFilter', function() {
+ return function(items, search) {
+ return items.filter(function(element, index, array) {
+ var albumDate = moment(element.date, 'YYYY-MM-DD');
+ var compDate = moment(search, 'YYYY');
+ var compNextDate = moment((parseInt(search) + 10), 'YYYY');
+
+ return (albumDate.isAfter(compDate) && albumDate.isBefore(compNextDate));
+ });
+ };
+}); \ No newline at end of file
diff --git a/static/scripts/app/services.js b/static/scripts/app/services.js
new file mode 100644
index 0000000..c7cd92b
--- /dev/null
+++ b/static/scripts/app/services.js
@@ -0,0 +1,97 @@
+var mach2Services = angular.module('mach2Services', ['ngResource']);
+
+mach2Services.factory('Artist', ['$resource', function($resource) {
+ return $resource('artists/:artistId', {}, {
+ query: {
+ method: 'GET'
+ }
+ });
+}]);
+
+mach2Services.factory('ArtistAlbums', ['$resource', function($resource) {
+ return $resource('artists/:artistId/albums', {}, {
+ query: {
+ method: 'GET',
+ isArray: true
+ }
+ });
+}]);
+
+mach2Services.factory('ArtistSearch', ['$resource', function($resource) {
+ return $resource('artists/:name', {}, {
+ query: {
+ method: 'GET',
+ isArray: true
+ }
+ });
+}]);
+
+mach2Services.factory('ArtistTracks', ['$resource', function($resource) {
+ return $resource('artists/:artistId/tracks', {}, {
+ query: {
+ method: 'GET',
+ isArray: true
+ }
+ });
+}]);
+
+mach2Services.factory('Album', ['$resource', function($resource) {
+ return $resource('albums/:albumId', {}, {
+ query: {
+ method: 'GET'
+ }
+ });
+}]);
+
+mach2Services.factory('AlbumArtists', ['$resource', function($resource) {
+ return $resource('albums/:albumId/artists', {}, {
+ query: {
+ method: 'GET',
+ isArray: true
+ }
+ });
+}]);
+
+mach2Services.factory('AlbumSearch', ['$resource', function($resource) {
+ return $resource('albums/:name', {}, {
+ query: {
+ method: 'GET',
+ isArray: true,
+ }
+ });
+}]);
+
+mach2Services.factory('AlbumTracks', ['$resource', function($resource) {
+ return $resource('albums/:albumId/tracks', {}, {
+ query: {
+ method: 'GET',
+ isArray: true
+ }
+ });
+}]);
+
+mach2Services.factory('Track', ['$resource', function($resource) {
+ return $resource('tracks/:trackId', {}, {
+ query: {
+ method: 'GET'
+ }
+ });
+}]);
+
+mach2Services.factory('TrackArtists', ['$resource', function($resource) {
+ return $resource('tracks/:trackId/artists', {}, {
+ query: {
+ method: 'GET'
+ }
+ });
+}]);
+
+
+mach2Services.factory('TrackSearch', ['$resource', function($resource) {
+ return $resource('tracks/:name', {}, {
+ query: {
+ method: 'GET',
+ isArray: true
+ }
+ });
+}]);