Skip to content

Commit

Permalink
feat(listen) Added recent recordings page for bare listen link
Browse files Browse the repository at this point in the history
Also served as a platform to test new query builder.
Added a library for humanising durations.
Added moment and _ services.
Added recent recordings page.
Added new /filter queries to Site and AudioRecording.
  • Loading branch information
atruskie committed Sep 6, 2014
1 parent e7fa031 commit 1af485d
Show file tree
Hide file tree
Showing 13 changed files with 224 additions and 16 deletions.
3 changes: 2 additions & 1 deletion bower.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@
"draggabilly": "~1.1.x",
"bowser": "0.7.x",
"angular-growl-v2": "~0.7.0",
"angular-local-storage": "~0.0.7"
"angular-local-storage": "~0.0.7",
"humanize-duration": "~2.0.0"
},
"dependencies": {},
"private": true
Expand Down
3 changes: 2 additions & 1 deletion build.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,8 @@ module.exports = {
'vendor/draggabilly/draggabilly.js',
'vendor/bowser/bowser.js',
'vendor/angular-growl-v2/build/angular-growl.js',
'vendor/angular-local-storage/angular-local-storage.js'
'vendor/angular-local-storage/angular-local-storage.js',
'vendor/humanize-duration/humanize-duration.js'

],
css: [
Expand Down
8 changes: 7 additions & 1 deletion src/app/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,12 @@ var app = angular.module('baw',
'bawApp.directives.ngAudio', /* our directives.js */
'bawApp.directives.toggleSwitch',
'bawApp.filters', /* our filters.js */

"bawApp.services.core",
'bawApp.services.queryBuilder',
'bawApp.services', /* our services.js */
'bawApp.services.unitConverter',

'audio-control',
'draggabilly',

Expand All @@ -95,6 +99,7 @@ var app = angular.module('baw',
'bawApp.projects',
'bawApp.recordInformation',
'bawApp.recordings',
'bawApp.recordings.recentRecordings',
'bawApp.search',
'bawApp.tags',
'bawApp.users',
Expand Down Expand Up @@ -129,7 +134,8 @@ var app = angular.module('baw',
when('/recordings/:recordingId',
{templateUrl: '/assets/recording.html', controller: 'RecordingCtrl' }).

when('/listen', {templateUrl: paths.site.files.listen, controller: 'ListenCtrl', title: 'Listen'}).

when('/listen', {templateUrl: paths.site.files.recordings.recentRecordings, controller: 'RecentRecordingsCtrl', title: 'Listen'}).
when('/listen/:recordingId', {templateUrl: paths.site.files.listen, controller: 'ListenCtrl', title: ':recordingId'}).
//when('/listen/:recordingId/start=:start/end=:end', {templateUrl: paths.site.files.listen, controller: 'ListenCtrl'}).

Expand Down
5 changes: 5 additions & 0 deletions src/app/recordings/recentRecordings/_recentRecordings.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#recentRecordingsTable {
tr:hover {
cursor: pointer;
}
}
74 changes: 74 additions & 0 deletions src/app/recordings/recentRecordings/recentRecordings.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
angular.module("bawApp.recordings.recentRecordings", [])
.controller("RecentRecordingsCtrl",
[
"$scope",
"$location",
"AudioRecording",
"Site",
"moment",
"conf.paths",
function RecentRecordingsCtrl($scope, $location, AudioRecording, Site, moment, paths) {
$scope.recentRecordings = [
{
siteId: 1000,
duration: 123456,
uploaded: new Date(),
id: 1234
},
{
siteId: 1000,
duration: 123456,
uploaded: new Date(),
id: 1234
},
{
siteId: 1000,
duration: 123456,
uploaded: new Date(),
id: 1234
}
];

function audioRecordingsFormat(wrapper) {
$scope.recentRecordings = wrapper.data;
// format return objects for display
$scope.recentRecordings.forEach(function(value, index) {
value.durationHumanized = moment.duration(value.durationSeconds, "seconds").humanizeDuration();
value.uploadedHumanized = moment(value.createdAt).fromNow();
value.listenLink = paths.site.ngRoutes.listen.format({recordingId: value.id});
});

return Site.getSitesByIds();
}

function sitesFormat(wrapper) {
var sites = wrapper.reduce(function(state, current) {
state[current.id] = current;
return state;
}, {});

$scope.audioRecordings.forEach(function (value) {
value.site = sites[value.siteId];
});
}

AudioRecording
.getRecentRecordings()
.then(audioRecordingsFormat)
.then(function gsbiSucccess(data) {

})
.catch(function error(reason) {
console.error(reason);
});



//Site.getNames();

$scope.navigate = function navigate(link) {
$location.url(link);
};
}
]
);
35 changes: 35 additions & 0 deletions src/app/recordings/recentRecordings/recentRecordings.tpl.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<div id="content">
<h1>Recent Audio Recordings</h1>
<div class="row">
<div class="col-md-12">
<span ng-if="recentRecordings.length === 0">
No recent audio recordings.
</span>
<table id="recentRecordingsTable" class="table table-striped table-hover" ng-if="recentRecordings.length !== 0">
<thead>
<tr>
<th>Site</th>
<th>Duration</th>
<th>Uploaded</th>
<th></th>
</tr>
</thead>
<tbody>
<tr ng-repeat="r in recentRecordings" ng-click="navigate(r.listenLink)">
<td>{{r.site.name || r.siteId}}</td>
<td>{{r.durationHumanized}}</td>
<td>{{r.uploadedHumanized}}</td>
<td>
<a ng-href="{{r.listenLink}}" class="btn btn-primary btn-small">
<span class="glyphicon glyphicon-play"></span> Play
</a>
<a ng-href="" class="btn btn-info btn-small" target="_self">
<span class="glyphicon glyphicon-map-marker"></span> Site
</a>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
10 changes: 8 additions & 2 deletions src/baw.configuration.tpl.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,14 @@ angular.module('bawApp.configuration', ['url'])
project: "/projects/{projectId}",
site: {
flattened: "/sites/{siteId}",
nested: "/projects/{projectId}/sites/{siteId}"
nested: "/projects/{projectId}/sites/{siteId}",
filter: "/sites/filter"
},
audioRecording: {
listShort: "/audio_recordings/{recordingId}",
show: "/audio_recordings/{recordingId}",
list: "/audio_recordings/"
list: "/audio_recordings/",
filter: "/audio_recordings/filter"
},
audioEvent: {
list: "/audio_recordings/{recordingId}/audio_events",
Expand Down Expand Up @@ -123,10 +125,14 @@ angular.module('bawApp.configuration', ['url'])
spec: 'assets/bird_walk/bird_walk_spec.json',
stats: 'assets/bird_walk/bird_walk_stats.json',
images: 'assets/bird_walk/images/'
},
recordings: {
recentRecordings: 'recordings/recentRecordings/recentRecordings.tpl.html'
}
},
// routes used by angular
ngRoutes: {
recentRecordings: "/listen",
listen: "/listen/{recordingId}",
library: "/library",
libraryItem: "/library/{recordingId}/audio_events/{audioEventId}"
Expand Down
11 changes: 11 additions & 0 deletions src/components/services/lodashService.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
var bawssc = bawssc || angular.module("bawApp.services.core", []);

bawssc.provider("_", function() {

// TODO: is there a better way to load lodash without requiring it be attached to window?
var _ = window._;

this.$get = [function lodashFactory() {
return _;
}];
});
19 changes: 19 additions & 0 deletions src/components/services/momentService.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
var bawssc = bawssc || angular.module("bawApp.services.core", []);

bawssc.provider("moment", function() {

// TODO: is there a better way to load moment without requiring it be attached to window?
var moment = window.moment;

// HACK: add real duration formatting onto moment object!
var humanizeDuration = window.humanizeDuration;
this.$get = [function momentFactory() {
moment.humanizeDuration = humanizeDuration;

moment.duration.fn.humanizeDuration = function(parameters) {
return humanizeDuration(this.asMilliseconds(), parameters);
};

return moment;
}];
});
26 changes: 23 additions & 3 deletions src/components/services/queryBuilder.js
Original file line number Diff line number Diff line change
Expand Up @@ -262,12 +262,32 @@ qb.factory("QueryBuilder", ["conf.constants", function(constants) {

RootQuery.prototype = Object.create(Query.prototype);

/**
* @callback createCallback
* @param {RootQuery} query
* @returns {RootQuery}
*/

/**
* Create a new query.
* Optional callback function automatically composes/ends the query.
* @param {createCallback=} queryComposer
* @returns {RootQuery}
*/
function create(queryComposer) {
var q = new RootQuery();

if (queryComposer) {
var result = queryComposer.call(q, q);
q.compose(result);
}

return q;
}

return {
Query: Query,
RootQuery: RootQuery,
create: function () {
return new RootQuery();
}
create: create
};
}]);
43 changes: 36 additions & 7 deletions src/components/services/services.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,23 +23,52 @@
return uri.replace(/(\{([^{}]*)\})/g, ":$2");
}

var bawss = angular.module("bawApp.services", ['ngResource', 'bawApp.configuration']);
var bawss = bawss || angular.module("bawApp.services", ["ngResource", "bawApp.configuration", "bawApp.services.core", "bawApp.services.queryBuilder"]);

bawss.factory('Project', [ '$resource', 'conf.paths', function ($resource, paths) {
return resourcePut($resource, uriConvert(paths.api.routes.projectAbsolute), {projectId: "@projectId"});
bawss.factory('Project', [ '$resource', "$http", 'conf.paths', "QueryBuilder", function ($resource, $http, paths, QueryBuilder) {
var resource = resourcePut($resource, uriConvert(paths.api.routes.projectAbsolute), {projectId: "@projectId"});

return resource;
}]);

bawss.factory('Site', [ '$resource', 'conf.paths', function ($resource, paths) {
return resourcePut($resource, uriConvert(paths.api.routes.site.flattenedAbsolute), { siteId: "@siteId"});
bawss.factory('Site', [ '$resource', "$http", 'conf.paths', "_", "QueryBuilder", function ($resource, $http, paths, _, QueryBuilder) {
var resource = resourcePut($resource, uriConvert(paths.api.routes.site.flattenedAbsolute), { siteId: "@siteId"});


resource.getSitesByIds = function(siteIds) {
var url = paths.api.routes.site.filterAbsolute;
siteIds = _.uniq(siteIds);
var query = QueryBuilder.create(function(q) {
return q.in("id", siteIds);
});
return $http.post(url, query.toJSON());
};


return resource;
}]);

// NOTE: deleted photo resource, API for photos no longer exposed

// NOTE: deleted user resource, API for users no longer exposed

bawss.factory('AudioRecording', [ '$resource', 'conf.paths', function ($resource, paths) {
return resourcePut($resource, uriConvert(paths.api.routes.audioRecording.showAbsolute),
bawss.factory('AudioRecording', [ '$resource', '$http', 'conf.paths', 'QueryBuilder', function ($resource, $http, paths, QueryBuilder) {
var resource = resourcePut($resource, uriConvert(paths.api.routes.audioRecording.showAbsolute),
{projectId: "@projectId", siteId: "@siteId", recordingId: '@recordingId'});

var query = QueryBuilder.create(function(q) {
return q
.sort({orderBy: "createdDate", direction: "desc"})
.page({page:1, items: 10})
.project({include: ["id", "siteId", "durationSeconds", "recordedDate", "createdAt"]});
});
resource.getRecentRecordings = function() {
var url = paths.api.routes.audioRecording.filterAbsolute;

return $http.post(url, query.toJSON());
};

return resource;
}]);

bawss.factory('AudioEvent', [ '$resource', '$url', 'conf.paths',
Expand Down
2 changes: 1 addition & 1 deletion src/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
<div class="collapse navbar-collapse">
<ul class="nav navbar-nav">
<li ng-class="{ active: activePath('/projects') }"><a ng-href="{{paths.api.links.projectsAbsolute}}" target="_self">Projects</a></li>
<li ng-class="{ active: activePath('/listen') }"><a href="#">Listen</a></li>
<li ng-class="{ active: activePath('/listen') }"><a ng-href="{{paths.site.ngRoutes.recentRecordings}}">Listen</a></li>
<li ng-class="{ active: activePath('/library') }"><a ng-href="{{paths.site.ngRoutes.library}}">Library</a></li>
<!--<li ng-class="{ active: activePath('/bird') }"><a href="/birdWalks">Bird Walks</a></li>-->

Expand Down
1 change: 1 addition & 0 deletions src/sass/application.tpl.scss
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ $DEBUG: '<%= build_configs.current.key === "development" %>' == 'true';
@import "../app/projects/projects";
@import "../app/recordInformation/record_information";
@import "../app/recordings/audio_recordings";
@import "../app/recordings/recentRecordings/recentRecordings";
@import "../app/search/saved_searches";
@import "../app/sites/sites";
@import "../app/tags/tags";
Expand Down

0 comments on commit 1af485d

Please sign in to comment.