├── .github └── workflows │ ├── ci.yml │ ├── commitlint.yml │ ├── pypi-publish.yml │ └── upgrade-python-requirements.yml ├── .gitignore ├── .tx └── config ├── LICENSE ├── MANIFEST.in ├── Makefile ├── README.md ├── doc_img ├── add_links.png ├── advanced_modules_list.png ├── advanced_settings.png ├── cancel_link.png ├── delete_link.png ├── img_and_label_poll.png ├── img_poll.png ├── img_poll_result.png ├── mixed_markdown.png ├── mixed_markdown_render.png ├── ordering_arrows.png ├── poll.png ├── poll_edit.png ├── poll_line_items.png ├── poll_mixed.png ├── poll_mixed_result.png ├── poll_result.png ├── private_results.png ├── private_results_submission.png ├── save_button.png ├── survey.png ├── survey_line_items.png ├── survey_mixed.png ├── survey_mixed_result.png └── survey_result.png ├── locale ├── manage.py ├── package-lock.json ├── package.json ├── poll ├── __init__.py ├── poll.py ├── public │ ├── css │ │ ├── poll.css │ │ ├── poll_edit.css │ │ └── themes │ │ │ └── lms.css │ ├── handlebars │ │ ├── poll_results.handlebars │ │ ├── poll_studio.handlebars │ │ └── survey_results.handlebars │ ├── html │ │ ├── poll.html │ │ ├── poll_edit.html │ │ └── survey.html │ └── js │ │ ├── poll.js │ │ ├── poll_common.js │ │ ├── poll_edit.js │ │ ├── translations │ │ ├── ar │ │ │ └── textjs.js │ │ ├── de_DE │ │ │ └── textjs.js │ │ ├── en │ │ │ └── textjs.js │ │ ├── eo │ │ │ └── textjs.js │ │ ├── es_419 │ │ │ └── textjs.js │ │ ├── fr │ │ │ └── textjs.js │ │ ├── fr_CA │ │ │ └── textjs.js │ │ ├── he │ │ │ └── textjs.js │ │ ├── hi │ │ │ └── textjs.js │ │ ├── it_IT │ │ │ └── textjs.js │ │ ├── ja_JP │ │ │ └── textjs.js │ │ ├── ko_KR │ │ │ └── textjs.js │ │ ├── pl │ │ │ └── textjs.js │ │ ├── pt_BR │ │ │ └── textjs.js │ │ ├── pt_PT │ │ │ └── textjs.js │ │ ├── ru │ │ │ └── textjs.js │ │ └── zh_CN │ │ │ └── textjs.js │ │ └── vendor │ │ └── handlebars.js ├── settings.py ├── tasks.py ├── translations │ ├── ar │ │ └── LC_MESSAGES │ │ │ ├── text.mo │ │ │ └── text.po │ ├── config.yaml │ ├── de_DE │ │ └── LC_MESSAGES │ │ │ ├── text.mo │ │ │ ├── text.po │ │ │ └── textjs.po │ ├── en │ │ └── LC_MESSAGES │ │ │ ├── text.mo │ │ │ ├── text.po │ │ │ └── textjs.po │ ├── eo │ │ └── LC_MESSAGES │ │ │ ├── text.mo │ │ │ ├── text.po │ │ │ └── textjs.po │ ├── es_419 │ │ └── LC_MESSAGES │ │ │ ├── text.mo │ │ │ ├── text.po │ │ │ └── textjs.po │ ├── fr │ │ └── LC_MESSAGES │ │ │ ├── text.mo │ │ │ ├── text.po │ │ │ └── textjs.po │ ├── fr_CA │ │ └── LC_MESSAGES │ │ │ ├── text.mo │ │ │ ├── text.po │ │ │ └── textjs.po │ ├── he │ │ └── LC_MESSAGES │ │ │ ├── text.mo │ │ │ └── text.po │ ├── it_IT │ │ └── LC_MESSAGES │ │ │ ├── text.mo │ │ │ ├── text.po │ │ │ └── textjs.po │ ├── ja_JP │ │ └── LC_MESSAGES │ │ │ ├── text.mo │ │ │ ├── text.po │ │ │ └── textjs.po │ ├── pt_BR │ │ └── LC_MESSAGES │ │ │ ├── text.mo │ │ │ ├── text.po │ │ │ └── textjs.po │ └── pt_PT │ │ └── LC_MESSAGES │ │ ├── text.mo │ │ ├── text.po │ │ └── textjs.po └── utils.py ├── pylintrc ├── requirements ├── base.in ├── base.txt ├── ci.in ├── ci.txt ├── constraints.txt ├── dev.in ├── dev.txt ├── pip-tools.in ├── pip-tools.txt ├── pip.in ├── pip.txt ├── private.readme ├── quality.in ├── quality.txt ├── test.in └── test.txt ├── run_tests.py ├── setup.py ├── tests.disabled ├── README.md └── integration │ ├── __init__.py │ ├── base_test.py │ ├── markdown_scenarios.py │ ├── studio_scenarios.py │ ├── test_defaults.py │ ├── test_functions.py │ ├── test_layout.py │ ├── test_markdown.py │ ├── test_max_submissions.py │ ├── test_private_results.py │ ├── test_studio.py │ ├── test_submit_button.py │ └── xml │ ├── poll_all_pictures.xml │ ├── poll_defaults.xml │ ├── poll_functions.xml │ ├── poll_markdown.xml │ ├── poll_max_submissions.xml │ ├── poll_max_submissions_infinite.xml │ ├── poll_no_pictures.xml │ ├── poll_one_picture.xml │ ├── poll_private.xml │ ├── poll_size_check.xml │ ├── poll_size_check_image.xml │ ├── poll_studio.xml │ ├── poll_submit_button.xml │ ├── survey_defaults.xml │ ├── survey_functions.xml │ ├── survey_markdown.xml │ ├── survey_max_submissions.xml │ ├── survey_max_submissions_infinite.xml │ ├── survey_multiple.xml │ ├── survey_private.xml │ └── survey_studio.xml ├── tests ├── __init__.py ├── unit │ ├── __init__.py │ └── test_xblock_poll.py └── utils.py └── tox.ini /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: Python CI 2 | on: 3 | pull_request: {} 4 | workflow_dispatch: {} 5 | push: 6 | branches: [master] 7 | 8 | concurrency: 9 | group: "${{ github.workflow }}-${{ github.ref }}" 10 | cancel-in-progress: true 11 | 12 | jobs: 13 | 14 | run_tests: 15 | name: tests 16 | runs-on: ${{ matrix.os }} 17 | strategy: 18 | matrix: 19 | os: [ubuntu-latest] 20 | python-version: ['3.11', '3.12'] 21 | toxenv: [quality, django42, django52, package] 22 | 23 | steps: 24 | - uses: actions/checkout@v4 25 | - name: setup python 26 | uses: actions/setup-python@v5 27 | with: 28 | python-version: ${{ matrix.python-version }} 29 | 30 | - name: Install pip 31 | run: make piptools 32 | 33 | - name: Install Dependencies 34 | run: pip-sync requirements/ci.txt 35 | 36 | - name: Run Tests 37 | env: 38 | TOXENV: ${{ matrix.toxenv }} 39 | run: tox 40 | -------------------------------------------------------------------------------- /.github/workflows/commitlint.yml: -------------------------------------------------------------------------------- 1 | # Run commitlint on the commit messages in a pull request. 2 | 3 | name: Lint Commit Messages 4 | 5 | on: 6 | - pull_request 7 | 8 | jobs: 9 | commitlint: 10 | uses: openedx/.github/.github/workflows/commitlint.yml@master 11 | -------------------------------------------------------------------------------- /.github/workflows/pypi-publish.yml: -------------------------------------------------------------------------------- 1 | name: Publish package to PyPi 2 | 3 | on: 4 | release: 5 | types: [published] 6 | 7 | jobs: 8 | 9 | push: 10 | runs-on: ubuntu-latest 11 | 12 | steps: 13 | - name: Checkout 14 | uses: actions/checkout@v4 15 | 16 | - name: setup python 17 | uses: actions/setup-python@v5 18 | with: 19 | python-version: 3.11 20 | 21 | - name: Install pip 22 | run: pip install -r requirements/pip.txt 23 | 24 | - name: Build package 25 | run: python setup.py sdist bdist_wheel 26 | 27 | - name: Publish to PyPi 28 | uses: pypa/gh-action-pypi-publish@release/v1 29 | with: 30 | user: __token__ 31 | password: ${{ secrets.PYPI_UPLOAD_TOKEN }} 32 | -------------------------------------------------------------------------------- /.github/workflows/upgrade-python-requirements.yml: -------------------------------------------------------------------------------- 1 | name: Upgrade Python Requirements 2 | 3 | on: 4 | schedule: 5 | - cron: "0 0 * * 1" 6 | workflow_dispatch: 7 | inputs: 8 | branch: 9 | description: Target branch against which to create requirements PR 10 | required: true 11 | default: master 12 | 13 | jobs: 14 | call-upgrade-python-requirements-workflow: 15 | uses: openedx/.github/.github/workflows/upgrade-python-requirements.yml@master 16 | # Do not run on forks 17 | if: github.repository_owner == 'open-craft' 18 | with: 19 | branch: ${{ github.event.inputs.branch || 'master' }} 20 | # optional parameters below; fill in if you'd like github or email notifications 21 | # user_reviewers: "" 22 | # team_reviewers: "" 23 | # email_address: "" 24 | send_success_notification: false 25 | secrets: 26 | requirements_bot_github_token: ${{ secrets.REQUIREMENTS_BOT_GITHUB_TOKEN }} 27 | requirements_bot_github_email: ${{ secrets.REQUIREMENTS_BOT_GITHUB_EMAIL }} 28 | edx_smtp_username: ${{ secrets.EDX_SMTP_USERNAME }} 29 | edx_smtp_password: ${{ secrets.EDX_SMTP_PASSWORD }} 30 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by https://www.gitignore.io 2 | 3 | tests.integration.*.png 4 | 5 | ### Python ### 6 | # Byte-compiled / optimized / DLL files 7 | __pycache__/ 8 | *.py[cod] 9 | 10 | # C extensions 11 | *.so 12 | 13 | # Firefox and Geckodriver for selenium integration tests 14 | .firefox 15 | .geckodriver 16 | 17 | # NodeJS 18 | node_modules 19 | yarn-error.log 20 | npm-debug.log 21 | 22 | # Distribution / packaging 23 | .Python 24 | env/ 25 | build/ 26 | develop-eggs/ 27 | dist/ 28 | downloads/ 29 | eggs/ 30 | lib/ 31 | lib64/ 32 | parts/ 33 | sdist/ 34 | var/ 35 | *.egg-info/ 36 | .installed.cfg 37 | *.egg 38 | 39 | # PyInstaller 40 | # Usually these files are written by a python script from a template 41 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 42 | *.manifest 43 | *.spec 44 | 45 | # Installer logs 46 | pip-log.txt 47 | pip-delete-this-directory.txt 48 | 49 | # Unit test / coverage reports 50 | htmlcov/ 51 | .tox/ 52 | .coverage 53 | .cache 54 | nosetests.xml 55 | coverage.xml 56 | tests.integration.* 57 | .noseids 58 | 59 | # Translations 60 | #*.mo 61 | *.pot 62 | 63 | # Django stuff: 64 | *.log 65 | 66 | # Sphinx documentation 67 | docs/_build/ 68 | 69 | # PyBuilder 70 | target/ 71 | 72 | 73 | ### Intellij ### 74 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm 75 | 76 | /*.iml 77 | 78 | ## Directory-based project format: 79 | .idea/ 80 | # if you remove the above rule, at least ignore the following: 81 | 82 | # User-specific stuff: 83 | # .idea/workspace.xml 84 | # .idea/tasks.xml 85 | # .idea/dictionaries 86 | 87 | # Sensitive or high-churn files: 88 | # .idea/dataSources.ids 89 | # .idea/dataSources.xml 90 | # .idea/sqlDataSources.xml 91 | # .idea/dynamic.xml 92 | # .idea/uiDesigner.xml 93 | 94 | # Gradle: 95 | # .idea/gradle.xml 96 | # .idea/libraries 97 | 98 | # Mongo Explorer plugin: 99 | # .idea/mongoSettings.xml 100 | 101 | ## File-based project format: 102 | *.ipr 103 | *.iws 104 | 105 | ## Plugin-specific files: 106 | 107 | # IntelliJ 108 | out/ 109 | 110 | # mpeltonen/sbt-idea plugin 111 | .idea_modules/ 112 | 113 | # JIRA plugin 114 | atlassian-ide-plugin.xml 115 | 116 | # Crashlytics plugin (for Android Studio and IntelliJ) 117 | com_crashlytics_export_strings.xml 118 | 119 | 120 | ### vim ### 121 | [._]*.s[a-w][a-z] 122 | [._]s[a-w][a-z] 123 | *.un~ 124 | Session.vim 125 | .netrwhist 126 | *~ 127 | 128 | 129 | ### Linux ### 130 | *~ 131 | 132 | # KDE directory preferences 133 | .directory 134 | 135 | # Gecko logs 136 | geckodriver.log 137 | 138 | # Misc 139 | .DS_Store 140 | -------------------------------------------------------------------------------- /.tx/config: -------------------------------------------------------------------------------- 1 | [main] 2 | host = https://www.transifex.com 3 | 4 | [xblocks.xblock-poll] 5 | source_file = poll/translations/en/LC_MESSAGES/text.po 6 | file_filter = poll/translations//LC_MESSAGES/text.po 7 | source_lang = en 8 | type = PO 9 | 10 | [xblocks.xblock-poll-js] 11 | source_file = poll/translations/en/LC_MESSAGES/textjs.po 12 | file_filter = poll/translations//LC_MESSAGES/textjs.po 13 | source_lang = en 14 | type = PO 15 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include LICENSE 2 | include README.md 3 | include requirements/base.in 4 | include requirements/constraints.txt 5 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: dummy_translations extract_translations help pull_translations push_translations 2 | 3 | .DEFAULT_GOAL := help 4 | 5 | FIREFOX_VERSION := "67.0" 6 | FIREFOX_LINUX_ARCH := $(shell uname -m) 7 | 8 | help: ## display this help message 9 | @echo "Please use \`make ' where is one of" 10 | @perl -nle'print $& if m{^[a-zA-Z_-]+:.*?## .*$$}' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m %-25s\033[0m %s\n", $$1, $$2}' 11 | 12 | clean: ## remove generated byte code, coverage reports, and build artifacts 13 | find . -name '__pycache__' -exec rm -rf {} + 14 | find . -name '*.pyc' -exec rm -f {} + 15 | find . -name '*.pyo' -exec rm -f {} + 16 | find . -name '*~' -exec rm -f {} + 17 | 18 | find poll/translations -name djangojs.mo -exec rm -f {} + 19 | find poll/translations -name djangojs.po -exec rm -f {} + 20 | find poll/translations -name textjs.mo -exec rm -f {} + 21 | 22 | coverage erase 23 | rm -fr build/ 24 | rm -fr dist/ 25 | rm -fr *.egg-info 26 | 27 | # Define PIP_COMPILE_OPTS=-v to get more information during make upgrade. 28 | PIP_COMPILE = pip-compile --upgrade $(PIP_COMPILE_OPTS) 29 | 30 | upgrade: export CUSTOM_COMPILE_COMMAND=make upgrade 31 | upgrade: ## update the requirements/*.txt files with the latest packages satisfying requirements/*.in 32 | pip install -qr requirements/pip-tools.txt 33 | # Make sure to compile files after any other files they include! 34 | $(PIP_COMPILE) --allow-unsafe -o requirements/pip.txt requirements/pip.in 35 | $(PIP_COMPILE) -o requirements/pip-tools.txt requirements/pip-tools.in 36 | pip install -qr requirements/pip.txt 37 | pip install -qr requirements/pip-tools.txt 38 | $(PIP_COMPILE) -o requirements/base.txt requirements/base.in 39 | $(PIP_COMPILE) -o requirements/test.txt requirements/test.in 40 | $(PIP_COMPILE) -o requirements/quality.txt requirements/quality.in 41 | $(PIP_COMPILE) -o requirements/ci.txt requirements/ci.in 42 | $(PIP_COMPILE) -o requirements/dev.txt requirements/dev.in 43 | sed -i '/^[dD]jango==/d' requirements/test.txt 44 | 45 | quality: ## check coding style with pycodestyle and pylint 46 | tox -e quality 47 | 48 | node_requirements: ## Install requirements for handlebar templates i18n extraction 49 | npm install 50 | 51 | piptools: ## install pinned version of pip-compile and pip-sync 52 | pip install -r requirements/pip.txt 53 | pip install -r requirements/pip-tools.txt 54 | 55 | python_requirements: install_linux_dev_firefox piptools ## install development environment requirements 56 | pip-sync requirements/dev.txt requirements/private.* 57 | 58 | requirements: node_requirements python_requirements ## install development environment requirements 59 | @echo "Finished installing requirements." 60 | 61 | install_linux_dev_firefox: ## Downloads custom version of firefox for Selenium in Linux 62 | @echo "This works only on Linux. For MacOS please check the README file" 63 | 64 | rm -rf .firefox .geckodriver 65 | mkdir .firefox .geckodriver 66 | 67 | curl http://ftp.mozilla.org/pub/firefox/releases/$(FIREFOX_VERSION)/linux-$(FIREFOX_LINUX_ARCH)/en-US/firefox-$(FIREFOX_VERSION).tar.bz2 \ 68 | --output .firefox/firefox.tar.bz2 69 | 70 | cd .firefox && tar -xvjf firefox.tar.bz2 71 | cd .geckodriver && wget https://github.com/mozilla/geckodriver/releases/download/v0.26.0/geckodriver-v0.26.0-linux64.tar.gz 72 | cd .geckodriver && tar -xzf geckodriver-v0.26.0-linux64.tar.gz 73 | 74 | linux_dev_test: ## Run tests in development environment to use custom firefox 75 | mkdir -p var 76 | PATH=.firefox/firefox/:.geckodriver/:$(PATH) xvfb-run python run_tests.py 77 | 78 | test: ## run tests in the current virtualenv 79 | mkdir -p var 80 | DJANGO_SETTINGS_MODULE=workbench.settings pytest 81 | 82 | selfcheck: ## check that the Makefile is well-formed 83 | @echo "The Makefile is well-formed." 84 | 85 | ## Localization targets 86 | 87 | extract_translations: ## extract strings to be translated, outputting .po files 88 | rm -rf docs/_build 89 | 90 | # Extract Python and Django template strings 91 | mkdir -p locale/en/LC_MESSAGES/ 92 | rm -f locale/en/LC_MESSAGES/{django,text}.po 93 | python manage.py makemessages -l en -v1 -d django 94 | mv locale/en/LC_MESSAGES/django.po locale/en/LC_MESSAGES/text.po 95 | 96 | @# Note: Intentionally ignoring JS translations in favor of Handlebars 97 | @# Keep the line below commented, there is one JavaScript file that has only one 98 | @# i18n string is js/poll_edit.js:259 which is (`Saving`) 99 | @# already available by other edX platform resources. 100 | @# django-admin makemessages -l en -v1 -d djangojs -e js 101 | 102 | # Extract Handlebars i18n strings 103 | > locale/en/LC_MESSAGES/textjs.po # Ensure it's empty 104 | # The sort to avoid bash arbitrary file order 105 | ls poll/public/handlebars/*.handlebars \ 106 | | xargs node node_modules/.bin/xgettext-template --from-code utf8 \ 107 | --language Handlebars \ 108 | --force-po \ 109 | --output locale/en/LC_MESSAGES/textjs.po 110 | 111 | compile_translations: ## compile translation files, outputting .mo files for each supported language 112 | i18n_tool generate 113 | python manage.py compilejsi18n 114 | make clean 115 | 116 | detect_changed_source_translations: ## Determines if the source translation files are up-to-date, otherwise exit with a non-zero code. 117 | i18n_tool changed 118 | 119 | pull_translations: ## pull translations from Transifex 120 | i18n_tool transifex pull 121 | make compile_translations 122 | 123 | push_translations: extract_translations ## push source translation files (.po) to Transifex 124 | tx push -s 125 | 126 | dummy_translations: ## generate dummy translation (.po) files 127 | i18n_tool dummy 128 | 129 | build_dummy_translations: extract_translations dummy_translations compile_translations ## generate and compile dummy translation files 130 | 131 | validate_translations: build_dummy_translations detect_changed_source_translations ## validate translations 132 | -------------------------------------------------------------------------------- /doc_img/add_links.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-craft/xblock-poll/aef56bd0b94a4a3a0c89f8edd442f7cc0132a760/doc_img/add_links.png -------------------------------------------------------------------------------- /doc_img/advanced_modules_list.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-craft/xblock-poll/aef56bd0b94a4a3a0c89f8edd442f7cc0132a760/doc_img/advanced_modules_list.png -------------------------------------------------------------------------------- /doc_img/advanced_settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-craft/xblock-poll/aef56bd0b94a4a3a0c89f8edd442f7cc0132a760/doc_img/advanced_settings.png -------------------------------------------------------------------------------- /doc_img/cancel_link.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-craft/xblock-poll/aef56bd0b94a4a3a0c89f8edd442f7cc0132a760/doc_img/cancel_link.png -------------------------------------------------------------------------------- /doc_img/delete_link.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-craft/xblock-poll/aef56bd0b94a4a3a0c89f8edd442f7cc0132a760/doc_img/delete_link.png -------------------------------------------------------------------------------- /doc_img/img_and_label_poll.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-craft/xblock-poll/aef56bd0b94a4a3a0c89f8edd442f7cc0132a760/doc_img/img_and_label_poll.png -------------------------------------------------------------------------------- /doc_img/img_poll.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-craft/xblock-poll/aef56bd0b94a4a3a0c89f8edd442f7cc0132a760/doc_img/img_poll.png -------------------------------------------------------------------------------- /doc_img/img_poll_result.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-craft/xblock-poll/aef56bd0b94a4a3a0c89f8edd442f7cc0132a760/doc_img/img_poll_result.png -------------------------------------------------------------------------------- /doc_img/mixed_markdown.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-craft/xblock-poll/aef56bd0b94a4a3a0c89f8edd442f7cc0132a760/doc_img/mixed_markdown.png -------------------------------------------------------------------------------- /doc_img/mixed_markdown_render.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-craft/xblock-poll/aef56bd0b94a4a3a0c89f8edd442f7cc0132a760/doc_img/mixed_markdown_render.png -------------------------------------------------------------------------------- /doc_img/ordering_arrows.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-craft/xblock-poll/aef56bd0b94a4a3a0c89f8edd442f7cc0132a760/doc_img/ordering_arrows.png -------------------------------------------------------------------------------- /doc_img/poll.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-craft/xblock-poll/aef56bd0b94a4a3a0c89f8edd442f7cc0132a760/doc_img/poll.png -------------------------------------------------------------------------------- /doc_img/poll_edit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-craft/xblock-poll/aef56bd0b94a4a3a0c89f8edd442f7cc0132a760/doc_img/poll_edit.png -------------------------------------------------------------------------------- /doc_img/poll_line_items.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-craft/xblock-poll/aef56bd0b94a4a3a0c89f8edd442f7cc0132a760/doc_img/poll_line_items.png -------------------------------------------------------------------------------- /doc_img/poll_mixed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-craft/xblock-poll/aef56bd0b94a4a3a0c89f8edd442f7cc0132a760/doc_img/poll_mixed.png -------------------------------------------------------------------------------- /doc_img/poll_mixed_result.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-craft/xblock-poll/aef56bd0b94a4a3a0c89f8edd442f7cc0132a760/doc_img/poll_mixed_result.png -------------------------------------------------------------------------------- /doc_img/poll_result.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-craft/xblock-poll/aef56bd0b94a4a3a0c89f8edd442f7cc0132a760/doc_img/poll_result.png -------------------------------------------------------------------------------- /doc_img/private_results.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-craft/xblock-poll/aef56bd0b94a4a3a0c89f8edd442f7cc0132a760/doc_img/private_results.png -------------------------------------------------------------------------------- /doc_img/private_results_submission.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-craft/xblock-poll/aef56bd0b94a4a3a0c89f8edd442f7cc0132a760/doc_img/private_results_submission.png -------------------------------------------------------------------------------- /doc_img/save_button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-craft/xblock-poll/aef56bd0b94a4a3a0c89f8edd442f7cc0132a760/doc_img/save_button.png -------------------------------------------------------------------------------- /doc_img/survey.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-craft/xblock-poll/aef56bd0b94a4a3a0c89f8edd442f7cc0132a760/doc_img/survey.png -------------------------------------------------------------------------------- /doc_img/survey_line_items.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-craft/xblock-poll/aef56bd0b94a4a3a0c89f8edd442f7cc0132a760/doc_img/survey_line_items.png -------------------------------------------------------------------------------- /doc_img/survey_mixed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-craft/xblock-poll/aef56bd0b94a4a3a0c89f8edd442f7cc0132a760/doc_img/survey_mixed.png -------------------------------------------------------------------------------- /doc_img/survey_mixed_result.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-craft/xblock-poll/aef56bd0b94a4a3a0c89f8edd442f7cc0132a760/doc_img/survey_mixed_result.png -------------------------------------------------------------------------------- /doc_img/survey_result.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-craft/xblock-poll/aef56bd0b94a4a3a0c89f8edd442f7cc0132a760/doc_img/survey_result.png -------------------------------------------------------------------------------- /locale: -------------------------------------------------------------------------------- 1 | poll/translations -------------------------------------------------------------------------------- /manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | from __future__ import absolute_import 3 | import os 4 | import sys 5 | 6 | if __name__ == "__main__": 7 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "poll.settings") 8 | 9 | from django.core.management import execute_from_command_line 10 | 11 | execute_from_command_line(sys.argv) 12 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "xgettext-template": "^6.0.0" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /poll/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Copyright (C) 2015 McKinsey Academy 4 | # 5 | # Authors: 6 | # Jonathan Piacenti 7 | # 8 | # This software's license gives you freedom; you can copy, convey, 9 | # propagate, redistribute and/or modify this program under the terms of 10 | # the GNU Affero General Public License (AGPL) as published by the Free 11 | # Software Foundation (FSF), either version 3 of the License, or (at your 12 | # option) any later version of the AGPL published by the FSF. 13 | # 14 | # This program is distributed in the hope that it will be useful, but 15 | # WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero 17 | # General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU Affero General Public License 20 | # along with this program in a file in the toplevel directory called 21 | # "AGPLv3". If not, see . 22 | # 23 | 24 | from .poll import PollBlock, SurveyBlock 25 | 26 | __version__ = "1.15.1" 27 | -------------------------------------------------------------------------------- /poll/public/css/poll_edit.css: -------------------------------------------------------------------------------- 1 | /* CSS for PollBlock Studio Menu View */ 2 | 3 | .poll-delete-answer { 4 | clear: right; 5 | float: right; 6 | margin-top: 1em; 7 | opacity: 0.5; 8 | } 9 | .poll-delete-answer:hover { 10 | opacity: 1; 11 | } 12 | #poll-question-editor-container, #poll-feedback-editor-container{ 13 | width: 100%; 14 | text-align: center; 15 | } 16 | #poll-question-editor, #poll-feedback-editor{ 17 | width: 98%; 18 | height: 7em; 19 | text-align: left; 20 | color: #4C4C4C; 21 | margin-top: 0.5em; 22 | margin-bottom: 0.5em; 23 | box-shadow: 0 0 9px #555 inset; 24 | border: 1px solid #B2B2B2; 25 | border-radius: 3px; 26 | padding: 10px; 27 | } 28 | 29 | .poll-move-up { 30 | display: block; 31 | opacity: .5; 32 | } 33 | 34 | .poll-move-down { 35 | display: block; 36 | opacity: .5; 37 | } 38 | 39 | .poll-move-down:hover, .poll-move-up:hover { 40 | opacity: 1; 41 | transition: opacity .4s; 42 | cursor: pointer 43 | } 44 | 45 | .poll-move { 46 | float: right; 47 | } 48 | 49 | #poll-error-container { 50 | background-color: #f8d7da; 51 | border: 1px solid #f5c6cb; 52 | color: #721c24; 53 | padding: 10px; 54 | margin: 10px 0; 55 | border-radius: 4px; 56 | font-weight: 500; 57 | display: none; 58 | cursor: pointer; 59 | } 60 | 61 | #poll-error-container:hover { 62 | background-color: #f5c2c7; 63 | transition: background-color 0.3s ease; 64 | } 65 | 66 | #poll-error-container:before { 67 | content: "⚠️ "; 68 | } 69 | 70 | #poll-error-message { 71 | display: inline-block; 72 | margin-top: 5px; 73 | } 74 | 75 | .poll-setting-label { 76 | text-transform: capitalize; 77 | } 78 | -------------------------------------------------------------------------------- /poll/public/css/themes/lms.css: -------------------------------------------------------------------------------- 1 | .themed-xblock.poll-block .poll-voting-thanks span { 2 | /* default LMS colors - contrast 11.0 */ 3 | background-color: #ffffff; 4 | color: #3c3c3c; 5 | } 6 | 7 | .themed-xblock.poll-block .poll-top-choice { 8 | /* close to LMS color for links and menu items - contrast 5.5 with white and 4.6 with e5ebee*/ 9 | color: #0070a0; 10 | } 11 | 12 | .themed-xblock.poll-block .poll-answer-label { 13 | vertical-align: middle; 14 | } 15 | 16 | .themed-xblock.poll-block .survey-table thead tr td, 17 | .themed-xblock.poll-block .survey-table thead tr th { 18 | font-size: 1em; 19 | } 20 | 21 | .themed-xblock.poll-block .survey-row td, 22 | .themed-xblock.poll-block .survey-row th { 23 | padding-top: 5px; 24 | padding-bottom: 5px; 25 | } 26 | 27 | /* LMS have very specific css selector that sets ~1.5em bottom margin */ 28 | .themed-xblock.poll-block table.survey-table .survey-row td p, 29 | .themed-xblock.poll-block table.survey-table .survey-row th p, 30 | .themed-xblock.poll-block .poll-answers .poll-answer .poll-answer p, 31 | .themed-xblock.poll-block ul.poll-results li.poll-result .poll-answer-label p { 32 | margin-bottom: 0; 33 | } 34 | 35 | .themed-xblock.poll-block ul.poll-results li.poll-spacer { 36 | margin-bottom: 0; 37 | } 38 | -------------------------------------------------------------------------------- /poll/public/handlebars/poll_results.handlebars: -------------------------------------------------------------------------------- 1 | 43 | -------------------------------------------------------------------------------- /poll/public/handlebars/poll_studio.handlebars: -------------------------------------------------------------------------------- 1 | 33 | -------------------------------------------------------------------------------- /poll/public/handlebars/survey_results.handlebars: -------------------------------------------------------------------------------- 1 | 52 | -------------------------------------------------------------------------------- /poll/public/html/poll.html: -------------------------------------------------------------------------------- 1 | {% load i18n %} 2 | {{ js_template|safe }} 3 |
5 |
6 | 7 |

