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
c656d9a4
Commit
c656d9a4
authored
Jul 20, 2012
by
Calen Pennington
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Allow for modular css from XModules, and split capa module css out as a test
parent
bdd07a97
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
368 additions
and
463 deletions
+368
-463
cms/envs/common.py
+55
-23
cms/static/sass/.gitignore
+1
-0
cms/static/sass/base-style.scss
+2
-0
common/djangoapps/xmodule_modifiers.py
+2
-0
common/lib/xmodule/xmodule/capa_module.py
+1
-0
common/lib/xmodule/xmodule/css/capa/display.scss
+214
-242
common/lib/xmodule/xmodule/x_module.py
+45
-46
common/templates/xmodule_display.html
+1
-1
common/templates/xmodule_edit.html
+1
-1
lms/envs/common.py
+43
-13
lms/static/sass/.gitignore
+1
-0
lms/static/sass/course.scss
+2
-1
lms/static/sass/course/old/courseware/_courseware.scss
+0
-136
No files found.
cms/envs/common.py
View file @
c656d9a4
...
@@ -27,6 +27,7 @@ import errno
...
@@ -27,6 +27,7 @@ import errno
import
glob2
import
glob2
import
lms.envs.common
import
lms.envs.common
import
hashlib
import
hashlib
from
collections
import
defaultdict
from
path
import
path
from
path
import
path
############################ FEATURE CONFIGURATION #############################
############################ FEATURE CONFIGURATION #############################
...
@@ -176,47 +177,78 @@ MESSAGE_STORAGE = 'django.contrib.messages.storage.session.SessionStorage'
...
@@ -176,47 +177,78 @@ MESSAGE_STORAGE = 'django.contrib.messages.storage.session.SessionStorage'
STATICFILES_STORAGE
=
'pipeline.storage.PipelineCachedStorage'
STATICFILES_STORAGE
=
'pipeline.storage.PipelineCachedStorage'
PIPELINE_CSS
=
{
# Load javascript and css from all of the available descriptors, and
'base-style'
:
{
'source_filenames'
:
[
'sass/base-style.scss'
],
'output_filename'
:
'css/base-style.css'
,
},
}
PIPELINE_ALWAYS_RECOMPILE
=
[
'sass/base-style.scss'
]
# Load javascript from all of the available descriptors, and
# prep it for use in pipeline js
# prep it for use in pipeline js
from
xmodule.x_module
import
XModuleDescriptor
from
xmodule.x_module
import
XModuleDescriptor
from
xmodule.raw_module
import
RawDescriptor
from
xmodule.raw_module
import
RawDescriptor
js_file_dir
=
PROJECT_ROOT
/
"static"
/
"coffee"
/
"module"
js_file_dir
=
PROJECT_ROOT
/
"static"
/
"coffee"
/
"module"
try
:
css_file_dir
=
PROJECT_ROOT
/
"static"
/
"sass"
/
"module"
os
.
makedirs
(
js_file_dir
)
module_styles_path
=
css_file_dir
/
"_module-styles.scss"
except
OSError
as
exc
:
if
exc
.
errno
==
errno
.
EEXIST
:
for
dir_
in
(
js_file_dir
,
css_file_dir
):
pass
try
:
else
:
os
.
makedirs
(
dir_
)
raise
except
OSError
as
exc
:
if
exc
.
errno
==
errno
.
EEXIST
:
fragments
=
set
()
pass
else
:
raise
js_fragments
=
set
()
css_fragments
=
defaultdict
(
set
)
for
descriptor
in
XModuleDescriptor
.
load_classes
()
+
[
RawDescriptor
]:
for
descriptor
in
XModuleDescriptor
.
load_classes
()
+
[
RawDescriptor
]:
descriptor_js
=
descriptor
.
get_javascript
()
descriptor_js
=
descriptor
.
get_javascript
()
module_js
=
descriptor
.
module_class
.
get_javascript
()
module_js
=
descriptor
.
module_class
.
get_javascript
()
for
filetype
in
(
'coffee'
,
'js'
):
for
filetype
in
(
'coffee'
,
'js'
):
for
idx
,
fragment
in
enumerate
(
descriptor_js
.
get
(
filetype
,
[])
+
module_js
.
get
(
filetype
,
[])):
for
idx
,
fragment
in
enumerate
(
descriptor_js
.
get
(
filetype
,
[])
+
module_js
.
get
(
filetype
,
[])):
fragments
.
add
((
idx
,
filetype
,
fragment
))
js_fragments
.
add
((
idx
,
filetype
,
fragment
))
for
class_
in
(
descriptor
,
descriptor
.
module_class
):
fragments
=
class_
.
get_css
()
for
filetype
in
(
'sass'
,
'scss'
,
'css'
):
for
idx
,
fragment
in
enumerate
(
fragments
.
get
(
filetype
,
[])):
css_fragments
[
idx
,
filetype
,
fragment
]
.
add
(
class_
.
__name__
)
module_js_sources
=
[]
module_js_sources
=
[]
for
idx
,
filetype
,
fragment
in
sorted
(
fragments
):
for
idx
,
filetype
,
fragment
in
sorted
(
js_
fragments
):
path
=
os
.
path
.
join
(
js_file_dir
,
"{idx}-{hash}.{type}"
.
format
(
path
=
js_file_dir
/
"{idx}-{hash}.{type}"
.
format
(
idx
=
idx
,
idx
=
idx
,
hash
=
hashlib
.
md5
(
fragment
)
.
hexdigest
(),
hash
=
hashlib
.
md5
(
fragment
)
.
hexdigest
(),
type
=
filetype
)
)
type
=
filetype
)
with
open
(
path
,
'w'
)
as
js_file
:
with
open
(
path
,
'w'
)
as
js_file
:
js_file
.
write
(
fragment
)
js_file
.
write
(
fragment
)
module_js_sources
.
append
(
path
.
replace
(
PROJECT_ROOT
/
"static/"
,
""
))
module_js_sources
.
append
(
path
.
replace
(
PROJECT_ROOT
/
"static/"
,
""
))
css_imports
=
defaultdict
(
set
)
for
(
idx
,
filetype
,
fragment
),
classes
in
sorted
(
css_fragments
.
items
()):
fragment_name
=
"{idx}-{hash}.{type}"
.
format
(
idx
=
idx
,
hash
=
hashlib
.
md5
(
fragment
)
.
hexdigest
(),
type
=
filetype
)
# Prepend _ so that sass just includes the files into a single file
with
open
(
css_file_dir
/
'_'
+
fragment_name
,
'w'
)
as
js_file
:
js_file
.
write
(
fragment
)
for
class_
in
classes
:
css_imports
[
class_
]
.
add
(
fragment_name
)
with
open
(
module_styles_path
,
'w'
)
as
module_styles
:
for
class_
,
fragment_names
in
css_imports
.
items
():
imports
=
"
\n
"
.
join
(
'@import "{0}";'
.
format
(
name
)
for
name
in
fragment_names
)
module_styles
.
write
(
""".xmodule_{class_} {{ {imports} }}"""
.
format
(
class_
=
class_
,
imports
=
imports
))
PIPELINE_CSS
=
{
'base-style'
:
{
'source_filenames'
:
[
'sass/base-style.scss'
],
'output_filename'
:
'css/base-style.css'
,
},
}
PIPELINE_ALWAYS_RECOMPILE
=
[
'sass/base-style.scss'
]
PIPELINE_JS
=
{
PIPELINE_JS
=
{
'main'
:
{
'main'
:
{
'source_filenames'
:
[
'source_filenames'
:
[
...
...
cms/static/sass/.gitignore
View file @
c656d9a4
*.css
*.css
module
cms/static/sass/base-style.scss
View file @
c656d9a4
...
@@ -4,3 +4,5 @@
...
@@ -4,3 +4,5 @@
@import
'base'
,
'layout'
,
'content-types'
;
@import
'base'
,
'layout'
,
'content-types'
;
@import
'calendar'
;
@import
'calendar'
;
@import
'section'
,
'unit'
;
@import
'section'
,
'unit'
;
@import
'module/module-styles.scss'
;
common/djangoapps/xmodule_modifiers.py
View file @
c656d9a4
...
@@ -14,6 +14,7 @@ def wrap_xmodule(get_html, module, template):
...
@@ -14,6 +14,7 @@ def wrap_xmodule(get_html, module, template):
module: An XModule
module: An XModule
template: A template that takes the variables:
template: A template that takes the variables:
content: the results of get_html,
content: the results of get_html,
class_: the module class name
module_name: the js_module_name of the module
module_name: the js_module_name of the module
"""
"""
...
@@ -21,6 +22,7 @@ def wrap_xmodule(get_html, module, template):
...
@@ -21,6 +22,7 @@ def wrap_xmodule(get_html, module, template):
def
_get_html
():
def
_get_html
():
return
render_to_string
(
template
,
{
return
render_to_string
(
template
,
{
'content'
:
get_html
(),
'content'
:
get_html
(),
'class_'
:
module
.
__class__
.
__name__
,
'module_name'
:
module
.
js_module_name
'module_name'
:
module
.
js_module_name
})
})
return
_get_html
return
_get_html
...
...
common/lib/xmodule/xmodule/capa_module.py
View file @
c656d9a4
...
@@ -75,6 +75,7 @@ class CapaModule(XModule):
...
@@ -75,6 +75,7 @@ class CapaModule(XModule):
'js'
:
[
resource_string
(
__name__
,
'js/src/capa/imageinput.js'
),
'js'
:
[
resource_string
(
__name__
,
'js/src/capa/imageinput.js'
),
resource_string
(
__name__
,
'js/src/capa/schematic.js'
)]}
resource_string
(
__name__
,
'js/src/capa/schematic.js'
)]}
js_module_name
=
"Problem"
js_module_name
=
"Problem"
css
=
{
'scss'
:
[
resource_string
(
__name__
,
'css/capa/display.scss'
)]}
def
__init__
(
self
,
system
,
location
,
definition
,
instance_state
=
None
,
shared_state
=
None
,
**
kwargs
):
def
__init__
(
self
,
system
,
location
,
definition
,
instance_state
=
None
,
shared_state
=
None
,
**
kwargs
):
XModule
.
__init__
(
self
,
system
,
location
,
definition
,
instance_state
,
shared_state
,
**
kwargs
)
XModule
.
__init__
(
self
,
system
,
location
,
definition
,
instance_state
,
shared_state
,
**
kwargs
)
...
...
lms/static/sass/course/old/courseware/_problems
.scss
→
common/lib/xmodule/xmodule/css/capa/display
.scss
View file @
c656d9a4
section
.problem-set
{
h2
{
position
:
relative
;
margin-top
:
0
;
@extend
.clearfix
;
margin-bottom
:
15px
;
width
:
flex-grid
(
2
,
9
);
h2
{
padding-right
:
flex-gutter
(
9
);
margin-top
:
0
;
border-right
:
1px
dashed
#ddd
;
margin-bottom
:
15px
;
@include
box-sizing
(
border-box
);
width
:
flex-grid
(
2
,
9
);
display
:
table-cell
;
padding-right
:
flex-gutter
(
9
);
vertical-align
:
top
;
border-right
:
1px
dashed
#ddd
;
@include
box-sizing
(
border-box
);
&
.problem-header
{
display
:
table-cell
;
section
.staff
{
vertical-align
:
top
;
margin-top
:
30px
;
font-size
:
80%
;
&
.problem-header
{
section
.staff
{
margin-top
:
30px
;
font-size
:
80%
;
}
}
@media
screen
and
(
max-width
:
1120px
)
{
display
:
block
;
width
:
auto
;
border-right
:
0
;
}
@media
print
{
display
:
block
;
width
:
auto
;
border-right
:
0
;
}
}
}
}
section
.problem
{
@media
screen
and
(
max-width
:
1120px
)
{
display
:
table-cell
;
display
:
block
;
width
:
flex-grid
(
7
,
9
);
width
:
auto
;
padding-left
:
flex-gutter
(
9
);
border-right
:
0
;
}
@media
screen
and
(
max-width
:
1120px
)
{
display
:
block
;
width
:
auto
;
padding
:
0
;
}
@media
print
{
display
:
block
;
width
:
auto
;
padding
:
0
;
canvas
,
img
{
page-break-inside
:
avoid
;
}
}
div
{
p
.status
{
text-indent
:
-9999px
;
margin
:
-1px
0
0
10px
;
}
&
.unanswered
{
@media
print
{
p
.status
{
display
:
block
;
@include
inline-block
();
width
:
auto
;
background
:
url('../images/unanswered-icon.png')
center
center
no-repeat
;
border-right
:
0
;
height
:
14px
;
}
width
:
14px
;
}
}
}
&
.correct
,
&
.ui-icon-check
{
section
.problem
{
p
.status
{
display
:
table-cell
;
@include
inline-block
();
width
:
flex-grid
(
7
,
9
);
background
:
url('../images/correct-icon.png')
center
center
no-repeat
;
padding-left
:
flex-gutter
(
9
);
height
:
20px
;
width
:
25px
;
}
input
{
border-color
:
green
;
}
}
&
.incorrect
,
&
.ui-icon-close
{
@media
screen
and
(
max-width
:
1120px
)
{
p
.status
{
display
:
block
;
@include
inline-block
();
width
:
auto
;
background
:
url('../images/incorrect-icon.png')
center
center
no-repeat
;
padding
:
0
;
height
:
20px
;
}
width
:
20px
;
text-indent
:
-9999px
;
}
input
{
border-color
:
red
;
}
}
>
span
{
@media
print
{
display
:
block
;
display
:
block
;
margin-bottom
:
lh
(
.5
)
;
width
:
auto
;
}
padding
:
0
;
p
.answer
{
canvas
,
img
{
@include
inline-block
();
page-break-inside
:
avoid
;
margin-bottom
:
0
;
}
margin-left
:
10px
;
}
&
:before
{
content
:
"Answer: "
;
font-weight
:
bold
;
display
:
inline
;
}
&
:empty
{
&
:before
{
display
:
none
;
}
}
}
div
.equation
{
div
{
clear
:
both
;
p
.status
{
padding
:
6px
;
text-indent
:
-9999px
;
background
:
#eee
;
margin
:
-1px
0
0
10px
;
}
span
{
&
.unanswered
{
margin-bottom
:
0
;
p
.status
{
}
@include
inline-block
();
}
background
:
url('../images/unanswered-icon.png')
center
center
no-repeat
;
height
:
14px
;
width
:
14px
;
}
}
span
{
&
.correct
,
&
.ui-icon-check
{
&
.unanswered
,
&
.ui-icon-bullet
{
p
.status
{
@include
inline-block
();
@include
inline-block
();
background
:
url('../images/unanswered-icon.png')
center
center
no-repeat
;
background
:
url('../images/correct-icon.png')
center
center
no-repeat
;
height
:
14px
;
height
:
20px
;
position
:
relative
;
width
:
25px
;
top
:
4px
;
width
:
14px
;
}
&
.correct
,
&
.ui-icon-check
{
@include
inline-block
();
background
:
url('../images/correct-icon.png')
center
center
no-repeat
;
height
:
20px
;
position
:
relative
;
top
:
6px
;
width
:
25px
;
}
&
.incorrect
,
&
.ui-icon-close
{
@include
inline-block
();
background
:
url('../images/incorrect-icon.png')
center
center
no-repeat
;
height
:
20px
;
width
:
20px
;
position
:
relative
;
top
:
6px
;
}
}
}
}
ul
{
input
{
list-style
:
disc
outside
none
;
border-color
:
green
;
margin-bottom
:
lh
();
margin-left
:
.75em
;
margin-left
:
.75rem
;
}
}
}
ol
{
&
.incorrect
,
&
.ui-icon-close
{
list-style
:
decimal
outside
none
;
p
.status
{
margin-bottom
:
lh
();
@include
inline-block
();
margin-left
:
.75em
;
background
:
url('../images/incorrect-icon.png')
center
center
no-repeat
;
margin-left
:
.75rem
;
height
:
20px
;
width
:
20px
;
text-indent
:
-9999px
;
}
}
dl
{
input
{
line-height
:
1
.4em
;
border-color
:
red
;
}
}
}
>
span
{
display
:
block
;
margin-bottom
:
lh
(
.5
);
}
p
.answer
{
@include
inline-block
();
margin-bottom
:
0
;
margin-left
:
10px
;
dl
dt
{
&
:before
{
content
:
"Answer: "
;
font-weight
:
bold
;
font-weight
:
bold
;
display
:
inline
;
}
}
&
:empty
{
&
:before
{
display
:
none
;
}
}
}
dl
dd
{
div
.equation
{
clear
:
both
;
padding
:
6px
;
background
:
#eee
;
span
{
margin-bottom
:
0
;
margin-bottom
:
0
;
}
}
}
dd
{
span
{
margin-left
:
.5em
;
&
.unanswered
,
&
.ui-icon-bullet
{
margin-left
:
.5rem
;
@include
inline-block
();
background
:
url('../images/unanswered-icon.png')
center
center
no-repeat
;
height
:
14px
;
position
:
relative
;
top
:
4px
;
width
:
14px
;
}
}
li
{
&
.correct
,
&
.ui-icon-check
{
line-height
:
1
.4em
;
@include
inline-block
()
;
margin-bottom
:
lh
(
.5
)
;
background
:
url('../images/correct-icon.png')
center
center
no-repeat
;
height
:
20px
;
&
:last-child
{
position
:
relative
;
margin-bottom
:
0
;
top
:
6px
;
}
width
:
25px
;
}
}
p
{
&
.incorrect
,
&
.ui-icon-close
{
margin-bottom
:
lh
();
@include
inline-block
();
background
:
url('../images/incorrect-icon.png')
center
center
no-repeat
;
height
:
20px
;
width
:
20px
;
position
:
relative
;
top
:
6px
;
}
}
}
}
table
{
ul
{
margin-bottom
:
lh
();
list-style
:
disc
outside
none
;
width
:
100%
;
margin-bottom
:
lh
();
// border: 1px solid #ddd;
margin-left
:
.75em
;
border-collapse
:
collapse
;
margin-left
:
.75rem
;
}
th
{
ol
{
// border-bottom: 2px solid #ccc;
list-style
:
decimal
outside
none
;
font-weight
:
bold
;
margin-bottom
:
lh
();
text-align
:
left
;
margin-left
:
.75em
;
}
margin-left
:
.75rem
;
}
td
{
dl
{
// border: 1px solid #ddd
;
line-height
:
1
.4em
;
}
}
caption
,
th
,
td
{
dl
dt
{
padding
:
.25em
.75em
.25em
0
;
font-weight
:
bold
;
padding
:
.25rem
.75rem
.25rem
0
;
}
}
caption
{
dl
dd
{
background
:
#f1f1f1
;
margin-bottom
:
0
;
margin-bottom
:
.75em
;
}
margin-bottom
:
.75rem
;
padding
:
.75em
0
;
padding
:
.75rem
0
;
}
tr
,
td
,
th
{
dd
{
vertical-align
:
middle
;
margin-left
:
.5em
;
}
margin-left
:
.5rem
;
}
}
li
{
line-height
:
1
.4em
;
margin-bottom
:
lh
(
.5
);
hr
{
&
:last-child
{
background
:
#ddd
;
margin-bottom
:
0
;
border
:
none
;
}
clear
:
both
;
}
color
:
#ddd
;
float
:
none
;
height
:
1px
;
margin
:
0
0
.75rem
;
width
:
100%
;
}
.hidden
{
p
{
display
:
none
;
margin-bottom
:
lh
();
visibility
:
hidden
;
}
}
#{
$all-text-inputs
}
{
table
{
display
:
inline
;
margin-bottom
:
lh
();
width
:
auto
;
width
:
100%
;
}
// border: 1px solid #ddd;
border-collapse
:
collapse
;
// this supports a deprecated element and should be removed once the center tag is removed
th
{
center
{
// border-bottom: 2px solid #ccc;
display
:
block
;
font-weight
:
bold
;
margin
:
lh
()
0
;
text-align
:
left
;
border
:
1px
solid
#ccc
;
padding
:
lh
();
}
}
}
section
.action
{
td
{
margin-top
:
lh
(
.5
);
// border: 1px solid #ddd;
}
input
[
type
=
"button"
]
{
caption
,
th
,
td
{
padding
:
lh
(
.4
)
lh
();
padding
:
.25em
.75em
.25em
0
;
text-shadow
:
0
-1px
0
#666
;
padding
:
.25rem
.75rem
.25rem
0
;
}
}
caption
{
background
:
#f1f1f1
;
margin-bottom
:
.75em
;
margin-bottom
:
.75rem
;
padding
:
.75em
0
;
padding
:
.75rem
0
;
}
tr
,
td
,
th
{
vertical-align
:
middle
;
}
}
}
section
.problems-wrapper
,
div
#seq_content
{
@extend
.problem-set
;
}
}
section
.problems-wrapper
{
hr
{
display
:
table
;
background
:
#ddd
;
border
:
none
;
clear
:
both
;
color
:
#ddd
;
float
:
none
;
height
:
1px
;
margin
:
0
0
.75rem
;
width
:
100%
;
width
:
100%
;
}
@media
screen
and
(
max-width
:
1120px
)
{
.hidden
{
display
:
block
;
display
:
none
;
width
:
auto
;
visibility
:
hidden
;
}
}
#{
$all-text-inputs
}
{
display
:
inline
;
width
:
auto
;
}
// this supports a deprecated element and should be removed once the center tag is removed
center
{
display
:
block
;
margin
:
lh
()
0
;
border
:
1px
solid
#ccc
;
padding
:
lh
();
}
}
}
common/lib/xmodule/xmodule/x_module.py
View file @
c656d9a4
...
@@ -64,7 +64,50 @@ class Plugin(object):
...
@@ -64,7 +64,50 @@ class Plugin(object):
in
pkg_resources
.
iter_entry_points
(
cls
.
entry_point
)]
in
pkg_resources
.
iter_entry_points
(
cls
.
entry_point
)]
class
XModule
(
object
):
class
HTMLSnippet
(
object
):
"""
A base class defining an interface for an object that is able to present an
html snippet, along with associated javascript and css
"""
js
=
{}
js_module_name
=
None
css
=
{}
@classmethod
def
get_javascript
(
cls
):
"""
Return a dictionary containing some of the following keys:
coffee: A list of coffeescript fragments that should be compiled and
placed on the page
js: A list of javascript fragments that should be included on the page
All of these will be loaded onto the page in the CMS
"""
return
cls
.
js
@classmethod
def
get_css
(
cls
):
"""
Return a dictionary containing some of the following keys:
css: A list of css fragments that should be applied to the html contents
of the snippet
sass: A list of sass fragments that should be applied to the html contents
of the snippet
scss: A list of scss fragments that should be applied to the html contents
of the snippet
"""
return
cls
.
css
def
get_html
(
self
):
"""
Return the html used to edit this module
"""
raise
NotImplementedError
(
"get_html() must be provided by specific modules"
)
class
XModule
(
HTMLSnippet
):
''' Implements a generic learning module.
''' Implements a generic learning module.
Subclasses must at a minimum provide a definition for get_html in order to be displayed to users.
Subclasses must at a minimum provide a definition for get_html in order to be displayed to users.
...
@@ -77,9 +120,6 @@ class XModule(object):
...
@@ -77,9 +120,6 @@ class XModule(object):
# if the icon class depends on the data in the module
# if the icon class depends on the data in the module
icon_class
=
'other'
icon_class
=
'other'
js
=
{}
js_module_name
=
None
def
__init__
(
self
,
system
,
location
,
definition
,
instance_state
=
None
,
shared_state
=
None
,
**
kwargs
):
def
__init__
(
self
,
system
,
location
,
definition
,
instance_state
=
None
,
shared_state
=
None
,
**
kwargs
):
'''
'''
Construct a new xmodule
Construct a new xmodule
...
@@ -196,28 +236,8 @@ class XModule(object):
...
@@ -196,28 +236,8 @@ class XModule(object):
get is a dictionary-like object '''
get is a dictionary-like object '''
return
""
return
""
# ================================== HTML INTERFACE DEFINITIONS ======================
@classmethod
def
get_javascript
(
cls
):
"""
Return a dictionary containing some of the following keys:
coffee: A list of coffeescript fragments that should be compiled and
placed on the page
js: A list of javascript fragments that should be included on the page
All of these will be loaded onto the page in the LMS
"""
return
cls
.
js
def
get_html
(
self
):
''' HTML, as shown in the browser. This is the only method that must be implemented
'''
raise
NotImplementedError
(
"get_html must be defined for all XModules that appear on the screen. Not defined in
%
s"
%
self
.
__class__
.
__name__
)
class
XModuleDescriptor
(
Plugin
,
HTMLSnippet
):
class
XModuleDescriptor
(
Plugin
):
"""
"""
An XModuleDescriptor is a specification for an element of a course. This could
An XModuleDescriptor is a specification for an element of a course. This could
be a problem, an organizational element (a group of content), or a segment of video,
be a problem, an organizational element (a group of content), or a segment of video,
...
@@ -228,8 +248,6 @@ class XModuleDescriptor(Plugin):
...
@@ -228,8 +248,6 @@ class XModuleDescriptor(Plugin):
and can generate XModules (which do know about student state).
and can generate XModules (which do know about student state).
"""
"""
entry_point
=
"xmodule.v1"
entry_point
=
"xmodule.v1"
js
=
{}
js_module_name
=
None
module_class
=
XModule
module_class
=
XModule
# A list of metadata that this module can inherit from its parent module
# A list of metadata that this module can inherit from its parent module
...
@@ -404,25 +422,6 @@ class XModuleDescriptor(Plugin):
...
@@ -404,25 +422,6 @@ class XModuleDescriptor(Plugin):
"""
"""
raise
NotImplementedError
(
'Modules must implement export_to_xml to enable xml export'
)
raise
NotImplementedError
(
'Modules must implement export_to_xml to enable xml export'
)
# ================================== HTML INTERFACE DEFINITIONS ======================
@classmethod
def
get_javascript
(
cls
):
"""
Return a dictionary containing some of the following keys:
coffee: A list of coffeescript fragments that should be compiled and
placed on the page
js: A list of javascript fragments that should be included on the page
All of these will be loaded onto the page in the CMS
"""
return
cls
.
js
def
get_html
(
self
):
"""
Return the html used to edit this module
"""
raise
NotImplementedError
(
"get_html() must be provided by specific modules"
)
# =============================== Testing ===================================
# =============================== Testing ===================================
def
get_sample_state
(
self
):
def
get_sample_state
(
self
):
"""
"""
...
...
common/templates/xmodule_display.html
View file @
c656d9a4
<section
class=
"xmodule_display"
data-type=
"${module_name}"
>
<section
class=
"xmodule_display
xmodule_${class_}
"
data-type=
"${module_name}"
>
${content}
${content}
</section>
</section>
common/templates/xmodule_edit.html
View file @
c656d9a4
<section
class=
"xmodule_edit"
data-type=
"${module_name}"
>
<section
class=
"xmodule_edit
xmodule_${class_}
"
data-type=
"${module_name}"
>
${content}
${content}
</section>
</section>
lms/envs/common.py
View file @
c656d9a4
...
@@ -24,6 +24,7 @@ import tempfile
...
@@ -24,6 +24,7 @@ import tempfile
import
glob2
import
glob2
import
errno
import
errno
import
hashlib
import
hashlib
from
collections
import
defaultdict
import
djcelery
import
djcelery
from
path
import
path
from
path
import
path
...
@@ -336,31 +337,60 @@ main_vendor_js = [
...
@@ -336,31 +337,60 @@ main_vendor_js = [
from
xmodule.x_module
import
XModuleDescriptor
from
xmodule.x_module
import
XModuleDescriptor
from
xmodule.hidden_module
import
HiddenDescriptor
from
xmodule.hidden_module
import
HiddenDescriptor
js_file_dir
=
PROJECT_ROOT
/
"static"
/
"coffee"
/
"module"
js_file_dir
=
PROJECT_ROOT
/
"static"
/
"coffee"
/
"module"
try
:
css_file_dir
=
PROJECT_ROOT
/
"static"
/
"sass"
/
"module"
os
.
makedirs
(
js_file_dir
)
module_styles_path
=
css_file_dir
/
"_module-styles.scss"
except
OSError
as
exc
:
if
exc
.
errno
==
errno
.
EEXIST
:
for
dir_
in
(
js_file_dir
,
css_file_dir
):
pass
try
:
else
:
os
.
makedirs
(
dir_
)
raise
except
OSError
as
exc
:
if
exc
.
errno
==
errno
.
EEXIST
:
fragments
=
set
()
pass
else
:
raise
js_fragments
=
set
()
css_fragments
=
defaultdict
(
set
)
for
descriptor
in
XModuleDescriptor
.
load_classes
()
+
[
HiddenDescriptor
]:
for
descriptor
in
XModuleDescriptor
.
load_classes
()
+
[
HiddenDescriptor
]:
module_js
=
descriptor
.
module_class
.
get_javascript
()
module_js
=
descriptor
.
module_class
.
get_javascript
()
for
filetype
in
(
'coffee'
,
'js'
):
for
filetype
in
(
'coffee'
,
'js'
):
for
idx
,
fragment
in
enumerate
(
module_js
.
get
(
filetype
,
[])):
for
idx
,
fragment
in
enumerate
(
module_js
.
get
(
filetype
,
[])):
fragments
.
add
((
idx
,
filetype
,
fragment
))
js_fragments
.
add
((
idx
,
filetype
,
fragment
))
module_css
=
descriptor
.
module_class
.
get_css
()
for
filetype
in
(
'sass'
,
'scss'
,
'css'
):
for
idx
,
fragment
in
enumerate
(
module_css
.
get
(
filetype
,
[])):
css_fragments
[
idx
,
filetype
,
fragment
]
.
add
(
descriptor
.
module_class
.
__name__
)
module_js_sources
=
[]
module_js_sources
=
[]
for
idx
,
filetype
,
fragment
in
sorted
(
fragments
):
for
idx
,
filetype
,
fragment
in
sorted
(
js_
fragments
):
path
=
os
.
path
.
join
(
js_file_dir
,
"{idx}-{hash}.{type}"
.
format
(
path
=
js_file_dir
/
"{idx}-{hash}.{type}"
.
format
(
idx
=
idx
,
idx
=
idx
,
hash
=
hashlib
.
md5
(
fragment
)
.
hexdigest
(),
hash
=
hashlib
.
md5
(
fragment
)
.
hexdigest
(),
type
=
filetype
)
)
type
=
filetype
)
with
open
(
path
,
'w'
)
as
js_file
:
with
open
(
path
,
'w'
)
as
js_file
:
js_file
.
write
(
fragment
)
js_file
.
write
(
fragment
)
module_js_sources
.
append
(
path
.
replace
(
PROJECT_ROOT
/
"static/"
,
""
))
module_js_sources
.
append
(
path
.
replace
(
PROJECT_ROOT
/
"static/"
,
""
))
css_imports
=
defaultdict
(
set
)
for
(
idx
,
filetype
,
fragment
),
classes
in
sorted
(
css_fragments
.
items
()):
fragment_name
=
"{idx}-{hash}.{type}"
.
format
(
idx
=
idx
,
hash
=
hashlib
.
md5
(
fragment
)
.
hexdigest
(),
type
=
filetype
)
# Prepend _ so that sass just includes the files into a single file
with
open
(
css_file_dir
/
'_'
+
fragment_name
,
'w'
)
as
js_file
:
js_file
.
write
(
fragment
)
for
class_
in
classes
:
css_imports
[
class_
]
.
add
(
fragment_name
)
with
open
(
module_styles_path
,
'w'
)
as
module_styles
:
for
class_
,
fragment_names
in
css_imports
.
items
():
imports
=
"
\n
"
.
join
(
'@import "{0}";'
.
format
(
name
)
for
name
in
fragment_names
)
module_styles
.
write
(
""".xmodule_{class_} {{ {imports} }}"""
.
format
(
class_
=
class_
,
imports
=
imports
))
PIPELINE_JS
=
{
PIPELINE_JS
=
{
'application'
:
{
'application'
:
{
...
...
lms/static/sass/.gitignore
View file @
c656d9a4
*.css
*.css
module
lms/static/sass/course.scss
View file @
c656d9a4
...
@@ -20,4 +20,5 @@
...
@@ -20,4 +20,5 @@
@import
'course/old/courseware/sidebar'
;
@import
'course/old/courseware/sidebar'
;
@import
'course/old/courseware/video'
;
@import
'course/old/courseware/video'
;
@import
'course/old/courseware/amplifier'
;
@import
'course/old/courseware/amplifier'
;
@import
'course/old/courseware/problems'
;
@import
'module/module-styles.scss'
;
lms/static/sass/course/old/courseware/_courseware.scss
View file @
c656d9a4
...
@@ -49,142 +49,6 @@ div.course-wrapper {
...
@@ -49,142 +49,6 @@ div.course-wrapper {
}
}
}
}
.problem-set
{
position
:
relative
;
@extend
.clearfix
;
h2
{
margin-top
:
0
;
margin-bottom
:
15px
;
width
:
flex-grid
(
2
,
9
);
padding-right
:
flex-gutter
(
9
);
border-right
:
1px
dashed
#ddd
;
@include
box-sizing
(
border-box
);
display
:
table-cell
;
vertical-align
:
top
;
&
.problem-header
{
section
.staff
{
margin-top
:
30px
;
font-size
:
80%
;
}
}
@media
screen
and
(
max-width
:
1120px
)
{
display
:
block
;
width
:
auto
;
border-right
:
0
;
}
@media
print
{
display
:
block
;
width
:
auto
;
border-right
:
0
;
}
}
section
.problem
{
display
:
table-cell
;
width
:
flex-grid
(
7
,
9
);
padding-left
:
flex-gutter
(
9
);
@media
screen
and
(
max-width
:
1120px
)
{
display
:
block
;
width
:
auto
;
padding
:
0
;
}
@media
print
{
display
:
block
;
width
:
auto
;
padding
:
0
;
canvas
,
img
{
page-break-inside
:
avoid
;
}
}
span
{
&
.unanswered
,
&
.ui-icon-bullet
{
@include
inline-block
();
background
:
url('../images/unanswered-icon.png')
center
center
no-repeat
;
height
:
14px
;
position
:
relative
;
top
:
4px
;
width
:
14px
;
}
&
.correct
,
&
.ui-icon-check
{
@include
inline-block
();
background
:
url('../images/correct-icon.png')
center
center
no-repeat
;
height
:
20px
;
position
:
relative
;
top
:
6px
;
width
:
25px
;
}
&
.incorrect
,
&
.ui-icon-close
{
@include
inline-block
();
background
:
url('../images/incorrect-icon.png')
center
center
no-repeat
;
height
:
20px
;
width
:
20px
;
position
:
relative
;
top
:
6px
;
}
}
}
div
{
>
span
{
display
:
block
;
margin-bottom
:
lh
(
.5
);
&
[
answer
]
{
border-top
:
1px
solid
#ededed
;
border-bottom
:
1px
solid
#ededed
;
background
:
#f3f3f3
;
margin
:
0
(
-
(
lh
()));
padding
:
lh
(
.5
)
lh
();
}
}
}
input
[
type
=
"text"
]
{
display
:
inline-block
;
width
:
50%
;
}
center
{
display
:
block
;
margin
:
lh
()
0
;
border
:
1px
solid
#ccc
;
padding
:
lh
();
}
section
.action
{
margin-top
:
lh
();
input
[
type
=
"button"
]
{
padding
:
lh
(
.4
)
lh
();
text-shadow
:
0
-1px
0
#666
;
}
}
}
section
.problems-wrapper
,
div
#seq_content
{
@extend
.problem-set
;
}
section
.problems-wrapper
{
display
:
table
;
width
:
100%
;
@media
screen
and
(
max-width
:
1120px
)
{
display
:
block
;
width
:
auto
;
}
}
div
#seq_content
{
div
#seq_content
{
h1
{
h1
{
background
:
none
;
background
:
none
;
...
...
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