diff --git a/src/app/citizenScience/citizenScienceCommon.js b/src/app/citizenScience/citizenScienceCommon.js index 63f59174..45c85a5d 100644 --- a/src/app/citizenScience/citizenScienceCommon.js +++ b/src/app/citizenScience/citizenScienceCommon.js @@ -17,6 +17,11 @@ citizenScienceCommon.factory("CitizenScienceCommon", [ var self = this; + self.studyData = { + study: null, + studyName: null + }; + /** * Default values for audio model, to be updated when UserProfile is loaded * @type {Object} @@ -44,17 +49,16 @@ citizenScienceCommon.factory("CitizenScienceCommon", [ self.profileLoaded(null, UserProfile); } - self.mediaModel = null; - - - self.functions = { + return { getAudioModel: function () { return self.audioElementModel; }, + studyData: self.studyData + }; - return self.functions; + }]); \ No newline at end of file diff --git a/src/app/citizenScience/datasetProgress/_progress.scss b/src/app/citizenScience/datasetProgress/_progress.scss index e83b540e..3d476cfb 100644 --- a/src/app/citizenScience/datasetProgress/_progress.scss +++ b/src/app/citizenScience/datasetProgress/_progress.scss @@ -1,13 +1,61 @@ -.citSci-next { +.dataset-progress-wrapper { - margin-left: 30px; + display: flex; - a, button { + .citSci-next { - width: 220px; + margin-left: 30px; + + a, button { + + width: 220px; + + } } + .dataset-progress { + + display: flex; + + background-color: #000000; + + .progress-summary { + margin-left: 15px; + background: #000000; + color: #aaa; + + } + + + + .progress-graphic { + margin-left: 15px; + background: #000000; + padding: 1px 1px 2px 2px; + display: block; + width: 23px; + height: 23px; + border-radius: 3px; + div { + display: block; + height: 1px; + width: 1px; + background: #00ca56; + margin:2px 2px 1px 1px; + float: left; + border-radius: 1px; + } + } + } + + + + } + + + + diff --git a/src/app/citizenScience/datasetProgress/citizenScienceSamples.js b/src/app/citizenScience/datasetProgress/citizenScienceSamples.js index 349a62e3..c59fa5f7 100644 --- a/src/app/citizenScience/datasetProgress/citizenScienceSamples.js +++ b/src/app/citizenScience/datasetProgress/citizenScienceSamples.js @@ -120,6 +120,9 @@ csSamples.factory("CsSamples", [ DatasetItem.datasetItems(self.datasetId, nextPageNum).then(x => { + // this should always be the same + self.totalItems = x.data.meta.paging.total; + if (x.data.data.length > 0) { self.pages[nextPageNum - 1] = x.data; if (thenSelectNewItem) { @@ -218,6 +221,10 @@ csSamples.factory("CsSamples", [ onPlayed: function () { ProgressEvent.createProgressEvent(self.currentItem.id, "played"); + }, + + totalItems: function () { + return self.totalItems; } }; diff --git a/src/app/citizenScience/datasetProgress/datasetProgress.js b/src/app/citizenScience/datasetProgress/datasetProgress.js index b2da1053..73d812d8 100644 --- a/src/app/citizenScience/datasetProgress/datasetProgress.js +++ b/src/app/citizenScience/datasetProgress/datasetProgress.js @@ -9,11 +9,13 @@ angular.module("bawApp.components.progress", ["bawApp.citizenScience.csSamples"]) .component("datasetProgress", { templateUrl: "citizenScience/datasetProgress/datasetProgress.tpl.html", - controller: ["$scope", "$routeParams", "CsSamples", "SampleLabels", "$url", "conf.paths", - function ($scope, $routeParams, CsSamples, SampleLabels, $url, paths) { + controller: ["$scope", "$routeParams", "CsSamples", "SampleLabels", "$url", "conf.paths", "QuestionResponse", "CitizenScienceCommon", + function ($scope, $routeParams, CsSamples, SampleLabels, $url, paths, QuestionResponse, CitizenScienceCommon) { var self = this; + + // routed dataset item id will link back to the unrouted listen page $scope.listenLink = $url.formatUri(paths.site.ngRoutes.citizenScience.listen, {studyName: $routeParams.studyName}); @@ -47,6 +49,9 @@ angular.module("bawApp.components.progress", ["bawApp.citizenScience.csSamples"] }); $scope.$watch(() => CsSamples.currentItem(), (newVal, oldVal) => { + + self.updateProgress(); + SampleLabels.reset(newVal.id); }); @@ -90,6 +95,122 @@ angular.module("bawApp.components.progress", ["bawApp.citizenScience.csSamples"] }; + $scope.progress = { + itemCount: 0, + responseCount: 0, + percent: 0, + breaks: false + + }; + + self.refreshIn = 0; + + + /** + * called each time we go to a new segment + * will increment response count. We only refresh from the server sometimes + * to save unecessary api calls. + */ + self.updateProgress = function () { + + if (self.refreshIn === 0) { + self.refreshProgress(); + self.refreshIn = 5; + } + $scope.progress.responseCount += 1; + self.updateProgressBreaks(); + self.refreshIn -= 1; + + }; + + + /** + * Update progress when the study changes. It will not be loaded when this controller is initialised + */ + $scope.$watch(() => CitizenScienceCommon.studyData.study, (newVal, oldVal) => { + self.refreshProgress(); + }); + + /** + * Watch the total items, because it will not be ready when the controller first loads + */ + $scope.$watch(CsSamples.totalItems, (newVal, oldVal) => { + if (typeof newVal === "number") { + $scope.progress.itemCount = newVal; + self.updateProgressBreaks(); + } + }); + + + /** + * gets the total number of dataset items and the total number of responses + * and calculates the percentage. + */ + self.refreshProgress = function () { + + // make sure the study has been loaded + if (CitizenScienceCommon.studyData.study) { + + // request 1 item to get the metadata showing the total number of items + var responseFilterParams = { + studyId: CitizenScienceCommon.studyData.study.id, + items: 1 + }; + + QuestionResponse.questionResponses(responseFilterParams).then((x) => { + + var totalResponses = x.data.meta.paging.total; + $scope.progress.responseCount = totalResponses; + self.updateProgressBreaks(); + self.refreshIn = 5; + + }); + + } + + }; + + /** + * Progress is rendered a 5x5 grid of divs + * each item represents 1 25th of the total number of items + * e.g. if there are 2500 items, the first point represents 100 items. + */ + self.updateProgressBreaks = function () { + + var numBreaks = 25; + + if (!$scope.progress.breaks) { + $scope.progress.breaks = new Array(numBreaks); + } + + if ($scope.progress.itemCount === 0) { + return; + } + + + var fullBreaks = ($scope.progress.responseCount / $scope.progress.itemCount) * numBreaks; + // number of completely full breaks. Because it's possible to be more than 100% complete + // this is also capped + var numFull = Math.min(Math.floor(fullBreaks), numBreaks); + + $scope.progress.breaks.fill(1, 0, numFull); + $scope.progress.breaks.fill(0, numFull , numBreaks); + if (numFull < numBreaks) { + $scope.progress.breaks[numFull] = fullBreaks % 1; + } + + var percent = Math.round(100 * $scope.progress.responseCount / $scope.progress.itemCount); + $scope.progress.percent = percent; + console.log("$scope.progress.percent", percent); + $scope.progress.percentCapped = Math.min(percent, 100); + + + + }; + + + + }], bindings: { datasetId: "=" diff --git a/src/app/citizenScience/datasetProgress/datasetProgress.tpl.html b/src/app/citizenScience/datasetProgress/datasetProgress.tpl.html index e30b1455..a171405c 100644 --- a/src/app/citizenScience/datasetProgress/datasetProgress.tpl.html +++ b/src/app/citizenScience/datasetProgress/datasetProgress.tpl.html @@ -1,25 +1,46 @@ +
+
+ + + {{nextText()}} + +
+ + +
+ + + {{progress.responseCount}} / {{progress.itemCount}} ({{progress.percent}} %) + + +
+
-
- - - {{nextText()}} -
+
+ + +
+ + + + + diff --git a/src/app/citizenScience/listen/listen.js b/src/app/citizenScience/listen/listen.js index 9c945772..d8fb47aa 100644 --- a/src/app/citizenScience/listen/listen.js +++ b/src/app/citizenScience/listen/listen.js @@ -19,6 +19,9 @@ class CitizenScienceListenController { */ $scope.csProject = $routeParams.studyName; + CitizenScienceCommon.studyData.studyName = $scope.csProject; + + /** * The current sample object, including sample id * @type {number} @@ -77,6 +80,7 @@ class CitizenScienceListenController { } $scope.study = studies[0]; + CitizenScienceCommon.studyData.study = $scope.study; Question.questions($scope.study.id).then(x => { console.log("questions loaded", x); diff --git a/src/components/services/questionResponse.js b/src/components/services/questionResponse.js index f25be98b..4ab00967 100644 --- a/src/components/services/questionResponse.js +++ b/src/components/services/questionResponse.js @@ -32,15 +32,15 @@ angular }; - resource.questionResponses = function getQuestionResponses(studyId, pageNum) { - var url = $url.formatUri(paths.api.routes.questionResponses.listAbsolute, {studyId: studyId, page: pageNum}); + resource.questionResponses = function getQuestionResponses(params) { + var url = $url.formatUri(paths.api.routes.questionResponse.listAbsolute, params); return $http.get(url).then(x => { return QuestionResponseModel.makeFromApi(x); }); }; resource.questionResponse = function getQuestionResponse(questionResponseId) { - var url = $url.formatUri(paths.api.routes.questionResponses.showAbsolute, {questionResponseId: questionResponseId}); + var url = $url.formatUri(paths.api.routes.questionResponse.showAbsolute, {questionResponseId: questionResponseId}); return $http.get(url).then(x => QuestionResponseModel.makeFromApi(x)); };