Skip to content

Commit

Permalink
Initial implementation of the accordion XBlock
Browse files Browse the repository at this point in the history
  • Loading branch information
xitij2000 committed Jul 27, 2024
1 parent 2104226 commit c435fd8
Show file tree
Hide file tree
Showing 44 changed files with 91,313 additions and 129 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ jobs:
strategy:
matrix:
os: [ubuntu-20.04]
python-version: ['3.8']
toxenv: [quality, docs, django32, django40]
python-version: ['3.8', '3.11', '3.12']
toxenv: [quality, docs, django40]

steps:
- uses: actions/checkout@v3
Expand All @@ -37,7 +37,7 @@ jobs:
run: tox

- name: Run coverage
if: matrix.python-version == '3.8' && matrix.toxenv == 'django32'
if: matrix.python-version == '3.11' && matrix.toxenv == 'django40'
uses: codecov/codecov-action@v4
with:
token: ${{ secrets.CODECOV_TOKEN }}
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ FROM openedx/xblock-sdk
RUN mkdir -p /usr/local/src/xblock-accordion
VOLUME ["/usr/local/src/xblock-accordion"]
RUN apt-get update && apt-get install -y gettext
RUN echo "pip install -r /usr/local/src/xblock-accordion/requirements.txt" >> /usr/local/src/xblock-sdk/install_and_run_xblock.sh
RUN echo "pip install -r /usr/local/src/xblock-accordion/requirements/dev.txt" >> /usr/local/src/xblock-sdk/install_and_run_xblock.sh
RUN echo "pip install -e /usr/local/src/xblock-accordion" >> /usr/local/src/xblock-sdk/install_and_run_xblock.sh
RUN echo "cd /usr/local/src/xblock-accordion && make compile_translations && cd /usr/local/src/xblock-sdk" >> /usr/local/src/xblock-sdk/install_and_run_xblock.sh
RUN echo "exec python /usr/local/src/xblock-sdk/manage.py \"\$@\"" >> /usr/local/src/xblock-sdk/install_and_run_xblock.sh
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ dev.build:
docker build -t $(REPO_NAME)-dev $(CURDIR)

dev.run: dev.clean dev.build ## Clean, build and run test image
docker run -p 8000:8000 -v $(CURDIR):/usr/local/src/$(REPO_NAME) --name $(REPO_NAME)-dev $(REPO_NAME)-dev
docker run -p 8200:8000 -v $(CURDIR):/usr/local/src/$(REPO_NAME) --name $(REPO_NAME)-dev $(REPO_NAME)-dev

## Localization targets

Expand Down
2 changes: 1 addition & 1 deletion accordion/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@

from .accordion import AccordionXBlock

__version__ = '0.1.0'
__version__ = "0.1.0"
124 changes: 59 additions & 65 deletions accordion/accordion.py
Original file line number Diff line number Diff line change
@@ -1,107 +1,101 @@
"""TO-DO: Write a description of what this XBlock is."""
"""
An XBlock that allows authors to create an accordion component for students
with multiple panels containing rich content.
"""

import pkg_resources
from django.utils import translation
from importlib import resources
from web_fragments.fragment import Fragment
from xblock.core import XBlock
from xblock.fields import Integer, Scope
from xblockutils.resources import ResourceLoader
from xblock.fields import Scope, List, String, Dict


class AccordionXBlock(XBlock):
"""
TO-DO: document what your XBlock does.
Accordion XBlock
"""

# Fields are defined on the class. You can access them in your code as
# self.<fieldname>.

# TO-DO: delete count, and define your own fields.
count = Integer(
default=0, scope=Scope.user_state,
help="A simple counter, to show something happening",
display_name = String(default=translation.gettext_noop("Accordion"))
panels = List(help="Accordion entries", default=[], scope=Scope.content)
styling = Dict(help="Accordion styling", default=[], scope=Scope.content)
border_style = String(
help="Accordion border style", default="", scope=Scope.content
)

def resource_string(self, path):
"""Handy helper for getting resources from our kit."""
data = pkg_resources.resource_string(__name__, path)
return data.decode("utf8")
data = resources.files("accordion").joinpath(path).read_text("utf8")
return data

# TO-DO: change this view to display your data your own way.
def student_view(self, context=None):
"""
Create primary view of the AccordionXBlock, shown to students when viewing courses.
"""
if context:
pass # TO-DO: do something based on the context.
html = self.resource_string("static/html/accordion.html")
frag = Fragment(html.format(self=self))
frag.add_css(self.resource_string("static/css/accordion.css"))

# Add i18n js
statici18n_js_url = self._get_statici18n_js_url()
if statici18n_js_url:
frag.add_javascript_url(self.runtime.local_resource_url(self, statici18n_js_url))

frag.add_javascript(self.resource_string("static/js/src/accordion.js"))
frag.initialize_js('AccordionXBlock')
frag = Fragment()
frag.add_css(self.resource_string("public/style.css"))
frag.add_javascript(self.resource_string("static/student.js"))
frag.initialize_js(
"AccordionBlock",
{
"url": self.runtime.local_resource_url(self, "public/student-ui.js"),
"panels": self.panels,
"styling": self.styling,
},
)
return frag

# TO-DO: change this handler to perform your own actions. You may need more
# than one handler, or you may not need any handlers at all.
@XBlock.json_handler
def increment_count(self, data, suffix=''):
def studio_save(self, data, suffix=''):
panels = data.get('panels', None)
styling = data.get('styling', None)
if panels:
self.panels = panels
if styling:
self.styling = styling

def studio_view(self, context=None):
"""
Increments data. An example handler.
Create primary view of the AccordionXBlock, shown to students when viewing courses.
"""
if suffix:
pass # TO-DO: Use the suffix when storing data.
# Just to show data coming in...
assert data['hello'] == 'world'

self.count += 1
return {"count": self.count}
html = self.resource_string("static/html/accordion.html")
frag = Fragment(html)
frag.add_javascript(self.resource_string("static/studio.js"))
frag.add_css(self.resource_string("public/style.css"))
frag.initialize_js(
"AccordionEditor",
{
"url": self.runtime.local_resource_url(self, "public/studio-ui.js"),
"panels": self.panels,
"styling": self.styling,
},
)
return frag

# TO-DO: change this to create the scenarios you'd like to see in the
# workbench while developing your XBlock.
@staticmethod
def workbench_scenarios():
"""Create canned scenario for display in the workbench."""
return [
("AccordionXBlock",
"""<accordion/>
"""),
("Multiple AccordionXBlock",
"""<vertical_demo>
(
"AccordionXBlock",
"""<accordion/>
""",
),
(
"Multiple AccordionXBlock",
"""<vertical_demo>
<accordion/>
<accordion/>
<accordion/>
</vertical_demo>
"""),
""",
),
]

@staticmethod
def _get_statici18n_js_url():
"""
Return the Javascript translation file for the currently selected language, if any.
Defaults to English if available.
"""
locale_code = translation.get_language()
if locale_code is None:
return None
text_js = 'public/js/translations/{locale_code}/text.js'
lang_code = locale_code.split('-')[0]
for code in (locale_code, lang_code, 'en'):
loader = ResourceLoader(__name__)
if pkg_resources.resource_exists(
loader.module_name, text_js.format(locale_code=code)):
return text_js.format(locale_code=code)
return None

@staticmethod
def get_dummy():
"""
Generate initial i18n with dummy method.
"""
return translation.gettext_noop('Dummy')
return translation.gettext_noop("Dummy")
Loading

0 comments on commit c435fd8

Please sign in to comment.