Add discrete stars rating system in top right corner of each documentation card.
Can be seen here: http://nitweb.moz-code.org/doc/core::Array
Pull-Request: #2215
Reviewed-by: Jean Privat <jean@pryen.org>
<div class='card' ng-if='mentity.mdoc'>
<div class='card-body'>
+ <div class='pull-right'>
+ <entity-rating mentity='mentity' />
+ </div>
<div ng-bind-html='mentity.mdoc.html_documentation'></div>
</div>
</div>
--- /dev/null
+<span class='stars' ng-repeat='star in [1, 2, 3, 4, 5]' ng-if='ratings' title='mean: {{ratings.mean}} ({{ratings.ratings.length}} stars)'>
+ <span
+ class='star glyphicon'
+ ng-class='star <= ratings.mean? "glyphicon-star": "glyphicon-star-empty"'
+ ng-click='postStar(star)' />
+</span>
}
};
}])
+
+ .directive('entityRating', ['Feedback', function(Feedback, Code) {
+ return {
+ restrict: 'E',
+ scope: {
+ mentity: '='
+ },
+ templateUrl: '/directives/entity/stars.html',
+ link: function ($scope, element, attrs) {
+ $scope.postStar = function(rating) {
+ Feedback.postEntityStar($scope.mentity.full_name, rating,
+ function(data) {
+ $scope.ratings = data;
+ }, function(err) {
+ $scope.err = err;
+ });
+ }
+
+ Feedback.loadEntityStars($scope.mentity.full_name,
+ function(data) {
+ $scope.ratings = data;
+ }, function(err) {
+ $scope.err = err;
+ });
+ }
+ };
+ }])
})();
}
}])
+ .factory('Feedback', [ '$http', function($http) {
+ return {
+ loadEntityStars: function(id, cb, cbErr) {
+ $http.get(apiUrl + '/feedback/stars/' + id)
+ .success(cb)
+ .error(cbErr);
+ },
+ postEntityStar: function(id, rating, cb, cbErr) {
+ $http.post(apiUrl + '/feedback/stars/' + id, {rating: rating})
+ .success(cb)
+ .error(cbErr);
+ }
+ }
+ }])
+
.factory('DocDown', [ '$http', function($http) {
return {
postMarkdown: function(md, cb, cbErr) {
margin-top: 8px;
margin-bottom: 0px;
}
+
+/*
+ * Ratings
+ */
+
+.card .stars {
+ visibility: hidden
+}
+
+.card:hover .stars {
+ visibility: visible
+}
+
+.star {
+ color: grey;
+ cursor: pointer;
+}
+
+.star:hover, .star.active:hover {
+ color: #FF8100
+}
+
+.star.active {
+ color: #FFC000
+}
+
/*
* Users
*/
<div class='tab-content'>
<div role='tabpanel' class='tab-pane fade in active' id='doc'>
- <entity-doc mentity='mentity.intro'/>
+ <entity-doc mentity='mentity'/>
<entity-list list-title='Parents'
list-entities='mentity.parents'
<div class='tab-content'>
<div role='tabpanel' class='tab-pane fade in active' id='doc'>
- <entity-doc mentity='mentity.intro'/>
+ <entity-doc mentity='mentity'/>
</div>
<div role='tabpanel' class='tab-pane fade' id='linearization'>
<entity-linearization
catalog.package_page(mpackage)
end
+ # Prepare mongo connection
+ var mongo = new MongoClient("mongodb://localhost:27017/")
+ var db = mongo.database("nitweb")
+ var collection = db.collection("stars")
+
# Run the server
var host = toolcontext.opt_host.value or else "localhost"
var port = toolcontext.opt_port.value
var app = new App
app.use_before("/*", new RequestClock)
- app.use("/api", new APIRouter(model, modelbuilder, mainmodule, catalog))
+ app.use("/api", new APIRouter(model, modelbuilder, mainmodule, catalog, collection))
app.use("/*", new StaticHandler(toolcontext.share_dir / "nitweb", "index.html"))
app.use_after("/*", new ConsoleLog)
# Catalog to pass to handlers.
var catalog: Catalog
+ # Mongo collection used to store ratings.
+ var collection: MongoCollection
+
init do
use("/catalog", new APICatalogRouter(model, mainmodule, catalog))
use("/list", new APIList(model, mainmodule))
use("/uml/:id", new APIEntityUML(model, mainmodule))
use("/linearization/:id", new APIEntityLinearization(model, mainmodule))
use("/defs/:id", new APIEntityDefs(model, mainmodule))
+ use("/feedback/", new APIFeedbackRouter(model, mainmodule, collection))
use("/inheritance/:id", new APIEntityInheritance(model, mainmodule))
use("/graph/", new APIGraphRouter(model, mainmodule))
use("/docdown/", new APIDocdown(model, mainmodule, modelbuilder))
--- /dev/null
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Feedback related features
+module api_feedback
+
+import web_base
+import mongodb
+
+# Group all api handlers in one router
+class APIFeedbackRouter
+ super Router
+
+ # Model to pass to handlers
+ var model: Model
+
+ # Mainmodule to pass to handlers
+ var mainmodule: MModule
+
+ # Mongo collection used to store ratings
+ var collection: MongoCollection
+
+ init do
+ use("/stars/:id", new APIStars(model, mainmodule, collection))
+ end
+end
+
+# Stars attributed to mentities
+class APIStars
+ super APIHandler
+
+ # Collection used to store ratings
+ var collection: MongoCollection
+
+ redef fun get(req, res) do
+ var mentity = mentity_from_uri(req, res)
+ if mentity == null then
+ res.error 404
+ return
+ end
+
+ res.json mentity_ratings(mentity)
+ end
+
+ redef fun post(req, res) do
+ var mentity = mentity_from_uri(req, res)
+ if mentity == null then
+ res.error 404
+ return
+ end
+ var obj = req.body.parse_json
+ if not obj isa JsonObject then
+ res.error 400
+ return
+ end
+ var rating = obj["rating"]
+ if not rating isa Int then
+ res.error 400
+ return
+ end
+
+ var val = new MEntityRating(mentity.full_name, rating, get_time)
+ collection.insert(val.json)
+
+ res.json mentity_ratings(mentity)
+ end
+
+ # Get the ratings of a `mentity`
+ fun mentity_ratings(mentity: MEntity): MEntityRatings do
+ var ratings = new MEntityRatings(mentity)
+
+ var req = new JsonObject
+ req["mentity"] = mentity.full_name
+ var rs = collection.find_all(req)
+ for r in rs do ratings.ratings.add new MEntityRating.from_json(r)
+ return ratings
+ end
+end
+
+# Ratings representation for a mentity
+class MEntityRatings
+ super Jsonable
+
+ # MEntity rated
+ var mentity: MEntity
+
+ # List of ratings
+ var ratings = new Array[MEntityRating]
+
+ # Mean of all ratings or 0
+ fun mean: Float do
+ if ratings.is_empty then return 0.0
+ var sum = 0.0
+ for r in ratings do sum += r.rating.to_f
+ var res = sum / ratings.length.to_f
+ return res
+ end
+
+ # Json representation of `self`
+ fun json: JsonObject do
+ var obj = new JsonObject
+ obj["mentity"] = mentity.full_name
+ obj["ratings"] = new JsonArray.from(ratings)
+ obj["mean"] = mean
+ return obj
+ end
+
+ redef fun to_json do return json.to_json
+end
+
+# Rating value of a MEntity
+class MEntityRating
+ super Jsonable
+
+ # MEntity this rating is about
+ var mentity: String
+
+ # Rating value (between 1 and 5)
+ var rating: Int
+
+ # Timestamp of this rating
+ var timestamp: Int
+
+ # Init this rating value from a JsonObject
+ init from_json(obj: JsonObject) do
+ init(obj["mentity"].as(String), obj["rating"].as(Int), obj["timestamp"].as(Int))
+ end
+
+ # Translate this rating value to a JsonObject
+ fun json: JsonObject do
+ var obj = new JsonObject
+ obj["mentity"] = mentity
+ obj["rating"] = rating
+ obj["timestamp"] = timestamp
+ return obj
+ end
+
+ redef fun to_json do return json.to_json
+end
# See the License for the specific language governing permissions and
# limitations under the License.
-module model_api
+module api_model
import web_base
import highlight
# Components required to build a web server about the nit model.
module web
-import model_api
+import api_model
import api_catalog
import api_graph
import api_docdown
+import api_feedback