{{ display_name }}

8 | 9 |
10 |
11 | 12 | {{ question|safe }} 13 | 14 |
15 | {% for key, value in answers %} 16 |
17 |
18 | 20 |
21 | {% if any_img %} 22 |
23 | 28 |
29 | {% endif %} 30 | 31 |
32 | {% endfor %} 33 |
34 |
35 | 38 |
39 | 40 |
42 | {% trans 'Thank you.' %} 43 |
44 | 45 |
46 | {% blocktrans with submissions_count_s='{{ submissions_count }}' max_submissions_s='{{ max_submissions }}' %} 47 | You have used {{ submissions_count_s }} out of {{ max_submissions_s }} submissions. 48 | {% endblocktrans %} 49 |
50 | 51 | {% if feedback %} 52 | 60 | {% endif %} 61 | 62 | 63 |
64 | {% if can_view_private_results %} 65 |
66 | 67 |
68 | {% endif %} 69 |
70 | {% if can_view_private_results %} 71 | {% if not studio_edit %} 72 |
73 | 74 | 75 |

76 |
77 | {% else %} 78 |

{% trans "Student data and results CSV available for download in the LMS." %}

79 | {% endif %} 80 | {% endif %} 81 | -------------------------------------------------------------------------------- /poll/public/html/survey.html: -------------------------------------------------------------------------------- 1 | {% load i18n %} 2 | {{ js_template|safe }} 3 |
5 |
6 |

{{block_name}}

7 |
8 | 9 | 10 | 11 | 12 | {% for answer, label in answers %} 13 | 14 | {% endfor %} 15 | 16 | 17 | {% for key, question in questions %} 18 | 19 | 27 | {% for answer, label in answers %} 28 | 49 | {% endfor %} 50 | 51 | {% endfor %} 52 | 53 | 56 |
57 |
{% trans 'Thank you.' %}
58 |
59 | {% blocktrans with submissions_count_s='{{ submissions_count }}' max_submissions_s='{{ max_submissions }}' %} 60 | You have used {{ submissions_count_s }} out of {{ max_submissions_s }} submissions. 61 | {% endblocktrans %} 62 |
63 | {% if feedback %} 64 | 71 | {% endif %} 72 | 73 | {% if can_view_private_results %} 74 |
75 | 76 |
77 | {% endif %} 78 |
79 |
80 | {% if can_view_private_results %} 81 | {% if not studio_edit %} 82 |
83 | 84 | 85 |

86 |
87 | {% else %} 88 |

{% trans "Student data and results CSV available for download in the LMS." %}

