diff --git a/vipra-backend/src/main/java/de/vipra/rest/resource/BugReportResource.java b/vipra-backend/src/main/java/de/vipra/rest/resource/BugReportResource.java deleted file mode 100644 index 3f73822f626c5fb9d07fed6f8a173657a056db3b..0000000000000000000000000000000000000000 --- a/vipra-backend/src/main/java/de/vipra/rest/resource/BugReportResource.java +++ /dev/null @@ -1,121 +0,0 @@ -package de.vipra.rest.resource; - -import java.io.IOException; -import java.net.URI; -import java.net.URISyntaxException; -import java.util.List; - -import javax.servlet.ServletContext; -import javax.ws.rs.Consumes; -import javax.ws.rs.DefaultValue; -import javax.ws.rs.GET; -import javax.ws.rs.POST; -import javax.ws.rs.Path; -import javax.ws.rs.PathParam; -import javax.ws.rs.Produces; -import javax.ws.rs.QueryParam; -import javax.ws.rs.core.Context; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.UriInfo; - -import org.bson.types.ObjectId; - -import de.vipra.rest.Messages; -import de.vipra.rest.model.APIError; -import de.vipra.rest.model.ResponseWrapper; -import de.vipra.util.Config; -import de.vipra.util.MongoUtils; -import de.vipra.util.StringUtils; -import de.vipra.util.ex.ConfigException; -import de.vipra.util.ex.DatabaseException; -import de.vipra.util.model.BugReport; -import de.vipra.util.service.MongoService; -import de.vipra.util.service.QueryBuilder; - -@Path("bugreports") -public class BugReportResource { - - @Context - UriInfo uri; - - final MongoService<BugReport, ObjectId> dbBugReports; - - public BugReportResource(@Context final ServletContext servletContext) throws ConfigException, IOException { - final Config config = Config.getConfig(); - dbBugReports = MongoService.getDatabaseService(config, BugReport.class); - } - - @GET - @Produces(MediaType.APPLICATION_JSON) - public Response getBugReports(@QueryParam("skip") final Integer skip, @QueryParam("limit") final Integer limit, - @QueryParam("sort") @DefaultValue("id") final String sortBy, @QueryParam("fields") final String fields) { - final ResponseWrapper<List<BugReport>> res = new ResponseWrapper<>(); - - if (res.hasErrors()) - return res.badRequest(); - - try { - final QueryBuilder query = QueryBuilder.builder().skip(skip).limit(limit).sortBy(sortBy); - if (fields != null && !fields.isEmpty()) - query.fields(true, StringUtils.getFields(fields)); - - final List<BugReport> bugReports = dbBugReports.getMultiple(query); - - if ((skip != null && skip > 0) || (limit != null && limit > 0)) - res.addHeader("total", dbBugReports.count(null)); - else - res.addHeader("total", bugReports.size()); - - return res.ok(bugReports); - } catch (final Exception e) { - e.printStackTrace(); - res.addError(new APIError(Response.Status.BAD_REQUEST, "Error", e.getMessage())); - return res.badRequest(); - } - } - - @GET - @Produces(MediaType.APPLICATION_JSON) - @Consumes(MediaType.APPLICATION_JSON) - @Path("{id}") - public Response getBugReport(@PathParam("id") final String id, @QueryParam("fields") final String fields) { - final ResponseWrapper<BugReport> res = new ResponseWrapper<>(); - if (id == null || id.trim().length() == 0) { - res.addError(new APIError(Response.Status.BAD_REQUEST, "ID is empty", String.format(Messages.BAD_REQUEST, "id cannot be empty"))); - return res.badRequest(); - } - - BugReport bugReport; - try { - bugReport = dbBugReports.getSingle(MongoUtils.objectId(id), StringUtils.getFields(fields)); - } catch (final Exception e) { - e.printStackTrace(); - res.addError(new APIError(Response.Status.BAD_REQUEST, "Error", e.getMessage())); - return res.badRequest(); - } - - if (bugReport != null) { - return res.ok(bugReport); - } else { - res.addError(new APIError(Response.Status.NOT_FOUND, "Resource not found", String.format(Messages.NOT_FOUND, "bugreport", id))); - return res.notFound(); - } - } - - @POST - @Consumes(MediaType.APPLICATION_JSON) - public Response createBugReport(final BugReport bugReport) throws URISyntaxException { - final ResponseWrapper<BugReport> res = new ResponseWrapper<>(); - - try { - dbBugReports.createSingle(bugReport); - } catch (final DatabaseException e) { - e.printStackTrace(); - res.addError(new APIError(Response.Status.BAD_REQUEST, "Error", e.getMessage())); - return res.badRequest(); - } - return res.created(null, new URI(uri.getPath().toString() + "/" + bugReport.getId().toString())); - } - -} diff --git a/vipra-ui/app/html/directives/word-evolution.html b/vipra-ui/app/html/directives/word-evolution.html index 6dcd19102e43dab95462b7efbbdbe872878611ca..45655308b47a199045c9284641804bc06a74730b 100644 --- a/vipra-ui/app/html/directives/word-evolution.html +++ b/vipra-ui/app/html/directives/word-evolution.html @@ -22,17 +22,20 @@ <div class="checkbox checkbox-condensed" ng-class="{selected:word.selected}"> <input tabindex="0" type="checkbox" ng-model="word.selected" ng-attr-id="{{::word.id}}" ng-change="redrawWordEvolutionChart()"> <label class="check" ng-attr-for="{{::word.id}}"> - <word-link word="::word" /> + <topic-menu topic="topic" class="menu-button" /> + <span class="ellipsis"> + <word-link word="::word" /> + </span> </label> + <span class="colorbox" style="background:{{::word.color}}"></span> </div> </li> </ul> </div> <div class="center message-container"> <div class="wrapper"> - <div class="chart area-chart" ng-attr-id="{{chartId}}" highcharts="topicWord"></div> + <div class="chart area-chart" ng-attr-id="{{chartId}}" highcharts="wordEvolution"></div> </div> </div> </div> - <div class="message text-muted" ng-show="!topic">No topic selected</div> </div> \ No newline at end of file diff --git a/vipra-ui/app/html/explorer.html b/vipra-ui/app/html/explorer.html index cac01643041796509050bdbeb7bd8c3161d1d8b3..8a95b5f7ff7d249d04df700c585d115159eb35db 100644 --- a/vipra-ui/app/html/explorer.html +++ b/vipra-ui/app/html/explorer.html @@ -106,7 +106,7 @@ <div role="tabpanel" class="tab-pane active tab-evolution"> <word-evolution topic="explorerModels.activeTopic"/> </div> - <div role="tabpanel" class="tab-pane active tab-articles auto-overflow"> + <div role="tabpanel" class="tab-pane tab-articles auto-overflow"> <div class="panel panel-default"> <div class="topbar"> <small>Sequence:</small> diff --git a/vipra-ui/app/index.html b/vipra-ui/app/index.html index 5227e8708a65a9f1130f314c7554dabe871f74ca..82f20d7e6dce05a87709c201764077a0985356e9 100644 --- a/vipra-ui/app/index.html +++ b/vipra-ui/app/index.html @@ -63,11 +63,6 @@ <li ng-class="{'text-italic active':rootModels.topicModel}"> <a tabindex="0" ng-click="chooseTopicModel()" ng-bind-template="{{rootModels.topicModel ? rootModels.topicModel.id : 'Models'}}" ng-attr-title="{{rootModels.topicModel.modelConfig.description}}"></a> </li> - <li title="Report a bug"> - <a tabindex="0" ng-click="reportBug()"> - <i class="fa fa-bug text-danger"></i> - </a> - </li> <li title="Keyboard cheatsheet"> <a tabindex="0" ng-click="showCheatSheet()"> <i class="fa fa-keyboard-o"></i> @@ -128,51 +123,6 @@ </div> </div> </div> - <div id="bugReportModal" class="modal" tabindex="-1" role="dialog" data-backdrop="static" data-keyboard="false" ng-controller="BugReportController"> - <div class="modal-dialog modal-lg"> - <div class="modal-content"> - <div class="modal-header"> - <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> - <h4 class="modal-title">Report a bug</h4> - </div> - <div class="modal-body"> - <form class="form-horizontal" name="bugReportForm"> - <div class="form-group"> - <div class="col-sm-offset-2 col-sm-10"> - <div class="checkbox"> - <input tabindex="0" type="checkbox" ng-model="bug.reproducible" id="reproducible"> - <label class="check" for="reproducible">Bug is reproducible</label> - </div> - </div> - </div> - <div class="form-group"> - <label for="description" class="col-sm-2 control-label">Description</label> - <div class="col-sm-10"> - <textarea class="form-control resize-vertical" id="description" rows="10" placeholder="Describe the bug..." ng-model="bug.description" autofocus></textarea> - </div> - </div> - <div class="form-group"> - <label class="col-sm-2 control-label">Screenshot</label> - <div class="col-sm-10"> - <div class="input-group"> - <span class="input-group-btn"> - <span class="btn btn-primary btn-file"> - Browse… <input type="file" id="bugScreenshot" accept="image/*"> - </span> - </span> - <input type="text" class="form-control readonly-white" readonly> - </div> - </div> - </div> - </form> - </div> - <div class="modal-footer"> - <button type="button" class="btn btn-default" data-dismiss="modal" ng-click="clear()">Close</button> - <button type="button" class="btn btn-primary" ng-click="sendBugReport()" ng-disabled="!bug.description">Report</button> - </div> - </div> - </div> - </div> <div class="alerts"> <bs-alert ng-model="alert" type="alert.type" ng-repeat="alert in alerts"/> </div> diff --git a/vipra-ui/app/js/controllers.js b/vipra-ui/app/js/controllers.js index cf0929cce76444eb108c01dcc8b18ae1486296a0..cb1934d3c46398e3a249d7e81d07418e80de0f6d 100644 --- a/vipra-ui/app/js/controllers.js +++ b/vipra-ui/app/js/controllers.js @@ -56,10 +56,6 @@ localStorage.tm = topicModel.id; }; - $scope.reportBug = function() { - $('#bugReportModal').modal(); - }; - $scope.menubarSearch = function(query) { $state.transitionTo('index', { q: query @@ -539,8 +535,7 @@ }, function(data) { $scope.topics = data; var colors = randomColor({ - count: $scope.topics.length, - seed: 1 + count: $scope.topics.length }); for (var i = 0, t; i < $scope.topics.length; i++) { t = $scope.topics[i]; @@ -574,7 +569,6 @@ delete $scope.explorerModels.activeTopic; delete $scope.explorerModels.activeSequence; } - $scope.redrawGraph(); }; @@ -1470,29 +1464,45 @@ }; $scope.redrawWordEvolutionChart = function() { - if (!$scope.topic || !$scope.topic.words || !$scope.topic.sequences) return; var evolutions = []; - - // create series - for (var i = 0, word, probs; i < $scope.topic.words.length; i++) { - word = $scope.topic.words[i]; - if (!word.selected) continue; - probs = []; - for (var j = 0, prob; j < word.sequenceProbabilities.length; j++) { - prob = $scope.wordSeqstyle === 'relative' ? word.sequenceProbabilitiesChange[j] : word.sequenceProbabilities[j]; - probs.push([new Date($scope.topic.sequences[j].window.startDate).getTime(), prob]); + if ($scope.topic && $scope.topic.words && $scope.topic.sequences) { + + // create series + for (var i = 0, word, probs; i < $scope.topic.words.length; i++) { + word = $scope.topic.words[i]; + if (!word.selected) continue; + probs = []; + for (var j = 0, prob; j < word.sequenceProbabilities.length; j++) { + prob = $scope.wordSeqstyle === 'relative' ? word.sequenceProbabilitiesChange[j] : word.sequenceProbabilities[j]; + probs.push([new Date($scope.topic.sequences[j].window.startDate).getTime(), prob]); + } + evolutions.push({ + name: word.id, + color: word.color, + data: probs + }); } - evolutions.push({ - name: word.id, - data: probs - }); } - $scope.topicWord = areaRelevanceChart(evolutions, 'Word Evolution', $scope.wordChartstyle); + $scope.wordEvolution = areaRelevanceChart(evolutions, 'Word Evolution', $scope.wordChartstyle); $scope.wordsSelected = evolutions.length; }; $scope.$watchGroup(['wordSeqstyle', 'wordChartstyle', 'topic'], $scope.redrawWordEvolutionChart); + + $scope.$watch('topic', function() { + if($scope.topic) { + var colors = randomColor({ + count: $scope.topic.words.length + }); + + for (var i = 0; i < $scope.topic.words.length; i++) { + $scope.topic.words[i].color = colors[i]; + } + } + + $scope.redrawWordEvolutionChart(); + }); } ]); diff --git a/vipra-ui/app/js/directives.js b/vipra-ui/app/js/directives.js index 6854967f1de3d2eb31be889ee2dd9482ad1d65fe..e84f8a019b78fd3da72e583bc7b84ae6eceea025 100644 --- a/vipra-ui/app/js/directives.js +++ b/vipra-ui/app/js/directives.js @@ -177,21 +177,13 @@ } ]); - app.directive('bsTab', ['$timeout', function($timeout) { + app.directive('bsTab', [function() { return { link: function($scope, $elem, $attrs) { - var hash = $elem.data('target').substring(1); - if(location.hash === '#' + hash) { - $timeout(function() { - $elem.tab('show'); - }, 0); - } - $elem.on('shown.bs.tab', function() { if ($attrs.shown) { $scope.$eval($attrs.shown); } - location.hash = hash; }); } }; diff --git a/vipra-ui/app/js/factories.js b/vipra-ui/app/js/factories.js index 7cb747e7f32322a41c4b79ad658d589c391df14c..514dc1cbf7d3404ab0b401d5aa47d7618accb8ff 100644 --- a/vipra-ui/app/js/factories.js +++ b/vipra-ui/app/js/factories.js @@ -84,8 +84,4 @@ return $myResource(Vipra.config.restUrl + '/entities/:id'); }]); - app.factory('BugReportFactory', ['$myResource', function($myResource) { - return $myResource(Vipra.config.restUrl + '/bugreports/:id'); - }]); - })(); \ No newline at end of file diff --git a/vipra-util/src/main/java/de/vipra/util/model/BugReport.java b/vipra-util/src/main/java/de/vipra/util/model/BugReport.java deleted file mode 100644 index bd3ba267b079a7b39064ee0e8da6e4efe56686f1..0000000000000000000000000000000000000000 --- a/vipra-util/src/main/java/de/vipra/util/model/BugReport.java +++ /dev/null @@ -1,106 +0,0 @@ -package de.vipra.util.model; - -import java.io.Serializable; -import java.util.Date; - -import org.bson.types.ObjectId; -import org.mongodb.morphia.annotations.Entity; -import org.mongodb.morphia.annotations.Id; -import org.mongodb.morphia.annotations.PrePersist; - -import de.vipra.util.an.QueryIgnore; - -@SuppressWarnings("serial") -@Entity(value = "bugreport", noClassnameStored = true) -public class BugReport implements Model<ObjectId>, Serializable { - - @Id - private ObjectId id = new ObjectId(); - - @QueryIgnore(multi = true) - private String route; - - @QueryIgnore(multi = true) - private String userAgent; - - @QueryIgnore(multi = true) - private String description; - - @QueryIgnore(multi = true) - private Boolean reproducible; - - @QueryIgnore(multi = true) - private Date created; - - @QueryIgnore(multi = true) - private Date modified; - - @QueryIgnore(multi = true) - private String screenshot; - - @Override - public ObjectId getId() { - return id; - } - - @Override - public void setId(final ObjectId id) { - this.id = id; - } - - public String getRoute() { - return route; - } - - public void setRoute(final String route) { - this.route = route; - } - - public String getUserAgent() { - return userAgent; - } - - public void setUserAgent(final String userAgent) { - this.userAgent = userAgent; - } - - public String getDescription() { - return description; - } - - public void setDescription(final String description) { - this.description = description; - } - - public Boolean isReproducible() { - return reproducible; - } - - public void setReproducible(final Boolean reproducible) { - this.reproducible = reproducible; - } - - public Date getCreated() { - return created; - } - - public void setCreated(final Date created) { - this.created = created; - } - - public String getScreenshot() { - return screenshot; - } - - public void setScreenshot(final String screenshot) { - this.screenshot = screenshot; - } - - @PrePersist - public void prePersist() { - modified = new Date(); - if (created == null) - created = modified; - } - -}