From cf44b4c2110eb44eee8fea699cc00d3281596242 Mon Sep 17 00:00:00 2001 From: Mark Date: Mon, 12 May 2014 17:49:59 +1000 Subject: [PATCH 01/10] added template for annnotation comments --- .../annotationLibrary/annotationItem.tpl.html | 76 ++++++++++++++++++- .../annotationLibrary/annotationLibrary.js | 17 ++++- 2 files changed, 86 insertions(+), 7 deletions(-) diff --git a/src/app/annotationLibrary/annotationItem.tpl.html b/src/app/annotationLibrary/annotationItem.tpl.html index e296afdd..419b5ecb 100644 --- a/src/app/annotationLibrary/annotationItem.tpl.html +++ b/src/app/annotationLibrary/annotationItem.tpl.html @@ -1,4 +1,4 @@ -
+

Annotation {{model.audioEventId}}

- Coming soon... +
    +
  • + + + + +
    +

    + link | report +

    +

    + UserName + time ago in words +

    +

    + Comment body +

    +
    +
  • +
  • + + + + +
    +

    + link | report +

    +

    + UserName + time ago in words +

    +

    + Comment body +

    +
    +
  • +
+
    +
  • + + + + +
    +

    + {{profile.userName}} + now +

    + +
    +
    + +
    + +
    + +
    +
  • +
