diff --git a/README.md b/README.md index b439ebacbbf54116b04107bd4a90e8c1363e97b1..81683aa1d75250b666f953ad60e45e491731cbd3 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,6 @@ The API documentation is available at `<BASE URL>/swagger-ui.html`. A JSON versi * When updating an article from the 'recent articles' list, bug with 'publish' state; * When updating a model the SVG is not updated (SVG updates when opening article editor); -* Dynamic stats (users, articles, ...); * In the profile view, we shouldn't see the '+' between firstname and lastname; * In the profile view links to own articles and so on, are not implemented; * Export PDF; diff --git a/src/main/java/org/hbp/mip/controllers/StatsApi.java b/src/main/java/org/hbp/mip/controllers/StatsApi.java index 8d54f00dfbcf78c8aafc86b5765e7cb0f980c35e..7f1edd7ccc11a314830ae568c9242b50ec847eba 100644 --- a/src/main/java/org/hbp/mip/controllers/StatsApi.java +++ b/src/main/java/org/hbp/mip/controllers/StatsApi.java @@ -1,7 +1,11 @@ package org.hbp.mip.controllers; import io.swagger.annotations.*; +import org.hbp.mip.model.GeneralStats; import org.hbp.mip.model.Statistics; +import org.hbp.mip.utils.HibernateUtil; +import org.hibernate.Query; +import org.hibernate.Session; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; @@ -16,22 +20,38 @@ import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE; @Controller @RequestMapping(value = "/stats", produces = {APPLICATION_JSON_VALUE}) @Api(value = "/stats", description = "the stats API") -@javax.annotation.Generated(value = "class io.swagger.codegen.languages.SpringMVCServerCodegen", date = "2016-01-20T14:47:53.152Z") public class StatsApi { - @ApiOperation(value = "Get the statistics for a group or a variable", notes = "", response = Statistics.class, responseContainer = "List") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "Found"), - @ApiResponse(code = 404, message = "Not found") }) - @RequestMapping(value = "/{code}", - produces = { "application/json" }, - - method = RequestMethod.GET) + + @ApiOperation(value = "Get general statistics", response = GeneralStats.class) + @ApiResponses(value = {@ApiResponse(code = 200, message = "Found"), @ApiResponse(code = 404, message = "Not found") }) + @RequestMapping(method = RequestMethod.GET) + public ResponseEntity<GeneralStats> getGeneralStatistics() throws NotFoundException { + GeneralStats stats = new GeneralStats(); + + Session session = HibernateUtil.getSessionFactory().getCurrentSession(); + session.beginTransaction(); + Query countUsersQuery = session.createQuery("SELECT COUNT(*) FROM User"); + Query countArticlesQuery = session.createQuery("SELECT COUNT(*) FROM Article"); + Query countVariablesQuery = session.createQuery("SELECT COUNT(*) FROM Variable"); + Long nbUsers = (Long) countUsersQuery.uniqueResult(); + Long nbArticles = (Long) countArticlesQuery.uniqueResult(); + Long nbVariables = (Long) countVariablesQuery.uniqueResult(); + session.getTransaction().commit(); + + stats.setUsers(nbUsers); + stats.setArticles(nbArticles); + stats.setVariables(nbVariables); + + return new ResponseEntity<GeneralStats>(HttpStatus.OK).ok(stats); + } + + @ApiOperation(value = "Get the statistics for a group or a variable", response = Statistics.class, responseContainer = "List") + @ApiResponses(value = {@ApiResponse(code = 200, message = "Found"), @ApiResponse(code = 404, message = "Not found") }) + @RequestMapping(value = "/{code}", produces = { "application/json" }, method = RequestMethod.GET) public ResponseEntity<List<Statistics>> getTheStatisticsForAGroupOrAVariable( @ApiParam(value = "code of the group or variable",required=true ) @PathVariable("code") String code - - ) - throws NotFoundException { - // do some magic! + ) throws NotFoundException { + // TODO: Implement this method return new ResponseEntity<List<Statistics>>(HttpStatus.OK); } diff --git a/src/main/java/org/hbp/mip/model/GeneralStats.java b/src/main/java/org/hbp/mip/model/GeneralStats.java new file mode 100644 index 0000000000000000000000000000000000000000..679b1d91ec310fe718319b46e3427ddcaf8d0399 --- /dev/null +++ b/src/main/java/org/hbp/mip/model/GeneralStats.java @@ -0,0 +1,43 @@ +package org.hbp.mip.model; + +import com.fasterxml.jackson.annotation.JsonInclude; +import io.swagger.annotations.ApiModel; + +/** + * Created by mirco on 03.02.16. + */ +@ApiModel(description = "") +@JsonInclude(JsonInclude.Include.NON_NULL) +public class GeneralStats { + + private Long users = null; + private Long articles = null; + private Long variables = null; + + public GeneralStats() { + } + + public Long getUsers() { + return users; + } + + public void setUsers(Long users) { + this.users = users; + } + + public Long getArticles() { + return articles; + } + + public void setArticles(Long articles) { + this.articles = articles; + } + + public Long getVariables() { + return variables; + } + + public void setVariables(Long variables) { + this.variables = variables; + } +} diff --git a/src/main/resources/static/frontend/app/scripts/app/home/home.controller.js b/src/main/resources/static/frontend/app/scripts/app/home/home.controller.js index a89b2fc7ab86cf5a926d0e779b7bd4d655d88ac9..68fc04616dda643ba05457a102af475226b90bec 100644 --- a/src/main/resources/static/frontend/app/scripts/app/home/home.controller.js +++ b/src/main/resources/static/frontend/app/scripts/app/home/home.controller.js @@ -1,119 +1,126 @@ -/** - * Created by Michael DESIGAUD on 11/08/2015. - */ -angular.module('chuvApp.home').controller('HomeController',['$scope','$translatePartialLoader','$translate','WidgetService','$rootScope','User','$cookies','Model','ChartUtil','$q', - function($scope,$translatePartialLoader,$translate,WidgetService,$rootScope,User,$cookies,Model,ChartUtil,$q){ - - $translatePartialLoader.addPart('home'); - $translatePartialLoader.addPart('articles'); - $translatePartialLoader.addPart('requests'); - $translate.refresh(); - - $scope.datas = { - scientists: 14, - articles: 73, - patients: 3721, - teams: 126 - }; - - $scope.models = []; - - /** - * Search articles with current selected filters - */ - $scope.init = function () { - var introTxtSelector = '.intro-txt'; - $scope.tlIntro = new TimelineMax({ paused : true }); - $scope.tlIntro .to($('.intro'), 0.6, { y : '-100%', scale : .4, autoAlpha : 0, ease : Power4.easeIn }) - .to($(introTxtSelector), 0.6, { y : '0%', scale : 1, autoAlpha : 1, ease : Power4.easeOut }); - - $scope.tlIntro2 = new TimelineMax({ paused : true }); - $scope.tlIntro2.to($(introTxtSelector), 0.6, { y : '-100%', scale : .4, autoAlpha : 0, ease : Power4.easeIn }, 'start') - .to($('.trigger-intro'), 0.3, { autoAlpha : 0 }, 'start') - .to($('.trigger-close-intro'), 0.3, { autoAlpha : 0 }, 'start') - .to($('.intro-container'), 0.2, { height: 0 }, '-=0.2'); - - Model.getList({ limit:3, team:0, own:1}).then(function(response){ - $scope.results = response.data; - var promises = []; - - angular.forEach($scope.results, function(model) { - promises.push($scope.getModel(model.slug)); - }); - - $q.all(promises).then(function (modelsData) { - angular.forEach(modelsData,function(model){ - $scope.models.push(model); - }); - }); - - }); - }; - - $scope.getModel = function(slug){ - var deferred = $q.defer(); - Model.get({slug:slug}).$promise.then(function(model){ - model.chartConfig = { - options: { - chart: { - zoomType: 'x', - height:'280' - } - }, - title:{}, - subtitle:{} - }; - model.chartConfig.title.text = model.title; - model.chartConfig.subtitle.text = model.description; - model.chartConfig.options.chart.type = model.chart.chartType; - model.chartConfig.xAxis = {code:model.chart.xAxis}; - model.chartConfig.series = _.map(model.chart.chartConfigSets, function(o) { - var configSet = {}; - configSet.color = o.color; - configSet.name = o.label; - configSet.code = o.code; - return configSet; - }); - ChartUtil.toChartData(model.chartConfig,model.dataset); - deferred.resolve(model); - }); - return deferred.promise; - }; - - $scope.gridsterOpts = { - resizable: { - enabled: false - } - }; - - $scope.animateIntro = function(){ - if( !$scope.step2 ) { - $scope.tlIntro.play(); - $scope.step2 = true; - } - else { - $scope.tlIntro2.play(); - $scope.hideIntro(); - } - }; - - $scope.closePanel = function(event){ - $(event.currentTarget).fadeOut(); - TweenMax.to($('.intro'), 0.6, { y : '-100%', scale : .4, autoAlpha : 0, ease : Power4.easeIn }); - $scope.tlIntro2.play(); - $scope.hideIntro(); - }; - - - - /** - * Hide intro and store in cookie - */ - $scope.hideIntro = function() { - $cookies.put('intro-' + User.current().username, "hide"); - }; - - // Init the controller values - $scope.init(); - - }]); +/** + * Created by Michael DESIGAUD on 11/08/2015. + */ +angular.module('chuvApp.home').controller('HomeController',['$scope','$translatePartialLoader','$translate','WidgetService','$rootScope','User','$cookies','Model','ChartUtil','$q','$http', 'backendUrl', + function($scope,$translatePartialLoader,$translate,WidgetService,$rootScope,User,$cookies,Model,ChartUtil,$q,$http, backendUrl){ + + $translatePartialLoader.addPart('home'); + $translatePartialLoader.addPart('articles'); + $translatePartialLoader.addPart('requests'); + $translate.refresh(); + + /*$scope.datas = { + scientists: 0, + articles: 0, + patients: 0, + teams: 0 + };*/ + + $scope.models = []; + + /** + * Search articles with current selected filters + */ + $scope.init = function () { + $http.get(backendUrl+"/stats").success( + function (response) { + $scope.datas = response; + } + ); + var introTxtSelector = '.intro-txt'; + $scope.tlIntro = new TimelineMax({ paused : true }); + $scope.tlIntro .to($('.intro'), 0.6, { y : '-100%', scale : .4, autoAlpha : 0, ease : Power4.easeIn }) + .to($(introTxtSelector), 0.6, { y : '0%', scale : 1, autoAlpha : 1, ease : Power4.easeOut }); + + $scope.tlIntro2 = new TimelineMax({ paused : true }); + $scope.tlIntro2.to($(introTxtSelector), 0.6, { y : '-100%', scale : .4, autoAlpha : 0, ease : Power4.easeIn }, 'start') + .to($('.trigger-intro'), 0.3, { autoAlpha : 0 }, 'start') + .to($('.trigger-close-intro'), 0.3, { autoAlpha : 0 }, 'start') + .to($('.intro-container'), 0.2, { height: 0 }, '-=0.2'); + + Model.getList({ limit:3, team:0, own:1}).then(function(response){ + $scope.results = response.data; + var promises = []; + + angular.forEach($scope.results, function(model) { + promises.push($scope.getModel(model.slug)); + }); + + $q.all(promises).then(function (modelsData) { + angular.forEach(modelsData,function(model){ + $scope.models.push(model); + }); + }); + + }); + }; + + $scope.getModel = function(slug){ + var deferred = $q.defer(); + Model.get({slug:slug}).$promise.then(function(model){ + model.chartConfig = { + options: { + chart: { + zoomType: 'x', + height:'280' + } + }, + title:{}, + subtitle:{} + }; + model.chartConfig.title.text = model.title; + model.chartConfig.subtitle.text = model.description; + model.chartConfig.options.chart.type = model.chart.chartType; + model.chartConfig.xAxis = {code:model.chart.xAxis}; + model.chartConfig.series = _.map(model.chart.chartConfigSets, function(o) { + var configSet = {}; + configSet.color = o.color; + configSet.name = o.label; + configSet.code = o.code; + return configSet; + }); + ChartUtil.toChartData(model.chartConfig,model.dataset); + deferred.resolve(model); + }); + return deferred.promise; + }; + + $scope.gridsterOpts = { + resizable: { + enabled: false + } + }; + + $scope.animateIntro = function(){ + if( !$scope.step2 ) { + $scope.tlIntro.play(); + $scope.step2 = true; + } + else { + $scope.tlIntro2.play(); + $scope.hideIntro(); + } + }; + + $scope.closePanel = function(event){ + $(event.currentTarget).fadeOut(); + TweenMax.to($('.intro'), 0.6, { y : '-100%', scale : .4, autoAlpha : 0, ease : Power4.easeIn }); + $scope.tlIntro2.play(); + $scope.hideIntro(); + }; + + + + /** + * Hide intro and store in cookie + */ + $scope.hideIntro = function() { + $cookies.put('intro-' + User.current().username, "hide"); + }; + + + + // Init the controller values + $scope.init(); + + }]); diff --git a/src/main/resources/static/frontend/app/scripts/app/home/home.html b/src/main/resources/static/frontend/app/scripts/app/home/home.html index 7ba2ddc5b394153aaca98b982818dc7a2fe6f0fb..fa5e9d285cfa40f30b416e3858226e5fdf0d0ea8 100644 --- a/src/main/resources/static/frontend/app/scripts/app/home/home.html +++ b/src/main/resources/static/frontend/app/scripts/app/home/home.html @@ -31,8 +31,8 @@ <div class="col-md-3"> <div class="info-tile tile-orange"> <div class="tile-icon"><i class="icon-glasses"></i></div> - <div class="tile-heading"><span>Scientists</span></div> - <div class="tile-body"><span>{{datas.scientists}}</span></div> + <div class="tile-heading"><span>Users</span></div> + <div class="tile-body"><span>{{datas.users}}</span></div> <div class="tile-footer">Scientists registered <br />on the platform sipides</div> </div> </div> @@ -47,8 +47,8 @@ <div class="col-md-3"> <div class="info-tile tile-gray"> <div class="tile-icon"><i class="icon-molecular"></i></div> - <div class="tile-heading"><span>Records</span></div> - <div class="tile-body"><span>{{datas.patients}}</span></div> + <div class="tile-heading"><span>Variables</span></div> + <div class="tile-body"><span>{{datas.variables}}</span></div> <div class="tile-footer">Records in database</div> </div> </div>