From: Alexandre Terrasa Date: Thu, 30 Jun 2016 02:34:53 +0000 (-0400) Subject: nitweb: introduce feedback API for star rating system X-Git-Url: http://nitlanguage.org nitweb: introduce feedback API for star rating system Signed-off-by: Alexandre Terrasa --- diff --git a/src/nitweb.nit b/src/nitweb.nit index 3897c5c..af58044 100644 --- a/src/nitweb.nit +++ b/src/nitweb.nit @@ -60,6 +60,11 @@ private class NitwebPhase 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 @@ -67,7 +72,7 @@ private class NitwebPhase 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) @@ -91,6 +96,9 @@ class APIRouter # 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)) @@ -101,6 +109,7 @@ class APIRouter 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)) diff --git a/src/web/api_feedback.nit b/src/web/api_feedback.nit new file mode 100644 index 0000000..61ba756 --- /dev/null +++ b/src/web/api_feedback.nit @@ -0,0 +1,150 @@ +# 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 diff --git a/src/web/web.nit b/src/web/web.nit index 4dd39b5..c6bb476 100644 --- a/src/web/web.nit +++ b/src/web/web.nit @@ -19,3 +19,4 @@ import api_model import api_catalog import api_graph import api_docdown +import api_feedback