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
f88b266c
Commit
f88b266c
authored
Jul 23, 2013
by
Miles Steele
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
add member list widget, add segment.io call for section view
parent
588a307d
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
450 additions
and
129 deletions
+450
-129
lms/static/coffee/src/instructor_dashboard/instructor_dashboard.coffee
+1
-1
lms/static/coffee/src/instructor_dashboard/membership.coffee
+175
-7
lms/static/images/info-icon-dark.png
+0
-0
lms/static/sass/course/instructor/_instructor_2.scss
+190
-73
lms/templates/courseware/instructor_dashboard_2/instructor_dashboard_2.html
+1
-0
lms/templates/courseware/instructor_dashboard_2/membership.html
+83
-48
No files found.
lms/static/coffee/src/instructor_dashboard/instructor_dashboard.coffee
View file @
f88b266c
...
...
@@ -64,7 +64,7 @@ setup_instructor_dashboard = (idash_content) =>
section
.
addClass
CSS_ACTIVE_SECTION
# tracking
# analytics.pageview "instructor_
#{section_name}"
analytics
.
pageview
"instructor_section:
#{
section_name
}
"
# deep linking
# write to url
...
...
lms/static/coffee/src/instructor_dashboard/membership.coffee
View file @
f88b266c
...
...
@@ -7,6 +7,175 @@ plantTimeout = -> window.InstructorDashboard.util.plantTimeout.apply this, argum
std_ajax_err
=
->
window
.
InstructorDashboard
.
util
.
std_ajax_err
.
apply
this
,
arguments
class
MemberListWidget
# create a MemberListWidget `$container` is a jquery object to embody.
# `params` holds template parameters. `params` should look like the defaults below.
constructor
:
(
@
$container
,
params
=
{})
->
params
=
_
.
defaults
params
,
title
:
"Member List"
info
:
"""
Use this list to manage members.
"""
labels
:
[
"field1"
,
"field2"
,
"field3"
]
add_placeholder
:
"Enter name"
add_btn_label
:
"Add Member"
add_handler
:
(
input
)
->
template_html
=
$
(
"#member-list-widget-template"
).
html
()
@
$container
.
html
Mustache
.
render
template_html
,
params
# bind info toggle
@
$
(
'.info-badge'
).
click
=>
@
toggle_info
()
# bind add button
@
$
(
'input[type="button"].add'
).
click
=>
params
.
add_handler
?
@
$
(
'.add-field'
).
val
()
show_info
:
->
@
$
(
'.info'
).
show
()
@
$
(
'.member-list'
).
hide
()
show_list
:
->
@
$
(
'.info'
).
hide
()
@
$
(
'.member-list'
).
show
()
toggle_info
:
->
@
$
(
'.info'
).
toggle
()
@
$
(
'.member-list'
).
toggle
()
# clear the input text field
clear_input
:
->
@
$
(
'.add-field'
).
val
''
# clear all table rows
clear_rows
:
->
@
$
(
'table tbody'
).
empty
()
# takes a table row as an array items are inserted as text, unless detected
# as a jquery objects in which case they are inserted directly. if an
# element is a jquery object
add_row
:
(
row_array
)
->
$tbody
=
@
$
(
'table tbody'
)
$tr
=
$
'<tr>'
for
item
in
row_array
$td
=
$
'<td>'
if
item
instanceof
jQuery
$td
.
append
item
else
$td
.
text
item
$tr
.
append
$td
$tbody
.
append
$tr
# local selector
$
:
(
selector
)
->
if
@
debug
?
s
=
@
$container
.
find
selector
if
s
?
.
length
!=
1
console
.
warn
"local selector '
#{
selector
}
' found (
#{
s
.
length
}
) results"
s
else
@
$container
.
find
selector
class
AuthListWidget
extends
MemberListWidget
constructor
:
(
$container
,
@
rolename
,
@
$error_section
)
->
super
$container
,
title
:
$container
.
data
'display-name'
info
:
$container
.
data
'info-text'
labels
:
[
"username"
,
"email"
,
"revoke access"
]
add_placeholder
:
"Enter email"
add_btn_label
:
$container
.
data
'add-button-label'
add_handler
:
(
input
)
=>
@
add_handler
input
@
debug
=
true
@
list_endpoint
=
$container
.
data
'list-endpoint'
@
modify_endpoint
=
$container
.
data
'modify-endpoint'
unless
@
rolename
?
throw
"AuthListWidget missing @rolename"
@
reload_list
()
# action to do when is reintroduced into user's view
re_view
:
->
@
clear_errors
()
@
clear_input
()
@
reload_list
()
@
$
(
'.info'
).
hide
()
@
$
(
'.member-list'
).
show
()
# handle clicks on the add button
add_handler
:
(
input
)
->
if
input
?
and
input
isnt
''
@
modify_member_access
input
,
'allow'
,
(
error
)
=>
# abort on error
return
@
show_errors
error
unless
error
is
null
@
clear_errors
()
@
clear_input
()
@
reload_list
()
else
@
show_errors
"Enter an email."
# reload the list of members
reload_list
:
->
# @clear_rows()
# @show_info()
@
get_member_list
(
error
,
member_list
)
=>
# abort on error
return
@
show_errors
error
unless
error
is
null
# only show the list of there are members
@
clear_rows
()
@
show_info
()
# @show_info()
# use _.each instead of 'for' so that member
# is bound in the button callback.
_
.
each
member_list
,
(
member
)
=>
# if there are members, show the list
# create revoke button and insert it into the row
$revoke_btn
=
$
'<div/>'
,
class
:
'revoke'
click
:
=>
@
modify_member_access
member
.
email
,
'revoke'
,
(
error
)
=>
# abort on error
return
@
show_errors
error
unless
error
is
null
@
clear_errors
()
@
reload_list
()
@
add_row
[
member
.
username
,
member
.
email
,
$revoke_btn
]
# make sure the list is shown because there are members.
@
show_list
()
# clear error display
clear_errors
:
->
@
$error_section
?
.
text
''
# set error display
show_errors
:
(
msg
)
->
@
$error_section
?
.
text
msg
# send ajax request to list members
# `cb` is called with cb(error, member_list)
get_member_list
:
(
cb
)
->
$
.
ajax
dataType
:
'json'
url
:
@
list_endpoint
data
:
rolename
:
@
rolename
success
:
(
data
)
=>
cb
?
null
,
data
[
@
rolename
]
error
:
std_ajax_err
=>
cb
?
"Error fetching list for role '
#{
@
rolename
}
'"
# send ajax request to modify access
# (add or remove them from the list)
# `action` can be 'allow' or 'revoke'
# `cb` is called with cb(error, data)
modify_member_access
:
(
email
,
action
,
cb
)
->
$
.
ajax
dataType
:
'json'
url
:
@
modify_endpoint
data
:
email
:
email
rolename
:
@
rolename
action
:
action
success
:
(
data
)
=>
cb
?
null
,
data
error
:
std_ajax_err
=>
cb
?
"Error changing user's permissions."
# Wrapper for the batch enrollment subsection.
# This object handles buttons, success and failure reporting,
# and server communication.
...
...
@@ -277,13 +446,15 @@ class Membership
plantTimeout
0
,
=>
new
BatchEnrollment
@
$section
.
find
'.batch-enrollment'
# gather elements
@
$list_selector
=
@
$section
.
find
(
'select#member-lists-selector'
)
@
$list_selector
=
@
$section
.
find
'select#member-lists-selector'
@
$auth_list_containers
=
@
$section
.
find
'.auth-list-container'
@
$auth_list_errors
=
@
$section
.
find
'.member-lists-management .request-response-error'
# initialize & store AuthList subsections
# one for each .auth-list-container in the section.
@
auth_lists
=
_
.
map
(
@
$
section
.
find
'.auth-list-container'
),
(
auth_list_container
)
-
>
@
auth_lists
=
_
.
map
(
@
$
auth_list_containers
),
(
auth_list_container
)
=
>
rolename
=
$
(
auth_list_container
).
data
'rolename'
new
AuthList
$
(
auth_list_container
),
rolename
new
AuthList
Widget
$
(
auth_list_container
),
rolename
,
@
$auth_list_errors
# populate selector
@
$list_selector
.
empty
()
...
...
@@ -299,17 +470,14 @@ class Membership
for
auth_list
in
@
auth_lists
auth_list
.
$container
.
removeClass
'active'
auth_list
=
$opt
.
data
(
'auth_list'
)
auth_list
.
refresh
()
auth_list
.
$container
.
addClass
'active'
auth_list
.
re_view
()
# one-time first selection of top list.
@
$list_selector
.
change
()
# handler for when the section title is clicked.
onClickTitle
:
->
for
auth_list
in
@
auth_lists
auth_list
.
refresh
()
# export for use
...
...
lms/static/images/info-icon-dark.png
0 → 100644
View file @
f88b266c
1.46 KB
lms/static/sass/course/instructor/_instructor_2.scss
View file @
f88b266c
...
...
@@ -18,92 +18,91 @@
right
:
15px
;
font-size
:
11pt
;
}
}
section
.instructor-dashboard-content-2
{
@extend
.content
;
// position: relative;
padding
:
40px
;
width
:
100%
;
section
.instructor-dashboard-content-2
{
@extend
.content
;
// position: relative;
padding
:
40px
;
width
:
100%
;
// .has-event-handler-for-click {
// border: 1px solid blue;
// }
// .has-event-handler-for-click {
// border: 1px solid blue;
// }
.request-response-error
{
margin-top
:
1em
;
margin-bottom
:
1em
;
color
:
$error-red
;
}
.slickgrid
{
margin-left
:
1px
;
color
:
#333333
;
font-size
:
11px
;
font-family
:
verdana
,
arial
,
sans-serif
;
.request-response-error
{
margin-top
:
1em
;
margin-bottom
:
1em
;
color
:
$error-red
;
}
.slick-header-column
{
// height: 100%
}
.slickgrid
{
margin-left
:
1px
;
color
:
#333333
;
font-size
:
11px
;
font-family
:
verdana
,
arial
,
sans-serif
;
.slick-cell
{
border
:
1px
dotted
silver
;
border-collapse
:
collapse
;
white-space
:
normal
;
word-wrap
:
break-word
;
}
.slick-header-column
{
// height: 100%
}
h1
{
@extend
.top-header
;
padding-bottom
:
0
;
border-bottom
:
0
;
.slick-cell
{
border
:
1px
dotted
silver
;
border-collapse
:
collapse
;
white-space
:
normal
;
word-wrap
:
break-word
;
}
}
input
[
type
=
"button"
]
{
@include
idashbutton
(
#eee
);
h1
{
@extend
.top-header
;
padding-bottom
:
0
;
border-bottom
:
0
;
}
&
.molly-guard
{
// @include idashbutton($danger-red);
// @include idashbutton($black);
// border: 2px solid $danger-red;
}
}
input
[
type
=
"button"
]
{
@include
idashbutton
(
#eee
);
.instructor_dash_glob_info
{
position
:
absolute
;
top
:
46px
;
right
:
50px
;
text-align
:
right
;
&
.molly-guard
{
// @include idashbutton($danger-red);
// @include idashbutton($black);
// border: 2px solid $danger-red;
}
}
.instructor-nav
{
padding-bottom
:
1em
;
.instructor_dash_glob_info
{
position
:
absolute
;
top
:
46px
;
right
:
50px
;
text-align
:
right
;
}
border-bottom
:
1px
solid
#C8C8C8
;
a
{
margin-right
:
1
.2em
;
}
.instructor-nav
{
padding-bottom
:
1em
;
.active-section
{
color
:
#551A8B
;
}
border-bottom
:
1px
solid
#C8C8C8
;
a
{
margin-right
:
1
.2em
;
}
section
.idash-section
{
display
:
none
;
// background-color: #0f0;
.active-section
{
color
:
#551A8B
;
}
}
&
.active-section
{
display
:
block
;
// background-color: #ff0;
}
section
.idash-section
{
display
:
none
;
// background-color: #0f0;
.basic-data
{
padding
:
6px
;
}
&
.active-section
{
display
:
block
;
// background-color: #ff0;
}
.basic-data
{
padding
:
6px
;
}
}
// @extend .table-wrapper;
}
...
...
@@ -250,14 +249,20 @@
display
:
block
;
}
.auth-list-table
{
.slickgrid
{
height
:
250px
;
}
}
.auth-list-add
{
margin-top
:
0
.5em
;
.revoke
{
width
:
10px
;
height
:
10px
;
background
:
url('../images/moderator-delete-icon.png')
left
center
no-repeat
;
opacity
:
0
.7
;
&
:hover
{
opacity
:
0
.8
;
}
&
:active
{
opacity
:
0
.9
;
}
// @include idashbutton($danger-red);
// line-height: 0.6em;
// margin-top: 5px;
// padding: 6px 9px;
// font-size: 9pt;
// border-radius: 10px;
}
}
}
...
...
@@ -329,3 +334,115 @@
}
}
}
.member-list-widget
{
$width
:
20
*
$baseline
;
$height
:
25
*
$baseline
;
$header-height
:
3
*
$baseline
;
$bottom-bar-height
:
3
*
$baseline
;
$content-height
:
$height
-
$header-height
-
$bottom-bar-height
;
$border-radius
:
3px
;
width
:
$width
;
height
:
$height
;
.header
{
@include
box-sizing
(
border-box
);
@include
border-top-radius
(
$border-radius
);
position
:
relative
;
padding
:
$baseline
;
width
:
$width
;
height
:
$header-height
;
background-color
:
#efefef
;
border
:
1px
solid
$light-gray
;
}
.title
{
font-size
:
16pt
;
}
.label
{
color
:
$lighter-base-font-color
;
font-size
:
$body-font-size
*
4
/
5
;
}
.info-badge
{
// float: right;
position
:
absolute
;
top
:
$baseline
/
2
;
right
:
$baseline
/
2
;
width
:
17px
;
height
:
17px
;
background
:
url('../images/info-icon-dark.png')
left
center
no-repeat
;
opacity
:
0
.35
;
&
:hover
{
opacity
:
0
.45
;
}
&
:active
{
opacity
:
0
.5
;
}
}
.info
{
display
:
none
;
@include
box-sizing
(
border-box
);
max-height
:
$content-height
;
padding
:
$baseline
;
border
:
1px
solid
$light-gray
;
border-top
:
none
;
color
:
$lighter-base-font-color
;
line-height
:
1
.3em
;
}
.member-list
{
@include
box-sizing
(
border-box
);
overflow
:
auto
;
padding-top
:
0
;
width
:
$width
;
max-height
:
$content-height
;
table
{
width
:
100%
;
}
tr
{
border-bottom
:
1px
solid
$light-gray
;
}
td
{
table-layout
:
fixed
;
vertical-align
:
middle
;
word-wrap
:
break-word
;
padding-left
:
15px
;
border-left
:
1px
solid
$light-gray
;
border-right
:
1px
solid
$light-gray
;
font-size
:
3
/
4
*
$body-font-size
;
}
}
.bottom-bar
{
@include
box-sizing
(
border-box
);
@include
border-bottom-radius
(
$border-radius
);
position
:
relative
;
width
:
$width
;
height
:
$bottom-bar-height
;
padding
:
$baseline
/
2
;
// border-top: none;
margin-top
:
-1px
;
border
:
1px
solid
$light-gray
;
background-color
:
#efefef
;
box-shadow
:
inset
#bbb
0px
1px
1px
0px
;
}
// .add-field
input
[
type
=
"button"
]
.add
{
@include
idashbutton
(
$blue
);
position
:
absolute
;
right
:
$baseline
;
}
}
lms/templates/courseware/instructor_dashboard_2/instructor_dashboard_2.html
View file @
f88b266c
...
...
@@ -5,6 +5,7 @@
<
%
block
name=
"headextra"
>
<
%
static:css
group=
'course'
/>
<script
type=
"text/javascript"
src=
"${static.url('js/vendor/underscore-min.js')}"
></script>
<script
type=
"text/javascript"
src=
"${static.url('js/vendor/mustache.js')}"
></script>
<script
type=
"text/javascript"
src=
"${static.url('js/vendor/flot/jquery.flot.js')}"
></script>
<script
type=
"text/javascript"
src=
"${static.url('js/vendor/flot/jquery.flot.axislabels.js')}"
></script>
<script
type=
"text/javascript"
src=
"${static.url('js/vendor/jquery-jvectormap-1.1.1/jquery-jvectormap-1.1.1.min.js')}"
></script>
...
...
lms/templates/courseware/instructor_dashboard_2/membership.html
View file @
f88b266c
<
%
page
args=
"section_data"
/>
<script
type=
"text/template"
id=
"member-list-widget-template"
>
<
div
class
=
"member-list-widget"
>
<
div
class
=
"header"
>
<
div
class
=
"title"
>
{{
title
}}
<
/div
>
<
div
class
=
"info-badge"
><
/div
>
<
/div
>
<
div
class
=
"info"
>
{{
info
}}
<
/div
>
<
div
class
=
"member-list"
>
<
table
>
<
thead
>
<
tr
>
{{
#
labels
}}
<
td
class
=
"label"
>
{{.}}
<
/td
>
{{
/
labels
}}
<
/tr
>
<
/thead
>
<
tbody
><
/tbody
>
<
/table
>
<
/div
>
<
div
class
=
"bottom-bar"
>
<
input
type
=
"text"
name
=
"add-field"
class
=
"add-field"
placeholder
=
"{{add_placeholder}}"
>
<
input
type
=
"button"
name
=
"add"
class
=
"add"
value
=
"{{add_btn_label}}"
>
<
/div
>
<
/div
>
</script>
<div
class=
"vert-left batch-enrollment"
>
<h2>
Batch Enrollment
</h2>
<p>
Enter student emails separated by new lines or commas.
</p>
...
...
@@ -26,66 +52,75 @@
<option>
Getting available lists...
</option>
</select>
<div
class=
"request-response-error"
></div>
%if section_data['access']['instructor']:
<div
class=
"auth-list-container"
data-rolename=
"staff"
data-display-name=
"Staff"
>
<div
class=
"auth-list-table"
data-endpoint=
"${ section_data['list_course_role_members_url'] }"
></div>
<div
class=
"auth-list-add"
data-endpoint=
"${ section_data['modify_access_url'] }"
>
<input
type=
"text"
name=
"email"
placeholder=
"Enter Email"
spellcheck=
"false"
>
<input
type=
"button"
name=
"allow"
value=
"Grant Staff Access"
>
</div>
<div
class=
"request-response-error"
></div>
</div>
<div
class=
"auth-list-container"
data-rolename=
"staff"
data-display-name=
"Course Staff"
data-info-text=
"
Course staff can help you manage limited aspects of your course. Staff can
enroll and unenroll students, as well as modify their grades and see all
course data. Course staff are not given access to Studio will not be able to
edit your course."
data-list-endpoint=
"${ section_data['list_course_role_members_url'] }"
data-modify-endpoint=
"${ section_data['modify_access_url'] }"
data-add-button-label=
"Add Staff"
></div>
%if section_data['access']['instructor']:
<div
class=
"auth-list-container"
data-rolename=
"instructor"
data-display-name=
"Instructors"
>
<div
class=
"auth-list-table"
data-endpoint=
"${ section_data['list_course_role_members_url'] }"
></div>
<div
class=
"auth-list-add"
data-endpoint=
"${ section_data['modify_access_url'] }"
>
<input
type=
"text"
name=
"email"
placeholder=
"Enter Email"
spellcheck=
"false"
>
<input
type=
"button"
name=
"allow"
value=
"Grant Instructor Access"
>
</div>
<div
class=
"request-response-error"
></div>
</div>
<div
class=
"auth-list-container"
data-rolename=
"instructor"
data-display-name=
"Instructors"
data-info-text=
"
Instructors are the core administration of your course. Instructors can
add and remove course staff, as well as administer forum access.
"
data-list-endpoint=
"${ section_data['list_course_role_members_url'] }"
data-modify-endpoint=
"${ section_data['modify_access_url'] }"
data-add-button-label=
"Add Instructor"
></div>
%endif
<div
class=
"auth-list-container"
data-rolename=
"beta"
data-display-name=
"Beta Testers"
>
<div
class=
"auth-list-table"
data-endpoint=
"${ section_data['list_course_role_members_url'] }"
></div>
<div
class=
"auth-list-add"
data-endpoint=
"${ section_data['modify_access_url'] }"
>
<input
type=
"text"
name=
"email"
placeholder=
"Enter Email"
spellcheck=
"false"
>
<input
type=
"button"
name=
"allow"
value=
"Grant Beta Tester Access"
>
</div>
<div
class=
"request-response-error"
></div>
</div>
<div
class=
"auth-list-container"
data-rolename=
"beta"
data-display-name=
"Beta Testers"
data-info-text=
"
Beta testers can see course content before the rest of the students.
They can make sure that the content works, but have no additional
privelages."
data-list-endpoint=
"${ section_data['list_course_role_members_url'] }"
data-modify-endpoint=
"${ section_data['modify_access_url'] }"
data-add-button-label=
"Add Beta Tester"
></div>
%endif
%if section_data['access']['instructor']:
<div
class=
"auth-list-container"
data-rolename=
"Administrator"
data-display-name=
"Forum Admins"
>
<div
class=
"auth-list-table"
data-endpoint=
"${ section_data['list_forum_members_url'] }"
></div>
<div
class=
"auth-list-add"
data-endpoint=
"${ section_data['update_forum_role_membership_url'] }"
>
<input
type=
"text"
name=
"email"
placeholder=
"Enter Email"
spellcheck=
"false"
>
<input
type=
"button"
name=
"allow"
value=
"Grant Forum Admin"
>
</div>
<div
class=
"request-response-error"
></div>
</div>
<div
class=
"auth-list-container"
data-rolename=
"Administrator"
data-display-name=
"Forum Admins"
data-list-endpoint=
"${ section_data['list_forum_members_url'] }"
data-modify-endpoint=
"${ section_data['update_forum_role_membership_url'] }"
data-add-button-label=
"Add Forum Admin"
></div>
%endif
%if section_data['access']['instructor'] or section_data['access']['forum_admin']:
<div
class=
"auth-list-container"
data-rolename=
"Moderator"
data-display-name=
"Forum Moderators"
>
<div
class=
"auth-list-table"
data-endpoint=
"${ section_data['list_forum_members_url'] }"
></div>
<div
class=
"auth-list-add"
data-endpoint=
"${ section_data['update_forum_role_membership_url'] }"
>
<input
type=
"text"
name=
"email"
placeholder=
"Enter Email"
spellcheck=
"false"
>
<input
type=
"button"
name=
"allow"
value=
"Grant Forum Moderator"
>
</div>
<div
class=
"request-response-error"
></div>
</div>
<div
class=
"auth-list-container"
data-rolename=
"Moderator"
data-display-name=
"Forum Moderators"
data-list-endpoint=
"${ section_data['list_forum_members_url'] }"
data-modify-endpoint=
"${ section_data['update_forum_role_membership_url'] }"
data-add-button-label=
"Add Moderator"
></div>
<div
class=
"auth-list-container"
data-rolename=
"Community TA"
data-display-name=
"Forum Community TAs"
>
<div
class=
"auth-list-table"
data-endpoint=
"${ section_data['list_forum_members_url'] }"
></div>
<div
class=
"auth-list-add"
data-endpoint=
"${ section_data['update_forum_role_membership_url'] }"
>
<input
type=
"text"
name=
"email"
placeholder=
"Enter Email"
spellcheck=
"false"
>
<input
type=
"button"
name=
"allow"
value=
"Grant Community TA"
>
</div>
<div
class=
"request-response-error"
></div>
</div>
<div
class=
"auth-list-container"
data-rolename=
"Community TA"
data-display-name=
"Forum Community TAs"
data-list-endpoint=
"${ section_data['list_forum_members_url'] }"
data-modify-endpoint=
"${ section_data['update_forum_role_membership_url'] }"
data-add-button-label=
"Add Community TA"
></div>
%endif
</div>
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