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
0dca3588
Commit
0dca3588
authored
Oct 07, 2016
by
Awais Qureshi
Committed by
GitHub
Oct 07, 2016
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #362 from edx/awais786/ECOM-5496
Awais786/ecom 5496
parents
057bca2d
5b361188
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
387 additions
and
21 deletions
+387
-21
course_discovery/apps/publisher/forms.py
+63
-1
course_discovery/apps/publisher/migrations/0010_auto_20161006_1151.py
+64
-0
course_discovery/apps/publisher/models.py
+19
-7
course_discovery/apps/publisher/tests/factories.py
+3
-0
course_discovery/apps/publisher/tests/test_views.py
+0
-0
course_discovery/apps/publisher/urls.py
+1
-0
course_discovery/apps/publisher/views.py
+81
-9
course_discovery/static/js/publisher/publisher.js
+13
-2
course_discovery/static/sass/publisher/course_detail.scss
+89
-2
course_discovery/templates/publisher/add_course_form.html
+0
-0
course_discovery/templates/publisher/view_course_form.html
+54
-0
No files found.
course_discovery/apps/publisher/forms.py
View file @
0dca3588
"""
Course publisher forms.
"""
from
django.contrib.auth.models
import
Group
from
django
import
forms
from
django.utils.translation
import
ugettext_lazy
as
_
from
course_discovery.apps.publisher.models
import
Course
,
CourseRun
,
Seat
from
course_discovery.apps.course_metadata.models
import
Person
from
course_discovery.apps.publisher.models
import
Course
,
CourseRun
,
Seat
,
User
class
BaseCourseForm
(
forms
.
ModelForm
):
...
...
@@ -40,6 +43,24 @@ class CourseForm(BaseCourseForm):
exclude
=
(
'changed_by'
,)
class
CustomCourseForm
(
CourseForm
):
""" Course Form. """
institution
=
forms
.
ModelChoiceField
(
queryset
=
Group
.
objects
.
all
(),
required
=
True
)
title
=
forms
.
CharField
(
label
=
'Course Title'
,
required
=
True
,
max_length
=
255
)
number
=
forms
.
CharField
(
label
=
'Course Number'
,
required
=
True
,
max_length
=
255
)
team_admin
=
forms
.
ModelChoiceField
(
queryset
=
User
.
objects
.
filter
(
is_staff
=
True
),
required
=
True
)
class
Meta
(
CourseForm
.
Meta
):
model
=
Course
fields
=
(
'title'
,
'number'
,
'short_description'
,
'full_description'
,
'expected_learnings'
,
'level_type'
,
'primary_subject'
,
'secondary_subject'
,
'tertiary_subject'
,
'prerequisites'
,
'level_type'
,
'image'
,
'team_admin'
,
'level_type'
,
'institution'
,
)
class
CourseRunForm
(
BaseCourseForm
):
""" Course Run Form. """
...
...
@@ -49,6 +70,30 @@ class CourseRunForm(BaseCourseForm):
exclude
=
(
'state'
,
'changed_by'
,)
class
CustomCourseRunForm
(
CourseRunForm
):
""" Course Run Form. """
contacted_partner_manager
=
forms
.
BooleanField
(
widget
=
forms
.
RadioSelect
(
choices
=
((
1
,
_
(
"Yes"
)),
(
0
,
_
(
"No"
)))),
initial
=
0
,
required
=
False
)
start
=
forms
.
DateTimeField
(
required
=
True
)
staff
=
forms
.
ModelMultipleChoiceField
(
queryset
=
Person
.
objects
.
all
(),
widget
=
forms
.
SelectMultiple
,
required
=
False
)
target_content
=
forms
.
BooleanField
(
widget
=
forms
.
RadioSelect
(
choices
=
((
1
,
_
(
"Yes"
)),
(
0
,
_
(
"No"
)))),
initial
=
0
,
required
=
False
)
class
Meta
(
CourseRunForm
.
Meta
):
fields
=
(
'keywords'
,
'start'
,
'end'
,
'length'
,
'transcript_languages'
,
'language'
,
'min_effort'
,
'max_effort'
,
'keywords'
,
'contacted_partner_manager'
,
'target_content'
,
'pacing_type'
,
'is_seo_review'
,
'video_language'
,
'staff'
,
)
class
SeatForm
(
BaseCourseForm
):
""" Course Seat Form. """
...
...
@@ -76,3 +121,20 @@ class SeatForm(BaseCourseForm):
seat
.
save
()
return
seat
def
clean
(
self
):
price
=
self
.
cleaned_data
.
get
(
'price'
)
seat_type
=
self
.
cleaned_data
.
get
(
'type'
)
if
seat_type
in
[
Seat
.
PROFESSIONAL
,
Seat
.
NO_ID_PROFESSIONAL
,
Seat
.
VERIFIED
,
Seat
.
CREDIT
]
\
and
not
price
:
self
.
add_error
(
'price'
,
_
(
'Only honor/audit seats can be without price.'
))
return
self
.
cleaned_data
class
CustomSeatForm
(
SeatForm
):
""" Course Seat Form. """
class
Meta
(
SeatForm
.
Meta
):
fields
=
(
'price'
,
'type'
)
course_discovery/apps/publisher/migrations/0010_auto_20161006_1151.py
0 → 100644
View file @
0dca3588
# -*- coding: utf-8 -*-
from
__future__
import
unicode_literals
from
django.db
import
migrations
,
models
class
Migration
(
migrations
.
Migration
):
dependencies
=
[
(
'publisher'
,
'0009_auto_20160929_1927'
),
]
operations
=
[
migrations
.
AlterField
(
model_name
=
'course'
,
name
=
'expected_learnings'
,
field
=
models
.
TextField
(
default
=
None
,
null
=
True
,
blank
=
True
,
verbose_name
=
'Expected Learnings'
),
),
migrations
.
AlterField
(
model_name
=
'course'
,
name
=
'full_description'
,
field
=
models
.
TextField
(
default
=
None
,
null
=
True
,
blank
=
True
,
verbose_name
=
'Full Description'
),
),
migrations
.
AlterField
(
model_name
=
'course'
,
name
=
'level_type'
,
field
=
models
.
ForeignKey
(
related_name
=
'publisher_courses'
,
default
=
None
,
to
=
'course_metadata.LevelType'
,
blank
=
True
,
verbose_name
=
'Level Type'
,
null
=
True
),
),
migrations
.
AlterField
(
model_name
=
'course'
,
name
=
'prerequisites'
,
field
=
models
.
TextField
(
default
=
None
,
null
=
True
,
blank
=
True
,
verbose_name
=
'Prerequisites'
),
),
migrations
.
AlterField
(
model_name
=
'course'
,
name
=
'short_description'
,
field
=
models
.
CharField
(
default
=
None
,
max_length
=
255
,
null
=
True
,
blank
=
True
,
verbose_name
=
'Brief Description'
),
),
migrations
.
AlterField
(
model_name
=
'courserun'
,
name
=
'language'
,
field
=
models
.
ForeignKey
(
related_name
=
'publisher_course_runs'
,
to
=
'ietf_language_tags.LanguageTag'
,
verbose_name
=
'Content Language'
,
blank
=
True
,
null
=
True
),
),
migrations
.
AlterField
(
model_name
=
'historicalcourse'
,
name
=
'expected_learnings'
,
field
=
models
.
TextField
(
default
=
None
,
null
=
True
,
blank
=
True
,
verbose_name
=
'Expected Learnings'
),
),
migrations
.
AlterField
(
model_name
=
'historicalcourse'
,
name
=
'full_description'
,
field
=
models
.
TextField
(
default
=
None
,
null
=
True
,
blank
=
True
,
verbose_name
=
'Full Description'
),
),
migrations
.
AlterField
(
model_name
=
'historicalcourse'
,
name
=
'prerequisites'
,
field
=
models
.
TextField
(
default
=
None
,
null
=
True
,
blank
=
True
,
verbose_name
=
'Prerequisites'
),
),
migrations
.
AlterField
(
model_name
=
'historicalcourse'
,
name
=
'short_description'
,
field
=
models
.
CharField
(
default
=
None
,
max_length
=
255
,
null
=
True
,
blank
=
True
,
verbose_name
=
'Brief Description'
),
),
]
course_discovery/apps/publisher/models.py
View file @
0dca3588
...
...
@@ -7,7 +7,7 @@ from django.dispatch import receiver
from
django.utils.translation
import
ugettext_lazy
as
_
from
django_extensions.db.models
import
TimeStampedModel
from
django_fsm
import
FSMField
,
transition
from
guardian.shortcuts
import
assign_perm
from
guardian.shortcuts
import
assign_perm
,
get_groups_with_perms
from
simple_history.models
import
HistoricalRecords
from
sortedm2m.fields
import
SortedManyToManyField
from
stdimage.models
import
StdImageField
...
...
@@ -84,18 +84,18 @@ class Course(TimeStampedModel, ChangedByMixin):
title
=
models
.
CharField
(
max_length
=
255
,
default
=
None
,
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
'Course title'
))
number
=
models
.
CharField
(
max_length
=
50
,
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
'Course number'
))
short_description
=
models
.
CharField
(
max_length
=
255
,
default
=
None
,
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
'
Course subtitle
'
)
max_length
=
255
,
default
=
None
,
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
'
Brief Description
'
)
)
full_description
=
models
.
TextField
(
default
=
None
,
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
'
About this course
'
))
full_description
=
models
.
TextField
(
default
=
None
,
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
'
Full Description
'
))
organizations
=
models
.
ManyToManyField
(
Organization
,
blank
=
True
,
related_name
=
'publisher_courses'
,
verbose_name
=
_
(
'Partner Name'
)
)
level_type
=
models
.
ForeignKey
(
LevelType
,
default
=
None
,
null
=
True
,
blank
=
True
,
related_name
=
'publisher_courses'
,
verbose_name
=
_
(
'
Course level
'
)
LevelType
,
default
=
None
,
null
=
True
,
blank
=
True
,
related_name
=
'publisher_courses'
,
verbose_name
=
_
(
'
Level Type
'
)
)
expected_learnings
=
models
.
TextField
(
default
=
None
,
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
"
What you'll learn
"
))
expected_learnings
=
models
.
TextField
(
default
=
None
,
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
"
Expected Learnings
"
))
syllabus
=
models
.
TextField
(
default
=
None
,
null
=
True
,
blank
=
True
)
prerequisites
=
models
.
TextField
(
default
=
None
,
null
=
True
,
blank
=
True
)
prerequisites
=
models
.
TextField
(
default
=
None
,
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
'Prerequisites'
)
)
learner_testimonial
=
models
.
CharField
(
max_length
=
50
,
null
=
True
,
blank
=
True
)
verification_deadline
=
models
.
DateTimeField
(
null
=
True
,
...
...
@@ -147,6 +147,15 @@ class Course(TimeStampedModel, ChangedByMixin):
for
group
in
user
.
groups
.
all
():
assign_perm
(
self
.
VIEW_PERMISSION
,
group
,
self
)
def
assign_permission_by_group
(
self
,
institution
):
assign_perm
(
self
.
VIEW_PERMISSION
,
institution
,
self
)
@property
def
get_group_institution
(
self
):
""" Returns the Group object with for the given course object. """
available_groups
=
get_groups_with_perms
(
self
)
return
available_groups
[
0
]
if
available_groups
else
None
class
CourseRun
(
TimeStampedModel
,
ChangedByMixin
):
""" Publisher CourseRun model. It contains fields related to the course run intake form."""
...
...
@@ -185,7 +194,10 @@ class CourseRun(TimeStampedModel, ChangedByMixin):
max_effort
=
models
.
PositiveSmallIntegerField
(
null
=
True
,
blank
=
True
,
help_text
=
_
(
'Estimated maximum number of hours per week needed to complete a course run.'
))
language
=
models
.
ForeignKey
(
LanguageTag
,
null
=
True
,
blank
=
True
,
related_name
=
'publisher_course_runs'
)
language
=
models
.
ForeignKey
(
LanguageTag
,
null
=
True
,
blank
=
True
,
related_name
=
'publisher_course_runs'
,
verbose_name
=
_
(
'Content Language'
)
)
transcript_languages
=
models
.
ManyToManyField
(
LanguageTag
,
blank
=
True
,
related_name
=
'publisher_transcript_course_runs'
)
...
...
course_discovery/apps/publisher/tests/factories.py
View file @
0dca3588
...
...
@@ -7,6 +7,7 @@ from factory.fuzzy import FuzzyText, FuzzyChoice, FuzzyDecimal, FuzzyDateTime, F
from
pytz
import
UTC
from
course_discovery.apps.core.models
import
Currency
from
course_discovery.apps.core.tests.factories
import
UserFactory
from
course_discovery.apps.course_metadata.choices
import
CourseRunPacing
from
course_discovery.apps.course_metadata.tests
import
factories
from
course_discovery.apps.ietf_language_tags.models
import
LanguageTag
...
...
@@ -34,6 +35,8 @@ class CourseFactory(factory.DjangoModelFactory):
secondary_subject
=
factory
.
SubFactory
(
factories
.
SubjectFactory
)
tertiary_subject
=
factory
.
SubFactory
(
factories
.
SubjectFactory
)
team_admin
=
factory
.
SubFactory
(
UserFactory
)
class
Meta
:
model
=
Course
...
...
course_discovery/apps/publisher/tests/test_views.py
View file @
0dca3588
This diff is collapsed.
Click to expand it.
course_discovery/apps/publisher/urls.py
View file @
0dca3588
...
...
@@ -7,6 +7,7 @@ from course_discovery.apps.publisher import views
urlpatterns
=
[
url
(
r'^courses/new$'
,
views
.
CreateCourseView
.
as_view
(),
name
=
'publisher_courses_new'
),
url
(
r'^courses/(?P<pk>\d+)/view/$'
,
views
.
ReadOnlyView
.
as_view
(),
name
=
'publisher_courses_readonly'
),
url
(
r'^courses/(?P<pk>\d+)/edit/$'
,
views
.
UpdateCourseView
.
as_view
(),
name
=
'publisher_courses_edit'
),
url
(
r'^course_runs/(?P<pk>\d+)/$'
,
views
.
CourseRunDetailView
.
as_view
(),
name
=
'publisher_course_run_detail'
),
url
(
r'^course_runs/$'
,
views
.
CourseRunListView
.
as_view
(),
name
=
'publisher_course_runs'
),
...
...
course_discovery/apps/publisher/views.py
View file @
0dca3588
...
...
@@ -2,8 +2,11 @@
Course publisher views.
"""
from
django.contrib
import
messages
from
django.contrib.auth.models
import
Group
from
django.core.urlresolvers
import
reverse
from
django.db
import
transaction
from
django.http
import
HttpResponseRedirect
,
HttpResponseForbidden
from
django.shortcuts
import
render
,
get_object_or_404
from
django.utils.translation
import
ugettext_lazy
as
_
from
django.views.generic
import
View
from
django.views.generic.detail
import
DetailView
...
...
@@ -12,7 +15,9 @@ from django.views.generic.list import ListView
from
django_fsm
import
TransitionNotAllowed
from
guardian.shortcuts
import
get_objects_for_user
from
course_discovery.apps.publisher.forms
import
CourseForm
,
CourseRunForm
,
SeatForm
from
course_discovery.apps.publisher.forms
import
(
CourseForm
,
CourseRunForm
,
SeatForm
,
CustomCourseForm
,
CustomCourseRunForm
,
CustomSeatForm
)
from
course_discovery.apps.publisher
import
mixins
from
course_discovery.apps.publisher.models
import
Course
,
CourseRun
,
Seat
,
State
from
course_discovery.apps.publisher.wrappers
import
CourseRunWrapper
...
...
@@ -59,16 +64,72 @@ class CourseRunDetailView(mixins.LoginRequiredMixin, mixins.ViewPermissionMixin,
# pylint: disable=attribute-defined-outside-init
class
CreateCourseView
(
mixins
.
LoginRequiredMixin
,
mixins
.
FormValidMixin
,
CreateView
):
class
CreateCourseView
(
mixins
.
LoginRequiredMixin
,
CreateView
):
""" Create Course View."""
model
=
Course
form_class
=
CourseForm
template_name
=
'publisher/course_form.html'
success_url
=
'publisher:publisher_courses_edit'
assign_user_groups
=
True
def
get_success_url
(
self
):
return
reverse
(
self
.
success_url
,
kwargs
=
{
'pk'
:
self
.
object
.
id
})
course_form
=
CustomCourseForm
run_form
=
CustomCourseRunForm
seat_form
=
CustomSeatForm
template_name
=
'publisher/add_course_form.html'
success_url
=
'publisher:publisher_courses_readonly'
def
get_success_url
(
self
,
course_id
):
# pylint: disable=arguments-differ
return
reverse
(
self
.
success_url
,
kwargs
=
{
'pk'
:
course_id
})
def
get_context_data
(
self
):
return
{
'course_form'
:
self
.
course_form
,
'run_form'
:
self
.
run_form
,
'seat_form'
:
self
.
seat_form
}
def
get
(
self
,
request
,
*
args
,
**
kwargs
):
return
render
(
request
,
self
.
template_name
,
self
.
get_context_data
())
def
post
(
self
,
request
,
*
args
,
**
kwargs
):
ctx
=
self
.
get_context_data
()
course_form
=
self
.
course_form
(
request
.
POST
,
request
.
FILES
)
run_form
=
self
.
run_form
(
request
.
POST
)
seat_form
=
self
.
seat_form
(
request
.
POST
)
if
course_form
.
is_valid
()
and
run_form
.
is_valid
()
and
seat_form
.
is_valid
():
try
:
with
transaction
.
atomic
():
seat
=
seat_form
.
save
(
commit
=
False
)
run_course
=
run_form
.
save
(
commit
=
False
)
course
=
course_form
.
save
(
commit
=
False
)
course
.
changed_by
=
self
.
request
.
user
course
.
save
()
run_course
.
course
=
course
run_course
.
changed_by
=
self
.
request
.
user
run_course
.
save
()
# commit false does not save m2m object.
run_form
.
save_m2m
()
seat
.
course_run
=
run_course
seat
.
changed_by
=
self
.
request
.
user
seat
.
save
()
institution
=
get_object_or_404
(
Group
,
pk
=
course_form
.
data
[
'institution'
])
# assign guardian permission.
course
.
assign_permission_by_group
(
institution
)
messages
.
success
(
request
,
_
(
'Course created successfully.'
)
)
return
HttpResponseRedirect
(
self
.
get_success_url
(
course
.
id
))
except
Exception
as
e
:
# pylint: disable=broad-except
messages
.
error
(
request
,
str
(
e
))
messages
.
error
(
request
,
_
(
'Please fill all required field.'
))
ctx
.
update
(
{
'course_form'
:
course_form
,
'run_form'
:
run_form
,
'seat_form'
:
seat_form
}
)
return
render
(
request
,
self
.
template_name
,
ctx
,
status
=
400
)
class
UpdateCourseView
(
mixins
.
LoginRequiredMixin
,
mixins
.
ViewPermissionMixin
,
mixins
.
FormValidMixin
,
UpdateView
):
...
...
@@ -88,6 +149,17 @@ class UpdateCourseView(mixins.LoginRequiredMixin, mixins.ViewPermissionMixin, mi
return
context
class
ReadOnlyView
(
mixins
.
LoginRequiredMixin
,
mixins
.
ViewPermissionMixin
,
DetailView
):
""" Course Run Detail View."""
model
=
Course
template_name
=
'publisher/view_course_form.html'
def
get_context_data
(
self
,
**
kwargs
):
context
=
super
(
ReadOnlyView
,
self
)
.
get_context_data
(
**
kwargs
)
context
[
'comment_object'
]
=
self
return
context
class
CreateCourseRunView
(
mixins
.
LoginRequiredMixin
,
mixins
.
FormValidMixin
,
CreateView
):
""" Create Course Run View."""
model
=
CourseRun
...
...
course_discovery/static/js/publisher/publisher.js
View file @
0dca3588
...
...
@@ -7,8 +7,20 @@ $(".administration-nav .tab-container > button").click(function(event) {
$
(
tab
).
fadeIn
();
});
$
(
document
).
ready
(
function
(){
$
(
'ul.tabs .course-tabs'
).
click
(
function
(){
var
tab_id
=
$
(
this
).
attr
(
'data-tab'
);
$
(
'ul.tabs .course-tabs'
).
removeClass
(
'active'
);
$
(
'.content'
).
removeClass
(
'active'
);
$
(
this
).
addClass
(
'active'
);
$
(
"#"
+
tab_id
).
addClass
(
'active'
);
})
});
function
alertTimeout
(
wait
)
{
setTimeout
(
function
(){
$
(
'.alert-messages'
).
html
(
''
);
},
wait
);
}
\ No newline at end of file
}
course_discovery/static/sass/publisher/course_detail.scss
View file @
0dca3588
...
...
@@ -321,10 +321,97 @@ $light-gray: rgba(204, 204, 204, 1);
margin-bottom
:
20px
;
}
.publisher-layout
{
background
:
rgb
(
242
,
242
,
242
);
padding
:
15px
;
margin-bottom
:
20px
;
.layout-title
{
font-size
:
24px
;
font-weight
:
bold
;
}
.course-form
{
margin
:
0
;
box-shadow
:
none
;
}
}
input
,
select
{
max-width
:
100%
;
}
.required
{
color
:
red
;
font-size
:
12px
;
}
.checkbox-inline
{
ul
{
list-style
:
none
;
margin-left
:
0
;
margin-bottom
:
15px
;
li
{
display
:
inline-block
;
@include
margin-right
(
10px
);
&
:last-child
{
margin-right
:
0
;
}
}
}
}
.course-information
{
margin-bottom
:
30px
;
@include
float
(
left
);
width
:
50%
;
input
,
select
{
margin-bottom
:
15px
;
}
.hd-4
{
margin-bottom
:
25px
;
padding-bottom
:
10px
;
border-bottom
:
1px
solid
rgb
(
51
,
51
,
51
);
}
.field-title
{
border-bottom
:
1px
solid
rgb
(
51
,
51
,
51
);
padding-bottom
:
10px
;
margin-bottom
:
20px
;
font-weight
:
bold
;
}
.course-tabs
{
list-style
:
none
;
@include
float
(
left
);
@include
margin-right
(
10px
);
padding
:
10px
;
border-bottom
:
2px
solid
#ccc
;
color
:
#ccc
;
text-align
:
center
;
&
:hover
{
color
:
#337ab7
;
border-bottom
:
2px
solid
#337ab7
;
}
}
.course-tabs.active
{
border-bottom
:
2px
solid
#337ab7
;
color
:
#337ab7
;
}
.content
{
display
:
none
;
p
{
margin
:
0
;
}
p
:first-of-type
{
margin-bottom
:
20px
;
}
}
.content.active
{
display
:
inline-block
;
}
.info-item
{
margin-bottom
:
15px
;
...
...
course_discovery/templates/publisher/add_course_form.html
0 → 100644
View file @
0dca3588
This diff is collapsed.
Click to expand it.
course_discovery/templates/publisher/view_course_form.html
0 → 100644
View file @
0dca3588
{% extends 'base.html' %}
{% load i18n %}
{% block title %}
{% trans "Course Form" %}
{% endblock title %}
{% block content %}
<div
class=
"alert-messages"
>
{% if messages %}
{% for message in messages %}
<div
class=
"alert alert-{{ message.tags }}"
role=
"alert"
aria-labelledby=
"alert-title-{{ message.tags }}"
tabindex=
"-1"
>
<div
class=
"alert-message-with-action"
>
<p
class=
"alert-copy"
>
{{ message }}
</p>
</div>
</div>
{% endfor %}
{% endif %}
</div>
<div
class=
"layout-full publisher-layout layout"
>
<h2
class=
"layout-title"
>
{% trans "Base information" %}
</h2>
<div
class=
"card course-form"
>
<div
class=
"course-information"
>
<h4
class=
"hd-4"
>
{% trans "Course Form" %}
</h4>
<fieldset
class=
"form-group grid-container grid-manual"
>
<div
class=
"field-title"
>
{% trans "INSTITUTION INFORMATION" %}
</div>
<div
class=
"row"
>
<div
class=
"col col-6"
>
{{ object.get_group_institution }}
</div>
</div>
</fieldset>
</div>
</div>
</div>
<div
class=
"layout-full layout"
>
<h2
class=
"layout-title"
>
{% trans "Course information" %}
</h2>
<div
class=
"card course-form"
>
<div
class=
"course-information"
>
<fieldset
class=
"form-group"
>
<div
class=
"field-row"
>
<div
class=
"field-col"
>
<label
class=
"field-label "
for=
"title"
>
{{ course_form.title.label }}
</label>
{{ object.title }}
</div>
</div>
</fieldset>
</div>
</div>
</div>
{% endblock content %}
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