Skip to content

Commit 9d8f1b6

Browse files
committed
Added summary page
Change data uri of class methods from /rest/class to /rest/data/class committer: Ralf Schlatterbeck <[email protected]>
1 parent 04d3171 commit 9d8f1b6

File tree

1 file changed

+99
-26
lines changed

1 file changed

+99
-26
lines changed

roundup/rest.py

Lines changed: 99 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import traceback
1515
import xml
1616
from roundup import hyperdb
17+
from roundup import date
1718
from roundup.exceptions import *
1819

1920

@@ -70,6 +71,7 @@ def format_object(self, *args, **kwargs):
7071
return result
7172
return format_object
7273

74+
7375
def parse_accept_header(accept):
7476
"""
7577
Parse the Accept header *accept*, returning a list with 3-tuples of
@@ -111,7 +113,7 @@ def parse_accept_header(accept):
111113
version = media_params.append(('version',
112114
float(rest)))
113115
except ValueError:
114-
version = 1.0 # could not be parsed
116+
version = 1.0 # could not be parsed
115117
# add the vendor code as a media param
116118
media_params.append(('vendor', vnd))
117119
# and re-write media_type to something like application/json so
@@ -130,6 +132,7 @@ def parse_accept_header(accept):
130132
result.sort(lambda x, y: -cmp(x[2], y[2]))
131133
return result
132134

135+
133136
class RestfulInstance(object):
134137
"""The RestfulInstance performs REST request from the client"""
135138

@@ -877,6 +880,68 @@ def option_attribute(self, class_name, item_id, attr_name, input):
877880
)
878881
return 204, ""
879882

883+
@_data_decorator
884+
def summary(self, input):
885+
"""Get a summary of resource from class URI.
886+
887+
This function returns only items have View permission
888+
class_name should be valid already
889+
890+
Args:
891+
class_name (string): class name of the resource (Ex: issue, msg)
892+
input (list): the submitted form of the user
893+
894+
Returns:
895+
int: http status code 200 (OK)
896+
list:
897+
"""
898+
if not self.db.security.hasPermission(
899+
'View', self.db.getuid(), 'issue'
900+
) and not self.db.security.hasPermission(
901+
'View', self.db.getuid(), 'status'
902+
) and not self.db.security.hasPermission(
903+
'View', self.db.getuid(), 'issue'
904+
):
905+
raise Unauthorised('Permission to view summary denied')
906+
907+
old = date.Date('-1w')
908+
909+
created = []
910+
summary = {}
911+
messages = []
912+
913+
# loop through all the recently-active issues
914+
for issue_id in self.db.issue.filter(None, {'activity': '-1w;'}):
915+
num = 0
916+
status_name = self.db.status.get(
917+
self.db.issue.get(issue_id, 'status'),
918+
'name'
919+
)
920+
issue_object = {
921+
'id': issue_id,
922+
'link': self.base_path + 'issue' + issue_id,
923+
'title': self.db.issue.get(issue_id, 'title')
924+
}
925+
for x, ts, uid, action, data in self.db.issue.history(issue_id):
926+
if ts < old:
927+
continue
928+
if action == 'create':
929+
created.append(issue_object)
930+
elif action == 'set' and 'messages' in data:
931+
num += 1
932+
summary.setdefault(status_name, []).append(issue_object)
933+
messages.append((num, issue_object))
934+
935+
messages.sort(reverse=True)
936+
937+
result = {
938+
'created': created,
939+
'summary': summary,
940+
'most_discussed': messages[:10]
941+
}
942+
943+
return 200, result
944+
880945
def dispatch(self, method, uri, input):
881946
"""format and process the request"""
882947
# if X-HTTP-Method-Override is set, follow the override method
@@ -920,34 +985,42 @@ def dispatch(self, method, uri, input):
920985

921986
# PATH is split to multiple pieces
922987
# 0 - rest
923-
# 1 - resource
924-
# 2 - attribute
925-
uri_split = uri.split("/")
926-
resource_uri = uri_split[1]
927-
928-
try:
929-
class_name, item_id = hyperdb.splitDesignator(resource_uri)
930-
except hyperdb.DesignatorError:
931-
class_name = resource_uri
932-
item_id = None
988+
# 1 - data
989+
# 2 - resource
990+
# 3 - attribute
991+
uri_split = uri.lower().split("/")
933992

934993
# Call the appropriate method
935-
if (class_name not in self.db.classes) or (len(uri_split) > 3):
936-
output = self.error_obj(404, "Not found")
937-
elif item_id is None:
938-
if len(uri_split) == 2:
939-
output = getattr(
940-
self, "%s_collection" % method.lower()
941-
)(class_name, input)
942-
else:
943-
if len(uri_split) == 2:
944-
output = getattr(
945-
self, "%s_element" % method.lower()
946-
)(class_name, item_id, input)
994+
if len(uri_split) == 2 and uri_split[1] == 'summary':
995+
output = self.summary(input)
996+
elif 4 >= len(uri_split) > 2 and uri_split[1] == 'data':
997+
resource_uri = uri_split[2]
998+
try:
999+
class_name, item_id = hyperdb.splitDesignator(resource_uri)
1000+
except hyperdb.DesignatorError:
1001+
class_name = resource_uri
1002+
item_id = None
1003+
1004+
if class_name not in self.db.classes:
1005+
output = self.error_obj(404, "Not found")
1006+
elif item_id is None:
1007+
if len(uri_split) == 3:
1008+
output = getattr(
1009+
self, "%s_collection" % method.lower()
1010+
)(class_name, input)
1011+
else:
1012+
output = self.error_obj(404, "Not found")
9471013
else:
948-
output = getattr(
949-
self, "%s_attribute" % method.lower()
950-
)(class_name, item_id, uri_split[2], input)
1014+
if len(uri_split) == 3:
1015+
output = getattr(
1016+
self, "%s_element" % method.lower()
1017+
)(class_name, item_id, input)
1018+
else:
1019+
output = getattr(
1020+
self, "%s_attribute" % method.lower()
1021+
)(class_name, item_id, uri_split[3], input)
1022+
else:
1023+
output = self.error_obj(404, "Not found")
9511024

9521025
# Format the content type
9531026
if data_type.lower() == "json":

0 commit comments

Comments
 (0)