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
8b59c6d5
Unverified
Commit
8b59c6d5
authored
Dec 06, 2017
by
Ari Rizzitano
Committed by
GitHub
Dec 06, 2017
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #16639 from edx/ari/react-renderer
mako/react bridge code
parents
9b92a3b7
8ca0fe9d
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
123 additions
and
32 deletions
+123
-32
cms/templates/index.html
+1
-0
common/djangoapps/pipeline_mako/templates/static_content.html
+43
-30
common/static/js/src/ReactRenderer.jsx
+66
-0
conftest.py
+9
-1
webpack.common.config.js
+4
-1
No files found.
cms/templates/index.html
View file @
8b59c6d5
...
...
@@ -552,6 +552,7 @@ from openedx.core.djangolib.js_utils import (
%endif
</div>
<
%
static:webpack
entry=
"StudioIndex"
>
var enableReruns = ${allow_course_reruns and rerun_creator_status and course_creator_status=='granted' | n, dump_js_escaped_json};
new StudioCourseIndex(
...
...
common/djangoapps/pipeline_mako/templates/static_content.html
View file @
8b59c6d5
<
%
page
expression_filter=
"h"
/>
<
%!
import
logging
import
json
from
django
.
contrib
.
staticfiles
.
storage
import
staticfiles_storage
from
pipeline_mako
import
compressed_css
,
compressed_js
from
django
.
utils
.
translation
import
get_language_bidi
from
mako
.
exceptions
import
TemplateLookupException
from
edxmako
.
shortcuts
import
marketing_link
from
openedx
.
core
.
djangolib
.
js_utils
import
js_escaped_string
from
openedx
.
core
.
djangolib
.
js_utils
import
js_escaped_string
,
dump_js_escaped_json
from
openedx
.
core
.
djangolib
.
markup
import
HTML
from
openedx
.
core
.
djangoapps
.
site_configuration
.
helpers
import
(
page_title_breadcrumbs
,
get_value
,
...
...
@@ -18,6 +20,7 @@ from openedx.core.djangoapps.theming.helpers import (
is_request_in_themed_site
,
)
from
certificates
.
api
import
get_asset_url_by_slug
from
webpack_loader
.
templatetags
.
webpack_loader
import
render_bundle
logger =
logging.getLogger(__name__)
%
>
...
...
@@ -97,25 +100,15 @@ source, template_path = Loader(engine).load_template_source(path)
-include it as the first script in this block
</
%
doc>
<
%
from
django
.
template
import
Template
,
Context
from
webpack_loader
.
exceptions
import
WebpackLoaderBadStatsError
import
json
body =
capture(caller.body)
body_dict =
json.loads(body)
body_dict
['
lang
']
=
lang
return
Template
("""
<
script
type=
"text/javascript"
id=
'studioContext'
>
var studioContext = {% autoescape off %}{{ body }}{% endautoescape %};
</script>
<div
id=
"root"
></div>
{% load render_bundle from webpack_loader %}
{% render_bundle page %}
""").render(Context({
'body': json.dumps(body_dict),
'page': page
}))
%
>
<script
type=
"text/javascript"
id=
'courseContext'
>
var
studioContext
=
$
{
body
|
n
,
decode
.
utf8
};
</script>
<div
id=
"root"
></div>
${HTML(render_bundle(page))}
</
%
def>
<
%
def
name=
"webpack(entry)"
>
...
...
@@ -124,21 +117,41 @@ source, template_path = Loader(engine).load_template_source(path)
Uses the Django template engine because our webpack loader only provides template tags for Jinja and Django.
</
%
doc>
<
%
from
django
.
template
import
Template
,
Context
from
webpack_loader
.
exceptions
import
WebpackLoaderBadStatsError
return
Template
("""
{%
load
render_bundle
from
webpack_loader
%}
{%
render_bundle
entry
%}
{%
if
body
%}
<
script
type=
"text/javascript"
>
{% autoescape off %}{{ body }}{% endautoescape %}
</script>
{% endif %}
""").render(Context({
'entry': entry,
'body': capture(caller.body)
}))
body =
capture(caller.body)
%
>
${HTML(render_bundle(entry))}
% if body:
<script
type=
"text/javascript"
>
$
{
body
|
n
,
decode
.
utf8
}
</script>
% endif
</
%
def>
<
%
def
name=
"renderReact(component, id, props={})"
>
<
%
doc
>
Wrapper function to load a React component via webpack() and render
it onto the page, passing an optional context object via props.
component: (string) The component to render, as specified by the name
of its Webpack entry point.
id: (string) A unique id to apply to the component's container div.
props: (dict, optional) An object containing data to pass into the
component as props.
</
%
doc>
${HTML(render_bundle(component))}
${HTML(render_bundle('ReactRenderer'))}
<div
id=
"${id}"
></div>
<script
type=
"text/javascript"
>
var
c
;
try
{
c
=
$
{
component
|
n
,
decode
.
utf8
};
}
catch
(
e
)
{
c
=
null
;
}
new
ReactRenderer
({
component
:
c
,
selector
:
'#${id | n, decode.utf8}'
,
componentName
:
'${component | n, js_escaped_string}'
,
props
:
$
{
props
|
n
,
dump_js_escaped_json
}
});
</script>
</
%
def>
<
%
def
name=
"require_module(module_name, class_name)"
>
...
...
common/static/js/src/ReactRenderer.jsx
0 → 100644
View file @
8b59c6d5
import
React
from
'react'
;
import
ReactDOM
from
'react-dom'
;
class
ReactRendererException
extends
Error
{
constructor
(
message
)
{
super
(
`ReactRendererException:
${
message
}
`
);
Error
.
captureStackTrace
(
this
,
ReactRendererException
);
}
}
export
class
ReactRenderer
{
constructor
({
component
,
selector
,
componentName
,
props
=
{}
})
{
Object
.
assign
(
this
,
{
component
,
selector
,
componentName
,
props
,
});
this
.
handleArgumentErrors
();
this
.
targetElement
=
this
.
getTargetElement
();
this
.
renderComponent
();
}
handleArgumentErrors
()
{
if
(
this
.
component
===
null
)
{
throw
new
ReactRendererException
(
`Component
${
this
.
componentName
}
is not defined. Make sure you're `
+
`using a non-default export statement for the
${
this
.
componentName
}
`
+
`class, that
${
this
.
componentName
}
has an entry point defined `
+
'within the
\'
entry
\'
section of webpack.common.config.js, and that the '
+
'entry point is pointing at the correct file path.'
,
);
}
if
(
!
(
this
.
props
instanceof
Object
&&
this
.
props
.
constructor
===
Object
))
{
let
propsType
=
typeof
this
.
props
;
if
(
Array
.
isArray
(
this
.
props
))
{
propsType
=
'array'
;
}
else
if
(
this
.
props
===
null
)
{
propsType
=
'null'
;
}
throw
new
ReactRendererException
(
`Invalid props passed to component
${
this
.
componentName
}
. Expected `
+
`an object, but received a
${
propsType
}
.`
,
);
}
}
getTargetElement
()
{
const
elementList
=
document
.
querySelectorAll
(
this
.
selector
);
if
(
elementList
.
length
!==
1
)
{
throw
new
ReactRendererException
(
`Expected 1 element match for selector "
${
this
.
selector
}
" `
+
`but received
${
elementList
.
length
}
matches.`
,
);
}
else
{
return
elementList
[
0
];
}
}
renderComponent
()
{
ReactDOM
.
render
(
React
.
createElement
(
this
.
component
,
this
.
props
,
null
),
this
.
targetElement
,
);
}
}
conftest.py
View file @
8b59c6d5
"""
Default unit test configuration and fixtures.
"""
from
__future__
import
absolute_import
,
unicode_literals
import
pytest
# Import hooks and fixture overrides from the cms package to
# avoid duplicating the implementation
from
cms.conftest
import
_django_clear_site_cache
,
pytest_configure
# pylint: disable=unused-import
@pytest.fixture
(
autouse
=
True
)
def
no_webpack_loader
(
monkeypatch
):
monkeypatch
.
setattr
(
"webpack_loader.templatetags.webpack_loader.render_bundle"
,
lambda
x
:
''
)
webpack.common.config.js
View file @
8b59c6d5
...
...
@@ -35,7 +35,10 @@ module.exports = {
Currency
:
'./openedx/features/course_experience/static/course_experience/js/currency.js'
,
Enrollment
:
'./openedx/features/course_experience/static/course_experience/js/Enrollment.js'
,
LatestUpdate
:
'./openedx/features/course_experience/static/course_experience/js/LatestUpdate.js'
,
WelcomeMessage
:
'./openedx/features/course_experience/static/course_experience/js/WelcomeMessage.js'
WelcomeMessage
:
'./openedx/features/course_experience/static/course_experience/js/WelcomeMessage.js'
,
// Common
ReactRenderer
:
'./common/static/js/src/ReactRenderer.jsx'
},
output
:
{
...
...
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