Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
C
course-discovery
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
course-discovery
Commits
40439efd
Commit
40439efd
authored
Apr 28, 2017
by
Waheed Ahmed
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added Instructor email field and fixed organization.
ECOM-7706
parent
6318abab
Hide whitespace changes
Inline
Side-by-side
Showing
18 changed files
with
114 additions
and
27 deletions
+114
-27
course_discovery/apps/api/serializers.py
+2
-1
course_discovery/apps/api/tests/test_serializers.py
+1
-0
course_discovery/apps/api/v1/tests/test_views/test_people.py
+1
-0
course_discovery/apps/course_metadata/migrations/0053_person_email.py
+20
-0
course_discovery/apps/course_metadata/models.py
+1
-0
course_discovery/apps/publisher/forms.py
+2
-12
course_discovery/apps/publisher/mixins.py
+24
-0
course_discovery/apps/publisher/tests/test_wrapper.py
+3
-1
course_discovery/apps/publisher/utils.py
+1
-0
course_discovery/apps/publisher/views.py
+4
-2
course_discovery/apps/publisher/wrappers.py
+1
-0
course_discovery/conf/locale/en/LC_MESSAGES/django.po
+9
-0
course_discovery/conf/locale/eo/LC_MESSAGES/django.po
+9
-0
course_discovery/static/js/publisher/instructors.js
+1
-0
course_discovery/static/js/publisher/modal-screen.js
+1
-0
course_discovery/static/sass/publisher/course_form.scss
+8
-0
course_discovery/templates/publisher/_add_instructor_popup.html
+19
-11
course_discovery/templates/publisher/course_run_detail/_instructor_profile.html
+7
-0
No files found.
course_discovery/apps/api/serializers.py
View file @
40439efd
...
...
@@ -214,6 +214,7 @@ class PersonSerializer(serializers.ModelSerializer):
profile_image
=
StdImageSerializerField
(
required
=
False
)
works
=
serializers
.
SlugRelatedField
(
many
=
True
,
read_only
=
True
,
slug_field
=
'value'
,
source
=
'person_works'
)
urls
=
serializers
.
SerializerMethodField
()
email
=
serializers
.
EmailField
(
required
=
True
)
@classmethod
def
prefetch_queryset
(
cls
):
...
...
@@ -225,7 +226,7 @@ class PersonSerializer(serializers.ModelSerializer):
model
=
Person
fields
=
(
'uuid'
,
'given_name'
,
'family_name'
,
'bio'
,
'profile_image_url'
,
'slug'
,
'position'
,
'profile_image'
,
'partner'
,
'works'
,
'urls'
'partner'
,
'works'
,
'urls'
,
'email'
)
extra_kwargs
=
{
'partner'
:
{
'write_only'
:
True
}
...
...
course_discovery/apps/api/tests/test_serializers.py
View file @
40439efd
...
...
@@ -1075,6 +1075,7 @@ class PersonSerializerTests(TestCase):
'blog'
:
None
},
'slug'
:
person
.
slug
,
'email'
:
person
.
email
,
}
self
.
assertDictEqual
(
serializer
.
data
,
expected
)
...
...
course_discovery/apps/api/v1/tests/test_views/test_people.py
View file @
40439efd
...
...
@@ -140,6 +140,7 @@ class PersonViewSetTests(SerializationMixin, APITestCase):
return
{
'given_name'
:
"Robert"
,
'family_name'
:
"Ford"
,
'email'
:
"test@example.com"
,
'bio'
:
"The maze is not for him."
,
'position'
:
{
'title'
:
"Park Director"
,
...
...
course_discovery/apps/course_metadata/migrations/0053_person_email.py
0 → 100644
View file @
40439efd
# -*- coding: utf-8 -*-
# Generated by Django 1.9.13 on 2017-04-27 11:49
from
__future__
import
unicode_literals
from
django.db
import
migrations
,
models
class
Migration
(
migrations
.
Migration
):
dependencies
=
[
(
'course_metadata'
,
'0052_create_course_run_publication_switch'
),
]
operations
=
[
migrations
.
AddField
(
model_name
=
'person'
,
name
=
'email'
,
field
=
models
.
EmailField
(
blank
=
True
,
max_length
=
255
,
null
=
True
),
),
]
course_discovery/apps/course_metadata/models.py
View file @
40439efd
...
...
@@ -210,6 +210,7 @@ class Person(TimeStampedModel):
)
slug
=
AutoSlugField
(
populate_from
=
(
'given_name'
,
'family_name'
),
editable
=
True
)
profile_url
=
models
.
URLField
(
null
=
True
,
blank
=
True
)
email
=
models
.
EmailField
(
null
=
True
,
blank
=
True
,
max_length
=
255
)
class
Meta
:
unique_together
=
(
...
...
course_discovery/apps/publisher/forms.py
View file @
40439efd
...
...
@@ -13,7 +13,7 @@ from opaque_keys.edx.keys import CourseKey
from
course_discovery.apps.course_metadata.choices
import
CourseRunPacing
from
course_discovery.apps.course_metadata.models
import
LevelType
,
Organization
,
Person
,
Subject
from
course_discovery.apps.ietf_language_tags.models
import
LanguageTag
from
course_discovery.apps.publisher.mixins
import
LanguageModelSelect2Multiple
,
check_roles_acces
s
from
course_discovery.apps.publisher.mixins
import
LanguageModelSelect2Multiple
,
get_user_organization
s
from
course_discovery.apps.publisher.models
import
(
Course
,
CourseRun
,
CourseUserRole
,
OrganizationExtension
,
OrganizationUserRole
,
PublisherUser
,
Seat
,
User
)
from
course_discovery.apps.publisher.utils
import
is_internal_user
...
...
@@ -181,17 +181,7 @@ class CustomCourseForm(CourseForm):
)
.
order_by
(
'full_name'
,
'username'
)
if
user
:
organizations
=
Organization
.
objects
.
filter
(
organization_extension__organization_id__isnull
=
False
)
.
order_by
(
Lower
(
'key'
))
if
not
check_roles_access
(
user
):
# If not internal user return only those organizations which belongs to user.
organizations
=
organizations
.
filter
(
organization_extension__group__in
=
user
.
groups
.
all
()
)
.
order_by
(
Lower
(
'key'
))
self
.
declared_fields
[
'organization'
]
.
queryset
=
organizations
self
.
declared_fields
[
'organization'
]
.
queryset
=
get_user_organizations
(
user
)
self
.
declared_fields
[
'team_admin'
]
.
widget
.
attrs
=
{
'data-user'
:
user
.
id
}
super
(
CustomCourseForm
,
self
)
.
__init__
(
*
args
,
**
kwargs
)
...
...
course_discovery/apps/publisher/mixins.py
View file @
40439efd
...
...
@@ -2,9 +2,11 @@ from functools import wraps
from
dal
import
autocomplete
from
django.contrib.auth.decorators
import
login_required
from
django.db.models.functions
import
Lower
from
django.http
import
HttpResponseForbidden
,
HttpResponseRedirect
from
django.utils.decorators
import
method_decorator
from
course_discovery.apps.course_metadata.models
import
Organization
from
course_discovery.apps.publisher.models
import
Course
,
Seat
from
course_discovery.apps.publisher.utils
import
is_internal_user
,
is_publisher_admin
,
is_publisher_user
...
...
@@ -131,3 +133,25 @@ class LanguageModelSelect2Multiple(autocomplete.ModelSelect2Multiple):
self
.
choices
.
queryset
=
self
.
choices
.
queryset
.
filter
(
code__in
=
[
c
for
c
in
selected_choices
if
c
]
)
def
get_user_organizations
(
user
):
"""
Get organizations for user.
Args:
user (Object): User object
Returns:
Organization (QuerySet): returns Organization objects queryset
"""
organizations
=
Organization
.
objects
.
filter
(
organization_extension__organization_id__isnull
=
False
)
.
order_by
(
Lower
(
'key'
))
if
not
check_roles_access
(
user
):
# If not internal user return only those organizations which belongs to user.
organizations
=
organizations
.
filter
(
organization_extension__group__in
=
user
.
groups
.
all
()
)
.
order_by
(
Lower
(
'key'
))
return
organizations
course_discovery/apps/publisher/tests/test_wrapper.py
View file @
40439efd
...
...
@@ -200,6 +200,7 @@ class CourseRunWrapperTests(TestCase):
'social_networks'
:
{},
'bio'
:
staff
.
bio
,
'is_new'
:
True
,
'email'
:
staff
.
email
},
{
'uuid'
:
str
(
staff_2
.
uuid
),
...
...
@@ -210,7 +211,8 @@ class CourseRunWrapperTests(TestCase):
'profile_url'
:
staff
.
profile_url
,
'is_new'
:
False
,
'social_networks'
:
{
'facebook'
:
facebook
.
value
,
'twitter'
:
twitter
.
value
},
'bio'
:
staff_2
.
bio
'bio'
:
staff_2
.
bio
,
'email'
:
staff_2
.
email
}
]
...
...
course_discovery/apps/publisher/utils.py
View file @
40439efd
""" Publisher Utils."""
from
dateutil
import
parser
from
course_discovery.apps.core.models
import
User
from
course_discovery.apps.publisher.constants
import
(
ADMIN_GROUP_NAME
,
INTERNAL_USER_GROUP_NAME
,
PROJECT_COORDINATOR_GROUP_NAME
)
...
...
course_discovery/apps/publisher/views.py
View file @
40439efd
...
...
@@ -594,12 +594,14 @@ class CourseRunEditView(mixins.LoginRequiredMixin, mixins.PublisherPermissionMix
return
reverse
(
self
.
success_url
,
kwargs
=
{
'pk'
:
self
.
object
.
id
})
def
get_context_data
(
self
):
user
=
self
.
request
.
user
return
{
'course_run'
:
self
.
get_object
(),
'publisher_hide_features_for_pilot'
:
waffle
.
switch_is_active
(
'publisher_hide_features_for_pilot'
),
'publisher_add_instructor_feature'
:
waffle
.
switch_is_active
(
'publisher_add_instructor_feature'
),
'is_internal_user'
:
mixins
.
check_roles_access
(
self
.
request
.
user
),
'is_project_coordinator'
:
is_project_coordinator_user
(
self
.
request
.
user
),
'is_internal_user'
:
mixins
.
check_roles_access
(
user
),
'is_project_coordinator'
:
is_project_coordinator_user
(
user
),
'organizations'
:
mixins
.
get_user_organizations
(
user
)
}
def
get
(
self
,
request
,
*
args
,
**
kwargs
):
...
...
course_discovery/apps/publisher/wrappers.py
View file @
40439efd
...
...
@@ -198,6 +198,7 @@ class CourseRunWrapper(BaseWrapper):
'image_url'
:
staff
.
get_profile_image_url
,
'profile_url'
:
staff
.
profile_url
,
'bio'
:
staff
.
bio
,
'email'
:
staff
.
email
,
'social_networks'
:
{
staff
.
type
:
staff
.
value
for
staff
in
staff
.
person_networks
.
all
()
...
...
course_discovery/conf/locale/en/LC_MESSAGES/django.po
View file @
40439efd
...
...
@@ -1037,6 +1037,15 @@ msgstr ""
#: templates/publisher/_add_instructor_popup.html
#: templates/publisher/course_run_detail/_instructor_profile.html
msgid "Email"
msgstr ""
#: templates/publisher/_add_instructor_popup.html
msgid "Institution email is preferred"
msgstr ""
#: templates/publisher/_add_instructor_popup.html
#: templates/publisher/course_run_detail/_instructor_profile.html
#: templates/publisher/course_run_detail/_studio.html
#: templates/publisher/dashboard/_in_preview.html
#: templates/publisher/dashboard/_in_progress.html
...
...
course_discovery/conf/locale/eo/LC_MESSAGES/django.po
View file @
40439efd
...
...
@@ -1197,6 +1197,15 @@ msgstr "Tïtlé Ⱡ'σяєм ιρѕ#"
#: templates/publisher/_add_instructor_popup.html
#: templates/publisher/course_run_detail/_instructor_profile.html
msgid "Email"
msgstr "Émäïl Ⱡ'σяєм ιρѕ#"
#: templates/publisher/_add_instructor_popup.html
msgid "Institution email is preferred"
msgstr "Ìnstïtütïön émäïl ïs préférréd Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢т#"
#: templates/publisher/_add_instructor_popup.html
#: templates/publisher/course_run_detail/_instructor_profile.html
#: templates/publisher/course_run_detail/_studio.html
#: templates/publisher/dashboard/_in_preview.html
#: templates/publisher/dashboard/_in_progress.html
...
...
course_discovery/static/js/publisher/instructors.js
View file @
40439efd
...
...
@@ -34,6 +34,7 @@ $(document).ready(function(){
'given_name'
:
$
(
'#given-name'
).
val
(),
'family_name'
:
$
(
'#family-name'
).
val
(),
'bio'
:
$
(
'#bio'
).
val
(),
'email'
:
$
(
'#email'
).
val
(),
'profile_image'
:
$
(
'.select-image'
).
attr
(
'src'
),
'position'
:
{
title
:
$
(
'#title'
).
val
(),
...
...
course_discovery/static/js/publisher/modal-screen.js
View file @
40439efd
...
...
@@ -39,6 +39,7 @@ $(document).ready(function(){
$
(
'#instructorProfileModal a.btn-download'
).
attr
(
'href'
,
data
[
'image_url'
]);
$
(
'#instructorProfileModal div.position'
).
html
(
data
[
'position'
]);
$
(
'#instructorProfileModal div.bio'
).
html
(
data
[
'bio'
]);
$
(
'#instructorProfileModal div.email'
).
html
(
data
[
'email'
]);
assignData
(
'.profile_url'
,
data
[
'profile_url'
]);
assignData
(
'.facebook_url'
,
data
[
'social_networks'
][
'facebook'
]);
...
...
course_discovery/static/sass/publisher/course_form.scss
View file @
40439efd
...
...
@@ -159,6 +159,14 @@
.actions
{
@include
text-align
(
right
);
}
#email
{
margin-bottom
:
5px
;
}
.email-field
{
margin-bottom
:
20px
;
}
}
}
...
...
course_discovery/templates/publisher/_add_instructor_popup.html
View file @
40439efd
...
...
@@ -27,22 +27,30 @@
</label>
<input
class=
"field-input input-text"
type=
"text"
id=
"title"
name=
"title"
/>
<label
class=
"field-label"
for=
"title"
>
{% trans "Email" %}
<span
class=
"required"
>
* {% trans "required" %}
</span>
</label>
<div
class=
"email-field"
>
<input
class=
"field-input input-text"
aria-describedby=
"email-hint"
type=
"email"
id=
"email"
name=
"email"
/>
<span
id=
"email-hint"
>
{% trans "Institution email is preferred" %}
</span>
</div>
<label
class=
"field-label"
>
{% trans "Organization" %}
<span
class=
"required"
>
* {% trans "required" %}
</span>
</label>
{% if edit_mode %}
<span
class=
"read-only-field"
>
{{ organization_name }}
</span>
{{ course_form.organization }}
{% if organizations.count > 1 %}
<select
class=
"field-input input-select"
id=
"id_organization"
name=
"organization"
>
<option
value=
"------"
>
-----
</option>
{% for organization in organizations %}
<option
value=
"{{ organization.id }}"
>
{{ organization.name }}
</option>
{% endfor%}
</select>
{% else %}
{% if course_form.organization.field.queryset.all.count > 1 %}
{{ course_form.organization }}
{% else %}
{% with course_form.organization.field.queryset|first as organization %}
<span
class=
"read-only-field"
>
{{ organization.name }}
</span>
<input
id=
"id_organization"
name=
"organization"
type=
"hidden"
value=
"{{ organization.id }}"
>
{% endwith %}
{% endif %}
{% with organizations|first as organization %}
<span
class=
"read-only-field"
>
{{ organization.name }}
</span>
<input
id=
"id_organization"
name=
"organization"
type=
"hidden"
value=
"{{ organization.id }}"
>
{% endwith %}
{% endif %}
<label
class=
"field-label"
for=
"bio"
>
{% trans "Bio" %}
...
...
course_discovery/templates/publisher/course_run_detail/_instructor_profile.html
View file @
40439efd
...
...
@@ -20,6 +20,13 @@
</div>
<div
class=
"info-item"
>
<div
class=
"heading"
>
{% trans "Email" %}:
{% include "publisher/course_run_detail/_clipboard.html" %}
</div>
<div
class=
"copy email"
></div>
</div>
<div
class=
"info-item"
>
<div
class=
"heading"
>
{% trans "Organization" %}:
{% include "publisher/course_run_detail/_clipboard.html" %}
</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