Changeset 1584
- Timestamp:
- Mar 3, 2011, 8:02:44 PM (12 years ago)
- Location:
- trunk
- Files:
-
- 1 added
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/application.properties
r1572 r1584 1 1 #Grails Metadata file 2 # Mon Feb 28 11:48:03 CET 20112 #Thu Mar 03 15:50:23 CET 2011 3 3 app.build.display.info=0 4 4 app.build.svn.revision=1079 … … 13 13 plugins.db-util=0.4 14 14 plugins.famfamfam=1.0.1 15 plugins.gdt=0.0.1 815 plugins.gdt=0.0.19 16 16 plugins.grom=0.2.2 17 17 plugins.hibernate=1.3.7 -
trunk/grails-app/controllers/HomeController.groovy
r1430 r1584 1 1 import dbnp.studycapturing.* 2 import dbnp.authentication.* 2 3 import org.codehaus.groovy.grails.commons.GrailsApplication 4 import org.codehaus.groovy.grails.commons.ConfigurationHolder 5 import grails.converters.JSON 6 import org.dbnp.gdt.Template 3 7 4 8 /** … … 17 21 */ 18 22 class HomeController { 19 def index = { 20 //if (!Template.count() && grails.util.GrailsUtil.environment != GrailsApplication.ENV_TEST && grails.util.GrailsUtil.environment != "dbnptest") { 21 // redirect(controller:'setup',action:'index') 22 //} else { 23 [ studyCount: dbnp.studycapturing.Study.count(), userCount: dbnp.authentication.SecUser.count(), facebookLikeUrl: '/' ] 24 //} 25 } 26 23 def authenticationService 24 def dataSource 25 def gdtService 26 27 def index = { 28 // create sql instance for advanced queries 29 def config = ConfigurationHolder.config 30 def sql = new groovy.sql.Sql(dataSource) 31 def db = config.dataSource.driverClassName 32 33 // get study statistics 34 def user = authenticationService.getLoggedInUser() 35 def studyCount = Study.count() 36 def readableStudyCount = Study.countReadableStudies(user) 37 def readableAndWritableStudyCount = Study.countReadableAndWritableStudies(user) 38 def readOnlyStudyCount = (readableStudyCount - readableAndWritableStudyCount) 39 def noAccessStudyCount = studyCount - readableAndWritableStudyCount 40 def publishedPublicStudyCount = Study.countPublicStudies(true) 41 def unPublishedPublicStudyCount = Study.countPublicStudies(false) 42 def publicStudyCount = publishedPublicStudyCount + unPublishedPublicStudyCount 43 def publishedPrivateStudyCount = Study.countPrivateStudies(true) 44 def unPublishedPrivateStudyCount = Study.countPrivateStudies(false) 45 def privateStudyCount = publishedPrivateStudyCount + unPublishedPrivateStudyCount 46 47 // daily statistics 48 def startDate, endDate, date, userTotal, studyTotal, templateTotal 49 def dailyStatistics = [:] 50 if (db == "org.postgresql.Driver") { 51 //sql.eachRow("SELECT b.*,(select cast( now() - '120 day'::interval * random() as date) FROM Template c WHERE c.id=b.id) as newDate FROM Template b WHERE b.id IN (SELECT id FROM Template a)") {sql.execute(sprintf("UPDATE Template SET date_created='%s' WHERE id=%s", it.newDate, it.id))} 52 def studiesPerDay = sql.rows("SELECT DISTINCT date_trunc('day', a.date_created) as day, (SELECT count(b.*) FROM study b WHERE date_trunc('day', b.date_created) = date_trunc('day', a.date_created)) as count FROM study a ORDER BY day ASC") 53 def usersPerDay = sql.rows("SELECT DISTINCT date_trunc('day', a.date_created) as day, (SELECT count(b.*) FROM sec_user b WHERE date_trunc('day', b.date_created) = date_trunc('day', a.date_created)) as count FROM sec_user a ORDER BY day ASC") 54 def templatesPerDay = sql.rows("SELECT DISTINCT date_trunc('day', a.date_created) as day, (SELECT count(b.*) FROM template b WHERE date_trunc('day', b.date_created) = date_trunc('day', a.date_created)) as count FROM template a ORDER BY day ASC") 55 56 // combine daily statistics 57 dailyStatistics = [:] 58 long oneDay = (1 * 24 * 60 * 60 * 1000) 59 startDate = (usersPerDay[0].day <= studiesPerDay[0].day) ? usersPerDay[0].day : studiesPerDay[0].day 60 startDate = (templatesPerDay[0].day != null && templatesPerDay[0].day < startDate) ? templatesPerDay[0].day : startDate 61 endDate = (usersPerDay[usersPerDay.size()-1].day >= studiesPerDay[studiesPerDay.size()-1].day) ? usersPerDay[usersPerDay.size()-1].day : studiesPerDay[studiesPerDay.size()-1].day 62 endDate = (templatesPerDay[0].day != null && templatesPerDay[templatesPerDay.size()-1].day > endDate) ? templatesPerDay[templatesPerDay.size()-1].day : endDate 63 date = startDate.clone() 64 65 userTotal = 0 66 studyTotal = 0 67 templateTotal = 0 68 while (date <= endDate) { 69 def userDay = usersPerDay.find{ it.day == date } 70 def studyDay = studiesPerDay.find{ it.day == date } 71 def templateDay = templatesPerDay.find{ it.day == date } 72 def users = (userDay) ? userDay.count : 0 73 def studies = (studyDay) ? studyDay.count : 0 74 def templates = (templateDay) ? templateDay.count : 0 75 76 userTotal += users 77 studyTotal += studies 78 templateTotal += templates 79 80 dailyStatistics[ date.clone() ] = [ 81 users : users, 82 userTotal : userTotal, 83 studies : studies, 84 studyTotal : studyTotal, 85 templates : templates, 86 templateTotal : templateTotal 87 ] 88 date.setTime(date.getTime() + oneDay) 89 } 90 } 91 92 [ 93 // daily statistics 94 startDate : startDate, 95 dailyStatistics : dailyStatistics, 96 97 // study 98 studyCount : studyCount, 99 publishedPublicStudyCount : publishedPublicStudyCount, 100 unPublishedPublicStudyCount : unPublishedPublicStudyCount, 101 publicStudyCount : publicStudyCount, 102 publishedPrivateStudyCount : publishedPrivateStudyCount, 103 unPublishedPrivateStudyCount: unPublishedPrivateStudyCount, 104 privateStudyCount : privateStudyCount, 105 readOnlyStudyCount : readOnlyStudyCount, 106 readWriteStudyCount : readableAndWritableStudyCount, 107 noAccessStudyCount : noAccessStudyCount, 108 readableTemplates : org.dbnp.gdt.Template.count(), 109 110 // miscelaneous 111 facebookLikeUrl : '/' 112 ] 113 } 114 115 def ajaxQuickSearch = { 116 def query = params.name_startsWith 117 def result = [ total: 0, data: [] ] 118 def user = authenticationService.getLoggedInUser() 119 120 // search studies 121 Study.createCriteria().list { 122 or { 123 ilike("title", "%${query}%") 124 ilike("description", "%${query}%") 125 eq("owner", user) 126 writers { 127 eq("id", user.id) 128 } 129 and { 130 readers { 131 eq("id", user.id) 132 } 133 eq("published", true) 134 } 135 } 136 }.each { study -> 137 result.data << [ 138 link : createLink(controller:'study', action:'show', id:study.id), 139 name : "${study.title}", 140 category : 'Study' 141 ] 142 } 143 144 // search templates 145 Template.createCriteria().list { 146 or { 147 ilike("name", "%${query}%") 148 ilike("description", "%${query}%") 149 } 150 }.each { template -> 151 def entityName = template.entity.toString().split(/\./) 152 def encodedEntity = gdtService.encryptEntity(template.entity.toString()).decodeURL() 153 154 result.data << [ 155 link : createLink(controller:'templateEditor', action:'template', params:[entity:encodedEntity, standalone:true, template:template.id]), 156 name : "${template.name}", 157 category : "${entityName[entityName.size()-1]} Template" 158 ] 159 } 160 161 // set total 162 result.total = result.data.size() 163 164 // render result 165 if (params.callback) { 166 render "${params.callback}(${result as JSON})" 167 } else { 168 render result as JSON 169 } 170 } 27 171 } -
trunk/grails-app/controllers/dbnp/query/SimpleQueryController.groovy
r1473 r1584 16 16 17 17 import dbnp.data.* 18 import dbnp.studycapturing. Study19 import dbnp.studycapturing.Assay18 import dbnp.studycapturing.* 19 import org.dbnp.gdt.* 20 20 import org.compass.core.engine.SearchEngineQueryParseException 21 21 import dbnp.rest.common.CommunicationManager -
trunk/grails-app/domain/dbnp/authentication/SecUser.groovy
r1430 r1584 42 42 return getAuthorities().contains(SecRole.findByAuthority('ROLE_ADMIN')); 43 43 } 44 45 44 } -
trunk/grails-app/domain/dbnp/studycapturing/Study.groovy
r1571 r1584 520 520 521 521 /** 522 * Returns the number of public studies 523 * @return int 524 */ 525 public static countPublicStudies() { return countPublicStudies(true) } 526 public static countPublicStudies(boolean published) { 527 def c = Study.createCriteria() 528 return c.count { 529 and { 530 eq("published", published) 531 eq("publicstudy", true) 532 } 533 } 534 } 535 536 /** 537 * Returns the number of private studies 538 * @return int 539 */ 540 public static countPrivateStudies() { return countPrivateStudies(false) } 541 public static countPrivateStudies(boolean published) { 542 def c = Study.createCriteria() 543 return c.count { 544 and { 545 eq("publicstudy", false) 546 } 547 or { 548 eq("published", published) 549 eq("publicstudy", true) 550 } 551 } 552 } 553 554 /** 522 555 * Returns the number of studies that are readable by the given user 523 556 */ … … 525 558 def c = Study.createCriteria() 526 559 527 // Administrators are allowed to read everything560 // got a user? 528 561 if (user == null) { 529 562 return c.count { … … 534 567 } 535 568 } else if (user.hasAdminRights()) { 536 return Study.count(); 569 // Administrators are allowed to read everything 570 return Study.count() 537 571 } else { 538 572 return c.count { … … 554 588 555 589 /** 590 * Returns the number of studies that are readable & writable by the given user 591 */ 592 public static countReadableAndWritableStudies(SecUser user) { 593 def c = Study.createCriteria() 594 595 // got a user? 596 if (user == null) { 597 return 0 598 } else if (user.hasAdminRights()) { 599 return Study.count() 600 } else { 601 return c.count { 602 or { 603 eq("owner", user) 604 writers { 605 eq("id", user.id) 606 } 607 } 608 } 609 } 610 } 611 612 /** 556 613 * Returns the UUID of this study and generates one if needed 557 614 */ -
trunk/grails-app/views/home/index.gsp
r1430 r1584 5 5 <meta property="og:description" content="A generic tool for planning scientific studies, and capturing study meta-data, integrating with analysis platform(s) / LIMS systems and searching relevant studies."/> 6 6 <meta name="layout" content="main"/> 7 <script type="text/javascript" src="${resource(dir: 'js', file: 'highcharts.js')}"></script> 8 <script type="text/javascript" src="${resource(dir: 'js', file: 'jquery.ui.autocomplete.html.js', plugin: 'gdt')}"></script> 9 <script type="text/javascript"> 10 Highcharts.theme = { colors: ['#4572A7'] }; 11 var highchartsOptions = Highcharts.getOptions(); 12 var studiesPieChart, dailyStatistics; 13 14 $(document).ready(function() { 15 studiesPieChart = new Highcharts.Chart({ 16 chart: { 17 renderTo: 'studies-pie', 18 plotBackgroundColor: null, 19 plotBorderWidth: null, 20 plotShadow: false 21 }, 22 title: { 23 text: '${studyCount} Studies' 24 }, 25 tooltip: { 26 formatter: function() { 27 return '<b>' + this.point.name + '</b>: ' + this.y + ' ' + ((this.y == 1) ? 'study' : 'studies'); 28 } 29 }, 30 plotOptions: { 31 pie: { 32 allowPointSelect: true, 33 cursor: 'pointer', 34 dataLabels: { 35 enabled: true, 36 color: Highcharts.theme.textColor || '#000000', 37 connectorColor: Highcharts.theme.textColor || '#000000', 38 formatter: function() { 39 return '<b>' + this.point.name + '</b>: ' + this.y + ' ' + ((this.y == 1) ? 'study' : 'studies'); 40 } 41 } 42 } 43 }, 44 series: [ 45 { 46 type: 'pie', 47 name: 'Your statistics',<sec:ifLoggedIn> 48 size: '45%', 49 innerSize: '25%', 50 </sec:ifLoggedIn><sec:ifNotLoggedIn> 51 innerSize: '45%', 52 </sec:ifNotLoggedIn> 53 data: [ 54 { name: 'Public', y: ${publicStudyCount}, color: '#89A54E' }, 55 { name: 'Private', y: ${privateStudyCount}, color: '#AA4643' } 56 ], 57 dataLabels: { 58 enabled: <sec:ifLoggedIn>false</sec:ifLoggedIn><sec:ifNotLoggedIn>true</sec:ifNotLoggedIn>, 59 } 60 }, 61 { 62 type: 'pie', 63 name: 'Your statistics',<sec:ifLoggedIn> 64 size: '25%', 65 innerSize: '10%', 66 </sec:ifLoggedIn><sec:ifNotLoggedIn> 67 size: '45%', 68 </sec:ifNotLoggedIn> 69 data: [ 70 { name: 'Published public', y: ${publishedPublicStudyCount}, color: '#89A54E' }, 71 { name: 'Unpublished Public', y: ${unPublishedPublicStudyCount}, color: '#bbc695' }, 72 { name: 'Published Private', y: ${publishedPrivateStudyCount}, color: '#AA4643' }, 73 { name: 'Unpublished Private', y: ${unPublishedPrivateStudyCount}, color: '#ae6e6c' } 74 ], 75 dataLabels: { 76 enabled: false 77 } 78 } 79 <sec:ifLoggedIn> 80 , 81 { 82 type: 'pie', 83 name: 'Total statistics', 84 85 innerSize: '45%', 86 data: [ 87 { name: 'Read only', y: ${readOnlyStudyCount}, color: '#80699B' }, 88 { name: 'Readable & writable', y: ${readWriteStudyCount}, color: '#89A54E' }, 89 { name: 'Not accessible', y: ${noAccessStudyCount}, color: '#AA4643' } 90 ], 91 dataLabels: { 92 enabled: true 93 } 94 }, 95 </sec:ifLoggedIn> 96 ] 97 }); 98 99 <g:if test="${startDate && dailyStatistics?.size()}"> 100 dailyStatistics = new Highcharts.Chart({ 101 chart: { 102 renderTo: 'daily-statistics', 103 zoomType: 'x', 104 spacingRight: 20 105 }, 106 title: { 107 text: 'Users, studies and templates' 108 }, 109 subtitle: { 110 text: document.ontouchstart === undefined ? 111 'Click and drag in the plot area to zoom in' : 112 'Drag your finger over the plot to zoom in' 113 }, 114 xAxis: { 115 type: 'datetime', 116 maxZoom: 14 * 24 * 3600000, // fourteen days 117 title: { 118 text: null 119 } 120 }, 121 yAxis: { 122 title: { 123 text: 'Total' 124 }, 125 min: 0, 126 startOnTick: false, 127 showFirstLabel: false 128 }, 129 tooltip: { 130 shared: true 131 }, 132 legend: { 133 enabled: false 134 }, 135 plotOptions: { 136 area: { 137 138 lineWidth: 1, 139 marker: { 140 enabled: false, 141 states: { 142 hover: { 143 enabled: true, 144 radius: 5 145 } 146 } 147 }, 148 shadow: false, 149 states: { 150 hover: { 151 lineWidth: 1 152 } 153 } 154 } 155 }, 156 157 series: [ 158 { 159 type: 'area', 160 name: 'Studies', 161 pointInterval: 24 * 3600 * 1000, 162 pointStart: Date.UTC(${startDate.year+1900}, ${startDate.month}, ${startDate.date}), 163 data: [ 164 <g:each var="day" in="${dailyStatistics}">${day.value.studyTotal},</g:each> 165 ] 166 }, 167 { 168 type: 'area', 169 name: 'Templates', 170 pointInterval: 24 * 3600 * 1000, 171 pointStart: Date.UTC(${startDate.year+1900}, ${startDate.month}, ${startDate.date}), 172 data: [ 173 <g:each var="day" in="${dailyStatistics}">${day.value.templateTotal},</g:each> 174 ] 175 }, 176 { 177 type: 'area', 178 name: 'Users', 179 pointInterval: 24 * 3600 * 1000, 180 pointStart: Date.UTC(${startDate.year+1900}, ${startDate.month}, ${startDate.date}), 181 data: [ 182 <g:each var="day" in="${dailyStatistics}">${day.value.userTotal},</g:each> 183 ] 184 } 185 ] 186 }); 187 </g:if> 188 189 $("#search_term").autocomplete({ 190 source: function(request, response) { 191 $.ajax({ 192 //url: "http://ws.geonames.org/searchJSON", 193 url: "${createLink(action:'ajaxQuickSearch')}", 194 dataType: "jsonp", 195 data: { 196 featureClass: "P", 197 style: "full", 198 maxRows: 12, 199 name_startsWith: request.term 200 }, 201 success: function(data) { 202 response($.map(data.data, function(item) { 203 return { 204 label : '<span class="about">'+item.category+'</div> <span class="from">'+item.name+'</span>', 205 value : item.link 206 } 207 })); 208 } 209 }); 210 }, 211 minLength: 2, 212 select: function(event, ui) { 213 // redirect 214 window.location = ui.item.value; 215 }, 216 open: function() { 217 $(this).removeClass("ui-corner-all").addClass("ui-corner-top"); 218 }, 219 close: function() { 220 $(this).removeClass("ui-corner-top").addClass("ui-corner-all"); 221 }, 222 html: true 223 }); 224 }); 225 </script> 226 <style type="text/css"> 227 #simpleQuery { 228 } 229 230 #simpleQuery .search { 231 display: block; 232 height: 30px; 233 margin-bottom: 10px; 234 zoom: 1; /* IE 6 & 7 hack */ 235 *display: inline; /* IE 6 & 7 hack */ 236 } 237 238 #simpleQuery .search .begin { 239 margin: 0px; 240 padding: 0px; 241 display: inline-block; 242 background-image: url(${resource(dir: 'images', file: 'simpleQuery/spotlight-begin.png')}); 243 height: 30px; 244 width: 140px; 245 vertical-align: top; 246 text-align: right; 247 zoom: 1; /* IE 6 & 7 hack */ 248 *display: inline; /* IE 6 & 7 hack */ 249 } 250 251 #simpleQuery .search .begin .label { 252 color: #fff; 253 font-face: Arial; 254 line-height: 30px; 255 text-shadow: 0px 0px 1px #006DBA; 256 font-size: 12px; 257 margin-right: 23px; 258 } 259 260 #simpleQuery .search .middle { 261 margin: 0px 0px -20px 0px; 262 padding: 0; 263 display: inline-block; 264 background-image: url(${resource(dir: 'images', file: 'simpleQuery/spotlight-middle.png')}); 265 height: 30px; 266 width: 300px; 267 vertical-align: top; 268 zoom: 1; /* IE 6 & 7 hack */ 269 *display: inline; /* IE 6 & 7 hack */ 270 } 271 272 #simpleQuery .search .searchfield { 273 vertical-align: middle; 274 width: 100%; 275 height: 100%; 276 color: #006DBA; 277 border-width: 0px; 278 border: none; 279 background-color: Transparent; 280 zoom: 1; /* IE 6 & 7 hack */ 281 *display: inline; /* IE 6 & 7 hack */ 282 } 283 284 #simpleQuery .search .end { 285 margin: 0px; 286 padding: 0px; 287 display: inline-block; 288 background-image: url(${resource(dir: 'images', file: 'simpleQuery/spotlight-end.png')}); 289 height: 30px; 290 width: 28px; 291 zoom: 1; /* IE 6 & 7 hack */ 292 *display: inline; /* IE 6 & 7 hack */ 293 } 294 295 </style> 7 296 </head> 8 297 <body> 9 298 10 <g:if env="dbnpdemo"><g:render template="/common/demo_intro"/></g:if> 299 <div style="clear:both;display:block;padding-top:10px;"> 300 <div style="margin:2px;width:476px;display:inline-block;float:left;zoom:1;*display:inline;"> 301 <h1>Lorem ipsum 1</h1> 302 Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut tincidunt auctor suscipit. Nam ultricies condimentum pulvinar. In magna orci, eleifend sit amet tincidunt eget, ultricies a justo. Vestibulum purus lorem, laoreet sit amet rutrum et, sollicitudin eget augue. Nulla consequat, mauris eget ornare fringilla, arcu enim mattis odio, rhoncus rutrum ante turpis vitae nulla. Sed et turpis vel urna venenatis sagittis. Sed sagittis vestibulum felis, vel ultricies tellus dictum ac. Nunc non massa et ligula gravida rutrum. Fusce porttitor, eros ac dictum suscipit, risus lacus aliquam justo, ut lobortis erat nulla sit amet risus. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Suspendisse fermentum ultricies ipsum, at consequat elit pharetra auctor. 303 </div> 304 <div style=""> 305 <h1>Quicksearch</h1> 306 <div id="simpleQuery" class="simplequery"> 307 <g:form action="pages" name="simpleQueryForm" id="simpleQueryForm"> 308 <g:if test="${search_term}"><g:set var="preterm" value="${search_term}"/></g:if> 309 <div class="searchContainer"> 310 <div class="search"> 311 <div class="begin"><span class="label">Search term</span></div><div class="middle"><g:textField name="search_term" id="search_term" class="searchfield" value="${preterm}"/></div><div class="end"><a onClick="$('#search_term').val('');"><img src="${resource(dir: 'images', file: 'simpleQuery/spotlight-end.png')}" value="Reset" alt="Reset" border="0"></a></div> 312 </div> 313 </div> 314 </g:form> 315 <h1>Lorem ipsum 2</h1> 316 Vivamus varius ullamcorper neque, sit amet mollis lacus accumsan vel. Pellentesque in augue a arcu pretium egestas vel at elit. Duis nunc odio, mollis et faucibus vel, aliquam vel quam. Sed laoreet pharetra urna, venenatis porttitor neque sagittis et. Aenean at nisl nunc, in mattis mauris. Proin iaculis nunc in erat rhoncus consectetur. Nullam sit amet risus vitae eros condimentum pellentesque. Vestibulum sollicitudin turpis id felis viverra a bibendum magna varius. Ut tristique pellentesque convallis. Maecenas id sollicitudin lacus. 317 </div> 318 </div> 319 </div> 320 321 322 <div style="clear:both;display:block;padding-top:10px;"> 323 <h1>Usage Statistics</h1> 324 <div id="graphs" style="display:block;border:1px solid #6c6f70;width:100%;height:300px;"> 325 <div id="studies-pie" style="margin:2px;width:476px;height:296px;display:inline-block;float:left;zoom:1;*display:inline;"></div> 326 <div id="daily-statistics" style="margin:2px;width:476px;height:296px;display:inline-block;float:left;zoom:1;*display:inline;"></div> 327 </div> 328 </div> 11 329 12 330 </body> -
trunk/grails-app/views/layouts/main.gsp
r1501 r1584 20 20 <script type="text/javascript" src="${resource(dir: 'js', file: 'login_panel.js')}"></script> 21 21 <script type="text/javascript" src="${resource(dir: 'js', file: 'topnav.js')}"></script> 22 < g:if env="development"><script type="text/javascript" src="${resource(dir: 'js', file: 'development.js')}"></script></g:if>22 <!--<g:if env="development"><script type="text/javascript" src="${resource(dir: 'js', file: 'development.js')}"></script></g:if>//--> 23 23 24 24 <!-- Scripts for pagination using dataTables --> … … 45 45 <div id="footer"> 46 46 Copyright © 2008 - <g:formatDate format="yyyy" date="${new Date()}"/> NuGO, NMC and NBIC. All rights reserved. For more information go to <a href="http://dbnp.org">http://dbnp.org</a>. 47 <g:if env="development">( style: <%=session.style%> )</g:if>48 47 </div> 49 <img src="${resource(dir: 'images', file: 'beta-stamp.png')}" alt="beta">50 48 </div> 51 49 </body>
Note: See TracChangeset
for help on using the changeset viewer.