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
24fcab7f
Commit
24fcab7f
authored
Feb 06, 2015
by
David Ormsbee
Committed by
Clinton Blackburn
Feb 11, 2015
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Very rough cut at generating a course outline after publishing.
parent
b3cc2f57
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
146 additions
and
4 deletions
+146
-4
cms/envs/common.py
+2
-0
common/lib/xmodule/xmodule/modulestore/django.py
+17
-0
common/lib/xmodule/xmodule/modulestore/mixed.py
+3
-0
common/lib/xmodule/xmodule/modulestore/mongo/base.py
+2
-0
common/lib/xmodule/xmodule/modulestore/split_mongo/split.py
+3
-1
common/lib/xmodule/xmodule/modulestore/split_mongo/split_draft.py
+5
-1
common/lib/xmodule/xmodule/modulestore/tests/utils.py
+2
-1
common/lib/xmodule/xmodule/modulestore/xml.py
+2
-1
lms/envs/common.py
+2
-0
openedx/core/djangoapps/content/__init__.py
+0
-0
openedx/core/djangoapps/content/course_structures/__init__.py
+0
-0
openedx/core/djangoapps/content/course_structures/admin.py
+5
-0
openedx/core/djangoapps/content/course_structures/migrations/0001_initial.py
+41
-0
openedx/core/djangoapps/content/course_structures/migrations/__init__.py
+0
-0
openedx/core/djangoapps/content/course_structures/models.py
+62
-0
No files found.
cms/envs/common.py
View file @
24fcab7f
...
@@ -719,6 +719,8 @@ INSTALLED_APPS = (
...
@@ -719,6 +719,8 @@ INSTALLED_APPS = (
# Additional problem types
# Additional problem types
'edx_jsme'
,
# Molecular Structure
'edx_jsme'
,
# Molecular Structure
'openedx.core.djangoapps.content.course_structures'
,
)
)
...
...
common/lib/xmodule/xmodule/modulestore/django.py
View file @
24fcab7f
...
@@ -11,6 +11,7 @@ from django.conf import settings
...
@@ -11,6 +11,7 @@ from django.conf import settings
if
not
settings
.
configured
:
if
not
settings
.
configured
:
settings
.
configure
()
settings
.
configure
()
from
django.core.cache
import
get_cache
,
InvalidCacheBackendError
from
django.core.cache
import
get_cache
,
InvalidCacheBackendError
import
django.dispatch
import
django.utils
import
django.utils
import
re
import
re
...
@@ -39,6 +40,20 @@ except ImportError:
...
@@ -39,6 +40,20 @@ except ImportError:
ASSET_IGNORE_REGEX
=
getattr
(
settings
,
"ASSET_IGNORE_REGEX"
,
r"(^\._.*$)|(^\.DS_Store$)|(^.*~$)"
)
ASSET_IGNORE_REGEX
=
getattr
(
settings
,
"ASSET_IGNORE_REGEX"
,
r"(^\._.*$)|(^\.DS_Store$)|(^.*~$)"
)
class
SignalHandler
(
object
):
course_published
=
django
.
dispatch
.
Signal
(
providing_args
=
[
"course_key"
,
"version"
])
_mapping
=
{
"course_published"
:
course_published
}
def
__init__
(
self
,
modulestore_class
):
self
.
modulestore_class
=
modulestore_class
def
send
(
self
,
signal_name
,
**
kwargs
):
signal
=
self
.
_mapping
[
signal_name
]
signal
.
send_robust
(
sender
=
self
.
modulestore_class
,
**
kwargs
)
def
load_function
(
path
):
def
load_function
(
path
):
"""
"""
...
@@ -59,6 +74,7 @@ def create_modulestore_instance(
...
@@ -59,6 +74,7 @@ def create_modulestore_instance(
i18n_service
=
None
,
i18n_service
=
None
,
fs_service
=
None
,
fs_service
=
None
,
user_service
=
None
,
user_service
=
None
,
signal_handler
=
None
,
):
):
"""
"""
This will return a new instance of a modulestore given an engine and options
This will return a new instance of a modulestore given an engine and options
...
@@ -104,6 +120,7 @@ def create_modulestore_instance(
...
@@ -104,6 +120,7 @@ def create_modulestore_instance(
i18n_service
=
i18n_service
or
ModuleI18nService
(),
i18n_service
=
i18n_service
or
ModuleI18nService
(),
fs_service
=
fs_service
or
xblock
.
reference
.
plugins
.
FSService
(),
fs_service
=
fs_service
or
xblock
.
reference
.
plugins
.
FSService
(),
user_service
=
user_service
or
xb_user_service
,
user_service
=
user_service
or
xb_user_service
,
signal_handler
=
signal_handler
or
SignalHandler
(
class_
),
**
_options
**
_options
)
)
...
...
common/lib/xmodule/xmodule/modulestore/mixed.py
View file @
24fcab7f
...
@@ -108,6 +108,7 @@ class MixedModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase):
...
@@ -108,6 +108,7 @@ class MixedModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase):
fs_service
=
None
,
fs_service
=
None
,
user_service
=
None
,
user_service
=
None
,
create_modulestore_instance
=
None
,
create_modulestore_instance
=
None
,
signal_handler
=
None
,
**
kwargs
**
kwargs
):
):
"""
"""
...
@@ -142,6 +143,7 @@ class MixedModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase):
...
@@ -142,6 +143,7 @@ class MixedModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase):
for
course_key
,
store_key
in
self
.
mappings
.
iteritems
()
for
course_key
,
store_key
in
self
.
mappings
.
iteritems
()
if
store_key
==
key
if
store_key
==
key
]
]
store
=
create_modulestore_instance
(
store
=
create_modulestore_instance
(
store_settings
[
'ENGINE'
],
store_settings
[
'ENGINE'
],
self
.
contentstore
,
self
.
contentstore
,
...
@@ -150,6 +152,7 @@ class MixedModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase):
...
@@ -150,6 +152,7 @@ class MixedModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase):
i18n_service
=
i18n_service
,
i18n_service
=
i18n_service
,
fs_service
=
fs_service
,
fs_service
=
fs_service
,
user_service
=
user_service
,
user_service
=
user_service
,
signal_handler
=
signal_handler
,
)
)
# replace all named pointers to the store into actual pointers
# replace all named pointers to the store into actual pointers
for
course_key
,
store_name
in
self
.
mappings
.
iteritems
():
for
course_key
,
store_name
in
self
.
mappings
.
iteritems
():
...
...
common/lib/xmodule/xmodule/modulestore/mongo/base.py
View file @
24fcab7f
...
@@ -504,6 +504,7 @@ class MongoModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase, Mongo
...
@@ -504,6 +504,7 @@ class MongoModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase, Mongo
i18n_service
=
None
,
i18n_service
=
None
,
fs_service
=
None
,
fs_service
=
None
,
user_service
=
None
,
user_service
=
None
,
signal_handler
=
None
,
retry_wait_time
=
0.1
,
retry_wait_time
=
0.1
,
**
kwargs
):
**
kwargs
):
"""
"""
...
@@ -560,6 +561,7 @@ class MongoModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase, Mongo
...
@@ -560,6 +561,7 @@ class MongoModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase, Mongo
self
.
user_service
=
user_service
self
.
user_service
=
user_service
self
.
_course_run_cache
=
{}
self
.
_course_run_cache
=
{}
self
.
signal_handler
=
signal_handler
def
close_connections
(
self
):
def
close_connections
(
self
):
"""
"""
...
...
common/lib/xmodule/xmodule/modulestore/split_mongo/split.py
View file @
24fcab7f
...
@@ -608,7 +608,7 @@ class SplitMongoModuleStore(SplitBulkWriteMixin, ModuleStoreWriteBase):
...
@@ -608,7 +608,7 @@ class SplitMongoModuleStore(SplitBulkWriteMixin, ModuleStoreWriteBase):
default_class
=
None
,
default_class
=
None
,
error_tracker
=
null_error_tracker
,
error_tracker
=
null_error_tracker
,
i18n_service
=
None
,
fs_service
=
None
,
user_service
=
None
,
i18n_service
=
None
,
fs_service
=
None
,
user_service
=
None
,
services
=
None
,
**
kwargs
):
services
=
None
,
signal_handler
=
None
,
**
kwargs
):
"""
"""
:param doc_store_config: must have a host, db, and collection entries. Other common entries: port, tz_aware.
:param doc_store_config: must have a host, db, and collection entries. Other common entries: port, tz_aware.
"""
"""
...
@@ -637,6 +637,8 @@ class SplitMongoModuleStore(SplitBulkWriteMixin, ModuleStoreWriteBase):
...
@@ -637,6 +637,8 @@ class SplitMongoModuleStore(SplitBulkWriteMixin, ModuleStoreWriteBase):
if
user_service
is
not
None
:
if
user_service
is
not
None
:
self
.
services
[
"user"
]
=
user_service
self
.
services
[
"user"
]
=
user_service
self
.
signal_handler
=
signal_handler
def
close_connections
(
self
):
def
close_connections
(
self
):
"""
"""
Closes any open connections to the underlying databases
Closes any open connections to the underlying databases
...
...
common/lib/xmodule/xmodule/modulestore/split_mongo/split_draft.py
View file @
24fcab7f
...
@@ -354,7 +354,11 @@ class DraftVersioningModuleStore(SplitMongoModuleStore, ModuleStoreDraftAndPubli
...
@@ -354,7 +354,11 @@ class DraftVersioningModuleStore(SplitMongoModuleStore, ModuleStoreDraftAndPubli
# Now it's been published, add the object to the courseware search index so that it appears in search results
# Now it's been published, add the object to the courseware search index so that it appears in search results
CoursewareSearchIndexer
.
add_to_search_index
(
self
,
location
)
CoursewareSearchIndexer
.
add_to_search_index
(
self
,
location
)
return
self
.
get_item
(
location
.
for_branch
(
ModuleStoreEnum
.
BranchName
.
published
),
**
kwargs
)
published_location
=
location
.
for_branch
(
ModuleStoreEnum
.
BranchName
.
published
)
if
self
.
signal_handler
:
self
.
signal_handler
.
send
(
"course_published"
,
course_key
=
published_location
.
course_key
)
return
self
.
get_item
(
published_location
,
**
kwargs
)
def
unpublish
(
self
,
location
,
user_id
,
**
kwargs
):
def
unpublish
(
self
,
location
,
user_id
,
**
kwargs
):
"""
"""
...
...
common/lib/xmodule/xmodule/modulestore/tests/utils.py
View file @
24fcab7f
...
@@ -34,7 +34,8 @@ def create_modulestore_instance(
...
@@ -34,7 +34,8 @@ def create_modulestore_instance(
options
,
options
,
i18n_service
=
None
,
i18n_service
=
None
,
fs_service
=
None
,
fs_service
=
None
,
user_service
=
None
user_service
=
None
,
signal_handler
=
None
,
):
):
"""
"""
This will return a new instance of a modulestore given an engine and options
This will return a new instance of a modulestore given an engine and options
...
...
common/lib/xmodule/xmodule/modulestore/xml.py
View file @
24fcab7f
...
@@ -294,7 +294,8 @@ class XMLModuleStore(ModuleStoreReadBase):
...
@@ -294,7 +294,8 @@ class XMLModuleStore(ModuleStoreReadBase):
"""
"""
def
__init__
(
def
__init__
(
self
,
data_dir
,
default_class
=
None
,
course_dirs
=
None
,
course_ids
=
None
,
self
,
data_dir
,
default_class
=
None
,
course_dirs
=
None
,
course_ids
=
None
,
load_error_modules
=
True
,
i18n_service
=
None
,
fs_service
=
None
,
user_service
=
None
,
**
kwargs
load_error_modules
=
True
,
i18n_service
=
None
,
fs_service
=
None
,
user_service
=
None
,
signal_handler
=
None
,
**
kwargs
):
):
"""
"""
Initialize an XMLModuleStore from data_dir
Initialize an XMLModuleStore from data_dir
...
...
lms/envs/common.py
View file @
24fcab7f
...
@@ -1620,6 +1620,8 @@ INSTALLED_APPS = (
...
@@ -1620,6 +1620,8 @@ INSTALLED_APPS = (
'survey'
,
'survey'
,
'lms.djangoapps.lms_xblock'
,
'lms.djangoapps.lms_xblock'
,
'openedx.core.djangoapps.content.course_structures'
,
)
)
######################### MARKETING SITE ###############################
######################### MARKETING SITE ###############################
...
...
openedx/core/djangoapps/content/__init__.py
0 → 100644
View file @
24fcab7f
openedx/core/djangoapps/content/course_structures/__init__.py
0 → 100644
View file @
24fcab7f
openedx/core/djangoapps/content/course_structures/admin.py
0 → 100644
View file @
24fcab7f
from
ratelimitbackend
import
admin
from
.models
import
CourseStructure
admin
.
site
.
register
(
CourseStructure
)
openedx/core/djangoapps/content/course_structures/migrations/0001_initial.py
0 → 100644
View file @
24fcab7f
# -*- coding: utf-8 -*-
import
datetime
from
south.db
import
db
from
south.v2
import
SchemaMigration
from
django.db
import
models
class
Migration
(
SchemaMigration
):
def
forwards
(
self
,
orm
):
# Adding model 'CourseStructure'
db
.
create_table
(
'course_structures_coursestructure'
,
(
(
'id'
,
self
.
gf
(
'django.db.models.fields.AutoField'
)(
primary_key
=
True
)),
(
'created'
,
self
.
gf
(
'model_utils.fields.AutoCreatedField'
)(
default
=
datetime
.
datetime
.
now
)),
(
'modified'
,
self
.
gf
(
'model_utils.fields.AutoLastModifiedField'
)(
default
=
datetime
.
datetime
.
now
)),
(
'course_id'
,
self
.
gf
(
'xmodule_django.models.CourseKeyField'
)(
max_length
=
255
,
db_index
=
True
)),
(
'version'
,
self
.
gf
(
'django.db.models.fields.CharField'
)(
max_length
=
255
)),
(
'structure_json'
,
self
.
gf
(
'django.db.models.fields.TextField'
)()),
))
db
.
send_create_signal
(
'course_structures'
,
[
'CourseStructure'
])
def
backwards
(
self
,
orm
):
# Deleting model 'CourseStructure'
db
.
delete_table
(
'course_structures_coursestructure'
)
models
=
{
'course_structures.coursestructure'
:
{
'Meta'
:
{
'object_name'
:
'CourseStructure'
},
'course_id'
:
(
'xmodule_django.models.CourseKeyField'
,
[],
{
'max_length'
:
'255'
,
'db_index'
:
'True'
}),
'created'
:
(
'model_utils.fields.AutoCreatedField'
,
[],
{
'default'
:
'datetime.datetime.now'
}),
'id'
:
(
'django.db.models.fields.AutoField'
,
[],
{
'primary_key'
:
'True'
}),
'modified'
:
(
'model_utils.fields.AutoLastModifiedField'
,
[],
{
'default'
:
'datetime.datetime.now'
}),
'structure_json'
:
(
'django.db.models.fields.TextField'
,
[],
{}),
'version'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'255'
})
}
}
complete_apps
=
[
'course_structures'
]
\ No newline at end of file
openedx/core/djangoapps/content/course_structures/migrations/__init__.py
0 → 100644
View file @
24fcab7f
openedx/core/djangoapps/content/course_structures/models.py
0 → 100644
View file @
24fcab7f
import
json
from
django.db
import
models
from
django.dispatch
import
receiver
from
celery.task
import
task
from
model_utils.models
import
TimeStampedModel
from
opaque_keys.edx.keys
import
CourseKey
from
xmodule.modulestore.django
import
modulestore
,
SignalHandler
from
xmodule_django.models
import
CourseKeyField
class
CourseStructure
(
TimeStampedModel
):
course_id
=
CourseKeyField
(
max_length
=
255
,
db_index
=
True
)
version
=
models
.
CharField
(
max_length
=
255
,
blank
=
True
,
default
=
""
)
# Right now the only thing we do with the structure doc is store it and
# send it on request. If we need to store a more complex data model later,
# we can do so and build a migration. The only problem with a normalized
# data model for this is that it will likely involve hundreds of rows, and
# we'd have to be careful about caching.
structure_json
=
models
.
TextField
()
# Index together:
# (course_id, version)
# (course_id, created)
def
course_structure
(
course_key
):
course
=
modulestore
()
.
get_course
(
course_key
,
depth
=
None
)
blocks_stack
=
[
course
]
blocks_dict
=
{}
while
blocks_stack
:
curr_block
=
blocks_stack
.
pop
()
children
=
curr_block
.
get_children
()
if
curr_block
.
has_children
else
[]
blocks_dict
[
unicode
(
curr_block
.
scope_ids
.
usage_id
)]
=
{
"usage_key"
:
unicode
(
curr_block
.
scope_ids
.
usage_id
),
"block_type"
:
curr_block
.
category
,
"display_name"
:
curr_block
.
display_name
,
"graded"
:
curr_block
.
graded
,
"format"
:
curr_block
.
format
,
"children"
:
[
unicode
(
ch
.
scope_ids
.
usage_id
)
for
ch
in
children
]
}
blocks_stack
.
extend
(
children
)
return
{
"root"
:
unicode
(
course
.
scope_ids
.
usage_id
),
"blocks"
:
blocks_dict
}
@receiver
(
SignalHandler
.
course_published
)
def
listen_for_course_publish
(
sender
,
course_key
,
**
kwargs
):
update_course_structure
(
course_key
)
@task
()
def
update_course_structure
(
course_key
):
structure
=
course_structure
(
course_key
)
CourseStructure
.
objects
.
create
(
course_id
=
unicode
(
course_key
),
structure_json
=
json
.
dumps
(
structure
),
version
=
""
,
)
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