[062892]: / ForgeFeedback / forgefeedback / feedback_main.py  Maximize  Restore  History

Download this file

251 lines (221 with data), 9.9 kB

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
# 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, 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
from ming.odm 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
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().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().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=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({'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'])
self.getRating() # force recalculation
redirect(c.app.url)
# 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
@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'])
self.getRating() # force recalculation
redirect(c.app.url)
# 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()
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() # force recalculation
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()
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