Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F76452556
views.py
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Thu, Aug 8, 01:31
Size
14 KB
Mime Type
text/x-python
Expires
Sat, Aug 10, 01:31 (1 d, 23 h)
Engine
blob
Format
Raw Data
Handle
19717214
Attached To
R3600 invenio-infoscience
views.py
View Options
# -*- coding: utf-8 -*-
#
# This file is part of Invenio.
# Copyright (C) 2013 CERN.
#
# Invenio is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2 of the
# License, or (at your option) any later version.
#
# Invenio is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Invenio; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
"""
invenio.modules.tags.blueprint
------------------------------
Tagging interface.
"""
# Flask
from
werkzeug
import
LocalProxy
from
flask
import
render_template
,
request
,
flash
,
redirect
,
url_for
,
\
jsonify
,
Blueprint
from
invenio.base.i18n
import
_
from
invenio.base.decorators
import
wash_arguments
,
templated
from
flask.ext.login
import
current_user
,
login_required
from
invenio.base.globals
import
cfg
# External imports
from
invenio.modules.accounts.models
import
User
from
invenio.modules.records.models
import
Record
as
Bibrec
from
invenio.modules.search.models
import
Collection
from
invenio.modules.search.views.search
import
response_formated_records
from
flask.ext.menu
import
register_menu
from
flask.ext.breadcrumbs
import
default_breadcrumb_root
,
register_breadcrumb
from
invenio.ext.sqlalchemy
import
db
# Internal imports
from
.models
import
\
WtgTAG
,
\
WtgTAGRecord
,
\
wash_tag
# Forms
from
.forms
import
\
CreateTagForm
,
\
AttachTagForm
,
\
DetachTagForm
,
\
EditTagForm
,
\
TagAnnotationForm
,
\
validate_tag_exists
,
\
validate_user_owns_tag
,
\
validators
# Uset settings
user_settings
=
LocalProxy
(
lambda
:
current_user
[
'settings'
]
.
get
(
'webtag'
,
cfg
[
'CFG_WEBTAG_DEFAULT_USER_SETTINGS'
]))
blueprint
=
Blueprint
(
'webtag'
,
__name__
,
url_prefix
=
'/yourtags'
,
template_folder
=
'templates'
,
static_folder
=
'static'
)
default_breadcrumb_root
(
blueprint
,
'.webaccount.tags'
)
@blueprint.route
(
'/'
,
methods
=
[
'GET'
,
'POST'
])
@blueprint.route
(
'/display'
,
methods
=
[
'GET'
,
'POST'
])
@blueprint.route
(
'/display/cloud'
,
methods
=
[
'GET'
,
'POST'
])
@login_required
@templated
(
'tags/display_cloud.html'
)
@register_menu
(
blueprint
,
'personalize.tags'
,
_
(
'Your Tags'
))
@register_breadcrumb
(
blueprint
,
'.'
,
_
(
'Your Tags'
))
def
display_cloud
():
""" List of user's private/group/public tags """
user
=
User
.
query
.
get
(
current_user
.
get_id
())
tags
=
user
.
tags_query
.
order_by
(
WtgTAG
.
name
)
.
all
()
# Calculate document count for each tag
min_count
=
0
max_count
=
0
for
tag
in
tags
:
if
tag
.
record_count
>
max_count
:
max_count
=
tag
.
record_count
if
tag
.
record_count
<
min_count
:
min_count
=
tag
.
record_count
difference
=
float
(
max_count
-
min_count
)
if
not
difference
:
difference
=
1.0
# Assign sizes
min_size
=
1.0
max_size
=
2.0
for
tag
in
tags
:
size
=
min_size
+
\
float
(
max_size
-
min_size
)
*
\
float
(
tag
.
record_count
-
min_count
)
/
difference
tag
.
css_size
=
str
(
size
*
100
)
return
dict
(
user_tags
=
tags
,
display_mode
=
'cloud'
)
@blueprint.route
(
'/display/list'
,
methods
=
[
'GET'
,
'POST'
])
@login_required
@templated
(
'tags/display_list.html'
)
@wash_arguments
({
'sort_by'
:
(
unicode
,
'name'
),
'order'
:
(
unicode
,
''
)})
@register_breadcrumb
(
blueprint
,
'.list'
,
_
(
'Display as List'
))
def
display_list
(
sort_by
,
order
):
""" List of user's private/group/public tags """
tags
=
User
.
query
.
get
(
current_user
.
get_id
())
.
tags_query
sort_by
=
str
(
sort_by
)
order
=
str
(
order
)
if
sort_by
==
'record_count'
:
tags
=
tags
.
order_by
(
WtgTAG
.
record_count
)
else
:
tags
=
tags
.
order_by
(
WtgTAG
.
name
)
tags
=
tags
.
all
()
if
order
==
'desc'
:
tags
.
reverse
()
return
dict
(
user_tags
=
tags
,
display_mode
=
'list'
)
@blueprint.route
(
'/tag/<int:id_tag>/records'
,
methods
=
[
'GET'
,
'POST'
])
@login_required
@register_breadcrumb
(
blueprint
,
'.tags_details'
,
_
(
'Associated Records'
))
def
tag_details
(
id_tag
):
""" List of documents attached to this tag """
if
not
id_tag
:
flash
(
_
(
'Invalid tag id'
),
"error"
)
return
redirect
(
url_for
(
'.display_cloud'
))
tag
=
WtgTAG
.
query
.
get
(
id_tag
)
if
not
tag
:
flash
(
_
(
'Invalid tag id'
),
"error"
)
return
redirect
(
url_for
(
'.display_cloud'
))
if
tag
.
id_user
!=
current_user
.
get_id
():
flash
(
_
(
'You are not authorized to view this tag'
),
"error"
)
return
redirect
(
url_for
(
'.display_cloud'
))
if
not
tag
.
records
:
flash
(
_
(
'There are no documents tagged with '
)
+
tag
.
name
)
return
redirect
(
url_for
(
'.display_cloud'
))
return
response_formated_records
([
bibrec
.
id
for
bibrec
in
tag
.
records
],
Collection
.
query
.
get
(
1
),
'hb'
)
@blueprint.route
(
'/tag/<int:id_tag>/edit'
,
methods
=
[
'GET'
,
'POST'
])
@login_required
@templated
(
'tags/record_tags_test.html'
)
# FIXME: tag editor template missing?
@register_breadcrumb
(
blueprint
,
'.tag_edit'
,
_
(
'Edit tag'
))
def
tag_edit
(
id_tag
):
""" List of documents attached to this tag """
id_user
=
current_user
.
get_id
()
tag
=
WtgTAG
.
query
.
get
(
id_tag
)
if
not
tag
:
flash
(
_
(
'Invalid tag id'
),
"error"
)
return
redirect
(
url_for
(
'.display_cloud'
))
if
tag
.
id_user
!=
id_user
:
flash
(
_
(
'You are not authorized to view this tag'
),
"error"
)
return
redirect
(
url_for
(
'.display_cloud'
))
form
=
EditTagForm
(
request
.
values
,
csrf_enabled
=
False
,
obj
=
tag
)
if
form
.
validate_on_submit
():
form
.
populate_obj
(
tag
)
name_count
=
db
.
session
.
query
(
WtgTAG
)
.
\
filter_by
(
id_user
=
id_user
,
name
=
tag
.
name
)
.
count
()
if
name_count
==
1
:
db
.
session
.
add
(
tag
)
db
.
session
.
commit
()
flash
(
_
(
'Tag Successfully edited.'
),
'success'
)
else
:
flash
(
_
(
'Tag name'
)
+
' <strong>'
+
tag
.
name
+
'</strong> '
+
_
(
'is already in use.'
),
'error'
)
return
dict
(
tag
=
tag
,
form
=
form
)
@blueprint.route
(
'/tag/<int:id_tag>/annotations/<int:id_bibrec>'
,
methods
=
[
'GET'
,
'POST'
])
@login_required
def
update_annotation
(
id_tag
,
id_bibrec
):
""" Change the annotation on relationship between record and tag """
from
werkzeug.datastructures
import
MultiDict
values
=
MultiDict
(
request
.
values
)
values
[
'id_tag'
]
=
id_tag
values
[
'id_bibrec'
]
=
id_bibrec
form
=
TagAnnotationForm
(
values
,
csrf_enabled
=
False
)
if
form
.
validate
():
relation
=
db
.
session
.
query
(
WtgTAGRecord
)
\
.
filter
(
WtgTAGRecord
.
id_tag
==
id_tag
)
\
.
filter
(
WtgTAGRecord
.
id_bibrec
==
id_bibrec
)
\
.
one
()
relation
.
annotation
=
form
.
data
.
get
(
'annotation_value'
,
''
)
db
.
session
.
add
(
relation
)
db
.
session
.
commit
()
return
relation
.
annotation
else
:
return
str
(
form
.
errors
)
@blueprint.route
(
'/record/<int:id_bibrec>/tags'
,
methods
=
[
'GET'
,
'POST'
])
@login_required
@templated
(
'tags/record_tags_test.html'
)
@register_breadcrumb
(
blueprint
,
'.tags_details'
,
_
(
'Tag list'
))
def
record_tags
(
id_bibrec
):
""" List of documents attached to this tag """
from
.template_context_functions.tfn_webtag_record_tags
\
import
template_context_function
from
invenio.ext.template
import
render_template_to_string
return
dict
(
tag_list
=
template_context_function
(
id_bibrec
,
current_user
.
get_id
()))
@blueprint.route
(
'/tokenize/<int:id_bibrec>'
,
methods
=
[
'GET'
,
'POST'
])
@login_required
@wash_arguments
({
'q'
:
(
unicode
,
''
)})
def
tokenize
(
id_bibrec
,
q
):
""" Data for tokeninput """
id_user
=
current_user
.
get_id
()
# Output only tags unattached to this record
record
=
Bibrec
.
query
.
get
(
id_bibrec
)
tags
=
WtgTAG
.
query
\
.
filter_by
(
id_user
=
id_user
)
\
.
filter
(
WtgTAG
.
name
.
like
(
'%'
+
q
+
'%'
))
\
.
filter
(
db
.
not_
(
WtgTAG
.
records
.
contains
(
record
)))
\
.
order_by
(
WtgTAG
.
name
)
# If a tag with searched name does not exist, lets suggest creating it
# Clean the name
new_name
=
wash_tag
(
q
)
add_new_name
=
True
response_tags
=
[]
for
tag
in
tags
.
all
():
tag_json
=
tag
.
serializable_fields
(
set
([
'id'
,
'name'
]))
response_tags
.
append
(
tag_json
)
# Check if it matches the search name
if
tag_json
[
'name'
]
==
new_name
:
add_new_name
=
False
#If the name was not found
if
add_new_name
:
# Check if a tag with this name is already attached
already_attached
=
WtgTAG
.
query
\
.
join
(
WtgTAGRecord
)
\
.
filter
(
WtgTAG
.
name
==
new_name
)
\
.
filter
(
WtgTAGRecord
.
id_bibrec
==
id_bibrec
)
\
.
count
()
if
not
already_attached
:
tag_json
=
{
'id'
:
0
,
'name'
:
new_name
}
response_tags
.
append
(
tag_json
)
return
jsonify
(
dict
(
results
=
response_tags
,
query
=
q
))
@blueprint.route
(
'/record/<int:id_bibrec>/edit'
,
methods
=
[
'GET'
,
'POST'
])
@login_required
def
editor
(
id_bibrec
):
"""Edits your tags for `id_bibrec`.
:param id_bibrec: record identifier"""
user
=
db
.
session
.
query
(
User
)
.
get
(
current_user
.
get_id
())
record
=
db
.
session
.
query
(
Bibrec
)
.
get
(
id_bibrec
)
tags
=
db
.
session
.
query
(
WtgTAG
)
\
.
filter_by
(
user
=
user
)
\
.
filter
(
WtgTAG
.
records
.
contains
(
record
))
tags_json
=
[]
for
tag
in
tags
.
all
():
fields
=
tag
.
serializable_fields
(
set
([
'id'
,
'name'
]))
fields
[
'can_remove'
]
=
True
tags_json
.
append
(
fields
)
# invenio_templated cannot be used,
# because this view is requested using AJAX
return
render_template
(
'tags/record_editor.html'
,
id_bibrec
=
id_bibrec
,
record_tags
=
tags_json
)
#Temporary solution to call validators, we need a better one
class
Field
(
object
):
def
__init__
(
self
,
attr
,
value
):
setattr
(
self
,
attr
,
value
)
@blueprint.route
(
'/delete'
,
methods
=
[
'GET'
,
'POST'
])
@login_required
def
delete
():
""" Delete a tag """
response
=
{}
response
[
'action'
]
=
'delete'
id_tags
=
request
.
values
.
getlist
(
'id_tag'
,
type
=
int
)
# Validate
for
id_tag
in
id_tags
:
try
:
field
=
Field
(
'data'
,
id_tag
)
validate_tag_exists
(
None
,
field
)
validate_user_owns_tag
(
None
,
field
)
except
validators
.
ValidationError
as
ex
:
flash
(
ex
.
message
,
'error'
)
for
id_tag
in
id_tags
:
tag
=
WtgTAG
.
query
.
get
(
id_tag
)
db
.
session
.
delete
(
tag
)
db
.
session
.
commit
()
#WtgTAG.query\
# .filter(WtgTAG.id.in_(id_tags))\
# .delete(synchronize_session=False)
flash
(
_
(
'Successfully deleted tags.'
),
'success'
)
return
redirect
(
url_for
(
'.display_list'
))
# AJAX
# reposnse template:
# action = name of action 'create' 'attach' 'detach'
# success = True / False
#
# if success:
# id_tag = id of tag participating in process
# id_bibrec = id of bibrec (if present in action)
# items = created or deleted model objects
#
# else:
# errors = dict of errors from form
@blueprint.route
(
'/create'
,
methods
=
[
'GET'
,
'POST'
])
@login_required
@register_breadcrumb
(
blueprint
,
'.create'
,
_
(
'New tag'
))
@templated
(
'tags/create.html'
)
def
create
():
""" Create a new tag """
response
=
{}
response
[
'action'
]
=
'create'
user
=
User
.
query
.
get
(
current_user
.
get_id
())
form
=
CreateTagForm
(
request
.
values
,
csrf_enabled
=
False
)
if
form
.
validate_on_submit
()
or
\
(
request
.
is_xhr
and
form
.
validate
()):
new_tag
=
WtgTAG
()
form
.
populate_obj
(
new_tag
)
new_tag
.
user
=
user
db
.
session
.
add
(
new_tag
)
db
.
session
.
flush
()
db
.
session
.
refresh
(
new_tag
)
if
'id_bibrec'
in
form
.
data
and
form
.
data
[
'id_bibrec'
]:
record
=
db
.
session
.
query
(
Bibrec
)
.
get
(
form
.
data
[
'id_bibrec'
])
new_tag
.
records
.
append
(
record
)
db
.
session
.
add
(
new_tag
)
response
[
'id_bibrec'
]
=
form
.
data
[
'id_bibrec'
]
db
.
session
.
commit
()
db
.
session
.
refresh
(
new_tag
)
response
[
'success'
]
=
True
response
[
'id_tag'
]
=
new_tag
.
id
response
[
'items'
]
=
[
new_tag
.
serializable_fields
()]
if
request
.
is_xhr
:
return
jsonify
(
response
)
else
:
return
redirect
(
url_for
(
'.display_list'
))
else
:
if
request
.
is_xhr
:
response
[
'success'
]
=
False
response
[
'errors'
]
=
form
.
errors
return
jsonify
(
response
)
else
:
return
dict
(
form
=
form
)
@blueprint.route
(
'/attach'
,
methods
=
[
'GET'
,
'POST'
])
@login_required
def
attach
():
""" Attach a tag to a record """
response
=
{}
response
[
'action'
]
=
'attach'
# Ajax - disable csrf
form
=
AttachTagForm
(
request
.
values
,
csrf_enabled
=
False
)
if
form
.
validate
():
association
=
WtgTAGRecord
()
form
.
populate_obj
(
association
)
db
.
session
.
add
(
association
)
db
.
session
.
commit
()
response
[
'success'
]
=
True
response
[
'id_tag'
]
=
association
.
id_tag
response
[
'id_bibrec'
]
=
association
.
id_bibrec
response
[
'items'
]
=
[
association
.
serializable_fields
()]
else
:
response
[
'success'
]
=
False
response
[
'errors'
]
=
form
.
errors
return
jsonify
(
response
)
@blueprint.route
(
'/detach'
,
methods
=
[
'GET'
,
'POST'
])
@login_required
def
detach
():
""" Detach a tag from a record """
response
=
{}
response
[
'action'
]
=
'detach'
# Ajax - disable csrf
form
=
DetachTagForm
(
request
.
values
,
csrf_enabled
=
False
)
if
form
.
validate
():
association
=
db
.
session
.
query
(
WtgTAGRecord
)
\
.
filter_by
(
id_tag
=
form
.
data
[
'id_tag'
],
id_bibrec
=
form
.
data
[
'id_bibrec'
])
.
first
()
if
association
:
db
.
session
.
delete
(
association
)
db
.
session
.
commit
()
response
[
'success'
]
=
True
response
[
'id_tag'
]
=
association
.
id_tag
response
[
'id_bibrec'
]
=
association
.
id_bibrec
response
[
'items'
]
=
[
association
.
serializable_fields
()]
else
:
response
[
'success'
]
=
False
response
[
'errors'
]
=
form
.
errors
return
jsonify
(
response
)
Event Timeline
Log In to Comment