89 | {% endif %} 90 | {% endif %} 91 | -------------------------------------------------------------------------------- /poll/public/js/poll_common.js: -------------------------------------------------------------------------------- 1 | /* JavaScript utils for both LMS and Studio poll. */ 2 | 3 | var PollCommonUtil = { 4 | init: function (Handlebars) { 5 | // Make gettext available in Handlebars templates 6 | Handlebars.registerHelper('gettext', function (str) { 7 | return PollXBlockI18N.gettext(str); 8 | }); 9 | 10 | // Make ngettext available in Handlebars templates 11 | Handlebars.registerHelper('ngettext', function (singular, plural, count) { 12 | return PollXBlockI18N.ngettext(singular, plural, count); 13 | }); 14 | 15 | // Add helper for interpolating values into strings in Handlebars templates 16 | Handlebars.registerHelper('interpolate', function (formatString, parameters) { 17 | parameters = parameters.hash; 18 | return formatString.replace(/{\w+}/g, 19 | function (parameter) { 20 | var parameterName = parameter.slice(1, -1); 21 | return String(parameters[parameterName]); 22 | }); 23 | }); 24 | 25 | // Add helper for equality check 26 | Handlebars.registerHelper('if_eq', function (a, b, opts) { 27 | if(a == b) 28 | return opts.fn(this); 29 | else 30 | return opts.inverse(this); 31 | }); 32 | } 33 | }; 34 | -------------------------------------------------------------------------------- /poll/public/js/translations/ar/textjs.js: -------------------------------------------------------------------------------- 1 | 2 | (function(global){ 3 | var PollXBlockI18N = { 4 | init: function() { 5 | 6 | 7 | (function(globals) { 8 | 9 | var django = globals.django || (globals.django = {}); 10 | 11 | 12 | django.pluralidx = function(count) { return (count == 1) ? 0 : 1; }; 13 | 14 | 15 | /* gettext library */ 16 | 17 | django.catalog = django.catalog || {}; 18 | 19 | 20 | if (!django.jsi18n_initialized) { 21 | django.gettext = function(msgid) { 22 | var value = django.catalog[msgid]; 23 | if (typeof(value) == 'undefined') { 24 | return msgid; 25 | } else { 26 | return (typeof(value) == 'string') ? value : value[0]; 27 | } 28 | }; 29 | 30 | django.ngettext = function(singular, plural, count) { 31 | var value = django.catalog[singular]; 32 | if (typeof(value) == 'undefined') { 33 | return (count == 1) ? singular : plural; 34 | } else { 35 | return value.constructor === Array ? value[django.pluralidx(count)] : value; 36 | } 37 | }; 38 | 39 | django.gettext_noop = function(msgid) { return msgid; }; 40 | 41 | django.pgettext = function(context, msgid) { 42 | var value = django.gettext(context + '\x04' + msgid); 43 | if (value.indexOf('\x04') != -1) { 44 | value = msgid; 45 | } 46 | return value; 47 | }; 48 | 49 | django.npgettext = function(context, singular, plural, count) { 50 | var value = django.ngettext(context + '\x04' + singular, context + '\x04' + plural, count); 51 | if (value.indexOf('\x04') != -1) { 52 | value = django.ngettext(singular, plural, count); 53 | } 54 | return value; 55 | }; 56 | 57 | django.interpolate = function(fmt, obj, named) { 58 | if (named) { 59 | return fmt.replace(/%\(\w+\)s/g, function(match){return String(obj[match.slice(2,-2)])}); 60 | } else { 61 | return fmt.replace(/%s/g, function(match){return String(obj.shift())}); 62 | } 63 | }; 64 | 65 | 66 | /* formatting library */ 67 | 68 | django.formats = { 69 | "DATETIME_FORMAT": "N j, Y, P", 70 | "DATETIME_INPUT_FORMATS": [ 71 | "%Y-%m-%d %H:%M:%S", 72 | "%Y-%m-%d %H:%M:%S.%f", 73 | "%Y-%m-%d %H:%M", 74 | "%Y-%m-%d", 75 | "%m/%d/%Y %H:%M:%S", 76 | "%m/%d/%Y %H:%M:%S.%f", 77 | "%m/%d/%Y %H:%M", 78 | "%m/%d/%Y", 79 | "%m/%d/%y %H:%M:%S", 80 | "%m/%d/%y %H:%M:%S.%f", 81 | "%m/%d/%y %H:%M", 82 | "%m/%d/%y" 83 | ], 84 | "DATE_FORMAT": "j F\u060c Y", 85 | "DATE_INPUT_FORMATS": [ 86 | "%Y-%m-%d", 87 | "%m/%d/%Y", 88 | "%m/%d/%y", 89 | "%b %d %Y", 90 | "%b %d, %Y", 91 | "%d %b %Y", 92 | "%d %b, %Y", 93 | "%B %d %Y", 94 | "%B %d, %Y", 95 | "%d %B %Y", 96 | "%d %B, %Y" 97 | ], 98 | "DECIMAL_SEPARATOR": ",", 99 | "FIRST_DAY_OF_WEEK": 0, 100 | "MONTH_DAY_FORMAT": "j F", 101 | "NUMBER_GROUPING": 0, 102 | "SHORT_DATETIME_FORMAT": "m/d/Y P", 103 | "SHORT_DATE_FORMAT": "d\u200f/m\u200f/Y", 104 | "THOUSAND_SEPARATOR": ".", 105 | "TIME_FORMAT": "g:i A", 106 | "TIME_INPUT_FORMATS": [ 107 | "%H:%M:%S", 108 | "%H:%M:%S.%f", 109 | "%H:%M" 110 | ], 111 | "YEAR_MONTH_FORMAT": "F Y" 112 | }; 113 | 114 | django.get_format = function(format_type) { 115 | var value = django.formats[format_type]; 116 | if (typeof(value) == 'undefined') { 117 | return format_type; 118 | } else { 119 | return value; 120 | } 121 | }; 122 | 123 | /* add to global namespace */ 124 | globals.pluralidx = django.pluralidx; 125 | globals.gettext = django.gettext; 126 | globals.ngettext = django.ngettext; 127 | globals.gettext_noop = django.gettext_noop; 128 | globals.pgettext = django.pgettext; 129 | globals.npgettext = django.npgettext; 130 | globals.interpolate = django.interpolate; 131 | globals.get_format = django.get_format; 132 | 133 | django.jsi18n_initialized = true; 134 | } 135 | 136 | }(this)); 137 | 138 | 139 | } 140 | }; 141 | PollXBlockI18N.init(); 142 | global.PollXBlockI18N = PollXBlockI18N; 143 | }(this)); 144 | -------------------------------------------------------------------------------- /poll/public/js/translations/de_DE/textjs.js: -------------------------------------------------------------------------------- 1 | 2 | (function(global){ 3 | var PollXBlockI18N = { 4 | init: function() { 5 | 6 | 7 | (function(globals) { 8 | 9 | var django = globals.django || (globals.django = {}); 10 | 11 | 12 | django.pluralidx = function(n) { 13 | var v=(n != 1); 14 | if (typeof(v) == 'boolean') { 15 | return v ? 1 : 0; 16 | } else { 17 | return v; 18 | } 19 | }; 20 | 21 | 22 | /* gettext library */ 23 | 24 | django.catalog = django.catalog || {}; 25 | 26 | var newcatalog = { 27 | "Answer": "Antwort", 28 | "Delete": "L\u00f6schen", 29 | "Feedback": "R\u00fcckmeldung", 30 | "Image URL": "Bild URL", 31 | "Image alternative text": "Alternativtext zum Bild", 32 | "Question": "Frage", 33 | "Results": "Ergebnisse", 34 | "Results gathered from {total} respondent.": [ 35 | "Ergebnisse von {total} Befragten erfasst.", 36 | "Ergebnisse von {total} Befragten erfasst." 37 | ], 38 | "Submit": "Absenden", 39 | "This must have an image URL or text, and can have both. If you add an image, you must also provide an alternative text that describes the image in a way that would allow someone to answer the poll if the image did not load.": "Dieser muss eine Bild-URL und/oder einen Text haben. Wenn Sie ein Bild hinzuf\u00fcgen, m\u00fcssen Sie auch einen alternativen Text angeben, der das Bild so beschreibt, dass jemand auf die Umfrage antworten kann, wenn das Bild nicht geladen wurde.", 40 | "You can make limited use of Markdown in answer texts, preferably only bold and italics.": "In den Antworttexten k\u00f6nnen Sie die Markdown-Funktion nur begrenzt verwenden, vorzugsweise nur fett und kursiv.", 41 | "move poll down": "Umfrage nach unten bewegen", 42 | "move poll up": "Umfrage nach oben bewegen" 43 | }; 44 | for (var key in newcatalog) { 45 | django.catalog[key] = newcatalog[key]; 46 | } 47 | 48 | 49 | if (!django.jsi18n_initialized) { 50 | django.gettext = function(msgid) { 51 | var value = django.catalog[msgid]; 52 | if (typeof(value) == 'undefined') { 53 | return msgid; 54 | } else { 55 | return (typeof(value) == 'string') ? value : value[0]; 56 | } 57 | }; 58 | 59 | django.ngettext = function(singular, plural, count) { 60 | var value = django.catalog[singular]; 61 | if (typeof(value) == 'undefined') { 62 | return (count == 1) ? singular : plural; 63 | } else { 64 | return value.constructor === Array ? value[django.pluralidx(count)] : value; 65 | } 66 | }; 67 | 68 | django.gettext_noop = function(msgid) { return msgid; }; 69 | 70 | django.pgettext = function(context, msgid) { 71 | var value = django.gettext(context + '\x04' + msgid); 72 | if (value.indexOf('\x04') != -1) { 73 | value = msgid; 74 | } 75 | return value; 76 | }; 77 | 78 | django.npgettext = function(context, singular, plural, count) { 79 | var value = django.ngettext(context + '\x04' + singular, context + '\x04' + plural, count); 80 | if (value.indexOf('\x04') != -1) { 81 | value = django.ngettext(singular, plural, count); 82 | } 83 | return value; 84 | }; 85 | 86 | django.interpolate = function(fmt, obj, named) { 87 | if (named) { 88 | return fmt.replace(/%\(\w+\)s/g, function(match){return String(obj[match.slice(2,-2)])}); 89 | } else { 90 | return fmt.replace(/%s/g, function(match){return String(obj.shift())}); 91 | } 92 | }; 93 | 94 | 95 | /* formatting library */ 96 | 97 | django.formats = { 98 | "DATETIME_FORMAT": "j. F Y H:i", 99 | "DATETIME_INPUT_FORMATS": [ 100 | "%d.%m.%Y %H:%M:%S", 101 | "%d.%m.%Y %H:%M:%S.%f", 102 | "%d.%m.%Y %H:%M", 103 | "%d.%m.%Y", 104 | "%Y-%m-%d %H:%M:%S", 105 | "%Y-%m-%d %H:%M:%S.%f", 106 | "%Y-%m-%d %H:%M", 107 | "%Y-%m-%d" 108 | ], 109 | "DATE_FORMAT": "j. F Y", 110 | "DATE_INPUT_FORMATS": [ 111 | "%d.%m.%Y", 112 | "%d.%m.%y", 113 | "%Y-%m-%d" 114 | ], 115 | "DECIMAL_SEPARATOR": ",", 116 | "FIRST_DAY_OF_WEEK": 1, 117 | "MONTH_DAY_FORMAT": "j. F", 118 | "NUMBER_GROUPING": 3, 119 | "SHORT_DATETIME_FORMAT": "d.m.Y H:i", 120 | "SHORT_DATE_FORMAT": "d.m.Y", 121 | "THOUSAND_SEPARATOR": ".", 122 | "TIME_FORMAT": "H:i", 123 | "TIME_INPUT_FORMATS": [ 124 | "%H:%M:%S", 125 | "%H:%M:%S.%f", 126 | "%H:%M" 127 | ], 128 | "YEAR_MONTH_FORMAT": "F Y" 129 | }; 130 | 131 | django.get_format = function(format_type) { 132 | var value = django.formats[format_type]; 133 | if (typeof(value) == 'undefined') { 134 | return format_type; 135 | } else { 136 | return value; 137 | } 138 | }; 139 | 140 | /* add to global namespace */ 141 | globals.pluralidx = django.pluralidx; 142 | globals.gettext = django.gettext; 143 | globals.ngettext = django.ngettext; 144 | globals.gettext_noop = django.gettext_noop; 145 | globals.pgettext = django.pgettext; 146 | globals.npgettext = django.npgettext; 147 | globals.interpolate = django.interpolate; 148 | globals.get_format = django.get_format; 149 | 150 | django.jsi18n_initialized = true; 151 | } 152 | 153 | }(this)); 154 | 155 | 156 | } 157 | }; 158 | PollXBlockI18N.init(); 159 | global.PollXBlockI18N = PollXBlockI18N; 160 | }(this)); 161 | -------------------------------------------------------------------------------- /poll/public/js/translations/en/textjs.js: -------------------------------------------------------------------------------- 1 | 2 | (function(global){ 3 | var PollXBlockI18N = { 4 | init: function() { 5 | 6 | 7 | (function(globals) { 8 | 9 | var django = globals.django || (globals.django = {}); 10 | 11 | 12 | django.pluralidx = function(count) { return (count == 1) ? 0 : 1; }; 13 | 14 | 15 | /* gettext library */ 16 | 17 | django.catalog = django.catalog || {}; 18 | 19 | 20 | if (!django.jsi18n_initialized) { 21 | django.gettext = function(msgid) { 22 | var value = django.catalog[msgid]; 23 | if (typeof(value) == 'undefined') { 24 | return msgid; 25 | } else { 26 | return (typeof(value) == 'string') ? value : value[0]; 27 | } 28 | }; 29 | 30 | django.ngettext = function(singular, plural, count) { 31 | var value = django.catalog[singular]; 32 | if (typeof(value) == 'undefined') { 33 | return (count == 1) ? singular : plural; 34 | } else { 35 | return value.constructor === Array ? value[django.pluralidx(count)] : value; 36 | } 37 | }; 38 | 39 | django.gettext_noop = function(msgid) { return msgid; }; 40 | 41 | django.pgettext = function(context, msgid) { 42 | var value = django.gettext(context + '\x04' + msgid); 43 | if (value.indexOf('\x04') != -1) { 44 | value = msgid; 45 | } 46 | return value; 47 | }; 48 | 49 | django.npgettext = function(context, singular, plural, count) { 50 | var value = django.ngettext(context + '\x04' + singular, context + '\x04' + plural, count); 51 | if (value.indexOf('\x04') != -1) { 52 | value = django.ngettext(singular, plural, count); 53 | } 54 | return value; 55 | }; 56 | 57 | django.interpolate = function(fmt, obj, named) { 58 | if (named) { 59 | return fmt.replace(/%\(\w+\)s/g, function(match){return String(obj[match.slice(2,-2)])}); 60 | } else { 61 | return fmt.replace(/%s/g, function(match){return String(obj.shift())}); 62 | } 63 | }; 64 | 65 | 66 | /* formatting library */ 67 | 68 | django.formats = { 69 | "DATETIME_FORMAT": "N j, Y, P", 70 | "DATETIME_INPUT_FORMATS": [ 71 | "%Y-%m-%d %H:%M:%S", 72 | "%Y-%m-%d %H:%M:%S.%f", 73 | "%Y-%m-%d %H:%M", 74 | "%Y-%m-%d", 75 | "%m/%d/%Y %H:%M:%S", 76 | "%m/%d/%Y %H:%M:%S.%f", 77 | "%m/%d/%Y %H:%M", 78 | "%m/%d/%Y", 79 | "%m/%d/%y %H:%M:%S", 80 | "%m/%d/%y %H:%M:%S.%f", 81 | "%m/%d/%y %H:%M", 82 | "%m/%d/%y" 83 | ], 84 | "DATE_FORMAT": "N j, Y", 85 | "DATE_INPUT_FORMATS": [ 86 | "%Y-%m-%d", 87 | "%m/%d/%Y", 88 | "%m/%d/%y" 89 | ], 90 | "DECIMAL_SEPARATOR": ".", 91 | "FIRST_DAY_OF_WEEK": 0, 92 | "MONTH_DAY_FORMAT": "F j", 93 | "NUMBER_GROUPING": 3, 94 | "SHORT_DATETIME_FORMAT": "m/d/Y P", 95 | "SHORT_DATE_FORMAT": "m/d/Y", 96 | "THOUSAND_SEPARATOR": ",", 97 | "TIME_FORMAT": "P", 98 | "TIME_INPUT_FORMATS": [ 99 | "%H:%M:%S", 100 | "%H:%M:%S.%f", 101 | "%H:%M" 102 | ], 103 | "YEAR_MONTH_FORMAT": "F Y" 104 | }; 105 | 106 | django.get_format = function(format_type) { 107 | var value = django.formats[format_type]; 108 | if (typeof(value) == 'undefined') { 109 | return format_type; 110 | } else { 111 | return value; 112 | } 113 | }; 114 | 115 | /* add to global namespace */ 116 | globals.pluralidx = django.pluralidx; 117 | globals.gettext = django.gettext; 118 | globals.ngettext = django.ngettext; 119 | globals.gettext_noop = django.gettext_noop; 120 | globals.pgettext = django.pgettext; 121 | globals.npgettext = django.npgettext; 122 | globals.interpolate = django.interpolate; 123 | globals.get_format = django.get_format; 124 | 125 | django.jsi18n_initialized = true; 126 | } 127 | 128 | }(this)); 129 | 130 | 131 | } 132 | }; 133 | PollXBlockI18N.init(); 134 | global.PollXBlockI18N = PollXBlockI18N; 135 | }(this)); 136 | -------------------------------------------------------------------------------- /poll/public/js/translations/es_419/textjs.js: -------------------------------------------------------------------------------- 1 | 2 | (function(global){ 3 | var PollXBlockI18N = { 4 | init: function() { 5 | 6 | 7 | (function(globals) { 8 | 9 | var django = globals.django || (globals.django = {}); 10 | 11 | 12 | django.pluralidx = function(n) { 13 | var v=(n != 1); 14 | if (typeof(v) == 'boolean') { 15 | return v ? 1 : 0; 16 | } else { 17 | return v; 18 | } 19 | }; 20 | 21 | 22 | /* gettext library */ 23 | 24 | django.catalog = django.catalog || {}; 25 | 26 | var newcatalog = { 27 | "Answer": "Respuesta", 28 | "Delete": "Borrar", 29 | "Feedback": "Retroalimentaci\u00f3n", 30 | "Image URL": "URL de la imagen", 31 | "Image alternative text": "Texto alternativo de la imagen", 32 | "Question": "Pregunta", 33 | "Results": "Resultados", 34 | "Results gathered from {total} respondent.": [ 35 | "Resultados obtenidos de {total} encuestado.", 36 | "Resultados obtenidos de {total} encuestados." 37 | ], 38 | "Submit": "Enviar", 39 | "This must have an image URL or text, and can have both. If you add an image, you must also provide an alternative text that describes the image in a way that would allow someone to answer the poll if the image did not load.": "Esto debe tener una URL de imagen o texto, y puede tener ambos. Si agrega una imagen, debe adem\u00e1s proporcionar un texto alternativo que describa la imagen de manera que permita a alguien responder la encuesta a\u00fan si la imagen no carga.", 40 | "You can make limited use of Markdown in answer texts, preferably only bold and italics.": "Puede hacer uso limitado de Markdown en los textos de respuesta, preferiblemente solo negritas e it\u00e1licas.", 41 | "move poll down": "mover la encuesta abajo", 42 | "move poll up": "mover la encuesta arriba" 43 | }; 44 | for (var key in newcatalog) { 45 | django.catalog[key] = newcatalog[key]; 46 | } 47 | 48 | 49 | if (!django.jsi18n_initialized) { 50 | django.gettext = function(msgid) { 51 | var value = django.catalog[msgid]; 52 | if (typeof(value) == 'undefined') { 53 | return msgid; 54 | } else { 55 | return (typeof(value) == 'string') ? value : value[0]; 56 | } 57 | }; 58 | 59 | django.ngettext = function(singular, plural, count) { 60 | var value = django.catalog[singular]; 61 | if (typeof(value) == 'undefined') { 62 | return (count == 1) ? singular : plural; 63 | } else { 64 | return value.constructor === Array ? value[django.pluralidx(count)] : value; 65 | } 66 | }; 67 | 68 | django.gettext_noop = function(msgid) { return msgid; }; 69 | 70 | django.pgettext = function(context, msgid) { 71 | var value = django.gettext(context + '\x04' + msgid); 72 | if (value.indexOf('\x04') != -1) { 73 | value = msgid; 74 | } 75 | return value; 76 | }; 77 | 78 | django.npgettext = function(context, singular, plural, count) { 79 | var value = django.ngettext(context + '\x04' + singular, context + '\x04' + plural, count); 80 | if (value.indexOf('\x04') != -1) { 81 | value = django.ngettext(singular, plural, count); 82 | } 83 | return value; 84 | }; 85 | 86 | django.interpolate = function(fmt, obj, named) { 87 | if (named) { 88 | return fmt.replace(/%\(\w+\)s/g, function(match){return String(obj[match.slice(2,-2)])}); 89 | } else { 90 | return fmt.replace(/%s/g, function(match){return String(obj.shift())}); 91 | } 92 | }; 93 | 94 | 95 | /* formatting library */ 96 | 97 | django.formats = { 98 | "DATETIME_FORMAT": "j \\d\\e F \\d\\e Y \\a \\l\\a\\s H:i", 99 | "DATETIME_INPUT_FORMATS": [ 100 | "%d/%m/%Y %H:%M:%S", 101 | "%d/%m/%Y %H:%M:%S.%f", 102 | "%d/%m/%Y %H:%M", 103 | "%d/%m/%y %H:%M:%S", 104 | "%d/%m/%y %H:%M:%S.%f", 105 | "%d/%m/%y %H:%M", 106 | "%Y-%m-%d %H:%M:%S", 107 | "%Y-%m-%d %H:%M:%S.%f", 108 | "%Y-%m-%d %H:%M", 109 | "%Y-%m-%d" 110 | ], 111 | "DATE_FORMAT": "j \\d\\e F \\d\\e Y", 112 | "DATE_INPUT_FORMATS": [ 113 | "%d/%m/%Y", 114 | "%d/%m/%y", 115 | "%Y-%m-%d" 116 | ], 117 | "DECIMAL_SEPARATOR": ",", 118 | "FIRST_DAY_OF_WEEK": 1, 119 | "MONTH_DAY_FORMAT": "j \\d\\e F", 120 | "NUMBER_GROUPING": 3, 121 | "SHORT_DATETIME_FORMAT": "d/m/Y H:i", 122 | "SHORT_DATE_FORMAT": "d/m/Y", 123 | "THOUSAND_SEPARATOR": ".", 124 | "TIME_FORMAT": "H:i", 125 | "TIME_INPUT_FORMATS": [ 126 | "%H:%M:%S", 127 | "%H:%M:%S.%f", 128 | "%H:%M" 129 | ], 130 | "YEAR_MONTH_FORMAT": "F \\d\\e Y" 131 | }; 132 | 133 | django.get_format = function(format_type) { 134 | var value = django.formats[format_type]; 135 | if (typeof(value) == 'undefined') { 136 | return format_type; 137 | } else { 138 | return value; 139 | } 140 | }; 141 | 142 | /* add to global namespace */ 143 | globals.pluralidx = django.pluralidx; 144 | globals.gettext = django.gettext; 145 | globals.ngettext = django.ngettext; 146 | globals.gettext_noop = django.gettext_noop; 147 | globals.pgettext = django.pgettext; 148 | globals.npgettext = django.npgettext; 149 | globals.interpolate = django.interpolate; 150 | globals.get_format = django.get_format; 151 | 152 | django.jsi18n_initialized = true; 153 | } 154 | 155 | }(this)); 156 | 157 | 158 | } 159 | }; 160 | PollXBlockI18N.init(); 161 | global.PollXBlockI18N = PollXBlockI18N; 162 | }(this)); 163 | -------------------------------------------------------------------------------- /poll/public/js/translations/fr/textjs.js: -------------------------------------------------------------------------------- 1 | 2 | (function(global){ 3 | var PollXBlockI18N = { 4 | init: function() { 5 | 6 | 7 | (function(globals) { 8 | 9 | var django = globals.django || (globals.django = {}); 10 | 11 | 12 | django.pluralidx = function(n) { 13 | var v=(n > 1); 14 | if (typeof(v) == 'boolean') { 15 | return v ? 1 : 0; 16 | } else { 17 | return v; 18 | } 19 | }; 20 | 21 | 22 | /* gettext library */ 23 | 24 | django.catalog = django.catalog || {}; 25 | 26 | var newcatalog = { 27 | "Answer": "R\u00e9ponse", 28 | "Delete": "Supprimer", 29 | "Feedback": "Commentaire", 30 | "Image URL": "URL de l'image", 31 | "Image alternative text": "Texte alternatif de l'image", 32 | "Question": "Question", 33 | "Results": "R\u00e9sultats", 34 | "Results gathered from {total} respondent.": [ 35 | "R\u00e9sultats recueillis aupr\u00e8s de {total} r\u00e9pondant.", 36 | "R\u00e9sultats recueillis aupr\u00e8s de {total} r\u00e9pondants." 37 | ], 38 | "Submit": "Soumettre", 39 | "This must have an image URL or text, and can have both. If you add an image, you must also provide an alternative text that describes the image in a way that would allow someone to answer the poll if the image did not load.": "Cela doit avoir une URL d'image ou un texte, et peut avoir les deux. Si vous ajoutez une image, vous devez \u00e9galement fournir un texte de remplacement d\u00e9crivant l'image de mani\u00e8re \u00e0 permettre \u00e0 quelqu'un de r\u00e9pondre au sondage si l'image ne s'est pas charg\u00e9e.", 40 | "You can make limited use of Markdown in answer texts, preferably only bold and italics.": "Vous pouvez utiliser Markdown de mani\u00e8re limit\u00e9e dans les textes de r\u00e9ponse, de pr\u00e9f\u00e9rence uniquement en gras et en italique.", 41 | "move poll down": "d\u00e9placer le sondage vers le bas", 42 | "move poll up": "d\u00e9placer le sondage vers le haut" 43 | }; 44 | for (var key in newcatalog) { 45 | django.catalog[key] = newcatalog[key]; 46 | } 47 | 48 | 49 | if (!django.jsi18n_initialized) { 50 | django.gettext = function(msgid) { 51 | var value = django.catalog[msgid]; 52 | if (typeof(value) == 'undefined') { 53 | return msgid; 54 | } else { 55 | return (typeof(value) == 'string') ? value : value[0]; 56 | } 57 | }; 58 | 59 | django.ngettext = function(singular, plural, count) { 60 | var value = django.catalog[singular]; 61 | if (typeof(value) == 'undefined') { 62 | return (count == 1) ? singular : plural; 63 | } else { 64 | return value.constructor === Array ? value[django.pluralidx(count)] : value; 65 | } 66 | }; 67 | 68 | django.gettext_noop = function(msgid) { return msgid; }; 69 | 70 | django.pgettext = function(context, msgid) { 71 | var value = django.gettext(context + '\x04' + msgid); 72 | if (value.indexOf('\x04') != -1) { 73 | value = msgid; 74 | } 75 | return value; 76 | }; 77 | 78 | django.npgettext = function(context, singular, plural, count) { 79 | var value = django.ngettext(context + '\x04' + singular, context + '\x04' + plural, count); 80 | if (value.indexOf('\x04') != -1) { 81 | value = django.ngettext(singular, plural, count); 82 | } 83 | return value; 84 | }; 85 | 86 | django.interpolate = function(fmt, obj, named) { 87 | if (named) { 88 | return fmt.replace(/%\(\w+\)s/g, function(match){return String(obj[match.slice(2,-2)])}); 89 | } else { 90 | return fmt.replace(/%s/g, function(match){return String(obj.shift())}); 91 | } 92 | }; 93 | 94 | 95 | /* formatting library */ 96 | 97 | django.formats = { 98 | "DATETIME_FORMAT": "j F Y H:i", 99 | "DATETIME_INPUT_FORMATS": [ 100 | "%d/%m/%Y %H:%M:%S", 101 | "%d/%m/%Y %H:%M:%S.%f", 102 | "%d/%m/%Y %H:%M", 103 | "%d/%m/%Y", 104 | "%d.%m.%Y %H:%M:%S", 105 | "%d.%m.%Y %H:%M:%S.%f", 106 | "%d.%m.%Y %H:%M", 107 | "%d.%m.%Y", 108 | "%Y-%m-%d %H:%M:%S", 109 | "%Y-%m-%d %H:%M:%S.%f", 110 | "%Y-%m-%d %H:%M", 111 | "%Y-%m-%d" 112 | ], 113 | "DATE_FORMAT": "j F Y", 114 | "DATE_INPUT_FORMATS": [ 115 | "%d/%m/%Y", 116 | "%d/%m/%y", 117 | "%d.%m.%Y", 118 | "%d.%m.%y", 119 | "%Y-%m-%d" 120 | ], 121 | "DECIMAL_SEPARATOR": ",", 122 | "FIRST_DAY_OF_WEEK": 1, 123 | "MONTH_DAY_FORMAT": "j F", 124 | "NUMBER_GROUPING": 3, 125 | "SHORT_DATETIME_FORMAT": "j N Y H:i", 126 | "SHORT_DATE_FORMAT": "j N Y", 127 | "THOUSAND_SEPARATOR": "\u00a0", 128 | "TIME_FORMAT": "H:i", 129 | "TIME_INPUT_FORMATS": [ 130 | "%H:%M:%S", 131 | "%H:%M:%S.%f", 132 | "%H:%M" 133 | ], 134 | "YEAR_MONTH_FORMAT": "F Y" 135 | }; 136 | 137 | django.get_format = function(format_type) { 138 | var value = django.formats[format_type]; 139 | if (typeof(value) == 'undefined') { 140 | return format_type; 141 | } else { 142 | return value; 143 | } 144 | }; 145 | 146 | /* add to global namespace */ 147 | globals.pluralidx = django.pluralidx; 148 | globals.gettext = django.gettext; 149 | globals.ngettext = django.ngettext; 150 | globals.gettext_noop = django.gettext_noop; 151 | globals.pgettext = django.pgettext; 152 | globals.npgettext = django.npgettext; 153 | globals.interpolate = django.interpolate; 154 | globals.get_format = django.get_format; 155 | 156 | django.jsi18n_initialized = true; 157 | } 158 | 159 | }(this)); 160 | 161 | 162 | } 163 | }; 164 | PollXBlockI18N.init(); 165 | global.PollXBlockI18N = PollXBlockI18N; 166 | }(this)); 167 | -------------------------------------------------------------------------------- /poll/public/js/translations/fr_CA/textjs.js: -------------------------------------------------------------------------------- 1 | 2 | (function(global){ 3 | var PollXBlockI18N = { 4 | init: function() { 5 | 6 | 7 | (function(globals) { 8 | 9 | var django = globals.django || (globals.django = {}); 10 | 11 | 12 | django.pluralidx = function(n) { 13 | var v=(n > 1); 14 | if (typeof(v) == 'boolean') { 15 | return v ? 1 : 0; 16 | } else { 17 | return v; 18 | } 19 | }; 20 | 21 | 22 | /* gettext library */ 23 | 24 | django.catalog = django.catalog || {}; 25 | 26 | var newcatalog = { 27 | "Answer": "R\u00e9ponse", 28 | "Delete": "Supprimer", 29 | "Feedback": "Commentaire", 30 | "Image URL": "URL de l'image", 31 | "Image alternative text": "Texte alternatif de l'image", 32 | "Question": "Question", 33 | "Results": "R\u00e9sultats", 34 | "Results gathered from {total} respondent.": [ 35 | "R\u00e9sultats recueillis aupr\u00e8s de {total} r\u00e9pondant.", 36 | "R\u00e9sultats recueillis aupr\u00e8s de {total} r\u00e9pondants." 37 | ], 38 | "Submit": "Soumettre", 39 | "This must have an image URL or text, and can have both. If you add an image, you must also provide an alternative text that describes the image in a way that would allow someone to answer the poll if the image did not load.": "Cela doit avoir une URL d'image ou un texte, et peut avoir les deux. Si vous ajoutez une image, vous devez \u00e9galement fournir un texte de remplacement d\u00e9crivant l'image de mani\u00e8re \u00e0 permettre \u00e0 quelqu'un de r\u00e9pondre au sondage si l'image ne s'est pas charg\u00e9e.", 40 | "You can make limited use of Markdown in answer texts, preferably only bold and italics.": "Vous pouvez utiliser Markdown de mani\u00e8re limit\u00e9e dans les textes de r\u00e9ponse, de pr\u00e9f\u00e9rence uniquement en gras et en italique.", 41 | "move poll down": "d\u00e9placer le sondage vers le bas", 42 | "move poll up": "d\u00e9placer le sondage vers le haut" 43 | }; 44 | for (var key in newcatalog) { 45 | django.catalog[key] = newcatalog[key]; 46 | } 47 | 48 | 49 | if (!django.jsi18n_initialized) { 50 | django.gettext = function(msgid) { 51 | var value = django.catalog[msgid]; 52 | if (typeof(value) == 'undefined') { 53 | return msgid; 54 | } else { 55 | return (typeof(value) == 'string') ? value : value[0]; 56 | } 57 | }; 58 | 59 | django.ngettext = function(singular, plural, count) { 60 | var value = django.catalog[singular]; 61 | if (typeof(value) == 'undefined') { 62 | return (count == 1) ? singular : plural; 63 | } else { 64 | return value.constructor === Array ? value[django.pluralidx(count)] : value; 65 | } 66 | }; 67 | 68 | django.gettext_noop = function(msgid) { return msgid; }; 69 | 70 | django.pgettext = function(context, msgid) { 71 | var value = django.gettext(context + '\x04' + msgid); 72 | if (value.indexOf('\x04') != -1) { 73 | value = msgid; 74 | } 75 | return value; 76 | }; 77 | 78 | django.npgettext = function(context, singular, plural, count) { 79 | var value = django.ngettext(context + '\x04' + singular, context + '\x04' + plural, count); 80 | if (value.indexOf('\x04') != -1) { 81 | value = django.ngettext(singular, plural, count); 82 | } 83 | return value; 84 | }; 85 | 86 | django.interpolate = function(fmt, obj, named) { 87 | if (named) { 88 | return fmt.replace(/%\(\w+\)s/g, function(match){return String(obj[match.slice(2,-2)])}); 89 | } else { 90 | return fmt.replace(/%s/g, function(match){return String(obj.shift())}); 91 | } 92 | }; 93 | 94 | 95 | /* formatting library */ 96 | 97 | django.formats = { 98 | "DATETIME_FORMAT": "j F Y H:i", 99 | "DATETIME_INPUT_FORMATS": [ 100 | "%d/%m/%Y %H:%M:%S", 101 | "%d/%m/%Y %H:%M:%S.%f", 102 | "%d/%m/%Y %H:%M", 103 | "%d/%m/%Y", 104 | "%d.%m.%Y %H:%M:%S", 105 | "%d.%m.%Y %H:%M:%S.%f", 106 | "%d.%m.%Y %H:%M", 107 | "%d.%m.%Y", 108 | "%Y-%m-%d %H:%M:%S", 109 | "%Y-%m-%d %H:%M:%S.%f", 110 | "%Y-%m-%d %H:%M", 111 | "%Y-%m-%d" 112 | ], 113 | "DATE_FORMAT": "j F Y", 114 | "DATE_INPUT_FORMATS": [ 115 | "%d/%m/%Y", 116 | "%d/%m/%y", 117 | "%d.%m.%Y", 118 | "%d.%m.%y", 119 | "%Y-%m-%d" 120 | ], 121 | "DECIMAL_SEPARATOR": ",", 122 | "FIRST_DAY_OF_WEEK": 1, 123 | "MONTH_DAY_FORMAT": "j F", 124 | "NUMBER_GROUPING": 3, 125 | "SHORT_DATETIME_FORMAT": "j N Y H:i", 126 | "SHORT_DATE_FORMAT": "j N Y", 127 | "THOUSAND_SEPARATOR": "\u00a0", 128 | "TIME_FORMAT": "H:i", 129 | "TIME_INPUT_FORMATS": [ 130 | "%H:%M:%S", 131 | "%H:%M:%S.%f", 132 | "%H:%M" 133 | ], 134 | "YEAR_MONTH_FORMAT": "F Y" 135 | }; 136 | 137 | django.get_format = function(format_type) { 138 | var value = django.formats[format_type]; 139 | if (typeof(value) == 'undefined') { 140 | return format_type; 141 | } else { 142 | return value; 143 | } 144 | }; 145 | 146 | /* add to global namespace */ 147 | globals.pluralidx = django.pluralidx; 148 | globals.gettext = django.gettext; 149 | globals.ngettext = django.ngettext; 150 | globals.gettext_noop = django.gettext_noop; 151 | globals.pgettext = django.pgettext; 152 | globals.npgettext = django.npgettext; 153 | globals.interpolate = django.interpolate; 154 | globals.get_format = django.get_format; 155 | 156 | django.jsi18n_initialized = true; 157 | } 158 | 159 | }(this)); 160 | 161 | 162 | } 163 | }; 164 | PollXBlockI18N.init(); 165 | global.PollXBlockI18N = PollXBlockI18N; 166 | }(this)); 167 | -------------------------------------------------------------------------------- /poll/public/js/translations/he/textjs.js: -------------------------------------------------------------------------------- 1 | 2 | (function(global){ 3 | var PollXBlockI18N = { 4 | init: function() { 5 | 6 | 7 | (function(globals) { 8 | 9 | var django = globals.django || (globals.django = {}); 10 | 11 | 12 | django.pluralidx = function(count) { return (count == 1) ? 0 : 1; }; 13 | 14 | 15 | /* gettext library */ 16 | 17 | django.catalog = django.catalog || {}; 18 | 19 | 20 | if (!django.jsi18n_initialized) { 21 | django.gettext = function(msgid) { 22 | var value = django.catalog[msgid]; 23 | if (typeof(value) == 'undefined') { 24 | return msgid; 25 | } else { 26 | return (typeof(value) == 'string') ? value : value[0]; 27 | } 28 | }; 29 | 30 | django.ngettext = function(singular, plural, count) { 31 | var value = django.catalog[singular]; 32 | if (typeof(value) == 'undefined') { 33 | return (count == 1) ? singular : plural; 34 | } else { 35 | return value.constructor === Array ? value[django.pluralidx(count)] : value; 36 | } 37 | }; 38 | 39 | django.gettext_noop = function(msgid) { return msgid; }; 40 | 41 | django.pgettext = function(context, msgid) { 42 | var value = django.gettext(context + '\x04' + msgid); 43 | if (value.indexOf('\x04') != -1) { 44 | value = msgid; 45 | } 46 | return value; 47 | }; 48 | 49 | django.npgettext = function(context, singular, plural, count) { 50 | var value = django.ngettext(context + '\x04' + singular, context + '\x04' + plural, count); 51 | if (value.indexOf('\x04') != -1) { 52 | value = django.ngettext(singular, plural, count); 53 | } 54 | return value; 55 | }; 56 | 57 | django.interpolate = function(fmt, obj, named) { 58 | if (named) { 59 | return fmt.replace(/%\(\w+\)s/g, function(match){return String(obj[match.slice(2,-2)])}); 60 | } else { 61 | return fmt.replace(/%s/g, function(match){return String(obj.shift())}); 62 | } 63 | }; 64 | 65 | 66 | /* formatting library */ 67 | 68 | django.formats = { 69 | "DATETIME_FORMAT": "j \u05d1F Y H:i", 70 | "DATETIME_INPUT_FORMATS": [ 71 | "%Y-%m-%d %H:%M:%S", 72 | "%Y-%m-%d %H:%M:%S.%f", 73 | "%Y-%m-%d %H:%M", 74 | "%Y-%m-%d", 75 | "%m/%d/%Y %H:%M:%S", 76 | "%m/%d/%Y %H:%M:%S.%f", 77 | "%m/%d/%Y %H:%M", 78 | "%m/%d/%Y", 79 | "%m/%d/%y %H:%M:%S", 80 | "%m/%d/%y %H:%M:%S.%f", 81 | "%m/%d/%y %H:%M", 82 | "%m/%d/%y" 83 | ], 84 | "DATE_FORMAT": "j \u05d1F Y", 85 | "DATE_INPUT_FORMATS": [ 86 | "%Y-%m-%d", 87 | "%m/%d/%Y", 88 | "%m/%d/%y", 89 | "%b %d %Y", 90 | "%b %d, %Y", 91 | "%d %b %Y", 92 | "%d %b, %Y", 93 | "%B %d %Y", 94 | "%B %d, %Y", 95 | "%d %B %Y", 96 | "%d %B, %Y" 97 | ], 98 | "DECIMAL_SEPARATOR": ".", 99 | "FIRST_DAY_OF_WEEK": 0, 100 | "MONTH_DAY_FORMAT": "j \u05d1F", 101 | "NUMBER_GROUPING": 0, 102 | "SHORT_DATETIME_FORMAT": "d/m/Y H:i", 103 | "SHORT_DATE_FORMAT": "d/m/Y", 104 | "THOUSAND_SEPARATOR": ",", 105 | "TIME_FORMAT": "H:i", 106 | "TIME_INPUT_FORMATS": [ 107 | "%H:%M:%S", 108 | "%H:%M:%S.%f", 109 | "%H:%M" 110 | ], 111 | "YEAR_MONTH_FORMAT": "F Y" 112 | }; 113 | 114 | django.get_format = function(format_type) { 115 | var value = django.formats[format_type]; 116 | if (typeof(value) == 'undefined') { 117 | return format_type; 118 | } else { 119 | return value; 120 | } 121 | }; 122 | 123 | /* add to global namespace */ 124 | globals.pluralidx = django.pluralidx; 125 | globals.gettext = django.gettext; 126 | globals.ngettext = django.ngettext; 127 | globals.gettext_noop = django.gettext_noop; 128 | globals.pgettext = django.pgettext; 129 | globals.npgettext = django.npgettext; 130 | globals.interpolate = django.interpolate; 131 | globals.get_format = django.get_format; 132 | 133 | django.jsi18n_initialized = true; 134 | } 135 | 136 | }(this)); 137 | 138 | 139 | } 140 | }; 141 | PollXBlockI18N.init(); 142 | global.PollXBlockI18N = PollXBlockI18N; 143 | }(this)); 144 | -------------------------------------------------------------------------------- /poll/public/js/translations/hi/textjs.js: -------------------------------------------------------------------------------- 1 | 2 | (function(global){ 3 | var PollXBlockI18N = { 4 | init: function() { 5 | 6 | 7 | (function(globals) { 8 | 9 | var django = globals.django || (globals.django = {}); 10 | 11 | 12 | django.pluralidx = function(count) { return (count == 1) ? 0 : 1; }; 13 | 14 | 15 | /* gettext library */ 16 | 17 | django.catalog = django.catalog || {}; 18 | 19 | 20 | if (!django.jsi18n_initialized) { 21 | django.gettext = function(msgid) { 22 | var value = django.catalog[msgid]; 23 | if (typeof(value) == 'undefined') { 24 | return msgid; 25 | } else { 26 | return (typeof(value) == 'string') ? value : value[0]; 27 | } 28 | }; 29 | 30 | django.ngettext = function(singular, plural, count) { 31 | var value = django.catalog[singular]; 32 | if (typeof(value) == 'undefined') { 33 | return (count == 1) ? singular : plural; 34 | } else { 35 | return value.constructor === Array ? value[django.pluralidx(count)] : value; 36 | } 37 | }; 38 | 39 | django.gettext_noop = function(msgid) { return msgid; }; 40 | 41 | django.pgettext = function(context, msgid) { 42 | var value = django.gettext(context + '\x04' + msgid); 43 | if (value.indexOf('\x04') != -1) { 44 | value = msgid; 45 | } 46 | return value; 47 | }; 48 | 49 | django.npgettext = function(context, singular, plural, count) { 50 | var value = django.ngettext(context + '\x04' + singular, context + '\x04' + plural, count); 51 | if (value.indexOf('\x04') != -1) { 52 | value = django.ngettext(singular, plural, count); 53 | } 54 | return value; 55 | }; 56 | 57 | django.interpolate = function(fmt, obj, named) { 58 | if (named) { 59 | return fmt.replace(/%\(\w+\)s/g, function(match){return String(obj[match.slice(2,-2)])}); 60 | } else { 61 | return fmt.replace(/%s/g, function(match){return String(obj.shift())}); 62 | } 63 | }; 64 | 65 | 66 | /* formatting library */ 67 | 68 | django.formats = { 69 | "DATETIME_FORMAT": "N j, Y, P", 70 | "DATETIME_INPUT_FORMATS": [ 71 | "%Y-%m-%d %H:%M:%S", 72 | "%Y-%m-%d %H:%M:%S.%f", 73 | "%Y-%m-%d %H:%M", 74 | "%Y-%m-%d", 75 | "%m/%d/%Y %H:%M:%S", 76 | "%m/%d/%Y %H:%M:%S.%f", 77 | "%m/%d/%Y %H:%M", 78 | "%m/%d/%Y", 79 | "%m/%d/%y %H:%M:%S", 80 | "%m/%d/%y %H:%M:%S.%f", 81 | "%m/%d/%y %H:%M", 82 | "%m/%d/%y" 83 | ], 84 | "DATE_FORMAT": "j F Y", 85 | "DATE_INPUT_FORMATS": [ 86 | "%Y-%m-%d", 87 | "%m/%d/%Y", 88 | "%m/%d/%y", 89 | "%b %d %Y", 90 | "%b %d, %Y", 91 | "%d %b %Y", 92 | "%d %b, %Y", 93 | "%B %d %Y", 94 | "%B %d, %Y", 95 | "%d %B %Y", 96 | "%d %B, %Y" 97 | ], 98 | "DECIMAL_SEPARATOR": ".", 99 | "FIRST_DAY_OF_WEEK": 0, 100 | "MONTH_DAY_FORMAT": "j F", 101 | "NUMBER_GROUPING": 0, 102 | "SHORT_DATETIME_FORMAT": "m/d/Y P", 103 | "SHORT_DATE_FORMAT": "d-m-Y", 104 | "THOUSAND_SEPARATOR": ",", 105 | "TIME_FORMAT": "g:i A", 106 | "TIME_INPUT_FORMATS": [ 107 | "%H:%M:%S", 108 | "%H:%M:%S.%f", 109 | "%H:%M" 110 | ], 111 | "YEAR_MONTH_FORMAT": "F Y" 112 | }; 113 | 114 | django.get_format = function(format_type) { 115 | var value = django.formats[format_type]; 116 | if (typeof(value) == 'undefined') { 117 | return format_type; 118 | } else { 119 | return value; 120 | } 121 | }; 122 | 123 | /* add to global namespace */ 124 | globals.pluralidx = django.pluralidx; 125 | globals.gettext = django.gettext; 126 | globals.ngettext = django.ngettext; 127 | globals.gettext_noop = django.gettext_noop; 128 | globals.pgettext = django.pgettext; 129 | globals.npgettext = django.npgettext; 130 | globals.interpolate = django.interpolate; 131 | globals.get_format = django.get_format; 132 | 133 | django.jsi18n_initialized = true; 134 | } 135 | 136 | }(this)); 137 | 138 | 139 | } 140 | }; 141 | PollXBlockI18N.init(); 142 | global.PollXBlockI18N = PollXBlockI18N; 143 | }(this)); 144 | -------------------------------------------------------------------------------- /poll/public/js/translations/it_IT/textjs.js: -------------------------------------------------------------------------------- 1 | 2 | (function(global){ 3 | var PollXBlockI18N = { 4 | init: function() { 5 | 6 | 7 | (function(globals) { 8 | 9 | var django = globals.django || (globals.django = {}); 10 | 11 | 12 | django.pluralidx = function(n) { 13 | var v=(n > 1); 14 | if (typeof(v) == 'boolean') { 15 | return v ? 1 : 0; 16 | } else { 17 | return v; 18 | } 19 | }; 20 | 21 | 22 | /* gettext library */ 23 | 24 | django.catalog = django.catalog || {}; 25 | 26 | var newcatalog = { 27 | "Answer": "Risposta", 28 | "Delete": "Cancella", 29 | "Feedback": "Feedback", 30 | "Image URL": "URL dell'immagine", 31 | "Image alternative text": "Texte alternatif de l'image", 32 | "Question": "Domanda", 33 | "Results": "Feedback", 34 | "Results gathered from {total} respondent.": [ 35 | "Risposte raccolte da {total} persone", 36 | "Risposte raccolte da {total} persone" 37 | ], 38 | "Submit": "Invia", 39 | "This must have an image URL or text, and can have both. If you add an image, you must also provide an alternative text that describes the image in a way that would allow someone to answer the poll if the image did not load.": "This must have an image URL or text, and can have both. If you add an image, you must also provide an alternative text that describes the image in a way that would allow someone to answer the poll if the image did not load.", 40 | "You can make limited use of Markdown in answer texts, preferably only bold and italics.": "You can make limited use of Markdown in answer texts, preferably only bold and italics.", 41 | "move poll down": "muovi sondaggio ingiù", 42 | "move poll up": "muovi sondaggio all'insù" 43 | }; 44 | for (var key in newcatalog) { 45 | django.catalog[key] = newcatalog[key]; 46 | } 47 | 48 | 49 | if (!django.jsi18n_initialized) { 50 | django.gettext = function(msgid) { 51 | var value = django.catalog[msgid]; 52 | if (typeof(value) == 'undefined') { 53 | return msgid; 54 | } else { 55 | return (typeof(value) == 'string') ? value : value[0]; 56 | } 57 | }; 58 | 59 | django.ngettext = function(singular, plural, count) { 60 | var value = django.catalog[singular]; 61 | if (typeof(value) == 'undefined') { 62 | return (count == 1) ? singular : plural; 63 | } else { 64 | return value.constructor === Array ? value[django.pluralidx(count)] : value; 65 | } 66 | }; 67 | 68 | django.gettext_noop = function(msgid) { return msgid; }; 69 | 70 | django.pgettext = function(context, msgid) { 71 | var value = django.gettext(context + '\x04' + msgid); 72 | if (value.indexOf('\x04') != -1) { 73 | value = msgid; 74 | } 75 | return value; 76 | }; 77 | 78 | django.npgettext = function(context, singular, plural, count) { 79 | var value = django.ngettext(context + '\x04' + singular, context + '\x04' + plural, count); 80 | if (value.indexOf('\x04') != -1) { 81 | value = django.ngettext(singular, plural, count); 82 | } 83 | return value; 84 | }; 85 | 86 | django.interpolate = function(fmt, obj, named) { 87 | if (named) { 88 | return fmt.replace(/%\(\w+\)s/g, function(match){return String(obj[match.slice(2,-2)])}); 89 | } else { 90 | return fmt.replace(/%s/g, function(match){return String(obj.shift())}); 91 | } 92 | }; 93 | 94 | 95 | /* formatting library */ 96 | 97 | django.formats = { 98 | "DATETIME_FORMAT": "j F Y H:i", 99 | "DATETIME_INPUT_FORMATS": [ 100 | "%d/%m/%Y %H:%M:%S", 101 | "%d/%m/%Y %H:%M:%S.%f", 102 | "%d/%m/%Y %H:%M", 103 | "%d/%m/%Y", 104 | "%d.%m.%Y %H:%M:%S", 105 | "%d.%m.%Y %H:%M:%S.%f", 106 | "%d.%m.%Y %H:%M", 107 | "%d.%m.%Y", 108 | "%Y-%m-%d %H:%M:%S", 109 | "%Y-%m-%d %H:%M:%S.%f", 110 | "%Y-%m-%d %H:%M", 111 | "%Y-%m-%d" 112 | ], 113 | "DATE_FORMAT": "j F Y", 114 | "DATE_INPUT_FORMATS": [ 115 | "%d/%m/%Y", 116 | "%d/%m/%y", 117 | "%d.%m.%Y", 118 | "%d.%m.%y", 119 | "%Y-%m-%d" 120 | ], 121 | "DECIMAL_SEPARATOR": ",", 122 | "FIRST_DAY_OF_WEEK": 1, 123 | "MONTH_DAY_FORMAT": "j F", 124 | "NUMBER_GROUPING": 3, 125 | "SHORT_DATETIME_FORMAT": "j N Y H:i", 126 | "SHORT_DATE_FORMAT": "j N Y", 127 | "THOUSAND_SEPARATOR": "\u00a0", 128 | "TIME_FORMAT": "H:i", 129 | "TIME_INPUT_FORMATS": [ 130 | "%H:%M:%S", 131 | "%H:%M:%S.%f", 132 | "%H:%M" 133 | ], 134 | "YEAR_MONTH_FORMAT": "F Y" 135 | }; 136 | 137 | django.get_format = function(format_type) { 138 | var value = django.formats[format_type]; 139 | if (typeof(value) == 'undefined') { 140 | return format_type; 141 | } else { 142 | return value; 143 | } 144 | }; 145 | 146 | /* add to global namespace */ 147 | globals.pluralidx = django.pluralidx; 148 | globals.gettext = django.gettext; 149 | globals.ngettext = django.ngettext; 150 | globals.gettext_noop = django.gettext_noop; 151 | globals.pgettext = django.pgettext; 152 | globals.npgettext = django.npgettext; 153 | globals.interpolate = django.interpolate; 154 | globals.get_format = django.get_format; 155 | 156 | django.jsi18n_initialized = true; 157 | } 158 | 159 | }(this)); 160 | 161 | 162 | } 163 | }; 164 | PollXBlockI18N.init(); 165 | global.PollXBlockI18N = PollXBlockI18N; 166 | }(this)); 167 | -------------------------------------------------------------------------------- /poll/public/js/translations/ja_JP/textjs.js: -------------------------------------------------------------------------------- 1 | 2 | (function(global){ 3 | var PollXBlockI18N = { 4 | init: function() { 5 | 6 | 7 | (function(globals) { 8 | 9 | var django = globals.django || (globals.django = {}); 10 | 11 | 12 | django.pluralidx = function(n) { 13 | var v=0; 14 | if (typeof(v) == 'boolean') { 15 | return v ? 1 : 0; 16 | } else { 17 | return v; 18 | } 19 | }; 20 | 21 | 22 | /* gettext library */ 23 | 24 | django.catalog = django.catalog || {}; 25 | 26 | var newcatalog = { 27 | "Answer": "\u89e3\u7b54", 28 | "Delete": "\u524a\u9664", 29 | "Feedback": "\u30d5\u30a3\u30fc\u30c9\u30d0\u30c3\u30af", 30 | "Image URL": "\u753b\u50cfURL", 31 | "Image alternative text": "\u753b\u50cf\u4ee3\u66ff\u30c6\u30ad\u30b9\u30c8", 32 | "Question": "\u8cea\u554f", 33 | "Results": "\u7d50\u679c", 34 | "Results gathered from {total} respondent.": [ 35 | "\u56de\u7b54\u8005\u304b\u3089\u306e{\u5408\u8a08}\u7d50\u679c\u3092\u96c6\u8a08\u3057\u307e\u3057\u305f\u3002" 36 | ], 37 | "Submit": "\u63d0\u51fa", 38 | "This must have an image URL or text, and can have both. If you add an image, you must also provide an alternative text that describes the image in a way that would allow someone to answer the poll if the image did not load.": "\u3053\u308c\u306b\u306f\u753b\u50cfURL\u307e\u305f\u306f\u30c6\u30ad\u30b9\u30c8\u304c\u5fc5\u8981\u3068\u306a\u308a\u307e\u3059\u304c\u3001\u4e21\u65b9\u6307\u5b9a\u3067\u304d\u307e\u3059\u3002\u753b\u50cf\u3092\u8ffd\u52a0\u3059\u308b\u5834\u5408\u306f\u3001\u753b\u50cf\u304c\u8aad\u307f\u8fbc\u307e\u308c\u306a\u304b\u3063\u305f\u5834\u5408\u306b\u3001\u753b\u50cf\u3092\u8aac\u660e\u3059\u308b\u4ee3\u66ff\u30c6\u30ad\u30b9\u30c8\u3092\u6307\u5b9a\u3057\u3001\u6295\u7968\u306b\u56de\u7b54\u3067\u304d\u308b\u3088\u3046\u306b\u3059\u308b\u5fc5\u8981\u3082\u3042\u308a\u307e\u3059\u3002", 39 | "You can make limited use of Markdown in answer texts, preferably only bold and italics.": "\u56de\u7b54\u30c6\u30ad\u30b9\u30c8\u3067\u306f\u30de\u30fc\u30af\u30c0\u30a6\u30f3\u3092\u9650\u5b9a\u7684\u306b\u4f7f\u7528\u3067\u304d\u307e\u3059\u304c\u3001\u592a\u5b57\u3068\u659c\u4f53\u306e\u307f\u3092\u304a\u52e7\u3081\u3057\u307e\u3059\u3002", 40 | "move poll down": "\u6295\u7968\u3092\u4e0b\u306b\u79fb\u52d5", 41 | "move poll up": "\u6295\u7968\u3092\u4e0a\u306b\u79fb\u52d5" 42 | }; 43 | for (var key in newcatalog) { 44 | django.catalog[key] = newcatalog[key]; 45 | } 46 | 47 | 48 | if (!django.jsi18n_initialized) { 49 | django.gettext = function(msgid) { 50 | var value = django.catalog[msgid]; 51 | if (typeof(value) == 'undefined') { 52 | return msgid; 53 | } else { 54 | return (typeof(value) == 'string') ? value : value[0]; 55 | } 56 | }; 57 | 58 | django.ngettext = function(singular, plural, count) { 59 | var value = django.catalog[singular]; 60 | if (typeof(value) == 'undefined') { 61 | return (count == 1) ? singular : plural; 62 | } else { 63 | return value.constructor === Array ? value[django.pluralidx(count)] : value; 64 | } 65 | }; 66 | 67 | django.gettext_noop = function(msgid) { return msgid; }; 68 | 69 | django.pgettext = function(context, msgid) { 70 | var value = django.gettext(context + '\x04' + msgid); 71 | if (value.indexOf('\x04') != -1) { 72 | value = msgid; 73 | } 74 | return value; 75 | }; 76 | 77 | django.npgettext = function(context, singular, plural, count) { 78 | var value = django.ngettext(context + '\x04' + singular, context + '\x04' + plural, count); 79 | if (value.indexOf('\x04') != -1) { 80 | value = django.ngettext(singular, plural, count); 81 | } 82 | return value; 83 | }; 84 | 85 | django.interpolate = function(fmt, obj, named) { 86 | if (named) { 87 | return fmt.replace(/%\(\w+\)s/g, function(match){return String(obj[match.slice(2,-2)])}); 88 | } else { 89 | return fmt.replace(/%s/g, function(match){return String(obj.shift())}); 90 | } 91 | }; 92 | 93 | 94 | /* formatting library */ 95 | 96 | django.formats = { 97 | "DATETIME_FORMAT": "Y\u5e74n\u6708j\u65e5G:i", 98 | "DATETIME_INPUT_FORMATS": [ 99 | "%Y-%m-%d %H:%M:%S", 100 | "%Y-%m-%d %H:%M:%S.%f", 101 | "%Y-%m-%d %H:%M", 102 | "%Y-%m-%d", 103 | "%m/%d/%Y %H:%M:%S", 104 | "%m/%d/%Y %H:%M:%S.%f", 105 | "%m/%d/%Y %H:%M", 106 | "%m/%d/%Y", 107 | "%m/%d/%y %H:%M:%S", 108 | "%m/%d/%y %H:%M:%S.%f", 109 | "%m/%d/%y %H:%M", 110 | "%m/%d/%y" 111 | ], 112 | "DATE_FORMAT": "Y\u5e74n\u6708j\u65e5", 113 | "DATE_INPUT_FORMATS": [ 114 | "%Y-%m-%d", 115 | "%m/%d/%Y", 116 | "%m/%d/%y", 117 | "%b %d %Y", 118 | "%b %d, %Y", 119 | "%d %b %Y", 120 | "%d %b, %Y", 121 | "%B %d %Y", 122 | "%B %d, %Y", 123 | "%d %B %Y", 124 | "%d %B, %Y" 125 | ], 126 | "DECIMAL_SEPARATOR": ".", 127 | "FIRST_DAY_OF_WEEK": 0, 128 | "MONTH_DAY_FORMAT": "n\u6708j\u65e5", 129 | "NUMBER_GROUPING": 0, 130 | "SHORT_DATETIME_FORMAT": "Y/m/d G:i", 131 | "SHORT_DATE_FORMAT": "Y/m/d", 132 | "THOUSAND_SEPARATOR": ",", 133 | "TIME_FORMAT": "G:i", 134 | "TIME_INPUT_FORMATS": [ 135 | "%H:%M:%S", 136 | "%H:%M:%S.%f", 137 | "%H:%M" 138 | ], 139 | "YEAR_MONTH_FORMAT": "Y\u5e74n\u6708" 140 | }; 141 | 142 | django.get_format = function(format_type) { 143 | var value = django.formats[format_type]; 144 | if (typeof(value) == 'undefined') { 145 | return format_type; 146 | } else { 147 | return value; 148 | } 149 | }; 150 | 151 | /* add to global namespace */ 152 | globals.pluralidx = django.pluralidx; 153 | globals.gettext = django.gettext; 154 | globals.ngettext = django.ngettext; 155 | globals.gettext_noop = django.gettext_noop; 156 | globals.pgettext = django.pgettext; 157 | globals.npgettext = django.npgettext; 158 | globals.interpolate = django.interpolate; 159 | globals.get_format = django.get_format; 160 | 161 | django.jsi18n_initialized = true; 162 | } 163 | 164 | }(this)); 165 | 166 | 167 | } 168 | }; 169 | PollXBlockI18N.init(); 170 | global.PollXBlockI18N = PollXBlockI18N; 171 | }(this)); 172 | -------------------------------------------------------------------------------- /poll/public/js/translations/ko_KR/textjs.js: -------------------------------------------------------------------------------- 1 | 2 | (function(global){ 3 | var PollXBlockI18N = { 4 | init: function() { 5 | 6 | 7 | (function(globals) { 8 | 9 | var django = globals.django || (globals.django = {}); 10 | 11 | 12 | django.pluralidx = function(count) { return (count == 1) ? 0 : 1; }; 13 | 14 | 15 | /* gettext library */ 16 | 17 | django.catalog = django.catalog || {}; 18 | 19 | 20 | if (!django.jsi18n_initialized) { 21 | django.gettext = function(msgid) { 22 | var value = django.catalog[msgid]; 23 | if (typeof(value) == 'undefined') { 24 | return msgid; 25 | } else { 26 | return (typeof(value) == 'string') ? value : value[0]; 27 | } 28 | }; 29 | 30 | django.ngettext = function(singular, plural, count) { 31 | var value = django.catalog[singular]; 32 | if (typeof(value) == 'undefined') { 33 | return (count == 1) ? singular : plural; 34 | } else { 35 | return value.constructor === Array ? value[django.pluralidx(count)] : value; 36 | } 37 | }; 38 | 39 | django.gettext_noop = function(msgid) { return msgid; }; 40 | 41 | django.pgettext = function(context, msgid) { 42 | var value = django.gettext(context + '\x04' + msgid); 43 | if (value.indexOf('\x04') != -1) { 44 | value = msgid; 45 | } 46 | return value; 47 | }; 48 | 49 | django.npgettext = function(context, singular, plural, count) { 50 | var value = django.ngettext(context + '\x04' + singular, context + '\x04' + plural, count); 51 | if (value.indexOf('\x04') != -1) { 52 | value = django.ngettext(singular, plural, count); 53 | } 54 | return value; 55 | }; 56 | 57 | django.interpolate = function(fmt, obj, named) { 58 | if (named) { 59 | return fmt.replace(/%\(\w+\)s/g, function(match){return String(obj[match.slice(2,-2)])}); 60 | } else { 61 | return fmt.replace(/%s/g, function(match){return String(obj.shift())}); 62 | } 63 | }; 64 | 65 | 66 | /* formatting library */ 67 | 68 | django.formats = { 69 | "DATETIME_FORMAT": "Y\ub144 n\uc6d4 j\uc77c g:i A", 70 | "DATETIME_INPUT_FORMATS": [ 71 | "%Y-%m-%d %H:%M:%S", 72 | "%Y-%m-%d %H:%M:%S.%f", 73 | "%Y-%m-%d %H:%M", 74 | "%Y-%m-%d", 75 | "%m/%d/%Y %H:%M:%S", 76 | "%m/%d/%Y %H:%M:%S.%f", 77 | "%m/%d/%Y %H:%M", 78 | "%m/%d/%Y", 79 | "%m/%d/%y %H:%M:%S", 80 | "%m/%d/%y %H:%M:%S.%f", 81 | "%m/%d/%y %H:%M", 82 | "%m/%d/%y", 83 | "%Y\ub144 %m\uc6d4 %d\uc77c %H\uc2dc %M\ubd84 %S\ucd08", 84 | "%Y\ub144 %m\uc6d4 %d\uc77c %H\uc2dc %M\ubd84" 85 | ], 86 | "DATE_FORMAT": "Y\ub144 n\uc6d4 j\uc77c", 87 | "DATE_INPUT_FORMATS": [ 88 | "%Y-%m-%d", 89 | "%m/%d/%Y", 90 | "%m/%d/%y", 91 | "%Y\ub144 %m\uc6d4 %d\uc77c" 92 | ], 93 | "DECIMAL_SEPARATOR": ".", 94 | "FIRST_DAY_OF_WEEK": 0, 95 | "MONTH_DAY_FORMAT": "n\uc6d4 j\uc77c", 96 | "NUMBER_GROUPING": 3, 97 | "SHORT_DATETIME_FORMAT": "Y-n-j H:i", 98 | "SHORT_DATE_FORMAT": "Y-n-j.", 99 | "THOUSAND_SEPARATOR": ",", 100 | "TIME_FORMAT": "A g:i", 101 | "TIME_INPUT_FORMATS": [ 102 | "%H:%M:%S", 103 | "%H:%M:%S.%f", 104 | "%H:%M", 105 | "%H\uc2dc %M\ubd84 %S\ucd08", 106 | "%H\uc2dc %M\ubd84" 107 | ], 108 | "YEAR_MONTH_FORMAT": "Y\ub144 n\uc6d4" 109 | }; 110 | 111 | django.get_format = function(format_type) { 112 | var value = django.formats[format_type]; 113 | if (typeof(value) == 'undefined') { 114 | return format_type; 115 | } else { 116 | return value; 117 | } 118 | }; 119 | 120 | /* add to global namespace */ 121 | globals.pluralidx = django.pluralidx; 122 | globals.gettext = django.gettext; 123 | globals.ngettext = django.ngettext; 124 | globals.gettext_noop = django.gettext_noop; 125 | globals.pgettext = django.pgettext; 126 | globals.npgettext = django.npgettext; 127 | globals.interpolate = django.interpolate; 128 | globals.get_format = django.get_format; 129 | 130 | django.jsi18n_initialized = true; 131 | } 132 | 133 | }(this)); 134 | 135 | 136 | } 137 | }; 138 | PollXBlockI18N.init(); 139 | global.PollXBlockI18N = PollXBlockI18N; 140 | }(this)); 141 | -------------------------------------------------------------------------------- /poll/public/js/translations/pl/textjs.js: -------------------------------------------------------------------------------- 1 | 2 | (function(global){ 3 | var PollXBlockI18N = { 4 | init: function() { 5 | 6 | 7 | (function(globals) { 8 | 9 | var django = globals.django || (globals.django = {}); 10 | 11 | 12 | django.pluralidx = function(count) { return (count == 1) ? 0 : 1; }; 13 | 14 | 15 | /* gettext library */ 16 | 17 | django.catalog = django.catalog || {}; 18 | 19 | 20 | if (!django.jsi18n_initialized) { 21 | django.gettext = function(msgid) { 22 | var value = django.catalog[msgid]; 23 | if (typeof(value) == 'undefined') { 24 | return msgid; 25 | } else { 26 | return (typeof(value) == 'string') ? value : value[0]; 27 | } 28 | }; 29 | 30 | django.ngettext = function(singular, plural, count) { 31 | var value = django.catalog[singular]; 32 | if (typeof(value) == 'undefined') { 33 | return (count == 1) ? singular : plural; 34 | } else { 35 | return value.constructor === Array ? value[django.pluralidx(count)] : value; 36 | } 37 | }; 38 | 39 | django.gettext_noop = function(msgid) { return msgid; }; 40 | 41 | django.pgettext = function(context, msgid) { 42 | var value = django.gettext(context + '\x04' + msgid); 43 | if (value.indexOf('\x04') != -1) { 44 | value = msgid; 45 | } 46 | return value; 47 | }; 48 | 49 | django.npgettext = function(context, singular, plural, count) { 50 | var value = django.ngettext(context + '\x04' + singular, context + '\x04' + plural, count); 51 | if (value.indexOf('\x04') != -1) { 52 | value = django.ngettext(singular, plural, count); 53 | } 54 | return value; 55 | }; 56 | 57 | django.interpolate = function(fmt, obj, named) { 58 | if (named) { 59 | return fmt.replace(/%\(\w+\)s/g, function(match){return String(obj[match.slice(2,-2)])}); 60 | } else { 61 | return fmt.replace(/%s/g, function(match){return String(obj.shift())}); 62 | } 63 | }; 64 | 65 | 66 | /* formatting library */ 67 | 68 | django.formats = { 69 | "DATETIME_FORMAT": "j E Y H:i", 70 | "DATETIME_INPUT_FORMATS": [ 71 | "%d.%m.%Y %H:%M:%S", 72 | "%d.%m.%Y %H:%M:%S.%f", 73 | "%d.%m.%Y %H:%M", 74 | "%d.%m.%Y", 75 | "%Y-%m-%d %H:%M:%S", 76 | "%Y-%m-%d %H:%M:%S.%f", 77 | "%Y-%m-%d %H:%M", 78 | "%Y-%m-%d" 79 | ], 80 | "DATE_FORMAT": "j E Y", 81 | "DATE_INPUT_FORMATS": [ 82 | "%d.%m.%Y", 83 | "%d.%m.%y", 84 | "%y-%m-%d", 85 | "%Y-%m-%d" 86 | ], 87 | "DECIMAL_SEPARATOR": ",", 88 | "FIRST_DAY_OF_WEEK": 1, 89 | "MONTH_DAY_FORMAT": "j E", 90 | "NUMBER_GROUPING": 3, 91 | "SHORT_DATETIME_FORMAT": "d-m-Y H:i", 92 | "SHORT_DATE_FORMAT": "d-m-Y", 93 | "THOUSAND_SEPARATOR": "\u00a0", 94 | "TIME_FORMAT": "H:i", 95 | "TIME_INPUT_FORMATS": [ 96 | "%H:%M:%S", 97 | "%H:%M:%S.%f", 98 | "%H:%M" 99 | ], 100 | "YEAR_MONTH_FORMAT": "F Y" 101 | }; 102 | 103 | django.get_format = function(format_type) { 104 | var value = django.formats[format_type]; 105 | if (typeof(value) == 'undefined') { 106 | return format_type; 107 | } else { 108 | return value; 109 | } 110 | }; 111 | 112 | /* add to global namespace */ 113 | globals.pluralidx = django.pluralidx; 114 | globals.gettext = django.gettext; 115 | globals.ngettext = django.ngettext; 116 | globals.gettext_noop = django.gettext_noop; 117 | globals.pgettext = django.pgettext; 118 | globals.npgettext = django.npgettext; 119 | globals.interpolate = django.interpolate; 120 | globals.get_format = django.get_format; 121 | 122 | django.jsi18n_initialized = true; 123 | } 124 | 125 | }(this)); 126 | 127 | 128 | } 129 | }; 130 | PollXBlockI18N.init(); 131 | global.PollXBlockI18N = PollXBlockI18N; 132 | }(this)); 133 | -------------------------------------------------------------------------------- /poll/public/js/translations/pt_BR/textjs.js: -------------------------------------------------------------------------------- 1 | 2 | (function(global){ 3 | var PollXBlockI18N = { 4 | init: function() { 5 | 6 | 7 | (function(globals) { 8 | 9 | var django = globals.django || (globals.django = {}); 10 | 11 | 12 | django.pluralidx = function(n) { 13 | var v=(n > 1); 14 | if (typeof(v) == 'boolean') { 15 | return v ? 1 : 0; 16 | } else { 17 | return v; 18 | } 19 | }; 20 | 21 | 22 | /* gettext library */ 23 | 24 | django.catalog = django.catalog || {}; 25 | 26 | var newcatalog = { 27 | "Answer": "Resposta", 28 | "Submit": "Enviar", 29 | "This must have an image URL or text, and can have both. If you add an image, you must also provide an alternative text that describes the image in a way that would allow someone to answer the poll if the image did not load.": "Uma imagem de URL ou texto, ou ambos, devem ser adicionados. Caso uma imagem seja adicionada, \u00e9 necess\u00e1rio que se adicione um texto alternativo descrevendo a imagem para permitir que usu\u00e1rios possam responder \u00e0 enquete caso a imagem n\u00e3o carregue.", 30 | "You can make limited use of Markdown in answer texts, preferably only bold and italics.": "Voc\u00ea pode fazer uso limitado do Markdown nas respostas de textos, de prefer\u00eancia negrito e it\u00e1lico. " 31 | }; 32 | for (var key in newcatalog) { 33 | django.catalog[key] = newcatalog[key]; 34 | } 35 | 36 | 37 | if (!django.jsi18n_initialized) { 38 | django.gettext = function(msgid) { 39 | var value = django.catalog[msgid]; 40 | if (typeof(value) == 'undefined') { 41 | return msgid; 42 | } else { 43 | return (typeof(value) == 'string') ? value : value[0]; 44 | } 45 | }; 46 | 47 | django.ngettext = function(singular, plural, count) { 48 | var value = django.catalog[singular]; 49 | if (typeof(value) == 'undefined') { 50 | return (count == 1) ? singular : plural; 51 | } else { 52 | return value.constructor === Array ? value[django.pluralidx(count)] : value; 53 | } 54 | }; 55 | 56 | django.gettext_noop = function(msgid) { return msgid; }; 57 | 58 | django.pgettext = function(context, msgid) { 59 | var value = django.gettext(context + '\x04' + msgid); 60 | if (value.indexOf('\x04') != -1) { 61 | value = msgid; 62 | } 63 | return value; 64 | }; 65 | 66 | django.npgettext = function(context, singular, plural, count) { 67 | var value = django.ngettext(context + '\x04' + singular, context + '\x04' + plural, count); 68 | if (value.indexOf('\x04') != -1) { 69 | value = django.ngettext(singular, plural, count); 70 | } 71 | return value; 72 | }; 73 | 74 | django.interpolate = function(fmt, obj, named) { 75 | if (named) { 76 | return fmt.replace(/%\(\w+\)s/g, function(match){return String(obj[match.slice(2,-2)])}); 77 | } else { 78 | return fmt.replace(/%s/g, function(match){return String(obj.shift())}); 79 | } 80 | }; 81 | 82 | 83 | /* formatting library */ 84 | 85 | django.formats = { 86 | "DATETIME_FORMAT": "j \\d\\e F \\d\\e Y \u00e0\\s H:i", 87 | "DATETIME_INPUT_FORMATS": [ 88 | "%d/%m/%Y %H:%M:%S", 89 | "%d/%m/%Y %H:%M:%S.%f", 90 | "%d/%m/%Y %H:%M", 91 | "%d/%m/%Y", 92 | "%d/%m/%y %H:%M:%S", 93 | "%d/%m/%y %H:%M:%S.%f", 94 | "%d/%m/%y %H:%M", 95 | "%d/%m/%y", 96 | "%Y-%m-%d %H:%M:%S", 97 | "%Y-%m-%d %H:%M:%S.%f", 98 | "%Y-%m-%d %H:%M", 99 | "%Y-%m-%d" 100 | ], 101 | "DATE_FORMAT": "j \\d\\e F \\d\\e Y", 102 | "DATE_INPUT_FORMATS": [ 103 | "%d/%m/%Y", 104 | "%d/%m/%y", 105 | "%Y-%m-%d" 106 | ], 107 | "DECIMAL_SEPARATOR": ",", 108 | "FIRST_DAY_OF_WEEK": 0, 109 | "MONTH_DAY_FORMAT": "j \\d\\e F", 110 | "NUMBER_GROUPING": 3, 111 | "SHORT_DATETIME_FORMAT": "d/m/Y H:i", 112 | "SHORT_DATE_FORMAT": "d/m/Y", 113 | "THOUSAND_SEPARATOR": ".", 114 | "TIME_FORMAT": "H:i", 115 | "TIME_INPUT_FORMATS": [ 116 | "%H:%M:%S", 117 | "%H:%M:%S.%f", 118 | "%H:%M" 119 | ], 120 | "YEAR_MONTH_FORMAT": "F \\d\\e Y" 121 | }; 122 | 123 | django.get_format = function(format_type) { 124 | var value = django.formats[format_type]; 125 | if (typeof(value) == 'undefined') { 126 | return format_type; 127 | } else { 128 | return value; 129 | } 130 | }; 131 | 132 | /* add to global namespace */ 133 | globals.pluralidx = django.pluralidx; 134 | globals.gettext = django.gettext; 135 | globals.ngettext = django.ngettext; 136 | globals.gettext_noop = django.gettext_noop; 137 | globals.pgettext = django.pgettext; 138 | globals.npgettext = django.npgettext; 139 | globals.interpolate = django.interpolate; 140 | globals.get_format = django.get_format; 141 | 142 | django.jsi18n_initialized = true; 143 | } 144 | 145 | }(this)); 146 | 147 | 148 | } 149 | }; 150 | PollXBlockI18N.init(); 151 | global.PollXBlockI18N = PollXBlockI18N; 152 | }(this)); 153 | -------------------------------------------------------------------------------- /poll/public/js/translations/pt_PT/textjs.js: -------------------------------------------------------------------------------- 1 | 2 | (function(global){ 3 | var PollXBlockI18N = { 4 | init: function() { 5 | 6 | 7 | (function(globals) { 8 | 9 | var django = globals.django || (globals.django = {}); 10 | 11 | 12 | django.pluralidx = function(n) { 13 | var v=(n != 1); 14 | if (typeof(v) == 'boolean') { 15 | return v ? 1 : 0; 16 | } else { 17 | return v; 18 | } 19 | }; 20 | 21 | 22 | /* gettext library */ 23 | 24 | django.catalog = django.catalog || {}; 25 | 26 | var newcatalog = { 27 | "Answer": "Resposta", 28 | "Delete": "Eliminar", 29 | "Feedback": "Coment\u00e1rio", 30 | "Image URL": "URL da Imagem", 31 | "Image alternative text": "Texto alternativo da imagem", 32 | "Question": "Pergunta", 33 | "Results": "Resultados", 34 | "Results gathered from {total} respondent.": [ 35 | "Resultados recolhidos de {total} respondente.", 36 | "Resultados recolhidos de {total} respondentes." 37 | ], 38 | "Submit": "Submeter", 39 | "This must have an image URL or text, and can have both. If you add an image, you must also provide an alternative text that describes the image in a way that would allow someone to answer the poll if the image did not load.": "Este deve ter um URL ou texto de imagem, e pode ter ambos. Se adicionar uma imagem, deve tamb\u00e9m fornecer um texto alternativo que descreva a imagem de uma forma que permita a algu\u00e9m responder \u00e0 sondagem se a imagem n\u00e3o for carregada.", 40 | "You can make limited use of Markdown in answer texts, preferably only bold and italics.": "Pode fazer um uso limitado do Markdown nos textos de resposta, de prefer\u00eancia apenas em negrito e it\u00e1lico.", 41 | "move poll down": "mover sondagem para baixo", 42 | "move poll up": "mover sondagem para cima" 43 | }; 44 | for (var key in newcatalog) { 45 | django.catalog[key] = newcatalog[key]; 46 | } 47 | 48 | 49 | if (!django.jsi18n_initialized) { 50 | django.gettext = function(msgid) { 51 | var value = django.catalog[msgid]; 52 | if (typeof(value) == 'undefined') { 53 | return msgid; 54 | } else { 55 | return (typeof(value) == 'string') ? value : value[0]; 56 | } 57 | }; 58 | 59 | django.ngettext = function(singular, plural, count) { 60 | var value = django.catalog[singular]; 61 | if (typeof(value) == 'undefined') { 62 | return (count == 1) ? singular : plural; 63 | } else { 64 | return value.constructor === Array ? value[django.pluralidx(count)] : value; 65 | } 66 | }; 67 | 68 | django.gettext_noop = function(msgid) { return msgid; }; 69 | 70 | django.pgettext = function(context, msgid) { 71 | var value = django.gettext(context + '\x04' + msgid); 72 | if (value.indexOf('\x04') != -1) { 73 | value = msgid; 74 | } 75 | return value; 76 | }; 77 | 78 | django.npgettext = function(context, singular, plural, count) { 79 | var value = django.ngettext(context + '\x04' + singular, context + '\x04' + plural, count); 80 | if (value.indexOf('\x04') != -1) { 81 | value = django.ngettext(singular, plural, count); 82 | } 83 | return value; 84 | }; 85 | 86 | django.interpolate = function(fmt, obj, named) { 87 | if (named) { 88 | return fmt.replace(/%\(\w+\)s/g, function(match){return String(obj[match.slice(2,-2)])}); 89 | } else { 90 | return fmt.replace(/%s/g, function(match){return String(obj.shift())}); 91 | } 92 | }; 93 | 94 | 95 | /* formatting library */ 96 | 97 | django.formats = { 98 | "DATETIME_FORMAT": "j \\d\\e F \\d\\e Y \u00e0\\s H:i", 99 | "DATETIME_INPUT_FORMATS": [ 100 | "%Y-%m-%d %H:%M:%S", 101 | "%Y-%m-%d %H:%M:%S.%f", 102 | "%Y-%m-%d %H:%M", 103 | "%Y-%m-%d", 104 | "%d/%m/%Y %H:%M:%S", 105 | "%d/%m/%Y %H:%M:%S.%f", 106 | "%d/%m/%Y %H:%M", 107 | "%d/%m/%Y", 108 | "%d/%m/%y %H:%M:%S", 109 | "%d/%m/%y %H:%M:%S.%f", 110 | "%d/%m/%y %H:%M", 111 | "%d/%m/%y" 112 | ], 113 | "DATE_FORMAT": "j \\d\\e F \\d\\e Y", 114 | "DATE_INPUT_FORMATS": [ 115 | "%Y-%m-%d", 116 | "%d/%m/%Y", 117 | "%d/%m/%y" 118 | ], 119 | "DECIMAL_SEPARATOR": ",", 120 | "FIRST_DAY_OF_WEEK": 0, 121 | "MONTH_DAY_FORMAT": "j \\d\\e F", 122 | "NUMBER_GROUPING": 3, 123 | "SHORT_DATETIME_FORMAT": "d/m/Y H:i", 124 | "SHORT_DATE_FORMAT": "d/m/Y", 125 | "THOUSAND_SEPARATOR": ".", 126 | "TIME_FORMAT": "H:i", 127 | "TIME_INPUT_FORMATS": [ 128 | "%H:%M:%S", 129 | "%H:%M:%S.%f", 130 | "%H:%M" 131 | ], 132 | "YEAR_MONTH_FORMAT": "F \\d\\e Y" 133 | }; 134 | 135 | django.get_format = function(format_type) { 136 | var value = django.formats[format_type]; 137 | if (typeof(value) == 'undefined') { 138 | return format_type; 139 | } else { 140 | return value; 141 | } 142 | }; 143 | 144 | /* add to global namespace */ 145 | globals.pluralidx = django.pluralidx; 146 | globals.gettext = django.gettext; 147 | globals.ngettext = django.ngettext; 148 | globals.gettext_noop = django.gettext_noop; 149 | globals.pgettext = django.pgettext; 150 | globals.npgettext = django.npgettext; 151 | globals.interpolate = django.interpolate; 152 | globals.get_format = django.get_format; 153 | 154 | django.jsi18n_initialized = true; 155 | } 156 | 157 | }(this)); 158 | 159 | 160 | } 161 | }; 162 | PollXBlockI18N.init(); 163 | global.PollXBlockI18N = PollXBlockI18N; 164 | }(this)); 165 | -------------------------------------------------------------------------------- /poll/public/js/translations/ru/textjs.js: -------------------------------------------------------------------------------- 1 | 2 | (function(global){ 3 | var PollXBlockI18N = { 4 | init: function() { 5 | 6 | 7 | (function(globals) { 8 | 9 | var django = globals.django || (globals.django = {}); 10 | 11 | 12 | django.pluralidx = function(count) { return (count == 1) ? 0 : 1; }; 13 | 14 | 15 | /* gettext library */ 16 | 17 | django.catalog = django.catalog || {}; 18 | 19 | 20 | if (!django.jsi18n_initialized) { 21 | django.gettext = function(msgid) { 22 | var value = django.catalog[msgid]; 23 | if (typeof(value) == 'undefined') { 24 | return msgid; 25 | } else { 26 | return (typeof(value) == 'string') ? value : value[0]; 27 | } 28 | }; 29 | 30 | django.ngettext = function(singular, plural, count) { 31 | var value = django.catalog[singular]; 32 | if (typeof(value) == 'undefined') { 33 | return (count == 1) ? singular : plural; 34 | } else { 35 | return value.constructor === Array ? value[django.pluralidx(count)] : value; 36 | } 37 | }; 38 | 39 | django.gettext_noop = function(msgid) { return msgid; }; 40 | 41 | django.pgettext = function(context, msgid) { 42 | var value = django.gettext(context + '\x04' + msgid); 43 | if (value.indexOf('\x04') != -1) { 44 | value = msgid; 45 | } 46 | return value; 47 | }; 48 | 49 | django.npgettext = function(context, singular, plural, count) { 50 | var value = django.ngettext(context + '\x04' + singular, context + '\x04' + plural, count); 51 | if (value.indexOf('\x04') != -1) { 52 | value = django.ngettext(singular, plural, count); 53 | } 54 | return value; 55 | }; 56 | 57 | django.interpolate = function(fmt, obj, named) { 58 | if (named) { 59 | return fmt.replace(/%\(\w+\)s/g, function(match){return String(obj[match.slice(2,-2)])}); 60 | } else { 61 | return fmt.replace(/%s/g, function(match){return String(obj.shift())}); 62 | } 63 | }; 64 | 65 | 66 | /* formatting library */ 67 | 68 | django.formats = { 69 | "DATETIME_FORMAT": "j E Y \u0433. G:i", 70 | "DATETIME_INPUT_FORMATS": [ 71 | "%d.%m.%Y %H:%M:%S", 72 | "%d.%m.%Y %H:%M:%S.%f", 73 | "%d.%m.%Y %H:%M", 74 | "%d.%m.%Y", 75 | "%d.%m.%y %H:%M:%S", 76 | "%d.%m.%y %H:%M:%S.%f", 77 | "%d.%m.%y %H:%M", 78 | "%d.%m.%y", 79 | "%Y-%m-%d %H:%M:%S", 80 | "%Y-%m-%d %H:%M:%S.%f", 81 | "%Y-%m-%d %H:%M", 82 | "%Y-%m-%d" 83 | ], 84 | "DATE_FORMAT": "j E Y \u0433.", 85 | "DATE_INPUT_FORMATS": [ 86 | "%d.%m.%Y", 87 | "%d.%m.%y", 88 | "%Y-%m-%d" 89 | ], 90 | "DECIMAL_SEPARATOR": ",", 91 | "FIRST_DAY_OF_WEEK": 1, 92 | "MONTH_DAY_FORMAT": "j F", 93 | "NUMBER_GROUPING": 3, 94 | "SHORT_DATETIME_FORMAT": "d.m.Y H:i", 95 | "SHORT_DATE_FORMAT": "d.m.Y", 96 | "THOUSAND_SEPARATOR": "\u00a0", 97 | "TIME_FORMAT": "G:i", 98 | "TIME_INPUT_FORMATS": [ 99 | "%H:%M:%S", 100 | "%H:%M:%S.%f", 101 | "%H:%M" 102 | ], 103 | "YEAR_MONTH_FORMAT": "F Y \u0433." 104 | }; 105 | 106 | django.get_format = function(format_type) { 107 | var value = django.formats[format_type]; 108 | if (typeof(value) == 'undefined') { 109 | return format_type; 110 | } else { 111 | return value; 112 | } 113 | }; 114 | 115 | /* add to global namespace */ 116 | globals.pluralidx = django.pluralidx; 117 | globals.gettext = django.gettext; 118 | globals.ngettext = django.ngettext; 119 | globals.gettext_noop = django.gettext_noop; 120 | globals.pgettext = django.pgettext; 121 | globals.npgettext = django.npgettext; 122 | globals.interpolate = django.interpolate; 123 | globals.get_format = django.get_format; 124 | 125 | django.jsi18n_initialized = true; 126 | } 127 | 128 | }(this)); 129 | 130 | 131 | } 132 | }; 133 | PollXBlockI18N.init(); 134 | global.PollXBlockI18N = PollXBlockI18N; 135 | }(this)); 136 | -------------------------------------------------------------------------------- /poll/public/js/translations/zh_CN/textjs.js: -------------------------------------------------------------------------------- 1 | 2 | (function(global){ 3 | var PollXBlockI18N = { 4 | init: function() { 5 | 6 | 7 | (function(globals) { 8 | 9 | var django = globals.django || (globals.django = {}); 10 | 11 | 12 | django.pluralidx = function(count) { return (count == 1) ? 0 : 1; }; 13 | 14 | 15 | /* gettext library */ 16 | 17 | django.catalog = django.catalog || {}; 18 | 19 | 20 | if (!django.jsi18n_initialized) { 21 | django.gettext = function(msgid) { 22 | var value = django.catalog[msgid]; 23 | if (typeof(value) == 'undefined') { 24 | return msgid; 25 | } else { 26 | return (typeof(value) == 'string') ? value : value[0]; 27 | } 28 | }; 29 | 30 | django.ngettext = function(singular, plural, count) { 31 | var value = django.catalog[singular]; 32 | if (typeof(value) == 'undefined') { 33 | return (count == 1) ? singular : plural; 34 | } else { 35 | return value.constructor === Array ? value[django.pluralidx(count)] : value; 36 | } 37 | }; 38 | 39 | django.gettext_noop = function(msgid) { return msgid; }; 40 | 41 | django.pgettext = function(context, msgid) { 42 | var value = django.gettext(context + '\x04' + msgid); 43 | if (value.indexOf('\x04') != -1) { 44 | value = msgid; 45 | } 46 | return value; 47 | }; 48 | 49 | django.npgettext = function(context, singular, plural, count) { 50 | var value = django.ngettext(context + '\x04' + singular, context + '\x04' + plural, count); 51 | if (value.indexOf('\x04') != -1) { 52 | value = django.ngettext(singular, plural, count); 53 | } 54 | return value; 55 | }; 56 | 57 | django.interpolate = function(fmt, obj, named) { 58 | if (named) { 59 | return fmt.replace(/%\(\w+\)s/g, function(match){return String(obj[match.slice(2,-2)])}); 60 | } else { 61 | return fmt.replace(/%s/g, function(match){return String(obj.shift())}); 62 | } 63 | }; 64 | 65 | 66 | /* formatting library */ 67 | 68 | django.formats = { 69 | "DATETIME_FORMAT": "N j, Y, P", 70 | "DATETIME_INPUT_FORMATS": [ 71 | "%Y-%m-%d %H:%M:%S", 72 | "%Y-%m-%d %H:%M:%S.%f", 73 | "%Y-%m-%d %H:%M", 74 | "%Y-%m-%d", 75 | "%m/%d/%Y %H:%M:%S", 76 | "%m/%d/%Y %H:%M:%S.%f", 77 | "%m/%d/%Y %H:%M", 78 | "%m/%d/%Y", 79 | "%m/%d/%y %H:%M:%S", 80 | "%m/%d/%y %H:%M:%S.%f", 81 | "%m/%d/%y %H:%M", 82 | "%m/%d/%y" 83 | ], 84 | "DATE_FORMAT": "N j, Y", 85 | "DATE_INPUT_FORMATS": [ 86 | "%Y-%m-%d", 87 | "%m/%d/%Y", 88 | "%m/%d/%y", 89 | "%b %d %Y", 90 | "%b %d, %Y", 91 | "%d %b %Y", 92 | "%d %b, %Y", 93 | "%B %d %Y", 94 | "%B %d, %Y", 95 | "%d %B %Y", 96 | "%d %B, %Y" 97 | ], 98 | "DECIMAL_SEPARATOR": ".", 99 | "FIRST_DAY_OF_WEEK": 0, 100 | "MONTH_DAY_FORMAT": "F j", 101 | "NUMBER_GROUPING": 0, 102 | "SHORT_DATETIME_FORMAT": "m/d/Y P", 103 | "SHORT_DATE_FORMAT": "m/d/Y", 104 | "THOUSAND_SEPARATOR": ",", 105 | "TIME_FORMAT": "P", 106 | "TIME_INPUT_FORMATS": [ 107 | "%H:%M:%S", 108 | "%H:%M:%S.%f", 109 | "%H:%M" 110 | ], 111 | "YEAR_MONTH_FORMAT": "F Y" 112 | }; 113 | 114 | django.get_format = function(format_type) { 115 | var value = django.formats[format_type]; 116 | if (typeof(value) == 'undefined') { 117 | return format_type; 118 | } else { 119 | return value; 120 | } 121 | }; 122 | 123 | /* add to global namespace */ 124 | globals.pluralidx = django.pluralidx; 125 | globals.gettext = django.gettext; 126 | globals.ngettext = django.ngettext; 127 | globals.gettext_noop = django.gettext_noop; 128 | globals.pgettext = django.pgettext; 129 | globals.npgettext = django.npgettext; 130 | globals.interpolate = django.interpolate; 131 | globals.get_format = django.get_format; 132 | 133 | django.jsi18n_initialized = true; 134 | } 135 | 136 | }(this)); 137 | 138 | 139 | } 140 | }; 141 | PollXBlockI18N.init(); 142 | global.PollXBlockI18N = PollXBlockI18N; 143 | }(this)); 144 | -------------------------------------------------------------------------------- /poll/settings.py: -------------------------------------------------------------------------------- 1 | """ 2 | Django settings for the xblock-poll project. 3 | For more information on this file, see 4 | https://docs.djangoproject.com/en/1.11/topics/settings/ 5 | For the full list of settings and their values, see 6 | https://docs.djangoproject.com/en/1.11/ref/settings/ 7 | """ 8 | 9 | # Build paths inside the project like this: os.path.join(BASE_DIR, ...) 10 | from __future__ import absolute_import 11 | import os 12 | import yaml 13 | 14 | BASE_DIR = os.path.dirname(os.path.dirname(__file__)) 15 | 16 | 17 | # Quick-start development settings - unsuitable for production 18 | # See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/ 19 | 20 | # SECURITY WARNING: keep the secret key used in production secret! 21 | # This is just a container for running tests, it's okay to allow it to be 22 | # defaulted here if not present in environment settings 23 | SECRET_KEY = os.environ.get('SECRET_KEY', '",cB3Jr.?xu[x_Ci]!%HP>#^AVmWi@r/W3u,w?pY+~J!R>;WN+,3}Sb{K=Jp~;&k') 24 | 25 | # SECURITY WARNING: don't run with debug turned on in production! 26 | # This is just a container for running tests 27 | DEBUG = True 28 | 29 | TEMPLATE_DEBUG = True 30 | 31 | ALLOWED_HOSTS = [] 32 | 33 | 34 | # Application definition 35 | 36 | INSTALLED_APPS = ( 37 | 'statici18n', 38 | 'poll', 39 | ) 40 | 41 | # Internationalization 42 | # https://docs.djangoproject.com/en/1.6/topics/i18n/ 43 | 44 | LANGUAGE_CODE = 'en-us' 45 | 46 | TIME_ZONE = 'UTC' 47 | 48 | USE_I18N = True 49 | 50 | USE_L10N = True 51 | 52 | USE_TZ = True 53 | 54 | 55 | # Static files (CSS, JavaScript, Images) 56 | # https://docs.djangoproject.com/en/1.6/howto/static-files/ 57 | 58 | STATIC_URL = '/static/' 59 | 60 | LOCALE_PATHS = [ 61 | os.path.join(BASE_DIR, 'poll/translations'), 62 | ] 63 | 64 | # statici18n 65 | # http://django-statici18n.readthedocs.io/en/latest/settings.html 66 | 67 | with open(os.path.join(BASE_DIR, 'poll/translations/config.yaml'), 'r') as locale_config_file: 68 | locale_config = yaml.load(locale_config_file, Loader=yaml.SafeLoader) 69 | 70 | LANGUAGES = [ 71 | (code, code,) 72 | for code in locale_config['locales'] + locale_config['dummy_locales'] 73 | ] 74 | 75 | STATICI18N_DOMAIN = 'textjs' 76 | 77 | # `PollI18N` might collide with other modules, using `PollXBlockI18N` to be more explicit 78 | STATICI18N_NAMESPACE = 'PollXBlockI18N' 79 | STATICI18N_PACKAGES = ( 80 | 'poll', 81 | ) 82 | STATICI18N_ROOT = 'poll/public/js' 83 | STATICI18N_OUTPUT_DIR = 'translations' 84 | -------------------------------------------------------------------------------- /poll/tasks.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | import time 3 | 4 | from celery import current_app # pylint: disable=import-error 5 | 6 | from lms.djangoapps.instructor_task.models import ReportStore # pylint: disable=import-error 7 | from opaque_keys.edx.keys import CourseKey, UsageKey # pylint: disable=import-error 8 | from xmodule.modulestore.django import modulestore # pylint: disable=import-error 9 | 10 | 11 | @current_app.task(name='poll.tasks.export_csv_data') 12 | def export_csv_data(block_id, course_id): 13 | """ 14 | Exports student answers to all supported questions to a CSV file. 15 | """ 16 | 17 | src_block = modulestore().get_item(UsageKey.from_string(block_id)) 18 | 19 | start_timestamp = time.time() 20 | course_key = CourseKey.from_string(course_id) 21 | 22 | filename = src_block.get_filename() 23 | 24 | report_store = ReportStore.from_config(config_name='GRADES_DOWNLOAD') 25 | report_store.store_rows(course_key, filename, src_block.prepare_data()) 26 | 27 | generation_time_s = time.time() - start_timestamp 28 | 29 | return { 30 | "error": None, 31 | "report_filename": filename, 32 | "start_timestamp": start_timestamp, 33 | "generation_time_s": generation_time_s, 34 | } 35 | -------------------------------------------------------------------------------- /poll/translations/ar/LC_MESSAGES/text.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-craft/xblock-poll/aef56bd0b94a4a3a0c89f8edd442f7cc0132a760/poll/translations/ar/LC_MESSAGES/text.mo -------------------------------------------------------------------------------- /poll/translations/config.yaml: -------------------------------------------------------------------------------- 1 | # Configuration for i18n workflow. 2 | 3 | locales: 4 | - en # English - Source Language 5 | - eo # Esperanto 6 | - ar # Arabic 7 | - es_419 # Spanish (Latin America) 8 | - ja_JP # Japanese 9 | - fr # French 10 | - fr_CA # French (Canada) 11 | - he # Hebrew 12 | - hi # Hindi 13 | - ko_KR # Korean (Korea) 14 | - pt_BR # Portuguese (Brazil) 15 | - pt_PT # Portuguese (Portugal) 16 | - ru # Russian 17 | - zh_CN # Chinese (China) 18 | - de_DE # German 19 | - pl # Polish 20 | 21 | # The locales used for fake-accented English, for testing. 22 | dummy_locales: 23 | - eo 24 | 25 | generate_merge: {} 26 | segment: {} 27 | -------------------------------------------------------------------------------- /poll/translations/de_DE/LC_MESSAGES/text.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-craft/xblock-poll/aef56bd0b94a4a3a0c89f8edd442f7cc0132a760/poll/translations/de_DE/LC_MESSAGES/text.mo -------------------------------------------------------------------------------- /poll/translations/de_DE/LC_MESSAGES/textjs.po: -------------------------------------------------------------------------------- 1 | # 2 | # Translators: 3 | # Ron Lucke , 2018 4 | # Alexander L. , 2018 5 | # yamahapsr200 , 2018 6 | # mc , 2018 7 | # Akif Vohra , 2018 8 | # Stefania Trabucchi , 2020 9 | # 10 | msgid "" 11 | msgstr "" 12 | "Last-Translator: Stefania Trabucchi , 2020\n" 13 | "Language-Team: German (Germany) (https://www.transifex.com/open-edx/teams/6205/de_DE/)\n" 14 | "Content-Type: text/plain; charset=UTF-8\n" 15 | "Language: de_DE\n" 16 | "Plural-Forms: nplurals=2; plural=(n != 1);\n" 17 | 18 | #: poll/public/handlebars/poll_studio.handlebars:6 19 | msgid "move poll up" 20 | msgstr "Umfrage nach oben bewegen" 21 | 22 | #: poll/public/handlebars/poll_studio.handlebars:7 23 | msgid "move poll down" 24 | msgstr "Umfrage nach unten bewegen" 25 | 26 | #: poll/public/handlebars/poll_studio.handlebars:9 27 | msgid "Delete" 28 | msgstr "Löschen" 29 | 30 | #: poll/public/handlebars/poll_studio.handlebars:11 31 | msgid "Answer" 32 | msgstr "Antwort" 33 | 34 | #: poll/public/handlebars/poll_studio.handlebars:12 35 | msgid "Question" 36 | msgstr "Frage" 37 | 38 | #: poll/public/handlebars/poll_studio.handlebars:16 39 | msgid "Image URL" 40 | msgstr "Bild URL" 41 | 42 | #: poll/public/handlebars/poll_studio.handlebars:18 43 | msgid "Image alternative text" 44 | msgstr "Alternativtext zum Bild" 45 | 46 | #: poll/public/handlebars/poll_studio.handlebars:23 47 | msgid "" 48 | "You can make limited use of Markdown in answer texts, preferably only bold " 49 | "and italics." 50 | msgstr "" 51 | "In den Antworttexten können Sie die Markdown-Funktion nur begrenzt " 52 | "verwenden, vorzugsweise nur fett und kursiv." 53 | 54 | #: poll/public/handlebars/poll_studio.handlebars:27 55 | msgid "" 56 | "This must have an image URL or text, and can have both. If you add an " 57 | "image, you must also provide an alternative text that describes the image in" 58 | " a way that would allow someone to answer the poll if the image did not " 59 | "load." 60 | msgstr "" 61 | "Dieser muss eine Bild-URL und/oder einen Text haben. Wenn Sie ein Bild " 62 | "hinzufügen, müssen Sie auch einen alternativen Text angeben, der das Bild so" 63 | " beschreibt, dass jemand auf die Umfrage antworten kann, wenn das Bild nicht" 64 | " geladen wurde." 65 | 66 | #: poll/public/handlebars/poll_results.handlebars:5 67 | #: poll/public/handlebars/survey_results.handlebars:4 68 | msgid "Results" 69 | msgstr "Ergebnisse" 70 | 71 | #: poll/public/handlebars/poll_results.handlebars:31 72 | #: poll/public/handlebars/survey_results.handlebars:39 73 | msgid "Submit" 74 | msgstr "Absenden" 75 | 76 | #: poll/public/handlebars/poll_results.handlebars:33 77 | #: poll/public/handlebars/survey_results.handlebars:41 78 | msgid "Results gathered from {total} respondent." 79 | msgid_plural "Results gathered from {total} respondents." 80 | msgstr[0] "Ergebnisse von {total} Befragten erfasst." 81 | msgstr[1] "Ergebnisse von {total} Befragten erfasst." 82 | 83 | #: poll/public/handlebars/poll_results.handlebars:37 84 | #: poll/public/handlebars/survey_results.handlebars:46 85 | msgid "Feedback" 86 | msgstr "Rückmeldung" 87 | -------------------------------------------------------------------------------- /poll/translations/en/LC_MESSAGES/text.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-craft/xblock-poll/aef56bd0b94a4a3a0c89f8edd442f7cc0132a760/poll/translations/en/LC_MESSAGES/text.mo -------------------------------------------------------------------------------- /poll/translations/en/LC_MESSAGES/textjs.po: -------------------------------------------------------------------------------- 1 | msgid "" 2 | msgstr "Content-Type: text/plain; charset=utf-8\n" 3 | 4 | #: poll/public/handlebars/poll_results.handlebars:5 5 | #: poll/public/handlebars/survey_results.handlebars:4 6 | msgid "Results" 7 | msgstr "" 8 | 9 | #: poll/public/handlebars/poll_results.handlebars:32 10 | #: poll/public/handlebars/survey_results.handlebars:40 11 | msgid "Results gathered from {total} respondent." 12 | msgid_plural "Results gathered from {total} respondents." 13 | msgstr[0] "" 14 | msgstr[1] "" 15 | 16 | #: poll/public/handlebars/poll_results.handlebars:36 17 | #: poll/public/handlebars/survey_results.handlebars:45 18 | msgid "Feedback" 19 | msgstr "" 20 | 21 | #: poll/public/handlebars/poll_studio.handlebars:6 22 | msgid "move poll up" 23 | msgstr "" 24 | 25 | #: poll/public/handlebars/poll_studio.handlebars:7 26 | msgid "move poll down" 27 | msgstr "" 28 | 29 | #: poll/public/handlebars/poll_studio.handlebars:9 30 | msgid "Delete" 31 | msgstr "" 32 | 33 | #: poll/public/handlebars/poll_studio.handlebars:11 34 | msgid "Answer" 35 | msgstr "" 36 | 37 | #: poll/public/handlebars/poll_studio.handlebars:12 38 | msgid "Question" 39 | msgstr "" 40 | 41 | #: poll/public/handlebars/poll_studio.handlebars:16 42 | msgid "Image URL" 43 | msgstr "" 44 | 45 | #: poll/public/handlebars/poll_studio.handlebars:18 46 | msgid "Image alternative text" 47 | msgstr "" 48 | 49 | #: poll/public/handlebars/poll_studio.handlebars:23 50 | msgid "" 51 | "You can make limited use of Markdown in answer texts, preferably only bold " 52 | "and italics." 53 | msgstr "" 54 | 55 | #: poll/public/handlebars/poll_studio.handlebars:27 56 | msgid "" 57 | "This must have an image URL or text, and can have both. If you add an " 58 | "image, you must also provide an alternative text that describes the image " 59 | "in a way that would allow someone to answer the poll if the image did not " 60 | "load." 61 | msgstr "" 62 | -------------------------------------------------------------------------------- /poll/translations/eo/LC_MESSAGES/text.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-craft/xblock-poll/aef56bd0b94a4a3a0c89f8edd442f7cc0132a760/poll/translations/eo/LC_MESSAGES/text.mo -------------------------------------------------------------------------------- /poll/translations/eo/LC_MESSAGES/textjs.po: -------------------------------------------------------------------------------- 1 | # 2 | msgid "" 3 | msgstr "" 4 | "Language: eo\n" 5 | "Content-Type: text/plain; charset=utf-8\n" 6 | "Plural-Forms: nplurals=2; plural=(n != 1);\n" 7 | 8 | #: poll/public/handlebars/survey_results.handlebars 9 | #: poll/public/handlebars/poll_results.handlebars 10 | msgid "Results" 11 | msgstr "Résülts Ⱡ'σяєм ιρѕυм #" 12 | 13 | #: poll/public/handlebars/survey_results.handlebars 14 | #: poll/public/handlebars/poll_results.handlebars 15 | msgid "Submit" 16 | msgstr "Süßmït Ⱡ'σяєм ιρѕυ#" 17 | 18 | #: poll/public/handlebars/survey_results.handlebars 19 | #: poll/public/handlebars/poll_results.handlebars 20 | msgid "Results gathered from {total} respondent." 21 | msgid_plural "Results gathered from {total} respondents." 22 | msgstr[0] "" 23 | "Résülts gäthéréd fröm {total} réspöndént. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, " 24 | "¢σηѕє¢тєтυ#" 25 | msgstr[1] "" 26 | "Résülts gäthéréd fröm {total} réspöndénts. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, " 27 | "¢σηѕє¢тєтυя#" 28 | 29 | #: poll/public/handlebars/survey_results.handlebars 30 | #: poll/public/handlebars/poll_results.handlebars 31 | msgid "Feedback" 32 | msgstr "Féédßäçk Ⱡ'σяєм ιρѕυм ∂#" 33 | 34 | #: poll/public/handlebars/poll_studio.handlebars 35 | msgid "move poll up" 36 | msgstr "mövé pöll üp Ⱡ'σяєм ιρѕυм ∂σłσя ѕ#" 37 | 38 | #: poll/public/handlebars/poll_studio.handlebars 39 | msgid "move poll down" 40 | msgstr "mövé pöll döwn Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт#" 41 | 42 | #: poll/public/handlebars/poll_studio.handlebars 43 | msgid "Delete" 44 | msgstr "Délété Ⱡ'σяєм ιρѕυ#" 45 | 46 | #: poll/public/handlebars/poll_studio.handlebars 47 | msgid "Answer" 48 | msgstr "Ànswér Ⱡ'σяєм ιρѕυ#" 49 | 50 | #: poll/public/handlebars/poll_studio.handlebars 51 | msgid "Question" 52 | msgstr "Qüéstïön Ⱡ'σяєм ιρѕυм ∂#" 53 | 54 | #: poll/public/handlebars/poll_studio.handlebars 55 | msgid "Image URL" 56 | msgstr "Ìmägé ÛRL Ⱡ'σяєм ιρѕυм ∂σł#" 57 | 58 | #: poll/public/handlebars/poll_studio.handlebars 59 | msgid "Image alternative text" 60 | msgstr "Ìmägé ältérnätïvé téxt Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢#" 61 | 62 | #: poll/public/handlebars/poll_studio.handlebars 63 | msgid "" 64 | "You can make limited use of Markdown in answer texts, preferably only bold " 65 | "and italics." 66 | msgstr "" 67 | "Ýöü çän mäké lïmïtéd üsé öf Märkdöwn ïn änswér téxts, préféräßlý önlý ßöld " 68 | "änd ïtälïçs. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє#" 69 | 70 | #: poll/public/handlebars/poll_studio.handlebars 71 | msgid "" 72 | "This must have an image URL or text, and can have both. If you add an " 73 | "image, you must also provide an alternative text that describes the image in" 74 | " a way that would allow someone to answer the poll if the image did not " 75 | "load." 76 | msgstr "" 77 | "Thïs müst hävé än ïmägé ÛRL ör téxt, änd çän hävé ßöth. Ìf ýöü ädd än " 78 | "ïmägé, ýöü müst älsö prövïdé än ältérnätïvé téxt thät désçrïßés thé ïmägé ïn" 79 | " ä wäý thät wöüld ällöw söméöné tö änswér thé pöll ïf thé ïmägé dïd nöt " 80 | "löäd. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя α∂ιριѕι¢ιηg єłιт, ѕє∂ ∂σ " 81 | "єιυѕмσ∂ тємρσя ιη¢ι∂ι∂υηт υт łαвσяє єт ∂σłσяє мαgηα αłιqυα. υт єηιм α∂ мιηιм" 82 | " νєηιαм, qυιѕ ησѕтяυ∂ єχєя¢ιтαтιση υłłαм¢σ łαвσяιѕ ηιѕι υт αłιqυιρ єχ єα " 83 | "¢σммσ∂σ ¢σηѕєqυαт. ∂υιѕ αυтє ιяυяє ∂σłσя ιη яєρяєнєη∂єяιт ιη νσłυρтαтє νєłιт" 84 | " єѕѕє ¢ιłłυм ∂σłσяє єυ ƒυgιαт #" 85 | -------------------------------------------------------------------------------- /poll/translations/es_419/LC_MESSAGES/text.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-craft/xblock-poll/aef56bd0b94a4a3a0c89f8edd442f7cc0132a760/poll/translations/es_419/LC_MESSAGES/text.mo -------------------------------------------------------------------------------- /poll/translations/es_419/LC_MESSAGES/textjs.po: -------------------------------------------------------------------------------- 1 | # 2 | # Translators: 3 | # Juan Camilo Montoya Franco , 2018 4 | # fco.aguilarm , 2018 5 | # Diego Rojas , 2018 6 | # Albeiro Gonzalez , 2018 7 | # 8 | msgid "" 9 | msgstr "" 10 | "Last-Translator: Albeiro Gonzalez , 2018\n" 11 | "Language-Team: Spanish (Latin America) (https://www.transifex.com/open-edx/teams/6205/es_419/)\n" 12 | "Content-Type: text/plain; charset=UTF-8\n" 13 | "Language: es_419\n" 14 | "Plural-Forms: nplurals=2; plural=(n != 1);\n" 15 | 16 | #: poll/public/handlebars/poll_studio.handlebars:6 17 | msgid "move poll up" 18 | msgstr "mover la encuesta arriba" 19 | 20 | #: poll/public/handlebars/poll_studio.handlebars:7 21 | msgid "move poll down" 22 | msgstr "mover la encuesta abajo" 23 | 24 | #: poll/public/handlebars/poll_studio.handlebars:9 25 | msgid "Delete" 26 | msgstr "Borrar" 27 | 28 | #: poll/public/handlebars/poll_studio.handlebars:11 29 | msgid "Answer" 30 | msgstr "Respuesta" 31 | 32 | #: poll/public/handlebars/poll_studio.handlebars:12 33 | msgid "Question" 34 | msgstr "Pregunta" 35 | 36 | #: poll/public/handlebars/poll_studio.handlebars:16 37 | msgid "Image URL" 38 | msgstr "URL de la imagen" 39 | 40 | #: poll/public/handlebars/poll_studio.handlebars:18 41 | msgid "Image alternative text" 42 | msgstr "Texto alternativo de la imagen" 43 | 44 | #: poll/public/handlebars/poll_studio.handlebars:23 45 | msgid "" 46 | "You can make limited use of Markdown in answer texts, preferably only bold " 47 | "and italics." 48 | msgstr "" 49 | "Puede hacer uso limitado de Markdown en los textos de respuesta, " 50 | "preferiblemente solo negritas e itálicas." 51 | 52 | #: poll/public/handlebars/poll_studio.handlebars:27 53 | msgid "" 54 | "This must have an image URL or text, and can have both. If you add an " 55 | "image, you must also provide an alternative text that describes the image in" 56 | " a way that would allow someone to answer the poll if the image did not " 57 | "load." 58 | msgstr "" 59 | "Esto debe tener una URL de imagen o texto, y puede tener ambos. Si agrega " 60 | "una imagen, debe además proporcionar un texto alternativo que describa la " 61 | "imagen de manera que permita a alguien responder la encuesta aún si la " 62 | "imagen no carga." 63 | 64 | #: poll/public/handlebars/poll_results.handlebars:5 65 | #: poll/public/handlebars/survey_results.handlebars:4 66 | msgid "Results" 67 | msgstr "Resultados" 68 | 69 | #: poll/public/handlebars/poll_results.handlebars:31 70 | #: poll/public/handlebars/survey_results.handlebars:39 71 | msgid "Submit" 72 | msgstr "Enviar" 73 | 74 | #: poll/public/handlebars/poll_results.handlebars:33 75 | #: poll/public/handlebars/survey_results.handlebars:41 76 | msgid "Results gathered from {total} respondent." 77 | msgid_plural "Results gathered from {total} respondents." 78 | msgstr[0] "Resultados obtenidos de {total} encuestado." 79 | msgstr[1] "Resultados obtenidos de {total} encuestados." 80 | 81 | #: poll/public/handlebars/poll_results.handlebars:37 82 | #: poll/public/handlebars/survey_results.handlebars:46 83 | msgid "Feedback" 84 | msgstr "Retroalimentación" 85 | -------------------------------------------------------------------------------- /poll/translations/fr/LC_MESSAGES/text.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-craft/xblock-poll/aef56bd0b94a4a3a0c89f8edd442f7cc0132a760/poll/translations/fr/LC_MESSAGES/text.mo -------------------------------------------------------------------------------- /poll/translations/fr/LC_MESSAGES/textjs.po: -------------------------------------------------------------------------------- 1 | # 2 | # Translators: 3 | # Sébastien Vigneau , 2018 4 | # Françoise Docq, 2018 5 | # rafcha , 2018 6 | # Eric Fischer , 2018 7 | # Manuel Dias , 2018 8 | # Abdessamad Derraz , 2021 9 | # 10 | msgid "" 11 | msgstr "" 12 | "Last-Translator: Abdessamad Derraz , 2021\n" 13 | "Language-Team: French (https://www.transifex.com/open-edx/teams/6205/fr/)\n" 14 | "Content-Type: text/plain; charset=UTF-8\n" 15 | "Language: fr\n" 16 | "Plural-Forms: nplurals=2; plural=(n > 1);\n" 17 | 18 | #: poll/public/handlebars/poll_studio.handlebars:6 19 | msgid "move poll up" 20 | msgstr "déplacer le sondage vers le haut" 21 | 22 | #: poll/public/handlebars/poll_studio.handlebars:7 23 | msgid "move poll down" 24 | msgstr "déplacer le sondage vers le bas" 25 | 26 | #: poll/public/handlebars/poll_studio.handlebars:9 27 | msgid "Delete" 28 | msgstr "Supprimer" 29 | 30 | #: poll/public/handlebars/poll_studio.handlebars:11 31 | msgid "Answer" 32 | msgstr "Réponse" 33 | 34 | #: poll/public/handlebars/poll_studio.handlebars:12 35 | msgid "Question" 36 | msgstr "Question" 37 | 38 | #: poll/public/handlebars/poll_studio.handlebars:16 39 | msgid "Image URL" 40 | msgstr "URL de l'image" 41 | 42 | #: poll/public/handlebars/poll_studio.handlebars:18 43 | msgid "Image alternative text" 44 | msgstr "Texte alternatif de l'image" 45 | 46 | #: poll/public/handlebars/poll_studio.handlebars:23 47 | msgid "" 48 | "You can make limited use of Markdown in answer texts, preferably only bold " 49 | "and italics." 50 | msgstr "" 51 | "Vous pouvez utiliser Markdown de manière limitée dans les textes de réponse," 52 | " de préférence uniquement en gras et en italique." 53 | 54 | #: poll/public/handlebars/poll_studio.handlebars:27 55 | msgid "" 56 | "This must have an image URL or text, and can have both. If you add an " 57 | "image, you must also provide an alternative text that describes the image in" 58 | " a way that would allow someone to answer the poll if the image did not " 59 | "load." 60 | msgstr "" 61 | "Cela doit avoir une URL d'image ou un texte, et peut avoir les deux. Si vous" 62 | " ajoutez une image, vous devez également fournir un texte de remplacement " 63 | "décrivant l'image de manière à permettre à quelqu'un de répondre au sondage " 64 | "si l'image ne s'est pas chargée." 65 | 66 | #: poll/public/handlebars/poll_results.handlebars:5 67 | #: poll/public/handlebars/survey_results.handlebars:4 68 | msgid "Results" 69 | msgstr "Résultats" 70 | 71 | #: poll/public/handlebars/poll_results.handlebars:31 72 | #: poll/public/handlebars/survey_results.handlebars:39 73 | msgid "Submit" 74 | msgstr "Soumettre" 75 | 76 | #: poll/public/handlebars/poll_results.handlebars:33 77 | #: poll/public/handlebars/survey_results.handlebars:41 78 | msgid "Results gathered from {total} respondent." 79 | msgid_plural "Results gathered from {total} respondents." 80 | msgstr[0] "Résultats recueillis auprès de {total} répondant." 81 | msgstr[1] "Résultats recueillis auprès de {total} répondants." 82 | 83 | #: poll/public/handlebars/poll_results.handlebars:37 84 | #: poll/public/handlebars/survey_results.handlebars:46 85 | msgid "Feedback" 86 | msgstr "Commentaire" 87 | -------------------------------------------------------------------------------- /poll/translations/fr_CA/LC_MESSAGES/text.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-craft/xblock-poll/aef56bd0b94a4a3a0c89f8edd442f7cc0132a760/poll/translations/fr_CA/LC_MESSAGES/text.mo -------------------------------------------------------------------------------- /poll/translations/fr_CA/LC_MESSAGES/textjs.po: -------------------------------------------------------------------------------- 1 | # 2 | # Translators: 3 | # Pierre Mailhot , 2019 4 | # 5 | msgid "" 6 | msgstr "" 7 | "Last-Translator: Pierre Mailhot , 2019\n" 8 | "Language-Team: French (Canada) (https://www.transifex.com/open-edx/teams/6205/fr_CA/)\n" 9 | "Content-Type: text/plain; charset=UTF-8\n" 10 | "Language: fr_CA\n" 11 | "Plural-Forms: nplurals=2; plural=(n > 1);\n" 12 | 13 | #: poll/public/handlebars/poll_studio.handlebars:6 14 | msgid "move poll up" 15 | msgstr "déplacer le sondage vers le haut" 16 | 17 | #: poll/public/handlebars/poll_studio.handlebars:7 18 | msgid "move poll down" 19 | msgstr "déplacer le sondage vers le bas" 20 | 21 | #: poll/public/handlebars/poll_studio.handlebars:9 22 | msgid "Delete" 23 | msgstr "Supprimer" 24 | 25 | #: poll/public/handlebars/poll_studio.handlebars:11 26 | msgid "Answer" 27 | msgstr "Réponse" 28 | 29 | #: poll/public/handlebars/poll_studio.handlebars:12 30 | msgid "Question" 31 | msgstr "Question" 32 | 33 | #: poll/public/handlebars/poll_studio.handlebars:16 34 | msgid "Image URL" 35 | msgstr "URL de l'image" 36 | 37 | #: poll/public/handlebars/poll_studio.handlebars:18 38 | msgid "Image alternative text" 39 | msgstr "Texte alternatif de l'image" 40 | 41 | #: poll/public/handlebars/poll_studio.handlebars:23 42 | msgid "" 43 | "You can make limited use of Markdown in answer texts, preferably only bold " 44 | "and italics." 45 | msgstr "" 46 | "Vous pouvez utiliser Markdown de manière limitée dans les textes de réponse," 47 | " de préférence uniquement en gras et en italique." 48 | 49 | #: poll/public/handlebars/poll_studio.handlebars:27 50 | msgid "" 51 | "This must have an image URL or text, and can have both. If you add an " 52 | "image, you must also provide an alternative text that describes the image in" 53 | " a way that would allow someone to answer the poll if the image did not " 54 | "load." 55 | msgstr "" 56 | "Cela doit avoir une URL d'image ou un texte, et peut avoir les deux. Si vous" 57 | " ajoutez une image, vous devez également fournir un texte de remplacement " 58 | "décrivant l'image de manière à permettre à quelqu'un de répondre au sondage " 59 | "si l'image ne s'est pas chargée." 60 | 61 | #: poll/public/handlebars/poll_results.handlebars:5 62 | #: poll/public/handlebars/survey_results.handlebars:4 63 | msgid "Results" 64 | msgstr "Résultats" 65 | 66 | #: poll/public/handlebars/poll_results.handlebars:31 67 | #: poll/public/handlebars/survey_results.handlebars:39 68 | msgid "Submit" 69 | msgstr "Soumettre" 70 | 71 | #: poll/public/handlebars/poll_results.handlebars:33 72 | #: poll/public/handlebars/survey_results.handlebars:41 73 | msgid "Results gathered from {total} respondent." 74 | msgid_plural "Results gathered from {total} respondents." 75 | msgstr[0] "Résultats recueillis auprès de {total} répondant." 76 | msgstr[1] "Résultats recueillis auprès de {total} répondants." 77 | 78 | #: poll/public/handlebars/poll_results.handlebars:37 79 | #: poll/public/handlebars/survey_results.handlebars:46 80 | msgid "Feedback" 81 | msgstr "Commentaire" 82 | -------------------------------------------------------------------------------- /poll/translations/he/LC_MESSAGES/text.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-craft/xblock-poll/aef56bd0b94a4a3a0c89f8edd442f7cc0132a760/poll/translations/he/LC_MESSAGES/text.mo -------------------------------------------------------------------------------- /poll/translations/it_IT/LC_MESSAGES/text.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-craft/xblock-poll/aef56bd0b94a4a3a0c89f8edd442f7cc0132a760/poll/translations/it_IT/LC_MESSAGES/text.mo -------------------------------------------------------------------------------- /poll/translations/it_IT/LC_MESSAGES/textjs.po: -------------------------------------------------------------------------------- 1 | # 2 | # Translators: 3 | # Monica Maria Crapanzano , 2018 4 | # anna.ghetti , 2018 5 | # Butta Tutto , 2018 6 | # Fare Fare , 2018 7 | # Transifex Bot <>, 2024 8 | # 9 | msgid "" 10 | msgstr "" 11 | "Last-Translator: Transifex Bot <>, 2024\n" 12 | "Language-Team: Italian (Italy) (https://app.transifex.com/open-edx/teams/6205/it_IT/)\n" 13 | "Content-Type: text/plain; charset=UTF-8\n" 14 | "Language: it_IT\n" 15 | "Plural-Forms: nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n" 16 | 17 | #: poll/public/handlebars/poll_studio.handlebars:6 18 | msgid "move poll up" 19 | msgstr "muovi sondaggio all'insù" 20 | 21 | #: poll/public/handlebars/poll_studio.handlebars:7 22 | msgid "move poll down" 23 | msgstr "muovi sondaggio ingiù" 24 | 25 | #: poll/public/handlebars/poll_studio.handlebars:9 26 | msgid "Delete" 27 | msgstr "Cancella" 28 | 29 | #: poll/public/handlebars/poll_studio.handlebars:11 30 | msgid "Answer" 31 | msgstr "Risposta" 32 | 33 | #: poll/public/handlebars/poll_studio.handlebars:12 34 | msgid "Question" 35 | msgstr "Domanda" 36 | 37 | #: poll/public/handlebars/poll_studio.handlebars:16 38 | msgid "Image URL" 39 | msgstr "URL dell'immagine" 40 | 41 | #: poll/public/handlebars/poll_studio.handlebars:18 42 | msgid "Image alternative text" 43 | msgstr "Testo alternativo per l'immagine" 44 | 45 | #: poll/public/handlebars/poll_studio.handlebars:23 46 | msgid "" 47 | "You can make limited use of Markdown in answer texts, preferably only bold " 48 | "and italics." 49 | msgstr "" 50 | "Puoi usare in modo limitato la sintassi Markdown nel testo delle risposta, " 51 | "preferibilmente solo grassetto e corsivo si possono utilizzare." 52 | 53 | #: poll/public/handlebars/poll_studio.handlebars:27 54 | msgid "" 55 | "This must have an image URL or text, and can have both. If you add an " 56 | "image, you must also provide an alternative text that describes the image in" 57 | " a way that would allow someone to answer the poll if the image did not " 58 | "load." 59 | msgstr "" 60 | "Questo deve avere un image URL o testo e può anche averli entrambi. Se " 61 | "aggiungi un'immagine, devi anche fornire un testo alternativo che descriva " 62 | "l'immagine in modo che questo possa consentire di rispondere al sondaggio " 63 | "anche se l'immagine non è stata correttamente caricata." 64 | 65 | #: poll/public/handlebars/poll_results.handlebars:5 66 | #: poll/public/handlebars/survey_results.handlebars:4 67 | msgid "Results" 68 | msgstr "Feedback" 69 | 70 | #: poll/public/handlebars/poll_results.handlebars:31 71 | #: poll/public/handlebars/survey_results.handlebars:39 72 | msgid "Submit" 73 | msgstr "Invia" 74 | 75 | #: poll/public/handlebars/poll_results.handlebars:33 76 | #: poll/public/handlebars/survey_results.handlebars:41 77 | msgid "Results gathered from {total} respondent." 78 | msgid_plural "Results gathered from {total} respondents." 79 | msgstr[0] "Risposte raccolte da {total} persone" 80 | msgstr[1] "Risposte raccolte da {total} persone" 81 | msgstr[2] "Risposte raccolte da {total} persone" 82 | 83 | #: poll/public/handlebars/poll_results.handlebars:37 84 | #: poll/public/handlebars/survey_results.handlebars:46 85 | msgid "Feedback" 86 | msgstr "" 87 | -------------------------------------------------------------------------------- /poll/translations/ja_JP/LC_MESSAGES/text.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-craft/xblock-poll/aef56bd0b94a4a3a0c89f8edd442f7cc0132a760/poll/translations/ja_JP/LC_MESSAGES/text.mo -------------------------------------------------------------------------------- /poll/translations/ja_JP/LC_MESSAGES/textjs.po: -------------------------------------------------------------------------------- 1 | # 2 | # Translators: 3 | # わたカフェの店長, 2018 4 | # h_yoshida , 2018 5 | # Toshiboumi Ohta , 2018 6 | # Kyoto University , 2018 7 | # 藤田 忠光 , 2018 8 | # Machida Miki , 2018 9 | # 10 | msgid "" 11 | msgstr "" 12 | "Last-Translator: Machida Miki , 2018\n" 13 | "Language-Team: Japanese (Japan) (https://www.transifex.com/open-edx/teams/6205/ja_JP/)\n" 14 | "Content-Type: text/plain; charset=UTF-8\n" 15 | "Language: ja_JP\n" 16 | "Plural-Forms: nplurals=1; plural=0;\n" 17 | 18 | #: poll/public/handlebars/poll_studio.handlebars:6 19 | msgid "move poll up" 20 | msgstr "投票を上に移動" 21 | 22 | #: poll/public/handlebars/poll_studio.handlebars:7 23 | msgid "move poll down" 24 | msgstr "投票を下に移動" 25 | 26 | #: poll/public/handlebars/poll_studio.handlebars:9 27 | msgid "Delete" 28 | msgstr "削除" 29 | 30 | #: poll/public/handlebars/poll_studio.handlebars:11 31 | msgid "Answer" 32 | msgstr "解答" 33 | 34 | #: poll/public/handlebars/poll_studio.handlebars:12 35 | msgid "Question" 36 | msgstr "質問" 37 | 38 | #: poll/public/handlebars/poll_studio.handlebars:16 39 | msgid "Image URL" 40 | msgstr "画像URL" 41 | 42 | #: poll/public/handlebars/poll_studio.handlebars:18 43 | msgid "Image alternative text" 44 | msgstr "画像代替テキスト" 45 | 46 | #: poll/public/handlebars/poll_studio.handlebars:23 47 | msgid "" 48 | "You can make limited use of Markdown in answer texts, preferably only bold " 49 | "and italics." 50 | msgstr "回答テキストではマークダウンを限定的に使用できますが、太字と斜体のみをお勧めします。" 51 | 52 | #: poll/public/handlebars/poll_studio.handlebars:27 53 | msgid "" 54 | "This must have an image URL or text, and can have both. If you add an " 55 | "image, you must also provide an alternative text that describes the image in" 56 | " a way that would allow someone to answer the poll if the image did not " 57 | "load." 58 | msgstr "" 59 | "これには画像URLまたはテキストが必要となりますが、両方指定できます。画像を追加する場合は、画像が読み込まれなかった場合に、画像を説明する代替テキストを指定し、投票に回答できるようにする必要もあります。" 60 | 61 | #: poll/public/handlebars/poll_results.handlebars:5 62 | #: poll/public/handlebars/survey_results.handlebars:4 63 | msgid "Results" 64 | msgstr "結果" 65 | 66 | #: poll/public/handlebars/poll_results.handlebars:31 67 | #: poll/public/handlebars/survey_results.handlebars:39 68 | msgid "Submit" 69 | msgstr "提出" 70 | 71 | #: poll/public/handlebars/poll_results.handlebars:33 72 | #: poll/public/handlebars/survey_results.handlebars:41 73 | msgid "Results gathered from {total} respondent." 74 | msgid_plural "Results gathered from {total} respondents." 75 | msgstr[0] "回答者からの{合計}結果を集計しました。" 76 | 77 | #: poll/public/handlebars/poll_results.handlebars:37 78 | #: poll/public/handlebars/survey_results.handlebars:46 79 | msgid "Feedback" 80 | msgstr "フィードバック" 81 | -------------------------------------------------------------------------------- /poll/translations/pt_BR/LC_MESSAGES/text.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-craft/xblock-poll/aef56bd0b94a4a3a0c89f8edd442f7cc0132a760/poll/translations/pt_BR/LC_MESSAGES/text.mo -------------------------------------------------------------------------------- /poll/translations/pt_BR/LC_MESSAGES/textjs.po: -------------------------------------------------------------------------------- 1 | # 2 | # Translators: 3 | # Renata Barboza, 2018 4 | # Gisele Spolador Lopes , 2018 5 | # Anderson Franca , 2018 6 | # Larissa Azevedo , 2018 7 | # Omar Al-Ithawi , 2021 8 | # 9 | msgid "" 10 | msgstr "" 11 | "Last-Translator: Omar Al-Ithawi , 2021\n" 12 | "Language-Team: Portuguese (Brazil) (https://www.transifex.com/open-edx/teams/6205/pt_BR/)\n" 13 | "Content-Type: text/plain; charset=UTF-8\n" 14 | "Language: pt_BR\n" 15 | "Plural-Forms: nplurals=2; plural=(n > 1);\n" 16 | 17 | #: poll/public/handlebars/poll_studio.handlebars:6 18 | msgid "move poll up" 19 | msgstr "" 20 | 21 | #: poll/public/handlebars/poll_studio.handlebars:7 22 | msgid "move poll down" 23 | msgstr "" 24 | 25 | #: poll/public/handlebars/poll_studio.handlebars:9 26 | msgid "Delete" 27 | msgstr "" 28 | 29 | #: poll/public/handlebars/poll_studio.handlebars:11 30 | msgid "Answer" 31 | msgstr "Resposta" 32 | 33 | #: poll/public/handlebars/poll_studio.handlebars:12 34 | msgid "Question" 35 | msgstr "" 36 | 37 | #: poll/public/handlebars/poll_studio.handlebars:16 38 | msgid "Image URL" 39 | msgstr "" 40 | 41 | #: poll/public/handlebars/poll_studio.handlebars:18 42 | msgid "Image alternative text" 43 | msgstr "" 44 | 45 | #: poll/public/handlebars/poll_studio.handlebars:23 46 | msgid "" 47 | "You can make limited use of Markdown in answer texts, preferably only bold " 48 | "and italics." 49 | msgstr "" 50 | "Você pode fazer uso limitado do Markdown nas respostas de textos, de " 51 | "preferência negrito e itálico. " 52 | 53 | #: poll/public/handlebars/poll_studio.handlebars:27 54 | msgid "" 55 | "This must have an image URL or text, and can have both. If you add an " 56 | "image, you must also provide an alternative text that describes the image in" 57 | " a way that would allow someone to answer the poll if the image did not " 58 | "load." 59 | msgstr "" 60 | "Uma imagem de URL ou texto, ou ambos, devem ser adicionados. Caso uma imagem" 61 | " seja adicionada, é necessário que se adicione um texto alternativo " 62 | "descrevendo a imagem para permitir que usuários possam responder à enquete " 63 | "caso a imagem não carregue." 64 | 65 | #: poll/public/handlebars/poll_results.handlebars:5 66 | #: poll/public/handlebars/survey_results.handlebars:4 67 | msgid "Results" 68 | msgstr "" 69 | 70 | #: poll/public/handlebars/poll_results.handlebars:31 71 | #: poll/public/handlebars/survey_results.handlebars:39 72 | msgid "Submit" 73 | msgstr "Enviar" 74 | 75 | #: poll/public/handlebars/poll_results.handlebars:33 76 | #: poll/public/handlebars/survey_results.handlebars:41 77 | msgid "Results gathered from {total} respondent." 78 | msgid_plural "Results gathered from {total} respondents." 79 | msgstr[0] "" 80 | msgstr[1] "" 81 | 82 | #: poll/public/handlebars/poll_results.handlebars:37 83 | #: poll/public/handlebars/survey_results.handlebars:46 84 | msgid "Feedback" 85 | msgstr "" 86 | -------------------------------------------------------------------------------- /poll/translations/pt_PT/LC_MESSAGES/text.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-craft/xblock-poll/aef56bd0b94a4a3a0c89f8edd442f7cc0132a760/poll/translations/pt_PT/LC_MESSAGES/text.mo -------------------------------------------------------------------------------- /poll/translations/pt_PT/LC_MESSAGES/textjs.po: -------------------------------------------------------------------------------- 1 | # 2 | # Translators: 3 | # Carlos , 2018 4 | # Waldo Luis Ribeiro, 2018 5 | # Developer QUEO , 2018 6 | # Manuela Silva , 2018 7 | # Rui Ribeiro , 2019 8 | # Ivo Branco , 2021 9 | # 10 | msgid "" 11 | msgstr "" 12 | "Last-Translator: Ivo Branco , 2021\n" 13 | "Language-Team: Portuguese (Portugal) (https://www.transifex.com/open-edx/teams/6205/pt_PT/)\n" 14 | "Content-Type: text/plain; charset=UTF-8\n" 15 | "Language: pt_PT\n" 16 | "Plural-Forms: nplurals=2; plural=(n != 1);\n" 17 | 18 | #: poll/public/handlebars/poll_results.handlebars:5 19 | #: poll/public/handlebars/survey_results.handlebars:4 20 | msgid "Results" 21 | msgstr "Resultados" 22 | 23 | #: poll/public/handlebars/poll_results.handlebars:31 24 | #: poll/public/handlebars/survey_results.handlebars:39 25 | msgid "Submit" 26 | msgstr "Submeter" 27 | 28 | #: poll/public/handlebars/poll_results.handlebars:33 29 | #: poll/public/handlebars/survey_results.handlebars:41 30 | msgid "Results gathered from {total} respondent." 31 | msgid_plural "Results gathered from {total} respondents." 32 | msgstr[0] "Resultados recolhidos de {total} respondente." 33 | msgstr[1] "Resultados recolhidos de {total} respondentes." 34 | 35 | #: poll/public/handlebars/poll_results.handlebars:37 36 | #: poll/public/handlebars/survey_results.handlebars:46 37 | msgid "Feedback" 38 | msgstr "Comentário" 39 | 40 | #: poll/public/handlebars/poll_studio.handlebars:6 41 | msgid "move poll up" 42 | msgstr "mover sondagem para cima" 43 | 44 | #: poll/public/handlebars/poll_studio.handlebars:7 45 | msgid "move poll down" 46 | msgstr "mover sondagem para baixo" 47 | 48 | #: poll/public/handlebars/poll_studio.handlebars:9 49 | msgid "Delete" 50 | msgstr "Eliminar" 51 | 52 | #: poll/public/handlebars/poll_studio.handlebars:11 53 | msgid "Answer" 54 | msgstr "Resposta" 55 | 56 | #: poll/public/handlebars/poll_studio.handlebars:12 57 | msgid "Question" 58 | msgstr "Pergunta" 59 | 60 | #: poll/public/handlebars/poll_studio.handlebars:16 61 | msgid "Image URL" 62 | msgstr "URL da Imagem" 63 | 64 | #: poll/public/handlebars/poll_studio.handlebars:18 65 | msgid "Image alternative text" 66 | msgstr "Texto alternativo da imagem" 67 | 68 | #: poll/public/handlebars/poll_studio.handlebars:23 69 | msgid "" 70 | "You can make limited use of Markdown in answer texts, preferably only bold " 71 | "and italics." 72 | msgstr "" 73 | "Pode fazer um uso limitado do Markdown nos textos de resposta, de " 74 | "preferência apenas em negrito e itálico." 75 | 76 | #: poll/public/handlebars/poll_studio.handlebars:27 77 | msgid "" 78 | "This must have an image URL or text, and can have both. If you add an " 79 | "image, you must also provide an alternative text that describes the image in" 80 | " a way that would allow someone to answer the poll if the image did not " 81 | "load." 82 | msgstr "" 83 | "Este deve ter um URL ou texto de imagem, e pode ter ambos. Se adicionar uma " 84 | "imagem, deve também fornecer um texto alternativo que descreva a imagem de " 85 | "uma forma que permita a alguém responder à sondagem se a imagem não for " 86 | "carregada." 87 | -------------------------------------------------------------------------------- /poll/utils.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | from bleach.sanitizer import Cleaner 4 | from markdown import markdown 5 | 6 | 7 | # Make '_' a no-op so we can scrape strings 8 | def _(text): 9 | return text 10 | 11 | 12 | def ngettext_fallback(text_singular, text_plural, number): 13 | """ Dummy `ngettext` replacement to make string extraction tools scrape strings marked for translation """ 14 | return text_singular if number == 1 else text_plural 15 | 16 | 17 | def remove_html_tags(data): 18 | """ Remove html tags from provided data """ 19 | cleaner = Cleaner(tags=[], strip=True) 20 | return cleaner.clean(data) 21 | 22 | 23 | def remove_markdown_and_html_tags(data): 24 | """ Remove both markdown and html tags from provided data """ 25 | return remove_html_tags(markdown(data)) 26 | 27 | 28 | class DummyTranslationService(object): # pylint: disable=bad-option-value 29 | """ 30 | Dummy drop-in replacement for i18n XBlock service 31 | """ 32 | _catalog = {} 33 | gettext = _ 34 | ngettext = ngettext_fallback 35 | -------------------------------------------------------------------------------- /pylintrc: -------------------------------------------------------------------------------- 1 | [REPORTS] 2 | reports=no 3 | 4 | [FORMAT] 5 | max-line-length=120 6 | 7 | [MESSAGES CONTROL] 8 | disable= 9 | abstract-class-not-used, 10 | broad-except, 11 | cyclic-import, 12 | fixme, 13 | invalid-name, 14 | locally-disabled, 15 | maybe-no-member, 16 | missing-docstring, 17 | protected-access, 18 | star-args, 19 | too-few-public-methods, 20 | too-many-public-methods, 21 | too-many-ancestors, 22 | too-many-arguments, 23 | too-many-locals, 24 | unused-argument, 25 | useless-object-inheritance, 26 | import-outside-toplevel, 27 | super-with-arguments, 28 | consider-using-f-string, 29 | unspecified-encoding, 30 | redundant-u-string-prefix 31 | 32 | [SIMILARITIES] 33 | min-similarity-lines=8 34 | -------------------------------------------------------------------------------- /requirements/base.in: -------------------------------------------------------------------------------- 1 | # Core requirements for using this application 2 | -c constraints.txt 3 | 4 | markdown 5 | django-statici18n 6 | xblock-utils 7 | bleach[css] 8 | -------------------------------------------------------------------------------- /requirements/base.txt: -------------------------------------------------------------------------------- 1 | # 2 | # This file is autogenerated by pip-compile with Python 3.11 3 | # by the following command: 4 | # 5 | # make upgrade 6 | # 7 | appdirs==1.4.4 8 | # via fs 9 | asgiref==3.8.1 10 | # via django 11 | bleach[css]==6.2.0 12 | # via -r requirements/base.in 13 | boto3==1.38.27 14 | # via fs-s3fs 15 | botocore==1.38.27 16 | # via 17 | # boto3 18 | # s3transfer 19 | django==4.2.21 20 | # via 21 | # -c https://raw.githubusercontent.com/edx/edx-lint/master/edx_lint/files/common_constraints.txt 22 | # django-appconf 23 | # django-statici18n 24 | # openedx-django-pyfs 25 | django-appconf==1.1.0 26 | # via django-statici18n 27 | django-statici18n==2.6.0 28 | # via -r requirements/base.in 29 | fs==2.4.16 30 | # via 31 | # fs-s3fs 32 | # openedx-django-pyfs 33 | # xblock 34 | fs-s3fs==1.1.1 35 | # via openedx-django-pyfs 36 | jmespath==1.0.1 37 | # via 38 | # boto3 39 | # botocore 40 | lazy==1.6 41 | # via xblock 42 | lxml==5.4.0 43 | # via xblock 44 | mako==1.3.10 45 | # via 46 | # xblock 47 | # xblock-utils 48 | markdown==3.8 49 | # via -r requirements/base.in 50 | markupsafe==3.0.2 51 | # via 52 | # mako 53 | # xblock 54 | openedx-django-pyfs==3.8.0 55 | # via xblock 56 | python-dateutil==2.9.0.post0 57 | # via 58 | # botocore 59 | # xblock 60 | pytz==2025.2 61 | # via xblock 62 | pyyaml==6.0.2 63 | # via xblock 64 | s3transfer==0.13.0 65 | # via boto3 66 | simplejson==3.20.1 67 | # via 68 | # xblock 69 | # xblock-utils 70 | six==1.17.0 71 | # via 72 | # fs 73 | # fs-s3fs 74 | # python-dateutil 75 | sqlparse==0.5.3 76 | # via django 77 | tinycss2==1.4.0 78 | # via bleach 79 | urllib3==2.2.3 80 | # via 81 | # -c https://raw.githubusercontent.com/edx/edx-lint/master/edx_lint/files/common_constraints.txt 82 | # botocore 83 | web-fragments==3.1.0 84 | # via 85 | # xblock 86 | # xblock-utils 87 | webencodings==0.5.1 88 | # via 89 | # bleach 90 | # tinycss2 91 | webob==1.8.9 92 | # via xblock 93 | xblock[django]==5.2.0 94 | # via xblock-utils 95 | xblock-utils==4.0.0 96 | # via -r requirements/base.in 97 | 98 | # The following packages are considered to be unsafe in a requirements file: 99 | # setuptools 100 | -------------------------------------------------------------------------------- /requirements/ci.in: -------------------------------------------------------------------------------- 1 | # Requirements for running tests in CI 2 | 3 | -c constraints.txt 4 | 5 | tox # Virtualenv management for tests 6 | tox-battery # Makes tox aware of requirements file changes 7 | -------------------------------------------------------------------------------- /requirements/ci.txt: -------------------------------------------------------------------------------- 1 | # 2 | # This file is autogenerated by pip-compile with Python 3.11 3 | # by the following command: 4 | # 5 | # make upgrade 6 | # 7 | distlib==0.3.9 8 | # via virtualenv 9 | filelock==3.18.0 10 | # via 11 | # tox 12 | # virtualenv 13 | packaging==25.0 14 | # via 15 | # pyproject-api 16 | # tox 17 | platformdirs==4.3.8 18 | # via 19 | # tox 20 | # virtualenv 21 | pluggy==1.6.0 22 | # via tox 23 | py==1.11.0 24 | # via tox 25 | six==1.17.0 26 | # via tox 27 | tox==3.28.0 28 | # via 29 | # -r requirements/ci.in 30 | # tox-battery 31 | tox-battery==0.6.2 32 | # via -r requirements/ci.in 33 | virtualenv==20.31.2 34 | # via tox 35 | -------------------------------------------------------------------------------- /requirements/constraints.txt: -------------------------------------------------------------------------------- 1 | # Version constraints for pip-installation. 2 | # 3 | # This file doesn't install any packages. It specifies version constraints 4 | # that will be applied if a package is needed. 5 | # 6 | # When pinning something here, please provide an explanation of why. Ideally, 7 | # link to other information that will help people in the future to remove the 8 | # pin when possible. Writing an issue against the offending project and 9 | # linking to it here is good. 10 | 11 | # Common constraints for edx repos 12 | -c https://raw.githubusercontent.com/edx/edx-lint/master/edx_lint/files/common_constraints.txt 13 | 14 | selenium==3.4.1 15 | bok-choy==0.7.1 16 | -------------------------------------------------------------------------------- /requirements/dev.in: -------------------------------------------------------------------------------- 1 | # Additional requirements for development of this application 2 | -c constraints.txt 3 | 4 | -r pip-tools.txt # pip-tools and its dependencies, for managing requirements files 5 | -r quality.txt # Core and quality check dependencies 6 | -r ci.txt # dependencies for setting up testing in CI 7 | -------------------------------------------------------------------------------- /requirements/pip-tools.in: -------------------------------------------------------------------------------- 1 | # Just the dependencies to run pip-tools, mainly for the "upgrade" make target 2 | 3 | -c constraints.txt 4 | 5 | pip-tools # Contains pip-compile, used to generate pip requirements files 6 | -------------------------------------------------------------------------------- /requirements/pip-tools.txt: -------------------------------------------------------------------------------- 1 | # 2 | # This file is autogenerated by pip-compile with Python 3.11 3 | # by the following command: 4 | # 5 | # make upgrade 6 | # 7 | build==1.2.2.post1 8 | # via pip-tools 9 | click==8.2.1 10 | # via pip-tools 11 | packaging==25.0 12 | # via build 13 | pip-tools==7.4.1 14 | # via -r requirements/pip-tools.in 15 | pyproject-hooks==1.2.0 16 | # via 17 | # build 18 | # pip-tools 19 | wheel==0.45.1 20 | # via pip-tools 21 | 22 | # The following packages are considered to be unsafe in a requirements file: 23 | # pip 24 | # setuptools 25 | -------------------------------------------------------------------------------- /requirements/pip.in: -------------------------------------------------------------------------------- 1 | # Core dependencies for installing other packages 2 | #-c constraints.txt 3 | 4 | pip 5 | setuptools 6 | wheel -------------------------------------------------------------------------------- /requirements/pip.txt: -------------------------------------------------------------------------------- 1 | # 2 | # This file is autogenerated by pip-compile with Python 3.11 3 | # by the following command: 4 | # 5 | # make upgrade 6 | # 7 | wheel==0.45.1 8 | # via -r requirements/pip.in 9 | 10 | # The following packages are considered to be unsafe in a requirements file: 11 | pip==25.1.1 12 | # via -r requirements/pip.in 13 | setuptools==80.9.0 14 | # via -r requirements/pip.in 15 | -------------------------------------------------------------------------------- /requirements/private.readme: -------------------------------------------------------------------------------- 1 | # If there are any Python packages you want to keep in your virtualenv beyond 2 | # those listed in the official requirements files, create a "private.in" file 3 | # and list them there. Generate the corresponding "private.txt" file pinning 4 | # all of their indirect dependencies to specific versions as follows: 5 | 6 | # pip-compile private.in 7 | 8 | # This allows you to use "pip-sync" without removing these packages: 9 | 10 | # pip-sync requirements/*.txt 11 | 12 | # "private.in" and "private.txt" aren't checked into git to avoid merge 13 | # conflicts, and the presence of this file allows "private.*" to be 14 | # included in scripted pip-sync usage without requiring that those files be 15 | # created first. 16 | -------------------------------------------------------------------------------- /requirements/quality.in: -------------------------------------------------------------------------------- 1 | # Requirements for code quality checks 2 | -c constraints.txt 3 | 4 | -r test.txt # Core and testing dependencies for this package 5 | 6 | edx-lint # edX pylint rules and plugins 7 | pycodestyle # PEP 8 compliance validation 8 | -------------------------------------------------------------------------------- /requirements/test.in: -------------------------------------------------------------------------------- 1 | # Requirements for test runs. 2 | -c constraints.txt 3 | 4 | -r base.txt # Core dependencies for this package 5 | 6 | pytest-cov # pytest extension for code coverage statistics 7 | pytest-django # pytest extension for better Django support 8 | ddt # data-driven tests 9 | 10 | bok-choy # integration tests 11 | selenium # integration tests 12 | mock # required by the workbench 13 | openedx-django-pyfs # required by the workbench 14 | 15 | edx-i18n-tools # For i18n_tool dummy 16 | 17 | xblock-sdk # workbench 18 | -------------------------------------------------------------------------------- /run_tests.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ 3 | Run tests for the Poll XBlock 4 | 5 | This script is required to run our selenium tests inside the xblock-sdk workbench 6 | because the workbench SDK's settings file is not inside any python module. 7 | """ 8 | 9 | from __future__ import absolute_import 10 | import logging 11 | import os 12 | import sys 13 | import workbench 14 | 15 | from django.conf import settings 16 | 17 | if __name__ == "__main__": 18 | # Find the location of the XBlock SDK. Note: it must be installed in development mode. 19 | # ('python setup.py develop' or 'pip install -e') 20 | xblock_sdk_dir = os.path.dirname(os.path.dirname(workbench.__file__)) 21 | sys.path.append(xblock_sdk_dir) 22 | 23 | # Use the workbench settings file: 24 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "workbench.settings") 25 | # Configure a range of ports in case the default port of 8081 is in use 26 | os.environ.setdefault("DJANGO_LIVE_TEST_SERVER_ADDRESS", "localhost:8081-8099") 27 | 28 | # Silence too verbose Django logging 29 | logging.disable(logging.DEBUG) 30 | 31 | from django.core.management import execute_from_command_line 32 | args = sys.argv[1:] 33 | paths = [arg for arg in args if arg[0] != '-'] 34 | if not paths: 35 | paths = ["tests/"] 36 | options = [arg for arg in args if arg not in paths] 37 | execute_from_command_line([sys.argv[0], "test"] + paths + options) 38 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Copyright (C) 2015 McKinsey Academy 4 | # 5 | # Authors: 6 | # Jonathan Piacenti 7 | # 8 | # This software's license gives you freedom; you can copy, convey, 9 | # propagate, redistribute and/or modify this program under the terms of 10 | # the GNU Affero General Public License (AGPL) as published by the Free 11 | # Software Foundation (FSF), either version 3 of the License, or (at your 12 | # option) any later version of the AGPL published by the FSF. 13 | # 14 | # This program is distributed in the hope that it will be useful, but 15 | # WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero 17 | # General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU Affero General Public License 20 | # along with this program in a file in the toplevel directory called 21 | # "AGPLv3". If not, see . 22 | # 23 | 24 | """Setup for poll XBlock.""" 25 | 26 | import os 27 | import re 28 | import sys 29 | 30 | from setuptools import setup 31 | 32 | 33 | def load_requirements(*requirements_paths): 34 | """ 35 | Load all requirements from the specified requirements files. 36 | Requirements will include any constraints from files specified 37 | with -c in the requirements files. 38 | Returns a list of requirement strings. 39 | """ 40 | requirements = {} 41 | constraint_files = set() 42 | 43 | # groups "pkg<=x.y.z,..." into ("pkg", "<=x.y.z,...") 44 | requirement_line_regex = re.compile(r"([a-zA-Z0-9-_.\[\]]+)([<>=][^#\s]+)?") 45 | 46 | def add_version_constraint_or_raise(current_line, current_requirements, add_if_not_present): 47 | regex_match = requirement_line_regex.match(current_line) 48 | if regex_match: 49 | package = regex_match.group(1) 50 | version_constraints = regex_match.group(2) 51 | existing_version_constraints = current_requirements.get(package, None) 52 | # fine to add constraints to an unconstrained package, 53 | # raise an error if there are already constraints in place 54 | if existing_version_constraints and existing_version_constraints != version_constraints: 55 | raise BaseException( 56 | f'Multiple constraint definitions found for {package}:' 57 | f' "{existing_version_constraints}" and "{version_constraints}".' 58 | f'Combine constraints into one location with {package}' 59 | f'{existing_version_constraints},{version_constraints}.' 60 | ) 61 | if add_if_not_present or package in current_requirements: 62 | current_requirements[package] = version_constraints 63 | 64 | # read requirements from .in 65 | # store the path to any constraint files that are pulled in 66 | for path in requirements_paths: 67 | with open(path) as reqs: 68 | for line in reqs: 69 | if is_requirement(line): 70 | add_version_constraint_or_raise(line, requirements, True) 71 | if line and line.startswith('-c') and not line.startswith('-c http'): 72 | constraint_files.add(os.path.dirname(path) + '/' + line.split('#')[0].replace('-c', '').strip()) 73 | 74 | # process constraint files: add constraints to existing requirements 75 | for constraint_file in constraint_files: 76 | with open(constraint_file) as reader: 77 | for line in reader: 78 | if is_requirement(line): 79 | add_version_constraint_or_raise(line, requirements, False) 80 | 81 | # process back into list of pkg><=constraints strings 82 | constrained_requirements = [f'{pkg}{version or ""}' for (pkg, version) in sorted(requirements.items())] 83 | return constrained_requirements 84 | 85 | 86 | def is_requirement(line): 87 | """ 88 | Return True if the requirement line is a package requirement. 89 | Returns: 90 | bool: True if the line is not blank, a comment, 91 | a URL, or an included file 92 | """ 93 | return line and line.strip() and not line.startswith(("-r", "#", "-e", "git+", "-c")) 94 | 95 | 96 | def get_version(*file_paths): 97 | """ 98 | Extract the version string from the file. 99 | Input: 100 | - file_paths: relative path fragments to file with 101 | version string 102 | """ 103 | filename = os.path.join(os.path.dirname(__file__), *file_paths) 104 | version_file = open(filename, encoding="utf8").read() 105 | version_match = re.search(r"^__version__ = ['\"]([^'\"]*)['\"]", version_file, re.M) 106 | if version_match: 107 | return version_match.group(1) 108 | raise RuntimeError('Unable to find version string.') 109 | 110 | 111 | def package_data(pkg, roots): 112 | """ 113 | Generic function to find package_data. 114 | 115 | All of the files under each of the `roots` will be declared as package 116 | data for package `pkg`. 117 | """ 118 | data = [] 119 | for root in roots: 120 | for dirname, _, files in os.walk(os.path.join(pkg, root)): 121 | for fname in files: 122 | data.append(os.path.relpath(os.path.join(dirname, fname), pkg)) 123 | 124 | return {pkg: data} 125 | 126 | 127 | VERSION = get_version('poll', '__init__.py') 128 | 129 | if sys.argv[-1] == 'tag': 130 | print("Tagging the version on GitHub:") 131 | os.system("git tag -a %s -m 'version %s'" % (VERSION, VERSION)) 132 | os.system("git push --tags") 133 | sys.exit() 134 | 135 | README = open(os.path.join(os.path.dirname(__file__), 'README.md'), encoding="utf8").read() 136 | 137 | setup( 138 | name='xblock-poll', 139 | version=VERSION, 140 | description='An XBlock for polling users.', 141 | long_description=README, 142 | long_description_content_type='text/markdown', 143 | url='https://github.com/open-craft/xblock-poll', 144 | classifiers=[ 145 | 'Development Status :: 5 - Production/Stable', 146 | 'Intended Audience :: Education', 147 | 'License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+)', 148 | 'Natural Language :: English', 149 | 'Programming Language :: Python :: 3.8', 150 | ], 151 | packages=[ 152 | 'poll', 153 | ], 154 | install_requires=load_requirements('requirements/base.in'), 155 | entry_points={ 156 | 'xblock.v1': [ 157 | 'poll = poll:PollBlock', 158 | 'survey = poll:SurveyBlock', 159 | ] 160 | }, 161 | package_data=package_data("poll", ["static", "public", "translations"]), 162 | ) 163 | -------------------------------------------------------------------------------- /tests.disabled/README.md: -------------------------------------------------------------------------------- 1 | Disabled tests 2 | ============== 3 | 4 | These tests have been disabled because of changes to the xblock-sdk, which dropped support for selenium tests. 5 | 6 | They should be converted and re-enabled when time allows. 7 | -------------------------------------------------------------------------------- /tests.disabled/integration/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-craft/xblock-poll/aef56bd0b94a4a3a0c89f8edd442f7cc0132a760/tests.disabled/integration/__init__.py -------------------------------------------------------------------------------- /tests.disabled/integration/base_test.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Copyright (C) 2015 McKinsey Academy 4 | # 5 | # Authors: 6 | # Jonathan Piacenti 7 | # 8 | # This software's license gives you freedom; you can copy, convey, 9 | # propagate, redistribute and/or modify this program under the terms of 10 | # the GNU Affero General Public License (AGPL) as published by the Free 11 | # Software Foundation (FSF), either version 3 of the License, or (at your 12 | # option) any later version of the AGPL published by the FSF. 13 | # 14 | # This program is distributed in the hope that it will be useful, but 15 | # WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero 17 | # General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU Affero General Public License 20 | # along with this program in a file in the toplevel directory called 21 | # "AGPLv3". If not, see . 22 | # 23 | 24 | from __future__ import absolute_import 25 | from xblockutils.base_test import SeleniumBaseTest 26 | from mock import patch 27 | 28 | 29 | # Default names for inputs for polls/surveys 30 | DEFAULT_SURVEY_NAMES = ('enjoy', 'recommend', 'learn') 31 | DEFAULT_POLL_NAMES = ('choice',) 32 | 33 | 34 | class PollBaseTest(SeleniumBaseTest): 35 | default_css_selector = 'div.poll-block' 36 | module_name = __name__ 37 | 38 | def setUp(self): 39 | super(PollBaseTest, self).setUp() 40 | self.translation_merge_patch = patch('django.utils.translation.trans_real.DjangoTranslation.merge') 41 | self.translation_domain_patch = patch('django.utils.translation.trans_real.DjangoTranslation.domain') 42 | self.translation_domain_patch.start() 43 | self.translation_merge_patch.start() 44 | 45 | def get_submit(self): 46 | return self.browser.find_element_by_css_selector('button.submit') 47 | 48 | def make_selections(self, names): 49 | """ 50 | Selects the first option for each named input. 51 | """ 52 | for name in names: 53 | self.browser.find_element_by_css_selector('input[name="%s"]' % name).click() 54 | 55 | def do_submit(self, names): 56 | """ 57 | Do selection and submit. 58 | """ 59 | self.make_selections(names) 60 | submit = self.get_submit() 61 | submit.click() 62 | self.wait_until_clickable(self.browser.find_element_by_css_selector('.poll-voting-thanks')) 63 | 64 | def tearDown(self): 65 | super(PollBaseTest, self).tearDown() 66 | self.translation_merge_patch.stop() 67 | self.translation_domain_patch.stop() 68 | -------------------------------------------------------------------------------- /tests.disabled/integration/markdown_scenarios.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Copyright (C) 2015 McKinsey Academy 4 | # 5 | # Authors: 6 | # Jonathan Piacenti 7 | # 8 | # This software's license gives you freedom; you can copy, convey, 9 | # propagate, redistribute and/or modify this program under the terms of 10 | # the GNU Affero General Public License (AGPL) as published by the Free 11 | # Software Foundation (FSF), either version 3 of the License, or (at your 12 | # option) any later version of the AGPL published by the FSF. 13 | # 14 | # This program is distributed in the hope that it will be useful, but 15 | # WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero 17 | # General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU Affero General Public License 20 | # along with this program in a file in the toplevel directory called 21 | # "AGPLv3". If not, see . 22 | # 23 | """ 24 | Contains a list of lists that will be used as the DDT arguments for the markdown test. 25 | """ 26 | ddt_scenarios = [ 27 | [ 28 | "Poll Markdown", '.poll-question', 29 | """

This is a test

30 |

This is only a ><test

31 | 32 |
    33 |
  • One
  • 34 |
  • Two
  • 35 |
  • 36 |

    Three

    37 |
  • 38 |
  • 39 |

    First

    40 |
  • 41 |
  • Second
  • 42 |
  • Third
  • 43 |
44 |

We shall find out if markdown is respected.

45 |
46 |

"I have not yet begun to code."

47 |
""" 48 | ], 49 | [ 50 | "Poll Markdown", '.poll-feedback', 51 | """

This is some feedback

52 |

This is a link

53 |

This is also a link.

54 |

This is a paragraph with emphasized and bold text, and both.

""", 55 | False 56 | ], 57 | [ 58 | "Poll Markdown", "label.poll-answer-text", "

I feel like this test will passtest.

", 59 | True, False 60 | ], 61 | [ 62 | "Poll Markdown", "label.poll-answer-label", "

I feel like this test will passtest.

", 63 | False, True 64 | ], 65 | [ 66 | "Survey Markdown", '.survey-question', "

I feel like this test will passtest.

" 67 | ], 68 | [ 69 | "Survey Markdown", '.poll-feedback', 70 | """

This is some feedback

71 |

This is a link

72 |

This is also a link.

73 |

This is a paragraph with emphasized and bold text, and both.

""", 74 | False 75 | ], 76 | ] 77 | -------------------------------------------------------------------------------- /tests.disabled/integration/studio_scenarios.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Copyright (C) 2015 McKinsey Academy 4 | # 5 | # Authors: 6 | # Jonathan Piacenti 7 | # 8 | # This software's license gives you freedom; you can copy, convey, 9 | # propagate, redistribute and/or modify this program under the terms of 10 | # the GNU Affero General Public License (AGPL) as published by the Free 11 | # Software Foundation (FSF), either version 3 of the License, or (at your 12 | # option) any later version of the AGPL published by the FSF. 13 | # 14 | # This program is distributed in the hope that it will be useful, but 15 | # WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero 17 | # General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU Affero General Public License 20 | # along with this program in a file in the toplevel directory called 21 | # "AGPLv3". If not, see . 22 | # 23 | """ 24 | Contains a list of lists that will be used as the DDT arguments for the studio test. 25 | """ 26 | ddt_scenarios = [ 27 | [ 28 | 'Poll Studio', 29 | 'answer', 30 | 4, 31 | 'label.poll-answer-text' 32 | ], 33 | [ 34 | 'Survey Studio', 35 | 'answer', 36 | 5, 37 | 'th.survey-answer' 38 | ], 39 | [ 40 | 'Survey Studio', 41 | 'question', 42 | 4, 43 | 'th.survey-question' 44 | ], 45 | ] 46 | -------------------------------------------------------------------------------- /tests.disabled/integration/test_defaults.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Copyright (C) 2015 McKinsey Academy 4 | # 5 | # Authors: 6 | # Jonathan Piacenti 7 | # 8 | # This software's license gives you freedom; you can copy, convey, 9 | # propagate, redistribute and/or modify this program under the terms of 10 | # the GNU Affero General Public License (AGPL) as published by the Free 11 | # Software Foundation (FSF), either version 3 of the License, or (at your 12 | # option) any later version of the AGPL published by the FSF. 13 | # 14 | # This program is distributed in the hope that it will be useful, but 15 | # WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero 17 | # General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU Affero General Public License 20 | # along with this program in a file in the toplevel directory called 21 | # "AGPLv3". If not, see . 22 | # 23 | """ 24 | Tests to verify a default poll XBlock is a functional demo. 25 | 26 | Deeper investigation should be tested in test_poll_functions. 27 | """ 28 | from __future__ import absolute_import 29 | from selenium.common.exceptions import NoSuchElementException 30 | from .base_test import PollBaseTest 31 | 32 | 33 | class TestDefault(PollBaseTest): 34 | """ 35 | Tests to run against the default XBlock configurations. 36 | """ 37 | def test_default_poll(self): 38 | """ 39 | Verifies that a default poll loads, that it can be voted on, and that 40 | the tally displays afterward. Verifies that the feedback section does 41 | not load since it is not enabled by default. 42 | """ 43 | self.go_to_page('Poll Defaults') 44 | button = self.browser.find_element_by_css_selector('input[type=radio]') 45 | button.click() 46 | submit = self.get_submit() 47 | submit.click() 48 | 49 | self.wait_until_exists('.poll-percent-display') 50 | 51 | # Should now be on the results page. 52 | self.assertEqual(self.browser.find_element_by_css_selector('.poll-percent-display').text, '100%') 53 | 54 | # No feedback section. 55 | self.assertRaises(NoSuchElementException, self.browser.find_element_by_css_selector, '.poll-feedback') 56 | 57 | def test_default_survey(self): 58 | """ 59 | Verifies that a default survey loads, that it can be voted on, and 60 | that the tally displays afterward. Verifies that the feedback section 61 | does not load since it is not enabled by default. 62 | """ 63 | self.go_to_page('Survey Defaults') 64 | names = ['enjoy', 'recommend', 'learn'] 65 | 66 | # Select the first answer for each. 67 | for name in names: 68 | self.browser.find_element_by_css_selector('input[name="%s"]' % name).click() 69 | 70 | submit = self.get_submit() 71 | submit.click() 72 | 73 | self.wait_until_exists('.survey-percentage') 74 | 75 | # Should now be on the results page. 76 | for element in self.browser.find_elements_by_css_selector('table > tr'): 77 | # Questions are 'th', so the first 'td' is the first answer. 78 | self.assertEqual(element.find_elements_by_css_selector('td')[0].text, '100%') 79 | 80 | # No feedback section. 81 | self.assertRaises(NoSuchElementException, self.browser.find_element_by_css_selector, '.poll-feedback') 82 | -------------------------------------------------------------------------------- /tests.disabled/integration/test_layout.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Copyright (C) 2015 McKinsey Academy 4 | # 5 | # Authors: 6 | # Jonathan Piacenti 7 | # 8 | # This software's license gives you freedom; you can copy, convey, 9 | # propagate, redistribute and/or modify this program under the terms of 10 | # the GNU Affero General Public License (AGPL) as published by the Free 11 | # Software Foundation (FSF), either version 3 of the License, or (at your 12 | # option) any later version of the AGPL published by the FSF. 13 | # 14 | # This program is distributed in the hope that it will be useful, but 15 | # WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero 17 | # General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU Affero General Public License 20 | # along with this program in a file in the toplevel directory called 21 | # "AGPLv3". If not, see . 22 | # 23 | 24 | """ 25 | Test to make sure the layout for results is sane when taking images into 26 | account. 27 | """ 28 | from __future__ import absolute_import 29 | from ddt import ddt, unpack, data 30 | from tests.integration.base_test import PollBaseTest 31 | 32 | 33 | @ddt 34 | class TestLayout(PollBaseTest): 35 | """ 36 | Do tests to verify that the layout of elements makes sense depeneding on 37 | the number of images. 38 | """ 39 | 40 | @unpack 41 | @data(('Poll All Pictures', 4), ('Poll One Picture', 4), ('Poll No Pictures', 0)) 42 | def test_images(self, scenario, count): 43 | """ 44 | Verify the poll-image divs only appear when they need to. 45 | """ 46 | self.go_to_page(scenario) 47 | pics = self.browser.find_elements_by_css_selector('.poll-image') 48 | self.assertEqual(len(pics), count) 49 | 50 | if not count: 51 | self.browser.find_element_by_css_selector('.poll-answer-text').click() 52 | else: 53 | # Pics should be within labels. 54 | self.browser.find_element_by_css_selector('.poll-image img').click() 55 | self.get_submit().click() 56 | 57 | self.wait_until_exists('.percentage-gauge') 58 | 59 | self.assertEqual(len(self.browser.find_elements_by_css_selector('.poll-image')), count) 60 | 61 | @data('Poll Size Check', 'Poll Size Check Image') 62 | def test_poll_size(self, scenario): 63 | self.go_to_page(scenario) 64 | width = self.browser.get_window_size()['width'] 65 | poll = self.browser.find_element_by_css_selector('.poll-block') 66 | self.assertLess(poll.__getattribute__('rect')['width'], width) 67 | 68 | self.browser.find_element_by_css_selector('.poll-answer-text').click() 69 | self.get_submit().click() 70 | 71 | self.wait_until_exists('.percentage-gauge') 72 | 73 | poll = self.browser.find_element_by_css_selector('.poll-block') 74 | self.assertLess(poll.__getattribute__('rect')['width'], width) 75 | -------------------------------------------------------------------------------- /tests.disabled/integration/test_markdown.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Copyright (C) 2015 McKinsey Academy 4 | # 5 | # Authors: 6 | # Jonathan Piacenti 7 | # 8 | # This software's license gives you freedom; you can copy, convey, 9 | # propagate, redistribute and/or modify this program under the terms of 10 | # the GNU Affero General Public License (AGPL) as published by the Free 11 | # Software Foundation (FSF), either version 3 of the License, or (at your 12 | # option) any later version of the AGPL published by the FSF. 13 | # 14 | # This program is distributed in the hope that it will be useful, but 15 | # WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero 17 | # General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU Affero General Public License 20 | # along with this program in a file in the toplevel directory called 21 | # "AGPLv3". If not, see . 22 | # 23 | """ 24 | Tests to make sure that markdown is both useful and secure. 25 | """ 26 | from __future__ import absolute_import 27 | from ddt import ddt, unpack, data 28 | from .markdown_scenarios import ddt_scenarios 29 | from .base_test import PollBaseTest 30 | 31 | 32 | @ddt 33 | class MarkdownTestCase(PollBaseTest): 34 | """ 35 | Tests for the Markdown functionality. 36 | """ 37 | 38 | def get_selector_text(self, selector): 39 | return self.browser.find_element_by_css_selector(selector).get_attribute('innerHTML').strip() 40 | 41 | @data(*ddt_scenarios) 42 | @unpack 43 | def test_markdown(self, page, selector, result, front=True, back=True): 44 | """ 45 | Test Markdown for a field. 46 | 47 | selector is a CSS selector to check for markdown results 48 | result is the desired result string 49 | front means the check will be done before the form is submitted 50 | back means it will be done afterward. 51 | 52 | Both are checked by default. 53 | """ 54 | self.go_to_page(page) 55 | if front: 56 | self.assertEqual(self.get_selector_text(selector), result) 57 | if back: 58 | self.browser.find_element_by_css_selector('input[type=radio]').click() 59 | self.get_submit().click() 60 | self.wait_until_exists('.poll-footnote') 61 | self.assertEqual(self.get_selector_text(selector), result) 62 | -------------------------------------------------------------------------------- /tests.disabled/integration/test_max_submissions.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Copyright (C) 2015 McKinsey Academy 4 | # 5 | # Authors: 6 | # Jonathan Piacenti 7 | # 8 | # This software's license gives you freedom; you can copy, convey, 9 | # propagate, redistribute and/or modify this program under the terms of 10 | # the GNU Affero General Public License (AGPL) as published by the Free 11 | # Software Foundation (FSF), either version 3 of the License, or (at your 12 | # option) any later version of the AGPL published by the FSF. 13 | # 14 | # This program is distributed in the hope that it will be useful, but 15 | # WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero 17 | # General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU Affero General Public License 20 | # along with this program in a file in the toplevel directory called 21 | # "AGPLv3". If not, see . 22 | # 23 | 24 | from ddt import ddt, unpack, data 25 | from tests.integration.base_test import PollBaseTest, DEFAULT_POLL_NAMES, DEFAULT_SURVEY_NAMES 26 | 27 | scenarios_infinite = ( 28 | ('Survey Max Submissions Infinite', DEFAULT_SURVEY_NAMES), 29 | ('Poll Max Submissions Infinite', DEFAULT_POLL_NAMES), 30 | ) 31 | 32 | scenarios_max = ( 33 | ('Survey Max Submissions', DEFAULT_SURVEY_NAMES), 34 | ('Poll Max Submissions', DEFAULT_POLL_NAMES), 35 | ) 36 | 37 | 38 | @ddt 39 | class TestPrivateResults(PollBaseTest): 40 | @unpack 41 | @data(*scenarios_infinite) 42 | def test_infinite_submissions(self, page, names): 43 | """ 44 | We can't actually test infinite submissions, but we can be reasonably certain it will work 45 | if it has worked a few times more than we have allocated, which should be '0' according to the 46 | setting, which is actually code for 'as often as you like' rather than '0 attempts permitted'. 47 | 48 | Try this by staying on the page, and by loading it up again. 49 | """ 50 | for __ in range(0, 2): 51 | self.go_to_page(page) 52 | for ___ in range(1, 5): 53 | self.do_submit(names) 54 | self.wait_until_exists('button.submit:enabled') 55 | 56 | @unpack 57 | @data(*scenarios_max) 58 | def test_max_submissions_one_view(self, page, names): 59 | """ 60 | Verify that the user can't submit more than a certain number of times. Our XML allows two submissions. 61 | """ 62 | self.go_to_page(page) 63 | for __ in range(0, 2): 64 | self.do_submit(names) 65 | self.assertFalse(self.get_submit().is_enabled()) 66 | 67 | @unpack 68 | @data(*scenarios_max) 69 | def test_max_submissions_reload(self, page, names): 70 | """ 71 | Same as above, but revisit the page between attempts. 72 | """ 73 | self.go_to_page(page) 74 | self.do_submit(names) 75 | self.go_to_page(page) 76 | self.do_submit(names) 77 | self.assertFalse(self.get_submit().is_enabled()) 78 | 79 | @unpack 80 | @data(*scenarios_max) 81 | def test_max_submissions_counter(self, page, names): 82 | """ 83 | Verify a counter is displayed stating how many submissions have been used. 84 | Our XML allows two submissions, and we must mind the off-by-one for range. 85 | """ 86 | self.go_to_page(page) 87 | counter_div = self.browser.find_element_by_css_selector('.poll-submissions-count') 88 | counter = self.browser.find_element_by_css_selector('.poll-current-count') 89 | self.assertFalse(counter_div.is_displayed()) 90 | for i in range(1, 3): 91 | self.do_submit(names) 92 | self.assertTrue(counter_div.is_displayed()) 93 | self.assertEqual(counter.text.strip(), str(i)) 94 | -------------------------------------------------------------------------------- /tests.disabled/integration/test_private_results.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Copyright (C) 2015 McKinsey Academy 4 | # 5 | # Authors: 6 | # Jonathan Piacenti 7 | # 8 | # This software's license gives you freedom; you can copy, convey, 9 | # propagate, redistribute and/or modify this program under the terms of 10 | # the GNU Affero General Public License (AGPL) as published by the Free 11 | # Software Foundation (FSF), either version 3 of the License, or (at your 12 | # option) any later version of the AGPL published by the FSF. 13 | # 14 | # This program is distributed in the hope that it will be useful, but 15 | # WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero 17 | # General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU Affero General Public License 20 | # along with this program in a file in the toplevel directory called 21 | # "AGPLv3". If not, see . 22 | # 23 | 24 | from __future__ import absolute_import 25 | from ddt import ddt, unpack, data 26 | from selenium.common.exceptions import NoSuchElementException 27 | 28 | from poll.poll import PollBase 29 | from .base_test import PollBaseTest, DEFAULT_SURVEY_NAMES, DEFAULT_POLL_NAMES 30 | 31 | 32 | scenarios = ('Survey Private', DEFAULT_SURVEY_NAMES), ('Poll Private', DEFAULT_POLL_NAMES) 33 | 34 | def stub_view_permission(can_view): 35 | """ 36 | Patches the 'can_view_private_results' function to return specified answer. 37 | """ 38 | def stub_view_permissions_decorator(test_fn): 39 | def test_patched(self, page_name, names): 40 | original = PollBase.can_view_private_results 41 | try: 42 | PollBase.can_view_private_results = lambda self: can_view 43 | test_fn(self, page_name, names) 44 | finally: 45 | PollBase.can_view_private_results = original 46 | return test_patched 47 | return stub_view_permissions_decorator 48 | 49 | 50 | @ddt 51 | class TestPrivateResults(PollBaseTest): 52 | """ 53 | Check the functionality of private results. 54 | """ 55 | 56 | @unpack 57 | @data(*scenarios) 58 | def test_form_remains(self, page_name, names): 59 | """ 60 | User should still have a form presented after submitting so they can resubmit. 61 | """ 62 | self.go_to_page(page_name) 63 | # Form should be there to begin with, of course. 64 | self.browser.find_element_by_css_selector('div.poll-block form') 65 | self.do_submit(names) 66 | 67 | @unpack 68 | @data(*scenarios) 69 | def test_no_results(self, page_name, names): 70 | """ 71 | The handlebars template for results should never be called, and the form should persist. 72 | """ 73 | self.go_to_page(page_name) 74 | self.do_submit(names) 75 | 76 | # No results should be showing. 77 | self.assertRaises(NoSuchElementException, self.browser.find_element_by_css_selector, '.poll-results') 78 | self.assertRaises(NoSuchElementException, self.browser.find_element_by_css_selector, '.poll-footnote') 79 | 80 | @unpack 81 | @data(*scenarios) 82 | def test_submit_button(self, page_name, names): 83 | self.go_to_page(page_name) 84 | submit = self.get_submit() 85 | self.assertIn('Submit', submit.get_attribute('outerHTML')) 86 | 87 | self.make_selections(names) 88 | submit.click() 89 | self.wait_until_clickable(self.browser.find_element_by_css_selector('.poll-voting-thanks')) 90 | 91 | self.assertIn('Submit', submit.get_attribute('outerHTML')) 92 | # ^ Note that in previous versions, this text would change to "Resubmit", 93 | # but we removed that functionality in v1.2.2 94 | 95 | @unpack 96 | @data(*scenarios) 97 | def test_feedback_display(self, page_name, names): 98 | self.go_to_page(page_name) 99 | self.assertFalse(self.browser.find_element_by_css_selector('.poll-feedback').is_displayed()) 100 | self.do_submit(names) 101 | self.assertTrue(self.browser.find_element_by_css_selector('.poll-feedback').is_displayed()) 102 | 103 | @unpack 104 | @data(*scenarios) 105 | @stub_view_permission(False) 106 | def test_results_button_visibility_without_permission(self, page_name, names): 107 | self.go_to_page(page_name) 108 | self.assertRaises(NoSuchElementException, self.browser.find_element_by_css_selector, '.view-results-button') 109 | 110 | @unpack 111 | @data(*scenarios) 112 | @stub_view_permission(True) 113 | def test_results_button_visibility_with_permission(self, page_name, names): 114 | self.go_to_page(page_name) 115 | self.browser.find_element_by_css_selector('.view-results-button') 116 | 117 | @unpack 118 | @data(*scenarios) 119 | @stub_view_permission(True) 120 | def test_results_button(self, page_name, names): 121 | self.go_to_page(page_name) 122 | button = self.browser.find_element_by_css_selector('.view-results-button') 123 | button.click() 124 | self.wait_until_exists('.poll-results') 125 | self.wait_until_exists('.poll-footnote') 126 | -------------------------------------------------------------------------------- /tests.disabled/integration/test_studio.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Copyright (C) 2015 McKinsey Academy 4 | # 5 | # Authors: 6 | # Jonathan Piacenti 7 | # 8 | # This software's license gives you freedom; you can copy, convey, 9 | # propagate, redistribute and/or modify this program under the terms of 10 | # the GNU Affero General Public License (AGPL) as published by the Free 11 | # Software Foundation (FSF), either version 3 of the License, or (at your 12 | # option) any later version of the AGPL published by the FSF. 13 | # 14 | # This program is distributed in the hope that it will be useful, but 15 | # WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero 17 | # General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU Affero General Public License 20 | # along with this program in a file in the toplevel directory called 21 | # "AGPLv3". If not, see . 22 | # 23 | 24 | """ 25 | Runs tests for the studio views. 26 | """ 27 | from __future__ import absolute_import 28 | from ddt import ddt, unpack, data 29 | from selenium.common.exceptions import NoSuchElementException 30 | from selenium.webdriver.support.wait import WebDriverWait 31 | from .base_test import PollBaseTest 32 | from .studio_scenarios import ddt_scenarios 33 | 34 | 35 | @ddt 36 | class StudioTest(PollBaseTest): 37 | """ 38 | Mixin class for poll studio tests. 39 | """ 40 | default_css_selector = '#settings-tab' 41 | 42 | def studio_save(self): 43 | self.browser.find_element_by_css_selector('#poll-submit-options').click() 44 | 45 | @data(*ddt_scenarios) 46 | @unpack 47 | def test_add_items(self, page_name, item_type, num_existing_items, answer_css_selector): 48 | """ 49 | Verify we can add more than one item and they both save. 50 | """ 51 | self.go_to_page(page_name, view_name='studio_view') 52 | add_item_button = self.browser.find_element_by_css_selector('#poll-add-%s' % item_type) 53 | # Add two answers 54 | add_item_button.click() 55 | add_item_button.click() 56 | # Make sure we get forms for both. 57 | wait = WebDriverWait(self.browser, self.timeout) 58 | selector = '.poll-%s-studio-item' % item_type 59 | total = num_existing_items + 2 60 | 61 | def get_last_item(driver): 62 | items = driver.find_elements_by_css_selector(selector) 63 | try: 64 | # Start from 0 65 | return items[total - 1] 66 | except IndexError: 67 | raise NoSuchElementException 68 | 69 | wait.until(get_last_item, u"{}th copy of selector '{}' should exist.".format(total, selector)) 70 | 71 | answers = self.browser.find_elements_by_css_selector('.poll-%s-studio-item' % item_type) 72 | results = [] 73 | for index, element in enumerate(answers[-2:]): 74 | # First input is the label, which should always be there. 75 | label = element.find_element_by_css_selector('input') 76 | text = 'Test %s %s' % (item_type, index) 77 | label.send_keys(text) 78 | results.append(text) 79 | 80 | self.studio_save() 81 | self.go_to_page(page_name, css_selector='div.poll-block') 82 | answers = [element.text for element in self.browser.find_elements_by_css_selector(answer_css_selector)] 83 | self.assertEqual(answers[-2:], results) 84 | 85 | -------------------------------------------------------------------------------- /tests.disabled/integration/test_submit_button.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Copyright (C) 2015 McKinsey Academy 4 | # 5 | # Authors: 6 | # Jonathan Piacenti 7 | # 8 | # This software's license gives you freedom; you can copy, convey, 9 | # propagate, redistribute and/or modify this program under the terms of 10 | # the GNU Affero General Public License (AGPL) as published by the Free 11 | # Software Foundation (FSF), either version 3 of the License, or (at your 12 | # option) any later version of the AGPL published by the FSF. 13 | # 14 | # This program is distributed in the hope that it will be useful, but 15 | # WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero 17 | # General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU Affero General Public License 20 | # along with this program in a file in the toplevel directory called 21 | # "AGPLv3". If not, see . 22 | # 23 | 24 | from __future__ import absolute_import 25 | from tests.integration.base_test import PollBaseTest 26 | 27 | from unittest import skip 28 | 29 | class TestSubmitButton(PollBaseTest): 30 | 31 | @skip("Flaky test") 32 | def test_submit_button(self): 33 | """ 34 | Goal: We have to make sure that submit button gets disabled right 35 | after it is clicked. We cannot test with 100% assurance by adding a 36 | method in other tests such as test_functions.py because in that case 37 | submit button is anyway disabled after the ajax request. 38 | 39 | We can utilize infinite submission feature and check if the submit 40 | button was disabled (because of js) and then re-enabled (because of 41 | ajax request). 42 | """ 43 | self.go_to_page('Poll Submit Button') 44 | # Find all the radio choices 45 | answer_elements = self.browser.find_elements_by_css_selector('label.poll-answer-text') 46 | # Select the first choice 47 | answer_elements[1].click() 48 | # When an answer is selected, make sure submit is enabled. 49 | self.wait_until_exists('button.submit:enabled') 50 | 51 | submit_button = self.get_submit() 52 | submit_button.click() 53 | 54 | # Make sure that submit button is disabled right away 55 | self.assertFalse(submit_button.is_enabled()) 56 | 57 | self.wait_until_clickable(self.browser.find_element_by_css_selector('.poll-voting-thanks')) 58 | # Wait until the ajax request is finished and submit button is enabled 59 | self.assertTrue(self.get_submit().is_enabled()) 60 | -------------------------------------------------------------------------------- /tests.disabled/integration/xml/poll_all_pictures.xml: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /tests.disabled/integration/xml/poll_defaults.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /tests.disabled/integration/xml/poll_functions.xml: -------------------------------------------------------------------------------- 1 | 5 | -------------------------------------------------------------------------------- /tests.disabled/integration/xml/poll_markdown.xml: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /tests.disabled/integration/xml/poll_max_submissions.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /tests.disabled/integration/xml/poll_max_submissions_infinite.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /tests.disabled/integration/xml/poll_no_pictures.xml: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /tests.disabled/integration/xml/poll_one_picture.xml: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /tests.disabled/integration/xml/poll_private.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /tests.disabled/integration/xml/poll_size_check.xml: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /tests.disabled/integration/xml/poll_size_check_image.xml: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /tests.disabled/integration/xml/poll_studio.xml: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /tests.disabled/integration/xml/poll_submit_button.xml: -------------------------------------------------------------------------------- 1 | 7 | -------------------------------------------------------------------------------- /tests.disabled/integration/xml/survey_defaults.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /tests.disabled/integration/xml/survey_functions.xml: -------------------------------------------------------------------------------- 1 | 5 | -------------------------------------------------------------------------------- /tests.disabled/integration/xml/survey_markdown.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /tests.disabled/integration/xml/survey_max_submissions.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /tests.disabled/integration/xml/survey_max_submissions_infinite.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /tests.disabled/integration/xml/survey_multiple.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /tests.disabled/integration/xml/survey_private.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /tests.disabled/integration/xml/survey_studio.xml: -------------------------------------------------------------------------------- 1 | 5 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-craft/xblock-poll/aef56bd0b94a4a3a0c89f8edd442f7cc0132a760/tests/__init__.py -------------------------------------------------------------------------------- /tests/unit/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-craft/xblock-poll/aef56bd0b94a4a3a0c89f8edd442f7cc0132a760/tests/unit/__init__.py -------------------------------------------------------------------------------- /tests/utils.py: -------------------------------------------------------------------------------- 1 | # Test mocks and helpers 2 | from __future__ import absolute_import 3 | from webob import Request 4 | from xblock.runtime import DictKeyValueStore, KvsFieldData 5 | from xblock.test.tools import TestRuntime 6 | 7 | 8 | def make_request(body, method='POST'): 9 | """ 10 | Helper method to make request 11 | """ 12 | request = Request.blank('/') 13 | request.body = body.encode('utf-8') 14 | request.method = method 15 | return request 16 | 17 | # pylint: disable=abstract-method 18 | class MockRuntime(TestRuntime): 19 | """ 20 | Provides a mock XBlock runtime object. 21 | """ 22 | def __init__(self, **kwargs): 23 | field_data = kwargs.get('field_data', KvsFieldData(DictKeyValueStore())) 24 | super(MockRuntime, self).__init__(field_data=field_data) 25 | -------------------------------------------------------------------------------- /tox.ini: -------------------------------------------------------------------------------- 1 | [tox] 2 | envlist = py{311,312}-django{42,52}, quality, release 3 | 4 | [pycodestyle] 5 | exclude = .git,.tox 6 | 7 | [testenv] 8 | allowlist_externals = 9 | make 10 | deps = 11 | django42: Django>=4.2,<4.3 12 | django52: Django>=5.2,<5.3 13 | -r{toxinidir}/requirements/test.txt 14 | commands = 15 | make install_linux_dev_firefox 16 | make linux_dev_test 17 | passenv = 18 | DISPLAY 19 | 20 | [testenv:quality] 21 | deps = 22 | -r{toxinidir}/requirements/quality.txt 23 | commands = 24 | pycodestyle poll --max-line-length=120 25 | pylint poll 26 | 27 | [testenv:package] 28 | deps = 29 | build 30 | twine 31 | commands = 32 | python -m build 33 | twine check dist/* 34 | --------------------------------------------------------------------------------