+ +
diff --git a/src/app/annotationLibrary/annotationLibrary.js b/src/app/annotationLibrary/annotationLibrary.js index b67bf0a8..900f5fdb 100644 --- a/src/app/annotationLibrary/annotationLibrary.js +++ b/src/app/annotationLibrary/annotationLibrary.js @@ -29,7 +29,8 @@ baw.annotationLibrary.addCalculatedProperties = function addCalculatedProperties '&end=' + audioEvent.calcOffsetEnd, listenWithoutPadding: '/listen/' + audioEvent.audioRecordingId + '?start=' + audioEvent.startTimeSeconds + - '&end=' + audioEvent.endTimeSeconds + '&end=' + audioEvent.endTimeSeconds, + audioRecording: '/library?' + $url.toKeyValue({audioRecordingId: audioEvent.audioRecordingId}, true), }; return audioEvent; @@ -269,8 +270,14 @@ angular.module('bawApp.annotationLibrary', ['bawApp.configuration']) .controller('AnnotationItemCtrl', ['$scope', '$location', '$resource', '$routeParams', '$url', 'conf.paths', 'conf.constants', 'bawApp.unitConverter', - 'AudioEvent', 'Tag', 'Media', - function ($scope, $location, $resource, $routeParams, $url, paths, constants, unitConverter, AudioEvent, Tag, Media) { + 'AudioEvent', 'Tag', 'Media', 'UserProfile', + function ($scope, $location, $resource, $routeParams, $url, + paths, constants, unitConverter, AudioEvent, Tag, Media, UserProfile) { + + $scope.$on(UserProfile.eventKeys.loaded, profileLoaded); + if (UserProfile.profile && UserProfile.profile.preferences) { + profileLoaded(null, UserProfile); + } var parameters = { audioEventId: $routeParams.audioEventId, @@ -311,4 +318,8 @@ angular.module('bawApp.annotationLibrary', ['bawApp.configuration']) return '/projects/' + projectId; }; + function profileLoaded(event, userProfile){ + $scope.profile = userProfile.profile; + } + }]); \ No newline at end of file From 18138235ca232580673652d94707fb7a58b05a25 Mon Sep 17 00:00:00 2001 From: Mark Date: Tue, 13 May 2014 16:28:04 +1000 Subject: [PATCH 02/10] Added comments to annotation item page Also added stubs for creative directive for comments. --- .../annotationLibrary/annotationItem.tpl.html | 81 +++++++------ .../annotationLibrary/annotationLibrary.js | 114 ++++++++++++++++-- .../annotationLibrary/comments/_comments.scss | 0 .../annotationLibrary/comments/comments.js | 11 ++ .../comments/comments.tpl.html | 0 src/baw.configuration.tpl.js | 4 + src/components/services/services.js | 5 + 7 files changed, 173 insertions(+), 42 deletions(-) create mode 100644 src/app/annotationLibrary/comments/_comments.scss create mode 100644 src/app/annotationLibrary/comments/comments.js create mode 100644 src/app/annotationLibrary/comments/comments.tpl.html diff --git a/src/app/annotationLibrary/annotationItem.tpl.html b/src/app/annotationLibrary/annotationItem.tpl.html index 419b5ecb..207c5e6f 100644 --- a/src/app/annotationLibrary/annotationItem.tpl.html +++ b/src/app/annotationLibrary/annotationItem.tpl.html @@ -109,63 +109,76 @@

-

- link | report -

- UserName - time ago in words + {{profile.userName}} + now

-

- Comment body -

-
- -
  • - - - -
    -

    - link | report -

    -

    - UserName - time ago in words -

    -

    - Comment body -

    +
    +
    + + {{error}} +
    + +
    +
    • -
    • +
    • +

      + link | + edit | + delete +

      + +

      + link | + report +

      - {{profile.userName}} - now + {{comment.updater.userName}} + + {{$parent.formatTimeAgo(comment.updatedAt, 'YYYY-MM-DDTHH:mm:ssZZ')}} +

      +

      + {{comment.comment}} +

      -
      -
      + +
      + style="width:90%" id="{{'editAnnotationComment'+comment.id}}" + ng-model="$parent.editComment.text"> + {{error}}
      - + + -
    - diff --git a/src/app/annotationLibrary/annotationLibrary.js b/src/app/annotationLibrary/annotationLibrary.js index 900f5fdb..37d89dc1 100644 --- a/src/app/annotationLibrary/annotationLibrary.js +++ b/src/app/annotationLibrary/annotationLibrary.js @@ -21,7 +21,7 @@ baw.annotationLibrary.addCalculatedProperties = function addCalculatedProperties annotationDuration: Math.round10(audioEvent.annotationDuration, -3), freqMin: Math.round(audioEvent.lowFrequencyHertz), freqMax: Math.round(audioEvent.highFrequencyHertz) - },true), + }, true), singleItem: '/library/' + audioEvent.audioRecordingId + '/audio_events/' + audioEvent.audioEventId, listen: '/listen/' + audioEvent.audioRecordingId + @@ -30,7 +30,7 @@ baw.annotationLibrary.addCalculatedProperties = function addCalculatedProperties listenWithoutPadding: '/listen/' + audioEvent.audioRecordingId + '?start=' + audioEvent.startTimeSeconds + '&end=' + audioEvent.endTimeSeconds, - audioRecording: '/library?' + $url.toKeyValue({audioRecordingId: audioEvent.audioRecordingId}, true), + audioRecording: '/library?' + $url.toKeyValue({audioRecordingId: audioEvent.audioRecordingId}, true) }; return audioEvent; @@ -171,7 +171,7 @@ angular.module('bawApp.annotationLibrary', ['bawApp.configuration']) $scope.filterSettings[currentvalue] = isVoid ? null : Number(stringValue); } ); - + // disable other options for reference filter $scope.filterSettings.reference = 'true'; } @@ -270,9 +270,9 @@ angular.module('bawApp.annotationLibrary', ['bawApp.configuration']) .controller('AnnotationItemCtrl', ['$scope', '$location', '$resource', '$routeParams', '$url', 'conf.paths', 'conf.constants', 'bawApp.unitConverter', - 'AudioEvent', 'Tag', 'Media', 'UserProfile', - function ($scope, $location, $resource, $routeParams, $url, - paths, constants, unitConverter, AudioEvent, Tag, Media, UserProfile) { + 'AudioEvent', 'Tag', + 'Media', 'UserProfile', 'AudioEventComment', + function ($scope, $location, $resource, $routeParams, $url, paths, constants, unitConverter, AudioEvent, Tag, Media, UserProfile, AudioEventComment) { $scope.$on(UserProfile.eventKeys.loaded, profileLoaded); if (UserProfile.profile && UserProfile.profile.preferences) { @@ -284,6 +284,19 @@ angular.module('bawApp.annotationLibrary', ['bawApp.configuration']) recordingId: $routeParams.recordingId }; + // new comment text and errors + $scope.newComment = { + // bind to new comment textarea + text: '', + errors: [] + }; + + $scope.editComment = { + id: null, + text: null, + errors: [] + }; + AudioEvent.get(parameters, function annotationShowSuccess(audioEventValue, responseHeaders) { @@ -294,6 +307,9 @@ angular.module('bawApp.annotationLibrary', ['bawApp.configuration']) $scope.annotation = annotation; + // comments + reloadComments(); + // paging if ($scope.annotation.paging.nextEvent.hasOwnProperty('audioEventId')) { $scope.annotation.paging.nextEvent.link = '/library/' + @@ -314,12 +330,94 @@ angular.module('bawApp.annotationLibrary', ['bawApp.configuration']) return '/library/?' + $url.toKeyValue(paramObj, true); }; - $scope.createProjectUrl = function createProjectUrl(projectId){ + $scope.createProjectUrl = function createProjectUrl(projectId) { return '/projects/' + projectId; }; - function profileLoaded(event, userProfile){ + $scope.createCommentLinkUrl = function createCommentLinkUrl(audioEventCommentId) { + return '/library/' + $routeParams.recordingId + '/audio_events/' + + $routeParams.audioEventId + '#' + audioEventCommentId + }; + + $scope.formatTimeAgo = function formatTimeAgo(time, formatString){ + return moment(time, formatString).fromNow(); + }; + + $scope.createComment = function createComment() { + AudioEventComment.save( + {audioEventId: $routeParams.audioEventId}, // parameters + {comment: $scope.newComment.text}, // post data + function createCommentSuccess(value, responseHeaders) { + console.log('create success', arguments); + $scope.newComment.errors = []; + $scope.newComment.text = ''; + reloadComments(); + }, + function createCommentError(httpResponse) { + console.log('create failure', arguments); + $scope.newComment.errors = httpResponse.data.comment; + }); + }; + + $scope.deleteComment = function deleteComment(commentText, audioEventCommentId) { + var isConfirmed = confirm('Are you sure you want to delete this comment? "' + commentText + '"'); + if (isConfirmed === true) { + AudioEventComment.delete( + { + audioEventId: $routeParams.audioEventId, + audioEventCommentId: audioEventCommentId + }, // parameters + null, // post data + function deleteCommentSuccess(value, responseHeaders) { + console.log('delete success', arguments); + $scope.newComment.errors = []; + $scope.newComment.text = ''; + reloadComments(); + }, + function deleteCommentError(httpResponse) { + console.log('delete failure', arguments); + $scope.newComment.errors = httpResponse.data.comment; + }); + } + }; + + $scope.updateComment = function updateComment(audioEventCommentId){ + AudioEventComment.update( + { + audioEventId: $routeParams.audioEventId, + audioEventCommentId: audioEventCommentId + }, // parameters + {comment: $scope.editComment.text}, // post data + function updateCommentSuccess(value, responseHeaders) { + console.log('update success', arguments); + $scope.editComment.errors = []; + $scope.editComment.text = null; + $scope.editComment.id = null; + reloadComments(); + }, + function updateCommentError(httpResponse) { + console.log('update failure', arguments); + $scope.editComment.errors = httpResponse.data.comment; + }); + }; + + $scope.editComment = function editComment(commentText, audioEventCommentId){ + $scope.editComment.id = audioEventCommentId; + $scope.editComment.text = commentText; + }; + + function profileLoaded(event, userProfile) { $scope.profile = userProfile.profile; } + function reloadComments() { + // get array of comment for the current audio event + AudioEventComment.query( + {audioEventId: $routeParams.audioEventId}, + function audioEventCommentSuccess(value, responseHeaders) { + $scope.comments = value; + }); + + } + }]); \ No newline at end of file diff --git a/src/app/annotationLibrary/comments/_comments.scss b/src/app/annotationLibrary/comments/_comments.scss new file mode 100644 index 00000000..e69de29b diff --git a/src/app/annotationLibrary/comments/comments.js b/src/app/annotationLibrary/comments/comments.js new file mode 100644 index 00000000..015e0ff9 --- /dev/null +++ b/src/app/annotationLibrary/comments/comments.js @@ -0,0 +1,11 @@ +var bawCs = angular + .module('bawApp.annotationLibrary.comments', ['bawApp.configuration']) + .directive('comments', ['conf.paths', function (paths) { + var commentDefinition = { + restrict: 'E', + templateUrl: paths.site.files.annotationComments, + link: function postLink(scope, $element, attributes) { + } + }; + return commentDefinition; + }]); \ No newline at end of file diff --git a/src/app/annotationLibrary/comments/comments.tpl.html b/src/app/annotationLibrary/comments/comments.tpl.html new file mode 100644 index 00000000..e69de29b diff --git a/src/baw.configuration.tpl.js b/src/baw.configuration.tpl.js index 8c71d776..f9dd82b3 100644 --- a/src/baw.configuration.tpl.js +++ b/src/baw.configuration.tpl.js @@ -92,6 +92,9 @@ angular.module('bawApp.configuration', ['url']) user: { profile: "/my_account", settings: "/my_account/prefs" + }, + audioEventComment:{ + show: '/audio_events/{audioEventId}/audio_event_comments/{audioEventCommentId}' } }, links: { @@ -109,6 +112,7 @@ angular.module('bawApp.configuration', ['url']) listen: 'listen/listen.tpl.html', annotationViewer: 'annotationViewer/annotationViewer.tpl.html', gridLines: 'annotationViewer/gridLines/gridLines.tpl.html', + annotationComments: 'annotationLibrary/comments/comments.tpl.html', library: { list: 'annotationLibrary/annotationLibrary.tpl.html', item: 'annotationLibrary/annotationItem.tpl.html' diff --git a/src/components/services/services.js b/src/components/services/services.js index c8c39825..36ab008d 100644 --- a/src/components/services/services.js +++ b/src/components/services/services.js @@ -37,6 +37,11 @@ // NOTE: deleted user resource, API for users no longer exposed + bawss.factory('AudioEventComment', [ '$resource', 'conf.paths', function ($resource, paths) { + return resourcePut($resource, uriConvert(paths.api.routes.audioEventComment.showAbsolute), + {audioEventId: "@audioEventId", audioEventCommentId: '@audioEventCommentId'}); + }]); + bawss.factory('AudioRecording', [ '$resource', 'conf.paths', function ($resource, paths) { return resourcePut($resource, uriConvert(paths.api.routes.audioRecording.showAbsolute), {projectId: "@projectId", siteId: "@siteId", recordingId: '@recordingId'}); From 713db63a08d72d861f10c8feb86b105d0f7b63f9 Mon Sep 17 00:00:00 2001 From: Mark Date: Tue, 13 May 2014 16:32:52 +1000 Subject: [PATCH 03/10] indicate comment time is last updated --- src/app/annotationLibrary/annotationItem.tpl.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/annotationLibrary/annotationItem.tpl.html b/src/app/annotationLibrary/annotationItem.tpl.html index 207c5e6f..0e920fe5 100644 --- a/src/app/annotationLibrary/annotationItem.tpl.html +++ b/src/app/annotationLibrary/annotationItem.tpl.html @@ -151,7 +151,7 @@

    {{comment.updater.userName}} - {{$parent.formatTimeAgo(comment.updatedAt, 'YYYY-MM-DDTHH:mm:ssZZ')}} + last change {{$parent.formatTimeAgo(comment.updatedAt, 'YYYY-MM-DDTHH:mm:ssZZ')}}

    From db959993d22e1447b68a2dbab09da28a1f535c88 Mon Sep 17 00:00:00 2001 From: Mark Date: Thu, 15 May 2014 14:08:19 +1000 Subject: [PATCH 04/10] comments header include number of comments --- src/app/annotationLibrary/annotationItem.tpl.html | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/app/annotationLibrary/annotationItem.tpl.html b/src/app/annotationLibrary/annotationItem.tpl.html index 0e920fe5..35990e5e 100644 --- a/src/app/annotationLibrary/annotationItem.tpl.html +++ b/src/app/annotationLibrary/annotationItem.tpl.html @@ -98,7 +98,9 @@

    Details

    -

     Comments +

    + +  {{comments.length == 0 ? 'No Comments Yet' : (comments.length == 1 ? '1 Comment' : comments.length + ' Comments') }}

    @@ -117,7 +119,7 @@

    Date: Mon, 12 May 2014 17:49:59 +1000 Subject: [PATCH 05/10] added template for annnotation comments --- .../annotationLibrary/annotationItem.tpl.html | 68 ++++++++++++++++++- .../annotationLibrary/annotationLibrary.js | 14 +++- 2 files changed, 78 insertions(+), 4 deletions(-) diff --git a/src/app/annotationLibrary/annotationItem.tpl.html b/src/app/annotationLibrary/annotationItem.tpl.html index e8ea14da..e8dc13c3 100644 --- a/src/app/annotationLibrary/annotationItem.tpl.html +++ b/src/app/annotationLibrary/annotationItem.tpl.html @@ -1,4 +1,4 @@ -
    +

    Annotation {{model.audioEventId}}

    @@ -78,6 +78,7 @@

    Details

    Site: {{annotation.siteName}} +   {{annotation.ownerName }} @@ -97,7 +98,70 @@

    - Coming soon... +
      +
    • + + + + +
      +

      + link | report +

      +

      + UserName + time ago in words +

      +

      + Comment body +

      +
      +
    • +
    • + + + + +
      +

      + link | report +

      +

      + UserName + time ago in words +

      +

      + Comment body +

      +
      +
    • +
    +
      +
    • + + + + +
      +

      + {{profile.userName}} + now +

      + + +
      + +
      + + + +
      +
    • +
    + +
    diff --git a/src/app/annotationLibrary/annotationLibrary.js b/src/app/annotationLibrary/annotationLibrary.js index a606a6c9..ce4451c2 100644 --- a/src/app/annotationLibrary/annotationLibrary.js +++ b/src/app/annotationLibrary/annotationLibrary.js @@ -288,8 +288,14 @@ angular.module('bawApp.annotationLibrary', ['bawApp.configuration']) .controller('AnnotationItemCtrl', ['$scope', '$location', '$resource', '$routeParams', '$url', 'conf.paths', 'conf.constants', 'bawApp.unitConverter', - 'AudioEvent', 'Tag', 'Media', - function ($scope, $location, $resource, $routeParams, $url, paths, constants, unitConverter, AudioEvent, Tag, Media) { + 'AudioEvent', 'Tag', 'Media', 'UserProfile', + function ($scope, $location, $resource, $routeParams, $url, + paths, constants, unitConverter, AudioEvent, Tag, Media, UserProfile) { + + $scope.$on(UserProfile.eventKeys.loaded, profileLoaded); + if (UserProfile.profile && UserProfile.profile.preferences) { + profileLoaded(null, UserProfile); + } var parameters = { audioEventId: $routeParams.audioEventId, @@ -340,4 +346,8 @@ angular.module('bawApp.annotationLibrary', ['bawApp.configuration']) return $url.formatUri(paths.api.links.projectAbsolute, {projectId: projectId}); }; + function profileLoaded(event, userProfile){ + $scope.profile = userProfile.profile; + } + }]); \ No newline at end of file From a38dd85ec7372e664dab91d26376078fc3680ead Mon Sep 17 00:00:00 2001 From: Mark Date: Tue, 13 May 2014 16:28:04 +1000 Subject: [PATCH 06/10] Added comments to annotation item page Also added stubs for creative directive for comments. --- .../annotationLibrary/annotationItem.tpl.html | 81 +++++++------ .../annotationLibrary/annotationLibrary.js | 108 +++++++++++++++++- .../annotationLibrary/comments/_comments.scss | 0 .../annotationLibrary/comments/comments.js | 11 ++ .../comments/comments.tpl.html | 0 src/baw.configuration.tpl.js | 4 + src/components/services/services.js | 5 + 7 files changed, 170 insertions(+), 39 deletions(-) create mode 100644 src/app/annotationLibrary/comments/_comments.scss create mode 100644 src/app/annotationLibrary/comments/comments.js create mode 100644 src/app/annotationLibrary/comments/comments.tpl.html diff --git a/src/app/annotationLibrary/annotationItem.tpl.html b/src/app/annotationLibrary/annotationItem.tpl.html index e8dc13c3..a0532997 100644 --- a/src/app/annotationLibrary/annotationItem.tpl.html +++ b/src/app/annotationLibrary/annotationItem.tpl.html @@ -105,63 +105,76 @@

    -

    - link | report -

    - UserName - time ago in words + {{profile.userName}} + now

    -

    - Comment body -

    -
    - -
  • - - - -
    -

    - link | report -

    -

    - UserName - time ago in words -

    -

    - Comment body -

    +
    +
    + + {{error}} +
    + +
    +
    • -
    • +
    • +

      + link | + edit | + delete +

      + +

      + link | + report +

      - {{profile.userName}} - now + {{comment.updater.userName}} + + {{$parent.formatTimeAgo(comment.updatedAt, 'YYYY-MM-DDTHH:mm:ssZZ')}} +

      +

      + {{comment.comment}} +

      -
      -
      + +
      + style="width:90%" id="{{'editAnnotationComment'+comment.id}}" + ng-model="$parent.editComment.text"> + {{error}}
      - + + -
    -

    diff --git a/src/app/annotationLibrary/annotationLibrary.js b/src/app/annotationLibrary/annotationLibrary.js index ce4451c2..7a16d0fe 100644 --- a/src/app/annotationLibrary/annotationLibrary.js +++ b/src/app/annotationLibrary/annotationLibrary.js @@ -189,7 +189,7 @@ angular.module('bawApp.annotationLibrary', ['bawApp.configuration']) $scope.filterSettings[currentvalue] = isVoid ? null : Number(stringValue); } ); - + // disable other options for reference filter $scope.filterSettings.reference = 'true'; } @@ -288,9 +288,9 @@ angular.module('bawApp.annotationLibrary', ['bawApp.configuration']) .controller('AnnotationItemCtrl', ['$scope', '$location', '$resource', '$routeParams', '$url', 'conf.paths', 'conf.constants', 'bawApp.unitConverter', - 'AudioEvent', 'Tag', 'Media', 'UserProfile', - function ($scope, $location, $resource, $routeParams, $url, - paths, constants, unitConverter, AudioEvent, Tag, Media, UserProfile) { + 'AudioEvent', 'Tag', + 'Media', 'UserProfile', 'AudioEventComment', + function ($scope, $location, $resource, $routeParams, $url, paths, constants, unitConverter, AudioEvent, Tag, Media, UserProfile, AudioEventComment) { $scope.$on(UserProfile.eventKeys.loaded, profileLoaded); if (UserProfile.profile && UserProfile.profile.preferences) { @@ -302,6 +302,19 @@ angular.module('bawApp.annotationLibrary', ['bawApp.configuration']) recordingId: $routeParams.recordingId }; + // new comment text and errors + $scope.newComment = { + // bind to new comment textarea + text: '', + errors: [] + }; + + $scope.editComment = { + id: null, + text: null, + errors: [] + }; + AudioEvent.get(parameters, function annotationShowSuccess(audioEventValue, responseHeaders) { @@ -312,6 +325,9 @@ angular.module('bawApp.annotationLibrary', ['bawApp.configuration']) $scope.annotation = annotation; + // comments + reloadComments(); + // paging if ($scope.annotation.paging.nextEvent.hasOwnProperty('audioEventId')) { $scope.annotation.paging.nextEvent.link = @@ -346,8 +362,90 @@ angular.module('bawApp.annotationLibrary', ['bawApp.configuration']) return $url.formatUri(paths.api.links.projectAbsolute, {projectId: projectId}); }; - function profileLoaded(event, userProfile){ + $scope.createCommentLinkUrl = function createCommentLinkUrl(audioEventCommentId) { + return '/library/' + $routeParams.recordingId + '/audio_events/' + + $routeParams.audioEventId + '#' + audioEventCommentId + }; + + $scope.formatTimeAgo = function formatTimeAgo(time, formatString){ + return moment(time, formatString).fromNow(); + }; + + $scope.createComment = function createComment() { + AudioEventComment.save( + {audioEventId: $routeParams.audioEventId}, // parameters + {comment: $scope.newComment.text}, // post data + function createCommentSuccess(value, responseHeaders) { + console.log('create success', arguments); + $scope.newComment.errors = []; + $scope.newComment.text = ''; + reloadComments(); + }, + function createCommentError(httpResponse) { + console.log('create failure', arguments); + $scope.newComment.errors = httpResponse.data.comment; + }); + }; + + $scope.deleteComment = function deleteComment(commentText, audioEventCommentId) { + var isConfirmed = confirm('Are you sure you want to delete this comment? "' + commentText + '"'); + if (isConfirmed === true) { + AudioEventComment.delete( + { + audioEventId: $routeParams.audioEventId, + audioEventCommentId: audioEventCommentId + }, // parameters + null, // post data + function deleteCommentSuccess(value, responseHeaders) { + console.log('delete success', arguments); + $scope.newComment.errors = []; + $scope.newComment.text = ''; + reloadComments(); + }, + function deleteCommentError(httpResponse) { + console.log('delete failure', arguments); + $scope.newComment.errors = httpResponse.data.comment; + }); + } + }; + + $scope.updateComment = function updateComment(audioEventCommentId){ + AudioEventComment.update( + { + audioEventId: $routeParams.audioEventId, + audioEventCommentId: audioEventCommentId + }, // parameters + {comment: $scope.editComment.text}, // post data + function updateCommentSuccess(value, responseHeaders) { + console.log('update success', arguments); + $scope.editComment.errors = []; + $scope.editComment.text = null; + $scope.editComment.id = null; + reloadComments(); + }, + function updateCommentError(httpResponse) { + console.log('update failure', arguments); + $scope.editComment.errors = httpResponse.data.comment; + }); + }; + + $scope.editComment = function editComment(commentText, audioEventCommentId){ + $scope.editComment.id = audioEventCommentId; + $scope.editComment.text = commentText; + }; + + function profileLoaded(event, userProfile) { $scope.profile = userProfile.profile; } + function reloadComments() { + // get array of comment for the current audio event + AudioEventComment.query( + {audioEventId: $routeParams.audioEventId}, + function audioEventCommentSuccess(value, responseHeaders) { + $scope.comments = value; + }); + + } + }]); \ No newline at end of file diff --git a/src/app/annotationLibrary/comments/_comments.scss b/src/app/annotationLibrary/comments/_comments.scss new file mode 100644 index 00000000..e69de29b diff --git a/src/app/annotationLibrary/comments/comments.js b/src/app/annotationLibrary/comments/comments.js new file mode 100644 index 00000000..015e0ff9 --- /dev/null +++ b/src/app/annotationLibrary/comments/comments.js @@ -0,0 +1,11 @@ +var bawCs = angular + .module('bawApp.annotationLibrary.comments', ['bawApp.configuration']) + .directive('comments', ['conf.paths', function (paths) { + var commentDefinition = { + restrict: 'E', + templateUrl: paths.site.files.annotationComments, + link: function postLink(scope, $element, attributes) { + } + }; + return commentDefinition; + }]); \ No newline at end of file diff --git a/src/app/annotationLibrary/comments/comments.tpl.html b/src/app/annotationLibrary/comments/comments.tpl.html new file mode 100644 index 00000000..e69de29b diff --git a/src/baw.configuration.tpl.js b/src/baw.configuration.tpl.js index ea5efdba..ad555933 100644 --- a/src/baw.configuration.tpl.js +++ b/src/baw.configuration.tpl.js @@ -92,6 +92,9 @@ angular.module('bawApp.configuration', ['url']) user: { profile: "/my_account", settings: "/my_account/prefs" + }, + audioEventComment:{ + show: '/audio_events/{audioEventId}/audio_event_comments/{audioEventCommentId}' } }, links: { @@ -112,6 +115,7 @@ angular.module('bawApp.configuration', ['url']) listen: 'listen/listen.tpl.html', annotationViewer: 'annotationViewer/annotationViewer.tpl.html', gridLines: 'annotationViewer/gridLines/gridLines.tpl.html', + annotationComments: 'annotationLibrary/comments/comments.tpl.html', library: { list: 'annotationLibrary/annotationLibrary.tpl.html', item: 'annotationLibrary/annotationItem.tpl.html' diff --git a/src/components/services/services.js b/src/components/services/services.js index e7e9e16d..ed9c29e7 100644 --- a/src/components/services/services.js +++ b/src/components/services/services.js @@ -37,6 +37,11 @@ // NOTE: deleted user resource, API for users no longer exposed + bawss.factory('AudioEventComment', [ '$resource', 'conf.paths', function ($resource, paths) { + return resourcePut($resource, uriConvert(paths.api.routes.audioEventComment.showAbsolute), + {audioEventId: "@audioEventId", audioEventCommentId: '@audioEventCommentId'}); + }]); + bawss.factory('AudioRecording', [ '$resource', 'conf.paths', function ($resource, paths) { return resourcePut($resource, uriConvert(paths.api.routes.audioRecording.showAbsolute), {projectId: "@projectId", siteId: "@siteId", recordingId: '@recordingId'}); From 7ff4e4b19d2546b5c398ffd54306663b4fd6fb3c Mon Sep 17 00:00:00 2001 From: Mark Date: Tue, 13 May 2014 16:32:52 +1000 Subject: [PATCH 07/10] indicate comment time is last updated --- src/app/annotationLibrary/annotationItem.tpl.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/annotationLibrary/annotationItem.tpl.html b/src/app/annotationLibrary/annotationItem.tpl.html index a0532997..9fb29ff8 100644 --- a/src/app/annotationLibrary/annotationItem.tpl.html +++ b/src/app/annotationLibrary/annotationItem.tpl.html @@ -147,7 +147,7 @@

    {{comment.updater.userName}} - {{$parent.formatTimeAgo(comment.updatedAt, 'YYYY-MM-DDTHH:mm:ssZZ')}} + last change {{$parent.formatTimeAgo(comment.updatedAt, 'YYYY-MM-DDTHH:mm:ssZZ')}}

    From 75a43512b231e519a5eabec2173e06da051ad968 Mon Sep 17 00:00:00 2001 From: Mark Date: Thu, 15 May 2014 14:08:19 +1000 Subject: [PATCH 08/10] comments header include number of comments --- src/app/annotationLibrary/annotationItem.tpl.html | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/app/annotationLibrary/annotationItem.tpl.html b/src/app/annotationLibrary/annotationItem.tpl.html index 9fb29ff8..b3b7096d 100644 --- a/src/app/annotationLibrary/annotationItem.tpl.html +++ b/src/app/annotationLibrary/annotationItem.tpl.html @@ -94,7 +94,9 @@

    Details

    -

     Comments +

    + +  {{comments.length == 0 ? 'No Comments Yet' : (comments.length == 1 ? '1 Comment' : comments.length + ' Comments') }}

    @@ -113,7 +115,7 @@

    Date: Fri, 6 Jun 2014 09:21:18 +1000 Subject: [PATCH 09/10] construct urls properly --- build.config.js | 2 +- .../annotationLibrary/annotationItem.tpl.html | 4 +- .../annotationLibrary/annotationLibrary.js | 59 +++++++++++-------- 3 files changed, 38 insertions(+), 27 deletions(-) diff --git a/build.config.js b/build.config.js index 85d60ae7..927afa20 100644 --- a/build.config.js +++ b/build.config.js @@ -18,7 +18,7 @@ module.exports = { }, configFile: appConfigFile, development: { - apiRoot: "http://staging.ecosounds.org", + apiRoot: "http://localhost:3000", siteRoot: "http://localhost:8080", siteDir: "/" }, diff --git a/src/app/annotationLibrary/annotationItem.tpl.html b/src/app/annotationLibrary/annotationItem.tpl.html index 81cfd7fd..e0657d2f 100644 --- a/src/app/annotationLibrary/annotationItem.tpl.html +++ b/src/app/annotationLibrary/annotationItem.tpl.html @@ -46,7 +46,7 @@

    Details

      {{tag.typeOfTag.replace('_',' ')}} @@ -55,7 +55,7 @@

    Details

    {{tag.text}} (ID {{tag.id}})
      Reference Tag diff --git a/src/app/annotationLibrary/annotationLibrary.js b/src/app/annotationLibrary/annotationLibrary.js index 4c42fb89..043dbfac 100644 --- a/src/app/annotationLibrary/annotationLibrary.js +++ b/src/app/annotationLibrary/annotationLibrary.js @@ -9,21 +9,25 @@ baw.annotationLibrary.addCalculatedProperties = function addCalculatedProperties audioEvent.calcOffsetStart = Math.floor(audioEvent.startTimeSeconds / 30) * 30; audioEvent.calcOffsetEnd = (Math.floor(audioEvent.startTimeSeconds / 30) * 30) + 30; + var roundedDuration = Math.round10(audioEvent.annotationDuration, -3); + var roundedFreqLow = Math.round(audioEvent.lowFrequencyHertz); + var roundedFreqHigh = Math.round(audioEvent.highFrequencyHertz); + audioEvent.urls = { site: $url.formatUri(paths.api.links.siteAbsolute, {projectId: audioEvent.projects[0].id, siteId: audioEvent.siteId}), user: $url.formatUri(paths.api.links.userAccountsAbsolute, {userId: audioEvent.ownerId}), tagSearch: $url.formatUri(paths.site.ngRoutes.libraryAbsolute, {tagsPartial: audioEvent.priorityTag.text}), + isReference: $url.formatUri(paths.site.ngRoutes.libraryAbsolute, {reference: audioEvent.isReference}), similar: $url.formatUri(paths.site.ngRoutes.libraryAbsolute, { - annotationDuration: Math.round10(audioEvent.annotationDuration, -3), - freqMin: Math.round(audioEvent.lowFrequencyHertz), - freqMax: Math.round(audioEvent.highFrequencyHertz) -<<<<<<< HEAD + annotationDuration: roundedDuration, + freqMin: roundedFreqLow, + freqMax: roundedFreqHigh }), singleItem: $url.formatUri(paths.site.ngRoutes.libraryItemAbsolute, { recordingId: audioEvent.audioRecordingId, - audioEventId: audioEvent.audioEventId + audioEventId: audioEvent.audioEventId }), listen: $url.formatUri(paths.site.ngRoutes.listenAbsolute, { @@ -37,20 +41,27 @@ baw.annotationLibrary.addCalculatedProperties = function addCalculatedProperties start: audioEvent.startTimeSeconds, end: audioEvent.endTimeSeconds }) -======= - }, true), - singleItem: '/library/' + audioEvent.audioRecordingId + - '/audio_events/' + audioEvent.audioEventId, - listen: '/listen/' + audioEvent.audioRecordingId + - '?start=' + audioEvent.calcOffsetStart + - '&end=' + audioEvent.calcOffsetEnd, - listenWithoutPadding: '/listen/' + audioEvent.audioRecordingId + - '?start=' + audioEvent.startTimeSeconds + - '&end=' + audioEvent.endTimeSeconds, - audioRecording: '/library?' + $url.toKeyValue({audioRecordingId: audioEvent.audioRecordingId}, true) ->>>>>>> db959993d22e1447b68a2dbab09da28a1f535c88 }; + audioEvent.tags.forEach( + function (currentvalue, index, array) { + currentvalue.similarPartial = $url.formatUri(paths.site.ngRoutes.libraryAbsolute, + { + tagsPartial: currentvalue.text, + annotationDuration: roundedDuration, + freqMin: roundedFreqLow, + freqMax: roundedFreqHigh + }); + } + ); + + audioEvent.projects.forEach( + function (currentvalue, index, array) { + currentvalue.link = $url.formatUri(paths.api.links.projectAbsolute, {projectId: currentvalue.id}); + } + ); + + return audioEvent; }; @@ -166,7 +177,7 @@ angular.module('bawApp.annotationLibrary', ['bawApp.configuration']) $scope.createFilterUrl = function createFilterUrl(paramObj) { - return $url.formatUri(paths.site.ngRoutes.libraryAbsolute,paramObj); + return $url.formatUri(paths.site.ngRoutes.libraryAbsolute, paramObj); }; function getEmptyFilterSettings() { @@ -326,7 +337,7 @@ angular.module('bawApp.annotationLibrary', ['bawApp.configuration']) id: null, text: null, errors: [] - }; + }; AudioEvent.get(parameters, function annotationShowSuccess(audioEventValue, responseHeaders) { @@ -368,10 +379,10 @@ angular.module('bawApp.annotationLibrary', ['bawApp.configuration']) }); $scope.createFilterUrl = function createFilterUrl(paramObj) { - return $url.formatUri(paths.site.ngRoutes.libraryAbsolute,paramObj); + return $url.formatUri(paths.site.ngRoutes.libraryAbsolute, paramObj); }; - $scope.createProjectUrl = function createProjectUrl(projectId){ + $scope.createProjectUrl = function createProjectUrl(projectId) { return $url.formatUri(paths.api.links.projectAbsolute, {projectId: projectId}); }; @@ -380,7 +391,7 @@ angular.module('bawApp.annotationLibrary', ['bawApp.configuration']) $routeParams.audioEventId + '#' + audioEventCommentId }; - $scope.formatTimeAgo = function formatTimeAgo(time, formatString){ + $scope.formatTimeAgo = function formatTimeAgo(time, formatString) { return moment(time, formatString).fromNow(); }; @@ -422,7 +433,7 @@ angular.module('bawApp.annotationLibrary', ['bawApp.configuration']) } }; - $scope.updateComment = function updateComment(audioEventCommentId){ + $scope.updateComment = function updateComment(audioEventCommentId) { AudioEventComment.update( { audioEventId: $routeParams.audioEventId, @@ -442,7 +453,7 @@ angular.module('bawApp.annotationLibrary', ['bawApp.configuration']) }); }; - $scope.editComment = function editComment(commentText, audioEventCommentId){ + $scope.editComment = function editComment(commentText, audioEventCommentId) { $scope.editComment.id = audioEventCommentId; $scope.editComment.text = commentText; }; From b6573cf28547915b6921b6b7bc5f5a58f610d942 Mon Sep 17 00:00:00 2001 From: Anthony Truskinger Date: Fri, 12 Dec 2014 23:07:16 +1000 Subject: [PATCH 10/10] Polished off annoation-comments - Adpated annotation comments to the new API format - Converted links to buttons where appropriate - Fully implemented reporting comments functionality (and reported warning icon / font color) - Ensured basic form validation was working. - Fixed the date formatting for comments - Simplified and refactored the forms - Added functionality to bawResource so that it does not expect an array result for `query()` calls --- .../annotationLibrary/_annotationLibrary.scss | 9 ++ .../annotationLibrary/annotationItem.tpl.html | 52 +++++++----- .../annotationLibrary/annotationLibrary.js | 85 +++++++++++++------ src/app/listen/listen.js | 1 + src/baw.configuration.tpl.js | 2 +- src/components/services/bawResource.js | 1 + src/components/services/bawResource.spec.js | 33 ++++++- src/components/services/services.js | 10 ++- 8 files changed, 136 insertions(+), 57 deletions(-) diff --git a/src/app/annotationLibrary/_annotationLibrary.scss b/src/app/annotationLibrary/_annotationLibrary.scss index c0ab5773..56c468b6 100644 --- a/src/app/annotationLibrary/_annotationLibrary.scss +++ b/src/app/annotationLibrary/_annotationLibrary.scss @@ -57,6 +57,15 @@ $loadGifPath: image-url('load.gif'); .library-single-info { margin: 0 auto 0 auto; + + & .reported { + color: $brand-danger; + margin: 0 $padding-base-horizontal; + } + + & .reported-comment { + color: $gray-lighter; + } } /* Shared spectrogram and grid */ diff --git a/src/app/annotationLibrary/annotationItem.tpl.html b/src/app/annotationLibrary/annotationItem.tpl.html index 1fc846cf..9863e3f7 100644 --- a/src/app/annotationLibrary/annotationItem.tpl.html +++ b/src/app/annotationLibrary/annotationItem.tpl.html @@ -58,7 +58,7 @@

    Details

    class="list-group-item" title="Reference tag.">   - Reference Tag + Reference Annotation
      @@ -116,17 +116,19 @@

    now

    - +
    - {{error}}
    - +
    + +
    @@ -140,40 +142,48 @@

    -

    - link | - edit | - delete -

    +
    + link + + + + + + + +
    -

    - link | - report -

    {{comment.updater.userName}} - last change {{$parent.formatTimeAgo(comment.updatedAt, 'YYYY-MM-DDTHH:mm:ssZZ')}} + last change {{formatTimeAgo(comment.updatedAt)}}

    -

    +

    {{comment.comment}}

    -
    +
    - + ng-model="comment.comment"> {{error}}
    -
    diff --git a/src/app/annotationLibrary/annotationLibrary.js b/src/app/annotationLibrary/annotationLibrary.js index e9b78eba..43770a72 100644 --- a/src/app/annotationLibrary/annotationLibrary.js +++ b/src/app/annotationLibrary/annotationLibrary.js @@ -313,15 +313,15 @@ angular.module('bawApp.annotationLibrary', ['bawApp.configuration']) }]) .controller('AnnotationItemCtrl', ['$scope', '$location', '$resource', '$routeParams', '$url', - 'conf.paths', 'conf.constants', 'bawApp.unitConverter', + 'conf.paths', 'conf.constants', 'bawApp.unitConverter', 'moment', 'AudioEvent', 'Tag', - 'Media', 'baw.models.Media', 'UserProfile', 'AudioEventComment', + 'Media', 'baw.models.Media', 'UserProfileEvents', 'UserProfile', 'AudioEventComment', function ($scope, $location, $resource, $routeParams, $url, - paths, constants, unitConverter, + paths, constants, unitConverter, moment, AudioEvent, Tag, - MediaService, Media, UserProfile, AudioEventComment) { + MediaService, Media, UserProfileEvents, UserProfile, AudioEventComment) { - $scope.$on(UserProfile.eventKeys.loaded, profileLoaded); + $scope.$on(UserProfileEvents.loaded, profileLoaded); if (UserProfile.profile && UserProfile.profile.preferences) { profileLoaded(null, UserProfile); } @@ -399,24 +399,31 @@ angular.module('bawApp.annotationLibrary', ['bawApp.configuration']) $routeParams.audioEventId + '#' + audioEventCommentId }; - $scope.formatTimeAgo = function formatTimeAgo(time, formatString) { - return moment(time, formatString).fromNow(); + $scope.formatTimeAgo = function formatTimeAgo(date) { + if (date) { + return moment(date).fromNow(); + } + else { + return "unknown"; + } }; $scope.createComment = function createComment() { - AudioEventComment.save( - {audioEventId: $routeParams.audioEventId}, // parameters - {comment: $scope.newComment.text}, // post data - function createCommentSuccess(value, responseHeaders) { - console.log('create success', arguments); - $scope.newComment.errors = []; - $scope.newComment.text = ''; - reloadComments(); - }, - function createCommentError(httpResponse) { - console.log('create failure', arguments); - $scope.newComment.errors = httpResponse.data.comment; - }); + if($scope.createCommentForm.$valid) { + AudioEventComment.save( + {audioEventId: $routeParams.audioEventId}, // parameters + {comment: $scope.newComment.text}, // post data + function createCommentSuccess(value, responseHeaders) { + console.log('create success', arguments); + $scope.newComment.errors = []; + $scope.newComment.text = ''; + reloadComments(); + }, + function createCommentError(httpResponse) { + console.log('create failure', arguments); + $scope.newComment.errors = httpResponse.data.comment; + }); + } }; $scope.deleteComment = function deleteComment(commentText, audioEventCommentId) { @@ -441,13 +448,15 @@ angular.module('bawApp.annotationLibrary', ['bawApp.configuration']) } }; - $scope.updateComment = function updateComment(audioEventCommentId) { + function updateCommentBase(id, body) { AudioEventComment.update( + // url parameters { audioEventId: $routeParams.audioEventId, - audioEventCommentId: audioEventCommentId - }, // parameters - {comment: $scope.editComment.text}, // post data + audioEventCommentId: id + }, + // body + body, function updateCommentSuccess(value, responseHeaders) { console.log('update success', arguments); $scope.editComment.errors = []; @@ -459,11 +468,27 @@ angular.module('bawApp.annotationLibrary', ['bawApp.configuration']) console.log('update failure', arguments); $scope.editComment.errors = httpResponse.data.comment; }); + } + + $scope.updateComment = function updateComment(comment, updateForm) { + if(updateForm.$valid) { + updateCommentBase(comment.id, { + comment: comment.comment + }); + comment.editing = false; + } }; - $scope.editComment = function editComment(commentText, audioEventCommentId) { - $scope.editComment.id = audioEventCommentId; - $scope.editComment.text = commentText; + $scope.editComment = function editComment(comment) { + comment.editing = true; + }; + + $scope.reportComment = function reportComment(comment) { + comment.flag = "report"; + updateCommentBase(comment.id, { + flag: comment.flag + }); + }; function profileLoaded(event, userProfile) { @@ -475,7 +500,11 @@ angular.module('bawApp.annotationLibrary', ['bawApp.configuration']) AudioEventComment.query( {audioEventId: $routeParams.audioEventId}, function audioEventCommentSuccess(value, responseHeaders) { - $scope.comments = value; + $scope.comments = value.data; + + $scope.comments.forEach(function(value) { + + }); }); } diff --git a/src/app/listen/listen.js b/src/app/listen/listen.js index 782d9e3b..6150ab74 100644 --- a/src/app/listen/listen.js +++ b/src/app/listen/listen.js @@ -46,6 +46,7 @@ angular.module('bawApp.listen', ['decipher.tags', 'ui.bootstrap.typeahead']) * @param UserProfile * @param Bookmark * @param UserProfileEvents + * @param moment */ function ListenCtrl( $scope, $resource, $location, $routeParams, $route, $q, paths, constants, $url, ngAudioEvents, diff --git a/src/baw.configuration.tpl.js b/src/baw.configuration.tpl.js index e094ad15..fb520e03 100644 --- a/src/baw.configuration.tpl.js +++ b/src/baw.configuration.tpl.js @@ -57,7 +57,7 @@ angular.module('bawApp.configuration', ['url']) settings: "/my_account/prefs" }, audioEventComment: { - show: '/audio_events/{audioEventId}/audio_event_comments/{audioEventCommentId}' + show: '/audio_events/{audioEventId}/comments/{audioEventCommentId}' }, bookmark: { show: "/bookmarks/{bookmarkId}" diff --git a/src/components/services/bawResource.js b/src/components/services/bawResource.js index cfdd5394..0be93e0d 100644 --- a/src/components/services/bawResource.js +++ b/src/components/services/bawResource.js @@ -25,6 +25,7 @@ angular.module("bawApp.services.resource", ["ngResource"]) var a = actions || {}; a.update = a.update || { method: 'PUT' }; + a.query = {method: "GET", isArray: false}; var resource = $resource(convertedPath, paramDefaults, a); resource.modifiedPath = convertedPath; diff --git a/src/components/services/bawResource.spec.js b/src/components/services/bawResource.spec.js index 1a61a57b..325ab077 100644 --- a/src/components/services/bawResource.spec.js +++ b/src/components/services/bawResource.spec.js @@ -1,17 +1,22 @@ describe("The bawResource service", function () { - var Bookmark; + var $httpBackend, bawResource, $rootScope; beforeEach(module('bawApp.services')); - beforeEach(inject(["Bookmark", function (providedBookmark) { - Bookmark = providedBookmark; + beforeEach(inject(["$injector", "bawResource", "$rootScope", function ($injector, providedBawResource, _$rootScope) { + $httpBackend = $injector.get('$httpBackend'); + + $httpBackend.when("GET", "/test").respond({data:[], meta:{}}); + + bawResource = providedBawResource; + $rootScope = _$rootScope; }])); it("should return a resource constructor that includes update/put", function () { - expect(Bookmark).toImplement({ + expect(bawResource("/test")).toImplement({ "get": null, "save": null, "query": null, @@ -21,4 +26,24 @@ describe("The bawResource service", function () { "modifiedPath": null }); }); + + it("should override $resource's query", function(done) { + + // make "new" resource + var testResource = bawResource("/test"); + + var pass; + var result = testResource + .query().$promise + .then(function() { + pass = true; + }, function() { + pass = false; + }); + $httpBackend.flush(); + + expect(pass).toBeTrue(); + + done(); + }); }); \ No newline at end of file diff --git a/src/components/services/services.js b/src/components/services/services.js index 791c3255..85c8d74b 100644 --- a/src/components/services/services.js +++ b/src/components/services/services.js @@ -93,12 +93,16 @@ // NOTE: deleted user resource, API for users no longer exposed - bawss.factory('AudioEventComment', [ '$resource', 'conf.paths', function ($resource, paths) { - return resourcePut($resource, uriConvert(paths.api.routes.audioEventComment.showAbsolute), + bawss.factory('AudioEventComment', [ "bawResource", 'conf.paths', function (bawResource, paths) { + return bawResource( + paths.api.routes.audioEventComment.showAbsolute, {audioEventId: "@audioEventId", audioEventCommentId: '@audioEventCommentId'}); }]); - bawss.factory('AudioRecording', [ '$resource', '$http', 'conf.paths', 'QueryBuilder', function ($resource, $http, paths, QueryBuilder) { + 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'});