diff --git a/.gitignore b/.gitignore index f0193121d077fce776b6d6c844773e41123b4575..3fc425ee2f1b47b80c75c73df9b536a7930e4a22 100644 --- a/.gitignore +++ b/.gitignore @@ -7,8 +7,7 @@ local_settings.py *.py[co] .sw[opn] doc/_build -components -bower_components +node_modules setuptools-[0-9]* virtualenv-[0-9]* diff --git a/course/templates/course/gradebook-by-opp.html b/course/templates/course/gradebook-by-opp.html index 8a48cb5410db394eb0e4833a7e33b82df7bc36f6..3b1a7bdb33caebc90485cd1ad7480450fb1a7172 100644 --- a/course/templates/course/gradebook-by-opp.html +++ b/course/templates/course/gradebook-by-opp.html @@ -225,7 +225,7 @@ "paging": false, "ordering": true, "columnDefs": [{ type: 'name', targets: 1 }], - "language": {url: '{% static "datatables-i18n/i18n/" %}{{LANG}}.json'}, + "language": {url: '{% static "datatables.net-plugins/i18n/" %}{{LANG}}.lang'}, } ); new $.fn.dataTable.FixedColumns(tbl); diff --git a/course/templates/course/gradebook-opp-list.html b/course/templates/course/gradebook-opp-list.html index 06f3b83d7fbd6e2a29c6ff02089205b548dd52e4..55294cb5483a89c5654a1c7c3e597cb3f7f81de8 100644 --- a/course/templates/course/gradebook-opp-list.html +++ b/course/templates/course/gradebook-opp-list.html @@ -76,7 +76,7 @@ "scrollCollapse": true, "paging": false, "ordering": true, - "language": {url: '{% static "datatables-i18n/i18n/" %}{{LANG}}.json'}, + "language": {url: '{% static "datatables.net-plugins/i18n/" %}{{LANG}}.lang'}, } ); diff --git a/course/templates/course/gradebook-participant.html b/course/templates/course/gradebook-participant.html index 68a4a2a90c2cd69301fd0167448b8f46f93132ed..ea4e15e5a4e0a308b77e4fab9f624d4685ecdb55 100644 --- a/course/templates/course/gradebook-participant.html +++ b/course/templates/course/gradebook-participant.html @@ -95,7 +95,7 @@ "scrollCollapse": true, "paging": false, "columnDefs": [{ type: 'name', targets: 1 }], - "language": {url: '{% static "datatables-i18n/i18n/" %}{{LANG}}.json'}, + "language": {url: '{% static "datatables.net-plugins/i18n/" %}{{LANG}}.lang'}, } ); diff --git a/course/templates/course/gradebook.html b/course/templates/course/gradebook.html index 48154c704861c44314f4db0da25897cfcd53c644..0f1241f6b6a7fa874aef352673961458d7f100c8 100644 --- a/course/templates/course/gradebook.html +++ b/course/templates/course/gradebook.html @@ -77,7 +77,7 @@ "paging": true, "ordering": true, "columnDefs": [{ type: 'name', targets: 1 }], - "language": {url: '{% static "datatables-i18n/i18n/" %}{{LANG}}.json'}, + "language": {url: '{% static "datatables.net-plugins/i18n/" %}{{LANG}}.lang'}, } ); new $.fn.dataTable.FixedColumns(tbl); diff --git a/course/templates/course/participation-table.html b/course/templates/course/participation-table.html index bde4c58eba7747121a04fb38e089064fb72fb4d6..aca66352c49be95ac8d2919a3b8f3f53cf83b17f 100644 --- a/course/templates/course/participation-table.html +++ b/course/templates/course/participation-table.html @@ -64,6 +64,6 @@ "paging": false, "ordering": true, "columnDefs": [{ type: 'name', targets: 1 }], - "language": {url: '{% static "datatables-i18n/i18n/" %}{{LANG}}.json'}, + "language": {url: '{% static "datatables.net-plugins/i18n/" %}{{LANG}}.lang'}, } ); diff --git a/course/templatetags/coursetags.py b/course/templatetags/coursetags.py index 6d15e4a2ed3cefbfa7065937609e00ae1f22ff01..aba4d2d4f3bccc2d2c5709b38e024c6e065b2217 100644 --- a/course/templatetags/coursetags.py +++ b/course/templatetags/coursetags.py @@ -24,7 +24,7 @@ THE SOFTWARE. from django.template import Library, Node, TemplateSyntaxError from django.utils import translation -from relate.utils import to_js_lang_name +from relate.utils import to_datatables_lang_name register = Library() @@ -36,8 +36,8 @@ class GetCurrentLanguageJsFmtNode(Node): self.variable = variable def render(self, context): - js_lang_name = to_js_lang_name(translation.get_language()) - context[self.variable] = js_lang_name + datatables_lang_name = to_datatables_lang_name(translation.get_language()) + context[self.variable] = datatables_lang_name return '' diff --git a/doc/misc.rst b/doc/misc.rst index 4c106c9c6cecbfa58283dce087428fb5cf7ac4e5..e08b73d72288811bc1fbce38637041a880516379 100644 --- a/doc/misc.rst +++ b/doc/misc.rst @@ -4,8 +4,8 @@ Installation RELATE currently works with Python 2.7 and Python 3. (By default, :file:`requirements.txt` is set up for Python 3. See below for edit instructions if you are using Python 2.) -Install `bower `_ and its dependencies, as described on its -web page. +Install [Node.js](https://nodejs.org) and NPM, or [Yarn](https://yarnpkg.com) +(alternative package manager) at your option. (Optional) Make a virtualenv to install to:: @@ -36,7 +36,11 @@ Initialize the database:: Retrieve static (JS/CSS) dependencies:: - python manage.py bower_install + npm install + +or + + yarn Run the server:: diff --git a/package.json b/package.json new file mode 100644 index 0000000000000000000000000000000000000000..49e8d5356eff241ef4590949074d7e7524f9d805 --- /dev/null +++ b/package.json @@ -0,0 +1,21 @@ +{ + "dependencies": { + "blueimp-tmpl": "^3.11.0", + "bootstrap": "^3.3.7", + "codemirror": "^5.35.0", + "datatables.net": "^1.10.16", + "datatables.net-bs": "^1.10.16", + "datatables.net-fixedcolumns": "^3.2.4", + "datatables.net-fixedcolumns-bs": "^3.2.4", + "datatables.net-plugins": "^1.10.15", + "font-awesome": "^4.7.0", + "fullcalendar": "^2.9.1", + "jquery": "^3.3.1", + "jquery-ui-dist": "^1.12.1", + "jstree": "^3.3.5", + "mathjax": "^2.7.3", + "select2": "^4.0.5", + "select2-bootstrap-theme": "^0.1.0-beta.10", + "video.js": "^5.20.5" + } +} diff --git a/relate/settings.py b/relate/settings.py index 967e14833f3b99cb1edbbde5295bca8ba7bb313c..5abfa1ed28f73cfe2cbaea7e2ba5f3cda2a90b32 100644 --- a/relate/settings.py +++ b/relate/settings.py @@ -54,7 +54,6 @@ INSTALLED_APPS = ( "crispy_forms", "jsonfield", "bootstrap3_datetime", - "djangobower", "django_select2", # message queue @@ -108,31 +107,10 @@ AUTH_USER_MODEL = 'accounts.User' # }}} -# {{{ bower packages - -BOWER_COMPONENTS_ROOT = os.path.join(BASE_DIR, "components") +# {{{ django-npm STATICFILES_FINDERS = tuple(STATICFILES_FINDERS) + ( - "djangobower.finders.BowerFinder", - ) - -BOWER_INSTALLED_APPS = ( - "bootstrap#3.3.4", - "fontawesome#4.4.0", - "videojs#5.6.0", - "MathJax", - "codemirror#5.2.0", - "fullcalendar#2.3.1", - "jqueryui", - "datatables.net", - "datatables-i18n", - "datatables.net-bs", - "datatables.net-fixedcolumns", - "datatables.net-fixedcolumns-bs", - "jstree#3.2.1", - "select2#4.0.1", - "select2-bootstrap-css", - "blueimp-tmpl", + "npm.finders.NpmFinder", ) CODEMIRROR_PATH = "codemirror" diff --git a/relate/templates/base.html b/relate/templates/base.html index 62ba95c56b7f9ee201f1682c79bd7f2616dd852d..5474c2bdd42d78523333b5d225be7c4a10d5531d 100644 --- a/relate/templates/base.html +++ b/relate/templates/base.html @@ -13,17 +13,17 @@ {% block head_assets %} {% block head_assets_before_form_media %} - - + + - + {# Don't be tempted to move all this JS stuff down to the end. #} {# The datepicker generates inline JS that relies on this being loaded. #} - - - + + + {% endblock %} @@ -184,7 +184,7 @@ ================================================== --> - - +{# FIXME: minified files not available per https://github.com/DataTables/DataTables/issues/1018 #} + + + - + {# allow sorting fields using localeCompare method #} diff --git a/relate/utils.py b/relate/utils.py index b03e2b71dae817fda45efa8a4740ec928f3ae0db..6408afff0aec178c67c04ff0ac8879d9fdc15c80 100644 --- a/relate/utils.py +++ b/relate/utils.py @@ -31,6 +31,7 @@ import datetime import django.forms as forms from django.utils.translation import ugettext_lazy as _ import dulwich.repo +import pycountry from typing import Union @@ -370,16 +371,23 @@ if 0: # {{{ convert django language name to js styled language name -def to_js_lang_name(dj_lang_name): +def to_datatables_lang_name(dj_lang_name): """ - Turns a django language name (en-us) into a js styled language - name (en-US). + Turns a Django language name (en-us) into the correspnding DataTables.net + i18n lang name. """ - p = dj_lang_name.find('-') - if p >= 0: - return dj_lang_name[:p].lower() + '-' + dj_lang_name[p + 1:].upper() + # The mapping is crap, we use a special case table to fix it. + mapping = {"zh-hans": "Chinese", + "zh-hant": "Chinese-traditional"} + + if dj_lang_name in mapping: + return mapping[dj_lang_name] else: - return dj_lang_name.lower() + primary = dj_lang_name.split('-')[0] + try: + return pycountry.languages.get(alpha_2=primary).name + except LookupError: + return "English" # }}} diff --git a/requirements.txt b/requirements.txt index 62959600441b1becd52536efeeb14336352aeaff..786ca464d1f8554d3ce3f92cc1f86010687c1d66 100644 --- a/requirements.txt +++ b/requirements.txt @@ -45,9 +45,7 @@ dnspython git+https://github.com/fritzy/SleekXMPP.git@6e27f28c854ce4ae1d9f0cc8ee407bda8de97d3b # To manage web dependencies -#django-bower -# pending release with https://github.com/nvbn/django-bower/issues/68 -git+https://github.com/nvbn/django-bower.git +django-npm # For comfortable code entry (git for py3 fix in git rev 8979538) @@ -70,6 +68,9 @@ unicodecsv # To support network matching for facility recognition ipaddress +# For datatables i18n +pycountry + # {{{ For interoperation with SAML2/Shibboleth pysaml2 diff --git a/setup.py b/setup.py index 64eee057b18732564af3cde21cacaad9c77822d4..fca3ff8ab06105720b615a9eebc4ba9f73d3be01 100644 --- a/setup.py +++ b/setup.py @@ -30,6 +30,7 @@ setup(name="relate-courseware", "nbconvert>=5.2.1", "pymbolic", "sympy", + "pycountry", ], package_data={ "relate": [ diff --git a/tests/test_misc.py b/tests/test_misc.py index 71a970175741563c3a4c180955466a497d3269ba..b6dcc4070c06369c538f27e81a5f658df81141da 100644 --- a/tests/test_misc.py +++ b/tests/test_misc.py @@ -277,13 +277,13 @@ class GetCurrentLanguageJsLangNameTest(TestCase): template = self.engines["django"].from_string( "{% get_current_js_lang_name as LANG %}{{LANG}}") text = template.render() - self.assertEqual(text, "en-US") + self.assertEqual(text, "English") with override_settings(LANGUAGE_CODE="de"): template = self.engines["django"].from_string( "{% get_current_js_lang_name as LANG %}{{LANG}}") text = template.render() - self.assertEqual(text, "de") + self.assertEqual(text, "German") def test_get_current_js_lang_name_tag_failed(self): from django.template import TemplateSyntaxError diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 0000000000000000000000000000000000000000..2942918688c3b83175956f481197e9a75f5ae882 --- /dev/null +++ b/yarn.lock @@ -0,0 +1,234 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +almond@~0.3.1: + version "0.3.3" + resolved "https://registry.yarnpkg.com/almond/-/almond-0.3.3.tgz#a0e7c95ac7624d6417b4494b1e68bff693168a20" + +babel-runtime@^6.9.2: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" + dependencies: + core-js "^2.4.0" + regenerator-runtime "^0.11.0" + +blueimp-tmpl@^3.11.0: + version "3.11.0" + resolved "https://registry.yarnpkg.com/blueimp-tmpl/-/blueimp-tmpl-3.11.0.tgz#47e78cbab16770e3922b019a250b4ad9c7b20f8f" + +bootstrap@^3.3.7: + version "3.3.7" + resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-3.3.7.tgz#5a389394549f23330875a3b150656574f8a9eb71" + +codemirror@^5.35.0: + version "5.35.0" + resolved "https://registry.yarnpkg.com/codemirror/-/codemirror-5.35.0.tgz#280653d495455bc66aa87e6284292b02775ba878" + +core-js@^2.4.0: + version "2.5.3" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.3.tgz#8acc38345824f16d8365b7c9b4259168e8ed603e" + +datatables.net-bs@^1.10.15, datatables.net-bs@^1.10.16: + version "1.10.16" + resolved "https://registry.yarnpkg.com/datatables.net-bs/-/datatables.net-bs-1.10.16.tgz#b0854f5b374f713ae3db4156c7cea8a760c3de76" + dependencies: + datatables.net "1.10.16" + jquery ">=1.7" + +datatables.net-fixedcolumns-bs@^3.2.4: + version "3.2.4" + resolved "https://registry.yarnpkg.com/datatables.net-fixedcolumns-bs/-/datatables.net-fixedcolumns-bs-3.2.4.tgz#48f05ddbb810507f8b6bddc8b4e9aee2809ff342" + dependencies: + datatables.net-bs "^1.10.15" + datatables.net-fixedcolumns "3.2.4" + jquery ">=1.7" + +datatables.net-fixedcolumns@3.2.4, datatables.net-fixedcolumns@^3.2.4: + version "3.2.4" + resolved "https://registry.yarnpkg.com/datatables.net-fixedcolumns/-/datatables.net-fixedcolumns-3.2.4.tgz#ae9a2a08b3fb9767633db47825ba8e598cdcfc0d" + dependencies: + datatables.net "^1.10.15" + jquery ">=1.7" + +datatables.net-plugins@^1.10.15: + version "1.10.15" + resolved "https://registry.yarnpkg.com/datatables.net-plugins/-/datatables.net-plugins-1.10.15.tgz#906deebff75010ab4c275f8058b4b60d2c8f3157" + +datatables.net@1.10.16, datatables.net@^1.10.15, datatables.net@^1.10.16: + version "1.10.16" + resolved "https://registry.yarnpkg.com/datatables.net/-/datatables.net-1.10.16.tgz#4b052d1082824261b68eed9d22741b711d3d2469" + dependencies: + jquery ">=1.7" + +dom-walk@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.1.tgz#672226dc74c8f799ad35307df936aba11acd6018" + +es5-shim@^4.5.1: + version "4.5.10" + resolved "https://registry.yarnpkg.com/es5-shim/-/es5-shim-4.5.10.tgz#b7e17ef4df2a145b821f1497b50c25cf94026205" + +font-awesome@^4.7.0: + version "4.7.0" + resolved "https://registry.yarnpkg.com/font-awesome/-/font-awesome-4.7.0.tgz#8fa8cf0411a1a31afd07b06d2902bb9fc815a133" + +for-each@^0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.2.tgz#2c40450b9348e97f281322593ba96704b9abd4d4" + dependencies: + is-function "~1.0.0" + +fullcalendar@^2.9.1: + version "2.9.1" + resolved "https://registry.yarnpkg.com/fullcalendar/-/fullcalendar-2.9.1.tgz#dd2a84469b627749e47c5dd9fd71f56146e0651b" + dependencies: + jquery ">=1.7.1" + moment ">=2.5.0" + +global@4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/global/-/global-4.3.0.tgz#ef7ec4beead579b454f5ebd5e7f303db54f42a2b" + dependencies: + min-document "^2.6.1" + process "~0.5.1" + +global@^4.3.1, global@~4.3.0: + version "4.3.2" + resolved "https://registry.yarnpkg.com/global/-/global-4.3.2.tgz#e76989268a6c74c38908b1305b10fc0e394e9d0f" + dependencies: + min-document "^2.19.0" + process "~0.5.1" + +individual@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/individual/-/individual-2.0.0.tgz#833b097dad23294e76117a98fb38e0d9ad61bb97" + +is-function@^1.0.1, is-function@~1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-function/-/is-function-1.0.1.tgz#12cfb98b65b57dd3d193a3121f5f6e2f437602b5" + +jquery-mousewheel@~3.1.13: + version "3.1.13" + resolved "https://registry.yarnpkg.com/jquery-mousewheel/-/jquery-mousewheel-3.1.13.tgz#06f0335f16e353a695e7206bf50503cb523a6ee5" + +jquery-ui-dist@^1.12.1: + version "1.12.1" + resolved "https://registry.yarnpkg.com/jquery-ui-dist/-/jquery-ui-dist-1.12.1.tgz#5c0815d3cc6f90ff5faaf5b268a6e23b4ca904fa" + +jquery@>=1.7, jquery@>=1.7.1, jquery@>=1.9.1, jquery@^3.3.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.3.1.tgz#958ce29e81c9790f31be7792df5d4d95fc57fbca" + +jstree@^3.3.5: + version "3.3.5" + resolved "https://registry.yarnpkg.com/jstree/-/jstree-3.3.5.tgz#9c578db32d0a643775cddd8020ad5992f4119c13" + dependencies: + jquery ">=1.9.1" + +mathjax@^2.7.3: + version "2.7.3" + resolved "https://registry.yarnpkg.com/mathjax/-/mathjax-2.7.3.tgz#9cf668467d9eafadcc28569cba8eb34f4ea2c9a3" + +min-document@^2.19.0, min-document@^2.6.1: + version "2.19.0" + resolved "https://registry.yarnpkg.com/min-document/-/min-document-2.19.0.tgz#7bd282e3f5842ed295bb748cdd9f1ffa2c824685" + dependencies: + dom-walk "^0.1.0" + +moment@>=2.5.0: + version "2.21.0" + resolved "https://registry.yarnpkg.com/moment/-/moment-2.21.0.tgz#2a114b51d2a6ec9e6d83cf803f838a878d8a023a" + +parse-headers@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/parse-headers/-/parse-headers-2.0.1.tgz#6ae83a7aa25a9d9b700acc28698cd1f1ed7e9536" + dependencies: + for-each "^0.3.2" + trim "0.0.1" + +process@~0.5.1: + version "0.5.2" + resolved "https://registry.yarnpkg.com/process/-/process-0.5.2.tgz#1638d8a8e34c2f440a91db95ab9aeb677fc185cf" + +regenerator-runtime@^0.11.0: + version "0.11.1" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" + +rust-result@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/rust-result/-/rust-result-1.0.0.tgz#34c75b2e6dc39fe5875e5bdec85b5e0f91536f72" + dependencies: + individual "^2.0.0" + +safe-json-parse@4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/safe-json-parse/-/safe-json-parse-4.0.0.tgz#7c0f578cfccd12d33a71c0e05413e2eca171eaac" + dependencies: + rust-result "^1.0.0" + +select2-bootstrap-theme@^0.1.0-beta.10: + version "0.1.0-beta.10" + resolved "https://registry.yarnpkg.com/select2-bootstrap-theme/-/select2-bootstrap-theme-0.1.0-beta.10.tgz#b9426ecfc03bf4a235e76a132377574310469ac0" + +select2@^4.0.5: + version "4.0.5" + resolved "https://registry.yarnpkg.com/select2/-/select2-4.0.5.tgz#7aac50692561985b34d3b82ec55e226f8960d40a" + dependencies: + almond "~0.3.1" + jquery-mousewheel "~3.1.13" + +trim@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/trim/-/trim-0.0.1.tgz#5858547f6b290757ee95cccc666fb50084c460dd" + +tsml@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/tsml/-/tsml-1.0.1.tgz#89f8218b9d9e257f47d7f6b56d01c5a4d2c68fc3" + +video.js@^5.20.5: + version "5.20.5" + resolved "https://registry.yarnpkg.com/video.js/-/video.js-5.20.5.tgz#445cdae204bce459782d86a31b25a32afd6d8eff" + dependencies: + babel-runtime "^6.9.2" + global "4.3.0" + safe-json-parse "4.0.0" + tsml "1.0.1" + videojs-font "2.0.0" + videojs-ie8 "1.1.2" + videojs-swf "5.4.1" + videojs-vtt.js "0.12.6" + xhr "2.2.2" + +videojs-font@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/videojs-font/-/videojs-font-2.0.0.tgz#af7461ef9d4b95e0334bffb78b2f2ff0364a9034" + +videojs-ie8@1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/videojs-ie8/-/videojs-ie8-1.1.2.tgz#a23d3d8608ad7192b69c6077fc4eb848998d35d9" + dependencies: + es5-shim "^4.5.1" + +videojs-swf@5.4.1: + version "5.4.1" + resolved "https://registry.yarnpkg.com/videojs-swf/-/videojs-swf-5.4.1.tgz#2077ef71c749f2c7823ef49babae4dd2acb08f87" + +videojs-vtt.js@0.12.6: + version "0.12.6" + resolved "https://registry.yarnpkg.com/videojs-vtt.js/-/videojs-vtt.js-0.12.6.tgz#e078600bda899eaa6f9c3307134cd0c811947b8e" + dependencies: + global "^4.3.1" + +xhr@2.2.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/xhr/-/xhr-2.2.2.tgz#2ee72571869f8686d41559a9ea286c18971435ff" + dependencies: + global "~4.3.0" + is-function "^1.0.1" + parse-headers "^2.0.0" + xtend "^4.0.0" + +xtend@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af"