You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@allura.apache.org by br...@apache.org on 2020/01/06 23:05:08 UTC
[allura] branch master updated (ea34e18 -> 7f41e15)
This is an automated email from the ASF dual-hosted git repository.
brondsem pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/allura.git.
from ea34e18 [#8345] default all event tasks created within web requests & tasks, to not flush immediately, so that they flush at the end of the task/req execution in MingMiddleware with everything else
new 66a2949 [FEATURE] Added ForgeFeedback app
new a6afcf9 Added Apache license header
new 59144b6 Handled review comments
new 7f41e15 More polishing
The 4 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
Summary of changes:
Allura/allura/model/project.py | 1 +
Allura/allura/templates/jinja_master/nav_menu.html | 32 +++
.../forgefeedback}/__init__.py | 0
ForgeFeedback/forgefeedback/feedback_main.py | 250 +++++++++++++++++++++
.../forgefeedback/model}/__init__.py | 4 +-
ForgeFeedback/forgefeedback/model/feedback.py | 80 +++++++
.../forgefeedback/nf/feedback/css/feedback.css | 131 +++++++++++
.../forgefeedback/templates}/__init__.py | 0
.../templates/feedback/common_feedback.html | 92 ++++++++
.../templates/feedback/edit_feedback.html | 84 +++++++
.../templates/feedback/feedback_list.html | 100 +++++++++
.../forgefeedback/templates/feedback/index.html | 69 ++++++
.../templates/feedback/new_feedback.html | 79 +++++++
.../forgefeedback/tests}/__init__.py | 0
.../forgefeedback/tests/functional}/__init__.py | 0
.../forgefeedback/tests/functional/test_root.py | 72 ++++++
.../forgefeedback/tests/test_feedback_roles.py | 17 +-
.../forgefeedback}/tests/unit/__init__.py | 6 +-
.../forgefeedback/tests/unit/test_feedback.py | 48 ++--
.../tests/unit/test_root_controller.py | 83 +++++++
.../forgefeedback}/version.py | 2 +-
{ForgeLink => ForgeFeedback}/setup.py | 13 +-
requirements.in | 4 +-
requirements.txt | 2 +
24 files changed, 1122 insertions(+), 47 deletions(-)
copy {ForgeWiki/forgewiki/widgets => ForgeFeedback/forgefeedback}/__init__.py (100%)
mode change 100644 => 100755
create mode 100755 ForgeFeedback/forgefeedback/feedback_main.py
copy {Allura/allura/lib => ForgeFeedback/forgefeedback/model}/__init__.py (96%)
mode change 100644 => 100755
create mode 100755 ForgeFeedback/forgefeedback/model/feedback.py
create mode 100755 ForgeFeedback/forgefeedback/nf/feedback/css/feedback.css
copy {ForgeWiki/forgewiki/widgets => ForgeFeedback/forgefeedback/templates}/__init__.py (100%)
mode change 100644 => 100755
create mode 100755 ForgeFeedback/forgefeedback/templates/feedback/common_feedback.html
create mode 100755 ForgeFeedback/forgefeedback/templates/feedback/edit_feedback.html
create mode 100755 ForgeFeedback/forgefeedback/templates/feedback/feedback_list.html
create mode 100755 ForgeFeedback/forgefeedback/templates/feedback/index.html
create mode 100755 ForgeFeedback/forgefeedback/templates/feedback/new_feedback.html
copy {ForgeWiki/forgewiki/widgets => ForgeFeedback/forgefeedback/tests}/__init__.py (100%)
mode change 100644 => 100755
copy {ForgeWiki/forgewiki/widgets => ForgeFeedback/forgefeedback/tests/functional}/__init__.py (100%)
mode change 100644 => 100755
create mode 100755 ForgeFeedback/forgefeedback/tests/functional/test_root.py
copy ForgeWiki/forgewiki/tests/test_wiki_roles.py => ForgeFeedback/forgefeedback/tests/test_feedback_roles.py (77%)
mode change 100644 => 100755
copy {ForgeBlog/forgeblog => ForgeFeedback/forgefeedback}/tests/unit/__init__.py (92%)
mode change 100644 => 100755
copy Dockerfile => ForgeFeedback/forgefeedback/tests/unit/test_feedback.py (53%)
mode change 100644 => 100755
create mode 100755 ForgeFeedback/forgefeedback/tests/unit/test_root_controller.py
copy {ForgeGit/forgegit => ForgeFeedback/forgefeedback}/version.py (92%)
mode change 100644 => 100755
copy {ForgeLink => ForgeFeedback}/setup.py (91%)
mode change 100644 => 100755
[allura] 02/04: Added Apache license header
Posted by br...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
brondsem pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/allura.git
commit a6afcf94d9752707bc2464d979b2ce6c37f3015b
Author: Vrinda A <Vr...@in.bosch.com>
AuthorDate: Sat Dec 14 11:50:36 2019 +0530
Added Apache license header
---
.../forgefeedback/nf/feedback/css/feedback.css | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/ForgeFeedback/forgefeedback/nf/feedback/css/feedback.css b/ForgeFeedback/forgefeedback/nf/feedback/css/feedback.css
index 15c2f9c..f6bdedd 100644
--- a/ForgeFeedback/forgefeedback/nf/feedback/css/feedback.css
+++ b/ForgeFeedback/forgefeedback/nf/feedback/css/feedback.css
@@ -1,3 +1,22 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you 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.
+*/
+
.rating {
float:left;
}
[allura] 01/04: [FEATURE] Added ForgeFeedback app
Posted by br...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
brondsem pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/allura.git
commit 66a29498d8099d5be31c3ea201d7e3f0f7c28a64
Author: Vrinda A <Vr...@in.bosch.com>
AuthorDate: Wed Sep 25 22:44:22 2019 +0530
[FEATURE] Added ForgeFeedback app
- This app will let the user rate and review a project.
---
Allura/allura/model/project.py | 1 +
Allura/allura/templates/jinja_master/nav_menu.html | 26 +++
ForgeFeedback/forgefeedback/__init__.py | 0
ForgeFeedback/forgefeedback/feedback_main.py | 230 +++++++++++++++++++++
ForgeFeedback/forgefeedback/model/__init__.py | 21 ++
ForgeFeedback/forgefeedback/model/feedback.py | 82 ++++++++
.../forgefeedback/nf/feedback/css/feedback.css | 112 ++++++++++
ForgeFeedback/forgefeedback/templates/__init__.py | 0
.../templates/feedback/common_feedback.html | 87 ++++++++
.../templates/feedback/edit_feedback.html | 103 +++++++++
.../templates/feedback/feedback_list.html | 100 +++++++++
.../forgefeedback/templates/feedback/index.html | 56 +++++
.../templates/feedback/new_feedback.html | 79 +++++++
ForgeFeedback/forgefeedback/tests/__init__.py | 17 ++
.../forgefeedback/tests/functional/__init__.py | 17 ++
.../forgefeedback/tests/functional/test_root.py | 69 +++++++
.../forgefeedback/tests/test_feedback_roles.py | 54 +++++
ForgeFeedback/forgefeedback/tests/unit/__init__.py | 51 +++++
.../forgefeedback/tests/unit/test_feedback.py | 41 ++++
.../tests/unit/test_root_controller.py | 80 +++++++
ForgeFeedback/forgefeedback/version.py | 24 +++
ForgeFeedback/setup.py | 53 +++++
requirements.in | 4 +-
requirements.txt | 2 +
24 files changed, 1308 insertions(+), 1 deletion(-)
diff --git a/Allura/allura/model/project.py b/Allura/allura/model/project.py
index 0776e8f..5a6f896 100644
--- a/Allura/allura/model/project.py
+++ b/Allura/allura/model/project.py
@@ -251,6 +251,7 @@ class Project(SearchIndexable, MappedClass, ActivityNode, ActivityObject):
tracking_id = FieldProperty(str, if_missing='')
is_nbhd_project = FieldProperty(bool, if_missing=False)
features = FieldProperty([str])
+ rating = FieldProperty(float, if_missing=0)
# transient properties
notifications_disabled = False
diff --git a/Allura/allura/templates/jinja_master/nav_menu.html b/Allura/allura/templates/jinja_master/nav_menu.html
index 0f956ce..9509334 100644
--- a/Allura/allura/templates/jinja_master/nav_menu.html
+++ b/Allura/allura/templates/jinja_master/nav_menu.html
@@ -59,6 +59,32 @@
<a href="{{ admin.url() }}">{{ admin.username }}</a>{{ ',' if not loop.last }}
{% endif %}
{%- endfor -%}
+ <p id="detailed_ratings"><span id=stars></span></p>
</div>
{% endif %}
{% endif %}
+
+<script>
+ document.getElementById("stars").innerHTML = getStars("{{c.project.rating}}");
+
+function getStars(ratings) {
+
+ // Round to nearest half
+ ratings = Math.round(ratings * 2) / 2;
+ let output = [];
+
+ // Append all the filled whole stars
+ for (var i = ratings; i >= 1; i--)
+ output.push('<i class="fa fa-star" aria-hidden="true" style="color: orange;"></i> ');
+
+ // If there is a half a star, append it
+ if (i == .5) output.push('<i class="fa fa-star-half-o" aria-hidden="true" style="color: orange;"></i> ');
+
+ // Fill the empty stars
+ for (let i = (5 - ratings); i >= 1; i--)
+ output.push('<i class="fa fa-star-o" aria-hidden="true" style="color: orange;"></i> ');
+
+ return output.join('');
+
+ }
+ </script>
diff --git a/ForgeFeedback/forgefeedback/__init__.py b/ForgeFeedback/forgefeedback/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/ForgeFeedback/forgefeedback/feedback_main.py b/ForgeFeedback/forgefeedback/feedback_main.py
new file mode 100644
index 0000000..0f9a555
--- /dev/null
+++ b/ForgeFeedback/forgefeedback/feedback_main.py
@@ -0,0 +1,230 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+
+import logging
+import pymongo
+
+# Non-stdlib imports
+
+from tg import expose, flash, url, config, request
+from tg.decorators import with_trailing_slash, without_trailing_slash
+from tg import tmpl_context as c, app_globals as g
+from ming.odm import session
+from ming.orm import session
+
+## profanityfilter package ##
+from profanityfilter import ProfanityFilter
+
+# Pyforge-specific imports
+
+from allura import model as M
+from allura import version
+from allura.app import (
+ Application,
+ )
+from allura.controllers import BaseController
+from allura.controllers.feed import FeedController
+from allura.lib.decorators import require_post
+from allura.lib.security import (require_access, has_access)
+from allura.model import project
+
+# Local imports
+
+from forgefeedback import model as TM
+from forgefeedback import version
+from forgefeedback.model import Feedback
+
+log = logging.getLogger(__name__)
+
+
+class ForgeFeedbackApp(Application):
+
+
+ __version__ = version.__version__
+ permissions = [
+ 'read', 'update', 'create',
+ 'post', 'admin', 'delete'
+ ]
+
+ permissions_desc = {
+ 'read': 'View ratings.',
+ 'update': 'Edit ratings.',
+ 'create': 'Create ratings.',
+ 'admin': 'Set permissions. Configure option.',
+ 'delete': 'Delete and undelete ratings. View deleted ratings.'
+ }
+
+ config_options = Application.config_options + [
+ ]
+ tool_label = 'Feedback'
+ tool_description = """
+ Feedbacks are given for the tools in the form of reviews and ratings, edit and delete the feedback"""
+ default_mount_label = 'Feedback'
+ default_mount_point = 'feedback'
+ ordinal = 8
+
+ def __init__(self, project, config):
+ Application.__init__(self, project, config)
+ self.root = RootController()
+
+ def install(self, project):
+ 'Set up any default permissions and roles here'
+ super(ForgeFeedbackApp, self).install(project)
+ # Setup permissions
+ role_admin = M.ProjectRole.by_name('Admin')._id
+ role_developer = M.ProjectRole.by_name('Developer')._id
+ role_auth = M.ProjectRole.by_name('*authenticated')._id
+ role_anon = M.ProjectRole.by_name('*anonymous')._id
+ self.config.acl = [
+ M.ACE.allow(role_anon, 'read'),
+ M.ACE.allow(role_auth, 'post'),
+ M.ACE.allow(role_auth, 'unmoderated_post'),
+ M.ACE.allow(role_auth, 'create'),
+ M.ACE.allow(role_developer, 'update'),
+ M.ACE.allow(role_developer, 'moderate'),
+ M.ACE.allow(role_developer, 'delete'),
+ M.ACE.allow(role_admin, 'configure'),
+ M.ACE.allow(role_admin, 'admin'),
+ ]
+
+ def uninstall(self, project):
+ """Remove all the tool's artifacts from the database"""
+ app_config_id = {'app_config_id': c.app.config._id}
+ TM.Feedback.query.remove(app_config_id)
+ super(ForgeFeedbackApp, self).uninstall(project)
+
+
+class RootController(BaseController, FeedController):
+
+ def _check_security(self):
+ require_access(c.app, 'read')
+
+ @expose('jinja:forgefeedback:templates/feedback/index.html')
+ def index(self,**kw):
+ require_access(c.app, 'read')
+ user_has_already_reviewed = False
+ rating_by_user = Feedback.query.find({
+ 'reported_by_id' : c.user._id,'project_id' : c.project._id}
+ ).count()
+ if (rating_by_user > 0) :
+ user_has_already_reviewed = True
+ return dict(review_list= self.get_review_list(), user_has_already_reviewed = user_has_already_reviewed, rating=self.getRating())
+
+ # the list of all the feedbacks given by various users is listed on the index page
+ @expose('jinja:forgefeedback:templates/feedback/index.html')
+ def get_review_list(self, **kw):
+ self.review_list = Feedback.query.find(dict(project_id=c.project._id)).sort('created_date', pymongo.DESCENDING).all()
+ return self.review_list
+
+ # The new feedback given by the logged in user which includes the review, rating, project id and the user id are all flushed into the database
+ @require_post()
+ @expose('jinja:forgefeedback:templates/feedback/index.html')
+ def create_feedback(self, description=None, rating=None, **kw):
+ """saving the review for the first time """
+ require_access(c.app, 'create')
+ p = Feedback( description=description , rating=rating, user_id=c.user._id, project_id=c.project._id)
+ session(p).flush()
+ flash('Feedback successfully added')
+ M.main_orm_session.flush()
+ g.director.create_activity(c.user, 'posted', p,related_nodes=[c.project], tags=['description'])
+ return dict(review_list = self.get_review_list(), rating=self.getRating())
+
+ # called on click of the Feedback link
+ @with_trailing_slash
+ @expose('jinja:forgefeedback:templates/feedback/new_feedback.html')
+ def new_feedback(self, **kw):
+ require_access(c.app, 'create')
+ return dict(action=c.app.config.url() + 'create')
+
+ #called on click of edit review link and displays the previous feedback
+ @expose('jinja:forgefeedback:templates/feedback/edit_feedback.html')
+ def edit_feedback(self, **kw):
+ self.review = Feedback.query.find({'reported_by_id' : c.user._id,'project_id' : c.project._id}).first()
+ return dict(description = self.review.description, rating=self.review.rating)
+
+ # The edited feedback will be updated in the index page
+ @expose('jinja:forgefeedback:templates/feedback/index.html')
+ def edit_user_review(self,description=None, rating=None, **kw):
+
+ Feedback.query.update(
+ {'reported_by_id': c.user._id,'project_id' : c.project._id},
+ {'$set': {'description': description, 'rating':rating}})
+ self.rating = Feedback.query.find({'reported_by_id' : c.user._id,'project_id' : c.project._id}).first()
+ flash('Feedback successfully edited')
+ g.director.create_activity(c.user,'modified', self.rating, related_nodes=[c.project], tags=['description'])
+ return dict(review_list = self.get_review_list(), rating=self.getRating())
+
+ #called when user clicks on delete link in feedback page
+ @without_trailing_slash
+ @expose('jinja:forgefeedback:templates/feedback/index.html')
+ def delete_feedback(self, **kw):
+ user_review = Feedback.query.find({'reported_by_id' : c.user._id,'project_id' : c.project._id}).first()
+ Feedback.query.remove(dict({'reported_by_id' : c.user._id,'project_id' : c.project._id}))
+ rating_by_user = Feedback.query.find({
+ 'reported_by_id' : c.user._id,'project_id' : c.project._id}
+ ).count()
+ if (rating_by_user > 0) :
+ user_has_already_reviewed = True
+ else :
+ user_has_already_reviewed = False
+ flash('Feedback successfully deleted')
+ M.main_orm_session.flush()
+ return dict(review_list = self.get_review_list(), user_has_already_reviewed = user_has_already_reviewed, rating=self.getRating())
+
+ #This method is used to check for profanity in feedback text
+ @expose()
+ def feedback_check(self, description=None):
+ pf = ProfanityFilter()
+ if description:
+ result = str(pf.is_profane(description)).lower()
+ else:
+ result = 'None'
+ return result
+
+
+ # This method count the number of stars finds their sum and calculates the average of all the star rating count
+ def getRating(self, **kw):
+
+
+ onestarcount = TM.Feedback.query.find({'rating':'1','project_id':c.project._id}).count()
+ twostarcount = TM.Feedback.query.find({'rating':'2','project_id':c.project._id}).count()
+ threestarcount = TM.Feedback.query.find({'rating':'3','project_id':c.project._id}).count()
+ fourstarcount = TM.Feedback.query.find({'rating':'4','project_id':c.project._id}).count()
+ fivestarcount = TM.Feedback.query.find({'rating':'5','project_id':c.project._id}).count()
+ sum_of_ratings = float(fivestarcount + fourstarcount + threestarcount + twostarcount + onestarcount)
+ if (sum_of_ratings != 0):
+ average_user_ratings =float((5*fivestarcount)+(4*fourstarcount)+(3*threestarcount)+(2*twostarcount)+(1*onestarcount))/sum_of_ratings
+ float_rating = float(average_user_ratings)
+ int_rating = int(float_rating)
+ float_point_value = float_rating - int_rating
+ if(float_point_value < 0.25 ):
+ c.project.rating= int_rating
+ elif(float_point_value>=0.25<0.75):
+ c.project.rating = 0.5 + int_rating
+ elif(float_point_value >= 0.75):
+ c.project.rating=float(int_rating)+1
+ return average_user_ratings
+ if (sum_of_ratings == 0):
+ c.project.rating = 0.0
+
+
+
+
+
+
+
+
diff --git a/ForgeFeedback/forgefeedback/model/__init__.py b/ForgeFeedback/forgefeedback/model/__init__.py
new file mode 100644
index 0000000..19f031b
--- /dev/null
+++ b/ForgeFeedback/forgefeedback/model/__init__.py
@@ -0,0 +1,21 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+
+from feedback import Feedback
+
+
+
diff --git a/ForgeFeedback/forgefeedback/model/feedback.py b/ForgeFeedback/forgefeedback/model/feedback.py
new file mode 100644
index 0000000..2ef7326
--- /dev/null
+++ b/ForgeFeedback/forgefeedback/model/feedback.py
@@ -0,0 +1,82 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+
+import logging
+import urllib
+# Non-stdlib imports
+
+from datetime import datetime
+from bson import ObjectId
+from tg import tmpl_context as c
+from ming import schema
+from ming.orm import Mapper
+from ming.orm import FieldProperty, ForeignIdProperty, RelationProperty
+
+# Pyforge-specific imports
+
+from allura.model.artifact import VersionedArtifact
+from allura.model.auth import AlluraUserProperty, User
+from allura.model.project import ProjectRole
+from allura.model.timeline import ActivityObject
+from allura.lib import helpers as h
+
+log = logging.getLogger(__name__)
+
+
+class Feedback(VersionedArtifact, ActivityObject):
+
+ class __mongometa__:
+ name = 'feedback'
+
+ type_s = 'Feedback'
+ _id = FieldProperty(schema.ObjectId)
+ created_date = FieldProperty(datetime, if_missing=datetime.utcnow)
+ rating = FieldProperty(str, if_missing='')
+ description = FieldProperty(str, if_missing='')
+ reported_by_id = AlluraUserProperty(if_missing=lambda: c.user._id)
+ project_id = ForeignIdProperty('Project', if_missing=lambda: c.project._id)
+ reported_by = RelationProperty(User, via='reported_by_id')
+
+ def index(self):
+ result = VersionedArtifact.index(self)
+ result.update(
+ created_date_dt=self.created_date,
+ text=self.description,
+ )
+ return result
+
+ @property
+ def activity_name(self):
+ return 'a review comment'
+
+ @property
+ def activity_extras(self):
+ d = ActivityObject.activity_extras.fget(self)
+ d.update(summary=self.description)
+ return d
+ def url(self):
+ return self.app_config.url()
+
+Mapper.compile_all()
+
+
+
+
+
+
+
+
diff --git a/ForgeFeedback/forgefeedback/nf/feedback/css/feedback.css b/ForgeFeedback/forgefeedback/nf/feedback/css/feedback.css
new file mode 100644
index 0000000..15c2f9c
--- /dev/null
+++ b/ForgeFeedback/forgefeedback/nf/feedback/css/feedback.css
@@ -0,0 +1,112 @@
+.rating {
+ float:left;
+}
+
+/* :not(:checked) is a filter, so that browsers that dont support :checked dont
+ follow these rules. Every browser that supports :checked also supports :not(), so
+ it doesnt make the test unnecessarily selective */
+.rating:not(:checked) > input {
+ position:absolute;
+ top:-9999px;
+ clip:rect(0,0,0,0);
+}
+.rating:not(:checked) > label {
+ float:right;
+ width:1em;
+ padding:0 .1em;
+ overflow:hidden;
+ white-space:nowrap;
+ cursor:pointer;
+ font-size:200%;
+ line-height:1.2;
+ color:#ddd;
+ text-shadow:1px 1px #bbb, 2px 2px #666, .1em .1em .2em rgba(0,0,0,.5);
+}
+.rating:not(:checked) > label:before {
+ content: '★ ';
+}
+.rating > input:checked ~ label {
+ color: #f70;
+ text-shadow:1px 1px #c60, 2px 2px #940, .1em .1em .2em rgba(0,0,0,.5);
+}
+
+.rating:not(:checked) > label:hover,
+.rating:not(:checked) > label:hover ~ label {
+ color: gold;
+ text-shadow:1px 1px goldenrod, 2px 2px #B57340, .1em .1em .2em rgba(0,0,0,.5);
+}
+.rating > input:checked + label:hover,
+.rating > input:checked + label:hover ~ label,
+.rating > input:checked ~ label:hover,
+.rating > input:checked ~ label:hover ~ label,
+.rating > label:hover ~ input:checked ~ label {
+ color: #ea0;
+ text-shadow:1px 1px goldenrod, 2px 2px #B57340, .1em .1em .2em rgba(0,0,0,.5);
+}
+.rating > label:active {
+ position:relative;
+ top:2px;
+ left:2px;
+}
+.feed {
+ padding: 0 20px 20px 20px;
+}
+.feed, .feed * {
+ box-sizing: border-box;
+}
+.feed form textarea {
+ width: 100%;
+ height: 200px;
+ display: block;
+}
+.index {
+ padding: 0 20px 20px 20px;
+}
+.index ul.list {
+ list-style: none;
+ margin: 0;
+}
+.index ul.list li {
+ padding: 20px;
+ border-bottom: 1px solid #eee;
+}
+.index ul.list li time {
+ font-size: 12px;
+ color: #777;
+}
+.index ul.list li h1 {
+ padding: 0;
+ font-size: 16px;
+ line-height: 32px;
+}
+.index ul.list li p {
+ padding: 0;
+ vertical-align: top;
+ font-size: 14px;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+.index ul.list li .avatar {
+ float: left;
+ margin: 10px 10px 0 0;
+}
+.fa-star {
+color:orange;
+}
+.fa-star-o {
+color :orange;
+}
+.rating {
+position:relative;
+}
+p {
+position:absolute;
+}
+.grid-19{
+ width:885px !important;
+}
+.btn.link.cancel_feed{
+ float:right;
+}
+
diff --git a/ForgeFeedback/forgefeedback/templates/__init__.py b/ForgeFeedback/forgefeedback/templates/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/ForgeFeedback/forgefeedback/templates/feedback/common_feedback.html b/ForgeFeedback/forgefeedback/templates/feedback/common_feedback.html
new file mode 100644
index 0000000..48db583
--- /dev/null
+++ b/ForgeFeedback/forgefeedback/templates/feedback/common_feedback.html
@@ -0,0 +1,87 @@
+{#-
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you 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.
+This is used when user is trying to imput a new review
+
+-#}
+
+
+<!-- macro for feedback textarea -->
+{% macro feed_textarea(name='description',id='description',placeholder='',description='') %}
+<textarea class="textbox" name="{{name}}" id="{{id}}" maxlength=100 onkeyup="manage()" placeholder="{{placeholder}}">{{description}}</textarea>
+{% endmacro %}
+
+<!-- macro for feedback alert message -->
+{% macro alert_message() %}
+ <div id="check">
+ <p id="status_msg" style="color:#f33;"> <i class="fa fa-exclamation-triangle"></i> Profanity alert! Please update your feedback.</p>
+ </div>
+{% endmacro %}
+
+<!-- macro for feedback cancel button -->
+{% macro feed_cancel(url='') %}
+ <a href="{{url}}" class="btn link cancel_feed" >Cancel</a>
+{% endmacro %}
+
+<!-- macro for profanity scripts -->
+{% macro profanity_scripts(url='') %}
+<script type="text/javascript">
+function manage()
+{
+ var description = document.getElementById('description');
+ var star5 = $('#star5').is(':checked');
+ var star4 = $('#star4').is(':checked');
+ var star3 = $('#star3').is(':checked');
+ var star2 = $('#star2').is(':checked');
+ var star1 = $('#star1').is(':checked');
+ var bt = document.getElementById('button');
+ if (description.value.trim().length != 0 && (star5 || star4 || star3 || star2 || star1 )) {
+ bt.disabled = false;
+ }
+ else {
+ bt.disabled = true;
+ }
+}
+
+</script>
+
+<script type="text/javascript">
+$('#status_msg').hide();
+
+$("#description").keyup(function(){
+ var description = $("#description").val();
+ $.ajax({
+ url:'{{url}}feedback_check',
+ type:'GET',
+ data: {'description':description},
+ success: function(status){
+ if (status == 'true'){
+ $('#button').attr('disabled', true);
+ $('#status_msg').show();
+ }
+ else{
+ $('#status_msg').hide();
+ }
+ }
+ });
+});
+</script>
+{% endmacro %}
+
+
+
+
diff --git a/ForgeFeedback/forgefeedback/templates/feedback/edit_feedback.html b/ForgeFeedback/forgefeedback/templates/feedback/edit_feedback.html
new file mode 100644
index 0000000..8f11e2a
--- /dev/null
+++ b/ForgeFeedback/forgefeedback/templates/feedback/edit_feedback.html
@@ -0,0 +1,103 @@
+{#-
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you 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.
+This is used when user is trying to imput a new review
+
+-#}
+
+{% import 'allura:templates/jinja_master/lib.html' as lib with context %}
+
+{% import 'forgefeedback:templates/feedback/common_feedback.html' as common_feed %}
+
+{% extends g.theme.master %}
+{% set hide_left_bar = True %}
+{% do g.register_app_css('css/feedback.css') %}
+
+{% block title %}{{c.project.name}} / {{c.app.config.options.mount_label}} / Edit feedback {% endblock %}
+
+{% block header %}{{c.app.config.options.mount_label}}{% endblock %}
+
+{% block content %}
+<style>
+p {
+ position:inherit;
+}
+</style>
+
+<div class="feed">
+<form action="{{ c.app.url }}edit_user_review" method="post">
+
+<div class="row">
+<div class="col-25">
+
+ <p> <h2>Edit your feedback for <b> {{c.project.name}} </b></h2> </p>
+ {{ common_feed.alert_message() }}
+
+ </div>
+ <div class="col-75">
+<fieldset class="rating">
+ {% if rating == '5' %}
+ <input type="radio" id="star5" name="rating" value="5" checked="checked" onclick="manage()" /><label for="star5" title="Excellent!"></label>
+ {% else %}
+ <input type="radio" id="star5" name="rating" value="5" onclick="manage()" /><label for="star5" title="Excellent!"></label>
+ {% endif %}
+ {% if rating == '4' %}
+ <input type="radio" id="star4" name="rating" value="4" checked="checked" onclick="manage()" /><label for="star4" title="Great!"></label>
+ {% else %}
+ <input type="radio" id="star4" name="rating" value="4" onclick="manage()" /><label for="star4" title="Great!"></label>
+ {% endif %}
+ {% if rating == '3' %}
+ <input type="radio" id="star3" name="rating" value="3" checked="checked" onclick="manage()" /><label for="star3" title="Good!"></label>
+ {% else %}
+ <input type="radio" id="star3" name="rating" value="3" onclick="manage()" /><label for="star3" title="Good!"></label>
+ {% endif %}
+ {% if rating == '2' %}
+ <input type="radio" id="star2" name="rating" value="2" checked="checked" onclick="manage()" /><label for="star2" title="Average"></label>
+ {% else %}
+ <input type="radio" id="star5" name="rating" value="5" onclick="manage()" /><label for="star5" title="Excellent!"></label>
+ {% endif %}
+ {% if rating == '1' %}
+ <input type="radio" id="star1" name="rating" value="1" checked="checked" onclick="manage()" /><label for="star1" title="Poor"></label>
+ {% else %}
+ <input type="radio" id="star5" name="rating" value="5" onclick="manage()" /><label for="star5" title="Excellent!"></label>
+ {% endif %}
+
+</fieldset>
+</div>
+</div>
+
+<!-- feedback textarea's macro -->
+{{ common_feed.feed_textarea(placeholder='Edit your feedback here',description=description ) }}
+
+<div class="grid-19">
+ <input type="submit" value="Submit" id="button" >
+ {{ common_feed.feed_cancel(url=c.app.url) }}
+</div>
+
+{{ lib.csrf_token() }}
+
+</form>
+</div>
+
+{% endblock %}
+
+{% block extra_js %}
+<!-- profanity script's macro -->
+ {{ common_feed.profanity_scripts(url=c.app.url) }}
+{% endblock %}
+
+
diff --git a/ForgeFeedback/forgefeedback/templates/feedback/feedback_list.html b/ForgeFeedback/forgefeedback/templates/feedback/feedback_list.html
new file mode 100644
index 0000000..195fb2e
--- /dev/null
+++ b/ForgeFeedback/forgefeedback/templates/feedback/feedback_list.html
@@ -0,0 +1,100 @@
+{#-
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you 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.
+-#}
+
+{% import 'forgeactivity:templates/macros.html' as am with context %}
+{#- to add the time -#}
+{% from 'allura:templates/jinja_master/lib.html' import abbr_date with context %}
+{% do g.register_app_css('css/feedback.css') %}
+{% block content %}
+
+{% for timeline in review_list %}
+<li>
+ <time>
+ {{abbr_date(timeline.created_date)}}
+ </time>
+<br/>
+ <h1>
+ {{ am.icon (timeline.reported_by, 32, 'avatar') }}
+ {{am.activity_obj(timeline.reported_by)}}
+ </h1><br/>
+ <fieldset class="rating" style="float:left">
+
+ {% if timeline.rating =='1' %}
+ <span class="fa fa-star checked"></span>
+ <span class="fa fa-star-o "></span>
+ <span class="fa fa-star-o "></span>
+ <span class="fa fa-star-o "></span>
+ <span class="fa fa-star-o"></span>
+
+ {% endif %}
+
+ {% if timeline.rating =='2' %}
+ <span class="fa fa-star checked"></span>
+ <span class="fa fa-star checked"></span>
+ <span class="fa fa-star-o"></span>
+ <span class="fa fa-star-o"></span>
+ <span class="fa fa-star-o"></span>
+
+ {% endif %}
+
+ {% if timeline.rating =='3' %}
+ <span class="fa fa-star checked"></span>
+ <span class="fa fa-star checked"></span>
+ <span class="fa fa-star checked"></span>
+ <span class="fa fa-star-o"></span>
+ <span class="fa fa-star-o"></span>
+ {% endif %}
+
+ {% if timeline.rating =='4' %}
+ <span class="fa fa-star checked"></span>
+ <span class="fa fa-star checked"></span>
+ <span class="fa fa-star checked"></span>
+ <span class="fa fa-star checked"></span>
+ <span class="fa fa-star-o"></span>
+
+ {% endif %}
+
+ {% if timeline.rating =='5' %}
+ <span class="fa fa-star checked"></span>
+ <span class="fa fa-star checked"></span>
+ <span class="fa fa-star checked"></span>
+ <span class="fa fa-star checked"></span>
+ <span class="fa fa-star checked"></span>
+ {% endif %}
+ </fieldset>
+<br/>
+
+ {{timeline.description}}
+
+</li>
+{% endfor %}
+{% endblock %}
+
+{% block extra_css %}
+<style>
+.rating {
+position:relative;
+}
+p {
+position:absolute;
+}
+</style>
+{% endblock %}
+
+
diff --git a/ForgeFeedback/forgefeedback/templates/feedback/index.html b/ForgeFeedback/forgefeedback/templates/feedback/index.html
new file mode 100644
index 0000000..fe96856
--- /dev/null
+++ b/ForgeFeedback/forgefeedback/templates/feedback/index.html
@@ -0,0 +1,56 @@
+{#-
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you 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
+
+ e 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.
+-#}
+{% extends g.theme.master %}
+{% do g.register_app_css('css/feedback.css') %}
+{% set hide_left_bar = True %}
+{% block nav_menu %}
+{{super()}}
+<br/>
+<br/>
+{% endblock %}
+
+{% block title %}{{c.project.name}} / {{c.app.config.options.mount_label}} / Feedback{% endblock %}
+{% block actions %}
+{% endblock %}
+
+{% block header %}{{c.app.config.options.mount_label}}{% endblock %}
+
+{% block content %}
+
+{% if c.user and c.user != c.user.anonymous() %}
+<div class="index">
+ {% if user_has_already_reviewed == False %}
+ <p><h2> Provide your <a href="{{c.app.url}}new_feedback">Feedback</a> for {{c.project.name}} </h2></p>
+ {% else %}
+ <p><h2><a href="{{c.app.url}}edit_feedback"> Edit </a> or <a href="{{c.app.url}}delete_feedback"> Delete </a> your feedback for {{c.project.name}} </h2> </p>
+ {% endif %}
+</div>
+{% else %}
+<p><h3> <a target="_parent" href="{{ config.get('auth.login_url', '/auth/') }}">Login </a> to Add/Modify Feedback</h3></p>
+{% endif %}
+<hr/>
+<div class ="index" >
+ <ul class="list">
+ {% include 'forgefeedback:templates/feedback/feedback_list.html' %}
+ </ul>
+</div>
+{% endblock %}
+
+
+
diff --git a/ForgeFeedback/forgefeedback/templates/feedback/new_feedback.html b/ForgeFeedback/forgefeedback/templates/feedback/new_feedback.html
new file mode 100644
index 0000000..b472aab
--- /dev/null
+++ b/ForgeFeedback/forgefeedback/templates/feedback/new_feedback.html
@@ -0,0 +1,79 @@
+{#-
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you 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.
+This is used when user is trying to imput a new review
+
+-#}
+{% import 'allura:templates/jinja_master/lib.html' as lib with context %}
+
+{% import 'forgefeedback:templates/feedback/common_feedback.html' as common_feed %}
+
+{% extends g.theme.master %}
+{% set hide_left_bar = True %}
+{% do g.register_app_css('css/feedback.css') %}
+{% block title %}{{c.project.name}} / {{c.app.config.options.mount_label}} / New feedback{% endblock %}
+
+{% block header %}{{c.app.config.options.mount_label}}{% endblock %}
+
+{% block content %}
+<style>
+p {
+ position:inherit;
+}
+</style>
+
+<div class="feed">
+ <form action="{{ c.app.url }}create_feedback" method="post">
+
+ <div class="row">
+ <div class="col-25">
+
+ <p> <h2>Provide your feedback for <b> {{c.project.name}}</b></h2> </p>
+ {{ common_feed.alert_message() }}
+
+ </div>
+ <div class="col-75">
+ <fieldset class="rating" id="sar">
+ <input type="radio" id="star5" name="rating" value="5" onclick="manage()" /><label for="star5" title="Excellent">5 stars</label>
+ <input type="radio" id="star4" name="rating" value="4" onclick="manage()" /><label for="star4" title="Great">4 stars</label>
+ <input type="radio" id="star3" name="rating" value="3" onclick="manage()" /><label for="star3" title="Good">3 stars</label>
+ <input type="radio" id="star2" name="rating" value="2" onclick="manage()" /><label for="star2" title="Average">2 stars</label>
+ <input type="radio" id="star1" name="rating" value="1" onclick="manage()" /><label for="star1" title="Poor">1 star</label>
+ </fieldset>
+ </div>
+ </div>
+
+ <!-- feedback textarea's macro -->
+ {{ common_feed.feed_textarea(placeholder='Enter your feedback here',description=description ) }}
+ <div class="grid-19">
+ <input type="submit" value="Submit" id="button" disabled />
+ {{ common_feed.feed_cancel(url=c.app.url) }}
+ </div>
+ {{ lib.csrf_token() }}
+ </form>
+</div>
+{% endblock %}
+
+
+{% block extra_js %}
+<!-- profanity script's macro -->
+ {{ common_feed.profanity_scripts(url=c.app.url) }}
+{% endblock %}
+
+
+
+
diff --git a/ForgeFeedback/forgefeedback/tests/__init__.py b/ForgeFeedback/forgefeedback/tests/__init__.py
new file mode 100644
index 0000000..77505f1
--- /dev/null
+++ b/ForgeFeedback/forgefeedback/tests/__init__.py
@@ -0,0 +1,17 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+
diff --git a/ForgeFeedback/forgefeedback/tests/functional/__init__.py b/ForgeFeedback/forgefeedback/tests/functional/__init__.py
new file mode 100644
index 0000000..77505f1
--- /dev/null
+++ b/ForgeFeedback/forgefeedback/tests/functional/__init__.py
@@ -0,0 +1,17 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+
diff --git a/ForgeFeedback/forgefeedback/tests/functional/test_root.py b/ForgeFeedback/forgefeedback/tests/functional/test_root.py
new file mode 100644
index 0000000..b97eafa
--- /dev/null
+++ b/ForgeFeedback/forgefeedback/tests/functional/test_root.py
@@ -0,0 +1,69 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+from tg import tmpl_context as c
+from tg import config
+
+from nose.tools import assert_equal, assert_in, assert_not_in, assert_true, assert_false, assert_raises
+
+from allura import model as M
+from alluratest.controller import TestController
+from allura.lib import helpers as h
+from allura.tests import decorators as td
+
+from forgefeedback import model as FM
+
+class TestFeedback(TestController):
+ def setUp(self):
+ TestController.setUp(self)
+
+ def test_feedback(self):
+ c.user = M.User.by_username('test-admin')
+ self.app.get('/feedback/')
+ r = self.app.get('/p/test/feedback')
+ assert 'test' in r
+ assert_in('<a href="/p/test/feedback/new_feedback">Feedback</a>', r)
+
+ def test_new_feedback(self):
+ c.user = M.User.by_username('test-admin')
+ self.app.get('/feedback/')
+ r = self.app.get('/p/test/feedback/new_feedback/')
+ assert_in('Provide your feedback for <b> Test Project</b>',r)
+ assert_in('Enter your feedback here', r)
+
+ def test_create_feedback(self):
+ resp = post_feedback(self)
+ assert_in('Good tool',resp)
+
+ def test_edit_feedback(self):
+ post_feedback(self)
+ data = {'rating': '2','description':'Not useful'}
+ resp = self.app.post('/p/test/feedback/edit_user_review',data)
+ assert_in('Not useful',resp)
+
+ def test_delete_feedback(self):
+ post_feedback(self)
+ resp=self.app.get('/p/test/feedback/delete_feedback')
+ assert_in('<a href="/p/test/feedback/new_feedback">Feedback</a>',resp)
+
+
+def post_feedback(self):
+ c.user =M.User.by_username('test-admin')
+ self.app.get('/feedback/')
+ self.app.get('/p/test/feedback')
+ data = {'rating':'4','description':'Good tool'}
+ resp = self.app.post('/p/test/feedback/create_feedback/',data)
+ return resp
diff --git a/ForgeFeedback/forgefeedback/tests/test_feedback_roles.py b/ForgeFeedback/forgefeedback/tests/test_feedback_roles.py
new file mode 100644
index 0000000..bd7f902
--- /dev/null
+++ b/ForgeFeedback/forgefeedback/tests/test_feedback_roles.py
@@ -0,0 +1,54 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+
+from tg import tmpl_context as c, app_globals as g
+
+from nose.tools import assert_equal
+
+from alluratest.controller import setup_basic_test, setup_global_objects
+from allura import model as M
+from allura.lib import security
+from allura.tests import decorators as td
+from allura.lib import helpers as h
+
+def setUp():
+ setup_basic_test()
+ setup_with_tools()
+
+
+@td.with_tool('u/test-user-1','feedback')
+@td.with_user_project('test-user-1')
+def setup_with_tools():
+ setup_global_objects()
+ h.set_context('test', neighborhood='Projects')
+ c.project.install_app('feedback', 'feedback')
+ g.set_app('feedback')
+
+
+def test_role_assignments():
+ admin = M.User.by_username('test-admin')
+ user = M.User.by_username('test-user')
+ anon = M.User.anonymous()
+
+ def check_access(perm):
+ pred = security.has_access(c.app, perm)
+ return pred(user=admin), pred(user=user), pred(user=anon)
+ assert_equal(check_access('read'), (True, True, True))
+ assert_equal(check_access('create'), (True, True, False))
+ assert_equal(check_access('update'), (True, False, False))
+ assert_equal(check_access('delete'), (True, False, False))
+
diff --git a/ForgeFeedback/forgefeedback/tests/unit/__init__.py b/ForgeFeedback/forgefeedback/tests/unit/__init__.py
new file mode 100644
index 0000000..9c6667a
--- /dev/null
+++ b/ForgeFeedback/forgefeedback/tests/unit/__init__.py
@@ -0,0 +1,51 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+
+from tg import tmpl_context as c
+from ming.orm.ormsession import ThreadLocalORMSession
+
+from allura.websetup import bootstrap
+from allura.lib import helpers as h
+from allura.lib import plugin
+from allura import model as M
+from alluratest.controller import setup_basic_test
+
+
+def setUp():
+ setup_basic_test()
+
+
+class FeedbackTestWithModel(object):
+
+ def setUp(self):
+ bootstrap.wipe_database()
+ project_reg = plugin.ProjectRegistrationProvider.get()
+ c.user = bootstrap.create_user('Test User')
+ neighborhood = M.Neighborhood(name='Projects', url_prefix='/p/',
+ features=dict(private_projects=False,
+ max_projects=None,
+ css='none',
+ google_analytics=False))
+ project_reg.register_neighborhood_project(neighborhood, [c.user])
+ c.project = neighborhood.register_project('test', c.user)
+ c.project.install_app('Feedback', 'feedback')
+ ThreadLocalORMSession.flush_all()
+ h.set_context('test', 'feedback', neighborhood='Projects')
+
+ def tearDown(self):
+ ThreadLocalORMSession.close_all()
+
diff --git a/ForgeFeedback/forgefeedback/tests/unit/test_feedback.py b/ForgeFeedback/forgefeedback/tests/unit/test_feedback.py
new file mode 100644
index 0000000..604041e
--- /dev/null
+++ b/ForgeFeedback/forgefeedback/tests/unit/test_feedback.py
@@ -0,0 +1,41 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+
+from datetime import datetime
+from nose.tools import assert_equal, assert_true
+from tg import tmpl_context as c
+
+from forgefeedback.tests.unit import FeedbackTestWithModel
+from forgefeedback import model as M
+
+class TestFeedback(FeedbackTestWithModel):
+
+ def test_feedback(self):
+ feedback = M.Feedback()
+ feedback.rating='4'
+ feedback.description='Very good tool'
+ assert_equal(feedback.rating, '4')
+ assert_equal(feedback.description, 'Very good tool')
+ assert_equal(feedback.activity_extras['summary'], feedback.description)
+ assert_true('allura_id' in feedback.activity_extras)
+
+ def test_index(self):
+ feedback= M.Feedback()
+ feedback.rating= '4'
+ feedback.description ='Good tool'
+ result= feedback.index()
+ assert_equal(result["text"], 'Good tool')
diff --git a/ForgeFeedback/forgefeedback/tests/unit/test_root_controller.py b/ForgeFeedback/forgefeedback/tests/unit/test_root_controller.py
new file mode 100644
index 0000000..f99332c
--- /dev/null
+++ b/ForgeFeedback/forgefeedback/tests/unit/test_root_controller.py
@@ -0,0 +1,80 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+
+import unittest
+
+from mock import Mock, patch
+from ming.orm.ormsession import session
+from tg import tmpl_context as c
+from tg import request
+from nose.tools import assert_equal
+
+from allura.lib import helpers as h
+from allura.model import User
+
+from forgefeedback.tests.unit import FeedbackTestWithModel
+from forgefeedback.model import Feedback
+from forgefeedback import feedback_main
+
+class TestFeedbackApp(FeedbackTestWithModel):
+
+ def setUp(self):
+ super(TestFeedbackApp, self).setUp()
+ c.user = User(username='test-user')
+ h.set_context('test', 'feedback', neighborhood='Projects')
+
+ def test_index(self):
+ reviews = feedback_main.RootController().index()
+ assert reviews['user_has_already_reviewed']==False
+ create_feedbacks()
+ reviews = feedback_main.RootController().index()
+ assert reviews['user_has_already_reviewed']==True
+
+ def test_feedback(self):
+ create_feedbacks()
+ reviews = feedback_main.RootController().get_review_list()
+ assert reviews[0].description =='Very good tool'
+ assert reviews[1].description =='Not Useful'
+ assert reviews[0].rating =='5'
+ assert reviews[1].rating =='2'
+
+ def test_getRating(self):
+ create_feedbacks()
+ rating=feedback_main.RootController().getRating()
+ assert_equal(rating,3.5)
+
+ def test_edit_feedback(self):
+ create_feedbacks()
+ old_feedback= feedback_main.RootController().edit_feedback()
+ assert old_feedback['description'] =='Very good tool'
+
+ def test_check_feedback(self):
+ feed_check = feedback_main.RootController().feedback_check('good')
+ assert feed_check == 'false'
+ feed_check = feedback_main.RootController().feedback_check('shit')
+ assert feed_check == 'true'
+
+def create_feedbacks():
+ feedback_1= create_feedback('2', 'Not Useful')
+ c.user = User(username='test-admin')
+ h.set_context('test', 'feedback', neighborhood='Projects')
+ feedback_2 = create_feedback('5', 'Very good tool')
+
+def create_feedback(rating, description):
+ feedback = Feedback(rating=rating, description=description)
+ session(feedback).flush()
+ return feedback
diff --git a/ForgeFeedback/forgefeedback/version.py b/ForgeFeedback/forgefeedback/version.py
new file mode 100644
index 0000000..1333217
--- /dev/null
+++ b/ForgeFeedback/forgefeedback/version.py
@@ -0,0 +1,24 @@
+#Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+
+__version_info__ = (0, 0)
+__version__ = '.'.join(map(str, __version_info__))
+
+
+
+
+
diff --git a/ForgeFeedback/setup.py b/ForgeFeedback/setup.py
new file mode 100644
index 0000000..cce91c5
--- /dev/null
+++ b/ForgeFeedback/setup.py
@@ -0,0 +1,53 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+
+
+from setuptools import setup, find_packages
+
+from forgefeedback.version import __version__
+
+setup(name='ForgeFeedback',
+ version=__version__,
+ description="",
+ long_description="""\
+""",
+ # Get strings from http://pypi.python.org/pypi?%3Aaction=list_classifiers
+ classifiers=[],
+ keywords='',
+ author='',
+ author_email='',
+ url='',
+ license='',
+ packages=find_packages(exclude=['ez_setup', 'examples', 'tests']),
+ include_package_data=True,
+ zip_safe=False,
+ install_requires=[
+ # -*- Extra requirements: -*-
+ 'Allura',
+ ],
+ entry_points="""
+ # -*- Entry points: -*-
+ [allura]
+ Feedback=forgefeedback.feedback_main:ForgeFeedbackApp
+
+
+ """,
+ )
+
+
+
+
diff --git a/requirements.in b/requirements.in
index 35e0f5b..a8276a7 100644
--- a/requirements.in
+++ b/requirements.in
@@ -25,6 +25,8 @@ Paste
PasteDeploy
PasteScript
Pillow
+# profanity filter for feedback
+profanityfilter==2.0.6
Pygments
pymongo==2.8.1
Pypeline[creole,markdown,textile,rst]
@@ -57,4 +59,4 @@ testfixtures
WebTest==2.0.33
# deployment
-gunicorn==19.4.5
\ No newline at end of file
+gunicorn==19.4.5
diff --git a/requirements.txt b/requirements.txt
index 7d4c669..91b2080 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -40,6 +40,7 @@ gunicorn==19.4.5
html5lib==1.0.1
httplib2==0.13.1 # via oauth2
idna==2.8 # via requests
+inflection==0.3.1 # via profanityfilter
ipaddress==1.0.22 # via cryptography
ipython-genutils==0.2.0 # via traitlets
ipython==5.8.0
@@ -64,6 +65,7 @@ pexpect==4.7.0 # via ipython
pickleshare==0.7.5 # via ipython
pillow==6.1.0
poster==0.8.1
+profanityfilter==2.0.6
prompt-toolkit==1.0.16 # via ipython
ptyprocess==0.6.0 # via pexpect
pycparser==2.19 # via cffi
[allura] 03/04: Handled review comments
Posted by br...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
brondsem pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/allura.git
commit 59144b629c5969346d95dd16d5879cbeaf3cd44e
Author: Vrinda A <vr...@in.bosch.com>
AuthorDate: Mon Jan 6 14:40:27 2020 +0530
Handled review comments
---
ForgeFeedback/forgefeedback/__init__.py | 0
ForgeFeedback/forgefeedback/feedback_main.py | 180 ++++++++++++---------
ForgeFeedback/forgefeedback/model/__init__.py | 3 -
ForgeFeedback/forgefeedback/model/feedback.py | 26 ++-
.../forgefeedback/nf/feedback/css/feedback.css | 0
ForgeFeedback/forgefeedback/templates/__init__.py | 0
.../templates/feedback/common_feedback.html | 47 +++---
.../templates/feedback/edit_feedback.html | 35 +---
.../templates/feedback/feedback_list.html | 0
.../forgefeedback/templates/feedback/index.html | 19 ++-
.../templates/feedback/new_feedback.html | 4 +-
ForgeFeedback/forgefeedback/tests/__init__.py | 1 -
.../forgefeedback/tests/functional/__init__.py | 1 -
.../forgefeedback/tests/functional/test_root.py | 75 ++++-----
.../forgefeedback/tests/test_feedback_roles.py | 4 +-
ForgeFeedback/forgefeedback/tests/unit/__init__.py | 1 -
.../forgefeedback/tests/unit/test_feedback.py | 31 ++--
.../tests/unit/test_root_controller.py | 39 ++---
ForgeFeedback/forgefeedback/version.py | 7 +-
ForgeFeedback/setup.py | 0
20 files changed, 241 insertions(+), 232 deletions(-)
diff --git a/ForgeFeedback/forgefeedback/__init__.py b/ForgeFeedback/forgefeedback/__init__.py
old mode 100644
new mode 100755
diff --git a/ForgeFeedback/forgefeedback/feedback_main.py b/ForgeFeedback/forgefeedback/feedback_main.py
old mode 100644
new mode 100755
index 0f9a555..4f04b61
--- a/ForgeFeedback/forgefeedback/feedback_main.py
+++ b/ForgeFeedback/forgefeedback/feedback_main.py
@@ -1,4 +1,4 @@
-# Licensed to the Apache Software Foundation (ASF) under one
+# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
@@ -26,7 +26,7 @@ from tg import tmpl_context as c, app_globals as g
from ming.odm import session
from ming.orm import session
-## profanityfilter package ##
+# profanityfilter package
from profanityfilter import ProfanityFilter
# Pyforge-specific imports
@@ -35,7 +35,7 @@ from allura import model as M
from allura import version
from allura.app import (
Application,
- )
+)
from allura.controllers import BaseController
from allura.controllers.feed import FeedController
from allura.lib.decorators import require_post
@@ -53,12 +53,11 @@ log = logging.getLogger(__name__)
class ForgeFeedbackApp(Application):
-
__version__ = version.__version__
permissions = [
- 'read', 'update', 'create',
+ 'read', 'update', 'create',
'post', 'admin', 'delete'
- ]
+ ]
permissions_desc = {
'read': 'View ratings.',
@@ -72,15 +71,17 @@ class ForgeFeedbackApp(Application):
]
tool_label = 'Feedback'
tool_description = """
- Feedbacks are given for the tools in the form of reviews and ratings, edit and delete the feedback"""
+ Feedbacks are given for the tools in the form of reviews and ratings,
+ edit and delete the feedback"""
default_mount_label = 'Feedback'
default_mount_point = 'feedback'
ordinal = 8
+ max_instances = 1
def __init__(self, project, config):
Application.__init__(self, project, config)
self.root = RootController()
-
+
def install(self, project):
'Set up any default permissions and roles here'
super(ForgeFeedbackApp, self).install(project)
@@ -110,82 +111,101 @@ class ForgeFeedbackApp(Application):
class RootController(BaseController, FeedController):
- def _check_security(self):
+ def _check_security(self):
require_access(c.app, 'read')
@expose('jinja:forgefeedback:templates/feedback/index.html')
- def index(self,**kw):
- require_access(c.app, 'read')
+ def index(self, **kw):
+ require_access(c.app, 'read')
user_has_already_reviewed = False
rating_by_user = Feedback.query.find({
- 'reported_by_id' : c.user._id,'project_id' : c.project._id}
- ).count()
- if (rating_by_user > 0) :
- user_has_already_reviewed = True
- return dict(review_list= self.get_review_list(), user_has_already_reviewed = user_has_already_reviewed, rating=self.getRating())
-
- # the list of all the feedbacks given by various users is listed on the index page
+ 'reported_by_id': c.user._id, 'project_id': c.project._id}
+ ).count()
+ if (rating_by_user > 0):
+ user_has_already_reviewed = True
+ return dict(review_list=self.get_review_list(),
+ user_has_already_reviewed=user_has_already_reviewed,
+ rating=c.project.rating)
+
+ """ the list of all the feedbacks given by
+ various users is listed on the index page """
@expose('jinja:forgefeedback:templates/feedback/index.html')
- def get_review_list(self, **kw):
- self.review_list = Feedback.query.find(dict(project_id=c.project._id)).sort('created_date', pymongo.DESCENDING).all()
+ def get_review_list(self, **kw):
+ self.review_list = Feedback.query.find({'project_id': c.project._id})\
+ .sort('created_date', pymongo.DESCENDING).all()
return self.review_list
- # The new feedback given by the logged in user which includes the review, rating, project id and the user id are all flushed into the database
+ """ The new feedback given by the logged in user which includes
+ the review, rating, project id and the user id are all flushed
+ into the database """
@require_post()
@expose('jinja:forgefeedback:templates/feedback/index.html')
def create_feedback(self, description=None, rating=None, **kw):
"""saving the review for the first time """
require_access(c.app, 'create')
- p = Feedback( description=description , rating=rating, user_id=c.user._id, project_id=c.project._id)
+ p = Feedback(description=description, rating=rating,
+ user_id=c.user._id, project_id=c.project._id)
session(p).flush()
flash('Feedback successfully added')
M.main_orm_session.flush()
- g.director.create_activity(c.user, 'posted', p,related_nodes=[c.project], tags=['description'])
- return dict(review_list = self.get_review_list(), rating=self.getRating())
-
- # called on click of the Feedback link
+ g.director.create_activity(c.user, 'posted', p, related_nodes=[
+ c.project], tags=['description'])
+ return dict(review_list=self.get_review_list(),
+ rating=self.getRating())
+
+ # called on click of the Feedback link
@with_trailing_slash
@expose('jinja:forgefeedback:templates/feedback/new_feedback.html')
def new_feedback(self, **kw):
require_access(c.app, 'create')
return dict(action=c.app.config.url() + 'create')
-
- #called on click of edit review link and displays the previous feedback
+
+ # called on click of edit review link and displays the previous feedback
@expose('jinja:forgefeedback:templates/feedback/edit_feedback.html')
def edit_feedback(self, **kw):
- self.review = Feedback.query.find({'reported_by_id' : c.user._id,'project_id' : c.project._id}).first()
- return dict(description = self.review.description, rating=self.review.rating)
-
- # The edited feedback will be updated in the index page
+ self.review = Feedback.query.find(
+ {'reported_by_id': c.user._id, 'project_id': c.project._id}
+ ).first()
+ return dict(description=self.review.description,
+ rating=self.review.rating)
+
+ # The edited feedback will be updated in the index page
+ @require_post()
@expose('jinja:forgefeedback:templates/feedback/index.html')
- def edit_user_review(self,description=None, rating=None, **kw):
-
- Feedback.query.update(
- {'reported_by_id': c.user._id,'project_id' : c.project._id},
- {'$set': {'description': description, 'rating':rating}})
- self.rating = Feedback.query.find({'reported_by_id' : c.user._id,'project_id' : c.project._id}).first()
- flash('Feedback successfully edited')
- g.director.create_activity(c.user,'modified', self.rating, related_nodes=[c.project], tags=['description'])
- return dict(review_list = self.get_review_list(), rating=self.getRating())
-
- #called when user clicks on delete link in feedback page
+ def edit_user_review(self, description=None, rating=None, **kw):
+ Feedback.query.update(
+ {'reported_by_id': c.user._id, 'project_id': c.project._id},
+ {'$set': {'description': description, 'rating': rating}})
+ self.rating = Feedback.query.find(
+ {'reported_by_id': c.user._id, 'project_id': c.project._id})\
+ .first()
+ flash('Feedback successfully edited')
+ g.director.create_activity(
+ c.user, 'modified', self.rating,
+ related_nodes=[c.project], tags=['description'])
+ return dict(
+ review_list=self.get_review_list(), rating=self.getRating())
+
+ # called when user clicks on delete link in feedback page
@without_trailing_slash
+ @require_post()
@expose('jinja:forgefeedback:templates/feedback/index.html')
def delete_feedback(self, **kw):
- user_review = Feedback.query.find({'reported_by_id' : c.user._id,'project_id' : c.project._id}).first()
- Feedback.query.remove(dict({'reported_by_id' : c.user._id,'project_id' : c.project._id}))
- rating_by_user = Feedback.query.find({
- 'reported_by_id' : c.user._id,'project_id' : c.project._id}
- ).count()
- if (rating_by_user > 0) :
- user_has_already_reviewed = True
- else :
- user_has_already_reviewed = False
- flash('Feedback successfully deleted')
- M.main_orm_session.flush()
- return dict(review_list = self.get_review_list(), user_has_already_reviewed = user_has_already_reviewed, rating=self.getRating())
-
- #This method is used to check for profanity in feedback text
+ user_review = Feedback.query.find(
+ {'reported_by_id': c.user._id, 'project_id': c.project._id}
+ ).first()
+ if user_review:
+ Feedback.query.remove(dict(
+ {'reported_by_id': c.user._id, 'project_id': c.project._id}))
+ M.main_orm_session.flush()
+ self.getRating()
+ flash('Feedback successfully deleted')
+ return 'Success'
+ else:
+ flash('Feedback was not deleted')
+ return 'Failed'
+
+ # This method is used to check for profanity in feedback text
@expose()
def feedback_check(self, description=None):
pf = ProfanityFilter()
@@ -195,36 +215,36 @@ class RootController(BaseController, FeedController):
result = 'None'
return result
-
- # This method count the number of stars finds their sum and calculates the average of all the star rating count
+ """ This method count the number of stars finds their sum and
+ calculates the average of all the star rating count """
def getRating(self, **kw):
-
-
- onestarcount = TM.Feedback.query.find({'rating':'1','project_id':c.project._id}).count()
- twostarcount = TM.Feedback.query.find({'rating':'2','project_id':c.project._id}).count()
- threestarcount = TM.Feedback.query.find({'rating':'3','project_id':c.project._id}).count()
- fourstarcount = TM.Feedback.query.find({'rating':'4','project_id':c.project._id}).count()
- fivestarcount = TM.Feedback.query.find({'rating':'5','project_id':c.project._id}).count()
- sum_of_ratings = float(fivestarcount + fourstarcount + threestarcount + twostarcount + onestarcount)
+ onestarcount = TM.Feedback.query.find(
+ {'rating': '1', 'project_id': c.project._id}).count()
+ twostarcount = TM.Feedback.query.find(
+ {'rating': '2', 'project_id': c.project._id}).count()
+ threestarcount = TM.Feedback.query.find(
+ {'rating': '3', 'project_id': c.project._id}).count()
+ fourstarcount = TM.Feedback.query.find(
+ {'rating': '4', 'project_id': c.project._id}).count()
+ fivestarcount = TM.Feedback.query.find(
+ {'rating': '5', 'project_id': c.project._id}).count()
+ sum_of_ratings = float(
+ fivestarcount + fourstarcount + threestarcount + twostarcount +
+ onestarcount)
if (sum_of_ratings != 0):
- average_user_ratings =float((5*fivestarcount)+(4*fourstarcount)+(3*threestarcount)+(2*twostarcount)+(1*onestarcount))/sum_of_ratings
+ average_user_ratings = float(
+ (5*fivestarcount) + (4*fourstarcount) +
+ (3*threestarcount) + (2*twostarcount) +
+ (1*onestarcount)) / sum_of_ratings
float_rating = float(average_user_ratings)
int_rating = int(float_rating)
float_point_value = float_rating - int_rating
- if(float_point_value < 0.25 ):
- c.project.rating= int_rating
- elif(float_point_value>=0.25<0.75):
+ if(float_point_value < 0.25):
+ c.project.rating = int_rating
+ elif(float_point_value >= 0.25 < 0.75):
c.project.rating = 0.5 + int_rating
elif(float_point_value >= 0.75):
- c.project.rating=float(int_rating)+1
+ c.project.rating = float(int_rating)+1
return average_user_ratings
if (sum_of_ratings == 0):
c.project.rating = 0.0
-
-
-
-
-
-
-
-
diff --git a/ForgeFeedback/forgefeedback/model/__init__.py b/ForgeFeedback/forgefeedback/model/__init__.py
old mode 100644
new mode 100755
index 19f031b..fc61e16
--- a/ForgeFeedback/forgefeedback/model/__init__.py
+++ b/ForgeFeedback/forgefeedback/model/__init__.py
@@ -16,6 +16,3 @@
# under the License.
from feedback import Feedback
-
-
-
diff --git a/ForgeFeedback/forgefeedback/model/feedback.py b/ForgeFeedback/forgefeedback/model/feedback.py
old mode 100644
new mode 100755
index 2ef7326..7cb61e5
--- a/ForgeFeedback/forgefeedback/model/feedback.py
+++ b/ForgeFeedback/forgefeedback/model/feedback.py
@@ -1,4 +1,4 @@
-# Licensed to the Apache Software Foundation (ASF) under one
+# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
@@ -30,7 +30,7 @@ from ming.orm import FieldProperty, ForeignIdProperty, RelationProperty
from allura.model.artifact import VersionedArtifact
from allura.model.auth import AlluraUserProperty, User
-from allura.model.project import ProjectRole
+from allura.model.project import ProjectRole
from allura.model.timeline import ActivityObject
from allura.lib import helpers as h
@@ -38,10 +38,10 @@ log = logging.getLogger(__name__)
class Feedback(VersionedArtifact, ActivityObject):
-
+
class __mongometa__:
- name = 'feedback'
-
+ name = 'feedback'
+
type_s = 'Feedback'
_id = FieldProperty(schema.ObjectId)
created_date = FieldProperty(datetime, if_missing=datetime.utcnow)
@@ -57,7 +57,7 @@ class Feedback(VersionedArtifact, ActivityObject):
created_date_dt=self.created_date,
text=self.description,
)
- return result
+ return result
@property
def activity_name(self):
@@ -66,17 +66,11 @@ class Feedback(VersionedArtifact, ActivityObject):
@property
def activity_extras(self):
d = ActivityObject.activity_extras.fget(self)
- d.update(summary=self.description)
+ d.update(summary=self.description)
return d
- def url(self):
- return self.app_config.url()
-
-Mapper.compile_all()
-
-
-
-
-
+ def url(self):
+ return self.app_config.url()
+Mapper.compile_all()
diff --git a/ForgeFeedback/forgefeedback/nf/feedback/css/feedback.css b/ForgeFeedback/forgefeedback/nf/feedback/css/feedback.css
old mode 100644
new mode 100755
diff --git a/ForgeFeedback/forgefeedback/templates/__init__.py b/ForgeFeedback/forgefeedback/templates/__init__.py
old mode 100644
new mode 100755
diff --git a/ForgeFeedback/forgefeedback/templates/feedback/common_feedback.html b/ForgeFeedback/forgefeedback/templates/feedback/common_feedback.html
old mode 100644
new mode 100755
index 48db583..6bd6634
--- a/ForgeFeedback/forgefeedback/templates/feedback/common_feedback.html
+++ b/ForgeFeedback/forgefeedback/templates/feedback/common_feedback.html
@@ -15,7 +15,7 @@
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-This is used when user is trying to imput a new review
+ This is used when user is trying to imput a new review
-#}
@@ -28,7 +28,7 @@ This is used when user is trying to imput a new review
<!-- macro for feedback alert message -->
{% macro alert_message() %}
<div id="check">
- <p id="status_msg" style="color:#f33;"> <i class="fa fa-exclamation-triangle"></i> Profanity alert! Please update your feedback.</p>
+ <p id="status_msg" style="color:#f33;display:none;"> <i class="fa fa-exclamation-triangle"></i> Profanity alert! Please update your feedback.</p>
</div>
{% endmacro %}
@@ -59,27 +59,32 @@ function manage()
</script>
-<script type="text/javascript">
-$('#status_msg').hide();
-
-$("#description").keyup(function(){
- var description = $("#description").val();
- $.ajax({
- url:'{{url}}feedback_check',
- type:'GET',
- data: {'description':description},
- success: function(status){
- if (status == 'true'){
- $('#button').attr('disabled', true);
- $('#status_msg').show();
- }
- else{
- $('#status_msg').hide();
- }
- }
- });
+<script>
+ $('#feedback_form').submit(function(event){
+ event.preventDefault();
+ var description = $("#description").val();
+
+ $.ajax({
+ context: this,
+ url:'{{url}}feedback_check',
+ type:'GET',
+ data: {'description':description},
+ success: function(status){
+ if (status == 'true'){
+ $('#button').attr('disabled', true);
+ $('#status_msg').show();
+ }
+ else{
+ $('#status_msg').hide();
+ $('#button').attr('disabled', false);
+ this.submit();
+ }
+ }
+
+ });
});
</script>
+
{% endmacro %}
diff --git a/ForgeFeedback/forgefeedback/templates/feedback/edit_feedback.html b/ForgeFeedback/forgefeedback/templates/feedback/edit_feedback.html
old mode 100644
new mode 100755
index 8f11e2a..bf6ec75
--- a/ForgeFeedback/forgefeedback/templates/feedback/edit_feedback.html
+++ b/ForgeFeedback/forgefeedback/templates/feedback/edit_feedback.html
@@ -15,7 +15,7 @@
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-This is used when user is trying to imput a new review
+ This is used when user is trying to imput a new review
-#}
@@ -39,7 +39,7 @@ p {
</style>
<div class="feed">
-<form action="{{ c.app.url }}edit_user_review" method="post">
+<form action="{{ c.app.url }}edit_user_review" method="post" id="feedback_form">
<div class="row">
<div class="col-25">
@@ -50,31 +50,12 @@ p {
</div>
<div class="col-75">
<fieldset class="rating">
- {% if rating == '5' %}
- <input type="radio" id="star5" name="rating" value="5" checked="checked" onclick="manage()" /><label for="star5" title="Excellent!"></label>
- {% else %}
- <input type="radio" id="star5" name="rating" value="5" onclick="manage()" /><label for="star5" title="Excellent!"></label>
- {% endif %}
- {% if rating == '4' %}
- <input type="radio" id="star4" name="rating" value="4" checked="checked" onclick="manage()" /><label for="star4" title="Great!"></label>
- {% else %}
- <input type="radio" id="star4" name="rating" value="4" onclick="manage()" /><label for="star4" title="Great!"></label>
- {% endif %}
- {% if rating == '3' %}
- <input type="radio" id="star3" name="rating" value="3" checked="checked" onclick="manage()" /><label for="star3" title="Good!"></label>
- {% else %}
- <input type="radio" id="star3" name="rating" value="3" onclick="manage()" /><label for="star3" title="Good!"></label>
- {% endif %}
- {% if rating == '2' %}
- <input type="radio" id="star2" name="rating" value="2" checked="checked" onclick="manage()" /><label for="star2" title="Average"></label>
- {% else %}
- <input type="radio" id="star5" name="rating" value="5" onclick="manage()" /><label for="star5" title="Excellent!"></label>
- {% endif %}
- {% if rating == '1' %}
- <input type="radio" id="star1" name="rating" value="1" checked="checked" onclick="manage()" /><label for="star1" title="Poor"></label>
- {% else %}
- <input type="radio" id="star5" name="rating" value="5" onclick="manage()" /><label for="star5" title="Excellent!"></label>
- {% endif %}
+
+ <input type="radio" id="star5" name="rating" value="5" {% if rating == '5' %} checked="checked" {% endif %} onclick="manage()" /><label for="star5" title="Excellent"></label>
+ <input type="radio" id="star4" name="rating" value="4" {% if rating == '4' %} checked="checked" {% endif %} onclick="manage()" /><label for="star4" title="Great"></label>
+ <input type="radio" id="star3" name="rating" value="3" {% if rating == '3' %} checked="checked" {% endif %} onclick="manage()" /><label for="star3" title="Good"></label>
+ <input type="radio" id="star2" name="rating" value="2" {% if rating == '2' %} checked="checked" {% endif %} onclick="manage()" /><label for="star2" title="Average"></label>
+ <input type="radio" id="star1" name="rating" value="1" {% if rating == '1' %} checked="checked" {% endif %} onclick="manage()" /><label for="star1" title="Poor"></label>
</fieldset>
</div>
diff --git a/ForgeFeedback/forgefeedback/templates/feedback/feedback_list.html b/ForgeFeedback/forgefeedback/templates/feedback/feedback_list.html
old mode 100644
new mode 100755
diff --git a/ForgeFeedback/forgefeedback/templates/feedback/index.html b/ForgeFeedback/forgefeedback/templates/feedback/index.html
old mode 100644
new mode 100755
index fe96856..853c4d1
--- a/ForgeFeedback/forgefeedback/templates/feedback/index.html
+++ b/ForgeFeedback/forgefeedback/templates/feedback/index.html
@@ -9,7 +9,7 @@
http://www.apache.org/licenses/LICENSE-2.0
- e Unless required by applicable law or agreed to in writing,
+ 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
@@ -38,7 +38,7 @@
{% if user_has_already_reviewed == False %}
<p><h2> Provide your <a href="{{c.app.url}}new_feedback">Feedback</a> for {{c.project.name}} </h2></p>
{% else %}
- <p><h2><a href="{{c.app.url}}edit_feedback"> Edit </a> or <a href="{{c.app.url}}delete_feedback"> Delete </a> your feedback for {{c.project.name}} </h2> </p>
+ <p><h2><a href="{{c.app.url}}edit_feedback"> Edit </a> or <a class="post-link" href="#"> Delete </a> your feedback for {{c.project.name}} </h2> </p>
{% endif %}
</div>
{% else %}
@@ -50,7 +50,20 @@
{% include 'forgefeedback:templates/feedback/feedback_list.html' %}
</ul>
</div>
-{% endblock %}
+{% endblock %}
+{% block extra_js %}
+<script>
+ $('.post-link').click(function() {
+ var cval = $.cookie('_session_id');
+ $.post( '{{c.app.url}}delete_feedback', {'_session_id':cval},
+ function(){
+ window.location.href = '{{c.app.url}}';
+ }
+ );
+
+ });
+</script>
+{% endblock %}
diff --git a/ForgeFeedback/forgefeedback/templates/feedback/new_feedback.html b/ForgeFeedback/forgefeedback/templates/feedback/new_feedback.html
old mode 100644
new mode 100755
index b472aab..bf93b3b
--- a/ForgeFeedback/forgefeedback/templates/feedback/new_feedback.html
+++ b/ForgeFeedback/forgefeedback/templates/feedback/new_feedback.html
@@ -15,7 +15,7 @@
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-This is used when user is trying to imput a new review
+ This is used when user is trying to imput a new review
-#}
{% import 'allura:templates/jinja_master/lib.html' as lib with context %}
@@ -37,7 +37,7 @@ p {
</style>
<div class="feed">
- <form action="{{ c.app.url }}create_feedback" method="post">
+ <form action="{{ c.app.url }}create_feedback" method="post" id="feedback_form">
<div class="row">
<div class="col-25">
diff --git a/ForgeFeedback/forgefeedback/tests/__init__.py b/ForgeFeedback/forgefeedback/tests/__init__.py
old mode 100644
new mode 100755
index 77505f1..144e298
--- a/ForgeFeedback/forgefeedback/tests/__init__.py
+++ b/ForgeFeedback/forgefeedback/tests/__init__.py
@@ -14,4 +14,3 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
-
diff --git a/ForgeFeedback/forgefeedback/tests/functional/__init__.py b/ForgeFeedback/forgefeedback/tests/functional/__init__.py
old mode 100644
new mode 100755
index 77505f1..144e298
--- a/ForgeFeedback/forgefeedback/tests/functional/__init__.py
+++ b/ForgeFeedback/forgefeedback/tests/functional/__init__.py
@@ -14,4 +14,3 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
-
diff --git a/ForgeFeedback/forgefeedback/tests/functional/test_root.py b/ForgeFeedback/forgefeedback/tests/functional/test_root.py
old mode 100644
new mode 100755
index b97eafa..e99fdb5
--- a/ForgeFeedback/forgefeedback/tests/functional/test_root.py
+++ b/ForgeFeedback/forgefeedback/tests/functional/test_root.py
@@ -17,7 +17,8 @@
from tg import tmpl_context as c
from tg import config
-from nose.tools import assert_equal, assert_in, assert_not_in, assert_true, assert_false, assert_raises
+from nose.tools import assert_equal, assert_in, assert_not_in
+from nose.tools import assert_true, assert_false, assert_raises
from allura import model as M
from alluratest.controller import TestController
@@ -26,44 +27,46 @@ from allura.tests import decorators as td
from forgefeedback import model as FM
+
class TestFeedback(TestController):
- def setUp(self):
- TestController.setUp(self)
-
- def test_feedback(self):
- c.user = M.User.by_username('test-admin')
- self.app.get('/feedback/')
- r = self.app.get('/p/test/feedback')
- assert 'test' in r
- assert_in('<a href="/p/test/feedback/new_feedback">Feedback</a>', r)
- def test_new_feedback(self):
- c.user = M.User.by_username('test-admin')
- self.app.get('/feedback/')
- r = self.app.get('/p/test/feedback/new_feedback/')
- assert_in('Provide your feedback for <b> Test Project</b>',r)
- assert_in('Enter your feedback here', r)
+ def setUp(self):
+ TestController.setUp(self)
+
+ def test_feedback(self):
+ c.user = M.User.by_username('test-admin')
+ self.app.get('/feedback/')
+ r = self.app.get('/p/test/feedback')
+ assert 'test' in r
+ assert_in('<a href="/p/test/feedback/new_feedback">Feedback</a>', r)
+
+ def test_new_feedback(self):
+ c.user = M.User.by_username('test-admin')
+ self.app.get('/feedback/')
+ r = self.app.get('/p/test/feedback/new_feedback/')
+ assert_in('Provide your feedback for <b> Test Project</b>', r)
+ assert_in('Enter your feedback here', r)
+
+ def test_create_feedback(self):
+ resp = post_feedback(self)
+ assert_in('Good tool', resp)
- def test_create_feedback(self):
- resp = post_feedback(self)
- assert_in('Good tool',resp)
-
- def test_edit_feedback(self):
- post_feedback(self)
- data = {'rating': '2','description':'Not useful'}
- resp = self.app.post('/p/test/feedback/edit_user_review',data)
- assert_in('Not useful',resp)
+ def test_edit_feedback(self):
+ post_feedback(self)
+ data = {'rating': '2', 'description': 'Not useful'}
+ resp = self.app.post('/p/test/feedback/edit_user_review', data)
+ assert_in('Not useful', resp)
+
+ def test_delete_feedback(self):
+ post_feedback(self)
+ resp = self.app.post('/p/test/feedback/delete_feedback')
+ assert_in('Success', resp)
- def test_delete_feedback(self):
- post_feedback(self)
- resp=self.app.get('/p/test/feedback/delete_feedback')
- assert_in('<a href="/p/test/feedback/new_feedback">Feedback</a>',resp)
-
def post_feedback(self):
- c.user =M.User.by_username('test-admin')
- self.app.get('/feedback/')
- self.app.get('/p/test/feedback')
- data = {'rating':'4','description':'Good tool'}
- resp = self.app.post('/p/test/feedback/create_feedback/',data)
- return resp
+ c.user = M.User.by_username('test-admin')
+ self.app.get('/feedback/')
+ self.app.get('/p/test/feedback')
+ data = {'rating': '4', 'description': 'Good tool'}
+ resp = self.app.post('/p/test/feedback/create_feedback/', data)
+ return resp
diff --git a/ForgeFeedback/forgefeedback/tests/test_feedback_roles.py b/ForgeFeedback/forgefeedback/tests/test_feedback_roles.py
old mode 100644
new mode 100755
index bd7f902..a8ea087
--- a/ForgeFeedback/forgefeedback/tests/test_feedback_roles.py
+++ b/ForgeFeedback/forgefeedback/tests/test_feedback_roles.py
@@ -25,12 +25,13 @@ from allura.lib import security
from allura.tests import decorators as td
from allura.lib import helpers as h
+
def setUp():
setup_basic_test()
setup_with_tools()
-@td.with_tool('u/test-user-1','feedback')
+@td.with_tool('u/test-user-1', 'feedback')
@td.with_user_project('test-user-1')
def setup_with_tools():
setup_global_objects()
@@ -51,4 +52,3 @@ def test_role_assignments():
assert_equal(check_access('create'), (True, True, False))
assert_equal(check_access('update'), (True, False, False))
assert_equal(check_access('delete'), (True, False, False))
-
diff --git a/ForgeFeedback/forgefeedback/tests/unit/__init__.py b/ForgeFeedback/forgefeedback/tests/unit/__init__.py
old mode 100644
new mode 100755
index 9c6667a..193f766
--- a/ForgeFeedback/forgefeedback/tests/unit/__init__.py
+++ b/ForgeFeedback/forgefeedback/tests/unit/__init__.py
@@ -48,4 +48,3 @@ class FeedbackTestWithModel(object):
def tearDown(self):
ThreadLocalORMSession.close_all()
-
diff --git a/ForgeFeedback/forgefeedback/tests/unit/test_feedback.py b/ForgeFeedback/forgefeedback/tests/unit/test_feedback.py
old mode 100644
new mode 100755
index 604041e..03f6944
--- a/ForgeFeedback/forgefeedback/tests/unit/test_feedback.py
+++ b/ForgeFeedback/forgefeedback/tests/unit/test_feedback.py
@@ -22,20 +22,21 @@ from tg import tmpl_context as c
from forgefeedback.tests.unit import FeedbackTestWithModel
from forgefeedback import model as M
+
class TestFeedback(FeedbackTestWithModel):
- def test_feedback(self):
- feedback = M.Feedback()
- feedback.rating='4'
- feedback.description='Very good tool'
- assert_equal(feedback.rating, '4')
- assert_equal(feedback.description, 'Very good tool')
- assert_equal(feedback.activity_extras['summary'], feedback.description)
- assert_true('allura_id' in feedback.activity_extras)
-
- def test_index(self):
- feedback= M.Feedback()
- feedback.rating= '4'
- feedback.description ='Good tool'
- result= feedback.index()
- assert_equal(result["text"], 'Good tool')
+ def test_feedback(self):
+ feedback = M.Feedback()
+ feedback.rating = '4'
+ feedback.description = 'Very good tool'
+ assert_equal(feedback.rating, '4')
+ assert_equal(feedback.description, 'Very good tool')
+ assert_equal(feedback.activity_extras['summary'], feedback.description)
+ assert_true('allura_id' in feedback.activity_extras)
+
+ def test_index(self):
+ feedback = M.Feedback()
+ feedback.rating = '4'
+ feedback.description = 'Good tool'
+ result = feedback.index()
+ assert_equal(result["text"], 'Good tool')
diff --git a/ForgeFeedback/forgefeedback/tests/unit/test_root_controller.py b/ForgeFeedback/forgefeedback/tests/unit/test_root_controller.py
old mode 100644
new mode 100755
index f99332c..4b000b1
--- a/ForgeFeedback/forgefeedback/tests/unit/test_root_controller.py
+++ b/ForgeFeedback/forgefeedback/tests/unit/test_root_controller.py
@@ -30,6 +30,7 @@ from forgefeedback.tests.unit import FeedbackTestWithModel
from forgefeedback.model import Feedback
from forgefeedback import feedback_main
+
class TestFeedbackApp(FeedbackTestWithModel):
def setUp(self):
@@ -39,28 +40,28 @@ class TestFeedbackApp(FeedbackTestWithModel):
def test_index(self):
reviews = feedback_main.RootController().index()
- assert reviews['user_has_already_reviewed']==False
+ assert True if not reviews['user_has_already_reviewed'] else False
create_feedbacks()
reviews = feedback_main.RootController().index()
- assert reviews['user_has_already_reviewed']==True
-
+ assert True if reviews['user_has_already_reviewed'] else False
+
def test_feedback(self):
create_feedbacks()
reviews = feedback_main.RootController().get_review_list()
- assert reviews[0].description =='Very good tool'
- assert reviews[1].description =='Not Useful'
- assert reviews[0].rating =='5'
- assert reviews[1].rating =='2'
+ assert reviews[0].description == 'Very good tool'
+ assert reviews[1].description == 'Not Useful'
+ assert reviews[0].rating == '5'
+ assert reviews[1].rating == '2'
def test_getRating(self):
create_feedbacks()
- rating=feedback_main.RootController().getRating()
- assert_equal(rating,3.5)
+ rating = feedback_main.RootController().getRating()
+ assert_equal(rating, 3.5)
def test_edit_feedback(self):
create_feedbacks()
- old_feedback= feedback_main.RootController().edit_feedback()
- assert old_feedback['description'] =='Very good tool'
+ old_feedback = feedback_main.RootController().edit_feedback()
+ assert old_feedback['description'] == 'Very good tool'
def test_check_feedback(self):
feed_check = feedback_main.RootController().feedback_check('good')
@@ -68,13 +69,15 @@ class TestFeedbackApp(FeedbackTestWithModel):
feed_check = feedback_main.RootController().feedback_check('shit')
assert feed_check == 'true'
+
def create_feedbacks():
- feedback_1= create_feedback('2', 'Not Useful')
- c.user = User(username='test-admin')
- h.set_context('test', 'feedback', neighborhood='Projects')
- feedback_2 = create_feedback('5', 'Very good tool')
+ feedback_1 = create_feedback('2', 'Not Useful')
+ c.user = User(username='test-admin')
+ h.set_context('test', 'feedback', neighborhood='Projects')
+ feedback_2 = create_feedback('5', 'Very good tool')
+
def create_feedback(rating, description):
- feedback = Feedback(rating=rating, description=description)
- session(feedback).flush()
- return feedback
+ feedback = Feedback(rating=rating, description=description)
+ session(feedback).flush()
+ return feedback
diff --git a/ForgeFeedback/forgefeedback/version.py b/ForgeFeedback/forgefeedback/version.py
old mode 100644
new mode 100755
index 1333217..3ea72c5
--- a/ForgeFeedback/forgefeedback/version.py
+++ b/ForgeFeedback/forgefeedback/version.py
@@ -1,4 +1,4 @@
-#Licensed to the Apache Software Foundation (ASF) under one
+# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
@@ -17,8 +17,3 @@
__version_info__ = (0, 0)
__version__ = '.'.join(map(str, __version_info__))
-
-
-
-
-
diff --git a/ForgeFeedback/setup.py b/ForgeFeedback/setup.py
old mode 100644
new mode 100755
[allura] 04/04: More polishing
Posted by br...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
brondsem pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/allura.git
commit 7f41e1514f224cad7394de389b08f1fa8d5e6898
Author: Dave Brondsema <da...@brondsema.net>
AuthorDate: Mon Jan 6 17:06:29 2020 -0500
More polishing
---
Allura/allura/templates/jinja_master/nav_menu.html | 14 +++++++++----
ForgeFeedback/forgefeedback/__init__.py | 16 +++++++++++++++
ForgeFeedback/forgefeedback/feedback_main.py | 24 +++++++++++-----------
ForgeFeedback/forgefeedback/model/feedback.py | 4 ++++
ForgeFeedback/forgefeedback/templates/__init__.py | 16 +++++++++++++++
5 files changed, 58 insertions(+), 16 deletions(-)
diff --git a/Allura/allura/templates/jinja_master/nav_menu.html b/Allura/allura/templates/jinja_master/nav_menu.html
index 9509334..3904896 100644
--- a/Allura/allura/templates/jinja_master/nav_menu.html
+++ b/Allura/allura/templates/jinja_master/nav_menu.html
@@ -64,6 +64,7 @@
{% endif %}
{% endif %}
+{% if c.project.rating %}{# hide if ratings haven't been used (project/site may not use ForgeFeedback) #}
<script>
document.getElementById("stars").innerHTML = getStars("{{c.project.rating}}");
@@ -74,17 +75,22 @@ function getStars(ratings) {
let output = [];
// Append all the filled whole stars
- for (var i = ratings; i >= 1; i--)
+ var i;
+ for (i = ratings; i >= 1; i--) {
output.push('<i class="fa fa-star" aria-hidden="true" style="color: orange;"></i> ');
+ }
// If there is a half a star, append it
- if (i == .5) output.push('<i class="fa fa-star-half-o" aria-hidden="true" style="color: orange;"></i> ');
+ if (i === .5) {
+ output.push('<i class="fa fa-star-half-o" aria-hidden="true" style="color: orange;"></i> ');
+ }
// Fill the empty stars
- for (let i = (5 - ratings); i >= 1; i--)
+ for (let i = (5 - ratings); i >= 1; i--) {
output.push('<i class="fa fa-star-o" aria-hidden="true" style="color: orange;"></i> ');
-
+ }
return output.join('');
}
</script>
+{% endif %}
\ No newline at end of file
diff --git a/ForgeFeedback/forgefeedback/__init__.py b/ForgeFeedback/forgefeedback/__init__.py
index e69de29..144e298 100755
--- a/ForgeFeedback/forgefeedback/__init__.py
+++ b/ForgeFeedback/forgefeedback/__init__.py
@@ -0,0 +1,16 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
diff --git a/ForgeFeedback/forgefeedback/feedback_main.py b/ForgeFeedback/forgefeedback/feedback_main.py
index 4f04b61..889c0f1 100755
--- a/ForgeFeedback/forgefeedback/feedback_main.py
+++ b/ForgeFeedback/forgefeedback/feedback_main.py
@@ -20,7 +20,7 @@ import pymongo
# Non-stdlib imports
-from tg import expose, flash, url, config, request
+from tg import expose, flash, url, config, request, redirect
from tg.decorators import with_trailing_slash, without_trailing_slash
from tg import tmpl_context as c, app_globals as g
from ming.odm import session
@@ -121,7 +121,7 @@ class RootController(BaseController, FeedController):
rating_by_user = Feedback.query.find({
'reported_by_id': c.user._id, 'project_id': c.project._id}
).count()
- if (rating_by_user > 0):
+ if rating_by_user > 0:
user_has_already_reviewed = True
return dict(review_list=self.get_review_list(),
user_has_already_reviewed=user_has_already_reviewed,
@@ -150,8 +150,8 @@ class RootController(BaseController, FeedController):
M.main_orm_session.flush()
g.director.create_activity(c.user, 'posted', p, related_nodes=[
c.project], tags=['description'])
- return dict(review_list=self.get_review_list(),
- rating=self.getRating())
+ self.getRating() # force recalculation
+ redirect(c.app.url)
# called on click of the Feedback link
@with_trailing_slash
@@ -183,8 +183,8 @@ class RootController(BaseController, FeedController):
g.director.create_activity(
c.user, 'modified', self.rating,
related_nodes=[c.project], tags=['description'])
- return dict(
- review_list=self.get_review_list(), rating=self.getRating())
+ self.getRating() # force recalculation
+ redirect(c.app.url)
# called when user clicks on delete link in feedback page
@without_trailing_slash
@@ -198,7 +198,7 @@ class RootController(BaseController, FeedController):
Feedback.query.remove(dict(
{'reported_by_id': c.user._id, 'project_id': c.project._id}))
M.main_orm_session.flush()
- self.getRating()
+ self.getRating() # force recalculation
flash('Feedback successfully deleted')
return 'Success'
else:
@@ -231,7 +231,7 @@ class RootController(BaseController, FeedController):
sum_of_ratings = float(
fivestarcount + fourstarcount + threestarcount + twostarcount +
onestarcount)
- if (sum_of_ratings != 0):
+ if sum_of_ratings != 0:
average_user_ratings = float(
(5*fivestarcount) + (4*fourstarcount) +
(3*threestarcount) + (2*twostarcount) +
@@ -239,12 +239,12 @@ class RootController(BaseController, FeedController):
float_rating = float(average_user_ratings)
int_rating = int(float_rating)
float_point_value = float_rating - int_rating
- if(float_point_value < 0.25):
+ if float_point_value < 0.25:
c.project.rating = int_rating
- elif(float_point_value >= 0.25 < 0.75):
+ elif float_point_value >= 0.25 < 0.75:
c.project.rating = 0.5 + int_rating
- elif(float_point_value >= 0.75):
+ elif float_point_value >= 0.75:
c.project.rating = float(int_rating)+1
return average_user_ratings
- if (sum_of_ratings == 0):
+ if sum_of_ratings == 0:
c.project.rating = 0.0
diff --git a/ForgeFeedback/forgefeedback/model/feedback.py b/ForgeFeedback/forgefeedback/model/feedback.py
index 7cb61e5..9498f70 100755
--- a/ForgeFeedback/forgefeedback/model/feedback.py
+++ b/ForgeFeedback/forgefeedback/model/feedback.py
@@ -41,6 +41,9 @@ class Feedback(VersionedArtifact, ActivityObject):
class __mongometa__:
name = 'feedback'
+ indexes = [
+ ('project_id', 'reported_by_id'),
+ ]
type_s = 'Feedback'
_id = FieldProperty(schema.ObjectId)
@@ -55,6 +58,7 @@ class Feedback(VersionedArtifact, ActivityObject):
result = VersionedArtifact.index(self)
result.update(
created_date_dt=self.created_date,
+ reported_by_username_t=self.reported_by.username,
text=self.description,
)
return result
diff --git a/ForgeFeedback/forgefeedback/templates/__init__.py b/ForgeFeedback/forgefeedback/templates/__init__.py
index e69de29..144e298 100755
--- a/ForgeFeedback/forgefeedback/templates/__init__.py
+++ b/ForgeFeedback/forgefeedback/templates/__init__.py
@@ -0,0 +1,16 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.