Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-platform
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
edx-platform
Commits
131c63b6
Commit
131c63b6
authored
Mar 25, 2013
by
Arthur Barrett
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
refactored model and api to search/filter by page uri
parent
0574eb49
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
128 additions
and
33 deletions
+128
-33
lms/djangoapps/notes/api.py
+31
-6
lms/djangoapps/notes/models.py
+53
-9
lms/djangoapps/notes/urls.py
+1
-1
lms/static/coffee/src/notes.coffee
+42
-15
lms/templates/static_htmlbook.html
+1
-2
No files found.
lms/djangoapps/notes/api.py
View file @
131c63b6
from
django.http
import
HttpResponse
,
Http404
from
django.core.exceptions
import
ValidationError
from
notes.models
import
Note
import
json
import
logging
...
...
@@ -73,13 +74,19 @@ def api_format(request, response, data):
# Exposed API actions via the resource map.
def
index
(
request
,
course_id
):
notes
=
Note
.
objects
.
all
(
)
notes
=
Note
.
objects
.
filter
(
course_id
=
course_id
,
user
=
request
.
user
)
return
[
HttpResponse
(),
[
note
.
as_dict
()
for
note
in
notes
]]
def
create
(
request
,
course_id
):
note
=
Note
(
course_id
=
course_id
,
body
=
request
.
body
,
user
=
request
.
user
)
note
.
save
()
note
=
Note
(
course_id
=
course_id
,
user
=
request
.
user
)
try
:
note
.
clean
(
request
.
body
)
except
ValidationError
as
e
:
log
.
debug
(
e
)
return
[
HttpResponse
(
''
,
status
=
500
),
None
]
note
.
save
()
response
=
HttpResponse
(
''
,
status
=
303
)
response
[
'Location'
]
=
note
.
get_absolute_url
()
...
...
@@ -105,8 +112,13 @@ def update(request, course_id, note_id):
if
not
note
.
user
.
id
==
request
.
user
.
id
:
return
[
HttpResponse
(
''
,
status
=
403
)]
note
.
body
=
request
.
body
note
.
save
(
update_fields
=
[
'body'
,
'updated'
])
try
:
note
.
clean
(
request
.
body
)
except
ValidationError
as
e
:
log
.
debug
(
e
)
return
[
HttpResponse
(
''
,
status
=
500
),
None
]
note
.
save
(
update_fields
=
[
'text'
,
'tags'
,
'updated'
])
return
[
HttpResponse
(
''
,
status
=
303
),
None
]
...
...
@@ -124,7 +136,20 @@ def delete(request, course_id, note_id):
return
[
HttpResponse
(
''
,
status
=
204
),
None
]
def
search
(
request
,
course_id
):
return
[
HttpResponse
(),
[]]
limit
=
request
.
GET
.
get
(
'limit'
)
uri
=
request
.
GET
.
get
(
'uri'
)
filters
=
{
'course_id'
:
course_id
,
'user'
:
request
.
user
}
if
uri
is
not
None
:
filters
[
'uri'
]
=
uri
notes
=
Note
.
objects
.
filter
(
**
filters
)
#if limit is not None and limit > 0:
#notes = notes[:limit]
result
=
{
'rows'
:
[
note
.
as_dict
()
for
note
in
notes
]}
return
[
HttpResponse
(),
result
]
def
version
(
request
,
course_id
):
return
[
HttpResponse
(),
{
'name'
:
'Notes API'
,
'version'
:
'1.0'
}]
lms/djangoapps/notes/models.py
View file @
131c63b6
from
django.db
import
models
from
django.contrib.auth.models
import
User
from
django.core.urlresolvers
import
reverse
from
django.core.exceptions
import
ValidationError
import
json
import
logging
log
=
logging
.
getLogger
(
__name__
)
class
Note
(
models
.
Model
):
user
=
models
.
ForeignKey
(
User
,
db_index
=
True
)
course_id
=
models
.
CharField
(
max_length
=
255
,
db_index
=
True
)
uri
=
models
.
CharField
(
max_length
=
1024
,
db_index
=
True
)
text
=
models
.
TextField
(
default
=
""
)
quote
=
models
.
TextField
(
default
=
""
)
range_start
=
models
.
CharField
(
max_length
=
2048
)
range_start_offset
=
models
.
IntegerField
()
range_end
=
models
.
CharField
(
max_length
=
2048
)
range_end_offset
=
models
.
IntegerField
()
tags
=
models
.
TextField
(
default
=
""
)
# comma-separated string
created
=
models
.
DateTimeField
(
auto_now_add
=
True
,
null
=
True
,
db_index
=
True
)
updated
=
models
.
DateTimeField
(
auto_now
=
True
,
db_index
=
True
)
body
=
models
.
TextField
()
def
clean
(
self
,
json_body
):
if
json_body
is
None
:
raise
ValidationError
(
'Note must have a body.'
)
body
=
json
.
loads
(
json_body
)
if
not
type
(
body
)
is
dict
:
raise
ValidationError
(
'Note body must be a dictionary.'
)
self
.
uri
=
body
.
get
(
'uri'
)
self
.
text
=
body
.
get
(
'text'
)
self
.
quote
=
body
.
get
(
'quote'
)
ranges
=
body
.
get
(
'ranges'
)
if
ranges
is
None
or
len
(
ranges
)
!=
1
:
raise
ValidationError
(
'Note must contain exactly one range.'
)
self
.
range_start
=
ranges
[
0
][
'start'
]
self
.
range_start_offset
=
ranges
[
0
][
'startOffset'
]
self
.
range_end
=
ranges
[
0
][
'end'
]
self
.
range_end_offset
=
ranges
[
0
][
'endOffset'
]
self
.
tags
=
""
tags
=
body
.
get
(
'tags'
,
[])
if
len
(
tags
)
>
0
:
self
.
tags
=
","
.
join
(
tags
)
def
get_absolute_url
(
self
):
kwargs
=
{
'course_id'
:
self
.
course_id
,
'note_id'
:
str
(
self
.
id
)}
return
reverse
(
'notes_api_note'
,
kwargs
=
kwargs
)
def
as_dict
(
self
):
d
=
{}
json_body
=
json
.
loads
(
self
.
body
)
if
type
(
json_body
)
is
dict
:
d
.
update
(
json_body
)
d
[
'id'
]
=
self
.
id
d
[
'user_id'
]
=
self
.
user
.
id
return
d
\ No newline at end of file
return
{
'id'
:
self
.
id
,
'user_id'
:
self
.
user
.
id
,
'uri'
:
self
.
uri
,
'text'
:
self
.
text
,
'quote'
:
self
.
quote
,
'ranges'
:
[{
'start'
:
self
.
range_start
,
'startOffset'
:
self
.
range_start_offset
,
'end'
:
self
.
range_end
,
'endOffset'
:
self
.
range_end_offset
}],
'tags'
:
self
.
tags
.
split
(
","
)
}
\ No newline at end of file
lms/djangoapps/notes/urls.py
View file @
131c63b6
...
...
@@ -5,5 +5,5 @@ urlpatterns = patterns('notes.api',
url
(
r'^api$'
,
'api_request'
,
{
'resource'
:
'root'
},
name
=
'notes_api_root'
),
url
(
r'^api/annotations$'
,
'api_request'
,
{
'resource'
:
'notes'
},
name
=
'notes_api_notes'
),
url
(
r'^api/annotations/'
+
id_regex
+
r'$'
,
'api_request'
,
{
'resource'
:
'note'
},
name
=
'notes_api_note'
),
url
(
r'^api/
annotations/search$
'
,
'api_request'
,
{
'resource'
:
'search'
},
name
=
'notes_api_search'
)
url
(
r'^api/
search
'
,
'api_request'
,
{
'resource'
:
'search'
},
name
=
'notes_api_search'
)
)
lms/static/coffee/src/notes.coffee
View file @
131c63b6
class
StudentNotes
_debug
:
true
targets
:
[]
# elements with annotator() instances
targets
:
[]
#
holds
elements with annotator() instances
# Adds a listener for "notes" events that may bubble up from descendants.
constructor
:
(
$
,
el
)
->
console
.
log
'student notes init'
,
arguments
,
this
if
@
_debug
if
$
(
el
).
data
(
'notes-ready'
)
isnt
'yes'
$
(
el
).
delegate
'*'
,
'notes:init'
:
@
onInitNotes
$
(
el
).
data
(
'notes-ready'
,
'yes'
)
if
not
$
(
el
).
data
(
'notes-instance'
)
events
=
'notes:init'
:
@
onInitNotes
$
(
el
).
delegate
(
'*'
,
events
)
$
(
el
).
data
(
'notes-instance'
,
@
)
onInitNotes
:
(
event
,
annotationData
=
null
)
=>
# Initializes annotations on a container element in response to an init event.
onInitNotes
:
(
event
,
uri
=
null
)
=>
event
.
stopPropagation
()
storeConfig
=
@
getStoreConfig
uri
found
=
@
targets
.
some
(
target
)
->
target
is
event
.
target
if
found
annotator
=
$
(
event
.
target
).
data
(
'annotator'
)
if
annotator
store
=
annotator
.
plugins
[
'Store'
]
store
.
options
.
annotationData
=
annotationData
if
annotationData
store
.
loadAnnotations
()
$
.
extend
(
store
.
options
,
storeConfig
)
if
uri
store
.
loadAnnotationsFromSearch
(
storeConfig
[
'loadFromSearch'
])
else
console
.
log
'URI is required to load annotations'
else
console
.
log
'No annotator() instance found for target: '
,
event
.
target
else
$
(
event
.
target
).
annotator
()
.
annotator
(
'addPlugin'
,
'Tags'
)
.
annotator
(
'addPlugin'
,
'Store'
,
@
getStoreConfig
(
annotationData
)
)
.
annotator
(
'addPlugin'
,
'Store'
,
storeConfig
)
@
targets
.
push
(
event
.
target
)
getStoreConfig
:
(
annotationData
)
->
# Returns a JSON config object that can be passed to the annotator Store plugin
getStoreConfig
:
(
uri
)
->
prefix
=
@
getPrefix
()
if
uri
is
null
console
.
log
'getURIPath()'
,
uri
,
@
getURIPath
()
uri
=
@
getURIPath
()
storeConfig
=
prefix
:
@
getPrefix
()
prefix
:
prefix
loadFromSearch
:
uri
:
uri
limit
:
0
annotationData
:
uri
:
@
getURIPath
()
# defaults to current URI path
$
.
extend
storeConfig
.
annotationData
,
annotationData
if
annotationData
uri
:
uri
storeConfig
# Returns the API endpoint for the annotation store
getPrefix
:
()
->
re
=
/^(\/courses\/[^/]+\/[^/]+\/[^/]+)/
match
=
re
.
exec
(
@
getURIPath
())
prefix
=
(
if
match
then
match
[
1
]
else
''
)
return
"
#{
prefix
}
/notes/api"
# Returns the URI path of the current page for filtering annotations
getURIPath
:
()
->
window
.
location
.
href
.
toString
().
split
(
window
.
location
.
host
)[
1
]
$
(
document
).
ready
(
$
)
->
new
StudentNotes
(
$
,
this
)
\ No newline at end of file
# Enable notes by default on the document root.
# To initialize annotations on a container element in the document:
#
# $('#myElement').trigger('notes:init');
#
# Comment this line to disable notes.
$
(
document
).
ready
(
$
)
->
new
StudentNotes
$
,
@
\ No newline at end of file
lms/templates/static_htmlbook.html
View file @
131c63b6
...
...
@@ -33,8 +33,7 @@
var
onComplete
=
function
(
url
)
{
return
function
()
{
var
annotationData
=
{
'uri'
:
url
}
$
(
'#viewerContainer'
).
trigger
(
'notes:init'
,
[
annotationData
]);
$
(
'#viewerContainer'
).
trigger
(
'notes:init'
,
[
url
]);
}
};
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment