From f47f9c5801e5d61d4e1560c1eaac636653d25ed1 Mon Sep 17 00:00:00 2001 From: Anthony Truskinger Date: Mon, 16 Dec 2013 16:32:03 +1000 Subject: [PATCH 1/8] [WIP] First interation of downloading metadata. Not ready. Needs a shallow route for sites. Requires changes to baw-server --- src/app/listen/listen.js | 102 +++++++++++++++++++++++++++++---------- 1 file changed, 76 insertions(+), 26 deletions(-) diff --git a/src/app/listen/listen.js b/src/app/listen/listen.js index 1edac256..975ca3b4 100644 --- a/src/app/listen/listen.js +++ b/src/app/listen/listen.js @@ -4,6 +4,7 @@ angular.module('bawApp.listen', ['decipher.tags', 'ui.bootstrap.typeahead']) '$resource', '$routeParams', '$route', + '$q', 'conf.paths', 'conf.constants', '$url', @@ -12,6 +13,8 @@ angular.module('bawApp.listen', ['decipher.tags', 'ui.bootstrap.typeahead']) 'AudioEvent', 'Tag', 'Taggings', + 'Site', + 'Project', /** * The listen controller. * @param $scope @@ -27,10 +30,12 @@ angular.module('bawApp.listen', ['decipher.tags', 'ui.bootstrap.typeahead']) * @param $url * @param AudioRecording * @param Taggings + * @param $q + * @param Site + * @param Project */ - function ListenCtrl( - $scope, $resource, $routeParams, $route, paths, constants, $url, AudioRecording, Media, AudioEvent, Tag, - Taggings) { + function ListenCtrl($scope, $resource, $routeParams, $route, $q, paths, constants, $url, + AudioRecording, Media, AudioEvent, Tag, Taggings, Site, Project) { var CHUNK_DURATION_SECONDS = constants.listen.chunkDurationSeconds; function getMediaParameters(format) { @@ -75,7 +80,10 @@ angular.module('bawApp.listen', ['decipher.tags', 'ui.bootstrap.typeahead']) audioElement: {}, audioEvents: [], media: null, - selectedAudioEvent: null + selectedAudioEvent: null, + audioRecording: null, + project: null, + site: null }; var formatPaths = function () { @@ -143,13 +151,47 @@ angular.module('bawApp.listen', ['decipher.tags', 'ui.bootstrap.typeahead']) console.error("retrieval of media json failed"); }); - $scope.model.audioRecording = AudioRecording.get({recordingId: recordingId}, {}, - function audioRecordingGetSuccess() { - // no-op - // if an audioRecording 'model' is ever created, this is where we would transform the returned data - }, - function audioRecordingGetFailure() { - console.error("retrieval of audioRecording json failed"); + + var promise = (function getResources() { + var deferred = $q.defer(); + + AudioRecording.get({recordingId: recordingId}, {}, + function audioRecordingGetSuccess(value) { + // if an audioRecording 'model' is ever created, this is where we would transform the returned data + $scope.model.audioRecording = value; + deferred.resolve(value); + }, + function audioRecordingGetFailure() { + deferred.reject("retrieval of audioRecording json failed"); + }); + + return deferred.promise; + })() + .then(function success(result) { + var siteDeferred = $q.defer(); + // get site + Site.get({siteId: result.siteId}, {}, function getSiteSuccess(value) { + $scope.model.site = value; + siteDeferred.resolve(value) + }, function getSiteError() { + siteDeferred.reject("retrieval of site json failed"); + }); + + return siteDeferred.promise; + }) + .then(function success() { + var projectDeferred = $q.defer(); + // get site + Project.get({id: result.projectId}, {}, function getProjectSuccess(value) { + $scope.model.project = value; + projectDeferred.resolve(value) + }, function getSiteError() { + projectDeferred.reject("retrieval of site json failed"); + }); + + return projectDeferred.promise; + }).catch(function error(err) { + console.error("An error occurred downloading metadata for this chunk:" + err, err); }); @@ -179,7 +221,7 @@ angular.module('bawApp.listen', ['decipher.tags', 'ui.bootstrap.typeahead']) $scope.tags.push(baw.Tag.make(value)); }); - $scope.model.audioEvents.forEach(function(value){ + $scope.model.audioEvents.forEach(function (value) { Tag.resolveAll(value.tags, $scope.tags); }); }, @@ -249,11 +291,16 @@ angular.module('bawApp.listen', ['decipher.tags', 'ui.bootstrap.typeahead']) var offset = base.add({seconds: $scope.model.media.startOffset}); return offset; }; - + + $scope.previousEnabled = false; $scope.nextEnabled = false; - $scope.createNavigationHref = function (linkType, stepBy) { + // skip if resources not available + if (!$scope.model.audioRecording) { + return "#"; + } + if (!angular.isNumber(stepBy)) { stepBy = CHUNK_DURATION_SECONDS; } @@ -262,13 +309,13 @@ angular.module('bawApp.listen', ['decipher.tags', 'ui.bootstrap.typeahead']) if (linkType === "previous") { var lowerBound = ($routeParams.start - stepBy); - + if ($routeParams.start > 0) { $scope.previousEnabled = true; } else { - $scope.previousEnabled = false; + $scope.previousEnabled = false; } - + if (lowerBound === 0) { baseLink.end = lowerBound + stepBy; } @@ -286,36 +333,40 @@ angular.module('bawApp.listen', ['decipher.tags', 'ui.bootstrap.typeahead']) return uriPrev; } - else if (linkType === "next") { - + else if (linkType === "next") { + var maxEnd = Math.floor($scope.model.audioRecording.durationSeconds); - + var uriNext = $url.formatUri( paths.site.ngRoutes.listen, { recordingId: recordingId, start: ($routeParams.start + stepBy), - end: (($routeParams.end + stepBy < maxEnd) ? $routeParams.end + stepBy : maxEnd) + end: (($routeParams.end + stepBy < maxEnd) ? $routeParams.end + stepBy : maxEnd) }); - + if ($routeParams.end < $scope.model.audioRecording.durationSeconds - constants.listen.minAudioDurationSeconds) { $scope.nextEnabled = true; } else { - $scope.nextEnabled = false; + $scope.nextEnabled = false; } - + return uriNext; } throw "Invalid link type specified in createNavigationHref"; }; + $scope.clearSelected = function () { $scope.model.audioEvents.forEach(function (value, key) { value.selected = false; }); + + $scope.model.selectedAudioEvent = null; }; + $scope.singleEditDisabled = function () { return ($scope.model.selectedAudioEvent === null || $scope.model.selectedAudioEvent.id === undefined); }; @@ -339,7 +390,6 @@ angular.module('bawApp.listen', ['decipher.tags', 'ui.bootstrap.typeahead']) tagTemplateUrl: "/templates/tags.html" }; - $scope.$on('decipher.tags.initialized', function (event) { event.stopPropagation(); console.debug('decipher.tags.initialized', arguments); @@ -409,7 +459,7 @@ angular.module('bawApp.listen', ['decipher.tags', 'ui.bootstrap.typeahead']) // assumes tags array is kept in sync //delete $scope.model.selectedAudioEvent.tags[index]; - console.debug("Tag removal success", removedTag.tag.text ); + console.debug("Tag removal success", removedTag.tag.text); }, function error(response) { console.error("Tagging creation failed", response); From b9e948d83eae81322da6e6c384f3430b8bd85ab1 Mon Sep 17 00:00:00 2001 From: Anthony Truskinger Date: Sat, 18 Jan 2014 05:30:17 +1000 Subject: [PATCH 2/8] Fixed navbar bug. created specialised binding and styles to ensure consitent visuals --- src/app/listen/_listen.scss | 16 ++++++++++++ src/app/listen/listen.js | 2 ++ src/app/listen/listen.tpl.html | 2 +- .../directives/input[type=range].js | 26 +++++++++++++++++++ 4 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 src/components/directives/input[type=range].js diff --git a/src/app/listen/_listen.scss b/src/app/listen/_listen.scss index 6056912c..f1ae4804 100644 --- a/src/app/listen/_listen.scss +++ b/src/app/listen/_listen.scss @@ -3,6 +3,8 @@ input[type="range"] { width: 300px; + + } &>span { @@ -11,6 +13,20 @@ } } +.hide-thumb { + + &::-ms-thumb { + opacity: 0; + } + &::-moz-range-thumb { + opacity: 0; + } + &::-webkit-slider-thumb { + opacity: 0; + } + +} + .position { & span { diff --git a/src/app/listen/listen.js b/src/app/listen/listen.js index 7995d079..30159b0d 100644 --- a/src/app/listen/listen.js +++ b/src/app/listen/listen.js @@ -72,6 +72,7 @@ angular.module('bawApp.listen', ['decipher.tags', 'ui.bootstrap.typeahead']) // set up some dummy objects for use later + $scope.jumpToHide = true; $scope.model = { audioElement: {}, audioEvents: [], @@ -153,6 +154,7 @@ angular.module('bawApp.listen', ['decipher.tags', 'ui.bootstrap.typeahead']) var maxMinutes = Math.floor(parseFloat($scope.model.audioRecording.durationSeconds) / 60); $scope.jumpToMax = maxMinutes; $scope.jumpToMinute = Math.floor( parseFloat($routeParams.start) / 60); + $scope.jumpToHide = false; }, function audioRecordingGetFailure() { console.error("retrieval of audioRecording json failed"); diff --git a/src/app/listen/listen.tpl.html b/src/app/listen/listen.tpl.html index 7b926946..c4696ebb 100644 --- a/src/app/listen/listen.tpl.html +++ b/src/app/listen/listen.tpl.html @@ -11,7 +11,7 @@

Jump to minute: - + {{jumpToMinute}} diff --git a/src/components/directives/input[type=range].js b/src/components/directives/input[type=range].js new file mode 100644 index 00000000..f0b0c1d4 --- /dev/null +++ b/src/components/directives/input[type=range].js @@ -0,0 +1,26 @@ +var bawds = bawds || angular.module('bawApp.directives', ['bawApp.configuration']); + +bawds.directive("ngSlider", function () { + return { + restrict: 'A', + link: function (scope, $element, attrs) { + var element = $element[0]; + + var updateScope = function () { + scope.$apply(function () { + scope[attrs.ngSlider] = element.value; + }); + }; + + $element.bind("change", updateScope); + + scope.$watch(function () { + return scope[attrs.ngSlider]; + }, function (newValue) { + element.value = newValue; + }); + + + } + }; +}); \ No newline at end of file From 6c3e40e398e8eb734cea1d802baf06a1acd3d1da Mon Sep 17 00:00:00 2001 From: Anthony Truskinger Date: Sat, 18 Jan 2014 23:58:26 +1000 Subject: [PATCH 3/8] Version bump --- Gruntfile.js | 4 ++-- bower.json | 2 +- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Gruntfile.js b/Gruntfile.js index d3d5398d..55f84529 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -16,7 +16,7 @@ module.exports = function (grunt) { grunt.loadNpmTasks('grunt-contrib-watch'); grunt.loadNpmTasks('grunt-contrib-uglify'); //grunt.loadNpmTasks('grunt-conventional-changelog'); - grunt.loadNpmTasks('grunt-conventional-changelog'); + grunt.loadNpmTasks('grunt-changelog'); grunt.loadNpmTasks('grunt-bump'); grunt.loadNpmTasks('grunt-sass'); grunt.loadNpmTasks('grunt-karma'); @@ -113,7 +113,7 @@ module.exports = function (grunt) { changelog: { options: { after: "2013-09-05T10:18:39.4492679+10:00", - before: "today", + before: "now", dest: 'CHANGELOG.md', template: 'changelog.tpl' } diff --git a/bower.json b/bower.json index 44a27783..4a2ce596 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "ng-boilerplate", - "version": "0.0.8", + "version": "0.0.9", "devDependencies": { "angular": "1.2.2", "angular-mocks": "~1.2.0", diff --git a/package.json b/package.json index f34378e0..fea9bf50 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "author": "QUT Bioacoustics", "name": "baw-client", - "version": "0.0.8", + "version": "0.0.9", "description": "The AngularJS client for the QUT Bioacoustics server", "licenses": { "type": "Apache", From b83fc0b4751777253deb16a37e00428714ff7758 Mon Sep 17 00:00:00 2001 From: Anthony Truskinger Date: Mon, 20 Jan 2014 17:35:35 +1000 Subject: [PATCH 4/8] debugging changelog --- Gruntfile.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gruntfile.js b/Gruntfile.js index 55f84529..1d7824ca 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -112,8 +112,8 @@ module.exports = function (grunt) { */ changelog: { options: { - after: "2013-09-05T10:18:39.4492679+10:00", - before: "now", + //after: "2013-09-05T10:18:39.4492679+10:00", + //before: "now", dest: 'CHANGELOG.md', template: 'changelog.tpl' } From e1af6650285b3100ff2066ebf6a4cd84350d1939 Mon Sep 17 00:00:00 2001 From: Anthony Truskinger Date: Mon, 16 Dec 2013 16:32:03 +1000 Subject: [PATCH 5/8] [WIP] First interation of downloading metadata. Not ready. Needs a shallow route for sites. Requires changes to baw-server --- src/app/listen/listen.js | 114 ++++++++++++++++++++++++++++----------- 1 file changed, 84 insertions(+), 30 deletions(-) diff --git a/src/app/listen/listen.js b/src/app/listen/listen.js index 30159b0d..ceac61ad 100644 --- a/src/app/listen/listen.js +++ b/src/app/listen/listen.js @@ -5,6 +5,7 @@ angular.module('bawApp.listen', ['decipher.tags', 'ui.bootstrap.typeahead']) '$location', '$routeParams', '$route', + '$q', 'conf.paths', 'conf.constants', '$url', @@ -13,6 +14,8 @@ angular.module('bawApp.listen', ['decipher.tags', 'ui.bootstrap.typeahead']) 'AudioEvent', 'Tag', 'Taggings', + 'Site', + 'Project', /** * The listen controller. * @param $scope @@ -28,10 +31,14 @@ angular.module('bawApp.listen', ['decipher.tags', 'ui.bootstrap.typeahead']) * @param $url * @param AudioRecording * @param Taggings + * @param $q + * @param Site + * @param Project */ function ListenCtrl( - $scope, $resource, $location, $routeParams, $route, paths, constants, $url, - AudioRecording, Media, AudioEvent, Tag, Taggings) { + $scope, $resource, $location, $routeParams, $route, $q, paths, constants, $url, + AudioRecording, Media, AudioEvent, Tag, Taggings, Site, Project) { + var CHUNK_DURATION_SECONDS = constants.listen.chunkDurationSeconds; function getMediaParameters(format) { @@ -77,7 +84,10 @@ angular.module('bawApp.listen', ['decipher.tags', 'ui.bootstrap.typeahead']) audioElement: {}, audioEvents: [], media: null, - selectedAudioEvent: null + selectedAudioEvent: null, + audioRecording: null, + project: null, + site: null }; var formatPaths = function () { @@ -145,19 +155,54 @@ angular.module('bawApp.listen', ['decipher.tags', 'ui.bootstrap.typeahead']) console.error("retrieval of media json failed"); }); - $scope.model.audioRecording = AudioRecording.get({recordingId: recordingId}, {}, - function audioRecordingGetSuccess() { - // no-op - // if an audioRecording 'model' is ever created, this is where we would transform the returned data - // set up jumpto vars - var maxMinutes = Math.floor(parseFloat($scope.model.audioRecording.durationSeconds) / 60); - $scope.jumpToMax = maxMinutes; - $scope.jumpToMinute = Math.floor( parseFloat($routeParams.start) / 60); - $scope.jumpToHide = false; - }, - function audioRecordingGetFailure() { - console.error("retrieval of audioRecording json failed"); + var promise = (function getResources() { + var deferred = $q.defer(); + + AudioRecording.get({recordingId: recordingId}, {}, + function audioRecordingGetSuccess(value) { + // if an audioRecording 'model' is ever created, this is where we would transform the returned data + $scope.model.audioRecording = value; + + // set up jumpto vars + var maxMinutes = Math.floor(parseFloat($scope.model.audioRecording.durationSeconds) / 60); + $scope.jumpToMax = maxMinutes; + $scope.jumpToMinute = Math.floor( parseFloat($routeParams.start) / 60); + $scope.jumpToHide = false; + + deferred.resolve(value); + }, + function audioRecordingGetFailure() { + deferred.reject("retrieval of audioRecording json failed"); + }); + + return deferred.promise; + })() + .then(function success(result) { + var siteDeferred = $q.defer(); + // get site + Site.get({siteId: result.siteId}, {}, function getSiteSuccess(value) { + $scope.model.site = value; + siteDeferred.resolve(value) + }, function getSiteError() { + siteDeferred.reject("retrieval of site json failed"); + }); + + return siteDeferred.promise; + }) + .then(function success() { + var projectDeferred = $q.defer(); + // get site + Project.get({id: result.projectId}, {}, function getProjectSuccess(value) { + $scope.model.project = value; + projectDeferred.resolve(value) + }, function getSiteError() { + projectDeferred.reject("retrieval of site json failed"); + }); + + return projectDeferred.promise; + }).catch(function error(err) { + console.error("An error occurred downloading metadata for this chunk:" + err, err); }); @@ -187,7 +232,7 @@ angular.module('bawApp.listen', ['decipher.tags', 'ui.bootstrap.typeahead']) $scope.tags.push(baw.Tag.make(value)); }); - $scope.model.audioEvents.forEach(function(value){ + $scope.model.audioEvents.forEach(function (value) { Tag.resolveAll(value.tags, $scope.tags); }); }, @@ -257,11 +302,16 @@ angular.module('bawApp.listen', ['decipher.tags', 'ui.bootstrap.typeahead']) var offset = base.add({seconds: $scope.model.media.startOffset}); return offset; }; - + + $scope.previousEnabled = false; $scope.nextEnabled = false; - $scope.createNavigationHref = function (linkType, stepBy) { + // skip if resources not available + if (!$scope.model.audioRecording) { + return "#"; + } + if (!angular.isNumber(stepBy)) { stepBy = CHUNK_DURATION_SECONDS; } @@ -270,13 +320,13 @@ angular.module('bawApp.listen', ['decipher.tags', 'ui.bootstrap.typeahead']) if (linkType === "previous") { var lowerBound = ($routeParams.start - stepBy); - + if ($routeParams.start > 0) { $scope.previousEnabled = true; } else { - $scope.previousEnabled = false; + $scope.previousEnabled = false; } - + if (lowerBound === 0) { baseLink.end = lowerBound + stepBy; } @@ -294,30 +344,31 @@ angular.module('bawApp.listen', ['decipher.tags', 'ui.bootstrap.typeahead']) return uriPrev; } - else if (linkType === "next") { - + else if (linkType === "next") { + var maxEnd = Math.floor($scope.model.audioRecording.durationSeconds); - + var uriNext = $url.formatUri( paths.site.ngRoutes.listen, { recordingId: recordingId, start: ($routeParams.start + stepBy), - end: (($routeParams.end + stepBy < maxEnd) ? $routeParams.end + stepBy : maxEnd) + end: (($routeParams.end + stepBy < maxEnd) ? $routeParams.end + stepBy : maxEnd) }); - + if ($routeParams.end < $scope.model.audioRecording.durationSeconds - constants.listen.minAudioDurationSeconds) { $scope.nextEnabled = true; } else { - $scope.nextEnabled = false; + $scope.nextEnabled = false; } - + return uriNext; } throw "Invalid link type specified in createNavigationHref"; }; + $scope.jumpTo = function() { var maxEnd = Math.floor($scope.model.audioRecording.durationSeconds), seconds = $scope.jumpToMinute * 60; @@ -339,12 +390,16 @@ angular.module('bawApp.listen', ['decipher.tags', 'ui.bootstrap.typeahead']) $location.url(url); }; + $scope.clearSelected = function () { $scope.model.audioEvents.forEach(function (value, key) { value.selected = false; }); + + $scope.model.selectedAudioEvent = null; }; + $scope.singleEditDisabled = function () { return ($scope.model.selectedAudioEvent === null || $scope.model.selectedAudioEvent.id === undefined); }; @@ -368,7 +423,6 @@ angular.module('bawApp.listen', ['decipher.tags', 'ui.bootstrap.typeahead']) tagTemplateUrl: "/templates/tags.html" }; - $scope.$on('decipher.tags.initialized', function (event) { event.stopPropagation(); console.debug('decipher.tags.initialized', arguments); @@ -438,7 +492,7 @@ angular.module('bawApp.listen', ['decipher.tags', 'ui.bootstrap.typeahead']) // assumes tags array is kept in sync //delete $scope.model.selectedAudioEvent.tags[index]; - console.debug("Tag removal success", removedTag.tag.text ); + console.debug("Tag removal success", removedTag.tag.text); }, function error(response) { console.error("Tagging creation failed", response); From 23fa5531b1e924d4663328ea1f8892ef3301617b Mon Sep 17 00:00:00 2001 From: Anthony Truskinger Date: Mon, 20 Jan 2014 20:52:18 +1000 Subject: [PATCH 6/8] fixed path for shallow site route. still waiting on project id link --- src/baw.configuration.tpl.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/baw.configuration.tpl.js b/src/baw.configuration.tpl.js index 648e2ddf..dbe92083 100644 --- a/src/baw.configuration.tpl.js +++ b/src/baw.configuration.tpl.js @@ -59,7 +59,7 @@ angular.module('bawApp.configuration', ['url']) root: "<%= current.apiRoot %>", routes: { project: "/projects/{projectId}", - site: "/projects/{projectId}/sites/{siteId}", + site: "/sites/{siteId}", audioRecording: { listShort: "/audio_recordings/{recordingId}", show: "/audio_recordings/{recordingId}", From 8fae07c2af8882ddd8797260cde638adaa3447da Mon Sep 17 00:00:00 2001 From: Anthony Truskinger Date: Wed, 22 Jan 2014 02:38:07 +1000 Subject: [PATCH 7/8] Finished work adding in metadata retieval and display. - Changed angular's default Accept header to 'application/json' only to counter weird rails bug on server - Added styling for the new metadata - Added support for downloading multiple projects and support for (not) accessing projects that the user does not have permission to access - Added support for short site routes - Added an angular filter for formatting strings --- src/app/app.js | 5 ++ src/app/listen/_listen.scss | 14 +++++ src/app/listen/listen.js | 97 ++++++++++++++++++++++--------- src/app/listen/listen.tpl.html | 23 ++++++-- src/baw.configuration.tpl.js | 2 +- src/components/filters/filters.js | 12 ++++ 6 files changed, 120 insertions(+), 33 deletions(-) diff --git a/src/app/app.js b/src/app/app.js index 11f0ae08..258e2112 100644 --- a/src/app/app.js +++ b/src/app/app.js @@ -155,6 +155,11 @@ var app = angular.module('baw', // http default configuration $httpProvider.defaults.withCredentials = true; + + // the default accept type is ` "application/json, text/plain, */*" ` + // for angular. This causes rails to do stupid shit for things like 403s... with old header it gives a 302 + // and redirects to HTML page. WTF. + $httpProvider.defaults.headers['common']['Accept'] = 'application/json'; }]) diff --git a/src/app/listen/_listen.scss b/src/app/listen/_listen.scss index ff9b49d7..43ee0a1f 100644 --- a/src/app/listen/_listen.scss +++ b/src/app/listen/_listen.scss @@ -1,3 +1,17 @@ + +.noPermissions { + @extend .alert; + @extend .alert-warning; +} + +.project-names>span:not(:last-child) { + word-spacing : -0.3em; + + & * { + word-spacing: normal; + } +} + .position { & span { margin-left: 10px; diff --git a/src/app/listen/listen.js b/src/app/listen/listen.js index 975ca3b4..d6ba2aa0 100644 --- a/src/app/listen/listen.js +++ b/src/app/listen/listen.js @@ -34,8 +34,7 @@ angular.module('bawApp.listen', ['decipher.tags', 'ui.bootstrap.typeahead']) * @param Site * @param Project */ - function ListenCtrl($scope, $resource, $routeParams, $route, $q, paths, constants, $url, - AudioRecording, Media, AudioEvent, Tag, Taggings, Site, Project) { + function ListenCtrl($scope, $resource, $routeParams, $route, $q, paths, constants, $url, AudioRecording, Media, AudioEvent, Tag, Taggings, Site, Project) { var CHUNK_DURATION_SECONDS = constants.listen.chunkDurationSeconds; function getMediaParameters(format) { @@ -152,48 +151,93 @@ angular.module('bawApp.listen', ['decipher.tags', 'ui.bootstrap.typeahead']) }); - var promise = (function getResources() { + var getAudioRecording = function getAudioRecording(recordingId) { var deferred = $q.defer(); AudioRecording.get({recordingId: recordingId}, {}, function audioRecordingGetSuccess(value) { // if an audioRecording 'model' is ever created, this is where we would transform the returned data $scope.model.audioRecording = value; - deferred.resolve(value); + var result = {audioRecording: value}; + deferred.resolve(result); }, function audioRecordingGetFailure() { deferred.reject("retrieval of audioRecording json failed"); }); return deferred.promise; - })() - .then(function success(result) { - var siteDeferred = $q.defer(); - // get site - Site.get({siteId: result.siteId}, {}, function getSiteSuccess(value) { - $scope.model.site = value; - siteDeferred.resolve(value) - }, function getSiteError() { - siteDeferred.reject("retrieval of site json failed"); - }); + }; + + var getSite = function getSite(result) { + var siteDeferred = $q.defer(); + // get site + Site.get({siteId: result.audioRecording.siteId}, {}, function getSiteSuccess(value) { + + value.link = paths.api.routes.siteAbsolute.format({"siteId": value.id}); + + $scope.model.site = value; + result.site = value; + siteDeferred.resolve(result); + }, function getSiteError() { + siteDeferred.reject("retrieval of site json failed"); + }); + + return siteDeferred.promise; + }; + + var getProjects = function getProjects(result) { + var projectPromises = []; - return siteDeferred.promise; - }) - .then(function success() { + $scope.model.projects = $scope.model.projects || []; + result.projects = result.projects || []; + + result.site.projectIds.forEach(function (id, index) { var projectDeferred = $q.defer(); - // get site - Project.get({id: result.projectId}, {}, function getProjectSuccess(value) { - $scope.model.project = value; - projectDeferred.resolve(value) - }, function getSiteError() { - projectDeferred.reject("retrieval of site json failed"); + // get project + Project.get({projectId: id}, {}, function getProjectSuccess(value) { + + value.link = paths.api.routes.projectAbsolute.format({"projectId": value.id}); + + $scope.model.projects[index] = value; + result.projects[index] = value; + projectDeferred.resolve(result); + }, function getProjectError(error) { + if (error.status === 403) { + console.warn("The project %s does not give permissions to current user to access it's content. There are %s projects.", id, result.site.projectIds.length); + // populate field anyway, not really sure what to do here, temp value added + var denied = { + id: id, + permissions: "access denied" + }; + + denied.link = paths.api.routes.projectAbsolute.format({"projectId": denied.id}); + + $scope.model.projects[index] = denied; + result.projects[index] = denied; + + // we don't mind that this "error" has occurred - there should be at least one project + // that did resolve. Resolve promise anyway + projectDeferred.resolve(result); + } + else { + projectDeferred.reject("retrieval of project json failed"); + } }); - return projectDeferred.promise; - }).catch(function error(err) { - console.error("An error occurred downloading metadata for this chunk:" + err, err); + projectPromises[index] = projectDeferred.promise; }); + return $q.all(projectPromises); + }; + getAudioRecording(recordingId).then(getSite).then(getProjects).then(function success(result) { + console.info("Metadata Promise chain success", result); + }, function error(err) { + console.error("An error occurred downloading metadata for this chunk:" + err, err); + }, function notify() { + // TODO: remove dodgy scope closure from promise functions, and update values here incrementally! + console.debug("All promises notify", arguments); + }); + AudioEvent.query( { @@ -358,6 +402,7 @@ angular.module('bawApp.listen', ['decipher.tags', 'ui.bootstrap.typeahead']) }; + $scope.clearSelected = function () { $scope.model.audioEvents.forEach(function (value, key) { value.selected = false; diff --git a/src/app/listen/listen.tpl.html b/src/app/listen/listen.tpl.html index b1275762..6fc50d88 100644 --- a/src/app/listen/listen.tpl.html +++ b/src/app/listen/listen.tpl.html @@ -1,12 +1,23 @@ -
+
Something has gone wrong - can't load this page.
-

Site: {{model.audioRecording.siteId}}, {{absoluteDateChunkStart() | moment:"format":"dddd, MMMM Do YYYY, HH:mm:ss ZZ"}} +

+ + {{ !$first && ", " || ""}} + {{p.name}} + {{p.id}} + + +  /  + {{model.site.name}} +  /  + {{absoluteDateChunkStart() | moment:"format":"dddd, MMMM Do YYYY, HH:mm:ss ZZ"}}

- +
@@ -63,7 +74,7 @@

Site: {{model.audioRecording.siteId}},
Tags - + @@ -75,7 +86,7 @@

Site: {{model.audioRecording.siteId}},   Should this be a reference annotation? - +

@@ -125,7 +136,7 @@

Site: {{model.audioRecording.siteId}}, +

Annotations

diff --git a/src/baw.configuration.tpl.js b/src/baw.configuration.tpl.js index 648e2ddf..dbe92083 100644 --- a/src/baw.configuration.tpl.js +++ b/src/baw.configuration.tpl.js @@ -59,7 +59,7 @@ angular.module('bawApp.configuration', ['url']) root: "<%= current.apiRoot %>", routes: { project: "/projects/{projectId}", - site: "/projects/{projectId}/sites/{siteId}", + site: "/sites/{siteId}", audioRecording: { listShort: "/audio_recordings/{recordingId}", show: "/audio_recordings/{recordingId}", diff --git a/src/components/filters/filters.js b/src/components/filters/filters.js index ce2e6cdb..8c058fc1 100644 --- a/src/components/filters/filters.js +++ b/src/components/filters/filters.js @@ -93,3 +93,15 @@ }; }]); + bawfs.filter('format', function() { + return function stringFormatFilter(string, args) { + var restOfArguments = Array.prototype.slice.call(arguments, 2, arguments.length); + + if (angular.isString(string)) { + return String.format.apply(string, (arguments)); + } + + throw "A string is required for the first argument"; + }; + }); + From c9be26c81de980efac86c2248488e2afcf0820b4 Mon Sep 17 00:00:00 2001 From: Anthony Truskinger Date: Fri, 24 Jan 2014 18:10:38 +1000 Subject: [PATCH 8/8] Code review complete --- src/app/listen/listen.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/listen/listen.js b/src/app/listen/listen.js index 74733e08..367c2c0b 100644 --- a/src/app/listen/listen.js +++ b/src/app/listen/listen.js @@ -86,7 +86,7 @@ angular.module('bawApp.listen', ['decipher.tags', 'ui.bootstrap.typeahead']) media: null, selectedAudioEvent: null, audioRecording: null, - project: null, + projects: [], site: null };