summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVictor Feyens <vfe@odoo.com>2021-04-30 13:24:57 +0000
committerAntoine Vandevenne (anv) <anv@odoo.com>2021-05-04 08:09:20 +0000
commit27bad8c3e32049ec69a588df0558e57a0b928309 (patch)
treeb60e430163d486c8c1fd052738c9854aeb8300f5
parent75a122bbae3a32bfa79da3506179fc63a8bced5d (diff)
[MOV] doc: move documentation to a dedicated repository
In odoo/documentation-user#945, the developer documentation is merged with the user documentation in a single repository and build config. This commit then removes source files for the developer documentation from the odoo/odoo repository. DOC PR: https://github.com/odoo/documentation-user/pull/945 task-2351938 task-2352371 task-2205684 task-2352544 Co-authored-by: Victor Feyens <vfe@odoo.com> Co-authored-by: Antoine Vandevenne <anv@odoo.com>
-rw-r--r--doc/Makefile166
-rw-r--r--doc/_extensions/autojsdoc/README.rst87
-rw-r--r--doc/_extensions/autojsdoc/__init__.py1
-rw-r--r--doc/_extensions/autojsdoc/__main__.py154
-rw-r--r--doc/_extensions/autojsdoc/ext/__init__.py13
-rw-r--r--doc/_extensions/autojsdoc/ext/directives.py719
-rw-r--r--doc/_extensions/autojsdoc/ext/extractor.py87
-rw-r--r--doc/_extensions/autojsdoc/parser/__init__.py1
-rw-r--r--doc/_extensions/autojsdoc/parser/jsdoc.py357
-rw-r--r--doc/_extensions/autojsdoc/parser/parser.py572
-rw-r--r--doc/_extensions/autojsdoc/parser/tests/README.rst6
-rw-r--r--doc/_extensions/autojsdoc/parser/tests/support.py73
-rw-r--r--doc/_extensions/autojsdoc/parser/tests/test_class.py227
-rw-r--r--doc/_extensions/autojsdoc/parser/tests/test_crap.py75
-rw-r--r--doc/_extensions/autojsdoc/parser/tests/test_module.py173
-rw-r--r--doc/_extensions/autojsdoc/parser/tests/test_namespace.py177
-rw-r--r--doc/_extensions/autojsdoc/parser/tests/test_params.py116
-rw-r--r--doc/_extensions/autojsdoc/parser/tests/test_typespec.py104
-rw-r--r--doc/_extensions/autojsdoc/parser/types.py196
-rw-r--r--doc/_extensions/autojsdoc/parser/utils.py295
-rw-r--r--doc/_extensions/autojsdoc/parser/visitor.py126
-rw-r--r--doc/_extensions/conftest.py0
-rw-r--r--doc/_extensions/exercise_admonition.py24
-rw-r--r--doc/_extensions/github_link.py105
-rw-r--r--doc/_extensions/html_domain.py129
-rw-r--r--doc/_extensions/odoo_ext/__init__.py148
-rw-r--r--doc/_extensions/odoo_ext/breadcrumb_list.html23
-rw-r--r--doc/_extensions/odoo_ext/layout.html339
-rw-r--r--doc/_extensions/odoo_ext/pygments_override.py126
-rw-r--r--doc/_extensions/odoo_ext/static/aside.less339
-rwxr-xr-xdoc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/alerts.less73
-rwxr-xr-xdoc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/badges.less66
-rwxr-xr-xdoc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/bootstrap.less56
-rwxr-xr-xdoc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/breadcrumbs.less26
-rwxr-xr-xdoc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/button-groups.less244
-rwxr-xr-xdoc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/buttons.less166
-rwxr-xr-xdoc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/carousel.less270
-rwxr-xr-xdoc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/close.less34
-rwxr-xr-xdoc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/code.less69
-rwxr-xr-xdoc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/component-animations.less33
-rwxr-xr-xdoc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/dropdowns.less216
-rwxr-xr-xdoc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/forms.less613
-rwxr-xr-xdoc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/glyphicons.less305
-rwxr-xr-xdoc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/grid.less84
-rwxr-xr-xdoc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/input-groups.less171
-rwxr-xr-xdoc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/jumbotron.less54
-rwxr-xr-xdoc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/labels.less64
-rwxr-xr-xdoc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/list-group.less130
-rwxr-xr-xdoc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/media.less66
-rwxr-xr-xdoc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins.less40
-rwxr-xr-xdoc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/alerts.less14
-rwxr-xr-xdoc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/background-variant.less9
-rwxr-xr-xdoc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/border-radius.less18
-rwxr-xr-xdoc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/buttons.less65
-rwxr-xr-xdoc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/center-block.less7
-rwxr-xr-xdoc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/clearfix.less22
-rwxr-xr-xdoc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/forms.less85
-rwxr-xr-xdoc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/gradients.less59
-rwxr-xr-xdoc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/grid-framework.less91
-rwxr-xr-xdoc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/grid.less122
-rwxr-xr-xdoc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/hide-text.less21
-rwxr-xr-xdoc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/image.less33
-rwxr-xr-xdoc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/labels.less12
-rwxr-xr-xdoc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/list-group.less30
-rwxr-xr-xdoc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/nav-divider.less10
-rwxr-xr-xdoc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/nav-vertical-align.less9
-rwxr-xr-xdoc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/opacity.less8
-rwxr-xr-xdoc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/pagination.less24
-rwxr-xr-xdoc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/panels.less24
-rwxr-xr-xdoc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/progress-bar.less10
-rwxr-xr-xdoc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/reset-filter.less8
-rwxr-xr-xdoc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/reset-text.less18
-rwxr-xr-xdoc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/resize.less6
-rwxr-xr-xdoc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/responsive-visibility.less15
-rwxr-xr-xdoc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/size.less10
-rwxr-xr-xdoc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/tab-focus.less9
-rwxr-xr-xdoc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/table-row.less28
-rwxr-xr-xdoc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/text-emphasis.less9
-rwxr-xr-xdoc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/text-overflow.less8
-rwxr-xr-xdoc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/vendor-prefixes.less227
-rwxr-xr-xdoc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/modals.less150
-rwxr-xr-xdoc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/navbar.less660
-rwxr-xr-xdoc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/navs.less242
-rwxr-xr-xdoc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/normalize.less424
-rwxr-xr-xdoc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/pager.less54
-rwxr-xr-xdoc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/pagination.less89
-rwxr-xr-xdoc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/panels.less271
-rwxr-xr-xdoc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/popovers.less131
-rwxr-xr-xdoc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/print.less101
-rwxr-xr-xdoc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/progress-bars.less87
-rwxr-xr-xdoc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/responsive-embed.less35
-rwxr-xr-xdoc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/responsive-utilities.less194
-rwxr-xr-xdoc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/scaffolding.less161
-rwxr-xr-xdoc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/tables.less234
-rwxr-xr-xdoc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/theme.less291
-rwxr-xr-xdoc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/thumbnails.less36
-rwxr-xr-xdoc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/tooltip.less101
-rwxr-xr-xdoc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/type.less302
-rwxr-xr-xdoc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/utilities.less55
-rwxr-xr-xdoc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/variables.less869
-rwxr-xr-xdoc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/wells.less29
-rw-r--r--doc/_extensions/odoo_ext/static/bootstrap.css.map1
-rw-r--r--doc/_extensions/odoo_ext/static/bootstrap.js2317
-rw-r--r--doc/_extensions/odoo_ext/static/components.less515
-rw-r--r--doc/_extensions/odoo_ext/static/doc.js405
-rw-r--r--doc/_extensions/odoo_ext/static/fonts/Material-Design-Icons.eotbin102112 -> 0 bytes
-rw-r--r--doc/_extensions/odoo_ext/static/fonts/Material-Design-Icons.svg769
-rw-r--r--doc/_extensions/odoo_ext/static/fonts/Material-Design-Icons.ttfbin101892 -> 0 bytes
-rw-r--r--doc/_extensions/odoo_ext/static/fonts/Material-Design-Icons.woffbin101968 -> 0 bytes
-rw-r--r--doc/_extensions/odoo_ext/static/footer.less95
-rw-r--r--doc/_extensions/odoo_ext/static/header.less834
-rw-r--r--doc/_extensions/odoo_ext/static/img/2x_apps_families_s.pngbin29045 -> 0 bytes
-rw-r--r--doc/_extensions/odoo_ext/static/img/apps_families_s.pngbin12077 -> 0 bytes
-rw-r--r--doc/_extensions/odoo_ext/static/img/banner_bg.pngbin8376 -> 0 bytes
-rw-r--r--doc/_extensions/odoo_ext/static/img/geometric_gradient.pngbin478601 -> 0 bytes
-rw-r--r--doc/_extensions/odoo_ext/static/img/github-square_32.pngbin499 -> 0 bytes
-rw-r--r--doc/_extensions/odoo_ext/static/img/logos/odoo_logo.pngbin20081 -> 0 bytes
-rw-r--r--doc/_extensions/odoo_ext/static/img/logos/odoo_logo.svg31
-rw-r--r--doc/_extensions/odoo_ext/static/img/logos/odoo_logo_small.pngbin8810 -> 0 bytes
-rw-r--r--doc/_extensions/odoo_ext/static/img/odoo_logo_rgb.pngbin4142 -> 0 bytes
-rw-r--r--doc/_extensions/odoo_ext/static/img/odoo_logo_white.pngbin8208 -> 0 bytes
-rw-r--r--doc/_extensions/odoo_ext/static/index.less114
-rw-r--r--doc/_extensions/odoo_ext/static/jquery.min.js4
-rw-r--r--doc/_extensions/odoo_ext/static/jquery.noconflict.js1
-rw-r--r--doc/_extensions/odoo_ext/static/layout.less164
-rw-r--r--doc/_extensions/odoo_ext/static/mdi.less2381
-rw-r--r--doc/_extensions/odoo_ext/static/mixins.less277
-rw-r--r--doc/_extensions/odoo_ext/static/print.less54
-rw-r--r--doc/_extensions/odoo_ext/static/style.css12181
-rw-r--r--doc/_extensions/odoo_ext/static/style.less276
-rw-r--r--doc/_extensions/odoo_ext/static/typography.less181
-rw-r--r--doc/_extensions/odoo_ext/static/variables.less169
-rw-r--r--doc/_extensions/odoo_ext/sub-menu_list.html20
-rw-r--r--doc/_extensions/odoo_ext/switcher.py45
-rw-r--r--doc/_extensions/odoo_ext/switchers_list.html25
-rw-r--r--doc/_extensions/odoo_ext/theme.conf4
-rw-r--r--doc/_extensions/odoo_ext/translator.py748
-rw-r--r--doc/_extensions/pyjsdoc/LICENSE174
-rw-r--r--doc/_extensions/pyjsdoc/__init__.py408
-rw-r--r--doc/_extensions/pyjsparser/LICENSE21
-rw-r--r--doc/_extensions/pyjsparser/README4
-rw-r--r--doc/_extensions/pyjsparser/__init__.py4
-rw-r--r--doc/_extensions/pyjsparser/parser.py2920
-rw-r--r--doc/_extensions/pyjsparser/pyjsparserdata.py297
-rw-r--r--doc/_extensions/pyjsparser/std_nodes.py470
-rw-r--r--doc/_static/.placeholder0
-rw-r--r--doc/_static/banners/actions.jpgbin50888 -> 0 bytes
-rw-r--r--doc/_static/banners/actions.small.jpgbin14903 -> 0 bytes
-rw-r--r--doc/_static/banners/build_a_module.jpgbin52198 -> 0 bytes
-rw-r--r--doc/_static/banners/build_a_module.small.jpgbin21254 -> 0 bytes
-rw-r--r--doc/_static/banners/build_a_theme.jpgbin39831 -> 0 bytes
-rw-r--r--doc/_static/banners/build_a_theme.small.jpgbin16195 -> 0 bytes
-rw-r--r--doc/_static/banners/build_a_website.jpgbin55384 -> 0 bytes
-rw-r--r--doc/_static/banners/build_a_website.small.jpgbin15993 -> 0 bytes
-rw-r--r--doc/_static/banners/build_interface_ext.jpgbin87474 -> 0 bytes
-rw-r--r--doc/_static/banners/build_interface_ext.small.jpgbin23342 -> 0 bytes
-rw-r--r--doc/_static/banners/cdn.jpgbin31119 -> 0 bytes
-rw-r--r--doc/_static/banners/cdn.small.jpgbin12505 -> 0 bytes
-rw-r--r--doc/_static/banners/cmdline.jpgbin29338 -> 0 bytes
-rw-r--r--doc/_static/banners/cmdline.small.jpgbin10920 -> 0 bytes
-rw-r--r--doc/_static/banners/company.jpgbin215140 -> 0 bytes
-rw-r--r--doc/_static/banners/data_files.jpgbin39778 -> 0 bytes
-rw-r--r--doc/_static/banners/data_files.small.jpgbin16174 -> 0 bytes
-rw-r--r--doc/_static/banners/deploying_odoo.jpgbin67532 -> 0 bytes
-rw-r--r--doc/_static/banners/deploying_odoo.small.jpgbin24107 -> 0 bytes
-rw-r--r--doc/_static/banners/email_gateway.jpgbin83480 -> 0 bytes
-rw-r--r--doc/_static/banners/email_gateway.small.jpgbin28803 -> 0 bytes
-rw-r--r--doc/_static/banners/enterprise.jpgbin74732 -> 0 bytes
-rw-r--r--doc/_static/banners/enterprise.small.jpgbin19886 -> 0 bytes
-rw-r--r--doc/_static/banners/extract_api.jpgbin86972 -> 0 bytes
-rw-r--r--doc/_static/banners/extract_api.small.jpgbin27842 -> 0 bytes
-rw-r--r--doc/_static/banners/iap.jpgbin20076 -> 0 bytes
-rw-r--r--doc/_static/banners/iap.small.jpgbin13220 -> 0 bytes
-rw-r--r--doc/_static/banners/index.jpgbin70127 -> 0 bytes
-rw-r--r--doc/_static/banners/installing_odoo.jpgbin44943 -> 0 bytes
-rw-r--r--doc/_static/banners/installing_odoo.small.jpgbin18154 -> 0 bytes
-rw-r--r--doc/_static/banners/iot.jpgbin163123 -> 0 bytes
-rw-r--r--doc/_static/banners/javascript.jpgbin91119 -> 0 bytes
-rw-r--r--doc/_static/banners/javascript.small.jpgbin30207 -> 0 bytes
-rw-r--r--doc/_static/banners/localization.jpgbin69043 -> 0 bytes
-rw-r--r--doc/_static/banners/m_1.small.jpgbin31253 -> 0 bytes
-rw-r--r--doc/_static/banners/m_2.small.jpgbin14701 -> 0 bytes
-rw-r--r--doc/_static/banners/m_accounting.small.jpgbin22229 -> 0 bytes
-rw-r--r--doc/_static/banners/mixins.jpgbin46643 -> 0 bytes
-rw-r--r--doc/_static/banners/mixins.small.jpgbin21639 -> 0 bytes
-rw-r--r--doc/_static/banners/mobile.jpgbin107392 -> 0 bytes
-rw-r--r--doc/_static/banners/module.jpgbin106342 -> 0 bytes
-rw-r--r--doc/_static/banners/module.small.jpgbin31319 -> 0 bytes
-rw-r--r--doc/_static/banners/odoo_guideline.jpgbin68963 -> 0 bytes
-rw-r--r--doc/_static/banners/odoo_guideline.small.jpgbin19603 -> 0 bytes
-rw-r--r--doc/_static/banners/orm_api.jpgbin66486 -> 0 bytes
-rw-r--r--doc/_static/banners/orm_api.small.jpgbin23032 -> 0 bytes
-rw-r--r--doc/_static/banners/qweb.jpgbin129901 -> 0 bytes
-rw-r--r--doc/_static/banners/qweb.small.jpgbin22321 -> 0 bytes
-rw-r--r--doc/_static/banners/reports.jpgbin63282 -> 0 bytes
-rw-r--r--doc/_static/banners/reports.small.jpgbin22657 -> 0 bytes
-rw-r--r--doc/_static/banners/security.jpgbin50513 -> 0 bytes
-rw-r--r--doc/_static/banners/security.small.jpgbin15128 -> 0 bytes
-rw-r--r--doc/_static/banners/testing_modules.jpgbin58469 -> 0 bytes
-rw-r--r--doc/_static/banners/testing_modules.small.jpgbin19171 -> 0 bytes
-rw-r--r--doc/_static/banners/translate.jpgbin81951 -> 0 bytes
-rw-r--r--doc/_static/banners/translate.small.jpgbin22192 -> 0 bytes
-rw-r--r--doc/_static/banners/upgrade_api.jpgbin38132 -> 0 bytes
-rw-r--r--doc/_static/banners/views.jpgbin34049 -> 0 bytes
-rw-r--r--doc/_static/banners/views.small.jpgbin10293 -> 0 bytes
-rw-r--r--doc/_static/banners/web_controllers.jpgbin63012 -> 0 bytes
-rw-r--r--doc/_static/banners/web_controllers.small.jpgbin22857 -> 0 bytes
-rw-r--r--doc/_static/banners/web_service_api.jpgbin126380 -> 0 bytes
-rw-r--r--doc/_static/banners/web_service_api.small.jpgbin33224 -> 0 bytes
-rw-r--r--doc/_static/extract_api_implementation.py100
-rw-r--r--doc/_static/issue_template.md19
-rw-r--r--doc/_static/odoo.css26
-rw-r--r--doc/_static/pull-request-version.pngbin12880 -> 0 bytes
-rw-r--r--doc/conf.py241
-rw-r--r--doc/glossary.rst43
-rw-r--r--doc/howtos/backend.rst1822
-rw-r--r--doc/howtos/backend/exercise-access-rights40
-rw-r--r--doc/howtos/backend/exercise-access-rules27
-rw-r--r--doc/howtos/backend/exercise-advanced-treeview19
-rw-r--r--doc/howtos/backend/exercise-basic-action53
-rw-r--r--doc/howtos/backend/exercise-calendar77
-rw-r--r--doc/howtos/backend/exercise-computed40
-rw-r--r--doc/howtos/backend/exercise-constraint-python25
-rw-r--r--doc/howtos/backend/exercise-constraint-sql24
-rw-r--r--doc/howtos/backend/exercise-copy-override27
-rw-r--r--doc/howtos/backend/exercise-creation152
-rw-r--r--doc/howtos/backend/exercise-dashboard91
-rw-r--r--doc/howtos/backend/exercise-defaults28
-rw-r--r--doc/howtos/backend/exercise-demo48
-rw-r--r--doc/howtos/backend/exercise-domain-advanced42
-rw-r--r--doc/howtos/backend/exercise-domain-basic17
-rw-r--r--doc/howtos/backend/exercise-formview29
-rw-r--r--doc/howtos/backend/exercise-formview-notebooks24
-rw-r--r--doc/howtos/backend/exercise-gantt30
-rw-r--r--doc/howtos/backend/exercise-graph55
-rw-r--r--doc/howtos/backend/exercise-kanban77
-rw-r--r--doc/howtos/backend/exercise-many2many22
-rw-r--r--doc/howtos/backend/exercise-many2one95
-rw-r--r--doc/howtos/backend/exercise-model19
-rw-r--r--doc/howtos/backend/exercise-model-inheritance78
-rw-r--r--doc/howtos/backend/exercise-onchange28
-rw-r--r--doc/howtos/backend/exercise-one2many36
-rw-r--r--doc/howtos/backend/exercise-report52
-rw-r--r--doc/howtos/backend/exercise-searchview28
-rw-r--r--doc/howtos/backend/exercise-searchview-basic24
-rw-r--r--doc/howtos/backend/exercise-session57
-rw-r--r--doc/howtos/backend/exercise-translations56
-rw-r--r--doc/howtos/backend/exercise-wizard36
-rw-r--r--doc/howtos/backend/exercise-wizard-action29
-rw-r--r--doc/howtos/backend/exercise-wizard-launch45
-rw-r--r--doc/howtos/backend/exercise-wizard-multi37
-rw-r--r--doc/howtos/backend/series35
-rw-r--r--doc/howtos/company.rst230
-rw-r--r--doc/howtos/profile/flamegraph.svg315
-rw-r--r--doc/howtos/profilecode.rst131
-rw-r--r--doc/howtos/theme_tutorial_assets/img/Intro.jpgbin34344 -> 0 bytes
-rwxr-xr-xdoc/howtos/theme_tutorial_assets/img/after-menu.pngbin90382 -> 0 bytes
-rwxr-xr-xdoc/howtos/theme_tutorial_assets/img/cms.jpgbin26015 -> 0 bytes
-rw-r--r--doc/howtos/theme_tutorial_assets/img/def_structure.jpgbin28760 -> 0 bytes
-rwxr-xr-xdoc/howtos/theme_tutorial_assets/img/functionalities.jpgbin11727 -> 0 bytes
-rwxr-xr-xdoc/howtos/theme_tutorial_assets/img/page.jpgbin62196 -> 0 bytes
-rwxr-xr-xdoc/howtos/theme_tutorial_assets/img/page_structure.jpgbin30602 -> 0 bytes
-rw-r--r--doc/howtos/theme_tutorial_assets/img/restart.pngbin724 -> 0 bytes
-rw-r--r--doc/howtos/theme_tutorial_assets/img/seo_promote.pngbin33125 -> 0 bytes
-rw-r--r--doc/howtos/theme_tutorial_assets/img/seo_snippet_good.pngbin158711 -> 0 bytes
-rw-r--r--doc/howtos/theme_tutorial_assets/img/seo_snippet_wrong.pngbin75244 -> 0 bytes
-rwxr-xr-xdoc/howtos/theme_tutorial_assets/img/services_page_menu.pngbin3513 -> 0 bytes
-rwxr-xr-xdoc/howtos/theme_tutorial_assets/img/services_page_nostyle.pngbin12961 -> 0 bytes
-rwxr-xr-xdoc/howtos/theme_tutorial_assets/img/services_page_styled.pngbin11114 -> 0 bytes
-rwxr-xr-xdoc/howtos/theme_tutorial_assets/img/snippet.jpgbin33063 -> 0 bytes
-rwxr-xr-xdoc/howtos/theme_tutorial_assets/img/snippet_bar.pngbin32119 -> 0 bytes
-rw-r--r--doc/howtos/theme_tutorial_assets/img/snippet_custom_method.pngbin39087 -> 0 bytes
-rwxr-xr-xdoc/howtos/theme_tutorial_assets/img/snippet_default.pngbin23694 -> 0 bytes
-rwxr-xr-xdoc/howtos/theme_tutorial_assets/img/snippet_options.pngbin27575 -> 0 bytes
-rwxr-xr-xdoc/howtos/theme_tutorial_assets/img/snippet_options2.pngbin28440 -> 0 bytes
-rwxr-xr-xdoc/howtos/theme_tutorial_assets/img/styles.jpgbin40789 -> 0 bytes
-rwxr-xr-xdoc/howtos/theme_tutorial_assets/img/theme_folder.jpgbin9643 -> 0 bytes
-rw-r--r--doc/howtos/theme_tutorial_assets/img/upgrade_module.pngbin39135 -> 0 bytes
-rw-r--r--doc/howtos/themes.rst1117
-rw-r--r--doc/howtos/web.rst2330
-rw-r--r--doc/howtos/web/about_odoo.pngbin8752 -> 0 bytes
-rw-r--r--doc/howtos/web/devmode.pngbin7967 -> 0 bytes
-rw-r--r--doc/howtos/web/qweb.pngbin14573 -> 0 bytes
-rw-r--r--doc/howtos/web/viewarchitecture.diabin1918 -> 0 bytes
-rw-r--r--doc/howtos/web/viewarchitecture.pngbin12937 -> 0 bytes
-rw-r--r--doc/howtos/web/viewarchitecture.svg1
-rw-r--r--doc/howtos/website.rst513
-rw-r--r--doc/howtos/website/basic-acl23
-rw-r--r--doc/howtos/website/basic-controller22
-rw-r--r--doc/howtos/website/basic-list.pngbin1434 -> 0 bytes
-rw-r--r--doc/howtos/website/basic-model18
-rw-r--r--doc/howtos/website/biography-esc23
-rw-r--r--doc/howtos/website/biography-field18
-rw-r--r--doc/howtos/website/chatter-backend29
-rw-r--r--doc/howtos/website/converter-model44
-rw-r--r--doc/howtos/website/course-m2o24
-rw-r--r--doc/howtos/website/course-no-price21
-rw-r--r--doc/howtos/website/course-o2m33
-rw-r--r--doc/howtos/website/course-product142
-rw-r--r--doc/howtos/website/course-products-sidebar18
-rw-r--r--doc/howtos/website/course-views57
-rw-r--r--doc/howtos/website/data-retrieval-orm30
-rw-r--r--doc/howtos/website/demo-data42
-rw-r--r--doc/howtos/website/field-format16
-rw-r--r--doc/howtos/website/field-raw15
-rw-r--r--doc/howtos/website/field-widget16
-rw-r--r--doc/howtos/website/helloworld.pngbin823 -> 0 bytes
-rw-r--r--doc/howtos/website/layout.pngbin4826 -> 0 bytes
-rw-r--r--doc/howtos/website/module-empty153
-rw-r--r--doc/howtos/website/product-dependency16
-rw-r--r--doc/howtos/website/routing-basic19
-rw-r--r--doc/howtos/website/routing-converter20
-rw-r--r--doc/howtos/website/series27
-rw-r--r--doc/howtos/website/teacher-links27
-rw-r--r--doc/howtos/website/teachers-formview26
-rw-r--r--doc/howtos/website/teachers-menu35
-rw-r--r--doc/howtos/website/template42
-rw-r--r--doc/howtos/website/website-support50
-rw-r--r--doc/images/inheritance_methods.pngbin14366 -> 0 bytes
-rw-r--r--doc/images/rating_request.pngbin12189 -> 0 bytes
-rw-r--r--doc/index.rst25
-rw-r--r--doc/python3.rst460
-rw-r--r--doc/reference.rst28
-rw-r--r--doc/reference/actions.rst445
-rw-r--r--doc/reference/cmdline.rst745
-rw-r--r--doc/reference/data.rst301
-rw-r--r--doc/reference/guidelines.rst1158
-rw-r--r--doc/reference/http.rst87
-rw-r--r--doc/reference/images/mobile_contact_create.pngbin7218 -> 0 bytes
-rw-r--r--doc/reference/images/mobile_notification.pngbin7714 -> 0 bytes
-rw-r--r--doc/reference/images/mobile_switch_account.pngbin19702 -> 0 bytes
-rw-r--r--doc/reference/images/mobile_working.jpgbin21719 -> 0 bytes
-rw-r--r--doc/reference/images/odoo_mobile_api.pngbin13125 -> 0 bytes
-rw-r--r--doc/reference/images/runner.pngbin2864 -> 0 bytes
-rw-r--r--doc/reference/images/runner2.pngbin4000 -> 0 bytes
-rw-r--r--doc/reference/images/snackbar.pngbin4111 -> 0 bytes
-rw-r--r--doc/reference/images/tests.pngbin110669 -> 0 bytes
-rw-r--r--doc/reference/images/tests2.pngbin10081 -> 0 bytes
-rw-r--r--doc/reference/images/tests3.pngbin10394 -> 0 bytes
-rw-r--r--doc/reference/images/toast.pngbin2986 -> 0 bytes
-rw-r--r--doc/reference/iot.rst195
-rw-r--r--doc/reference/javascript_cheatsheet.rst545
-rw-r--r--doc/reference/javascript_reference.rst2425
-rw-r--r--doc/reference/mixins.rst1076
-rw-r--r--doc/reference/mobile.rst213
-rw-r--r--doc/reference/module.rst148
-rw-r--r--doc/reference/orm.rst1092
-rw-r--r--doc/reference/qweb.rst686
-rw-r--r--doc/reference/reports.rst326
-rw-r--r--doc/reference/security.rst389
-rw-r--r--doc/reference/static/res.country.state.csv15
-rw-r--r--doc/reference/testing.rst638
-rw-r--r--doc/reference/translations.rst214
-rw-r--r--doc/reference/translations/po-export.pngbin11576 -> 0 bytes
-rw-r--r--doc/reference/views.rst2139
-rw-r--r--doc/requirements.txt2
-rw-r--r--doc/setup.rst15
-rw-r--r--doc/setup/cdn.rst82
-rw-r--r--doc/setup/cdn/keycdn_create_a_pull_zone.pngbin41837 -> 0 bytes
-rw-r--r--doc/setup/cdn/keycdn_enable_CORS.pngbin10695 -> 0 bytes
-rw-r--r--doc/setup/cdn/keycdn_progressbar.pngbin28715 -> 0 bytes
-rw-r--r--doc/setup/cdn/odoo_cdn_base_url.pngbin10054 -> 0 bytes
-rw-r--r--doc/setup/cdn/odoo_check_your_html.pngbin33487 -> 0 bytes
-rw-r--r--doc/setup/cdn/odoo_font_file_not_loaded.pngbin6418 -> 0 bytes
-rw-r--r--doc/setup/cdn/odoo_security_message.pngbin7343 -> 0 bytes
-rw-r--r--doc/setup/deploy.rst662
-rw-r--r--doc/setup/email_gateway.rst49
-rw-r--r--doc/setup/enterprise.rst107
-rw-r--r--doc/setup/enterprise/db_manager.pngbin7023 -> 0 bytes
-rw-r--r--doc/setup/enterprise/enterprise_code.pngbin22677 -> 0 bytes
-rw-r--r--doc/setup/enterprise/windows_setup.pngbin12761 -> 0 bytes
-rw-r--r--doc/setup/enterprise/windows_uninstall.pngbin27515 -> 0 bytes
-rw-r--r--doc/setup/install.rst784
-rw-r--r--doc/setup/update.rst151
-rw-r--r--doc/tutorials.rst13
-rw-r--r--doc/webservices.rst15
-rw-r--r--doc/webservices/extract_api.rst558
-rw-r--r--doc/webservices/iap.rst770
-rw-r--r--doc/webservices/iap/01-init16
-rw-r--r--doc/webservices/iap/02-button34
-rw-r--r--doc/webservices/iap/03-callback39
-rw-r--r--doc/webservices/iap/series3
-rw-r--r--doc/webservices/iap_service/01-init16
-rw-r--r--doc/webservices/iap_service/02-tnx48
-rw-r--r--doc/webservices/iap_service/03-template56
-rw-r--r--doc/webservices/iap_service/series3
-rw-r--r--doc/webservices/images/account-security.pngbin15889 -> 0 bytes
-rw-r--r--doc/webservices/images/button.pngbin11828 -> 0 bytes
-rw-r--r--doc/webservices/images/creating_service.pngbin135059 -> 0 bytes
-rw-r--r--doc/webservices/images/credits.jpgbin52414 -> 0 bytes
-rw-r--r--doc/webservices/images/credits2.jpgbin33996 -> 0 bytes
-rw-r--r--doc/webservices/images/delete-key.pngbin24002 -> 0 bytes
-rw-r--r--doc/webservices/images/flow.pngbin6419 -> 0 bytes
-rw-r--r--doc/webservices/images/menu.pngbin30694 -> 0 bytes
-rw-r--r--doc/webservices/images/no-credit.pngbin15426 -> 0 bytes
-rw-r--r--doc/webservices/images/normal.pngbin16181 -> 0 bytes
-rw-r--r--doc/webservices/images/package.pngbin44586 -> 0 bytes
-rw-r--r--doc/webservices/images/players.pngbin23348 -> 0 bytes
-rw-r--r--doc/webservices/images/preferences.pngbin12360 -> 0 bytes
-rw-r--r--doc/webservices/images/service_created.pngbin60608 -> 0 bytes
-rw-r--r--doc/webservices/images/service_list.pngbin35389 -> 0 bytes
-rw-r--r--doc/webservices/images/template.pngbin16080 -> 0 bytes
-rw-r--r--doc/webservices/localization.rst423
-rw-r--r--doc/webservices/odoo.rst1337
-rw-r--r--doc/webservices/upgrade.rst659
405 files changed, 0 insertions, 67862 deletions
diff --git a/doc/Makefile b/doc/Makefile
deleted file mode 100644
index 9795b90275b..00000000000
--- a/doc/Makefile
+++ /dev/null
@@ -1,166 +0,0 @@
-# Makefile for Sphinx documentation
-#
-
-# You can set these variables from the command line.
-SPHINXOPTS = -q -t solutions
-SPHINXBUILD = sphinx-build
-PAPER =
-BUILDDIR = _build
-LESSC = lessc
-
-# Internal variables.
-PAPEROPT_a4 = -D latex_paper_size=a4
-PAPEROPT_letter = -D latex_paper_size=letter
-ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
-# the i18n builder cannot share the environment and doctrees with the others
-I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
-
-.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
-
-help:
- @echo "Please use \`make <target>' where <target> is one of"
- @echo " html to make standalone HTML files"
- @echo " dirhtml to make HTML files named index.html in directories"
- @echo " singlehtml to make a single large HTML file"
- @echo " pickle to make pickle files"
- @echo " json to make JSON files"
- @echo " htmlhelp to make HTML files and a HTML help project"
- @echo " qthelp to make HTML files and a qthelp project"
- @echo " devhelp to make HTML files and a Devhelp project"
- @echo " epub to make an epub"
- @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
- @echo " latexpdf to make LaTeX files and run them through pdflatex"
- @echo " text to make text files"
- @echo " man to make manual pages"
- @echo " texinfo to make Texinfo files"
- @echo " info to make Texinfo files and run them through makeinfo"
- @echo " gettext to make PO message catalogs"
- @echo " changes to make an overview of all changed/added/deprecated items"
- @echo " linkcheck to check all external links for integrity"
- @echo " doctest to run all doctests embedded in the documentation (if enabled)"
-
-clean:
- -rm -rf $(BUILDDIR)/*
-
-STATICS = _extensions/odoo_ext/static
-# TODO: add bootstrap files
-LESSFILES = $(wildcard $(STATICS)/*.less)
-$(STATICS)/style.css: $(LESSFILES)
- $(LESSC) $(STATICS)/style.less $(STATICS)/style.css
-
-html: _extensions/odoo_ext/static/style.css
- $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
- @echo
- @echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
-
-dirhtml:
- $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
- sed -i '/-99999/d' _build/dirhtml/_static/flasky.css
- @echo
- @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
-
-singlehtml:
- $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
- @echo
- @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
-
-pickle:
- $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
- @echo
- @echo "Build finished; now you can process the pickle files."
-
-json:
- $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
- @echo
- @echo "Build finished; now you can process the JSON files."
-
-htmlhelp:
- $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
- @echo
- @echo "Build finished; now you can run HTML Help Workshop with the" \
- ".hhp project file in $(BUILDDIR)/htmlhelp."
-
-qthelp:
- $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
- @echo
- @echo "Build finished; now you can run "qcollectiongenerator" with the" \
- ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
- @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/OpenERPTechnicalDocumentation.qhcp"
- @echo "To view the help file:"
- @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/OpenERPTechnicalDocumentation.qhc"
-
-devhelp:
- $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
- @echo
- @echo "Build finished."
- @echo "To view the help file:"
- @echo "# mkdir -p $$HOME/.local/share/devhelp/OpenERPTechnicalDocumentation"
- @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/OpenERPTechnicalDocumentation"
- @echo "# devhelp"
-
-epub:
- $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
- @echo
- @echo "Build finished. The epub file is in $(BUILDDIR)/epub."
-
-latex:
- $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
- @echo
- @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
- @echo "Run \`make' in that directory to run these through (pdf)latex" \
- "(use \`make latexpdf' here to do that automatically)."
-
-latexpdf:
- $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
- @echo "Running LaTeX files through pdflatex..."
- $(MAKE) -C $(BUILDDIR)/latex all-pdf
- @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
-
-text:
- $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
- @echo
- @echo "Build finished. The text files are in $(BUILDDIR)/text."
-
-man:
- $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
- @echo
- @echo "Build finished. The manual pages are in $(BUILDDIR)/man."
-
-texinfo:
- $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
- @echo
- @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
- @echo "Run \`make' in that directory to run these through makeinfo" \
- "(use \`make info' here to do that automatically)."
-
-info:
- $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
- @echo "Running Texinfo files through makeinfo..."
- make -C $(BUILDDIR)/texinfo info
- @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
-
-gettext:
- $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
- @echo
- @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
-
-changes:
- $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
- @echo
- @echo "The overview file is in $(BUILDDIR)/changes."
-
-linkcheck:
- $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
- @echo
- @echo "Link check complete; look for any errors in the above output " \
- "or in $(BUILDDIR)/linkcheck/output.txt."
-
-doctest:
- $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
- @echo "Testing of doctests in the sources finished, look at the " \
- "results in $(BUILDDIR)/doctest/output.txt."
-
-pseudoxml:
- $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
- @echo
- @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."
diff --git a/doc/_extensions/autojsdoc/README.rst b/doc/_extensions/autojsdoc/README.rst
deleted file mode 100644
index ef7681778a1..00000000000
--- a/doc/_extensions/autojsdoc/README.rst
+++ /dev/null
@@ -1,87 +0,0 @@
-:orphan:
-
-======================================
-JSDoc parser/Sphinx extension for Odoo
-======================================
-
-Why?
-====
-
-Spent about a week trying to coerce "standard" javascript tools (jsdoc_ with
-the hope of using sphinx-js_ for integration or `documentation.js`_) and
-failed to ever get a sensible result: failed to get any result with the
-current state of the documentation, significant changes/additions/fixes to
-docstrings brought this up to "garbage output" level.
-
-Bug reports and mailing list posts didn't show any path to improvement on the
-ES5 codebase (if we ever go whole-hog on ES6 modules and classes things could
-be different, in fact most of JSDoc's current effort seem focused on
-ES6/ES2015 features) but both experience and looking at the mailing lists
-told me that spending more time would be wasted.
-
-Even more so as I was writing visitors/rewriters to generate documentation
-from our existing structure, which broadly speaking is relatively strict, and
-thus
-
-What?
-=====
-
-If it were possible to generate JSDoc annotations from our relatively
-well-defined code structures, it was obviously possible to extract documentary
-information directly from it, hence this Odoo-specific package/extension
-trying to do exactly that.
-
-This package should eventually provide:
-
-* a command-line interface which can be invoked via ``-m autojsdoc`` (assuming
- your ``PYTHONPATH`` can find it) which should allow dumping the parsed AST
- in a convenient-ish form, possibly doing searches through the AST, a
- dependency graph extractor/analysis and a text dumper for the
- documentation.
-
-* a sphinx extension (``autojsdoc.sphinx``) which can be used to integrate the
- parsed JSDoc information into the Sphinx doc.
-
-How?
-====
-
-Sphinx-aside, the package relies on 3 libraries:
-
-* pyjsparser_, an Esprima-compliant ES5.1 parser (with bits of ES6 support),
- sadly it does not support comments in its current form so I had to fork it.
- Fed a javascript source file, pyjsparser_ simply generates a bunch of nested
- dicts representing an Esprima ast, ast-types_ does a reasonably good job of
- describing it once you understand that "bases" are basically just structural
- mixins.
-
- Because the original does not, this package provides a ``visitor`` module
- for pyjsparser_ ASTs.
-
-* pyjsdoc_, a one-file "port" of jsdoc, can actually do much of the JS parsing
- (using string munging) but its core semantics don't fit our needs so I'm
- only using it to parse the actual JSDoc content, and the ``jsdoc`` module
- contains some replacement classes, extensions & monkey patches for things
- `pyjsdoc`_ itself does not support, at the time of this writing:
-
- - a bug in FunctionDoc.return_val
- - a type on FunctionDoc so it's compatible with ParamDoc
- - a more reliable comments-parsing function
- - a replacement ModuleDoc as the original does not materialise AMD modules
- - a ClassDoc extension to support mixins
- - two additional CommentDoc extensions for "namespaces" objects (bag of
- attributes without any more information) and mixin objects
-
-* pytest_ to configure and run the test suite, which you can run by invoking
- ``pytest doc/_extensions`` from the project top-level, the tests represent
- both "happy path" things we want to parse and various code patterns which
- tripped the happy path because e.g. they were matched and should not have,
- they were not matched and should have, or they were more complex than the
- happy path had expected
-
-.. _ast-types: _https://github.com/benjamn/ast-types/blob/master/def/core.js
-.. _documentation.js: http://documentation.js.org
-.. _jsdoc: http://usejsdoc.org
-.. _pyjsdoc: https://github.com/nostrademons/pyjsdoc
-.. _pyjsparser: https://github.com/PiotrDabkowski/pyjsparser
-.. _pytest: https://pytest.org/
-.. _sphinx-js: https://sphinx-js-howto.readthedocs.io
diff --git a/doc/_extensions/autojsdoc/__init__.py b/doc/_extensions/autojsdoc/__init__.py
deleted file mode 100644
index 40a96afc6ff..00000000000
--- a/doc/_extensions/autojsdoc/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-# -*- coding: utf-8 -*-
diff --git a/doc/_extensions/autojsdoc/__main__.py b/doc/_extensions/autojsdoc/__main__.py
deleted file mode 100644
index 2ac5f3a0cb3..00000000000
--- a/doc/_extensions/autojsdoc/__main__.py
+++ /dev/null
@@ -1,154 +0,0 @@
-# -*- coding: utf-8 -*-
-from __future__ import print_function
-import cgitb
-import fnmatch
-import io
-import logging
-
-import click
-
-import pyjsparser
-import sys
-
-from .parser.parser import ModuleMatcher
-from .parser.visitor import Visitor, SKIP
-from .parser import jsdoc
-
-class Printer(Visitor):
- def __init__(self, level=0):
- super(Printer, self).__init__()
- self.level = level
-
- def _print(self, text):
- print(' ' * self.level, text)
-
- def enter_generic(self, node):
- self._print(node['type'])
- self.level += 1
-
- def exit_generic(self, node):
- self.level -= 1
-
- def enter_Identifier(self, node):
- self._print(node['name'])
- return SKIP
-
- def enter_Literal(self, node):
- self._print(node['value'])
- return SKIP
-
- def enter_BinaryExpression(self, node):
- self._print(node['operator'])
- self.level += 1
-
-def visit_files(files, visitor, ctx):
- for name in files:
- with io.open(name) as f:
- ctx.logger.info("%s", name)
- try:
- yield visitor().visit(pyjsparser.parse(f.read()))
- except Exception as e:
- if ctx.logger.isEnabledFor(logging.DEBUG):
- ctx.logger.exception("while visiting %s", name)
- else:
- ctx.logger.error("%s while visiting %s", e, name)
-
-# bunch of modules various bits depend on which are not statically defined
-# (or are outside the scope of the system)
-ABSTRACT_MODULES = [
- jsdoc.ModuleDoc({
- 'module': 'web.web_client',
- 'dependency': {'web.AbstractWebClient'},
- 'exports': jsdoc.NSDoc({
- 'name': 'web_client',
- 'doc': 'instance of AbstractWebClient',
- }),
- }),
- jsdoc.ModuleDoc({
- 'module': 'web.Tour',
- 'dependency': {'web_tour.TourManager'},
- 'exports': jsdoc.NSDoc({
- 'name': 'Tour',
- 'doc': 'maybe tourmanager instance?',
- }),
- }),
- # OH FOR FUCK'S SAKE
- jsdoc.ModuleDoc({
- 'module': 'summernote/summernote',
- 'exports': jsdoc.NSDoc({'doc': "totally real summernote"}),
- })
-]
-
-@click.group(context_settings={'help_option_names': ['-h', '--help']})
-@click.option('-v', '--verbose', count=True)
-@click.option('-q', '--quiet', count=True)
-@click.pass_context
-def autojsdoc(ctx, verbose, quiet):
- logging.basicConfig(
- level=logging.INFO + (quiet - verbose) * 10,
- format="[%(levelname)s %(created)f] %(message)s",
- )
- ctx.logger = logging.getLogger('autojsdoc')
- ctx.visitor = None
- ctx.files = []
- ctx.kw = {}
-
-@autojsdoc.command()
-@click.argument('files', type=click.Path(exists=True), nargs=-1)
-@click.pass_context
-def ast(ctx, files):
- """ Prints a structure tree of the provided files
- """
- if not files:
- print(ctx.get_help())
- visit_files(files, lambda: Printer(level=1), ctx.parent)
-
-@autojsdoc.command()
-@click.option('-m', '--module', multiple=True, help="Only shows dependencies matching any of the patterns")
-@click.argument('files', type=click.Path(exists=True), nargs=-1)
-@click.pass_context
-def dependencies(ctx, module, files):
- """ Prints a dot file of all modules to stdout
- """
- if not files:
- print(ctx.get_help())
- byname = {
- mod.name: mod.dependencies
- for mod in ABSTRACT_MODULES
- }
- for modules in visit_files(files, ModuleMatcher, ctx.parent):
- for mod in modules:
- byname[mod.name] = mod.dependencies
-
- print('digraph dependencies {')
-
- todo = set()
- # if module filters, roots are only matching modules
- if module:
- for f in module:
- todo.update(fnmatch.filter(byname.keys(), f))
-
- for m in todo:
- # set a different box for selected roots
- print(' "%s" [color=orangered]' % m)
- else:
- # otherwise check all modules
- todo.update(byname)
-
- done = set()
- while todo:
- node = todo.pop()
- if node in done:
- continue
-
- done.add(node)
- deps = byname[node]
- todo.update(deps - done)
- for dep in deps:
- print(' "%s" -> "%s";' % (node, dep))
- print('}')
-
-try:
- autojsdoc.main(prog_name='autojsdoc')
-except Exception:
- print(cgitb.text(sys.exc_info()))
diff --git a/doc/_extensions/autojsdoc/ext/__init__.py b/doc/_extensions/autojsdoc/ext/__init__.py
deleted file mode 100644
index e27a9e3d318..00000000000
--- a/doc/_extensions/autojsdoc/ext/__init__.py
+++ /dev/null
@@ -1,13 +0,0 @@
-# -*- coding: utf-8 -*-
-from .directives import automodule_bound, autodirective_bound
-from .extractor import _get_roots
-
-
-def setup(app):
- app.add_config_value('js_roots', _get_roots, 'env')
- modules = {}
- app.add_directive_to_domain('js', 'automodule', automodule_bound(app, modules)
- )
- autodirective = autodirective_bound(app, modules)
- for n in ['autonamespace', 'automixin', 'autoclass', 'autofunction']:
- app.add_directive_to_domain('js', n, autodirective)
diff --git a/doc/_extensions/autojsdoc/ext/directives.py b/doc/_extensions/autojsdoc/ext/directives.py
deleted file mode 100644
index c666b07a20d..00000000000
--- a/doc/_extensions/autojsdoc/ext/directives.py
+++ /dev/null
@@ -1,719 +0,0 @@
-# -*- coding: utf-8 -*-
-import abc
-import collections
-import contextlib
-import fnmatch
-import io
-import re
-
-from docutils import nodes
-from docutils.parsers.rst import Directive
-from docutils.statemachine import StringList
-from sphinx import addnodes
-from sphinx.ext.autodoc import members_set_option, bool_option, ALL
-
-from autojsdoc.ext.extractor import read_js
-from ..parser import jsdoc, types
-
-class DocumenterError(Exception): pass
-
-@contextlib.contextmanager
-def addto(parent, newnode):
- assert isinstance(newnode, nodes.Node), \
- "Expected newnode to be a Node, got %s" % (type(newnode))
- yield newnode
- parent.append(newnode)
-
-
-def documenter_for(directive, doc):
- if isinstance(doc, jsdoc.FunctionDoc):
- return FunctionDocumenter(directive, doc)
- if isinstance(doc, jsdoc.ClassDoc):
- return ClassDocumenter(directive, doc)
- if isinstance(doc, jsdoc.MixinDoc):
- return MixinDocumenter(directive, doc)
- if isinstance(doc, (jsdoc.PropertyDoc, jsdoc.LiteralDoc)):
- return PropertyDocumenter(directive, doc)
- if isinstance(doc, jsdoc.InstanceDoc):
- return InstanceDocumenter(directive, doc)
- if isinstance(doc, jsdoc.Unknown):
- return UnknownDocumenter(directive, doc)
- if isinstance(doc, jsdoc.NSDoc):
- return NSDocumenter(directive, doc)
-
- raise TypeError("No documenter for %s" % type(doc))
-
-def to_list(doc, source=None):
- return StringList([
- line.rstrip('\n')
- for line in io.StringIO(doc)
- ], source=source)
-
-DIRECTIVE_OPTIONS = {
- 'members': members_set_option,
- 'undoc-members': bool_option,
- 'private-members': bool_option,
- 'undoc-matches': bool_option,
-}
-def automodule_bound(app, modules):
- class AutoModuleDirective(Directive):
- required_arguments = 1
- has_content = True
- option_spec = DIRECTIVE_OPTIONS
-
- # self.state.nested_parse(string, offset, node) => parse context for sub-content (body which can contain RST data)
- # => needed for doc (converted?) and for actual directive body
- def run(self):
- self.env = self.state.document.settings.env
- modname = self.arguments[0].strip()
-
- # TODO: cache/memoize modules & symbols?
- if not modules:
- read_js(app, modules)
-
- mods = [
- (name, mod)
- for name, mod in modules.items()
- if fnmatch.fnmatch(name, modname)
- ]
- ret = []
- for name, mod in mods:
- if mod.is_private:
- continue
- if name != modname and not (mod.doc or mod.exports):
- # this module has no documentation, no exports and was
- # not specifically requested through automodule -> skip
- # unless requested
- if not self.options.get('undoc-matches'):
- continue
- modsource = mod['sourcefile']
- if modsource:
- self.env.note_dependency(modsource)
- # not sure what that's used for as normal xrefs are resolved using the id directly
- target = nodes.target('', '', ids=['module-' + name], ismod=True)
- self.state.document.note_explicit_target(target)
-
- documenter = ModuleDocumenter(self, mod)
-
- ret.append(target)
- ret.extend(documenter.generate())
- return ret
-
- return AutoModuleDirective
-
-def autodirective_bound(app, modules):
- documenters = {
- 'js:autoclass': ClassDocumenter,
- 'js:autonamespace': NSDocumenter,
- 'js:autofunction': FunctionDocumenter,
- 'js:automixin': MixinDocumenter,
- }
- class AutoDirective(Directive):
- required_arguments = 1
- has_content = True
- option_spec = DIRECTIVE_OPTIONS
-
- def run(self):
- self.env = self.state.document.settings.env
-
- objname = self.arguments[0].strip()
- if not modules:
- read_js(app, modules)
-
- # build complete path to object
- path = self.env.temp_data.get('autojs:prefix', []) + objname.split('.')
- # look for module/object split
- for i in range(1, len(path)):
- modname, objpath = '.'.join(path[:-i]), path[-i:]
- module = modules.get(modname)
- if module:
- break
- else:
- raise Exception("Found no valid module in " + '.'.join(path))
-
- item = module
- # deref' namespaces until we reach the object we're looking for
- for k in objpath:
- item = item.get_property(k)
-
- docclass = documenters[self.name]
- return docclass(self, item).generate()
-
- return AutoDirective
-
-class Documenter(object):
- objtype = None
- def __init__(self, directive, doc):
- self.directive = directive
- self.env = directive.env
- self.item = doc
-
- @property
- def modname(self):
- return self.env.temp_data.get('autojs:module', '')
- @property
- def classname(self):
- return self.env.temp_data.get('autojs:class', '')
- def generate(self, all_members=False):
- """
- :rtype: List[nodes.Node]
- """
- try:
- return self._generate(all_members=all_members)
- except Exception as e:
- raise DocumenterError("Failed to document %s" % self.item) from e
- def _generate(self, all_members=False):
- objname = self.item.name
- prefixed = (self.item['sourcemodule'].name + '.' + objname) if self.item['sourcemodule'] else None
- objtype = self.objtype
- assert objtype, '%s has no objtype' % type(self)
- root = addnodes.desc(domain='js', desctype=objtype, objtype=objtype)
- with addto(root, addnodes.desc_signature(
- module=self.modname or '',
- fullname=objname,
- )) as s:
- s['class'] = self.classname
-
- s['ids'] = []
- if objname:
- s['ids'].append(objname)
- if prefixed:
- s['ids'].append(prefixed)
-
- if objtype:
- s += addnodes.desc_annotation(
- objtype, objtype,
- nodes.Text(' '),
- )
-
- env = self.env
- if objname:
- env.domaindata['js']['objects'][objname] = (env.docname, objtype)
- if prefixed:
- env.domaindata['js']['objects'][prefixed] = (env.docname, objtype)
-
- # TODO: linkcode_resolve
- s += self.make_signature()
- with addto(root, addnodes.desc_content()) as c:
- # must be here otherwise nested_parse(self.content) will not have
- # the prefix set
- self.env.temp_data.setdefault('autojs:prefix', []).append(self.item.name)
- c += self.make_content(all_members=all_members)
- self.env.temp_data['autojs:prefix'].pop()
- return [root]
-
- def make_signature(self):
- """
- :rtype: List[nodes.Node]
- """
- return [addnodes.desc_name(self.item.name, self.item.name)]
-
- @abc.abstractmethod
- def make_content(self, all_members):
- """
- :rtype: List[nodes.Node]
- """
-
- def document_subtypes(self, subtypes):
- docs = []
- with with_mapping_value(self.directive.options, 'undoc-members', True):
- for cls in subtypes:
- docs += ClassDocumenter(self.directive, cls).generate(all_members=True)
- return docs
-
-
-class NSDocumenter(Documenter):
- objtype = 'namespace'
- def make_content(self, all_members):
- doc = self.item
- ret = nodes.section()
-
- if doc.doc:
- self.directive.state.nested_parse(to_list(doc.doc), 0, ret)
-
- self.directive.state.nested_parse(self.directive.content, 0, ret)
-
- ret += self.document_properties(all_members)
- return ret.children
-
- def should_document(self, member, name, all_members):
- """
- :type member: jsdoc.CommentDoc
- :type name: str
- :type all_members: bool
- :rtype: bool
- """
- options = self.directive.options
-
- members = options.get('members') or []
- if not (all_members or members is ALL):
- # if a member is requested by name, it's always documented
- return name in members
-
- # ctor params are merged into the class doc
- if member.is_constructor:
- return False
-
- # only document "private" members if option is set
- if self.is_private(member, name) and not options.get('private-members'):
- return False
-
- # TODO: what if member doesn't have a description but has non-desc tags set?
- # TODO: add @public to force documenting symbol? => useful for implicit typedef
- return bool(member.doc or options.get('undoc-members'))
-
- def is_private(self, member, name):
- return member.is_private
-
- def document_properties(self, all_members):
- ret = nodes.section()
- # TODO: :member-order: [alphabetical | groupwise | bysource]
- for (n, p) in self.item.properties:
- if not self.should_document(p, n, all_members):
- continue
- # FIXME: maybe should use property name as name inside?
- ret += documenter_for(self.directive, p).generate(all_members=True)
- return ret.children
-
-_NONE = object()
-@contextlib.contextmanager
-def with_mapping_value(mapping, key, value, restore_to=_NONE):
- """ Sets ``key`` to ``value`` for the duration of the context.
-
- If ``restore_to`` is not provided, restores ``key``'s old value
- afterwards, removes it entirely if there was no value for ``key`` in the
- mapping.
-
- .. warning:: for defaultdict & similar mappings, may restore the default
- value (depends how the collections' .get behaves)
- """
- if restore_to is _NONE:
- restore_to = mapping.get(key, _NONE)
- mapping[key] = value
- try:
- yield
- finally:
- if restore_to is _NONE:
- del mapping[key]
- else:
- mapping[key] = restore_to
-class ModuleDocumenter(NSDocumenter):
- objtype = 'module'
- def document_properties(self, all_members):
- with with_mapping_value(self.env.temp_data, 'autojs:module', self.item.name, ''):
- return super(ModuleDocumenter, self).document_properties(all_members)
-
- def make_content(self, all_members):
- doc = self.item
- content = addnodes.desc_content()
-
- if doc.exports or doc.dependencies:
- with addto(content, nodes.field_list()) as fields:
- if doc.exports:
- with addto(fields, nodes.field()) as field:
- field += nodes.field_name('Exports', 'Exports')
- with addto(field, nodes.field_body()) as body:
- ref = doc['exports'] # warning: not the same as doc.exports
- label = ref or '<anonymous>'
- link = addnodes.pending_xref(
- ref, nodes.paragraph(ref, label),
- refdomain='js',
- reftype='any',
- reftarget=ref,
- )
- link['js:module'] = doc.name
- body += link
-
- if doc.dependencies:
- with addto(fields, nodes.field()) as field:
- self.make_dependencies(field, doc)
-
- if doc.doc:
- # FIXME: source offset
- self.directive.state.nested_parse(to_list(doc.doc, source=doc['sourcefile']), 0, content)
-
- self.directive.state.nested_parse(self.directive.content, 0, content)
-
- content += self.document_properties(all_members)
-
- return content
-
- def make_dependencies(self, field, doc):
- field += nodes.field_name("Depends On", "Depends On")
- with addto(field, nodes.field_body()) as body:
- with addto(body, nodes.bullet_list()) as deps:
- for dep in sorted(doc.dependencies):
- ref = addnodes.pending_xref(
- dep, nodes.paragraph(dep, dep),
- refdomain='js',
- reftype='module',
- reftarget=dep,
- )
- deps += nodes.list_item(dep, ref)
-
- def should_document(self, member, name, all_members):
- # member can be Nothing?
- if not member:
- return False
- modname = getattr(member['sourcemodule'], 'name', None)
- doc = self.item
-
- # always document exported symbol (regardless undoc, private, ...)
- # otherwise things become... somewhat odd
- if name == doc['exports']:
- return True
-
- # if doc['exports'] the module is exporting a "named" item which
- # does not need to be documented twice, if not doc['exports'] it's
- # exporting an anonymous item (e.g. object literal) which needs to
- # be documented on its own
- if name == '<exports>' and not doc['exports']:
- return True
-
- # TODO: :imported-members:
- # FIXME: *directly* re-exported "foreign symbols"?
- return (not modname or modname == doc.name) \
- and super(ModuleDocumenter, self).should_document(member, name, all_members)
-
-
-class ClassDocumenter(NSDocumenter):
- objtype = 'class'
-
- def document_properties(self, all_members):
- with with_mapping_value(self.env.temp_data, 'autojs:class', self.item.name, ''):
- return super(ClassDocumenter, self).document_properties(all_members)
-
- def make_signature(self):
- sig = super(ClassDocumenter, self).make_signature()
- sig.append(self.make_parameters())
- return sig
-
- def make_parameters(self):
- params = addnodes.desc_parameterlist('', '')
- ctor = self.item.constructor
- if ctor:
- params += make_desc_parameters(ctor.params)
-
- return params
-
- def make_content(self, all_members):
- doc = self.item
- ret = nodes.section()
-
- ctor = self.item.constructor
- params = subtypes = []
- if ctor:
- check_parameters(self, ctor)
- params, subtypes = extract_subtypes(doc.name, ctor)
-
- fields = nodes.field_list()
- fields += self.make_super()
- fields += self.make_mixins()
- fields += self.make_params(params)
- if fields.children:
- ret += fields
-
- if doc.doc:
- self.directive.state.nested_parse(to_list(doc.doc), 0, ret)
-
- self.directive.state.nested_parse(self.directive.content, 0, ret)
-
- ret += self.document_properties(all_members)
-
- ret += self.document_subtypes(subtypes)
-
- return ret.children
-
- def is_private(self, member, name):
- return name.startswith('_') or super(ClassDocumenter, self).is_private(member, name)
-
- def make_super(self):
- doc = self.item
- if not doc.superclass:
- return []
-
- sup_link = addnodes.pending_xref(
- doc.superclass.name, nodes.paragraph(doc.superclass.name, doc.superclass.name),
- refdomain='js', reftype='class', reftarget=doc.superclass.name,
- )
- sup_link['js:module'] = doc.superclass['sourcemodule'].name
- return nodes.field(
- '',
- nodes.field_name("Extends", "Extends"),
- nodes.field_body(doc.superclass.name, sup_link),
- )
-
- def make_mixins(self):
- doc = self.item
- if not doc.mixins:
- return []
-
- ret = nodes.field('', nodes.field_name("Mixes", "Mixes"))
- with addto(ret, nodes.field_body()) as body:
- with addto(body, nodes.bullet_list()) as mixins:
- for mixin in sorted(doc.mixins, key=lambda m: m.name):
- mixin_link = addnodes.pending_xref(
- mixin.name, nodes.paragraph(mixin.name, mixin.name),
- refdomain='js', reftype='mixin', reftarget=mixin.name
- )
- mixin_link['js:module'] = mixin['sourcemodule'].name
- mixins += nodes.list_item('', mixin_link)
- return ret
-
- def make_params(self, params):
- if not params:
- return []
-
- ret = nodes.field('', nodes.field_name('Parameters', 'Parameters'))
- with addto(ret, nodes.field_body()) as body,\
- addto(body, nodes.bullet_list()) as holder:
- holder += make_parameters(params, mod=self.modname)
- return ret
-
-class InstanceDocumenter(Documenter):
- objtype = 'object'
- def make_signature(self):
- cls = self.item.cls
- ret = super(InstanceDocumenter, self).make_signature()
- if cls:
- super_ref = addnodes.pending_xref(
- cls.name, nodes.Text(cls.name, cls.name),
- refdomain='js', reftype='class', reftarget=cls.name
- )
- super_ref['js:module'] = cls['sourcemodule'].name
- ret.append(addnodes.desc_annotation(' instance of ', ' instance of '))
- ret.append(addnodes.desc_type(cls.name, '', super_ref))
- if not ret:
- return [addnodes.desc_name('???', '???')]
- return ret
-
- def make_content(self, all_members):
- ret = nodes.section()
-
- if self.item.doc:
- self.directive.state.nested_parse(to_list(self.item.doc), 0, ret)
-
- self.directive.state.nested_parse(self.directive.content, 0, ret)
-
- return ret.children
-
-class FunctionDocumenter(Documenter):
- @property
- def objtype(self):
- return 'method' if self.classname else 'function'
- def make_signature(self):
- ret = super(FunctionDocumenter, self).make_signature()
- with addto(ret, addnodes.desc_parameterlist()) as params:
- params += make_desc_parameters(self.item.params)
- retval = self.item.return_val
- if retval.type or retval.doc:
- ret.append(addnodes.desc_returns(retval.type or '*', retval.type or '*'))
- return ret
-
- def make_content(self, all_members):
- ret = nodes.section()
- doc = self.item
-
- if doc.doc:
- self.directive.state.nested_parse(to_list(doc.doc), 0, ret)
-
- self.directive.state.nested_parse(self.directive.content, 0, ret)
-
- check_parameters(self, doc)
-
- params, subtypes = extract_subtypes(self.item.name, self.item)
- rdoc = doc.return_val.doc
- rtype = doc.return_val.type
- if params or rtype or rdoc:
- with addto(ret, nodes.field_list()) as fields:
- if params:
- with addto(fields, nodes.field()) as field:
- field += nodes.field_name('Parameters', 'Parameters')
- with addto(field, nodes.field_body()) as body,\
- addto(body, nodes.bullet_list()) as holder:
- holder.extend(make_parameters(params, mod=doc['sourcemodule'].name))
- if rdoc:
- with addto(fields, nodes.field()) as field:
- field += nodes.field_name("Returns", "Returns")
- with addto(field, nodes.field_body()) as body,\
- addto(body, nodes.paragraph()) as p:
- p += nodes.inline(rdoc, rdoc)
- if rtype:
- with addto(fields, nodes.field()) as field:
- field += nodes.field_name("Return Type", "Return Type")
- with addto(field, nodes.field_body()) as body, \
- addto(body, nodes.paragraph()) as p:
- p += make_types(rtype, mod=doc['sourcemodule'].name)
-
- ret += self.document_subtypes(subtypes)
-
- return ret.children
-
-def pascal_case_ify(name):
- """
- Uppercase first letter of ``name``, or any letter following an ``_``. In
- the latter case, also strips out the ``_``.
-
- => key_for becomes KeyFor
- => options becomes Options
- """
- return re.sub(r'(^|_)\w', lambda m: m.group(0)[-1].upper(), name)
-def extract_subtypes(parent_name, doc):
- """ Extracts composite parameters (a.b) into sub-types for the parent
- parameter, swaps the parent's type from whatever it is to the extracted
- one, and returns the extracted type for inclusion into the parent.
-
- :arg parent_name: name of the containing symbol (function, class), will
- be used to compose subtype names
- :type parent_name: str
- :type doc: FunctionDoc
- :rtype: (List[ParamDoc], List[ClassDoc])
- """
- # map of {param_name: [ParamDoc]} (from complete doc)
- subparams = collections.defaultdict(list)
- for p in map(jsdoc.ParamDoc, doc.get_as_list('param')):
- pair = p.name.split('.', 1)
- if len(pair) == 2:
- k, p.name = pair # remove prefix from param name
- subparams[k].append(p)
-
- # keep original params order as that's the order of formal parameters in
- # the function signature
- params = collections.OrderedDict((p.name, p) for p in doc.params)
- subtypes = []
- # now we can use the subparams map to extract "compound" parameter types
- # and swap the new type for the original param's type
- for param_name, subs in subparams.items():
- typename = '%s%s' % (
- pascal_case_ify(parent_name),
- pascal_case_ify(param_name),
- )
- param = params[param_name]
- param.type = typename
- subtypes.append(jsdoc.ClassDoc({
- 'name': typename,
- 'doc': param.doc,
- '_members': [
- # TODO: add default value
- (sub.name, jsdoc.PropertyDoc(dict(sub.to_dict(), sourcemodule=doc['sourcemodule'])))
- for sub in subs
- ],
- 'sourcemodule': doc['sourcemodule'],
- }))
- return params.values(), subtypes
-
-def check_parameters(documenter, doc):
- """
- Check that all documented parameters match a formal parameter for the
- function. Documented params which don't match the actual function may be
- typos.
- """
- guessed = set(doc['guessed_params'] or [])
- if not guessed:
- return
-
- documented = {
- # param name can be of the form [foo.bar.baz=default]\ndescription
- jsdoc.ParamDoc(text).name.split('.')[0]
- for text in doc.get_as_list('param')
- }
- odd = documented - guessed
- if not odd:
- return
-
- app = documenter.directive.env.app
- app.warn("Found documented params %s not in formal parameter list "
- "of function %s in module %s (%s)" % (
- ', '.join(odd),
- doc.name,
- documenter.modname,
- doc['sourcemodule']['sourcefile'],
- ))
-
-def make_desc_parameters(params):
- for p in params:
- if '.' in p.name:
- continue
-
- node = addnodes.desc_parameter(p.name, p.name)
- if p.optional:
- node = addnodes.desc_optional('', '', node)
- yield node
-
-def make_parameters(params, mod=None):
- for param in params:
- p = nodes.paragraph('', '', nodes.strong(param.name, param.name))
- if param.default is not None:
- p += nodes.Text('=', '=')
- p += nodes.emphasis(param.default, param.default)
- if param.type:
- p += nodes.Text(' (')
- p += make_types(param.type, mod=mod)
- p += nodes.Text(')')
- if param.doc:
- p += [
- nodes.Text(' -- '),
- nodes.inline(param.doc, param.doc)
- ]
- yield p
-
-
-def _format_value(v):
- if v == '|':
- return nodes.emphasis(' or ', ' or ')
- if v == ',':
- return nodes.Text(', ', ', ')
- return nodes.Text(v, v)
-def make_types(typespec, mod=None):
- # TODO: in closure notation {type=} => optional, do we care?
- def format_type(t):
- ref = addnodes.pending_xref(
- t, addnodes.literal_emphasis(t, t),
- refdomain='js', reftype='class', reftarget=t,
- )
- if mod:
- ref['js:module'] = mod
- return ref
-
- try:
- return types.iterate(
- types.parse(typespec),
- format_type,
- _format_value
- )
- except ValueError as e:
- raise ValueError("%s in '%s'" % (e, typespec))
-
-
-class MixinDocumenter(NSDocumenter):
- objtype = 'mixin'
-
-class PropertyDocumenter(Documenter):
- objtype = 'attribute'
- def make_signature(self):
- ret = super(PropertyDocumenter, self).make_signature()
- proptype = self.item.type
- if proptype:
- typeref = addnodes.pending_xref(
- proptype, nodes.Text(proptype, proptype),
- refdomain='js', reftype='class', reftarget=proptype
- )
- typeref['js:module'] = self.item['sourcemodule'].name
- ret.append(nodes.Text(' '))
- ret.append(typeref)
- return ret
-
- def make_content(self, all_members):
- doc = self.item
- ret = nodes.section()
-
- self.directive.state.nested_parse(self.directive.content, 0, ret)
-
- if doc.doc:
- self.directive.state.nested_parse(to_list(doc.doc), 0, ret)
- return ret.children
-
-class UnknownDocumenter(Documenter):
- objtype = 'unknown'
- def make_content(self, all_members):
- return []
diff --git a/doc/_extensions/autojsdoc/ext/extractor.py b/doc/_extensions/autojsdoc/ext/extractor.py
deleted file mode 100644
index 36211cfd3b3..00000000000
--- a/doc/_extensions/autojsdoc/ext/extractor.py
+++ /dev/null
@@ -1,87 +0,0 @@
-# -*- coding: utf-8 -*-
-import io
-import os
-
-import pyjsdoc
-import pyjsparser
-
-try:
- from sphinx.util import status_iterator
- def it(app): return status_iterator
-except ImportError:
- # 1.2: Builder.status_iterator
- # 1.3: Application.status_iterator (with alias on Builder)
- # 1.6: sphinx.util.status_iterator (with *deprecated* aliases on Application and Builder)
- # 1.7: removed Application and Builder aliases
- # => if no sphinx.util.status_iterator, fallback onto the builder one for
- # 1.2 compatibility, remove this entirely if we ever require 1.6+
- status_iterator = None
- def it(app): return app.builder.status_iterator
-
-from ..parser import jsdoc, parser
-
-
-def _get_roots(conf):
- env_roots = os.environ.get('AUTOJSDOC_ROOTS_PATH')
- if env_roots:
- return env_roots.split(':')
- return []
-
-def read_js(app, modules):
- """
- :type app: sphinx.application.Sphinx
- :type modules: Dict[str, jsdoc.ModuleDoc]
- """
- roots = map(os.path.normpath, app.config.js_roots or [os.path.join(app.confdir, '..')])
- files = [
- os.path.join(r, f)
- for root in roots
- for r, _, fs in os.walk(root)
- if 'static/src/js' in r
- for f in fs
- if f.endswith('.js')
- ]
-
- modules.update((mod.name, mod) for mod in ABSTRACT_MODULES)
- for name in it(app)(files, "Parsing javascript files...", length=len(files)):
- with io.open(name) as f:
- ast = pyjsparser.parse(f.read())
- modules.update(
- (mod.name, mod)
- for mod in parser.ModuleMatcher(name).visit(ast)
- )
- _resolve_references(modules)
-
-def _resolve_references(byname):
- # must be done in topological order otherwise the dependent can't
- # resolve non-trivial references to a dependency properly
- for name in pyjsdoc.topological_sort(
- *pyjsdoc.build_dependency_graph(
- list(byname.keys()),
- byname
- )
- ):
- byname[name].post_process(byname)
-
-ABSTRACT_MODULES = [
- jsdoc.ModuleDoc({
- 'module': u'web.web_client',
- 'dependency': {u'web.AbstractWebClient'},
- 'exports': jsdoc.NSDoc({
- 'name': u'web_client',
- 'doc': u'instance of AbstractWebClient',
- }),
- }),
- jsdoc.ModuleDoc({
- 'module': u'web.Tour',
- 'dependency': {u'web_tour.TourManager'},
- 'exports': jsdoc.NSDoc({
- 'name': u'Tour',
- 'doc': u'maybe tourmanager instance?',
- }),
- }),
- jsdoc.ModuleDoc({
- 'module': u'summernote/summernote',
- 'exports': jsdoc.NSDoc({'doc': u"totally real summernote"}),
- })
-]
diff --git a/doc/_extensions/autojsdoc/parser/__init__.py b/doc/_extensions/autojsdoc/parser/__init__.py
deleted file mode 100644
index 40a96afc6ff..00000000000
--- a/doc/_extensions/autojsdoc/parser/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-# -*- coding: utf-8 -*-
diff --git a/doc/_extensions/autojsdoc/parser/jsdoc.py b/doc/_extensions/autojsdoc/parser/jsdoc.py
deleted file mode 100644
index 9e9b0ba441d..00000000000
--- a/doc/_extensions/autojsdoc/parser/jsdoc.py
+++ /dev/null
@@ -1,357 +0,0 @@
-# -*- coding: utf-8 -*-
-import re
-
-import collections
-
-import pyjsdoc
-
-def strip_stars(doc_comment):
- """
- Version of jsdoc.strip_stars which always removes 1 space after * if
- one is available.
- """
- return re.sub('\n\s*?\*[\t ]?', '\n', doc_comment[3:-2]).strip()
-
-class ParamDoc(pyjsdoc.ParamDoc):
- """
- Replace ParamDoc because FunctionDoc doesn't properly handle optional
- params or default values (TODO: or compounds) if guessed_params is used
-
- => augment paramdoc with "required" and "default" items to clean up name
- """
- def __init__(self, text):
- super(ParamDoc, self).__init__(text)
- # param name and doc can be separated by - or :, strip it
- self.doc = self.doc.strip().lstrip('-:').lstrip()
- self.optional = False
- self.default = None
- # there may not be a space between the param name and the :, in which
- # case the : gets attached to the name, strip *again*
- # TODO: formal @param/@property parser to handle this crap properly once and for all
- self.name = self.name.strip().rstrip(':')
- if self.name.startswith('['):
- self.name = self.name.strip('[]')
- self.optional = True
- if '=' in self.name:
- self.name, self.default = self.name.rsplit('=', 1)
- def to_dict(self):
- d = super(ParamDoc, self).to_dict()
- d['optional'] = self.optional
- d['default'] = self.default
- return d
-pyjsdoc.ParamDoc = ParamDoc
-
-class CommentDoc(pyjsdoc.CommentDoc):
- namekey = object()
- is_constructor = False
-
- @property
- def name(self):
- return self[self.namekey] or self['name'] or self['guessed_name']
- def set_name(self, name):
- # not great...
- if name != '<exports>':
- self.parsed['guessed_name'] = name
-
- @property
- def is_private(self):
- return 'private' in self.parsed
-
- def to_dict(self):
- d = super(CommentDoc, self).to_dict()
- d['name'] = self.name
- return d
-
- # don't resolve already resolved docs (e.g. a literal dict being
- # include-ed in two different classes because I don't even care anymore
- def become(self, modules):
- return self
-
-class PropertyDoc(CommentDoc):
- @classmethod
- def from_param(cls, s, sourcemodule=None):
- parsed = ParamDoc(s).to_dict()
- parsed['sourcemodule'] = sourcemodule
- return cls(parsed)
-
- @property
- def type(self):
- return self['type'].strip('{}')
-
- def to_dict(self):
- d = super(PropertyDoc, self).to_dict()
- d['type'] = self.type
- d['is_private'] = self.is_private
- return d
-
-class InstanceDoc(CommentDoc):
- @property
- def cls(self):
- return self['cls']
-
- def to_dict(self):
- return dict(super(InstanceDoc, self).to_dict(), cls=self.cls)
-
-class LiteralDoc(CommentDoc):
- @property
- def type(self):
- if self['type']:
- return self['type']
- valtype = type(self['value'])
- if valtype is bool:
- return 'Boolean'
- elif valtype is float:
- return 'Number'
- elif valtype is type(u''):
- return 'String'
- return ''
-
- @property
- def value(self):
- return self['value']
-
- def to_dict(self):
- d = super(LiteralDoc, self).to_dict()
- d['type'] = self.type
- d['value'] = self.value
- return d
-
-class FunctionDoc(CommentDoc):
- type = 'Function'
- namekey = 'function'
-
- @property
- def is_constructor(self):
- return self.name == 'init'
-
- @property
- def params(self):
- tag_texts = self.get_as_list('param')
- # turns out guessed_params is *almost* (?) always set to a list,
- # if empty list of guessed params fall back to @params
- if not self['guessed_params']:
- # only get "primary" params (no "." in name)
- return [
- p for p in map(ParamDoc, tag_texts)
- if '.' not in p.name
- ]
- else:
- param_dict = {}
- for text in tag_texts:
- param = ParamDoc(text)
- param_dict[param.name] = param
- return [param_dict.get(name) or ParamDoc('{} ' + name)
- for name in self.get('guessed_params')]
- @property
- def return_val(self):
- ret = self.get('return') or self.get('returns')
- type = self.get('type')
- if '{' in ret and '}' in ret:
- if not '} ' in ret:
- # Ensure that name is empty
- ret = re.sub(r'\}\s*', '} ', ret)
- return ParamDoc(ret)
- if ret and type:
- return ParamDoc('{%s} %s' % (type, ret))
- return ParamDoc(ret)
-
- def to_dict(self):
- d = super(FunctionDoc, self).to_dict()
- d['name'] = self.name
- d['params'] = [param.to_dict() for param in self.params]
- d['return_val']= self.return_val.to_dict()
- return d
-
-class NSDoc(CommentDoc):
- namekey = 'namespace'
- def __init__(self, parsed_comment):
- super(NSDoc, self).__init__(parsed_comment)
- self.members = collections.OrderedDict()
- def add_member(self, name, member):
- """
- :type name: str
- :type member: CommentDoc
- """
- member.set_name(name)
- self.members[name] = member
-
- @property
- def properties(self):
- if self.get('property'):
- return [
- (p.name, p)
- for p in (
- PropertyDoc.from_param(p, self['sourcemodule'])
- for p in self.get_as_list('property')
- )
- ]
- return list(self.members.items()) or self['_members'] or []
-
- def has_property(self, name):
- return self.get_property(name) is not None
-
- def get_property(self, name):
- return next((p for n, p in self.properties if n == name), None)
-
- def to_dict(self):
- d = super(NSDoc, self).to_dict()
- d['properties'] = [(n, p.to_dict()) for n, p in self.properties]
- return d
-
-class MixinDoc(NSDoc):
- namekey = 'mixin'
-
-class ModuleDoc(NSDoc):
- namekey = 'module'
- def __init__(self, parsed_comment):
- super(ModuleDoc, self).__init__(parsed_comment)
- #: callbacks to run with the modules mapping once every module is resolved
- self._post_process = []
-
- def post_process(self, modules):
- for callback in self._post_process:
- callback(modules)
-
- @property
- def module(self):
- return self # lol
-
- @property
- def dependencies(self):
- """
- Returns the immediate dependencies of a module (only those explicitly
- declared/used).
- """
- return self.get('dependency', None) or set()
-
- @property
- def exports(self):
- """
- Returns the actual item exported from the AMD module, can be a
- namespace, a class, a function, an instance, ...
- """
- return self.get_property('<exports>')
-
- def to_dict(self):
- vars = super(ModuleDoc, self).to_dict()
- vars['dependencies'] = self.dependencies
- vars['exports'] = self.exports
- return vars
-
- def __str__(self):
- s = super().__str__()
- if self['sourcefile']:
- s += " in file " + self['sourcefile']
- return s
-
-class ClassDoc(NSDoc):
- namekey = 'class'
- @property
- def constructor(self):
- return self.get_property('init')
-
- @property
- def superclass(self):
- return self['extends'] or self['base']
-
- def get_property(self, method_name):
- if method_name == 'extend':
- return FunctionDoc({
- 'doc': 'Create subclass for %s' % self.name,
- 'guessed_function': 'extend',
- })
- # FIXME: should ideally be a proxy namespace
- if method_name == 'prototype':
- return self
- return super(ClassDoc, self).get_property(method_name)\
- or (self.superclass and self.superclass.get_property(method_name))
-
- @property
- def mixins(self):
- return self.get_as_list('mixes')
-
- def to_dict(self):
- d = super(ClassDoc, self).to_dict()
- d['mixins'] = self.mixins
- return d
-
-DEFAULT = object()
-class UnknownNS(NSDoc):
- params = () # TODO: log warning when (somehow) trying to access / document an unknown object as ctor?
- def get_property(self, name):
- return super(UnknownNS, self).get_property(name) or \
- UnknownNS({'name': '{}.{}'.format(self.name, name)})
-
- def __getitem__(self, item):
- if self._probably_not_property(item):
- return super().__getitem__(item)
- return self.get_property(item)
-
- def _probably_not_property(self, item):
- return (
- not isinstance(item, str)
- or item in (self.namekey, 'name', 'params')
- or item.startswith(('_', 'guessed_'))
- or item in self.parsed
- )
-
-class Unknown(CommentDoc):
- @classmethod
- def from_(cls, source):
- def builder(parsed):
- inst = cls(parsed)
- inst.parsed['source'] = source
- return inst
- return builder
-
- @property
- def name(self):
- return self['name'] + ' ' + self['source']
-
- @property
- def type(self):
- return "Unknown"
-
- def get_property(self, p):
- return Unknown(dict(self.parsed, source=self.name, name=p + '<'))
-
-def parse_comments(comments, doctype=None):
- # find last comment which starts with a *
- docstring = next((
- c['value']
- for c in reversed(comments or [])
- if c['value'].startswith(u'*')
- ), None) or u""
-
- # \n prefix necessary otherwise parse_comment fails to take first
- # block comment parser strips delimiters, but strip_stars fails without
- # them
- extract = '\n' + strip_stars('/*' + docstring + '\n*/')
- parsed = pyjsdoc.parse_comment(extract, u'')
-
- if doctype == 'FunctionExpression':
- doctype = FunctionDoc
- elif doctype == 'ObjectExpression' or doctype is None:
- doctype = guess
-
- if doctype is guess:
- return doctype(parsed)
-
- # in case a specific doctype is given, allow overriding it anyway
- return guess(parsed, default=doctype)
-
-def guess(parsed, default=UnknownNS):
- if 'class' in parsed:
- return ClassDoc(parsed)
- if 'function' in parsed:
- return FunctionDoc(parsed)
- if 'mixin' in parsed:
- return MixinDoc(parsed)
- if 'namespace' in parsed:
- return NSDoc(parsed)
- if 'module' in parsed:
- return ModuleDoc(parsed)
- if 'type' in parsed:
- return PropertyDoc(parsed)
-
- return default(parsed)
diff --git a/doc/_extensions/autojsdoc/parser/parser.py b/doc/_extensions/autojsdoc/parser/parser.py
deleted file mode 100644
index 62660514598..00000000000
--- a/doc/_extensions/autojsdoc/parser/parser.py
+++ /dev/null
@@ -1,572 +0,0 @@
-# -*- coding: utf-8 -*-
-import collections
-
-import pyjsdoc
-
-from . import jsdoc
-from . import utils
-from .visitor import Visitor, SKIP
-
-DECLARATOR_INIT_TO_REF = ('Literal', 'Identifier', 'MemberExpression')
-
-
-class ModuleMatcher(Visitor):
- """Looks for structures of the form::
-
- odoo.define($string, function ($name) {
-
- These are *Odoo module definitions*, upon encountering one the
- matcher:
-
- * creates a module entry, optionally associated with the module comment
- * spawns off a :class:`ModuleBodyMatcher` on the function's body with the
- module name and the $name as "require" function
- """
- def __init__(self, filename):
- super(ModuleMatcher, self).__init__()
- self.filename = filename
- self.result = []
- def enter_Program(self, node):
- pass # allows visiting toplevel
- def enter_ExpressionStatement(self, node):
- # we're interested in expression statements (toplevel call)
- if utils.match(node, {'expression': {
- 'callee': {
- 'object': {'name': 'odoo'},
- 'property': {'name': 'define'},
- },
- }}):
- [module, *_, func] = node['expression']['arguments']
- mod = jsdoc.parse_comments(node.get('comments'), jsdoc.ModuleDoc)
- # set module name
- mod.set_name(module['value'])
- mod.parsed['sourcefile'] = self.filename
- self.result.append(mod)
-
- # get name of require parameter
- require = None # a module can have no dependencies
- if func['params']:
- require = func['params'][0]['name']
- mod.parsed['dependency'], post = ModuleExtractor(mod, require).visit(func['body'])
- mod._post_process.extend(post)
- # don't recurse since we've fired off a sub-visitor for the
- # bits we're interested in
- return SKIP
- def enter_generic(self, node):
- # skip all other toplevel statements
- return SKIP
-
-ref = collections.namedtuple('Ref', 'object property')
-def _name(r):
- bits = []
- while isinstance(r, ref):
- bits.append(str(r.property))
- r = r.object
- return '.'.join(reversed(bits))
-def deref(item, prop=None):
- assert isinstance(item, ref)
-
- while isinstance(item, ref):
- obj = item.object
- if isinstance(obj, ref):
- obj = deref(obj)
-
- if isinstance(obj, (jsdoc.NSDoc, jsdoc.Unknown)):
- item = obj.get_property(item.property)
- elif isinstance(obj, dict):
- item = obj[item.property]
- elif isinstance(obj, jsdoc.PropertyDoc):
- # f'n dynamic crap
- item = jsdoc.Unknown(obj.to_dict()).get_property(item.property)
- else:
- raise ValueError("%r (%s) should be a dict or namespace" % (obj, type(obj)))
- return item
-
-def m2r(me, scope):
- # create a ref to the scope in case it's a hoisted function declaration,
- # this may false-positive on other hoisting but w/e
- if me['type'] == 'Literal':
- return jsdoc.LiteralDoc({'value': me['value']})
- if me['type'] == 'Identifier':
- return ref(scope, me['name'])
- if me['type'] != 'MemberExpression':
- raise ValueError(me)
- return ref(
- m2r(me['object'], scope),
- utils._value(me['property'], strict=True)
- )
-
-NOTHING = object()
-class Declaration(object):
- __slots__ = ['id', 'comments']
- def __init__(self, id=None, comments=NOTHING):
- self.id = id
- self.comments = [] if comments is NOTHING else comments
-
-class ModuleContent(object):
- __slots__ = ['dependencies', 'post']
- def __init__(self, dependencies=NOTHING, post=NOTHING):
- self.dependencies = set() if dependencies is NOTHING else dependencies
- self.post = [] if post is NOTHING else post
- def __iter__(self):
- yield self.dependencies
- yield self.post
-
-class Nothing(object):
- def __init__(self, name):
- self.name = name
- def __bool__(self):
- return False
- __nonzero__ = __bool__
-
-class RefProxy(object):
- def __init__(self, r):
- self._ref = r
- def become(self, modules):
- s = self
- other = deref(self._ref) or Nothing(_name(self._ref))
- # ??? shouldn't all previous refs have been resolved?
- if isinstance(other, (RefProxy, ModuleProxy)):
- other = other.become(modules)
- self.__class__ = other.__class__
- self.__dict__ = other.__dict__
- return self
- def set_name(self, name):
- pass # ???
-class ModuleProxy(object):
- def __init__(self, name):
- self._name = name
-
- # replace the ModuleProxy by the module's exports
- def become(self, modules):
- s = self
- m = modules[self._name].get_property('<exports>') or Nothing(self._name)
- self.__class__ = m.__class__
- self.__dict__ = m.__dict__
- return self
-
- def set_name(self, name):
- pass # FIXME: ???
-
-jq = jsdoc.UnknownNS({
- 'name': u'jQuery',
- 'doc': u'<jQuery>',
-})
-window = jsdoc.UnknownNS({
- 'doc': '<window>',
- 'name': 'window',
-})
-
-class BaseScope(collections.defaultdict):
- """ The base scope assumes anything it's asked for is just an unknown
- (global) namespace of some sort. Can hold a bunch of predefined params but
- avoids the variables inference system blowing up when new (browser)
- globals get used in module bodies.
- """
- def __missing__(self, key):
- it = jsdoc.UnknownNS({
- 'name': key,
- 'doc': u'<%s>' % key,
- })
- self[key] = it
- return it
-BASE_SCOPE = BaseScope(None, {
- '_': jsdoc.UnknownNS({'doc': u'<underscore.js>', 'name': u'_'}),
- '$': jq, 'jQuery': jq,
- 'window': window,
- 'document': window.get_property('document'),
- 'Date': jsdoc.ClassDoc({
- 'name': u'Date',
- 'doc': u'',
- }),
- 'Backbone': jsdoc.UnknownNS({
- '_members': [
- ('Model', jsdoc.ClassDoc({
- 'name': u'Model',
- 'doc': u'',
- })),
- ('Collection', jsdoc.ClassDoc({
- 'name': u'Collection',
- 'doc': u'',
- })),
- ]
- }),
- 'odoo': jsdoc.UnknownNS({
- 'name': u'odoo',
- 'doc': u"Odoo",
- '_members': [
- ('name', jsdoc.PropertyDoc({'name': u'csrf_token', 'type': u'{String}'})),
- ]
- }),
- 'undefined': jsdoc.LiteralDoc({'name': u'undefined', 'value': None}),
-})
-
-class Scope(object):
- """
- Add hoc scope versioning/SSA such that rebinding a symbol in a module
- scope does not screw everything up e.g. "Foo = Foo.extend({})" should not
- have the final Foo extending itself...
- """
- def __init__(self, mapping):
- self._namemap = self._empty(mapping)
- self._targets = []
- for k, v in mapping.items():
- self[k] = v
-
- @staticmethod
- def _empty(mapping):
- m = mapping.copy()
- m.clear()
- return m
-
- def __setitem__(self, k, v):
- self._namemap[k] = len(self._targets)
- self._targets.append(v)
-
- def freeze(self):
- d = self._empty(self._namemap)
- for k, v in self._namemap.items():
- d[k] = self._targets[v]
- return d
-
-class ModuleExtractor(Visitor):
- def __init__(self, module, requirefunc):
- super(ModuleExtractor, self).__init__()
- self.module = module
- self.requirefunc = requirefunc
- self.result = ModuleContent()
- self.scope = Scope(BASE_SCOPE)
- self.declaration = None
-
- def enter_BlockStatement(self, node):
- Hoistifier(self).visit(node)
- def exit_BlockStatement(self, node):
- for k, v in self.scope._namemap.items():
- if k not in BASE_SCOPE:
- self.module.add_member(k, self.scope._targets[v])
- for t in TypedefMatcher(self).visit(node):
- self.module.add_member(t.name, t)
-
- def enter_VariableDeclaration(self, node):
- self.declaration = Declaration(comments=node.get('comments'))
- def enter_VariableDeclarator(self, node):
- # otherwise we've already hoisted the declaration so the variable
- # already exist initialised to undefined, and ValueExtractor does not
- # handle a None input node so it returns None which makes no sense
- if node['init']:
- self.declaration.id = node['id']['name']
- self.scope[self.declaration.id] = ValueExtractor(
- self, self.declaration
- ).visit(node['init'] or [])
- self.declaration.id = None
- return SKIP
- def exit_VariableDeclaration(self, node):
- self.declaration = None
-
- # as the name denotes, AssignmentExpression is an *expression*, which
- # means at the module toplevel it is wrapped into an ExpressionStatement
- # which is where the comments get attached
- def enter_ExpressionStatement(self, node):
- self.declaration = Declaration(comments=node.get('comments'))
- def exit_ExpressionStatement(self, node):
- self.declaration = None
- def enter_AssignmentExpression(self, node):
- target = node['left']
- if target['type'] == 'Identifier':
- self.declaration.id = target['name']
- self.scope[self.declaration.id] = ValueExtractor(
- self, self.declaration
- ).visit(node['right'])
- self.declaration.id = None
- return SKIP
-
- if target['type'] != 'MemberExpression':
- raise ValueError("Unhandled assign to %s" % target['type'])
-
- # only assign to straight a.b.c patterns (OK and trivial literals)
- if target['computed'] and target['property']['type'] != 'Literal':
- return SKIP
-
- name = utils._value(target['property'], strict=True)
- if isinstance(name, type(u'')) and name.endswith('.extend'):
- return SKIP # ignore overwrite of .extend (WTF)
- self.declaration.id = name
- it = ValueExtractor(
- self, self.declaration
- ).visit(node['right'])
- self.declaration.id = None
- assert it, "assigned a non-value from %s to %s" % (node['right'], name)
-
- @self.result.post.append
- def _augment_module(modules):
- try:
- t = deref(m2r(target['object'], self.scope.freeze()))
- except ValueError:
- return # f'n extension of global libraries garbage
- if not isinstance(t, jsdoc.NSDoc):
- # function Foo(){}; Foo.prototype = bar
- # fuck that yo
- return
- # TODO: note which module added this
- m = it
- if isinstance(m, jsdoc.LiteralDoc):
- m = jsdoc.PropertyDoc(m.to_dict())
- t.add_member(name, m)
- return SKIP
-
- def enter_FunctionDeclaration(self, node):
- """ Already processed by hoistitifier
- """
- return SKIP
-
- def enter_ReturnStatement(self, node):
- self.declaration = Declaration(comments=node.get('comments'))
- if node['argument']:
- export = ValueExtractor(self, self.declaration).visit(node['argument'])
- if isinstance(export, RefProxy):
- self.module.parsed['exports'] = _name(export._ref)
- self.scope['<exports>'] = export
- self.declaration = None
- return SKIP
-
- def enter_CallExpression(self, node):
- if utils.match(node, {
- 'callee': {
- 'type': 'MemberExpression',
- 'object': lambda n: (
- n['type'] in ('Identifier', 'MemberExpression')
- # _.str.include
- and not utils._name(n).startswith('_')
- ),
- 'property': {'name': 'include'},
- }
- }):
- target = RefProxy(m2r(node['callee']['object'], self.scope.freeze()))
- target_name = utils._name(node['callee']['object'])
- items = ClassProcessor(self).visit(node['arguments'])
- @self.result.post.append
- def resolve_extension(modules):
- t = target.become(modules)
- if not isinstance(t, jsdoc.ClassDoc):
- return # FIXME: log warning
- # raise ValueError("include() subjects should be classes, %s is %s" % (target_name, type(t)))
- # TODO: note which module added these
- for it in items:
- if isinstance(it, dict):
- for n, member in it.items():
- t.add_member(n, member)
- else:
- t.parsed.setdefault('mixes', []).append(it.become(modules))
-
- return SKIP
-
- def refify(self, node, also=None):
- it = m2r(node, self.scope.freeze())
- assert isinstance(it, ref), "Expected ref, got {}".format(it)
- px = RefProxy(it)
- @self.result.post.append
- def resolve(modules):
- p = px.become(modules)
- if also: also(p)
- return px
-
-class ValueExtractor(Visitor):
- def __init__(self, parent, declaration=None):
- super(ValueExtractor, self).__init__()
- self.parent = parent
- self.declaration = declaration or Declaration()
-
- def enter_generic(self, node):
- self.result = jsdoc.parse_comments(
- self.declaration.comments,
- jsdoc.Unknown.from_(node['type'])
- )
- self._update_result_meta()
- return SKIP
-
- def _update_result_meta(self, name=None):
- self.result.parsed['sourcemodule'] = self.parent.module
- n = name or self.declaration.id
- if n:
- self.result.set_name(n)
-
- def enter_Literal(self, node):
- self.result = jsdoc.parse_comments(
- self.declaration.comments, jsdoc.LiteralDoc)
- self._update_result_meta()
- self.result.parsed['value'] = node['value']
- return SKIP
- def enter_Identifier(self, node):
- self.result = self.parent.refify(node)
- return SKIP
-
- def enter_MemberExpression(self, node):
- self.result = RefProxy(ref(
- ValueExtractor(self.parent).visit(node['object']),
- utils._value(node['property'], strict=True)
- ))
- self.parent.result.post.append(self.result.become)
- return SKIP
-
- def enter_FunctionExpression(self, node):
- name, comments = (self.declaration.id, self.declaration.comments)
- self.result = jsdoc.parse_comments(comments, jsdoc.FunctionDoc)
- self.result.parsed['name'] = node['id'] and node['id']['name']
- self._update_result_meta()
- self.result.parsed['guessed_params'] = [p['name'] for p in node['params']]
- return SKIP
-
- def enter_NewExpression(self, node):
- comments = self.declaration.comments if self.declaration else node.get('comments')
- self.result = ns = jsdoc.parse_comments(comments, jsdoc.InstanceDoc)
- self._update_result_meta()
-
- def _update_contents(cls):
- if not isinstance(cls, jsdoc.ClassDoc):
- return
- ns.parsed['cls'] = cls
- self.parent.refify(node['callee'], also=_update_contents)
- return SKIP
-
- def enter_ObjectExpression(self, node):
- self.result = obj = jsdoc.parse_comments(self.declaration.comments)
- self._update_result_meta()
- for n, p in MemberExtractor(parent=self.parent).visit(node['properties']).items():
- obj.add_member(n, p)
- return SKIP
-
- def enter_CallExpression(self, node):
- # require(a_module_name)
- if utils.match(node, {'callee': {'type': 'Identifier', 'name': self.parent.requirefunc}}):
- depname = node['arguments'][0]['value']
- # TODO: clean this up
- self.parent.result.dependencies.add(depname)
- self.result = ModuleProxy(name=depname)
- self.parent.result.post.append(self.result.become)
-
- # Class.extend(..mixins, {})
- elif utils.match(node, {
- 'callee': {
- 'type': 'MemberExpression',
- 'object': lambda n: (
- n['type'] in ('Identifier', 'MemberExpression')
- # $.extend, $.fn.extend, _.extend
- and not utils._name(n).startswith(('_', '$'))
- ),
- 'property': {'name': 'extend'},
- },
- }): # creates a new class, but may not actually return it
- obj = node['callee']['object']
- comments = self.declaration.comments
- self.result = cls = jsdoc.parse_comments(comments, jsdoc.ClassDoc)
- cls.parsed['extends'] = self.parent.refify(obj)
- self._update_result_meta()
- items = ClassProcessor(self.parent).visit(node['arguments'])
-
- @self.parent.result.post.append
- def add_to_class(modules):
- for item in items:
- if isinstance(item, dict):
- # methods/attributes
- for n, method in item.items():
- cls.add_member(n, method)
- else:
- cls.parsed.setdefault('mixes', []).append(item)
-
- # other function calls
- else:
- self.result = jsdoc.parse_comments(self.declaration.comments, jsdoc.guess)
- self._update_result_meta()
-
- return SKIP
-
-class ClassProcessor(Visitor):
- def __init__(self, parent):
- super(ClassProcessor, self).__init__()
- self.result = []
- self.parent = parent
-
- def enter_generic(self, node):
- self.result.append(self.parent.refify(node))
- return SKIP
- def enter_ObjectExpression(self, node):
- self.result.append(MemberExtractor(parent=self.parent, for_class=True).visit(node['properties']))
- return SKIP
-
-String = type(u'')
-class MemberExtractor(Visitor):
- def __init__(self, parent, for_class=False):
- super(MemberExtractor, self).__init__()
- self.result = collections.OrderedDict()
- self.parent = parent
- self.for_class = for_class
-
- def enter_Property(self, node):
- name = utils._value(node['key'])
- prop = ValueExtractor(
- self.parent,
- Declaration(id=name, comments=node.get('comments'))
- ).visit(node['value'])
-
- if isinstance(prop, jsdoc.LiteralDoc):
- prop = jsdoc.PropertyDoc(prop.to_dict())
-
- # ValueExtractor can return a Ref, maybe this should be sent as part
- # of the decl/comments?
- if name.startswith('_') and hasattr(prop, 'parsed'):
- prop.parsed['private'] = True
- self.result[name] = prop
-
- return SKIP
-
-class Hoistifier(Visitor):
- """
- Processor for variable and function declarations properly hoisting them
- to the "top" of a module such that they are available with the relevant
- value afterwards.
- """
- def __init__(self, parent):
- super(Hoistifier, self).__init__()
- self.parent = parent
-
- def enter_generic(self, node):
- return SKIP
-
- # nodes to straight recurse into, others are just skipped
- enter_BlockStatement = enter_VariableDeclaration = lambda self, node: None
-
- def enter_VariableDeclarator(self, node):
- self.parent.scope[node['id']['name']] = BASE_SCOPE['undefined']
-
- def enter_FunctionDeclaration(self, node):
- funcname = node['id']['name']
- self.parent.scope[funcname] = fn = jsdoc.parse_comments(
- node.get('comments'),
- jsdoc.FunctionDoc,
- )
- fn.parsed['sourcemodule'] = self.parent.module
- fn.parsed['name'] = funcname
- fn.parsed['guessed_params'] = [p['name'] for p in node['params']]
- return SKIP
-
-class TypedefMatcher(Visitor):
- def __init__(self, parent):
- super(TypedefMatcher, self).__init__()
- self.parent = parent
- self.result = []
-
- enter_BlockStatement = lambda self, node: None
- def enter_generic(self, node):
- # just traverse all top-level statements, check their comments, and
- # bail
- for comment in node.get('comments') or []:
- if '@typedef' in comment['value']:
- extract = '\n' + jsdoc.strip_stars('/*' + comment['value'] + '\n*/')
- parsed = pyjsdoc.parse_comment(extract, u'')
- p = jsdoc.ParamDoc(parsed['typedef'])
- parsed['name'] = p.name
- parsed['sourcemodule'] = self.parent.module
- # TODO: add p.type as superclass somehow? Builtin types not in scope :(
- self.result.append(jsdoc.ClassDoc(parsed))
-
- return SKIP
diff --git a/doc/_extensions/autojsdoc/parser/tests/README.rst b/doc/_extensions/autojsdoc/parser/tests/README.rst
deleted file mode 100644
index dd862beae66..00000000000
--- a/doc/_extensions/autojsdoc/parser/tests/README.rst
+++ /dev/null
@@ -1,6 +0,0 @@
-:orphan:
-
-These files should be run via pytest_, simply install pytest and from the top
-of the Odoo project run ``pytest doc/_extensions``.
-
-.. _pytest: https://pytest.org/
diff --git a/doc/_extensions/autojsdoc/parser/tests/support.py b/doc/_extensions/autojsdoc/parser/tests/support.py
deleted file mode 100644
index f533f98d90c..00000000000
--- a/doc/_extensions/autojsdoc/parser/tests/support.py
+++ /dev/null
@@ -1,73 +0,0 @@
-# -*- coding: utf-8 -*-
-import operator
-
-import pyjsparser
-
-from autojsdoc.parser import jsdoc, parser
-
-params = operator.attrgetter('name', 'type', 'doc')
-
-
-def parse(s, source=None):
- tree = pyjsparser.parse(s)
- mods = parser.ModuleMatcher(source).visit(tree)
- post(mods)
- return mods
-
-def post(mods):
- modules = dict(BASE_MODULES)
- modules.update((m.name, m) for m in mods)
-
- for mod in mods:
- mod.post_process(modules)
-
-BASE_MODULES = {
- 'other': jsdoc.ModuleDoc({
- 'module': 'other',
- '_members': [
- ('<exports>', jsdoc.LiteralDoc({'name': 'value', 'value': "ok"})),
- ],
- }),
- 'dep2': jsdoc.ModuleDoc({
- 'module': 'dep2',
- '_members': [
- ('<exports>', jsdoc.LiteralDoc({'value': 42.})),
- ],
- }),
- 'dep3': jsdoc.ModuleDoc({
- 'module': 'dep3',
- '_members': [
- ('<exports>', jsdoc.LiteralDoc({'value': 56.})),
- ],
- }),
- 'Class': jsdoc.ModuleDoc({
- 'module': 'Class',
- '_members': [
- ('<exports>', jsdoc.ClassDoc({
- 'name': 'Class',
- 'doc': "Base Class"
- })),
- ],
- }),
- 'mixins': jsdoc.ModuleDoc({
- 'module': 'mixins',
- '_members': [
- ('<exports>', jsdoc.NSDoc({
- 'name': 'mixins',
- '_members': [
- ('Bob', jsdoc.ClassDoc({'class': "Bob"})),
- ]
- })),
- ],
- }),
- 'Mixin': jsdoc.ModuleDoc({
- 'module': 'Mixin',
- '_members': [
- ('<exports>', jsdoc.MixinDoc({
- '_members': [
- ('a', jsdoc.FunctionDoc({'function': 'a'})),
- ]
- })),
- ],
- })
-}
diff --git a/doc/_extensions/autojsdoc/parser/tests/test_class.py b/doc/_extensions/autojsdoc/parser/tests/test_class.py
deleted file mode 100644
index 403ae9b48b7..00000000000
--- a/doc/_extensions/autojsdoc/parser/tests/test_class.py
+++ /dev/null
@@ -1,227 +0,0 @@
-# -*- coding: utf-8 -*-
-import pytest
-
-from autojsdoc.parser import jsdoc
-from support import params, parse
-
-def test_classvar():
- [mod] = parse("""
- odoo.define('a.A', function(require) {
- var Class = require('Class');
- /**
- * This is my class-kai
- */
- var A = Class.extend({});
- return A;
- });
- """)
- cls = mod.exports
- assert type(cls) == jsdoc.ClassDoc
-
- assert type(cls.superclass) == jsdoc.ClassDoc
- assert cls.superclass.name == 'Class'
-
- assert cls.name == 'A'
- assert cls.constructor is None
- assert cls.properties == []
- assert cls['doc'] == 'This is my class-kai'
-
-def test_classret():
- [mod] = parse("""
- odoo.define('a.A', function(require) {
- var Class = require('Class');
- /**
- * This is my class-kai
- */
- return Class.extend({});
- });
- """)
- cls = mod.exports
- assert type(cls) == jsdoc.ClassDoc
-
- assert cls.name == ''
- assert cls.constructor is None
- assert cls.properties == []
- assert cls['doc'] == 'This is my class-kai'
-
-def test_methods():
- [mod] = parse("""
- odoo.define('a.A', function(require) {
- var Class = require('Class');
- return Class.extend({
- /**
- * @param {Widget} parent
- */
- init: function (parent) {},
- /**
- * @returns {Widget}
- */
- itself: function () { return this; },
- /**
- * @param {MouseEvent} e
- */
- _onValidate: function (e) {},
- });
- });
- """)
- cls = mod.exports
- assert len(cls.properties) == 3
- assert cls.constructor
- # assume methods are in source order
- [_, init] = cls.properties[0]
- assert init == cls.constructor
- assert init.name == 'init'
- assert not init.is_private
- assert init.is_constructor
- [param] = init.params
- assert params(param) == ('parent', 'Widget', '')
-
- [_, itself] = cls.properties[1]
- assert itself.name == 'itself'
- assert not itself.is_private
- assert not itself.is_constructor
- assert not itself.params
- assert params(itself.return_val) == ('', 'Widget', '')
-
- [_, _on] = cls.properties[2]
- assert _on.name == '_onValidate'
- assert _on.is_private
- assert not _on.is_constructor
- [param] = _on.params
- assert params(param) == ('e', 'MouseEvent', '')
-
-def test_mixin_explicit():
- [mod] = parse("""
- odoo.define('a.A', function (require) {
- var Class = require('Class');
- var mixins = require('mixins');
- /**
- * This is my class-kai
- * @mixes mixins.Bob
- */
- return Class.extend({});
- });
- """)
- cls = mod.exports
- # FIXME: ClassDoc may want to m2r(mixin, scope)?
- assert cls.mixins == ['mixins.Bob']
-
-def test_mixin_implicit():
- [mod] = parse("""
- odoo.define('a.A', function(require) {
- var Class = require('Class');
- var Mixin = require('Mixin');
- /**
- * This is my class-kai
- */
- return Class.extend(Mixin, { foo: function() {} });
- });
- """)
- cls = mod.exports
- [mixin] = cls.mixins
- assert type(mixin) == jsdoc.MixinDoc
- assert params(mixin.properties[0][1]) == ('a', 'Function', '')
- assert params(mixin.get_property('a')) == ('a', 'Function', '')
-
- assert params(cls.get_property('foo')) == ('foo', 'Function', '')
-
-def test_instanciation():
- [A, a] = parse("""
- odoo.define('A', function (r) {
- var Class = r('Class');
- /**
- * @class A
- */
- return Class.extend({
- foo: function () {}
- });
- });
- odoo.define('a', function (r) {
- var A = r('A');
- var a = new A;
- return a;
- });
- """)
- assert type(a.exports) == jsdoc.InstanceDoc
- assert a.exports.cls.name == A.exports.name
-
-def test_non_function_properties():
- [A] = parse("""
- odoo.define('A', function (r) {
- var Class = r('Class');
- return Class.extend({
- template: 'thing',
- a_prop: [1, 2, 3],
- 'other': {a: 7}
- });
- });
- """)
- t = A.exports.get_property('template')
- assert type(t) == jsdoc.PropertyDoc
- assert params(t) == ('template', 'String', '')
- assert not t.is_private
-
-def test_non_extend_classes():
- [mod] = parse("""
- odoo.define('A', function () {
- /**
- * @class
- */
- var Class = function () {}
- return Class;
- });
- """)
- assert type(mod.exports) == jsdoc.ClassDoc
-
-def test_extend():
- [a, _] = parse("""
- odoo.define('A', function (require) {
- var Class = require('Class');
- return Class.extend({});
- });
- odoo.define('B', function (require) {
- var A = require('A');
- A.include({
- /** A property */
- a: 3,
- /** A method */
- b: function () {}
- });
- });
- """)
- cls = a.exports
- assert type(cls) == jsdoc.ClassDoc
- a = cls.get_property('a')
- assert type(a) == jsdoc.PropertyDoc
- assert params(a) == ('a', 'Number', 'A property')
- b = cls.get_property('b')
- assert type(b) == jsdoc.FunctionDoc
- assert params(b) == ('b', 'Function', 'A method')
-
-# TODO: also support virtual members?
-# TODO: computed properties?
-@pytest.mark.skip(reason="Need to implement member/var-parsing?")
-def test_members():
- [mod] = parse("""
- odoo.define('A', function (r) {
- var Class = r('Class');
- return Class.extend({
- init: function () {
- /**
- * This is bob
- * @var {Foo}
- */
- this.foo = 3;
- this.bar = 42;
- /**
- * @member {Baz}
- */
- this.baz = null;
- }
- });
- });
- """)
- cls = mod.exports
- assert params(cls.members[0]) == ('foo', 'Foo', 'This is bob')
- assert params(cls.members[1]) == ('bar', '', '')
- assert params(cls.members[2]) == ('baz', 'Baz', '')
diff --git a/doc/_extensions/autojsdoc/parser/tests/test_crap.py b/doc/_extensions/autojsdoc/parser/tests/test_crap.py
deleted file mode 100644
index 70063e6dd47..00000000000
--- a/doc/_extensions/autojsdoc/parser/tests/test_crap.py
+++ /dev/null
@@ -1,75 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-Test various crap patterns found in Odoo code to ensure they don't blow up
-the parser thingie
-"""
-from autojsdoc.parser import jsdoc
-from support import parse
-
-def test_export_external():
- [mod] = parse("""
- odoo.define('module', function () {
- return $.Deferred().reject();
- });
- """)
- assert isinstance(mod.exports, jsdoc.CommentDoc)
- assert mod.exports.doc == ''
-
-def test_extend_jq():
- parse("""
- odoo.define('a', function (r) {
- $.extend($.expr[':'], { a: function () {} });
- $.fn.extend({ a: function () {} });
- });
- """)
-
-def test_extend_dynamic():
- parse("""
- odoo.define('a', function () {
- foo.bar.baz[qux + '_external'] = function () {};
- });
- """)
-
-def test_extend_deep():
- parse("""
- odoo.define('a', function () {
- var eventHandler = $.summernote.eventHandler;
- var dom = $.summernote.core.dom;
- dom.thing = function () {};
-
- var fn_editor_currentstyle = eventHandler.modules.editor.currentStyle;
- eventHandler.modules.editor.currentStyle = function () {}
- });
- """)
-
-def test_arbitrary():
- parse("""
- odoo.define('bob', function () {
- var page = window.location.href.replace(/^.*\/\/[^\/]+/, '');
- var mailWidgets = ['mail_followers', 'mail_thread', 'mail_activity', 'kanban_activity'];
- var bob;
- var fldj = foo.getTemplate().baz;
- });
- """)
-
-def test_prototype():
- [A, B] = parse("""
- odoo.define('mod1', function () {
- var exports = {};
- exports.Foo = Backbone.Model.extend({});
- exports.Bar = Backbone.Model.extend({});
- var BarCollection = Backbone.Collection.extend({
- model: exports.Bar,
- });
- exports.Baz = Backbone.Model.extend({});
- return exports;
- });
- odoo.define('mod2', function (require) {
- var models = require('mod1');
- var _super_orderline = models.Bar.prototype;
- models.Foo = models.Bar.extend({});
- var _super_order = models.Baz.prototype;
- models.Bar = models.Baz.extend({});
- });
- """)
-
diff --git a/doc/_extensions/autojsdoc/parser/tests/test_module.py b/doc/_extensions/autojsdoc/parser/tests/test_module.py
deleted file mode 100644
index 2a63cc1754c..00000000000
--- a/doc/_extensions/autojsdoc/parser/tests/test_module.py
+++ /dev/null
@@ -1,173 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from autojsdoc.parser import jsdoc
-from support import params, parse, BASE_MODULES
-
-
-def test_single():
- [mod] = parse("""
- /**
- * This is a super module!
- */
- odoo.define('supermodule', function (req) {
- var other = req('other');
- });
- """)
- assert mod.name == 'supermodule'
- assert mod.dependencies == {'other'}
- assert mod.exports is None
- assert mod.doc == "This is a super module!"
- m = mod.get_property('other')
- assert m.name == 'value', "property is exported value not imported module"
-
-def test_multiple():
- [mod1, mod2, mod3] = parse("""
- odoo.define('module1', function (req) {
- return 1;
- });
- odoo.define('module2', function (req) {
- return req('dep2');
- });
- odoo.define('module3', function (req) {
- var r = req('dep3');
- return r;
- });
- """)
- assert mod1.name == 'module1'
- assert mod1.dependencies == set()
- assert isinstance(mod1.exports, jsdoc.LiteralDoc)
- assert mod1.exports.value == 1.0
- assert mod1.exports['sourcemodule'] is mod1
- assert mod1.doc == ""
-
- assert mod2.name == 'module2'
- assert mod2.dependencies == {'dep2'}
- assert isinstance(mod2.exports, jsdoc.LiteralDoc)
- assert mod2.exports.value == 42.0
- assert mod2.doc == ""
-
- assert mod3.name == 'module3'
- assert mod3.dependencies == {'dep3'}
- assert isinstance(mod3.exports, jsdoc.LiteralDoc)
- assert mod3.exports.value == 56.0
- assert mod3.doc == ''
-
-def test_func():
- [mod] = parse("""
- odoo.define('module', function (d) {
- /**
- * @param {Foo} bar this is a bar
- * @param {Baz} qux this is a qux
- */
- return function (bar, qux) {
- return 42;
- }
- });
- """)
- exports = mod.exports
- assert type(exports) == jsdoc.FunctionDoc
- assert exports['sourcemodule'] is mod
-
- assert exports.name == ''
- assert exports.is_constructor == False
- assert exports.is_private == False
-
- assert params(exports.params[0]) == ('bar', 'Foo', 'this is a bar')
- assert params(exports.params[1]) == ('qux', 'Baz', 'this is a qux')
- assert params(exports.return_val) == ('', '', '')
-
-def test_hoist():
- [mod] = parse("""
- odoo.define('module', function() {
- return foo;
- /**
- * @param a_thing
- */
- function foo(a_thing) {
- return 42;
- }
- });
- """)
- actual = mod.exports
- assert type(actual) == jsdoc.FunctionDoc
- [param] = actual.params
- assert params(param) == ('a_thing', '', '')
-
-def test_export_instance():
- [mod] = parse("""
- odoo.define('module', function (require) {
- var Class = require('Class');
- /**
- * Provides an instance of Class
- */
- return new Class();
- });
- """)
- assert type(mod.exports) == jsdoc.InstanceDoc
- assert mod.exports.doc == 'Provides an instance of Class'
- assert mod.exports['sourcemodule'] is mod
-
-def test_bounce():
- [m2, m1] = parse("""
- odoo.define('m2', function (require) {
- var Item = require('m1');
- return {
- Item: Item
- };
- });
- odoo.define('m1', function (require) {
- var Class = require('Class');
- var Item = Class.extend({});
- return Item;
- });
- """)
- assert type(m2.exports) == jsdoc.NSDoc
- it = m2.exports.get_property('Item')
- assert type(it) == jsdoc.ClassDoc
- assert it['sourcemodule'] is m1
- assert sorted([n for n, _ in m1.properties]) == ['<exports>', 'Class', 'Item']
-
-def test_reassign():
- [m] = parse("""
- odoo.define('m', function (require) {
- var Class = require('Class');
- /** local class */
- var Class = Class.extend({});
- return Class
- });
- """)
- assert m.exports.doc == 'local class'
- # can't use equality or identity so use class comment...
- assert m.exports.superclass.doc == 'Base Class'
-
-def test_attr():
- [m1, m2] = parse("""
- odoo.define('m1', function (require) {
- var Class = require('Class');
- var Item = Class.extend({});
- return {Item: Item};
- });
- odoo.define('m2', function (require) {
- var Item = require('m1').Item;
- Item.include({});
- return Item.extend({});
- });
- """)
- assert type(m2.exports) == jsdoc.ClassDoc
- # that these two are resolved separately may be an issue at one point (?)
- assert m2.exports.superclass.to_dict() == m1.exports.get_property('Item').to_dict()
-
-def test_nothing_implicit():
- [m] = parse("""
- odoo.define('m', function () {
- });
- """)
- assert m.exports is None
-
-def test_nothing_explicit():
- [m] = parse("""
- odoo.define('m', function () {
- return;
- });
- """)
- assert m.exports is None
diff --git a/doc/_extensions/autojsdoc/parser/tests/test_namespace.py b/doc/_extensions/autojsdoc/parser/tests/test_namespace.py
deleted file mode 100644
index 54cbcf8cbb4..00000000000
--- a/doc/_extensions/autojsdoc/parser/tests/test_namespace.py
+++ /dev/null
@@ -1,177 +0,0 @@
-# -*- coding: utf-8 -*-
-from autojsdoc.parser import jsdoc
-from support import parse, params
-
-
-def test_empty():
- [mod] = parse("""
- odoo.define('a.ns', function (r) {
- return {};
- });
- """)
- assert type(mod.exports) == jsdoc.NSDoc
- assert mod.exports.properties == []
-
-def test_inline():
- [mod] = parse("""
- odoo.define('a.ns', function (r) {
- return {
- /**
- * a thing
- * @type {Boolean}
- */
- a: true
- }
- });
- """)
- assert isinstance(mod.exports, jsdoc.NSDoc)
- [(n, p)] = mod.exports.properties
- assert n == 'a'
- assert params(p) == ('a', 'Boolean', 'a thing')
-
-def test_header():
- [mod] = parse("""
- odoo.define('a.ns', function (r) {
- /**
- * @property {Boolean} a a thing
- */
- return { a: true }
- });
- """)
- assert isinstance(mod.exports, jsdoc.NSDoc)
- [(_, p)] = mod.exports.properties
- assert params(p) == ('a', 'Boolean', 'a thing')
-
-def test_header_conflict():
- """ should the header or the inline comment take precedence? """
- [mod] = parse("""
- odoo.define('a.ns', function (r) {
- /**
- * @property {Boolean} a a thing
- */
- return {
- /** @type {String} */
- a: true
- }
- });
- """)
- assert isinstance(mod.exports, jsdoc.NSDoc)
- [(_, p)] = mod.exports.properties
- assert params(p) == ('a', 'Boolean', 'a thing')
-
-def test_mixin():
- [mod] = parse("""
- odoo.define('a.mixin', function (r) {
- /**
- * @mixin
- */
- return {
- /**
- * @returns {Number} a number
- */
- do_thing: function other() { return 42; }
- }
- });
- """)
- assert isinstance(mod.exports, jsdoc.MixinDoc)
- [(n, p)] = mod.exports.properties
- assert n == 'do_thing'
- assert params(p) == ('other', 'Function', '')
- assert params(p.return_val) == ('', 'Number', 'a number')
-
-def test_literal():
- [mod] = parse("""
- odoo.define('a.ns', function (r) {
- /** whop whop */
- return {
- 'a': 1,
- /** wheee */
- 'b': 2,
- };
- });
- """)
- assert mod.exports.doc == 'whop whop'
- [(_1, a), (_2, b)] = mod.exports.properties
- assert params(a) == ('a', 'Number', '')
- assert params(b) == ('b', 'Number', 'wheee')
-
-def test_fill_ns():
- [mod] = parse("""
- odoo.define('a.ns', function (r) {
- var Class = r('Class');
- var ns = {};
- /** ok */
- ns.a = 1;
- /** @type {String} */
- ns['b'] = 2;
- /** Ike */
- ns.c = Class.extend({});
- ns.d = function () {}
- return ns;
- });
- """)
- ns = mod.exports
- assert type(ns) == jsdoc.NSDoc
- [(_a, a), (_b, b), (_c, c), (_d, d)] = ns.properties
- assert params(a) == ('a', 'Number', 'ok')
- assert params(b) == ('b', 'String', '')
- assert type(c) == jsdoc.ClassDoc
- assert type(d) == jsdoc.FunctionDoc
-
-def test_extend_other():
- [o, b] = parse("""
- odoo.define('a.ns', function () {
- /** @name outer */
- return {
- /** @name inner */
- a: {}
- };
- });
- odoo.define('b', function (r) {
- var o = r('a.ns');
- var Class = r('Class');
- /** Class 1 */
- o.a.b = Class.extend({m_b: 1});
- /** Class 2 */
- o.a['c'] = Class.extend({m_c: 1});
- });
- """)
- [(_, m)] = o.exports.properties
- assert type(m) == jsdoc.NSDoc
-
- b = m.get_property('b')
- assert type(b) == jsdoc.ClassDoc
- assert b.get_property('m_b')
- assert b.doc == 'Class 1'
-
- c = m.get_property('c')
- assert type(c) == jsdoc.ClassDoc
- assert c.get_property('m_c')
- assert c.doc == 'Class 2'
-
-def test_ns_variables():
- [mod] = parse("""
- odoo.define('A', function (r) {
- var Class = r('Class');
- var Thing = Class.extend({});
- return {
- Thing: Thing
- };
- });
- """)
- p = mod.exports.get_property('Thing')
- assert type(p) == jsdoc.ClassDoc
-
-def test_diff():
- """ Have the NS key and the underlying object differ
- """
- [mod] = parse("""
- odoo.define('mod', function (r) {
- var Class = r('Class');
- var Foo = Class.extend({});
- return { Class: Foo };
- });
- """)
- c = mod.exports.get_property('Class')
- assert type(c) == jsdoc.ClassDoc
- assert c.name == 'Foo'
diff --git a/doc/_extensions/autojsdoc/parser/tests/test_params.py b/doc/_extensions/autojsdoc/parser/tests/test_params.py
deleted file mode 100644
index c51139b8cb3..00000000000
--- a/doc/_extensions/autojsdoc/parser/tests/test_params.py
+++ /dev/null
@@ -1,116 +0,0 @@
-# -*- coding: utf-8 -*-
-from autojsdoc.parser.jsdoc import ParamDoc
-
-"Lorem ipsum dolor sit amet, consectetur adipiscing elit."
-
-def test_basic():
- d = ParamDoc("Lorem ipsum dolor sit amet, consectetur adipiscing elit.").to_dict()
- assert d == {
- 'name': 'Lorem',
- 'type': '',
- 'optional': False,
- 'default': None,
- 'doc': 'ipsum dolor sit amet, consectetur adipiscing elit.',
- }
-
- d = ParamDoc("{Lorem} ipsum dolor sit amet, consectetur adipiscing elit.").to_dict()
- assert d == {
- 'name': 'ipsum',
- 'type': 'Lorem',
- 'optional': False,
- 'default': None,
- 'doc': 'dolor sit amet, consectetur adipiscing elit.',
- }
-
-def test_optional():
- d = ParamDoc("[Lorem] ipsum dolor sit amet, consectetur adipiscing elit.").to_dict()
- assert d == {
- 'name': 'Lorem',
- 'type': '',
- 'optional': True,
- 'default': None,
- 'doc': 'ipsum dolor sit amet, consectetur adipiscing elit.',
- }
-
- d = ParamDoc("[Lorem=42] ipsum dolor sit amet, consectetur adipiscing elit.").to_dict()
- assert d == {
- 'name': 'Lorem',
- 'type': '',
- 'optional': True,
- 'default': "42",
- 'doc': 'ipsum dolor sit amet, consectetur adipiscing elit.',
- }
-
- d = ParamDoc("{Lorem} [ipsum] dolor sit amet, consectetur adipiscing elit.").to_dict()
- assert d == {
- 'name': 'ipsum',
- 'type': 'Lorem',
- 'optional': True,
- 'default': None,
- 'doc': 'dolor sit amet, consectetur adipiscing elit.',
- }
-
- d = ParamDoc("{Lorem} [ipsum=42] dolor sit amet, consectetur adipiscing elit.").to_dict()
- assert d == {
- 'name': 'ipsum',
- 'type': 'Lorem',
- 'optional': True,
- 'default': '42',
- 'doc': 'dolor sit amet, consectetur adipiscing elit.',
- }
-
-def test_returns():
- d = ParamDoc("{} ipsum dolor sit amet, consectetur adipiscing elit.").to_dict()
- assert d == {
- 'name': '',
- 'type': '',
- 'optional': False,
- 'default': None,
- 'doc': 'ipsum dolor sit amet, consectetur adipiscing elit.',
- }
- d = ParamDoc("{Lorem} ipsum dolor sit amet, consectetur adipiscing elit.").to_dict()
- assert d == {
- 'name': '',
- 'type': 'Lorem',
- 'optional': False,
- 'default': None,
- 'doc': 'ipsum dolor sit amet, consectetur adipiscing elit.',
- }
-
-def test_odd():
- d = ParamDoc("{jQuery} [$target] the node where content will be prepended").to_dict()
- assert d == {
- 'name': '$target',
- 'type': 'jQuery',
- 'optional': True,
- 'default': None,
- 'doc': 'the node where content will be prepended',
- }
-
- d = ParamDoc("""{htmlString} [content] DOM element,
- array of elements, HTML string or jQuery object to prepend to $target""").to_dict()
- assert d == {
- 'name': 'content',
- 'type': 'htmlString',
- 'optional': True,
- 'default': None,
- 'doc': "DOM element,\n array of elements, HTML string or jQuery object to prepend to $target",
- }
-
- d = ParamDoc("{Boolean} [options.in_DOM] true if $target is in the DOM").to_dict()
- assert d == {
- 'name': 'options.in_DOM',
- 'type': 'Boolean',
- 'optional': True,
- 'default': None,
- 'doc': 'true if $target is in the DOM',
- }
-
- d = ParamDoc("Lorem\n ipsum dolor sit amet, consectetur adipiscing elit.").to_dict()
- assert d['doc'] == 'ipsum dolor sit amet, consectetur adipiscing elit.'
-
- d = ParamDoc("Lorem - ipsum dolor sit amet, consectetur adipiscing elit.").to_dict()
- assert d['doc'] == 'ipsum dolor sit amet, consectetur adipiscing elit.'
-
- d = ParamDoc("Lorem : ipsum dolor sit amet, consectetur adipiscing elit.").to_dict()
- assert d['doc'] == 'ipsum dolor sit amet, consectetur adipiscing elit.'
diff --git a/doc/_extensions/autojsdoc/parser/tests/test_typespec.py b/doc/_extensions/autojsdoc/parser/tests/test_typespec.py
deleted file mode 100644
index b2a5a5258b2..00000000000
--- a/doc/_extensions/autojsdoc/parser/tests/test_typespec.py
+++ /dev/null
@@ -1,104 +0,0 @@
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
-import pytest
-
-from autojsdoc.parser import types
-
-def test_parser():
- assert types.parse("MouseEvent|TouchEvent") == types.Alt([
- types.Type('MouseEvent', []),
- types.Type('TouchEvent', []),
- ])
-
- assert types.parse('Deferred<Object>') == types.Alt([
- types.Type('Deferred', [
- types.Alt([types.Type('Object', [])])
- ])
- ])
-
- assert types.parse('Object|undefined') == types.Alt([
- types.Type('Object', []),
- types.Literal('undefined'),
- ])
- assert types.parse('any[]') == types.Alt([
- types.Type('Array', [types.Type('any', [])])
- ])
- assert types.parse("'xml' | 'less'") == types.Alt([
- types.Literal('xml'),
- types.Literal('less'),
- ])
- assert types.parse('Foo<Bar | Bar[] | null>') == types.Alt([
- types.Type('Foo', [types.Alt([
- types.Type('Bar', []),
- types.Type('Array', [types.Type('Bar', [])]),
- types.Literal('null'),
- ])])
- ])
- assert types.parse('Function<Array<Object[]>>') == types.Alt([
- types.Type('Function', [types.Alt([
- types.Type('Array', [types.Alt([
- types.Type('Array', [
- types.Type('Object', [])
- ])
- ])])
- ])])
- ])
-
-
-def test_tokens():
- toks = list(types.tokenize('A'))
- assert toks == [(types.NAME, 'A')]
-
- toks = list(types.tokenize('"foo" | "bar"'))
- assert toks == [(types.LITERAL, 'foo'), (types.OP, '|'), (types.LITERAL, 'bar')]
-
- toks = list(types.tokenize('1 or 2'))
- assert toks == [(types.LITERAL, 1), (types.OP, '|'), (types.LITERAL, 2)]
-
- toks = list(types.tokenize('a.b.c.d'))
- assert toks == [
- (types.NAME, 'a'), (types.OP, '.'),
- (types.NAME, 'b'), (types.OP, '.'),
- (types.NAME, 'c'), (types.OP, '.'),
- (types.NAME, 'd'),
- ]
-
- toks = list(types.tokenize('Function<String, Object>'))
- assert toks == [
- (types.NAME, 'Function'),
- (types.OP, '<'),
- (types.NAME, 'String'),
- (types.OP, ','),
- (types.NAME, 'Object'),
- (types.OP, '>')
- ]
-
- toks = list(types.tokenize('Function<Array<Object[]>>'))
- assert toks == [
- (types.NAME, 'Function'),
- (types.OP, '<'),
- (types.NAME, 'Array'),
- (types.OP, '<'),
- (types.NAME, 'Object'),
- (types.OP, '['),
- (types.OP, ']'),
- (types.OP, '>'),
- (types.OP, '>')
- ]
-
-def test_peekable():
- p = types.Peekable(range(5))
-
- assert p.peek() == 0
- assert next(p) == 0, "consuming should yield previously peeked value"
- next(p)
- next(p)
- assert next(p) == 3
- assert p.peek() == 4
- next(p)
- assert p.peek(None) is None
- with pytest.raises(StopIteration):
- p.peek()
- with pytest.raises(StopIteration):
- next(p)
diff --git a/doc/_extensions/autojsdoc/parser/types.py b/doc/_extensions/autojsdoc/parser/types.py
deleted file mode 100644
index 69836f46ac4..00000000000
--- a/doc/_extensions/autojsdoc/parser/types.py
+++ /dev/null
@@ -1,196 +0,0 @@
-# -*- coding: utf-8 -*-
-import ast
-import collections
-import io
-import token
-from tokenize import generate_tokens
-
-LITERAL_NAME = ('null', 'undefined', 'true', 'false')
-
-__all__ = ['tokenize', 'parse', 'iterate', 'Alt', 'Type', 'Literal']
-
-class _Marker(object):
- __slots__ = ['name']
- def __init__(self, name): self.name = name
- def __repr__(self): return '<%s>' % self.name
-
-OP = _Marker('OP')
-NAME = _Marker('NAME')
-LITERAL = _Marker('LITERAL')
-def tokenize(typespec):
- typespec = typespec.replace('$', 'jQuery')
- for toktype, string, _, _, _ in generate_tokens(io.StringIO(typespec).readline):
- if toktype == token.NAME:
- if string == 'or': # special case "A or B"
- # TODO: deprecation warning
- yield (OP, '|')
- else:
- yield (NAME, string)
- elif toktype == token.OP:
- if string in '|<>[].,':
- yield (OP, string)
- elif string == '>>':
- yield (OP, '>')
- yield (OP, '>')
- elif string == '*': # maybe?
- yield (NAME, 'any')
- elif string in '()':
- # TODO: deprecation warning
- # seems useless unless we add support for "..."
- continue
- else:
- raise ValueError("Unknown typespec operator %r" % string)
- elif toktype in (token.STRING, token.NUMBER): # enum-ish
- yield (LITERAL, ast.literal_eval(string))
- elif toktype == token.ENDMARKER:
- return
- elif toktype == token.NEWLINE:
- pass
- else:
- raise ValueError("Unknown typespec token %s" % token.tok_name[toktype])
-
-Alt = collections.namedtuple('Alt', ['params'])
-Literal = collections.namedtuple('Literal', ['value'])
-Type = collections.namedtuple('Type', ['name', 'params'])
-
-def iterate(t, fortype, forliteral):
- if isinstance(t, Alt):
- ps = Peekable(t.params)
- for param in ps:
- for it in iterate(param, fortype, forliteral):
- yield it
- if ps.peek(None):
- yield forliteral('|')
- elif isinstance(t, Type):
- yield fortype(t.name)
- if not t.params:
- return
- yield forliteral('<')
- ps = Peekable(t.params)
- for param in ps:
- for it in iterate(param, fortype, forliteral):
- yield it
- if ps.peek(None):
- yield forliteral(',')
- yield forliteral('>')
- elif isinstance(t, Literal):
- yield forliteral(t.value)
- else:
- raise ValueError('Unknown item %s' % t)
-
-def parse(typespec):
- tokens = Peekable(tokenize(typespec))
- return parse_alt(tokens)
-
-# alt = param
-# | param '|' alt
-def parse_alt(tokens):
- alt = Alt([])
- while True:
- alt.params.append(parse_param(tokens))
- if not next_is(tokens, (OP, '|')):
- break
- return alt
-
-# param = 'null' | 'undefined' | 'true' | 'false'
-# | number
-# | string
-# | typename '[]'
-# X '[' alt ']'
-# | typename '<' params '>'
-# params = alt | alt ',' params
-def parse_param(tokens):
- t, v = tokens.peek()
- if t == LITERAL or (t == NAME and v in LITERAL_NAME):
- next(tokens)
- return Literal(str(v))
-
- # # [typespec] # should this be Array<T> or an n-uple allowing multiple items?
- # if tok == (OP, '['):
- # next(tokens)
- # t = Type('Array', [parse_alt(tokens)])
- # rest = next(tokens)
- # expect(rest, (OP, ']'))
- # return t
-
- t = Type(parse_typename(tokens), [])
- # type[]
- peek = tokens.peek(None)
- if peek == (OP, '['):
- next(tokens) # skip peeked
- expect(next(tokens), (OP, ']'))
- return Type('Array', [t])
- # type<typespec, ...>
- if peek == (OP, '<'):
- next(tokens) # skip peeked
- while True:
- t.params.append(parse_alt(tokens))
- n = next(tokens)
- if n == (OP, ','):
- continue
- if n == (OP, '>'):
- break
- raise ValueError("Expected OP ',' or OP ',', got %s '%s'" % n)
- return t
-
-# typename = name | name '.' typename
-def parse_typename(tokens):
- typename = []
- while True:
- (t, n) = next(tokens)
- if t != NAME:
- raise ValueError("Expected a name token, got %s '%s'" % (t, n))
- if n in LITERAL_NAME:
- raise ValueError("Expected a type name, got literal %s" % n)
- typename.append(n)
- if not next_is(tokens, (OP, '.')):
- break
- return '.'.join(typename)
-
-def next_is(tokens, expected):
- """
- Consumes the next token if it's `expected` otherwise does not touch the
- tokens.
-
- Returns whether it consumed a token
- """
- if tokens.peek(None) == expected:
- next(tokens)
- return True
- return False
-
-def expect(actual, expected):
- """ Raises ValueError if `actual` and `expected` are different
-
- :type actual: (object, str)
- :type expected: (object, str)
- """
- if actual != expected:
- raise ValueError("Expected %s '%s', got %s '%s'" % (expected + actual))
-
-
-NONE = object()
-class Peekable(object):
- __slots__ = ['_head', '_it']
- def __init__(self, iterable):
- self._head = NONE
- self._it = iter(iterable)
-
- def __iter__(self):
- return self
- def __next__(self):
- if self._head is not NONE:
- r, self._head = self._head, NONE
- return r
- return next(self._it)
- next = __next__
-
- def peek(self, default=NONE):
- if self._head is NONE:
- try:
- self._head = next(self._it)
- except StopIteration:
- if default is not NONE:
- return default
- raise
- return self._head
diff --git a/doc/_extensions/autojsdoc/parser/utils.py b/doc/_extensions/autojsdoc/parser/utils.py
deleted file mode 100644
index 213327f6c0e..00000000000
--- a/doc/_extensions/autojsdoc/parser/utils.py
+++ /dev/null
@@ -1,295 +0,0 @@
-# -*- coding: utf-8 -*-
-def _name(node):
- if node['type'] == 'Identifier':
- return node['name']
- if node['type'] == 'MemberExpression':
- return "%s.%s" % (_name(node['object']), _name(node['property']))
- raise ValueError("Unnamable node type %s" % node['type'])
-
-def _value(node, strict=False):
- t = node['type']
- if t == 'Identifier':
- return node['name']
- elif t == 'Literal':
- return node['value']
- msg = '<%s has no value>' % _identify(node, {})
- if strict:
- raise ValueError(msg)
- return msg
-
-def _identify(valnode, ns):
- if valnode is None:
- return "None"
- # already identified and re-set in the ns?
- if isinstance(valnode, Printable):
- return valnode
-
- # check other non-empty returns
- t = valnode['type']
- if t == "Literal":
- if valnode.get('regex'):
- return valnode['regex']['pattern']
- return valnode['value']
- elif t == "Identifier":
- n = valnode['name']
- return ns.get(n, Global(n))
- elif t == "NewExpression":
- return Instance(_identify(valnode['callee'], ns))
- elif t == "ObjectExpression":
- return Namespace({
- _value(prop['key']): _identify(prop['value'], ns)
- for prop in valnode['properties']
- })
- elif t == "MemberExpression":
- return Deref(
- _identify(valnode['object'], ns),
- _identify(valnode['property'], ns) if valnode['computed'] else valnode['property']['name'],
- )
- elif t == "CallExpression":
- return Call(
- _identify(valnode['callee'], ns),
- [_identify(arg, ns) for arg in valnode['arguments']],
- )
- elif t == 'BinaryExpression':
- return "%s %s %s" % (
- _identify(valnode['left'], ns),
- valnode['operator'],
- _identify(valnode['right'], ns),
- )
- else:
- return t
-
-class Counter(object):
- __slots__ = ['_number']
- def __init__(self):
- self._number = 0
-
- def __bool__(self):
- return bool(self._number)
- __nonzero__ = __bool__
- def __int__(self):
- return self._number
-
- def get(self):
- return self._number
- def increment(self):
- self._number += 1
- return self._number
- def decrement(self):
- self._number -= 1
- return self._number
-
- def __enter__(self):
- self._number += 1
- return self._number
- def __exit__(self, *args):
- self._number -= 1
-
-class Printable(object):
- __slots__ = []
- depth = Counter()
- def __repr__(self):
- with self.depth as i:
- if i > 2:
- return "%s(...)" % type(self).__name__
- return "%s(%s)" % (type(self).__name__, ', '.join(
- "%s=%r" % (k, getattr(self, k))
- for k in self.__slots__
- if not k.startswith('_')
- if getattr(self, k)
- ))
-
-
-def resolve(obj, store):
- if obj is None:
- return None
-
- if isinstance(obj, (type(u''), bool, int, float)):
- return obj
-
- if isinstance(obj, ModuleProxy):
- return resolve(obj.get(), store)
-
- try:
- if getattr(obj, 'resolved', False):
- return obj
- return obj.resolve(store)
- except AttributeError:
- raise TypeError("Unresolvable {!r}".format(obj))
-
-class Resolvable(Printable):
- """
- For types resolved in place
- """
- __slots__ = ['resolved']
-
- def __init__(self):
- super(Resolvable, self).__init__()
- self.resolved = False
- def resolve(self, store):
- self.resolved = True
- return self
-
-class Namespace(Resolvable):
- __slots__ = ['attrs']
- def __init__(self, attrs):
- super(Namespace, self).__init__()
- self.attrs = attrs
- def resolve(self, store):
- r = super(Namespace, self).resolve(store)
- self.attrs = {
- k: resolve(v, store)
- for k, v in self.attrs.items()
- }
- return r
- def __getitem__(self, key):
- assert isinstance(key, type(u'')), "%r is not a namespace key" % key
- try:
- return self.attrs[key]
- except KeyError:
- return Global(self)[key]
-
-class Module(Resolvable):
- __slots__ = ('name', 'comments', 'exports', 'augments', 'dependencies', '_store')
- def __init__(self, name, store, comments=()):
- super(Module, self).__init__()
- self.name = name
- self._store = store
- self.comments = tuple(comments)
- self.exports = None
- self.augments = []
- self.dependencies = set()
- store[name] = self
- def add_dependency(self, depname):
- dep = ModuleProxy(depname, self._store)
- self.dependencies.add(dep)
- return dep
- def get(self):
- return self
- def resolve(self, store=None):
- r = super(Module, self).resolve(store)
- self.exports = resolve(self.exports, self._store)
- self.augments = [resolve(a, self._store) for a in self.augments]
- self.dependencies = {
- resolve(d, self._store)
- for d in self.dependencies
- }
- return r
- def __getitem__(self, k):
- try:
- return self.exports[k]
- except KeyError:
- return Global(self)[k]
-
-class ModuleProxy(object):
- def __init__(self, name, store):
- self.name = name
- self.store = store
- def get(self):
- # web.web_client is not an actual module
- return self.store.get(self.name, '<unstored %s>' % self.name)
- def __repr__(self):
- return repr(self.get())
- def __hash__(self):
- return hash(self.name)
- def __eq__(self, other):
- return self.name == other.name
-
-class Class(Resolvable):
- __slots__ = ['name', 'members', 'extends', 'mixins', 'comments']
- def __init__(self, name, extends):
- super(Class, self).__init__()
- self.name = name
- self.extends = extends
- self.members = {}
- self.mixins = []
- self.comments = []
-
- def resolve(self, store):
- r = super(Class, self).resolve(store)
- self.extends = resolve(self.extends, store)
- self.mixins = [resolve(m, store) for m in self.mixins]
- return r
-
-class Instance(Resolvable):
- __slots__ = ['type']
- def __init__(self, type):
- super(Instance, self).__init__()
- self.type = type
-
- def resolve(self, store):
- r = super(Instance, self).resolve(store)
- self.type = resolve(self.type, store)
- if isinstance(self.type, Module):
- self.type = self.type.exports
- return r
-
- def __getitem__(self, key):
- return Global(self)['key']
-
-class Function(Resolvable):
- __slots__ = ['comments']
- def __init__(self, comments):
- super(Function, self).__init__()
- self.comments = comments
-
-class Deref(Printable):
- __slots__ = ['object', 'property']
- def __init__(self, object, property):
- self.object = object
- self.property = property
- def resolve(self, store):
- return resolve(self.object, store)[self.property]
-
-class Call(Resolvable):
- __slots__ = ['callable']
- def __init__(self, callable, arguments):
- super(Call, self).__init__()
- self.callable = callable
- def resolve(self, store):
- r = super(Call, self).resolve(store)
- self.callable = resolve(self.callable, store)
- return r
- def __getitem__(self, item):
- return Global(self)[item]
-
-def get(node, it, *path):
- if not path:
- return node[it]
- return get(node[it], *path)
-
-
-def match(node, pattern):
- """Checks that ``pattern`` is a subset of ``node``.
-
- If a sub-pattern is a callable it will be called with the current
- sub-node and its result is the match's. Other sub-patterns are
- checked by equality against the correspoding sub-node.
-
- Can be used to quickly check the descendants of a node of suitable
- type.
-
- TODO: support checking list content? Would be convenient to
- constraint e.g. CallExpression based on their parameters
-
- """
- if node is None and pattern is not None:
- return
- if callable(pattern):
- return pattern(node)
- if isinstance(node, list):
- return all(len(node) > i and match(node[i], v) for i, v in pattern.items())
- if isinstance(pattern, dict):
- return all(match(node.get(k), v) for k, v in pattern.items())
- return node == pattern
-
-
-class Global(object):
- def __init__(self, name):
- self.name = name
- def __repr__(self):
- return '<external %s>' % self.name
- def __getitem__(self, name):
- return Global('%s.%s' % (self.name, name))
- def resolve(self, store):
- return self
diff --git a/doc/_extensions/autojsdoc/parser/visitor.py b/doc/_extensions/autojsdoc/parser/visitor.py
deleted file mode 100644
index e5529d511dc..00000000000
--- a/doc/_extensions/autojsdoc/parser/visitor.py
+++ /dev/null
@@ -1,126 +0,0 @@
-from pyjsparser.pyjsparserdata import Syntax
-
-_binary = lambda n: [n['left'], n['right']]
-_function = lambda n: n['params'] + n['defaults'] + [n['body']]
-# yields children in visitation order
-_children = {
- Syntax.ArrayExpression: lambda n: n['elements'],
- Syntax.ArrayPattern: lambda n: n['elements'],
- Syntax.ArrowFunctionExpression: _function,
- Syntax.AssignmentExpression: _binary,
- Syntax.AssignmentPattern: _binary,
- Syntax.BinaryExpression: _binary,
- Syntax.BlockStatement: lambda n: n['body'],
- Syntax.BreakStatement: lambda n: [],
- Syntax.CallExpression: lambda n: [n['callee']] + n['arguments'],
- Syntax.CatchClause: lambda n: [n['param'], n['body']],
- Syntax.ClassBody: lambda n: [n['body']],
- Syntax.ClassDeclaration: lambda n: [n['superClass'], n['body']],
- Syntax.ClassExpression: lambda n: [n['superClass'], n['body']],
- Syntax.ConditionalExpression: lambda n: [n['test'], n['consequent'], n['alternate']],
- Syntax.ContinueStatement: lambda n: [],
- Syntax.DebuggerStatement: lambda n: [],
- Syntax.DoWhileStatement: lambda n: [n['body'], n['test']],
- Syntax.EmptyStatement: lambda n: [],
- Syntax.ExportAllDeclaration: lambda n: [n['source']],
- Syntax.ExportDefaultDeclaration: lambda n: [n['declaration']],
- Syntax.ExportNamedDeclaration: lambda n: ([n['declaration']] if n['declaration'] else n['specifiers']) + [n['source']],
- Syntax.ExportSpecifier: lambda n: [n['local'], n['exported']],
- Syntax.ExpressionStatement: lambda n: [n['expression']],
- Syntax.ForStatement: lambda n: [n['init'], n['test'], n['update'], n['body']],
- Syntax.ForInStatement: lambda n: [n['left'], n['right'], n['body']],
- Syntax.FunctionDeclaration: _function,
- Syntax.FunctionExpression: _function,
- Syntax.Identifier: lambda n: [],
- Syntax.IfStatement: lambda n: [n['test'], n['consequent'], n['alternate']],
- Syntax.ImportDeclaration: lambda n: n['specifiers'] + [n['source']],
- Syntax.ImportDefaultSpecifier: lambda n: [n['local']],
- Syntax.ImportNamespaceSpecifier: lambda n: [n['local']],
- Syntax.ImportSpecifier: lambda n: [n['local'], n['imported']],
- Syntax.LabeledStatement: lambda n: [n['body']],
- Syntax.Literal: lambda n: [],
- Syntax.LogicalExpression: _binary,
- Syntax.MemberExpression: lambda n: [n['object'], n['property']],
- #Syntax.MethodDefinition: lambda n: [],
- Syntax.NewExpression: lambda n: [n['callee']] + n['arguments'],
- Syntax.ObjectExpression: lambda n: n['properties'],
- Syntax.ObjectPattern: lambda n: n['properties'],
- Syntax.Program: lambda n: n['body'],
- Syntax.Property: lambda n: [n['key'], n['value']],
- Syntax.RestElement: lambda n: [n['argument']],
- Syntax.ReturnStatement: lambda n: [n['argument']],
- Syntax.SequenceExpression: lambda n: n['expressions'],
- Syntax.SpreadElement: lambda n: [n['argument']],
- Syntax.Super: lambda n: [],
- Syntax.SwitchCase: lambda n: [n['test'], n['consequent']],
- Syntax.SwitchStatement: lambda n: [n['discriminant']] + n['cases'],
- Syntax.TaggedTemplateExpression: lambda n: [n['tag'], n['quasi']],
- Syntax.TemplateElement: lambda n: [],
- Syntax.TemplateLiteral: lambda n: n['quasis'] + n['expressions'],
- Syntax.ThisExpression: lambda n: [],
- Syntax.ThrowStatement: lambda n: [n['argument']],
- Syntax.TryStatement: lambda n: [n['block'], n['handler'], n['finalizer']],
- Syntax.UnaryExpression: lambda n: [n['argument']],
- Syntax.UpdateExpression: lambda n: [n['argument']],
- Syntax.VariableDeclaration: lambda n: n['declarations'],
- Syntax.VariableDeclarator: lambda n: [n['id'], n['init']],
- Syntax.WhileStatement: lambda n: [n['test'], n['body']],
- Syntax.WithStatement: lambda n: [n['object'], n['body']],
-}
-
-SKIP = object()
-class Visitor(object):
- """
- Generic visitor for the pyjsparser AST.
-
- Visitation is driven by the ``visit`` method, which iterates the tree in
- depth-first pre-order.
-
- For each node, calls ``enter_$NODETYPE``, visits the children then calls
- ``exit_$NODETYPE``. If the enter or exit methods are not present on the
- visitor, falls back on ``enter_generic`` and ``exit_generic``.
-
- Any ``enter_`` method can return ``SKIP`` to suppress both the traversal
- of the subtree *and* the call to the corresponding ``exit_`` method
- (whether generic or specific).
-
- For convenience, ``visit`` will return whatever is set as the visitor's
- ``result`` attribute, ``None`` by default.
-
- ``visit`` can be given multiple root nodes, and it can be called multiple
- times. The ``result`` attribute is cleared at each call but not between
- two roots of the same ``visit`` call.
- """
- def __init__(self):
- super(Visitor, self).__init__()
- self.result = None
-
- def enter_generic(self, node): pass
- def exit_generic(self, node): pass
-
- def visit(self, nodes):
- if isinstance(nodes, dict):
- nodes = [nodes]
- # if multiple nodes are passed in, we need to reverse the order in
- # order to traverse front-to-back rather than the other way around
- nodes = list(reversed(nodes))
-
- while nodes:
- node = nodes.pop()
- # should probably filter None descendants in _children...
- if node is None:
- continue
- node_type = node['type']
- if node_type == '_exit':
- node = node['node']
- getattr(self, 'exit_' + node['type'], self.exit_generic)(node)
- continue
-
- if getattr(self, 'enter_' + node_type, self.enter_generic)(node) is SKIP:
- continue
-
- nodes.append({'type': '_exit', 'node': node})
- nodes.extend(reversed(_children[node_type](node)))
-
- return self.result
-
diff --git a/doc/_extensions/conftest.py b/doc/_extensions/conftest.py
deleted file mode 100644
index e69de29bb2d..00000000000
--- a/doc/_extensions/conftest.py
+++ /dev/null
diff --git a/doc/_extensions/exercise_admonition.py b/doc/_extensions/exercise_admonition.py
deleted file mode 100644
index 07cb11a5389..00000000000
--- a/doc/_extensions/exercise_admonition.py
+++ /dev/null
@@ -1,24 +0,0 @@
-# -*- coding: utf-8 -*-
-
-"""
-Adds a new "exercise" admonition type
-"""
-
-def setup(app):
- app.add_directive('exercise', Exercise)
- app.add_node(exercise, html=(
- lambda self, node: self.visit_admonition(node, 'exercise'),
- lambda self, node: self.depart_admonition(node)
- ), latex=(
- lambda self, node: self.visit_admonition(node),
- lambda self, node: self.depart_admonition(node)
- ))
-
-from docutils import nodes
-from docutils.parsers.rst.directives import admonitions
-class exercise(nodes.Admonition, nodes.Element): pass
-class Exercise(admonitions.BaseAdmonition):
- node_class = exercise
-
-from sphinx.locale import admonitionlabels
-admonitionlabels['exercise'] = 'Exercise'
diff --git a/doc/_extensions/github_link.py b/doc/_extensions/github_link.py
deleted file mode 100644
index 8f7a0084039..00000000000
--- a/doc/_extensions/github_link.py
+++ /dev/null
@@ -1,105 +0,0 @@
-import inspect
-import importlib
-import os.path
-
-from werkzeug import urls
-
-"""
-* adds github_link(mode) context variable: provides URL (in relevant mode) of
- current document on github
-* if sphinx.ext.linkcode is enabled, automatically generates github linkcode
- links (by setting config.linkcode_resolve)
-
-Settings
-========
-
-* ``github_user``, username/organisation under which the project lives
-* ``github_project``, name of the project on github
-* (optional) ``version``, github branch to link to (default: master)
-
-Notes
-=====
-
-* provided ``linkcode_resolve`` only supports Python domain
-* generates https github links
-* explicitly imports ``odoo``, so useless for anyone else
-"""
-
-def setup(app):
- app.add_config_value('github_user', None, 'env')
- app.add_config_value('github_project', None, 'env')
- app.connect('html-page-context', add_doc_link)
-
- def linkcode_resolve(domain, info):
- """ Resolves provided object to corresponding github URL
- """
- # TODO: js?
- if domain != 'py':
- return None
- if not (app.config.github_user and app.config.github_project):
- return None
-
- module, fullname = info['module'], info['fullname']
- # TODO: attributes/properties don't have modules, maybe try to look
- # them up based on their cached host object?
- if not module:
- return None
-
- obj = importlib.import_module(module)
- for item in fullname.split('.'):
- obj = getattr(obj, item, None)
-
- if obj is None:
- return None
-
- # get original from decorated methods
- try: obj = getattr(obj, '_orig')
- except AttributeError: pass
-
- try:
- obj_source_path = inspect.getsourcefile(obj)
- _, line = inspect.getsourcelines(obj)
- except (TypeError, IOError):
- # obj doesn't have a module, or something
- return None
-
- import odoo
- # FIXME: make finding project root project-independent
- project_root = os.path.join(os.path.dirname(odoo.__file__), '..')
- return make_github_link(
- app,
- os.path.relpath(obj_source_path, project_root),
- line)
- app.config.linkcode_resolve = linkcode_resolve
-
-def make_github_link(app, path, line=None, mode="blob"):
- config = app.config
-
- urlpath = "/{user}/{project}/{mode}/{branch}/{path}".format(
- user=config.github_user,
- project=config.github_project,
- branch=config.version or 'master',
- path=path,
- mode=mode,
- )
- return urls.url_unparse((
- 'https',
- 'github.com',
- urlpath,
- '',
- '' if line is None else 'L%d' % line
- ))
-def add_doc_link(app, pagename, templatename, context, doctree):
- """ Add github_link function linking to the current page on github """
- if not app.config.github_user and app.config.github_project:
- return
-
- source_suffix = app.config.source_suffix
- # in 1.3 source_suffix can be a list
- # in 1.8 source_suffix can be a mapping
- # FIXME: will break if we ever add support for !rst markdown documents maybe
- if not isinstance(source_suffix, str):
- source_suffix = next(iter(source_suffix))
- # can't use functools.partial because 3rd positional is line not mode
- context['github_link'] = lambda mode='edit': make_github_link(
- app, 'doc/%s%s' % (pagename, source_suffix), mode=mode)
diff --git a/doc/_extensions/html_domain.py b/doc/_extensions/html_domain.py
deleted file mode 100644
index 75d3c6e1127..00000000000
--- a/doc/_extensions/html_domain.py
+++ /dev/null
@@ -1,129 +0,0 @@
-# -*- coding: utf-8 -*-
-
-"""
-Defines a "raw HTML" domain with a ``div[classes]`` and a number of roles
-rendered more or less directly to HTML.
-
-.. warning::
-
- the purpose of this domain is *not* to document HTML or components
-"""
-
-from docutils import nodes, utils
-from docutils.parsers.rst import Directive, directives
-from docutils.parsers.rst.directives.body import LineBlock
-
-import sphinx
-import sphinx.roles
-from sphinx.domains import Domain
-
-def setup(app):
- app.add_domain(HtmlDomain)
- app.add_node(div, html=(
- lambda self, node: self.body.append(self.starttag(node, 'div')),
- lambda self, node: self.body.append('</div>\n')))
- # override parameter was added for version sphinx >= 1.4, TypeError before
- kw = {'override': True} if sphinx.version_info >= (1, 4) else {}
- app.add_node(address, html=(
- lambda self, node: self.body.append(self.starttag(node, 'address')),
- lambda self, node: self.body.append('</address>\n')
- ), **kw) # docutils.nodes.address exists and is a bibliographic element
- app.add_node(cite, html=(visit_cite, depart_cite))
- for name, node in [('mark', mark), ('ins', insert), ('del', delete),
- ('s', strikethrough), ('u', underline), ('small', small),
- ('kbd', kbd), ('var', var), ('samp', samp)]:
- addnode(app, node, name)
-
-
-class div(nodes.General, nodes.Element): pass
-class Div(Directive):
- optional_arguments = 1
- final_argument_whitespace = 1
- has_content = True
-
- def run(self):
- self.assert_has_content()
- text = '\n'.join(self.content)
- try:
- if self.arguments:
- classes = directives.class_option(self.arguments[0])
- else:
- classes = []
- except ValueError:
- raise self.error(
- 'Invalid class attribute value for "%s" directive: "%s".'
- % (self.name, self.arguments[0]))
- node = div(text)
- node['classes'].extend(classes)
- self.add_name(node)
- self.state.nested_parse(self.content, self.content_offset, node)
- return [node]
-
-class address(nodes.General, nodes.Element): pass
-class Address(LineBlock):
- def run(self):
- [node] = super(Address, self).run()
- ad = address(node.rawsource, *node.children)
- return [ad]
-
-class mark(nodes.Inline, nodes.TextElement): pass
-class insert(nodes.Inline, nodes.TextElement): pass
-class delete(nodes.Inline, nodes.TextElement): pass
-class strikethrough(nodes.Inline, nodes.TextElement): pass
-class underline(nodes.Inline, nodes.TextElement): pass
-class small(nodes.Inline, nodes.TextElement): pass
-class kbd(nodes.Inline, nodes.FixedTextElement): pass
-class var(nodes.Inline, nodes.FixedTextElement): pass
-class samp(nodes.Inline, nodes.FixedTextElement): pass
-
-def makerole(node):
- return lambda name, rawtext, text, lineno, inliner, options=None, content=None:\
- ([node(rawtext.strip(), text.strip())], [])
-def addnode(app, node, nodename):
- app.add_node(node, html=(
- lambda self, n: self.body.append(self.starttag(n, nodename)),
- lambda self, n: self.body.append('</%s>' % nodename)
- ))
-def initialism(*args, **kwargs):
- nodes, _ = sphinx.roles.abbr_role(*args, **kwargs)
- [abbr] = nodes
- abbr.attributes.setdefault('classes', []).append('initialism')
- return [abbr], []
-
-def cite_role(typ, rawtext, text, lineno, inliner, options=None, content=None):
- text = utils.unescape(text)
- m = sphinx.roles._abbr_re.search(text)
- if m is None:
- return [cite(text, text, **(options or {}))], []
- content = text[:m.start()].strip()
- source = m.group(1)
- return [cite(content, content, source=source)], []
-class cite(nodes.Inline, nodes.TextElement): pass
-def visit_cite(self, node):
- attrs = {}
- if node.hasattr('source'):
- attrs['title'] = node['source']
- self.body.append(self.starttag(node, 'cite', '', **attrs))
-def depart_cite(self, node):
- self.body.append('</abbr>')
-
-class HtmlDomain(Domain):
- name = 'h'
- label = 'HTML'
- directives = {
- 'div': Div,
- 'address': Address,
- }
- roles = {
- 'mark': makerole(mark),
- 'ins': makerole(insert),
- 'del': makerole(delete),
- 's': makerole(strikethrough),
- 'u': makerole(underline),
- 'small': makerole(small),
- 'initialism': initialism,
- 'cite': cite_role,
- 'kbd': makerole(kbd),
- 'var': makerole(var),
- 'samp': makerole(samp),
- }
diff --git a/doc/_extensions/odoo_ext/__init__.py b/doc/_extensions/odoo_ext/__init__.py
deleted file mode 100644
index 16b4a5326f7..00000000000
--- a/doc/_extensions/odoo_ext/__init__.py
+++ /dev/null
@@ -1,148 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from . import pygments_override
-from . import switcher
-from . import translator
-
-import sphinx.environment
-try:
- from sphinx.environment.adapters import toctree
-except ImportError:
- toctree = None
-
-import sphinx.builders.html
-from docutils import nodes
-def setup(app):
- if hasattr(app, 'set_translator'):
- app.set_translator('html', translator.BootstrapTranslator)
- else:
- if getattr(app.config, 'html_translator_class', None):
- app.warn("Overriding the explicitly set html_translator_class setting",
- location="odoo extension")
- app.config.html_translator_class = 'odoo_ext.translator.BootstrapTranslator'
-
- add_js_file = getattr(app, 'add_js_file', None) or app.add_javascript
- for f in ['jquery.min.js', 'bootstrap.js', 'doc.js', 'jquery.noconflict.js']:
- add_js_file(f)
-
- switcher.setup(app)
- app.add_config_value('odoo_cover_default', None, 'env')
- app.add_config_value('odoo_cover_external', {}, 'env')
- app.add_config_value('odoo_cover_default_external', lambda conf: conf.odoo_cover_default, 'env')
- app.connect('html-page-context', update_meta)
-
-def update_meta(app, pagename, templatename, context, doctree):
- meta = context.get('meta')
- if meta is None:
- meta = context['meta'] = {}
- meta.setdefault('banner', app.config.odoo_cover_default)
-
-def navbarify(node, navbar=None):
- """
- :param node: toctree node to navbarify
- :param navbar: Whether this toctree is a 'main' navbar, a 'side' navbar or
- not a navbar at all
- """
- if navbar == 'main':
- # add classes to just toplevel
- node['classes'].extend(['nav', 'navbar-nav', 'navbar-right'])
- for list_item in node.children:
- # bullet_list
- # list_item
- # compact_paragraph
- # reference
- # bullet_list
- # list_item
- # compact_paragraph
- # reference
- # no bullet_list.list_item -> don't dropdownify
- if len(list_item.children) < 2 or not list_item.children[1].children:
- continue
-
- list_item['classes'].append('dropdown')
- # list_item.compact_paragraph.reference
- link = list_item.children[0].children[0]
- link['classes'].append('dropdown-toggle')
- link.attributes['data-toggle'] = 'dropdown'
- # list_item.bullet_list
- list_item.children[1]['classes'].append('dropdown-menu')
- elif navbar is None:
- for n in node.traverse(nodes.reference):
- # list_item
- # compact_paragraph
- # reference <- starting point
- # bullet_list
- # list_item+
- # if the current list item (GP of current node) has bullet list
- # children, unref it
- list_item = n.parent.parent
- # only has a reference -> ignore
- if len(list_item.children) < 2:
- continue
- # no subrefs -> ignore
- if not list_item.children[1].children:
- continue
- # otherwise replace reference node by an inline (so it can still be styled)
- para = n.parent
- para.remove(n)
- para.append(nodes.inline('', '', *n.children))
-
-
-def resolve_content_toctree(
- environment, docname, builder, toctree, prune=True, maxdepth=0,
- titles_only=False, collapse=False, includehidden=False):
- """Alternative toctree resolution for main content: don't resolve the
- toctree, just handle it as a normal node, in the translator
- """
- return toctree
-
-class monkey(object):
- def __init__(self, obj):
- self.obj = obj
- def __call__(self, fn):
- name = fn.__name__
- old = getattr(self.obj, name)
- setattr(self.obj, name, lambda self_, *args, **kwargs: \
- fn(old, self_, *args, **kwargs))
-if toctree:
- # 1.6 and above use a new toctree adapter object for processing rather
- # than functions on the BuildEnv & al
- @monkey(toctree.TocTree)
- def resolve(old_resolve, tree, docname, *args, **kwargs):
- if docname == tree.env.config.master_doc:
- return resolve_content_toctree(tree.env, docname, *args, **kwargs)
- return old_resolve(tree, docname, *args, **kwargs)
-
-@monkey(sphinx.environment.BuildEnvironment)
-def resolve_toctree(old_resolve, self, docname, *args, **kwargs):
- """ If navbar, bootstrapify TOC to yield a navbar
-
- """
- navbar = kwargs.pop('navbar', None)
- if docname == self.config.master_doc and not navbar:
- return resolve_content_toctree(self, docname, *args, **kwargs)
- toc = old_resolve(self, docname, *args, **kwargs)
- if toc is None:
- return None
-
- navbarify(toc[0], navbar=navbar)
- return toc
-
-@monkey(sphinx.builders.html.StandaloneHTMLBuilder)
-def render_partial(old_partial, self, node):
- if isinstance(node, nodes.bullet_list) and node.children:
- # side nav?
- # remove single top-level item
- # bullet_list/0(list_item)/1(bullet_list)
- level1 = node.children[0].children
- if len(level1) > 1:
- node = level1[1]
- node['classes'].extend(['list-group', 'nav', 'text-left'])
- for n in node.traverse():
- if isinstance(n, nodes.list_item):
- n['classes'].append('list-group-item')
- elif isinstance(n, nodes.reference):
- n['classes'].append('ripple')
- else:
- node.clear()
- return old_partial(self, node)
diff --git a/doc/_extensions/odoo_ext/breadcrumb_list.html b/doc/_extensions/odoo_ext/breadcrumb_list.html
deleted file mode 100644
index 9d670a4879c..00000000000
--- a/doc/_extensions/odoo_ext/breadcrumb_list.html
+++ /dev/null
@@ -1,23 +0,0 @@
-{# warning: if doc structure change, these rules may have to change as well #}
-
-{# ===== VARIABLES ====== #}
-{% set master_doc_short_name = 'Developer Doc' %}
-
-{% if pagename == master_doc %}
- <li><a href="{{ pathto(master_doc) }}" class="active">{{ master_doc_short_name }}</a></li>
-{% else %}
- {% for parent in parents %}
- {% if loop.length > 1%}
- {% if loop.first %}
- <li><a href="{{ pathto(master_doc) }}">{{ master_doc_short_name }}</a></li>
- {% else %}
- {% if loop.index == 2 %}
- <li><a href="{{ parent.link|e }}">{{parent.title}}</a></li>
- {% endif %}
- {% endif %}
- {% else %}
- <li><a href="{{ pathto(master_doc) }}">{{ master_doc_short_name }}</a></li>
- {% endif %}
- {% endfor %}
- <li class="active"><a href="#">{{ meta.get('main-title', title) }}</a></li>
-{% endif %} \ No newline at end of file
diff --git a/doc/_extensions/odoo_ext/layout.html b/doc/_extensions/odoo_ext/layout.html
deleted file mode 100644
index e631b496e6b..00000000000
--- a/doc/_extensions/odoo_ext/layout.html
+++ /dev/null
@@ -1,339 +0,0 @@
-{% extends "basic/layout.html" %}
-
-{% set classes = [] %}
-{% if pagename == master_doc %}
- {% set classes = classes + ['index'] %}
-{% endif %}
-
-{% if 'code-column' in meta %}
- {% set classes = classes + ['has_code_col'] %}
-{% endif %}
-
-{%- block doctype -%}
- <!doctype html>
-{%- endblock -%}
-
-{%- block linktags %}
- <link href="https://fonts.googleapis.com/css?family=Work+Sans:500,600" rel="stylesheet">
- <link rel="canonical" href="{{ canonical }}" />
- {{- super() }}
-{%- endblock %}
-
-{%- block sidebar1 -%}{%- endblock -%}
-{%- block sidebar2 -%}{%- endblock -%}
-{%- block relbar1 -%}{%- endblock -%}
-{%- block relbar2 -%}{%- endblock -%}
-
-{%- block footer -%}
- {%- if google_analytics_key -%}
- <script>
- (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
- (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
- m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
- })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
-
- ga('create', '{{ google_analytics_key }}', 'auto');
- ga('send','pageview');
- </script>
- {%- endif -%}
-{%- endblock -%}
-
-{%- block header -%}
- <header class="o_main_header o_has_sub_nav o_inverted {{ ' '.join(classes) }}">
- <div class="o_main_header_main">
- <a class="pull-left o_logo" href="/"></a>
- <a href="#" class="o_mobile_menu_toggle visible-xs-block pull-right">
- <span class="sr-only">Toggle navigation</span>
- <span class="mdi-navigation-menu"></span>
- </a>
- <div class="o_header_buttons">
- <a href="http://www.odoo.com/trial" class="btn btn-primary">Start Now</a>
- </div>
- <ul class="o_primary_nav">
- <li class="dropdown">
- <a href="#" class="dropdown-toggle">Apps</a>
- <div class="dropdown-menu o_secondary_nav">
- <div class="container">
- <div class="row">
- <div class="col-sm-3 o_website_apps">
- <div class="o_nav_app_family">
- <span></span> Websites
- <div>Build great user experience</div>
- </div>
- <ul>
- <li><a href="https://www.odoo.com/page/website-builder">Website Builder</a></li>
- <li><a href="https://www.odoo.com/page/e-commerce">eCommerce</a></li>
- <li><a href="https://www.odoo.com/page/blog-engine">Blogs</a></li>
- <li><a href="https://www.odoo.com/page/community-builder">Forums</a></li>
- <li><a href="https://www.odoo.com/page/slides">Slides</a></li>
- <li><a href="https://adspike.odoo.com">SEA</a></li>
- </ul>
- </div>
- <div class="col-sm-3 o_sale_apps">
- <div class="o_nav_app_family">
- <span></span> Sales
- <div>Boost your success rate</div>
- </div>
- <ul>
- <li><a href="https://www.odoo.com/page/sales">Sales</a></li>
- <li><a href="https://www.odoo.com/page/crm">CRM</a></li>
- <li><a href="https://www.odoo.com/page/billing">Invoicing</a></li>
- <li class="dropdown">
- <a href="#0" class="dropdown-toggle">Point of Sale</a>
- <ul>
- <li><a href="https://www.odoo.com/page/point-of-sale">Shops</a></li>
- <li><a href="https://www.odoo.com/page/pos-restaurant">Restaurants</a></li>
- </ul>
- </li>
- <li><a href="https://www.odoo.com/page/subscriptions">Subscriptions</a></li>
- <li><a href="https://www.odoo.com/page/sign">Sign</a></li>
- </ul>
- </div>
- <div class="col-sm-3 o_operation_apps">
- <div class="o_nav_app_family">
- <span></span> Operations
- <div>It's all about efficiency</div>
- </div>
- <ul>
- <li><a href="https://www.odoo.com/page/accounting">Accounting</a></li>
- <li><a href="https://www.odoo.com/page/project-management">Project</a></li>
- <li class="dropdown">
- <a href="#0" class="dropdown-toggle">Human Resources</a>
- <ul>
- <li><a href="https://www.odoo.com/page/recruitment">Recruitment</a></li>
- <li><a href="https://www.odoo.com/page/employees">Employees</a></li>
- <li><a href="https://www.odoo.com/page/expenses">Expenses</a></li>
- <li><a href="https://www.odoo.com/page/appraisal">Appraisal</a></li>
- <li><a href="https://www.odoo.com/page/fleet">Fleet</a></li>
- <li><a href="https://www.odoo.com/page/leaves">Leaves</a></li>
- </ul>
- </li>
- <li><a href="https://www.odoo.com/page/warehouse">Inventory</a></li>
- <li><a href="https://www.odoo.com/page/purchase">Purchase</a></li>
- <li class="dropdown">
- <a href="#0" class="dropdown-toggle">Manufacturing</a>
- <ul>
- <li><a href="https://www.odoo.com/page/manufacturing">MRP</a></li>
- <li><a href="https://www.odoo.com/page/plm">PLM</a></li>
- <li><a href="https://www.odoo.com/page/maintenance">Maintenance</a></li>
- <li><a href="https://www.odoo.com/page/quality">Quality</a></li>
- </ul>
- </li>
- </ul>
- </div>
- <div class="col-sm-3 o_productivity_apps">
- <div class="o_nav_app_family">
- <span></span> Productivity Tools
- <div>Great Tools = Happy People</div>
- </div>
- <ul>
- <li class="dropdown">
- <a href="#0" class="dropdown-toggle">Communication</a>
- <ul>
- <li><a href="https://www.odoo.com/page/discuss">Discuss</a></li>
- <li><a href="https://www.odoo.com/page/discuss-groups">Mailing Lists</a></li>
- <li><a href="https://www.odoo.com/page/notes">Notes</a></li>
- <li><a href="#">Help desk</a></li>
- <li><a href="#">Appointment</a></li>
- </ul>
- </li>
- <li><a href="https://www.odoo.com/page/timesheet">Timesheet</a></li>
- <li><a href="https://www.odoo.com/page/email-marketing">Email Marketing</a></li>
- <li><a href="https://www.odoo.com/page/events">Events</a></li>
- <li><a href="https://www.odoo.com/page/survey">Survey</a></li>
- <li><a href="https://www.odoo.com/page/live-chat">Live Chat</a></li>
- </ul>
- </div>
- </div>
- </div>
- <a href="http://www.odoo.com/apps/modules" class="o_store_link"><i class="fa fa-cube fa-fw"></i> Third party apps</a>
- </div>
- </li>
- <li><a href="https://www.odoo.com/page/tour">Tour</a></li>
- <li><a href="https://www.odoo.com/pricing">Pricing</a></li>
- <li><a href="https://www.odoo.com/page/docs">Docs</a></li>
- </ul>
- </div>
- <nav class="navbar o_sub_nav">
- <div class="container">
- <div class="navbar-header visible-xs">
- <button type="button" class="navbar-toggle collapsed text-left btn-block" data-toggle="collapse" data-target="#o_sub-menu" aria-expanded="false">
- Navigate
- <span class="mdi-hardware-keyboard-arrow-down pull-right"></span>
- </button>
- </div>
-
- <div class="collapse navbar-collapse" id="o_sub-menu">
- <ol class="o_breadcrumb breadcrumb nav navbar-left">
- {% block breadcrumb_desktop %}
- {% include "breadcrumb_list.html" %}
- {% endblock %}
- </ol>
-
- <div class="call-to-action navbar-right hidden-xs">
- <a href="http://www.odoo.com/trial" class="btn btn-primary">Start Now</a>
- </div>
-
- <ul class="navbar-nav navbar-right nav o_sub_nav_actions">
- {% if pagename != master_doc %}
- <li class="divider"></li>
- {% endif%}
-
- {% block switchers_desktop %}
- {% include "switchers_list.html" %}
- {% endblock %}
- </ul>
-
- <ul class="nav navbar-nav navbar-right">
- {% if languages or versions %}
- <li class="divider"></li>
- {% endif %}
-
- {% block sub_menu_desktop %}
- {% include "sub-menu_list.html" %}
- {% endblock %}
-
- {% if languages or versions %}
- <li class="divider"></li>
- {% endif %}
- </ul>
- </div>
- </div>
- </nav>
- </header>
-
-{%- endblock -%}
-
-{%- block content -%}
- <div id="wrap" class="{{' '.join(classes) }}">
- {% if meta['banner'] %}
- {% set has_banner = 'has_banner' %}
- {% endif %}
- <figure class="card top {{ has_banner }}">
- <span class="card-img" {% if meta['banner'] %}style="background-image: url('{{ pathto('_static/' + meta['banner'], True) }}');"{% endif %}></span>
- <div class="container text-center">
- <h1> {{ meta.get('main-title', title) }} </h1>
- </div>
- </figure>
- {% if 'code-column' in meta %}
- {% set container = 'container-fluid' %}
- {% else %}
- {% set container = 'container' %}
- {% endif %}
- <main class="container {{ ' '.join(classes) }}">
- {% if pagename != master_doc %}
- <div class="o_content row">
- {% if 'has-toc' not in meta and not (pagename in toc) %}
- <aside>
- <div class="navbar-aside text-center">
- {{ toc }}
- {% if github_link %}
- <p class="gith-container"><a href="{{ github_link(mode='edit') }}" class="gith-link">
- Edit on GitHub
- </a></p>
- {% endif %}
- </div>
- </aside>
- {% endif %}
- <article class="doc-body {% if 'has-toc' in meta %}doc-toc{% endif %}{% if pagename in toc%}index-category{% endif %}">
- {% endif %}
- {% block body %} {% endblock %}
- {% if pagename != master_doc %}</article>
- </div>
- {% endif %}
- <div id="mask"></div>
- </main>
- </div>
-
- <div class="floating_action_container">
- <a id="floating_action" class="ripple" href="#">
- <i class="mdi-action-explore"></i>
- </a>
- <div id="floating_action_menu">
- <span class="bubble"></span>
- <ul class="list-group content">
- <li class="list-group-item ripple"><a>Cras justo odio</a></li>
- <li class="list-group-item ripple"><a>Dapibus ac facilisis in</a></li>
- <li class="list-group-item ripple"><a>Morbi leo risus</a></li>
- <li class="list-group-item ripple"><a>Porta ac consectetur ac</a></li>
- <li class="list-group-item ripple"><a>Vestibulum at eros</a></li>
- </ul>
- </div>
- </div>
- <footer>
- <div id="footer" class="container">
- <span class="o_logo o_logo_inverse center-block o_footer_logo"></span>
- <div class="row">
- <div class="col-sm-7 col-md-7 col-lg-6">
- <div class="row">
- <div class="col-xs-6 col-sm-4">
- <span class="menu_title">Community</span>
- <ul>
- <li><a href="https://github.com/odoo/odoo">Github</a></li>
- <li><a href="http://www.odoo.com/page/download">Download</a></li>
- <li class="divider"></li>
- <li><a href="https://runbot.odoo.com">Runbot</a></li>
- <li><a href="https://github.com/odoo/odoo/wiki/Translations">Translations</a></li>
- <li class="divider"></li>
- <li><a href="http://www.odoo.com/page/odoo-community">Mailing Lists</a></li>
- <li><a href="http://www.odoo.com/forum/help-1">Forum</a></li>
- </ul>
- </div>
- <div class="col-xs-6 col-sm-4">
- <span class="menu_title">Services</span>
- <ul>
- <li><a href="https://www.odoo.sh">Odoo Cloud Platform</a></li>
- <li class="divider"></li>
- <li><a href="http://www.odoo.com/help">Support</a></li>
- <li><a href="https://upgrade.odoo.com">Upgrade</a></li>
- <li class="divider"></li>
- <li><a href="http://www.odoo.com/partners">Find a partner</a></li>
- <li><a href="http://www.odoo.com/page/become-a-partner">Become a partner</a></li>
- <li class="divider"></li>
- <li><a href="http://training.odoo.com/courses/odoo-functional">Training Center</a></li>
- <li><a href="http://www.odoo.com/page/education-program">Education</a></li>
- <li class="divider"></li>
- <li><a href="http://www.odoo.com/page/security">Security</a></li>
- </ul>
- </div>
- <div class="col-xs-12 col-sm-4 mb64">
- <span class="menu_title">About us</span>
- <ul>
- <li><a href="http://www.odoo.com/page/about-us">Our company</a></li>
- <li><a href="http://www.odoo.com/page/contactus">Contact</a></li>
- <li class="divider" />
- <li><a href="http://www.odoo.com/event">Events</a></li>
- <li><a href="http://www.odoo.com/blog">Blog</a></li>
- <li><a href="http://www.odoo.com/blog/6">Customers</a></li>
- <li class="divider" />
- <li><a href="http://www.odoo.com/jobs">Jobs</a></li>
- <li class="divider" />
- <li><a href="http://www.odoo.com/page/legal">Legal</a> | <a href="http://www.odoo.com/privacy">Privacy</a></li>
- </ul>
- </div>
- </div>
- </div>
- <div class="col-sm-5 col-md-4 col-md-offset-1 col-lg-5 col-lg-offset-1">
- <p>
- <small>
- Odoo is a suite of open source business apps that cover all your company needs: CRM, eCommerce, accounting, inventory, point of sale, project management, etc.
- <br/><br/>
- Odoo's unique value proposition is to be at the same time very easy to use and fully integrated.
- </small>
- </p>
- </div>
- </div>
- </div>
- <div class="o_footer_bottom">
- <div class="container">
- <a class="small" href="http://www.odoo.com/page/website-builder">Website made with <span class="o_logo o_logo_inverse o_logo_15"></span></a>
- <div class="social-links pull-right">
- <a href="http://www.odoo.com/web/about/facebook"><i class="fa fa-facebook"></i></a>
- <a href="http://www.odoo.com/web/about/twitter"><i class="fa fa-twitter"></i></a>
- <a href="http://www.odoo.com/web/about/linkedin"><i class="fa fa-linkedin"></i></a>
- <a href="mailto:info@odoo.com"><i class="fa fa-envelope"></i></a>
- </div>
- </div>
- </div>
- </footer>
-{%- endblock -%}
diff --git a/doc/_extensions/odoo_ext/pygments_override.py b/doc/_extensions/odoo_ext/pygments_override.py
deleted file mode 100644
index aa03003c0f1..00000000000
--- a/doc/_extensions/odoo_ext/pygments_override.py
+++ /dev/null
@@ -1,126 +0,0 @@
-# -*- coding: utf-8 -*-
-from pygments.style import Style
-from pygments.token import Keyword, Name, Comment, String, Error, Text, \
- Number, Operator, Generic, Whitespace, Punctuation, Other, Literal
-
-
-BACKGROUND = '#272727'
-CURRENT_LINE = "#41323f"
-SELECTION = "#4f424c"
-FOREGROUND = "#e7e9db"
-COMMENT = "#776e71"
-RED = "#ef6155"
-ORANGE = "#f99b15"
-YELLOW = "#fec418"
-GREEN = "#48b685"
-AQUA = "#5bc4bf"
-BLUE = "#06b6ef"
-PURPLE = "#815ba4"
-
-class OdooStyle(Style):
- """Modified version of Paraiso Dark style to avoid Pygments version
- annoyances.
-
- Paraíso (Dark) by Jan T. Sott
-
- Pygments template by Jan T. Sott (https://github.com/idleberg)
- Created with Base16 Builder by Chris Kempson
- (https://github.com/chriskempson/base16-builder).
-
- :copyright: Copyright 2006-2014 by the Pygments team
- :license: BSD
- """
-
- default_style = ''
-
- background_color = BACKGROUND
- highlight_color = SELECTION
-
- styles = {
- # No corresponding class for the following:
- Text: FOREGROUND,
- Whitespace: "",
- Error: RED,
- Other: "",
-
- Comment: COMMENT,
- Comment.Multiline: "",
- Comment.Preproc: "",
- Comment.Single: "",
- Comment.Special: "",
-
- Keyword: '#cb49a8',
- Keyword.Constant: "",
- Keyword.Declaration: "",
- Keyword.Namespace: AQUA,
- Keyword.Pseudo: "",
- Keyword.Reserved: "",
- Keyword.Type: YELLOW,
-
- Operator: AQUA,
- Operator.Word: "",
-
- Punctuation: FOREGROUND,
-
- Name: FOREGROUND,
- Name.Attribute: BLUE,
- Name.Builtin: "",
- Name.Builtin.Pseudo: "",
- Name.Class: YELLOW,
- Name.Constant: RED,
- Name.Decorator: AQUA,
- Name.Entity: "",
- Name.Exception: RED,
- Name.Function: BLUE,
- Name.Property: "",
- Name.Label: "",
- Name.Namespace: YELLOW,
- Name.Other: BLUE,
- Name.Tag: '#21b799',
- Name.Variable: RED,
- Name.Variable.Class: "",
- Name.Variable.Global: "",
- Name.Variable.Instance: "",
-
- Number: ORANGE,
- Number.Float: "",
- Number.Hex: "",
- Number.Integer: "",
- Number.Integer.Long: "",
- Number.Oct: "",
-
- Literal: ORANGE,
- Literal.Date: GREEN,
-
- String: GREEN,
- String.Backtick: "",
- String.Char: FOREGROUND,
- String.Doc: COMMENT,
- String.Double: "",
- String.Escape: ORANGE,
- String.Heredoc: "",
- String.Interpol: ORANGE,
- String.Other: "",
- String.Regex: "",
- String.Single: "",
- String.Symbol: "",
-
- Generic: "",
- Generic.Deleted: RED,
- Generic.Emph: "italic",
- Generic.Error: "",
- Generic.Heading: "bold " + FOREGROUND,
- Generic.Inserted: GREEN,
- Generic.Output: "",
- Generic.Prompt: "bold " + COMMENT,
- Generic.Strong: "bold",
- Generic.Subheading: "bold " + AQUA,
- Generic.Traceback: "",
- }
-
-import types
-import sys
-modname = 'pygments.styles.odoo'
-m = types.ModuleType(modname)
-m.OdooStyle = OdooStyle
-sys.modules[modname] = m
diff --git a/doc/_extensions/odoo_ext/static/aside.less b/doc/_extensions/odoo_ext/static/aside.less
deleted file mode 100644
index 98d560a9a2a..00000000000
--- a/doc/_extensions/odoo_ext/static/aside.less
+++ /dev/null
@@ -1,339 +0,0 @@
-// ====== Aside =======
-// ======================
-
-aside {
- .pseudo-col();
- width: 100%;
- max-width: 240px;
- position: static;
- padding: 0;
- display: block;
- border-right: 1px solid @gray-lighter;
-
- @media (max-width:@screen-md-min) {
- display: none;
- }
-}
-
-.navbar-aside {
- position: relative;
- overflow: hidden;
- font-family: @headings-font-family;
- font-size: 0.85em;
- line-height: 1.5;
- overflow-y: auto;
-
- &.affix {
- z-index: 2;
- top: @w-sub-nav-height - 1;
- position: fixed;
- backface-visibility: hidden;
- @media (max-width:@screen-md-min) {
- display: none;
- }
- }
-
- > ul.list-group {
- margin: 0;
- z-index: 0;
- }
-
- > h3 {
- margin: 0;
- padding: 15px 0 10px;
- text-transform: uppercase;
- font-weight: @fw_semibold;
- font-size: 16px;
- color: @text-color;
- overflow-x: hidden;
- position: relative;
- z-index: 1;
- .box-shadow(0 10px 9px -10px #d2d2d2);
- }
-
- .gith-container {
- margin: 0;
- z-index: 1;
- position: relative;
- overflow-x: hidden;
-
- .gith-link {
- color: @text-color;
- text-decoration: none;
- display: inline-block;
- position: relative;
- margin: 10px 0;
- font-family: @font-family-base;
-
- &:hover {
- color: @headings-color;
- text-decoration: none;
- }
-
- &:before {
- .square(1em);
- content: '';
- position: relative;
- background-image: url('img/github-square_32.png');
- background-size: 100%;
- display: inline-block;
- vertical-align: middle;
- .translate(0;-1px);
- }
- }
- }
- //-- All menu levels
- ul {
- padding: 0;
- position: relative;
- margin-bottom: 0 !important;
-
- li {
- padding: 0;
- margin-bottom: 0;
-
- &:first-child, &:last-child {
- // Reset border radius
- border-radius: 0;
- }
-
- &:first-child {
- overflow: hidden;
- border-radius: 2px 0 0 0;
- }
-
- > a {
- display: block;
- padding: 5px 15px;
- color: @text-color;
- line-height: 1.2;
-
- &:focus, &:hover {
- color: @headings-color;
- }
- }
-
- &.parent > a:after{
- content: '\e7c1';
- font-family: 'Material-Design-Icons';
- opacity: 0.8;
- margin-top: -6px;
- .o-position-absolute(50%, 10px);
- .rotate(90deg);
- .transition(transform 0.2s);
- }
-
- &.parent.active > a:after{
- .rotate(0);
- }
- }
-
- //-- Inner menu list
- ul {
- max-height: 0;
- background-color: fade(@gray-light, 20%);
- padding: 0px;
- overflow: hidden;
- margin-left: 0;
- box-shadow: inset 0 3px 5px -2px @gray-light;
- .transition(max-height 0.3s @o-ease);
-
- > li:not(:last-child) {
- box-shadow: 0 1px 0 fade(black, 4%);
-
- &.active > ul > li:not(:first-child) {
- border-top: 1px solid @gray-lighter;
- }
- }
- }
- }
-
- //-- Active lis
- li.active {
- &, &:focus, &:hover {
- border-color: @gray-lighter;
- background: transparent;
-
- > a {
- font-weight: bold;
- color: @headings-color;
- }
- }
-
- > ul {
- max-height: 1000px;
- }
- }
-
- // First menu level
- > ul > li {
- background: white;
- border-bottom: 1px solid fade(black, 8%);
-
- > a {
- padding: 10px 15px;
- border-left: 3px solid transparent;
- }
-
- &:focus, &:hover {
- > a {
- border-left: 3px solid @gray-light;
- background-color: transparent;
- }
- }
-
- &.active, &.active:focus, &.active:hover {
- > a {
- border-left: 3px solid @brand-primary;
- }
- }
-
- &.active.parent + li {
- box-shadow: 0 -3px 5px -4px fade(@gray-darker, 40%);
- }
-
- > ul > li {
- > a {
- padding-left: 20px;
- }
-
- > ul > li {
- > a {
- padding-left: 30px;
- }
-
- > ul > li > a {
- padding-left: 40px;
- }
- }
- }
- }
-}
-
-.floating_action_container {
- position: fixed;
- right: 8px;
- bottom: 8px;
- width: auto;
- z-index: @zIndex--float_action;
- @media (min-width:@screen-md-min) {
- display: none;
- }
-}
-
-#floating_action {
- .square(56px);
- display: inline-block;
- z-index: 0;
- background-color: transparent;
- border-radius: 50%;
- padding: 16px;
- box-shadow: 0 8px 17px 0 rgba(0, 0, 0, 0.1), 0 6px 20px 0 rgba(0, 0, 0, 0.05);
- background-color: @brand-primary;
- .transition(transform 500ms @o-ease);
-
- i {
- color: white;
- }
-
- &.active {
- .transform(~ "translateZ(0px) rotateZ(-180deg)");
- }
-}
-
-#floating_action_menu {
- .o-position-absolute(auto,0,0);
- z-index: 1;
- overflow: hidden;
- width: 380px;
- padding: 0;
- display: block;
- border-radius: 2px;
- visibility: hidden;
- .transition(all 0.5s);
- .box-shadow(0 0 0 transparent);
-
- .content {
- margin: 0;
- opacity:0;
-
- li {
- border: none;
- border-top: 1px solid #DDD;
-
- &:first-child {
- border-top: none;
- }
- }
-
- a {
- display: inline-block;
- cursor: pointer;
- color: @headings-color;
- text-decoration: none;
- float: left;
- width: 100%;
- padding: 5px 10px;
- }
- }
-
- .bubble {
- .o-position-absolute(auto,28px,28px);
- .square(1px);
- background: @brand-primary;
- content: '';
- color: #fff;
- border-radius: 50%;
- .transition(all 300ms @o-ease);
- }
-
- &:before {
- .bubble;
- background: white;
- }
-
- &.active {
- display: block;
- visibility: visible;
- .transition(all 500ms @o-ease);
-
- &:before, .bubble {
- .size(1000px; 2000px);
- border-radius: 50%;
- opacity: 0;
- margin-right: -500px;
- margin-bottom: -500px;
- display: block;
- .transition(all .4s @o-ease);
- }
-
- &:before {
- .opacity(1);
- }
-
- .content {
- position: relative;
- z-index: 1;
- .opacity(1);
- .transition(all 500ms @ease-material-3);
- }
- }
-}
-
-#mask {
- .opacity(0);
- position: fixed;
- z-index: @zIndex--mask;
- top: 0;
- left: 0;
- .size(100%; 0);
- background-color: fade(black, 20%);
- .transition(opacity .3s);
-
- &.active {
- .opacity(1);
- display: block;
- .square(100%);
- .transition(opacity .3s);
- }
-} \ No newline at end of file
diff --git a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/alerts.less b/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/alerts.less
deleted file mode 100755
index c4199db927e..00000000000
--- a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/alerts.less
+++ /dev/null
@@ -1,73 +0,0 @@
-//
-// Alerts
-// --------------------------------------------------
-
-
-// Base styles
-// -------------------------
-
-.alert {
- padding: @alert-padding;
- margin-bottom: @line-height-computed;
- border: 1px solid transparent;
- border-radius: @alert-border-radius;
-
- // Headings for larger alerts
- h4 {
- margin-top: 0;
- // Specified for the h4 to prevent conflicts of changing @headings-color
- color: inherit;
- }
-
- // Provide class for links that match alerts
- .alert-link {
- font-weight: @alert-link-font-weight;
- }
-
- // Improve alignment and spacing of inner content
- > p,
- > ul {
- margin-bottom: 0;
- }
-
- > p + p {
- margin-top: 5px;
- }
-}
-
-// Dismissible alerts
-//
-// Expand the right padding and account for the close button's positioning.
-
-.alert-dismissable, // The misspelled .alert-dismissable was deprecated in 3.2.0.
-.alert-dismissible {
- padding-right: (@alert-padding + 20);
-
- // Adjust close link position
- .close {
- position: relative;
- top: -2px;
- right: -21px;
- color: inherit;
- }
-}
-
-// Alternate styles
-//
-// Generate contextual modifier classes for colorizing the alert.
-
-.alert-success {
- .alert-variant(@alert-success-bg; @alert-success-border; @alert-success-text);
-}
-
-.alert-info {
- .alert-variant(@alert-info-bg; @alert-info-border; @alert-info-text);
-}
-
-.alert-warning {
- .alert-variant(@alert-warning-bg; @alert-warning-border; @alert-warning-text);
-}
-
-.alert-danger {
- .alert-variant(@alert-danger-bg; @alert-danger-border; @alert-danger-text);
-}
diff --git a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/badges.less b/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/badges.less
deleted file mode 100755
index 6ee16dca413..00000000000
--- a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/badges.less
+++ /dev/null
@@ -1,66 +0,0 @@
-//
-// Badges
-// --------------------------------------------------
-
-
-// Base class
-.badge {
- display: inline-block;
- min-width: 10px;
- padding: 3px 7px;
- font-size: @font-size-small;
- font-weight: @badge-font-weight;
- color: @badge-color;
- line-height: @badge-line-height;
- vertical-align: middle;
- white-space: nowrap;
- text-align: center;
- background-color: @badge-bg;
- border-radius: @badge-border-radius;
-
- // Empty badges collapse automatically (not available in IE8)
- &:empty {
- display: none;
- }
-
- // Quick fix for badges in buttons
- .btn & {
- position: relative;
- top: -1px;
- }
-
- .btn-xs &,
- .btn-group-xs > .btn & {
- top: 0;
- padding: 1px 5px;
- }
-
- // Hover state, but only for links
- a& {
- &:hover,
- &:focus {
- color: @badge-link-hover-color;
- text-decoration: none;
- cursor: pointer;
- }
- }
-
- // Account for badges in navs
- .list-group-item.active > &,
- .nav-pills > .active > a > & {
- color: @badge-active-color;
- background-color: @badge-active-bg;
- }
-
- .list-group-item > & {
- float: right;
- }
-
- .list-group-item > & + & {
- margin-right: 5px;
- }
-
- .nav-pills > li > a > & {
- margin-left: 3px;
- }
-}
diff --git a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/bootstrap.less b/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/bootstrap.less
deleted file mode 100755
index 1c0477805fa..00000000000
--- a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/bootstrap.less
+++ /dev/null
@@ -1,56 +0,0 @@
-/*!
- * Bootstrap v3.3.6 (http://getbootstrap.com)
- * Copyright 2011-2015 Twitter, Inc.
- * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
- */
-
-// Core variables and mixins
-@import "variables.less";
-@import "mixins.less";
-
-// Reset and dependencies
-@import "normalize.less";
-@import "print.less";
-@import "glyphicons.less";
-
-// Core CSS
-@import "scaffolding.less";
-@import "type.less";
-@import "code.less";
-@import "grid.less";
-@import "tables.less";
-@import "forms.less";
-@import "buttons.less";
-
-// Components
-@import "component-animations.less";
-@import "dropdowns.less";
-@import "button-groups.less";
-@import "input-groups.less";
-@import "navs.less";
-@import "navbar.less";
-@import "breadcrumbs.less";
-@import "pagination.less";
-@import "pager.less";
-@import "labels.less";
-@import "badges.less";
-@import "jumbotron.less";
-@import "thumbnails.less";
-@import "alerts.less";
-@import "progress-bars.less";
-@import "media.less";
-@import "list-group.less";
-@import "panels.less";
-@import "responsive-embed.less";
-@import "wells.less";
-@import "close.less";
-
-// Components w/ JavaScript
-@import "modals.less";
-@import "tooltip.less";
-@import "popovers.less";
-@import "carousel.less";
-
-// Utility classes
-@import "utilities.less";
-@import "responsive-utilities.less";
diff --git a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/breadcrumbs.less b/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/breadcrumbs.less
deleted file mode 100755
index cb01d503fbe..00000000000
--- a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/breadcrumbs.less
+++ /dev/null
@@ -1,26 +0,0 @@
-//
-// Breadcrumbs
-// --------------------------------------------------
-
-
-.breadcrumb {
- padding: @breadcrumb-padding-vertical @breadcrumb-padding-horizontal;
- margin-bottom: @line-height-computed;
- list-style: none;
- background-color: @breadcrumb-bg;
- border-radius: @border-radius-base;
-
- > li {
- display: inline-block;
-
- + li:before {
- content: "@{breadcrumb-separator}\00a0"; // Unicode space added since inline-block means non-collapsing white-space
- padding: 0 5px;
- color: @breadcrumb-color;
- }
- }
-
- > .active {
- color: @breadcrumb-active-color;
- }
-}
diff --git a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/button-groups.less b/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/button-groups.less
deleted file mode 100755
index 293245a6503..00000000000
--- a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/button-groups.less
+++ /dev/null
@@ -1,244 +0,0 @@
-//
-// Button groups
-// --------------------------------------------------
-
-// Make the div behave like a button
-.btn-group,
-.btn-group-vertical {
- position: relative;
- display: inline-block;
- vertical-align: middle; // match .btn alignment given font-size hack above
- > .btn {
- position: relative;
- float: left;
- // Bring the "active" button to the front
- &:hover,
- &:focus,
- &:active,
- &.active {
- z-index: 2;
- }
- }
-}
-
-// Prevent double borders when buttons are next to each other
-.btn-group {
- .btn + .btn,
- .btn + .btn-group,
- .btn-group + .btn,
- .btn-group + .btn-group {
- margin-left: -1px;
- }
-}
-
-// Optional: Group multiple button groups together for a toolbar
-.btn-toolbar {
- margin-left: -5px; // Offset the first child's margin
- &:extend(.clearfix all);
-
- .btn,
- .btn-group,
- .input-group {
- float: left;
- }
- > .btn,
- > .btn-group,
- > .input-group {
- margin-left: 5px;
- }
-}
-
-.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) {
- border-radius: 0;
-}
-
-// Set corners individual because sometimes a single button can be in a .btn-group and we need :first-child and :last-child to both match
-.btn-group > .btn:first-child {
- margin-left: 0;
- &:not(:last-child):not(.dropdown-toggle) {
- .border-right-radius(0);
- }
-}
-// Need .dropdown-toggle since :last-child doesn't apply given a .dropdown-menu immediately after it
-.btn-group > .btn:last-child:not(:first-child),
-.btn-group > .dropdown-toggle:not(:first-child) {
- .border-left-radius(0);
-}
-
-// Custom edits for including btn-groups within btn-groups (useful for including dropdown buttons within a btn-group)
-.btn-group > .btn-group {
- float: left;
-}
-.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn {
- border-radius: 0;
-}
-.btn-group > .btn-group:first-child:not(:last-child) {
- > .btn:last-child,
- > .dropdown-toggle {
- .border-right-radius(0);
- }
-}
-.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child {
- .border-left-radius(0);
-}
-
-// On active and open, don't show outline
-.btn-group .dropdown-toggle:active,
-.btn-group.open .dropdown-toggle {
- outline: 0;
-}
-
-
-// Sizing
-//
-// Remix the default button sizing classes into new ones for easier manipulation.
-
-.btn-group-xs > .btn { &:extend(.btn-xs); }
-.btn-group-sm > .btn { &:extend(.btn-sm); }
-.btn-group-lg > .btn { &:extend(.btn-lg); }
-
-
-// Split button dropdowns
-// ----------------------
-
-// Give the line between buttons some depth
-.btn-group > .btn + .dropdown-toggle {
- padding-left: 8px;
- padding-right: 8px;
-}
-.btn-group > .btn-lg + .dropdown-toggle {
- padding-left: 12px;
- padding-right: 12px;
-}
-
-// The clickable button for toggling the menu
-// Remove the gradient and set the same inset shadow as the :active state
-.btn-group.open .dropdown-toggle {
- .box-shadow(inset 0 3px 5px rgba(0,0,0,.125));
-
- // Show no shadow for `.btn-link` since it has no other button styles.
- &.btn-link {
- .box-shadow(none);
- }
-}
-
-
-// Reposition the caret
-.btn .caret {
- margin-left: 0;
-}
-// Carets in other button sizes
-.btn-lg .caret {
- border-width: @caret-width-large @caret-width-large 0;
- border-bottom-width: 0;
-}
-// Upside down carets for .dropup
-.dropup .btn-lg .caret {
- border-width: 0 @caret-width-large @caret-width-large;
-}
-
-
-// Vertical button groups
-// ----------------------
-
-.btn-group-vertical {
- > .btn,
- > .btn-group,
- > .btn-group > .btn {
- display: block;
- float: none;
- width: 100%;
- max-width: 100%;
- }
-
- // Clear floats so dropdown menus can be properly placed
- > .btn-group {
- &:extend(.clearfix all);
- > .btn {
- float: none;
- }
- }
-
- > .btn + .btn,
- > .btn + .btn-group,
- > .btn-group + .btn,
- > .btn-group + .btn-group {
- margin-top: -1px;
- margin-left: 0;
- }
-}
-
-.btn-group-vertical > .btn {
- &:not(:first-child):not(:last-child) {
- border-radius: 0;
- }
- &:first-child:not(:last-child) {
- .border-top-radius(@btn-border-radius-base);
- .border-bottom-radius(0);
- }
- &:last-child:not(:first-child) {
- .border-top-radius(0);
- .border-bottom-radius(@btn-border-radius-base);
- }
-}
-.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn {
- border-radius: 0;
-}
-.btn-group-vertical > .btn-group:first-child:not(:last-child) {
- > .btn:last-child,
- > .dropdown-toggle {
- .border-bottom-radius(0);
- }
-}
-.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child {
- .border-top-radius(0);
-}
-
-
-// Justified button groups
-// ----------------------
-
-.btn-group-justified {
- display: table;
- width: 100%;
- table-layout: fixed;
- border-collapse: separate;
- > .btn,
- > .btn-group {
- float: none;
- display: table-cell;
- width: 1%;
- }
- > .btn-group .btn {
- width: 100%;
- }
-
- > .btn-group .dropdown-menu {
- left: auto;
- }
-}
-
-
-// Checkbox and radio options
-//
-// In order to support the browser's form validation feedback, powered by the
-// `required` attribute, we have to "hide" the inputs via `clip`. We cannot use
-// `display: none;` or `visibility: hidden;` as that also hides the popover.
-// Simply visually hiding the inputs via `opacity` would leave them clickable in
-// certain cases which is prevented by using `clip` and `pointer-events`.
-// This way, we ensure a DOM element is visible to position the popover from.
-//
-// See https://github.com/twbs/bootstrap/pull/12794 and
-// https://github.com/twbs/bootstrap/pull/14559 for more information.
-
-[data-toggle="buttons"] {
- > .btn,
- > .btn-group > .btn {
- input[type="radio"],
- input[type="checkbox"] {
- position: absolute;
- clip: rect(0,0,0,0);
- pointer-events: none;
- }
- }
-}
diff --git a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/buttons.less b/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/buttons.less
deleted file mode 100755
index 9cbb8f416fa..00000000000
--- a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/buttons.less
+++ /dev/null
@@ -1,166 +0,0 @@
-//
-// Buttons
-// --------------------------------------------------
-
-
-// Base styles
-// --------------------------------------------------
-
-.btn {
- display: inline-block;
- margin-bottom: 0; // For input.btn
- font-weight: @btn-font-weight;
- text-align: center;
- vertical-align: middle;
- touch-action: manipulation;
- cursor: pointer;
- background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214
- border: 1px solid transparent;
- white-space: nowrap;
- .button-size(@padding-base-vertical; @padding-base-horizontal; @font-size-base; @line-height-base; @btn-border-radius-base);
- .user-select(none);
-
- &,
- &:active,
- &.active {
- &:focus,
- &.focus {
- .tab-focus();
- }
- }
-
- &:hover,
- &:focus,
- &.focus {
- color: @btn-default-color;
- text-decoration: none;
- }
-
- &:active,
- &.active {
- outline: 0;
- background-image: none;
- .box-shadow(inset 0 3px 5px rgba(0,0,0,.125));
- }
-
- &.disabled,
- &[disabled],
- fieldset[disabled] & {
- cursor: @cursor-disabled;
- .opacity(.65);
- .box-shadow(none);
- }
-
- a& {
- &.disabled,
- fieldset[disabled] & {
- pointer-events: none; // Future-proof disabling of clicks on `<a>` elements
- }
- }
-}
-
-
-// Alternate buttons
-// --------------------------------------------------
-
-.btn-default {
- .button-variant(@btn-default-color; @btn-default-bg; @btn-default-border);
-}
-.btn-primary {
- .button-variant(@btn-primary-color; @btn-primary-bg; @btn-primary-border);
-}
-// Success appears as green
-.btn-success {
- .button-variant(@btn-success-color; @btn-success-bg; @btn-success-border);
-}
-// Info appears as blue-green
-.btn-info {
- .button-variant(@btn-info-color; @btn-info-bg; @btn-info-border);
-}
-// Warning appears as orange
-.btn-warning {
- .button-variant(@btn-warning-color; @btn-warning-bg; @btn-warning-border);
-}
-// Danger and error appear as red
-.btn-danger {
- .button-variant(@btn-danger-color; @btn-danger-bg; @btn-danger-border);
-}
-
-
-// Link buttons
-// -------------------------
-
-// Make a button look and behave like a link
-.btn-link {
- color: @link-color;
- font-weight: normal;
- border-radius: 0;
-
- &,
- &:active,
- &.active,
- &[disabled],
- fieldset[disabled] & {
- background-color: transparent;
- .box-shadow(none);
- }
- &,
- &:hover,
- &:focus,
- &:active {
- border-color: transparent;
- }
- &:hover,
- &:focus {
- color: @link-hover-color;
- text-decoration: @link-hover-decoration;
- background-color: transparent;
- }
- &[disabled],
- fieldset[disabled] & {
- &:hover,
- &:focus {
- color: @btn-link-disabled-color;
- text-decoration: none;
- }
- }
-}
-
-
-// Button Sizes
-// --------------------------------------------------
-
-.btn-lg {
- // line-height: ensure even-numbered height of button next to large input
- .button-size(@padding-large-vertical; @padding-large-horizontal; @font-size-large; @line-height-large; @btn-border-radius-large);
-}
-.btn-sm {
- // line-height: ensure proper height of button next to small input
- .button-size(@padding-small-vertical; @padding-small-horizontal; @font-size-small; @line-height-small; @btn-border-radius-small);
-}
-.btn-xs {
- .button-size(@padding-xs-vertical; @padding-xs-horizontal; @font-size-small; @line-height-small; @btn-border-radius-small);
-}
-
-
-// Block button
-// --------------------------------------------------
-
-.btn-block {
- display: block;
- width: 100%;
-}
-
-// Vertically space out multiple block buttons
-.btn-block + .btn-block {
- margin-top: 5px;
-}
-
-// Specificity overrides
-input[type="submit"],
-input[type="reset"],
-input[type="button"] {
- &.btn-block {
- width: 100%;
- }
-}
diff --git a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/carousel.less b/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/carousel.less
deleted file mode 100755
index 252011e9e25..00000000000
--- a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/carousel.less
+++ /dev/null
@@ -1,270 +0,0 @@
-//
-// Carousel
-// --------------------------------------------------
-
-
-// Wrapper for the slide container and indicators
-.carousel {
- position: relative;
-}
-
-.carousel-inner {
- position: relative;
- overflow: hidden;
- width: 100%;
-
- > .item {
- display: none;
- position: relative;
- .transition(.6s ease-in-out left);
-
- // Account for jankitude on images
- > img,
- > a > img {
- &:extend(.img-responsive);
- line-height: 1;
- }
-
- // WebKit CSS3 transforms for supported devices
- @media all and (transform-3d), (-webkit-transform-3d) {
- .transition-transform(~'0.6s ease-in-out');
- .backface-visibility(~'hidden');
- .perspective(1000px);
-
- &.next,
- &.active.right {
- .translate3d(100%, 0, 0);
- left: 0;
- }
- &.prev,
- &.active.left {
- .translate3d(-100%, 0, 0);
- left: 0;
- }
- &.next.left,
- &.prev.right,
- &.active {
- .translate3d(0, 0, 0);
- left: 0;
- }
- }
- }
-
- > .active,
- > .next,
- > .prev {
- display: block;
- }
-
- > .active {
- left: 0;
- }
-
- > .next,
- > .prev {
- position: absolute;
- top: 0;
- width: 100%;
- }
-
- > .next {
- left: 100%;
- }
- > .prev {
- left: -100%;
- }
- > .next.left,
- > .prev.right {
- left: 0;
- }
-
- > .active.left {
- left: -100%;
- }
- > .active.right {
- left: 100%;
- }
-
-}
-
-// Left/right controls for nav
-// ---------------------------
-
-.carousel-control {
- position: absolute;
- top: 0;
- left: 0;
- bottom: 0;
- width: @carousel-control-width;
- .opacity(@carousel-control-opacity);
- font-size: @carousel-control-font-size;
- color: @carousel-control-color;
- text-align: center;
- text-shadow: @carousel-text-shadow;
- background-color: rgba(0, 0, 0, 0); // Fix IE9 click-thru bug
- // We can't have this transition here because WebKit cancels the carousel
- // animation if you trip this while in the middle of another animation.
-
- // Set gradients for backgrounds
- &.left {
- #gradient > .horizontal(@start-color: rgba(0,0,0,.5); @end-color: rgba(0,0,0,.0001));
- }
- &.right {
- left: auto;
- right: 0;
- #gradient > .horizontal(@start-color: rgba(0,0,0,.0001); @end-color: rgba(0,0,0,.5));
- }
-
- // Hover/focus state
- &:hover,
- &:focus {
- outline: 0;
- color: @carousel-control-color;
- text-decoration: none;
- .opacity(.9);
- }
-
- // Toggles
- .icon-prev,
- .icon-next,
- .glyphicon-chevron-left,
- .glyphicon-chevron-right {
- position: absolute;
- top: 50%;
- margin-top: -10px;
- z-index: 5;
- display: inline-block;
- }
- .icon-prev,
- .glyphicon-chevron-left {
- left: 50%;
- margin-left: -10px;
- }
- .icon-next,
- .glyphicon-chevron-right {
- right: 50%;
- margin-right: -10px;
- }
- .icon-prev,
- .icon-next {
- width: 20px;
- height: 20px;
- line-height: 1;
- font-family: serif;
- }
-
-
- .icon-prev {
- &:before {
- content: '\2039';// SINGLE LEFT-POINTING ANGLE QUOTATION MARK (U+2039)
- }
- }
- .icon-next {
- &:before {
- content: '\203a';// SINGLE RIGHT-POINTING ANGLE QUOTATION MARK (U+203A)
- }
- }
-}
-
-// Optional indicator pips
-//
-// Add an unordered list with the following class and add a list item for each
-// slide your carousel holds.
-
-.carousel-indicators {
- position: absolute;
- bottom: 10px;
- left: 50%;
- z-index: 15;
- width: 60%;
- margin-left: -30%;
- padding-left: 0;
- list-style: none;
- text-align: center;
-
- li {
- display: inline-block;
- width: 10px;
- height: 10px;
- margin: 1px;
- text-indent: -999px;
- border: 1px solid @carousel-indicator-border-color;
- border-radius: 10px;
- cursor: pointer;
-
- // IE8-9 hack for event handling
- //
- // Internet Explorer 8-9 does not support clicks on elements without a set
- // `background-color`. We cannot use `filter` since that's not viewed as a
- // background color by the browser. Thus, a hack is needed.
- // See https://developer.mozilla.org/en-US/docs/Web/Events/click#Internet_Explorer
- //
- // For IE8, we set solid black as it doesn't support `rgba()`. For IE9, we
- // set alpha transparency for the best results possible.
- background-color: #000 \9; // IE8
- background-color: rgba(0,0,0,0); // IE9
- }
- .active {
- margin: 0;
- width: 12px;
- height: 12px;
- background-color: @carousel-indicator-active-bg;
- }
-}
-
-// Optional captions
-// -----------------------------
-// Hidden by default for smaller viewports
-.carousel-caption {
- position: absolute;
- left: 15%;
- right: 15%;
- bottom: 20px;
- z-index: 10;
- padding-top: 20px;
- padding-bottom: 20px;
- color: @carousel-caption-color;
- text-align: center;
- text-shadow: @carousel-text-shadow;
- & .btn {
- text-shadow: none; // No shadow for button elements in carousel-caption
- }
-}
-
-
-// Scale up controls for tablets and up
-@media screen and (min-width: @screen-sm-min) {
-
- // Scale up the controls a smidge
- .carousel-control {
- .glyphicon-chevron-left,
- .glyphicon-chevron-right,
- .icon-prev,
- .icon-next {
- width: (@carousel-control-font-size * 1.5);
- height: (@carousel-control-font-size * 1.5);
- margin-top: (@carousel-control-font-size / -2);
- font-size: (@carousel-control-font-size * 1.5);
- }
- .glyphicon-chevron-left,
- .icon-prev {
- margin-left: (@carousel-control-font-size / -2);
- }
- .glyphicon-chevron-right,
- .icon-next {
- margin-right: (@carousel-control-font-size / -2);
- }
- }
-
- // Show and left align the captions
- .carousel-caption {
- left: 20%;
- right: 20%;
- padding-bottom: 30px;
- }
-
- // Move up the indicators
- .carousel-indicators {
- bottom: 20px;
- }
-}
diff --git a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/close.less b/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/close.less
deleted file mode 100755
index 6d5bfe087ae..00000000000
--- a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/close.less
+++ /dev/null
@@ -1,34 +0,0 @@
-//
-// Close icons
-// --------------------------------------------------
-
-
-.close {
- float: right;
- font-size: (@font-size-base * 1.5);
- font-weight: @close-font-weight;
- line-height: 1;
- color: @close-color;
- text-shadow: @close-text-shadow;
- .opacity(.2);
-
- &:hover,
- &:focus {
- color: @close-color;
- text-decoration: none;
- cursor: pointer;
- .opacity(.5);
- }
-
- // Additional properties for button version
- // iOS requires the button element instead of an anchor tag.
- // If you want the anchor version, it requires `href="#"`.
- // See https://developer.mozilla.org/en-US/docs/Web/Events/click#Safari_Mobile
- button& {
- padding: 0;
- cursor: pointer;
- background: transparent;
- border: 0;
- -webkit-appearance: none;
- }
-}
diff --git a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/code.less b/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/code.less
deleted file mode 100755
index a08b4d48c4c..00000000000
--- a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/code.less
+++ /dev/null
@@ -1,69 +0,0 @@
-//
-// Code (inline and block)
-// --------------------------------------------------
-
-
-// Inline and block code styles
-code,
-kbd,
-pre,
-samp {
- font-family: @font-family-monospace;
-}
-
-// Inline code
-code {
- padding: 2px 4px;
- font-size: 90%;
- color: @code-color;
- background-color: @code-bg;
- border-radius: @border-radius-base;
-}
-
-// User input typically entered via keyboard
-kbd {
- padding: 2px 4px;
- font-size: 90%;
- color: @kbd-color;
- background-color: @kbd-bg;
- border-radius: @border-radius-small;
- box-shadow: inset 0 -1px 0 rgba(0,0,0,.25);
-
- kbd {
- padding: 0;
- font-size: 100%;
- font-weight: bold;
- box-shadow: none;
- }
-}
-
-// Blocks of code
-pre {
- display: block;
- padding: ((@line-height-computed - 1) / 2);
- margin: 0 0 (@line-height-computed / 2);
- font-size: (@font-size-base - 1); // 14px to 13px
- line-height: @line-height-base;
- word-break: break-all;
- word-wrap: break-word;
- color: @pre-color;
- background-color: @pre-bg;
- border: 1px solid @pre-border-color;
- border-radius: @border-radius-base;
-
- // Account for some code outputs that place code tags in pre tags
- code {
- padding: 0;
- font-size: inherit;
- color: inherit;
- white-space: pre-wrap;
- background-color: transparent;
- border-radius: 0;
- }
-}
-
-// Enable scrollable blocks of code
-.pre-scrollable {
- max-height: @pre-scrollable-max-height;
- overflow-y: scroll;
-}
diff --git a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/component-animations.less b/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/component-animations.less
deleted file mode 100755
index 0bcee910ac5..00000000000
--- a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/component-animations.less
+++ /dev/null
@@ -1,33 +0,0 @@
-//
-// Component animations
-// --------------------------------------------------
-
-// Heads up!
-//
-// We don't use the `.opacity()` mixin here since it causes a bug with text
-// fields in IE7-8. Source: https://github.com/twbs/bootstrap/pull/3552.
-
-.fade {
- opacity: 0;
- .transition(opacity .15s linear);
- &.in {
- opacity: 1;
- }
-}
-
-.collapse {
- display: none;
-
- &.in { display: block; }
- tr&.in { display: table-row; }
- tbody&.in { display: table-row-group; }
-}
-
-.collapsing {
- position: relative;
- height: 0;
- overflow: hidden;
- .transition-property(~"height, visibility");
- .transition-duration(.35s);
- .transition-timing-function(ease);
-}
diff --git a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/dropdowns.less b/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/dropdowns.less
deleted file mode 100755
index f6876c1a9b2..00000000000
--- a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/dropdowns.less
+++ /dev/null
@@ -1,216 +0,0 @@
-//
-// Dropdown menus
-// --------------------------------------------------
-
-
-// Dropdown arrow/caret
-.caret {
- display: inline-block;
- width: 0;
- height: 0;
- margin-left: 2px;
- vertical-align: middle;
- border-top: @caret-width-base dashed;
- border-top: @caret-width-base solid ~"\9"; // IE8
- border-right: @caret-width-base solid transparent;
- border-left: @caret-width-base solid transparent;
-}
-
-// The dropdown wrapper (div)
-.dropup,
-.dropdown {
- position: relative;
-}
-
-// Prevent the focus on the dropdown toggle when closing dropdowns
-.dropdown-toggle:focus {
- outline: 0;
-}
-
-// The dropdown menu (ul)
-.dropdown-menu {
- position: absolute;
- top: 100%;
- left: 0;
- z-index: @zindex-dropdown;
- display: none; // none by default, but block on "open" of the menu
- float: left;
- min-width: 160px;
- padding: 5px 0;
- margin: 2px 0 0; // override default ul
- list-style: none;
- font-size: @font-size-base;
- text-align: left; // Ensures proper alignment if parent has it changed (e.g., modal footer)
- background-color: @dropdown-bg;
- border: 1px solid @dropdown-fallback-border; // IE8 fallback
- border: 1px solid @dropdown-border;
- border-radius: @border-radius-base;
- .box-shadow(0 6px 12px rgba(0,0,0,.175));
- background-clip: padding-box;
-
- // Aligns the dropdown menu to right
- //
- // Deprecated as of 3.1.0 in favor of `.dropdown-menu-[dir]`
- &.pull-right {
- right: 0;
- left: auto;
- }
-
- // Dividers (basically an hr) within the dropdown
- .divider {
- .nav-divider(@dropdown-divider-bg);
- }
-
- // Links within the dropdown menu
- > li > a {
- display: block;
- padding: 3px 20px;
- clear: both;
- font-weight: normal;
- line-height: @line-height-base;
- color: @dropdown-link-color;
- white-space: nowrap; // prevent links from randomly breaking onto new lines
- }
-}
-
-// Hover/Focus state
-.dropdown-menu > li > a {
- &:hover,
- &:focus {
- text-decoration: none;
- color: @dropdown-link-hover-color;
- background-color: @dropdown-link-hover-bg;
- }
-}
-
-// Active state
-.dropdown-menu > .active > a {
- &,
- &:hover,
- &:focus {
- color: @dropdown-link-active-color;
- text-decoration: none;
- outline: 0;
- background-color: @dropdown-link-active-bg;
- }
-}
-
-// Disabled state
-//
-// Gray out text and ensure the hover/focus state remains gray
-
-.dropdown-menu > .disabled > a {
- &,
- &:hover,
- &:focus {
- color: @dropdown-link-disabled-color;
- }
-
- // Nuke hover/focus effects
- &:hover,
- &:focus {
- text-decoration: none;
- background-color: transparent;
- background-image: none; // Remove CSS gradient
- .reset-filter();
- cursor: @cursor-disabled;
- }
-}
-
-// Open state for the dropdown
-.open {
- // Show the menu
- > .dropdown-menu {
- display: block;
- }
-
- // Remove the outline when :focus is triggered
- > a {
- outline: 0;
- }
-}
-
-// Menu positioning
-//
-// Add extra class to `.dropdown-menu` to flip the alignment of the dropdown
-// menu with the parent.
-.dropdown-menu-right {
- left: auto; // Reset the default from `.dropdown-menu`
- right: 0;
-}
-// With v3, we enabled auto-flipping if you have a dropdown within a right
-// aligned nav component. To enable the undoing of that, we provide an override
-// to restore the default dropdown menu alignment.
-//
-// This is only for left-aligning a dropdown menu within a `.navbar-right` or
-// `.pull-right` nav component.
-.dropdown-menu-left {
- left: 0;
- right: auto;
-}
-
-// Dropdown section headers
-.dropdown-header {
- display: block;
- padding: 3px 20px;
- font-size: @font-size-small;
- line-height: @line-height-base;
- color: @dropdown-header-color;
- white-space: nowrap; // as with > li > a
-}
-
-// Backdrop to catch body clicks on mobile, etc.
-.dropdown-backdrop {
- position: fixed;
- left: 0;
- right: 0;
- bottom: 0;
- top: 0;
- z-index: (@zindex-dropdown - 10);
-}
-
-// Right aligned dropdowns
-.pull-right > .dropdown-menu {
- right: 0;
- left: auto;
-}
-
-// Allow for dropdowns to go bottom up (aka, dropup-menu)
-//
-// Just add .dropup after the standard .dropdown class and you're set, bro.
-// TODO: abstract this so that the navbar fixed styles are not placed here?
-
-.dropup,
-.navbar-fixed-bottom .dropdown {
- // Reverse the caret
- .caret {
- border-top: 0;
- border-bottom: @caret-width-base dashed;
- border-bottom: @caret-width-base solid ~"\9"; // IE8
- content: "";
- }
- // Different positioning for bottom up menu
- .dropdown-menu {
- top: auto;
- bottom: 100%;
- margin-bottom: 2px;
- }
-}
-
-
-// Component alignment
-//
-// Reiterate per navbar.less and the modified component alignment there.
-
-@media (min-width: @grid-float-breakpoint) {
- .navbar-right {
- .dropdown-menu {
- .dropdown-menu-right();
- }
- // Necessary for overrides of the default right aligned menu.
- // Will remove come v4 in all likelihood.
- .dropdown-menu-left {
- .dropdown-menu-left();
- }
- }
-}
diff --git a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/forms.less b/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/forms.less
deleted file mode 100755
index e8b071a138e..00000000000
--- a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/forms.less
+++ /dev/null
@@ -1,613 +0,0 @@
-//
-// Forms
-// --------------------------------------------------
-
-
-// Normalize non-controls
-//
-// Restyle and baseline non-control form elements.
-
-fieldset {
- padding: 0;
- margin: 0;
- border: 0;
- // Chrome and Firefox set a `min-width: min-content;` on fieldsets,
- // so we reset that to ensure it behaves more like a standard block element.
- // See https://github.com/twbs/bootstrap/issues/12359.
- min-width: 0;
-}
-
-legend {
- display: block;
- width: 100%;
- padding: 0;
- margin-bottom: @line-height-computed;
- font-size: (@font-size-base * 1.5);
- line-height: inherit;
- color: @legend-color;
- border: 0;
- border-bottom: 1px solid @legend-border-color;
-}
-
-label {
- display: inline-block;
- max-width: 100%; // Force IE8 to wrap long content (see https://github.com/twbs/bootstrap/issues/13141)
- margin-bottom: 5px;
- font-weight: bold;
-}
-
-
-// Normalize form controls
-//
-// While most of our form styles require extra classes, some basic normalization
-// is required to ensure optimum display with or without those classes to better
-// address browser inconsistencies.
-
-// Override content-box in Normalize (* isn't specific enough)
-input[type="search"] {
- .box-sizing(border-box);
-}
-
-// Position radios and checkboxes better
-input[type="radio"],
-input[type="checkbox"] {
- margin: 4px 0 0;
- margin-top: 1px \9; // IE8-9
- line-height: normal;
-}
-
-input[type="file"] {
- display: block;
-}
-
-// Make range inputs behave like textual form controls
-input[type="range"] {
- display: block;
- width: 100%;
-}
-
-// Make multiple select elements height not fixed
-select[multiple],
-select[size] {
- height: auto;
-}
-
-// Focus for file, radio, and checkbox
-input[type="file"]:focus,
-input[type="radio"]:focus,
-input[type="checkbox"]:focus {
- .tab-focus();
-}
-
-// Adjust output element
-output {
- display: block;
- padding-top: (@padding-base-vertical + 1);
- font-size: @font-size-base;
- line-height: @line-height-base;
- color: @input-color;
-}
-
-
-// Common form controls
-//
-// Shared size and type resets for form controls. Apply `.form-control` to any
-// of the following form controls:
-//
-// select
-// textarea
-// input[type="text"]
-// input[type="password"]
-// input[type="datetime"]
-// input[type="datetime-local"]
-// input[type="date"]
-// input[type="month"]
-// input[type="time"]
-// input[type="week"]
-// input[type="number"]
-// input[type="email"]
-// input[type="url"]
-// input[type="search"]
-// input[type="tel"]
-// input[type="color"]
-
-.form-control {
- display: block;
- width: 100%;
- height: @input-height-base; // Make inputs at least the height of their button counterpart (base line-height + padding + border)
- padding: @padding-base-vertical @padding-base-horizontal;
- font-size: @font-size-base;
- line-height: @line-height-base;
- color: @input-color;
- background-color: @input-bg;
- background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214
- border: 1px solid @input-border;
- border-radius: @input-border-radius; // Note: This has no effect on <select>s in some browsers, due to the limited stylability of <select>s in CSS.
- .box-shadow(inset 0 1px 1px rgba(0,0,0,.075));
- .transition(~"border-color ease-in-out .15s, box-shadow ease-in-out .15s");
-
- // Customize the `:focus` state to imitate native WebKit styles.
- .form-control-focus();
-
- // Placeholder
- .placeholder();
-
- // Unstyle the caret on `<select>`s in IE10+.
- &::-ms-expand {
- border: 0;
- background-color: transparent;
- }
-
- // Disabled and read-only inputs
- //
- // HTML5 says that controls under a fieldset > legend:first-child won't be
- // disabled if the fieldset is disabled. Due to implementation difficulty, we
- // don't honor that edge case; we style them as disabled anyway.
- &[disabled],
- &[readonly],
- fieldset[disabled] & {
- background-color: @input-bg-disabled;
- opacity: 1; // iOS fix for unreadable disabled content; see https://github.com/twbs/bootstrap/issues/11655
- }
-
- &[disabled],
- fieldset[disabled] & {
- cursor: @cursor-disabled;
- }
-
- // Reset height for `textarea`s
- textarea& {
- height: auto;
- }
-}
-
-
-// Search inputs in iOS
-//
-// This overrides the extra rounded corners on search inputs in iOS so that our
-// `.form-control` class can properly style them. Note that this cannot simply
-// be added to `.form-control` as it's not specific enough. For details, see
-// https://github.com/twbs/bootstrap/issues/11586.
-
-input[type="search"] {
- -webkit-appearance: none;
-}
-
-
-// Special styles for iOS temporal inputs
-//
-// In Mobile Safari, setting `display: block` on temporal inputs causes the
-// text within the input to become vertically misaligned. As a workaround, we
-// set a pixel line-height that matches the given height of the input, but only
-// for Safari. See https://bugs.webkit.org/show_bug.cgi?id=139848
-//
-// Note that as of 8.3, iOS doesn't support `datetime` or `week`.
-
-@media screen and (-webkit-min-device-pixel-ratio: 0) {
- input[type="date"],
- input[type="time"],
- input[type="datetime-local"],
- input[type="month"] {
- &.form-control {
- line-height: @input-height-base;
- }
-
- &.input-sm,
- .input-group-sm & {
- line-height: @input-height-small;
- }
-
- &.input-lg,
- .input-group-lg & {
- line-height: @input-height-large;
- }
- }
-}
-
-
-// Form groups
-//
-// Designed to help with the organization and spacing of vertical forms. For
-// horizontal forms, use the predefined grid classes.
-
-.form-group {
- margin-bottom: @form-group-margin-bottom;
-}
-
-
-// Checkboxes and radios
-//
-// Indent the labels to position radios/checkboxes as hanging controls.
-
-.radio,
-.checkbox {
- position: relative;
- display: block;
- margin-top: 10px;
- margin-bottom: 10px;
-
- label {
- min-height: @line-height-computed; // Ensure the input doesn't jump when there is no text
- padding-left: 20px;
- margin-bottom: 0;
- font-weight: normal;
- cursor: pointer;
- }
-}
-.radio input[type="radio"],
-.radio-inline input[type="radio"],
-.checkbox input[type="checkbox"],
-.checkbox-inline input[type="checkbox"] {
- position: absolute;
- margin-left: -20px;
- margin-top: 4px \9;
-}
-
-.radio + .radio,
-.checkbox + .checkbox {
- margin-top: -5px; // Move up sibling radios or checkboxes for tighter spacing
-}
-
-// Radios and checkboxes on same line
-.radio-inline,
-.checkbox-inline {
- position: relative;
- display: inline-block;
- padding-left: 20px;
- margin-bottom: 0;
- vertical-align: middle;
- font-weight: normal;
- cursor: pointer;
-}
-.radio-inline + .radio-inline,
-.checkbox-inline + .checkbox-inline {
- margin-top: 0;
- margin-left: 10px; // space out consecutive inline controls
-}
-
-// Apply same disabled cursor tweak as for inputs
-// Some special care is needed because <label>s don't inherit their parent's `cursor`.
-//
-// Note: Neither radios nor checkboxes can be readonly.
-input[type="radio"],
-input[type="checkbox"] {
- &[disabled],
- &.disabled,
- fieldset[disabled] & {
- cursor: @cursor-disabled;
- }
-}
-// These classes are used directly on <label>s
-.radio-inline,
-.checkbox-inline {
- &.disabled,
- fieldset[disabled] & {
- cursor: @cursor-disabled;
- }
-}
-// These classes are used on elements with <label> descendants
-.radio,
-.checkbox {
- &.disabled,
- fieldset[disabled] & {
- label {
- cursor: @cursor-disabled;
- }
- }
-}
-
-
-// Static form control text
-//
-// Apply class to a `p` element to make any string of text align with labels in
-// a horizontal form layout.
-
-.form-control-static {
- // Size it appropriately next to real form controls
- padding-top: (@padding-base-vertical + 1);
- padding-bottom: (@padding-base-vertical + 1);
- // Remove default margin from `p`
- margin-bottom: 0;
- min-height: (@line-height-computed + @font-size-base);
-
- &.input-lg,
- &.input-sm {
- padding-left: 0;
- padding-right: 0;
- }
-}
-
-
-// Form control sizing
-//
-// Build on `.form-control` with modifier classes to decrease or increase the
-// height and font-size of form controls.
-//
-// The `.form-group-* form-control` variations are sadly duplicated to avoid the
-// issue documented in https://github.com/twbs/bootstrap/issues/15074.
-
-.input-sm {
- .input-size(@input-height-small; @padding-small-vertical; @padding-small-horizontal; @font-size-small; @line-height-small; @input-border-radius-small);
-}
-.form-group-sm {
- .form-control {
- height: @input-height-small;
- padding: @padding-small-vertical @padding-small-horizontal;
- font-size: @font-size-small;
- line-height: @line-height-small;
- border-radius: @input-border-radius-small;
- }
- select.form-control {
- height: @input-height-small;
- line-height: @input-height-small;
- }
- textarea.form-control,
- select[multiple].form-control {
- height: auto;
- }
- .form-control-static {
- height: @input-height-small;
- min-height: (@line-height-computed + @font-size-small);
- padding: (@padding-small-vertical + 1) @padding-small-horizontal;
- font-size: @font-size-small;
- line-height: @line-height-small;
- }
-}
-
-.input-lg {
- .input-size(@input-height-large; @padding-large-vertical; @padding-large-horizontal; @font-size-large; @line-height-large; @input-border-radius-large);
-}
-.form-group-lg {
- .form-control {
- height: @input-height-large;
- padding: @padding-large-vertical @padding-large-horizontal;
- font-size: @font-size-large;
- line-height: @line-height-large;
- border-radius: @input-border-radius-large;
- }
- select.form-control {
- height: @input-height-large;
- line-height: @input-height-large;
- }
- textarea.form-control,
- select[multiple].form-control {
- height: auto;
- }
- .form-control-static {
- height: @input-height-large;
- min-height: (@line-height-computed + @font-size-large);
- padding: (@padding-large-vertical + 1) @padding-large-horizontal;
- font-size: @font-size-large;
- line-height: @line-height-large;
- }
-}
-
-
-// Form control feedback states
-//
-// Apply contextual and semantic states to individual form controls.
-
-.has-feedback {
- // Enable absolute positioning
- position: relative;
-
- // Ensure icons don't overlap text
- .form-control {
- padding-right: (@input-height-base * 1.25);
- }
-}
-// Feedback icon (requires .glyphicon classes)
-.form-control-feedback {
- position: absolute;
- top: 0;
- right: 0;
- z-index: 2; // Ensure icon is above input groups
- display: block;
- width: @input-height-base;
- height: @input-height-base;
- line-height: @input-height-base;
- text-align: center;
- pointer-events: none;
-}
-.input-lg + .form-control-feedback,
-.input-group-lg + .form-control-feedback,
-.form-group-lg .form-control + .form-control-feedback {
- width: @input-height-large;
- height: @input-height-large;
- line-height: @input-height-large;
-}
-.input-sm + .form-control-feedback,
-.input-group-sm + .form-control-feedback,
-.form-group-sm .form-control + .form-control-feedback {
- width: @input-height-small;
- height: @input-height-small;
- line-height: @input-height-small;
-}
-
-// Feedback states
-.has-success {
- .form-control-validation(@state-success-text; @state-success-text; @state-success-bg);
-}
-.has-warning {
- .form-control-validation(@state-warning-text; @state-warning-text; @state-warning-bg);
-}
-.has-error {
- .form-control-validation(@state-danger-text; @state-danger-text; @state-danger-bg);
-}
-
-// Reposition feedback icon if input has visible label above
-.has-feedback label {
-
- & ~ .form-control-feedback {
- top: (@line-height-computed + 5); // Height of the `label` and its margin
- }
- &.sr-only ~ .form-control-feedback {
- top: 0;
- }
-}
-
-
-// Help text
-//
-// Apply to any element you wish to create light text for placement immediately
-// below a form control. Use for general help, formatting, or instructional text.
-
-.help-block {
- display: block; // account for any element using help-block
- margin-top: 5px;
- margin-bottom: 10px;
- color: lighten(@text-color, 25%); // lighten the text some for contrast
-}
-
-
-// Inline forms
-//
-// Make forms appear inline(-block) by adding the `.form-inline` class. Inline
-// forms begin stacked on extra small (mobile) devices and then go inline when
-// viewports reach <768px.
-//
-// Requires wrapping inputs and labels with `.form-group` for proper display of
-// default HTML form controls and our custom form controls (e.g., input groups).
-//
-// Heads up! This is mixin-ed into `.navbar-form` in navbars.less.
-
-.form-inline {
-
- // Kick in the inline
- @media (min-width: @screen-sm-min) {
- // Inline-block all the things for "inline"
- .form-group {
- display: inline-block;
- margin-bottom: 0;
- vertical-align: middle;
- }
-
- // In navbar-form, allow folks to *not* use `.form-group`
- .form-control {
- display: inline-block;
- width: auto; // Prevent labels from stacking above inputs in `.form-group`
- vertical-align: middle;
- }
-
- // Make static controls behave like regular ones
- .form-control-static {
- display: inline-block;
- }
-
- .input-group {
- display: inline-table;
- vertical-align: middle;
-
- .input-group-addon,
- .input-group-btn,
- .form-control {
- width: auto;
- }
- }
-
- // Input groups need that 100% width though
- .input-group > .form-control {
- width: 100%;
- }
-
- .control-label {
- margin-bottom: 0;
- vertical-align: middle;
- }
-
- // Remove default margin on radios/checkboxes that were used for stacking, and
- // then undo the floating of radios and checkboxes to match.
- .radio,
- .checkbox {
- display: inline-block;
- margin-top: 0;
- margin-bottom: 0;
- vertical-align: middle;
-
- label {
- padding-left: 0;
- }
- }
- .radio input[type="radio"],
- .checkbox input[type="checkbox"] {
- position: relative;
- margin-left: 0;
- }
-
- // Re-override the feedback icon.
- .has-feedback .form-control-feedback {
- top: 0;
- }
- }
-}
-
-
-// Horizontal forms
-//
-// Horizontal forms are built on grid classes and allow you to create forms with
-// labels on the left and inputs on the right.
-
-.form-horizontal {
-
- // Consistent vertical alignment of radios and checkboxes
- //
- // Labels also get some reset styles, but that is scoped to a media query below.
- .radio,
- .checkbox,
- .radio-inline,
- .checkbox-inline {
- margin-top: 0;
- margin-bottom: 0;
- padding-top: (@padding-base-vertical + 1); // Default padding plus a border
- }
- // Account for padding we're adding to ensure the alignment and of help text
- // and other content below items
- .radio,
- .checkbox {
- min-height: (@line-height-computed + (@padding-base-vertical + 1));
- }
-
- // Make form groups behave like rows
- .form-group {
- .make-row();
- }
-
- // Reset spacing and right align labels, but scope to media queries so that
- // labels on narrow viewports stack the same as a default form example.
- @media (min-width: @screen-sm-min) {
- .control-label {
- text-align: right;
- margin-bottom: 0;
- padding-top: (@padding-base-vertical + 1); // Default padding plus a border
- }
- }
-
- // Validation states
- //
- // Reposition the icon because it's now within a grid column and columns have
- // `position: relative;` on them. Also accounts for the grid gutter padding.
- .has-feedback .form-control-feedback {
- right: floor((@grid-gutter-width / 2));
- }
-
- // Form group sizes
- //
- // Quick utility class for applying `.input-lg` and `.input-sm` styles to the
- // inputs and labels within a `.form-group`.
- .form-group-lg {
- @media (min-width: @screen-sm-min) {
- .control-label {
- padding-top: (@padding-large-vertical + 1);
- font-size: @font-size-large;
- }
- }
- }
- .form-group-sm {
- @media (min-width: @screen-sm-min) {
- .control-label {
- padding-top: (@padding-small-vertical + 1);
- font-size: @font-size-small;
- }
- }
- }
-}
diff --git a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/glyphicons.less b/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/glyphicons.less
deleted file mode 100755
index 7bc5852d2c0..00000000000
--- a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/glyphicons.less
+++ /dev/null
@@ -1,305 +0,0 @@
-//
-// Glyphicons for Bootstrap
-//
-// Since icons are fonts, they can be placed anywhere text is placed and are
-// thus automatically sized to match the surrounding child. To use, create an
-// inline element with the appropriate classes, like so:
-//
-// <a href="#"><span class="glyphicon glyphicon-star"></span> Star</a>
-
-// Import the fonts
-@font-face {
- font-family: 'Glyphicons Halflings';
- src: url('@{icon-font-path}@{icon-font-name}.eot');
- src: url('@{icon-font-path}@{icon-font-name}.eot?#iefix') format('embedded-opentype'),
- url('@{icon-font-path}@{icon-font-name}.woff2') format('woff2'),
- url('@{icon-font-path}@{icon-font-name}.woff') format('woff'),
- url('@{icon-font-path}@{icon-font-name}.ttf') format('truetype'),
- url('@{icon-font-path}@{icon-font-name}.svg#@{icon-font-svg-id}') format('svg');
-}
-
-// Catchall baseclass
-.glyphicon {
- position: relative;
- top: 1px;
- display: inline-block;
- font-family: 'Glyphicons Halflings';
- font-style: normal;
- font-weight: normal;
- line-height: 1;
- -webkit-font-smoothing: antialiased;
- -moz-osx-font-smoothing: grayscale;
-}
-
-// Individual icons
-.glyphicon-asterisk { &:before { content: "\002a"; } }
-.glyphicon-plus { &:before { content: "\002b"; } }
-.glyphicon-euro,
-.glyphicon-eur { &:before { content: "\20ac"; } }
-.glyphicon-minus { &:before { content: "\2212"; } }
-.glyphicon-cloud { &:before { content: "\2601"; } }
-.glyphicon-envelope { &:before { content: "\2709"; } }
-.glyphicon-pencil { &:before { content: "\270f"; } }
-.glyphicon-glass { &:before { content: "\e001"; } }
-.glyphicon-music { &:before { content: "\e002"; } }
-.glyphicon-search { &:before { content: "\e003"; } }
-.glyphicon-heart { &:before { content: "\e005"; } }
-.glyphicon-star { &:before { content: "\e006"; } }
-.glyphicon-star-empty { &:before { content: "\e007"; } }
-.glyphicon-user { &:before { content: "\e008"; } }
-.glyphicon-film { &:before { content: "\e009"; } }
-.glyphicon-th-large { &:before { content: "\e010"; } }
-.glyphicon-th { &:before { content: "\e011"; } }
-.glyphicon-th-list { &:before { content: "\e012"; } }
-.glyphicon-ok { &:before { content: "\e013"; } }
-.glyphicon-remove { &:before { content: "\e014"; } }
-.glyphicon-zoom-in { &:before { content: "\e015"; } }
-.glyphicon-zoom-out { &:before { content: "\e016"; } }
-.glyphicon-off { &:before { content: "\e017"; } }
-.glyphicon-signal { &:before { content: "\e018"; } }
-.glyphicon-cog { &:before { content: "\e019"; } }
-.glyphicon-trash { &:before { content: "\e020"; } }
-.glyphicon-home { &:before { content: "\e021"; } }
-.glyphicon-file { &:before { content: "\e022"; } }
-.glyphicon-time { &:before { content: "\e023"; } }
-.glyphicon-road { &:before { content: "\e024"; } }
-.glyphicon-download-alt { &:before { content: "\e025"; } }
-.glyphicon-download { &:before { content: "\e026"; } }
-.glyphicon-upload { &:before { content: "\e027"; } }
-.glyphicon-inbox { &:before { content: "\e028"; } }
-.glyphicon-play-circle { &:before { content: "\e029"; } }
-.glyphicon-repeat { &:before { content: "\e030"; } }
-.glyphicon-refresh { &:before { content: "\e031"; } }
-.glyphicon-list-alt { &:before { content: "\e032"; } }
-.glyphicon-lock { &:before { content: "\e033"; } }
-.glyphicon-flag { &:before { content: "\e034"; } }
-.glyphicon-headphones { &:before { content: "\e035"; } }
-.glyphicon-volume-off { &:before { content: "\e036"; } }
-.glyphicon-volume-down { &:before { content: "\e037"; } }
-.glyphicon-volume-up { &:before { content: "\e038"; } }
-.glyphicon-qrcode { &:before { content: "\e039"; } }
-.glyphicon-barcode { &:before { content: "\e040"; } }
-.glyphicon-tag { &:before { content: "\e041"; } }
-.glyphicon-tags { &:before { content: "\e042"; } }
-.glyphicon-book { &:before { content: "\e043"; } }
-.glyphicon-bookmark { &:before { content: "\e044"; } }
-.glyphicon-print { &:before { content: "\e045"; } }
-.glyphicon-camera { &:before { content: "\e046"; } }
-.glyphicon-font { &:before { content: "\e047"; } }
-.glyphicon-bold { &:before { content: "\e048"; } }
-.glyphicon-italic { &:before { content: "\e049"; } }
-.glyphicon-text-height { &:before { content: "\e050"; } }
-.glyphicon-text-width { &:before { content: "\e051"; } }
-.glyphicon-align-left { &:before { content: "\e052"; } }
-.glyphicon-align-center { &:before { content: "\e053"; } }
-.glyphicon-align-right { &:before { content: "\e054"; } }
-.glyphicon-align-justify { &:before { content: "\e055"; } }
-.glyphicon-list { &:before { content: "\e056"; } }
-.glyphicon-indent-left { &:before { content: "\e057"; } }
-.glyphicon-indent-right { &:before { content: "\e058"; } }
-.glyphicon-facetime-video { &:before { content: "\e059"; } }
-.glyphicon-picture { &:before { content: "\e060"; } }
-.glyphicon-map-marker { &:before { content: "\e062"; } }
-.glyphicon-adjust { &:before { content: "\e063"; } }
-.glyphicon-tint { &:before { content: "\e064"; } }
-.glyphicon-edit { &:before { content: "\e065"; } }
-.glyphicon-share { &:before { content: "\e066"; } }
-.glyphicon-check { &:before { content: "\e067"; } }
-.glyphicon-move { &:before { content: "\e068"; } }
-.glyphicon-step-backward { &:before { content: "\e069"; } }
-.glyphicon-fast-backward { &:before { content: "\e070"; } }
-.glyphicon-backward { &:before { content: "\e071"; } }
-.glyphicon-play { &:before { content: "\e072"; } }
-.glyphicon-pause { &:before { content: "\e073"; } }
-.glyphicon-stop { &:before { content: "\e074"; } }
-.glyphicon-forward { &:before { content: "\e075"; } }
-.glyphicon-fast-forward { &:before { content: "\e076"; } }
-.glyphicon-step-forward { &:before { content: "\e077"; } }
-.glyphicon-eject { &:before { content: "\e078"; } }
-.glyphicon-chevron-left { &:before { content: "\e079"; } }
-.glyphicon-chevron-right { &:before { content: "\e080"; } }
-.glyphicon-plus-sign { &:before { content: "\e081"; } }
-.glyphicon-minus-sign { &:before { content: "\e082"; } }
-.glyphicon-remove-sign { &:before { content: "\e083"; } }
-.glyphicon-ok-sign { &:before { content: "\e084"; } }
-.glyphicon-question-sign { &:before { content: "\e085"; } }
-.glyphicon-info-sign { &:before { content: "\e086"; } }
-.glyphicon-screenshot { &:before { content: "\e087"; } }
-.glyphicon-remove-circle { &:before { content: "\e088"; } }
-.glyphicon-ok-circle { &:before { content: "\e089"; } }
-.glyphicon-ban-circle { &:before { content: "\e090"; } }
-.glyphicon-arrow-left { &:before { content: "\e091"; } }
-.glyphicon-arrow-right { &:before { content: "\e092"; } }
-.glyphicon-arrow-up { &:before { content: "\e093"; } }
-.glyphicon-arrow-down { &:before { content: "\e094"; } }
-.glyphicon-share-alt { &:before { content: "\e095"; } }
-.glyphicon-resize-full { &:before { content: "\e096"; } }
-.glyphicon-resize-small { &:before { content: "\e097"; } }
-.glyphicon-exclamation-sign { &:before { content: "\e101"; } }
-.glyphicon-gift { &:before { content: "\e102"; } }
-.glyphicon-leaf { &:before { content: "\e103"; } }
-.glyphicon-fire { &:before { content: "\e104"; } }
-.glyphicon-eye-open { &:before { content: "\e105"; } }
-.glyphicon-eye-close { &:before { content: "\e106"; } }
-.glyphicon-warning-sign { &:before { content: "\e107"; } }
-.glyphicon-plane { &:before { content: "\e108"; } }
-.glyphicon-calendar { &:before { content: "\e109"; } }
-.glyphicon-random { &:before { content: "\e110"; } }
-.glyphicon-comment { &:before { content: "\e111"; } }
-.glyphicon-magnet { &:before { content: "\e112"; } }
-.glyphicon-chevron-up { &:before { content: "\e113"; } }
-.glyphicon-chevron-down { &:before { content: "\e114"; } }
-.glyphicon-retweet { &:before { content: "\e115"; } }
-.glyphicon-shopping-cart { &:before { content: "\e116"; } }
-.glyphicon-folder-close { &:before { content: "\e117"; } }
-.glyphicon-folder-open { &:before { content: "\e118"; } }
-.glyphicon-resize-vertical { &:before { content: "\e119"; } }
-.glyphicon-resize-horizontal { &:before { content: "\e120"; } }
-.glyphicon-hdd { &:before { content: "\e121"; } }
-.glyphicon-bullhorn { &:before { content: "\e122"; } }
-.glyphicon-bell { &:before { content: "\e123"; } }
-.glyphicon-certificate { &:before { content: "\e124"; } }
-.glyphicon-thumbs-up { &:before { content: "\e125"; } }
-.glyphicon-thumbs-down { &:before { content: "\e126"; } }
-.glyphicon-hand-right { &:before { content: "\e127"; } }
-.glyphicon-hand-left { &:before { content: "\e128"; } }
-.glyphicon-hand-up { &:before { content: "\e129"; } }
-.glyphicon-hand-down { &:before { content: "\e130"; } }
-.glyphicon-circle-arrow-right { &:before { content: "\e131"; } }
-.glyphicon-circle-arrow-left { &:before { content: "\e132"; } }
-.glyphicon-circle-arrow-up { &:before { content: "\e133"; } }
-.glyphicon-circle-arrow-down { &:before { content: "\e134"; } }
-.glyphicon-globe { &:before { content: "\e135"; } }
-.glyphicon-wrench { &:before { content: "\e136"; } }
-.glyphicon-tasks { &:before { content: "\e137"; } }
-.glyphicon-filter { &:before { content: "\e138"; } }
-.glyphicon-briefcase { &:before { content: "\e139"; } }
-.glyphicon-fullscreen { &:before { content: "\e140"; } }
-.glyphicon-dashboard { &:before { content: "\e141"; } }
-.glyphicon-paperclip { &:before { content: "\e142"; } }
-.glyphicon-heart-empty { &:before { content: "\e143"; } }
-.glyphicon-link { &:before { content: "\e144"; } }
-.glyphicon-phone { &:before { content: "\e145"; } }
-.glyphicon-pushpin { &:before { content: "\e146"; } }
-.glyphicon-usd { &:before { content: "\e148"; } }
-.glyphicon-gbp { &:before { content: "\e149"; } }
-.glyphicon-sort { &:before { content: "\e150"; } }
-.glyphicon-sort-by-alphabet { &:before { content: "\e151"; } }
-.glyphicon-sort-by-alphabet-alt { &:before { content: "\e152"; } }
-.glyphicon-sort-by-order { &:before { content: "\e153"; } }
-.glyphicon-sort-by-order-alt { &:before { content: "\e154"; } }
-.glyphicon-sort-by-attributes { &:before { content: "\e155"; } }
-.glyphicon-sort-by-attributes-alt { &:before { content: "\e156"; } }
-.glyphicon-unchecked { &:before { content: "\e157"; } }
-.glyphicon-expand { &:before { content: "\e158"; } }
-.glyphicon-collapse-down { &:before { content: "\e159"; } }
-.glyphicon-collapse-up { &:before { content: "\e160"; } }
-.glyphicon-log-in { &:before { content: "\e161"; } }
-.glyphicon-flash { &:before { content: "\e162"; } }
-.glyphicon-log-out { &:before { content: "\e163"; } }
-.glyphicon-new-window { &:before { content: "\e164"; } }
-.glyphicon-record { &:before { content: "\e165"; } }
-.glyphicon-save { &:before { content: "\e166"; } }
-.glyphicon-open { &:before { content: "\e167"; } }
-.glyphicon-saved { &:before { content: "\e168"; } }
-.glyphicon-import { &:before { content: "\e169"; } }
-.glyphicon-export { &:before { content: "\e170"; } }
-.glyphicon-send { &:before { content: "\e171"; } }
-.glyphicon-floppy-disk { &:before { content: "\e172"; } }
-.glyphicon-floppy-saved { &:before { content: "\e173"; } }
-.glyphicon-floppy-remove { &:before { content: "\e174"; } }
-.glyphicon-floppy-save { &:before { content: "\e175"; } }
-.glyphicon-floppy-open { &:before { content: "\e176"; } }
-.glyphicon-credit-card { &:before { content: "\e177"; } }
-.glyphicon-transfer { &:before { content: "\e178"; } }
-.glyphicon-cutlery { &:before { content: "\e179"; } }
-.glyphicon-header { &:before { content: "\e180"; } }
-.glyphicon-compressed { &:before { content: "\e181"; } }
-.glyphicon-earphone { &:before { content: "\e182"; } }
-.glyphicon-phone-alt { &:before { content: "\e183"; } }
-.glyphicon-tower { &:before { content: "\e184"; } }
-.glyphicon-stats { &:before { content: "\e185"; } }
-.glyphicon-sd-video { &:before { content: "\e186"; } }
-.glyphicon-hd-video { &:before { content: "\e187"; } }
-.glyphicon-subtitles { &:before { content: "\e188"; } }
-.glyphicon-sound-stereo { &:before { content: "\e189"; } }
-.glyphicon-sound-dolby { &:before { content: "\e190"; } }
-.glyphicon-sound-5-1 { &:before { content: "\e191"; } }
-.glyphicon-sound-6-1 { &:before { content: "\e192"; } }
-.glyphicon-sound-7-1 { &:before { content: "\e193"; } }
-.glyphicon-copyright-mark { &:before { content: "\e194"; } }
-.glyphicon-registration-mark { &:before { content: "\e195"; } }
-.glyphicon-cloud-download { &:before { content: "\e197"; } }
-.glyphicon-cloud-upload { &:before { content: "\e198"; } }
-.glyphicon-tree-conifer { &:before { content: "\e199"; } }
-.glyphicon-tree-deciduous { &:before { content: "\e200"; } }
-.glyphicon-cd { &:before { content: "\e201"; } }
-.glyphicon-save-file { &:before { content: "\e202"; } }
-.glyphicon-open-file { &:before { content: "\e203"; } }
-.glyphicon-level-up { &:before { content: "\e204"; } }
-.glyphicon-copy { &:before { content: "\e205"; } }
-.glyphicon-paste { &:before { content: "\e206"; } }
-// The following 2 Glyphicons are omitted for the time being because
-// they currently use Unicode codepoints that are outside the
-// Basic Multilingual Plane (BMP). Older buggy versions of WebKit can't handle
-// non-BMP codepoints in CSS string escapes, and thus can't display these two icons.
-// Notably, the bug affects some older versions of the Android Browser.
-// More info: https://github.com/twbs/bootstrap/issues/10106
-// .glyphicon-door { &:before { content: "\1f6aa"; } }
-// .glyphicon-key { &:before { content: "\1f511"; } }
-.glyphicon-alert { &:before { content: "\e209"; } }
-.glyphicon-equalizer { &:before { content: "\e210"; } }
-.glyphicon-king { &:before { content: "\e211"; } }
-.glyphicon-queen { &:before { content: "\e212"; } }
-.glyphicon-pawn { &:before { content: "\e213"; } }
-.glyphicon-bishop { &:before { content: "\e214"; } }
-.glyphicon-knight { &:before { content: "\e215"; } }
-.glyphicon-baby-formula { &:before { content: "\e216"; } }
-.glyphicon-tent { &:before { content: "\26fa"; } }
-.glyphicon-blackboard { &:before { content: "\e218"; } }
-.glyphicon-bed { &:before { content: "\e219"; } }
-.glyphicon-apple { &:before { content: "\f8ff"; } }
-.glyphicon-erase { &:before { content: "\e221"; } }
-.glyphicon-hourglass { &:before { content: "\231b"; } }
-.glyphicon-lamp { &:before { content: "\e223"; } }
-.glyphicon-duplicate { &:before { content: "\e224"; } }
-.glyphicon-piggy-bank { &:before { content: "\e225"; } }
-.glyphicon-scissors { &:before { content: "\e226"; } }
-.glyphicon-bitcoin { &:before { content: "\e227"; } }
-.glyphicon-btc { &:before { content: "\e227"; } }
-.glyphicon-xbt { &:before { content: "\e227"; } }
-.glyphicon-yen { &:before { content: "\00a5"; } }
-.glyphicon-jpy { &:before { content: "\00a5"; } }
-.glyphicon-ruble { &:before { content: "\20bd"; } }
-.glyphicon-rub { &:before { content: "\20bd"; } }
-.glyphicon-scale { &:before { content: "\e230"; } }
-.glyphicon-ice-lolly { &:before { content: "\e231"; } }
-.glyphicon-ice-lolly-tasted { &:before { content: "\e232"; } }
-.glyphicon-education { &:before { content: "\e233"; } }
-.glyphicon-option-horizontal { &:before { content: "\e234"; } }
-.glyphicon-option-vertical { &:before { content: "\e235"; } }
-.glyphicon-menu-hamburger { &:before { content: "\e236"; } }
-.glyphicon-modal-window { &:before { content: "\e237"; } }
-.glyphicon-oil { &:before { content: "\e238"; } }
-.glyphicon-grain { &:before { content: "\e239"; } }
-.glyphicon-sunglasses { &:before { content: "\e240"; } }
-.glyphicon-text-size { &:before { content: "\e241"; } }
-.glyphicon-text-color { &:before { content: "\e242"; } }
-.glyphicon-text-background { &:before { content: "\e243"; } }
-.glyphicon-object-align-top { &:before { content: "\e244"; } }
-.glyphicon-object-align-bottom { &:before { content: "\e245"; } }
-.glyphicon-object-align-horizontal{ &:before { content: "\e246"; } }
-.glyphicon-object-align-left { &:before { content: "\e247"; } }
-.glyphicon-object-align-vertical { &:before { content: "\e248"; } }
-.glyphicon-object-align-right { &:before { content: "\e249"; } }
-.glyphicon-triangle-right { &:before { content: "\e250"; } }
-.glyphicon-triangle-left { &:before { content: "\e251"; } }
-.glyphicon-triangle-bottom { &:before { content: "\e252"; } }
-.glyphicon-triangle-top { &:before { content: "\e253"; } }
-.glyphicon-console { &:before { content: "\e254"; } }
-.glyphicon-superscript { &:before { content: "\e255"; } }
-.glyphicon-subscript { &:before { content: "\e256"; } }
-.glyphicon-menu-left { &:before { content: "\e257"; } }
-.glyphicon-menu-right { &:before { content: "\e258"; } }
-.glyphicon-menu-down { &:before { content: "\e259"; } }
-.glyphicon-menu-up { &:before { content: "\e260"; } }
diff --git a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/grid.less b/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/grid.less
deleted file mode 100755
index e100655b70e..00000000000
--- a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/grid.less
+++ /dev/null
@@ -1,84 +0,0 @@
-//
-// Grid system
-// --------------------------------------------------
-
-
-// Container widths
-//
-// Set the container width, and override it for fixed navbars in media queries.
-
-.container {
- .container-fixed();
-
- @media (min-width: @screen-sm-min) {
- width: @container-sm;
- }
- @media (min-width: @screen-md-min) {
- width: @container-md;
- }
- @media (min-width: @screen-lg-min) {
- width: @container-lg;
- }
-}
-
-
-// Fluid container
-//
-// Utilizes the mixin meant for fixed width containers, but without any defined
-// width for fluid, full width layouts.
-
-.container-fluid {
- .container-fixed();
-}
-
-
-// Row
-//
-// Rows contain and clear the floats of your columns.
-
-.row {
- .make-row();
-}
-
-
-// Columns
-//
-// Common styles for small and large grid columns
-
-.make-grid-columns();
-
-
-// Extra small grid
-//
-// Columns, offsets, pushes, and pulls for extra small devices like
-// smartphones.
-
-.make-grid(xs);
-
-
-// Small grid
-//
-// Columns, offsets, pushes, and pulls for the small device range, from phones
-// to tablets.
-
-@media (min-width: @screen-sm-min) {
- .make-grid(sm);
-}
-
-
-// Medium grid
-//
-// Columns, offsets, pushes, and pulls for the desktop device range.
-
-@media (min-width: @screen-md-min) {
- .make-grid(md);
-}
-
-
-// Large grid
-//
-// Columns, offsets, pushes, and pulls for the large desktop device range.
-
-@media (min-width: @screen-lg-min) {
- .make-grid(lg);
-}
diff --git a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/input-groups.less b/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/input-groups.less
deleted file mode 100755
index 5f73eec40ca..00000000000
--- a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/input-groups.less
+++ /dev/null
@@ -1,171 +0,0 @@
-//
-// Input groups
-// --------------------------------------------------
-
-// Base styles
-// -------------------------
-.input-group {
- position: relative; // For dropdowns
- display: table;
- border-collapse: separate; // prevent input groups from inheriting border styles from table cells when placed within a table
-
- // Undo padding and float of grid classes
- &[class*="col-"] {
- float: none;
- padding-left: 0;
- padding-right: 0;
- }
-
- .form-control {
- // Ensure that the input is always above the *appended* addon button for
- // proper border colors.
- position: relative;
- z-index: 2;
-
- // IE9 fubars the placeholder attribute in text inputs and the arrows on
- // select elements in input groups. To fix it, we float the input. Details:
- // https://github.com/twbs/bootstrap/issues/11561#issuecomment-28936855
- float: left;
-
- width: 100%;
- margin-bottom: 0;
-
- &:focus {
- z-index: 3;
- }
- }
-}
-
-// Sizing options
-//
-// Remix the default form control sizing classes into new ones for easier
-// manipulation.
-
-.input-group-lg > .form-control,
-.input-group-lg > .input-group-addon,
-.input-group-lg > .input-group-btn > .btn {
- .input-lg();
-}
-.input-group-sm > .form-control,
-.input-group-sm > .input-group-addon,
-.input-group-sm > .input-group-btn > .btn {
- .input-sm();
-}
-
-
-// Display as table-cell
-// -------------------------
-.input-group-addon,
-.input-group-btn,
-.input-group .form-control {
- display: table-cell;
-
- &:not(:first-child):not(:last-child) {
- border-radius: 0;
- }
-}
-// Addon and addon wrapper for buttons
-.input-group-addon,
-.input-group-btn {
- width: 1%;
- white-space: nowrap;
- vertical-align: middle; // Match the inputs
-}
-
-// Text input groups
-// -------------------------
-.input-group-addon {
- padding: @padding-base-vertical @padding-base-horizontal;
- font-size: @font-size-base;
- font-weight: normal;
- line-height: 1;
- color: @input-color;
- text-align: center;
- background-color: @input-group-addon-bg;
- border: 1px solid @input-group-addon-border-color;
- border-radius: @input-border-radius;
-
- // Sizing
- &.input-sm {
- padding: @padding-small-vertical @padding-small-horizontal;
- font-size: @font-size-small;
- border-radius: @input-border-radius-small;
- }
- &.input-lg {
- padding: @padding-large-vertical @padding-large-horizontal;
- font-size: @font-size-large;
- border-radius: @input-border-radius-large;
- }
-
- // Nuke default margins from checkboxes and radios to vertically center within.
- input[type="radio"],
- input[type="checkbox"] {
- margin-top: 0;
- }
-}
-
-// Reset rounded corners
-.input-group .form-control:first-child,
-.input-group-addon:first-child,
-.input-group-btn:first-child > .btn,
-.input-group-btn:first-child > .btn-group > .btn,
-.input-group-btn:first-child > .dropdown-toggle,
-.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle),
-.input-group-btn:last-child > .btn-group:not(:last-child) > .btn {
- .border-right-radius(0);
-}
-.input-group-addon:first-child {
- border-right: 0;
-}
-.input-group .form-control:last-child,
-.input-group-addon:last-child,
-.input-group-btn:last-child > .btn,
-.input-group-btn:last-child > .btn-group > .btn,
-.input-group-btn:last-child > .dropdown-toggle,
-.input-group-btn:first-child > .btn:not(:first-child),
-.input-group-btn:first-child > .btn-group:not(:first-child) > .btn {
- .border-left-radius(0);
-}
-.input-group-addon:last-child {
- border-left: 0;
-}
-
-// Button input groups
-// -------------------------
-.input-group-btn {
- position: relative;
- // Jankily prevent input button groups from wrapping with `white-space` and
- // `font-size` in combination with `inline-block` on buttons.
- font-size: 0;
- white-space: nowrap;
-
- // Negative margin for spacing, position for bringing hovered/focused/actived
- // element above the siblings.
- > .btn {
- position: relative;
- + .btn {
- margin-left: -1px;
- }
- // Bring the "active" button to the front
- &:hover,
- &:focus,
- &:active {
- z-index: 2;
- }
- }
-
- // Negative margin to only have a 1px border between the two
- &:first-child {
- > .btn,
- > .btn-group {
- margin-right: -1px;
- }
- }
- &:last-child {
- > .btn,
- > .btn-group {
- z-index: 2;
- margin-left: -1px;
- }
- }
-}
diff --git a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/jumbotron.less b/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/jumbotron.less
deleted file mode 100755
index 1d9b515b386..00000000000
--- a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/jumbotron.less
+++ /dev/null
@@ -1,54 +0,0 @@
-//
-// Jumbotron
-// --------------------------------------------------
-
-
-.jumbotron {
- padding-top: @jumbotron-padding;
- padding-bottom: @jumbotron-padding;
- margin-bottom: @jumbotron-padding;
- color: @jumbotron-color;
- background-color: @jumbotron-bg;
-
- h1,
- .h1 {
- color: @jumbotron-heading-color;
- }
-
- p {
- margin-bottom: (@jumbotron-padding / 2);
- font-size: @jumbotron-font-size;
- font-weight: 200;
- }
-
- > hr {
- border-top-color: darken(@jumbotron-bg, 10%);
- }
-
- .container &,
- .container-fluid & {
- border-radius: @border-radius-large; // Only round corners at higher resolutions if contained in a container
- padding-left: (@grid-gutter-width / 2);
- padding-right: (@grid-gutter-width / 2);
- }
-
- .container {
- max-width: 100%;
- }
-
- @media screen and (min-width: @screen-sm-min) {
- padding-top: (@jumbotron-padding * 1.6);
- padding-bottom: (@jumbotron-padding * 1.6);
-
- .container &,
- .container-fluid & {
- padding-left: (@jumbotron-padding * 2);
- padding-right: (@jumbotron-padding * 2);
- }
-
- h1,
- .h1 {
- font-size: @jumbotron-heading-font-size;
- }
- }
-}
diff --git a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/labels.less b/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/labels.less
deleted file mode 100755
index 9a5a27006a5..00000000000
--- a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/labels.less
+++ /dev/null
@@ -1,64 +0,0 @@
-//
-// Labels
-// --------------------------------------------------
-
-.label {
- display: inline;
- padding: .2em .6em .3em;
- font-size: 75%;
- font-weight: bold;
- line-height: 1;
- color: @label-color;
- text-align: center;
- white-space: nowrap;
- vertical-align: baseline;
- border-radius: .25em;
-
- // Add hover effects, but only for links
- a& {
- &:hover,
- &:focus {
- color: @label-link-hover-color;
- text-decoration: none;
- cursor: pointer;
- }
- }
-
- // Empty labels collapse automatically (not available in IE8)
- &:empty {
- display: none;
- }
-
- // Quick fix for labels in buttons
- .btn & {
- position: relative;
- top: -1px;
- }
-}
-
-// Colors
-// Contextual variations (linked labels get darker on :hover)
-
-.label-default {
- .label-variant(@label-default-bg);
-}
-
-.label-primary {
- .label-variant(@label-primary-bg);
-}
-
-.label-success {
- .label-variant(@label-success-bg);
-}
-
-.label-info {
- .label-variant(@label-info-bg);
-}
-
-.label-warning {
- .label-variant(@label-warning-bg);
-}
-
-.label-danger {
- .label-variant(@label-danger-bg);
-}
diff --git a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/list-group.less b/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/list-group.less
deleted file mode 100755
index 216b91230ab..00000000000
--- a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/list-group.less
+++ /dev/null
@@ -1,130 +0,0 @@
-//
-// List groups
-// --------------------------------------------------
-
-
-// Base class
-//
-// Easily usable on <ul>, <ol>, or <div>.
-
-.list-group {
- // No need to set list-style: none; since .list-group-item is block level
- margin-bottom: 20px;
- padding-left: 0; // reset padding because ul and ol
-}
-
-
-// Individual list items
-//
-// Use on `li`s or `div`s within the `.list-group` parent.
-
-.list-group-item {
- position: relative;
- display: block;
- padding: 10px 15px;
- // Place the border on the list items and negative margin up for better styling
- margin-bottom: -1px;
- background-color: @list-group-bg;
- border: 1px solid @list-group-border;
-
- // Round the first and last items
- &:first-child {
- .border-top-radius(@list-group-border-radius);
- }
- &:last-child {
- margin-bottom: 0;
- .border-bottom-radius(@list-group-border-radius);
- }
-}
-
-
-// Interactive list items
-//
-// Use anchor or button elements instead of `li`s or `div`s to create interactive items.
-// Includes an extra `.active` modifier class for showing selected items.
-
-a.list-group-item,
-button.list-group-item {
- color: @list-group-link-color;
-
- .list-group-item-heading {
- color: @list-group-link-heading-color;
- }
-
- // Hover state
- &:hover,
- &:focus {
- text-decoration: none;
- color: @list-group-link-hover-color;
- background-color: @list-group-hover-bg;
- }
-}
-
-button.list-group-item {
- width: 100%;
- text-align: left;
-}
-
-.list-group-item {
- // Disabled state
- &.disabled,
- &.disabled:hover,
- &.disabled:focus {
- background-color: @list-group-disabled-bg;
- color: @list-group-disabled-color;
- cursor: @cursor-disabled;
-
- // Force color to inherit for custom content
- .list-group-item-heading {
- color: inherit;
- }
- .list-group-item-text {
- color: @list-group-disabled-text-color;
- }
- }
-
- // Active class on item itself, not parent
- &.active,
- &.active:hover,
- &.active:focus {
- z-index: 2; // Place active items above their siblings for proper border styling
- color: @list-group-active-color;
- background-color: @list-group-active-bg;
- border-color: @list-group-active-border;
-
- // Force color to inherit for custom content
- .list-group-item-heading,
- .list-group-item-heading > small,
- .list-group-item-heading > .small {
- color: inherit;
- }
- .list-group-item-text {
- color: @list-group-active-text-color;
- }
- }
-}
-
-
-// Contextual variants
-//
-// Add modifier classes to change text and background color on individual items.
-// Organizationally, this must come after the `:hover` states.
-
-.list-group-item-variant(success; @state-success-bg; @state-success-text);
-.list-group-item-variant(info; @state-info-bg; @state-info-text);
-.list-group-item-variant(warning; @state-warning-bg; @state-warning-text);
-.list-group-item-variant(danger; @state-danger-bg; @state-danger-text);
-
-
-// Custom content options
-//
-// Extra classes for creating well-formatted content within `.list-group-item`s.
-
-.list-group-item-heading {
- margin-top: 0;
- margin-bottom: 5px;
-}
-.list-group-item-text {
- margin-bottom: 0;
- line-height: 1.3;
-}
diff --git a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/media.less b/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/media.less
deleted file mode 100755
index 8c835e861ed..00000000000
--- a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/media.less
+++ /dev/null
@@ -1,66 +0,0 @@
-.media {
- // Proper spacing between instances of .media
- margin-top: 15px;
-
- &:first-child {
- margin-top: 0;
- }
-}
-
-.media,
-.media-body {
- zoom: 1;
- overflow: hidden;
-}
-
-.media-body {
- width: 10000px;
-}
-
-.media-object {
- display: block;
-
- // Fix collapse in webkit from max-width: 100% and display: table-cell.
- &.img-thumbnail {
- max-width: none;
- }
-}
-
-.media-right,
-.media > .pull-right {
- padding-left: 10px;
-}
-
-.media-left,
-.media > .pull-left {
- padding-right: 10px;
-}
-
-.media-left,
-.media-right,
-.media-body {
- display: table-cell;
- vertical-align: top;
-}
-
-.media-middle {
- vertical-align: middle;
-}
-
-.media-bottom {
- vertical-align: bottom;
-}
-
-// Reset margins on headings for tighter default spacing
-.media-heading {
- margin-top: 0;
- margin-bottom: 5px;
-}
-
-// Media list variation
-//
-// Undo default ul/ol styles
-.media-list {
- padding-left: 0;
- list-style: none;
-}
diff --git a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins.less b/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins.less
deleted file mode 100755
index e6f9fe684b7..00000000000
--- a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins.less
+++ /dev/null
@@ -1,40 +0,0 @@
-// Mixins
-// --------------------------------------------------
-
-// Utilities
-@import "mixins/hide-text.less";
-@import "mixins/opacity.less";
-@import "mixins/image.less";
-@import "mixins/labels.less";
-@import "mixins/reset-filter.less";
-@import "mixins/resize.less";
-@import "mixins/responsive-visibility.less";
-@import "mixins/size.less";
-@import "mixins/tab-focus.less";
-@import "mixins/reset-text.less";
-@import "mixins/text-emphasis.less";
-@import "mixins/text-overflow.less";
-@import "mixins/vendor-prefixes.less";
-
-// Components
-@import "mixins/alerts.less";
-@import "mixins/buttons.less";
-@import "mixins/panels.less";
-@import "mixins/pagination.less";
-@import "mixins/list-group.less";
-@import "mixins/nav-divider.less";
-@import "mixins/forms.less";
-@import "mixins/progress-bar.less";
-@import "mixins/table-row.less";
-
-// Skins
-@import "mixins/background-variant.less";
-@import "mixins/border-radius.less";
-@import "mixins/gradients.less";
-
-// Layout
-@import "mixins/clearfix.less";
-@import "mixins/center-block.less";
-@import "mixins/nav-vertical-align.less";
-@import "mixins/grid-framework.less";
-@import "mixins/grid.less";
diff --git a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/alerts.less b/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/alerts.less
deleted file mode 100755
index 396196f438f..00000000000
--- a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/alerts.less
+++ /dev/null
@@ -1,14 +0,0 @@
-// Alerts
-
-.alert-variant(@background; @border; @text-color) {
- background-color: @background;
- border-color: @border;
- color: @text-color;
-
- hr {
- border-top-color: darken(@border, 5%);
- }
- .alert-link {
- color: darken(@text-color, 10%);
- }
-}
diff --git a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/background-variant.less b/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/background-variant.less
deleted file mode 100755
index a85c22b7453..00000000000
--- a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/background-variant.less
+++ /dev/null
@@ -1,9 +0,0 @@
-// Contextual backgrounds
-
-.bg-variant(@color) {
- background-color: @color;
- a&:hover,
- a&:focus {
- background-color: darken(@color, 10%);
- }
-}
diff --git a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/border-radius.less b/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/border-radius.less
deleted file mode 100755
index ca05dbf4570..00000000000
--- a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/border-radius.less
+++ /dev/null
@@ -1,18 +0,0 @@
-// Single side border-radius
-
-.border-top-radius(@radius) {
- border-top-right-radius: @radius;
- border-top-left-radius: @radius;
-}
-.border-right-radius(@radius) {
- border-bottom-right-radius: @radius;
- border-top-right-radius: @radius;
-}
-.border-bottom-radius(@radius) {
- border-bottom-right-radius: @radius;
- border-bottom-left-radius: @radius;
-}
-.border-left-radius(@radius) {
- border-bottom-left-radius: @radius;
- border-top-left-radius: @radius;
-}
diff --git a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/buttons.less b/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/buttons.less
deleted file mode 100755
index b294d8c210e..00000000000
--- a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/buttons.less
+++ /dev/null
@@ -1,65 +0,0 @@
-// Button variants
-//
-// Easily pump out default styles, as well as :hover, :focus, :active,
-// and disabled options for all buttons
-
-.button-variant(@color; @background; @border) {
- color: @color;
- background-color: @background;
- border-color: @border;
-
- &:focus,
- &.focus {
- color: @color;
- background-color: darken(@background, 10%);
- border-color: darken(@border, 25%);
- }
- &:hover {
- color: @color;
- background-color: darken(@background, 10%);
- border-color: darken(@border, 12%);
- }
- &:active,
- &.active,
- .open > .dropdown-toggle& {
- color: @color;
- background-color: darken(@background, 10%);
- border-color: darken(@border, 12%);
-
- &:hover,
- &:focus,
- &.focus {
- color: @color;
- background-color: darken(@background, 17%);
- border-color: darken(@border, 25%);
- }
- }
- &:active,
- &.active,
- .open > .dropdown-toggle& {
- background-image: none;
- }
- &.disabled,
- &[disabled],
- fieldset[disabled] & {
- &:hover,
- &:focus,
- &.focus {
- background-color: @background;
- border-color: @border;
- }
- }
-
- .badge {
- color: @background;
- background-color: @color;
- }
-}
-
-// Button sizes
-.button-size(@padding-vertical; @padding-horizontal; @font-size; @line-height; @border-radius) {
- padding: @padding-vertical @padding-horizontal;
- font-size: @font-size;
- line-height: @line-height;
- border-radius: @border-radius;
-}
diff --git a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/center-block.less b/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/center-block.less
deleted file mode 100755
index d18d6de9ed6..00000000000
--- a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/center-block.less
+++ /dev/null
@@ -1,7 +0,0 @@
-// Center-align a block level element
-
-.center-block() {
- display: block;
- margin-left: auto;
- margin-right: auto;
-}
diff --git a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/clearfix.less b/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/clearfix.less
deleted file mode 100755
index 3f7a3820c1c..00000000000
--- a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/clearfix.less
+++ /dev/null
@@ -1,22 +0,0 @@
-// Clearfix
-//
-// For modern browsers
-// 1. The space content is one way to avoid an Opera bug when the
-// contenteditable attribute is included anywhere else in the document.
-// Otherwise it causes space to appear at the top and bottom of elements
-// that are clearfixed.
-// 2. The use of `table` rather than `block` is only necessary if using
-// `:before` to contain the top-margins of child elements.
-//
-// Source: http://nicolasgallagher.com/micro-clearfix-hack/
-
-.clearfix() {
- &:before,
- &:after {
- content: " "; // 1
- display: table; // 2
- }
- &:after {
- clear: both;
- }
-}
diff --git a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/forms.less b/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/forms.less
deleted file mode 100755
index 6f55ed96708..00000000000
--- a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/forms.less
+++ /dev/null
@@ -1,85 +0,0 @@
-// Form validation states
-//
-// Used in forms.less to generate the form validation CSS for warnings, errors,
-// and successes.
-
-.form-control-validation(@text-color: #555; @border-color: #ccc; @background-color: #f5f5f5) {
- // Color the label and help text
- .help-block,
- .control-label,
- .radio,
- .checkbox,
- .radio-inline,
- .checkbox-inline,
- &.radio label,
- &.checkbox label,
- &.radio-inline label,
- &.checkbox-inline label {
- color: @text-color;
- }
- // Set the border and box shadow on specific inputs to match
- .form-control {
- border-color: @border-color;
- .box-shadow(inset 0 1px 1px rgba(0,0,0,.075)); // Redeclare so transitions work
- &:focus {
- border-color: darken(@border-color, 10%);
- @shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 6px lighten(@border-color, 20%);
- .box-shadow(@shadow);
- }
- }
- // Set validation states also for addons
- .input-group-addon {
- color: @text-color;
- border-color: @border-color;
- background-color: @background-color;
- }
- // Optional feedback icon
- .form-control-feedback {
- color: @text-color;
- }
-}
-
-
-// Form control focus state
-//
-// Generate a customized focus state and for any input with the specified color,
-// which defaults to the `@input-border-focus` variable.
-//
-// We highly encourage you to not customize the default value, but instead use
-// this to tweak colors on an as-needed basis. This aesthetic change is based on
-// WebKit's default styles, but applicable to a wider range of browsers. Its
-// usability and accessibility should be taken into account with any change.
-//
-// Example usage: change the default blue border and shadow to white for better
-// contrast against a dark gray background.
-.form-control-focus(@color: @input-border-focus) {
- @color-rgba: rgba(red(@color), green(@color), blue(@color), .6);
- &:focus {
- border-color: @color;
- outline: 0;
- .box-shadow(~"inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px @{color-rgba}");
- }
-}
-
-// Form control sizing
-//
-// Relative text size, padding, and border-radii changes for form controls. For
-// horizontal sizing, wrap controls in the predefined grid classes. `<select>`
-// element gets special love because it's special, and that's a fact!
-.input-size(@input-height; @padding-vertical; @padding-horizontal; @font-size; @line-height; @border-radius) {
- height: @input-height;
- padding: @padding-vertical @padding-horizontal;
- font-size: @font-size;
- line-height: @line-height;
- border-radius: @border-radius;
-
- select& {
- height: @input-height;
- line-height: @input-height;
- }
-
- textarea&,
- select[multiple]& {
- height: auto;
- }
-}
diff --git a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/gradients.less b/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/gradients.less
deleted file mode 100755
index 0b88a89cc56..00000000000
--- a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/gradients.less
+++ /dev/null
@@ -1,59 +0,0 @@
-// Gradients
-
-#gradient {
-
- // Horizontal gradient, from left to right
- //
- // Creates two color stops, start and end, by specifying a color and position for each color stop.
- // Color stops are not available in IE9 and below.
- .horizontal(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {
- background-image: -webkit-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+
- background-image: -o-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Opera 12
- background-image: linear-gradient(to right, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+
- background-repeat: repeat-x;
- filter: e(%("progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)",argb(@start-color),argb(@end-color))); // IE9 and down
- }
-
- // Vertical gradient, from top to bottom
- //
- // Creates two color stops, start and end, by specifying a color and position for each color stop.
- // Color stops are not available in IE9 and below.
- .vertical(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {
- background-image: -webkit-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+
- background-image: -o-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Opera 12
- background-image: linear-gradient(to bottom, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+
- background-repeat: repeat-x;
- filter: e(%("progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)",argb(@start-color),argb(@end-color))); // IE9 and down
- }
-
- .directional(@start-color: #555; @end-color: #333; @deg: 45deg) {
- background-repeat: repeat-x;
- background-image: -webkit-linear-gradient(@deg, @start-color, @end-color); // Safari 5.1-6, Chrome 10+
- background-image: -o-linear-gradient(@deg, @start-color, @end-color); // Opera 12
- background-image: linear-gradient(@deg, @start-color, @end-color); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+
- }
- .horizontal-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {
- background-image: -webkit-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);
- background-image: -o-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);
- background-image: linear-gradient(to right, @start-color, @mid-color @color-stop, @end-color);
- background-repeat: no-repeat;
- filter: e(%("progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback
- }
- .vertical-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {
- background-image: -webkit-linear-gradient(@start-color, @mid-color @color-stop, @end-color);
- background-image: -o-linear-gradient(@start-color, @mid-color @color-stop, @end-color);
- background-image: linear-gradient(@start-color, @mid-color @color-stop, @end-color);
- background-repeat: no-repeat;
- filter: e(%("progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback
- }
- .radial(@inner-color: #555; @outer-color: #333) {
- background-image: -webkit-radial-gradient(circle, @inner-color, @outer-color);
- background-image: radial-gradient(circle, @inner-color, @outer-color);
- background-repeat: no-repeat;
- }
- .striped(@color: rgba(255,255,255,.15); @angle: 45deg) {
- background-image: -webkit-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);
- background-image: -o-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);
- background-image: linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);
- }
-}
diff --git a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/grid-framework.less b/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/grid-framework.less
deleted file mode 100755
index 8c23eed24e6..00000000000
--- a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/grid-framework.less
+++ /dev/null
@@ -1,91 +0,0 @@
-// Framework grid generation
-//
-// Used only by Bootstrap to generate the correct number of grid classes given
-// any value of `@grid-columns`.
-
-.make-grid-columns() {
- // Common styles for all sizes of grid columns, widths 1-12
- .col(@index) { // initial
- @item: ~".col-xs-@{index}, .col-sm-@{index}, .col-md-@{index}, .col-lg-@{index}";
- .col((@index + 1), @item);
- }
- .col(@index, @list) when (@index =< @grid-columns) { // general; "=<" isn't a typo
- @item: ~".col-xs-@{index}, .col-sm-@{index}, .col-md-@{index}, .col-lg-@{index}";
- .col((@index + 1), ~"@{list}, @{item}");
- }
- .col(@index, @list) when (@index > @grid-columns) { // terminal
- @{list} {
- position: relative;
- // Prevent columns from collapsing when empty
- min-height: 1px;
- // Inner gutter via padding
- padding-left: ceil((@grid-gutter-width / 2));
- padding-right: floor((@grid-gutter-width / 2));
- }
- }
- .col(1); // kickstart it
-}
-
-.float-grid-columns(@class) {
- .col(@index) { // initial
- @item: ~".col-@{class}-@{index}";
- .col((@index + 1), @item);
- }
- .col(@index, @list) when (@index =< @grid-columns) { // general
- @item: ~".col-@{class}-@{index}";
- .col((@index + 1), ~"@{list}, @{item}");
- }
- .col(@index, @list) when (@index > @grid-columns) { // terminal
- @{list} {
- float: left;
- }
- }
- .col(1); // kickstart it
-}
-
-.calc-grid-column(@index, @class, @type) when (@type = width) and (@index > 0) {
- .col-@{class}-@{index} {
- width: percentage((@index / @grid-columns));
- }
-}
-.calc-grid-column(@index, @class, @type) when (@type = push) and (@index > 0) {
- .col-@{class}-push-@{index} {
- left: percentage((@index / @grid-columns));
- }
-}
-.calc-grid-column(@index, @class, @type) when (@type = push) and (@index = 0) {
- .col-@{class}-push-0 {
- left: auto;
- }
-}
-.calc-grid-column(@index, @class, @type) when (@type = pull) and (@index > 0) {
- .col-@{class}-pull-@{index} {
- right: percentage((@index / @grid-columns));
- }
-}
-.calc-grid-column(@index, @class, @type) when (@type = pull) and (@index = 0) {
- .col-@{class}-pull-0 {
- right: auto;
- }
-}
-.calc-grid-column(@index, @class, @type) when (@type = offset) {
- .col-@{class}-offset-@{index} {
- margin-left: percentage((@index / @grid-columns));
- }
-}
-
-// Basic looping in LESS
-.loop-grid-columns(@index, @class, @type) when (@index >= 0) {
- .calc-grid-column(@index, @class, @type);
- // next iteration
- .loop-grid-columns((@index - 1), @class, @type);
-}
-
-// Create grid for specific class
-.make-grid(@class) {
- .float-grid-columns(@class);
- .loop-grid-columns(@grid-columns, @class, width);
- .loop-grid-columns(@grid-columns, @class, pull);
- .loop-grid-columns(@grid-columns, @class, push);
- .loop-grid-columns(@grid-columns, @class, offset);
-}
diff --git a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/grid.less b/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/grid.less
deleted file mode 100755
index df496d0b3c1..00000000000
--- a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/grid.less
+++ /dev/null
@@ -1,122 +0,0 @@
-// Grid system
-//
-// Generate semantic grid columns with these mixins.
-
-// Centered container element
-.container-fixed(@gutter: @grid-gutter-width) {
- margin-right: auto;
- margin-left: auto;
- padding-left: floor((@gutter / 2));
- padding-right: ceil((@gutter / 2));
- &:extend(.clearfix all);
-}
-
-// Creates a wrapper for a series of columns
-.make-row(@gutter: @grid-gutter-width) {
- margin-left: ceil((@gutter / -2));
- margin-right: floor((@gutter / -2));
- &:extend(.clearfix all);
-}
-
-// Generate the extra small columns
-.make-xs-column(@columns; @gutter: @grid-gutter-width) {
- position: relative;
- float: left;
- width: percentage((@columns / @grid-columns));
- min-height: 1px;
- padding-left: (@gutter / 2);
- padding-right: (@gutter / 2);
-}
-.make-xs-column-offset(@columns) {
- margin-left: percentage((@columns / @grid-columns));
-}
-.make-xs-column-push(@columns) {
- left: percentage((@columns / @grid-columns));
-}
-.make-xs-column-pull(@columns) {
- right: percentage((@columns / @grid-columns));
-}
-
-// Generate the small columns
-.make-sm-column(@columns; @gutter: @grid-gutter-width) {
- position: relative;
- min-height: 1px;
- padding-left: (@gutter / 2);
- padding-right: (@gutter / 2);
-
- @media (min-width: @screen-sm-min) {
- float: left;
- width: percentage((@columns / @grid-columns));
- }
-}
-.make-sm-column-offset(@columns) {
- @media (min-width: @screen-sm-min) {
- margin-left: percentage((@columns / @grid-columns));
- }
-}
-.make-sm-column-push(@columns) {
- @media (min-width: @screen-sm-min) {
- left: percentage((@columns / @grid-columns));
- }
-}
-.make-sm-column-pull(@columns) {
- @media (min-width: @screen-sm-min) {
- right: percentage((@columns / @grid-columns));
- }
-}
-
-// Generate the medium columns
-.make-md-column(@columns; @gutter: @grid-gutter-width) {
- position: relative;
- min-height: 1px;
- padding-left: (@gutter / 2);
- padding-right: (@gutter / 2);
-
- @media (min-width: @screen-md-min) {
- float: left;
- width: percentage((@columns / @grid-columns));
- }
-}
-.make-md-column-offset(@columns) {
- @media (min-width: @screen-md-min) {
- margin-left: percentage((@columns / @grid-columns));
- }
-}
-.make-md-column-push(@columns) {
- @media (min-width: @screen-md-min) {
- left: percentage((@columns / @grid-columns));
- }
-}
-.make-md-column-pull(@columns) {
- @media (min-width: @screen-md-min) {
- right: percentage((@columns / @grid-columns));
- }
-}
-
-// Generate the large columns
-.make-lg-column(@columns; @gutter: @grid-gutter-width) {
- position: relative;
- min-height: 1px;
- padding-left: (@gutter / 2);
- padding-right: (@gutter / 2);
-
- @media (min-width: @screen-lg-min) {
- float: left;
- width: percentage((@columns / @grid-columns));
- }
-}
-.make-lg-column-offset(@columns) {
- @media (min-width: @screen-lg-min) {
- margin-left: percentage((@columns / @grid-columns));
- }
-}
-.make-lg-column-push(@columns) {
- @media (min-width: @screen-lg-min) {
- left: percentage((@columns / @grid-columns));
- }
-}
-.make-lg-column-pull(@columns) {
- @media (min-width: @screen-lg-min) {
- right: percentage((@columns / @grid-columns));
- }
-}
diff --git a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/hide-text.less b/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/hide-text.less
deleted file mode 100755
index 2bb84a3b444..00000000000
--- a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/hide-text.less
+++ /dev/null
@@ -1,21 +0,0 @@
-// CSS image replacement
-//
-// Heads up! v3 launched with only `.hide-text()`, but per our pattern for
-// mixins being reused as classes with the same name, this doesn't hold up. As
-// of v3.0.1 we have added `.text-hide()` and deprecated `.hide-text()`.
-//
-// Source: https://github.com/h5bp/html5-boilerplate/commit/aa0396eae757
-
-// Deprecated as of v3.0.1 (has been removed in v4)
-.hide-text() {
- font: ~"0/0" a;
- color: transparent;
- text-shadow: none;
- background-color: transparent;
- border: 0;
-}
-
-// New mixin to use as of v3.0.1
-.text-hide() {
- .hide-text();
-}
diff --git a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/image.less b/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/image.less
deleted file mode 100755
index f233cb3e199..00000000000
--- a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/image.less
+++ /dev/null
@@ -1,33 +0,0 @@
-// Image Mixins
-// - Responsive image
-// - Retina image
-
-
-// Responsive image
-//
-// Keep images from scaling beyond the width of their parents.
-.img-responsive(@display: block) {
- display: @display;
- max-width: 100%; // Part 1: Set a maximum relative to the parent
- height: auto; // Part 2: Scale the height according to the width, otherwise you get stretching
-}
-
-
-// Retina image
-//
-// Short retina mixin for setting background-image and -size. Note that the
-// spelling of `min--moz-device-pixel-ratio` is intentional.
-.img-retina(@file-1x; @file-2x; @width-1x; @height-1x) {
- background-image: url("@{file-1x}");
-
- @media
- only screen and (-webkit-min-device-pixel-ratio: 2),
- only screen and ( min--moz-device-pixel-ratio: 2),
- only screen and ( -o-min-device-pixel-ratio: 2/1),
- only screen and ( min-device-pixel-ratio: 2),
- only screen and ( min-resolution: 192dpi),
- only screen and ( min-resolution: 2dppx) {
- background-image: url("@{file-2x}");
- background-size: @width-1x @height-1x;
- }
-}
diff --git a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/labels.less b/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/labels.less
deleted file mode 100755
index 9f7a67ee3d0..00000000000
--- a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/labels.less
+++ /dev/null
@@ -1,12 +0,0 @@
-// Labels
-
-.label-variant(@color) {
- background-color: @color;
-
- &[href] {
- &:hover,
- &:focus {
- background-color: darken(@color, 10%);
- }
- }
-}
diff --git a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/list-group.less b/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/list-group.less
deleted file mode 100755
index 03aa19069d9..00000000000
--- a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/list-group.less
+++ /dev/null
@@ -1,30 +0,0 @@
-// List Groups
-
-.list-group-item-variant(@state; @background; @color) {
- .list-group-item-@{state} {
- color: @color;
- background-color: @background;
-
- a&,
- button& {
- color: @color;
-
- .list-group-item-heading {
- color: inherit;
- }
-
- &:hover,
- &:focus {
- color: @color;
- background-color: darken(@background, 5%);
- }
- &.active,
- &.active:hover,
- &.active:focus {
- color: #fff;
- background-color: @color;
- border-color: @color;
- }
- }
- }
-}
diff --git a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/nav-divider.less b/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/nav-divider.less
deleted file mode 100755
index feb1e9ed0da..00000000000
--- a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/nav-divider.less
+++ /dev/null
@@ -1,10 +0,0 @@
-// Horizontal dividers
-//
-// Dividers (basically an hr) within dropdowns and nav lists
-
-.nav-divider(@color: #e5e5e5) {
- height: 1px;
- margin: ((@line-height-computed / 2) - 1) 0;
- overflow: hidden;
- background-color: @color;
-}
diff --git a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/nav-vertical-align.less b/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/nav-vertical-align.less
deleted file mode 100755
index d458c78613e..00000000000
--- a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/nav-vertical-align.less
+++ /dev/null
@@ -1,9 +0,0 @@
-// Navbar vertical align
-//
-// Vertically center elements in the navbar.
-// Example: an element has a height of 30px, so write out `.navbar-vertical-align(30px);` to calculate the appropriate top margin.
-
-.navbar-vertical-align(@element-height) {
- margin-top: ((@navbar-height - @element-height) / 2);
- margin-bottom: ((@navbar-height - @element-height) / 2);
-}
diff --git a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/opacity.less b/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/opacity.less
deleted file mode 100755
index 33ed25ce676..00000000000
--- a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/opacity.less
+++ /dev/null
@@ -1,8 +0,0 @@
-// Opacity
-
-.opacity(@opacity) {
- opacity: @opacity;
- // IE8 filter
- @opacity-ie: (@opacity * 100);
- filter: ~"alpha(opacity=@{opacity-ie})";
-}
diff --git a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/pagination.less b/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/pagination.less
deleted file mode 100755
index 618804f2dee..00000000000
--- a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/pagination.less
+++ /dev/null
@@ -1,24 +0,0 @@
-// Pagination
-
-.pagination-size(@padding-vertical; @padding-horizontal; @font-size; @line-height; @border-radius) {
- > li {
- > a,
- > span {
- padding: @padding-vertical @padding-horizontal;
- font-size: @font-size;
- line-height: @line-height;
- }
- &:first-child {
- > a,
- > span {
- .border-left-radius(@border-radius);
- }
- }
- &:last-child {
- > a,
- > span {
- .border-right-radius(@border-radius);
- }
- }
- }
-}
diff --git a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/panels.less b/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/panels.less
deleted file mode 100755
index 49ee10d4ad3..00000000000
--- a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/panels.less
+++ /dev/null
@@ -1,24 +0,0 @@
-// Panels
-
-.panel-variant(@border; @heading-text-color; @heading-bg-color; @heading-border) {
- border-color: @border;
-
- & > .panel-heading {
- color: @heading-text-color;
- background-color: @heading-bg-color;
- border-color: @heading-border;
-
- + .panel-collapse > .panel-body {
- border-top-color: @border;
- }
- .badge {
- color: @heading-bg-color;
- background-color: @heading-text-color;
- }
- }
- & > .panel-footer {
- + .panel-collapse > .panel-body {
- border-bottom-color: @border;
- }
- }
-}
diff --git a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/progress-bar.less b/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/progress-bar.less
deleted file mode 100755
index f07996a34db..00000000000
--- a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/progress-bar.less
+++ /dev/null
@@ -1,10 +0,0 @@
-// Progress bars
-
-.progress-bar-variant(@color) {
- background-color: @color;
-
- // Deprecated parent class requirement as of v3.2.0
- .progress-striped & {
- #gradient > .striped();
- }
-}
diff --git a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/reset-filter.less b/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/reset-filter.less
deleted file mode 100755
index 68cdb5e1860..00000000000
--- a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/reset-filter.less
+++ /dev/null
@@ -1,8 +0,0 @@
-// Reset filters for IE
-//
-// When you need to remove a gradient background, do not forget to use this to reset
-// the IE filter for IE9 and below.
-
-.reset-filter() {
- filter: e(%("progid:DXImageTransform.Microsoft.gradient(enabled = false)"));
-}
diff --git a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/reset-text.less b/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/reset-text.less
deleted file mode 100755
index 58dd4d19b4d..00000000000
--- a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/reset-text.less
+++ /dev/null
@@ -1,18 +0,0 @@
-.reset-text() {
- font-family: @font-family-base;
- // We deliberately do NOT reset font-size.
- font-style: normal;
- font-weight: normal;
- letter-spacing: normal;
- line-break: auto;
- line-height: @line-height-base;
- text-align: left; // Fallback for where `start` is not supported
- text-align: start;
- text-decoration: none;
- text-shadow: none;
- text-transform: none;
- white-space: normal;
- word-break: normal;
- word-spacing: normal;
- word-wrap: normal;
-}
diff --git a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/resize.less b/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/resize.less
deleted file mode 100755
index 3acd3afdbac..00000000000
--- a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/resize.less
+++ /dev/null
@@ -1,6 +0,0 @@
-// Resize anything
-
-.resizable(@direction) {
- resize: @direction; // Options: horizontal, vertical, both
- overflow: auto; // Per CSS3 UI, `resize` only applies when `overflow` isn't `visible`
-}
diff --git a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/responsive-visibility.less b/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/responsive-visibility.less
deleted file mode 100755
index ecf1e979fd2..00000000000
--- a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/responsive-visibility.less
+++ /dev/null
@@ -1,15 +0,0 @@
-// Responsive utilities
-
-//
-// More easily include all the states for responsive-utilities.less.
-.responsive-visibility() {
- display: block !important;
- table& { display: table !important; }
- tr& { display: table-row !important; }
- th&,
- td& { display: table-cell !important; }
-}
-
-.responsive-invisibility() {
- display: none !important;
-}
diff --git a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/size.less b/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/size.less
deleted file mode 100755
index a8be6508960..00000000000
--- a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/size.less
+++ /dev/null
@@ -1,10 +0,0 @@
-// Sizing shortcuts
-
-.size(@width; @height) {
- width: @width;
- height: @height;
-}
-
-.square(@size) {
- .size(@size; @size);
-}
diff --git a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/tab-focus.less b/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/tab-focus.less
deleted file mode 100755
index 1f1f05ab054..00000000000
--- a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/tab-focus.less
+++ /dev/null
@@ -1,9 +0,0 @@
-// WebKit-style focus
-
-.tab-focus() {
- // Default
- outline: thin dotted;
- // WebKit
- outline: 5px auto -webkit-focus-ring-color;
- outline-offset: -2px;
-}
diff --git a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/table-row.less b/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/table-row.less
deleted file mode 100755
index 0f287f1a8bd..00000000000
--- a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/table-row.less
+++ /dev/null
@@ -1,28 +0,0 @@
-// Tables
-
-.table-row-variant(@state; @background) {
- // Exact selectors below required to override `.table-striped` and prevent
- // inheritance to nested tables.
- .table > thead > tr,
- .table > tbody > tr,
- .table > tfoot > tr {
- > td.@{state},
- > th.@{state},
- &.@{state} > td,
- &.@{state} > th {
- background-color: @background;
- }
- }
-
- // Hover states for `.table-hover`
- // Note: this is not available for cells or rows within `thead` or `tfoot`.
- .table-hover > tbody > tr {
- > td.@{state}:hover,
- > th.@{state}:hover,
- &.@{state}:hover > td,
- &:hover > .@{state},
- &.@{state}:hover > th {
- background-color: darken(@background, 5%);
- }
- }
-}
diff --git a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/text-emphasis.less b/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/text-emphasis.less
deleted file mode 100755
index 9e8a77a6985..00000000000
--- a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/text-emphasis.less
+++ /dev/null
@@ -1,9 +0,0 @@
-// Typography
-
-.text-emphasis-variant(@color) {
- color: @color;
- a&:hover,
- a&:focus {
- color: darken(@color, 10%);
- }
-}
diff --git a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/text-overflow.less b/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/text-overflow.less
deleted file mode 100755
index c11ad2fb747..00000000000
--- a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/text-overflow.less
+++ /dev/null
@@ -1,8 +0,0 @@
-// Text overflow
-// Requires inline-block or block for proper styling
-
-.text-overflow() {
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
-}
diff --git a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/vendor-prefixes.less b/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/vendor-prefixes.less
deleted file mode 100755
index 2b5e74b99ed..00000000000
--- a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/mixins/vendor-prefixes.less
+++ /dev/null
@@ -1,227 +0,0 @@
-// Vendor Prefixes
-//
-// All vendor mixins are deprecated as of v3.2.0 due to the introduction of
-// Autoprefixer in our Gruntfile. They have been removed in v4.
-
-// - Animations
-// - Backface visibility
-// - Box shadow
-// - Box sizing
-// - Content columns
-// - Hyphens
-// - Placeholder text
-// - Transformations
-// - Transitions
-// - User Select
-
-
-// Animations
-.animation(@animation) {
- -webkit-animation: @animation;
- -o-animation: @animation;
- animation: @animation;
-}
-.animation-name(@name) {
- -webkit-animation-name: @name;
- animation-name: @name;
-}
-.animation-duration(@duration) {
- -webkit-animation-duration: @duration;
- animation-duration: @duration;
-}
-.animation-timing-function(@timing-function) {
- -webkit-animation-timing-function: @timing-function;
- animation-timing-function: @timing-function;
-}
-.animation-delay(@delay) {
- -webkit-animation-delay: @delay;
- animation-delay: @delay;
-}
-.animation-iteration-count(@iteration-count) {
- -webkit-animation-iteration-count: @iteration-count;
- animation-iteration-count: @iteration-count;
-}
-.animation-direction(@direction) {
- -webkit-animation-direction: @direction;
- animation-direction: @direction;
-}
-.animation-fill-mode(@fill-mode) {
- -webkit-animation-fill-mode: @fill-mode;
- animation-fill-mode: @fill-mode;
-}
-
-// Backface visibility
-// Prevent browsers from flickering when using CSS 3D transforms.
-// Default value is `visible`, but can be changed to `hidden`
-
-.backface-visibility(@visibility) {
- -webkit-backface-visibility: @visibility;
- -moz-backface-visibility: @visibility;
- backface-visibility: @visibility;
-}
-
-// Drop shadows
-//
-// Note: Deprecated `.box-shadow()` as of v3.1.0 since all of Bootstrap's
-// supported browsers that have box shadow capabilities now support it.
-
-.box-shadow(@shadow) {
- -webkit-box-shadow: @shadow; // iOS <4.3 & Android <4.1
- box-shadow: @shadow;
-}
-
-// Box sizing
-.box-sizing(@boxmodel) {
- -webkit-box-sizing: @boxmodel;
- -moz-box-sizing: @boxmodel;
- box-sizing: @boxmodel;
-}
-
-// CSS3 Content Columns
-.content-columns(@column-count; @column-gap: @grid-gutter-width) {
- -webkit-column-count: @column-count;
- -moz-column-count: @column-count;
- column-count: @column-count;
- -webkit-column-gap: @column-gap;
- -moz-column-gap: @column-gap;
- column-gap: @column-gap;
-}
-
-// Optional hyphenation
-.hyphens(@mode: auto) {
- word-wrap: break-word;
- -webkit-hyphens: @mode;
- -moz-hyphens: @mode;
- -ms-hyphens: @mode; // IE10+
- -o-hyphens: @mode;
- hyphens: @mode;
-}
-
-// Placeholder text
-.placeholder(@color: @input-color-placeholder) {
- // Firefox
- &::-moz-placeholder {
- color: @color;
- opacity: 1; // Override Firefox's unusual default opacity; see https://github.com/twbs/bootstrap/pull/11526
- }
- &:-ms-input-placeholder { color: @color; } // Internet Explorer 10+
- &::-webkit-input-placeholder { color: @color; } // Safari and Chrome
-}
-
-// Transformations
-.scale(@ratio) {
- -webkit-transform: scale(@ratio);
- -ms-transform: scale(@ratio); // IE9 only
- -o-transform: scale(@ratio);
- transform: scale(@ratio);
-}
-.scale(@ratioX; @ratioY) {
- -webkit-transform: scale(@ratioX, @ratioY);
- -ms-transform: scale(@ratioX, @ratioY); // IE9 only
- -o-transform: scale(@ratioX, @ratioY);
- transform: scale(@ratioX, @ratioY);
-}
-.scaleX(@ratio) {
- -webkit-transform: scaleX(@ratio);
- -ms-transform: scaleX(@ratio); // IE9 only
- -o-transform: scaleX(@ratio);
- transform: scaleX(@ratio);
-}
-.scaleY(@ratio) {
- -webkit-transform: scaleY(@ratio);
- -ms-transform: scaleY(@ratio); // IE9 only
- -o-transform: scaleY(@ratio);
- transform: scaleY(@ratio);
-}
-.skew(@x; @y) {
- -webkit-transform: skewX(@x) skewY(@y);
- -ms-transform: skewX(@x) skewY(@y); // See https://github.com/twbs/bootstrap/issues/4885; IE9+
- -o-transform: skewX(@x) skewY(@y);
- transform: skewX(@x) skewY(@y);
-}
-.translate(@x; @y) {
- -webkit-transform: translate(@x, @y);
- -ms-transform: translate(@x, @y); // IE9 only
- -o-transform: translate(@x, @y);
- transform: translate(@x, @y);
-}
-.translate3d(@x; @y; @z) {
- -webkit-transform: translate3d(@x, @y, @z);
- transform: translate3d(@x, @y, @z);
-}
-.rotate(@degrees) {
- -webkit-transform: rotate(@degrees);
- -ms-transform: rotate(@degrees); // IE9 only
- -o-transform: rotate(@degrees);
- transform: rotate(@degrees);
-}
-.rotateX(@degrees) {
- -webkit-transform: rotateX(@degrees);
- -ms-transform: rotateX(@degrees); // IE9 only
- -o-transform: rotateX(@degrees);
- transform: rotateX(@degrees);
-}
-.rotateY(@degrees) {
- -webkit-transform: rotateY(@degrees);
- -ms-transform: rotateY(@degrees); // IE9 only
- -o-transform: rotateY(@degrees);
- transform: rotateY(@degrees);
-}
-.perspective(@perspective) {
- -webkit-perspective: @perspective;
- -moz-perspective: @perspective;
- perspective: @perspective;
-}
-.perspective-origin(@perspective) {
- -webkit-perspective-origin: @perspective;
- -moz-perspective-origin: @perspective;
- perspective-origin: @perspective;
-}
-.transform-origin(@origin) {
- -webkit-transform-origin: @origin;
- -moz-transform-origin: @origin;
- -ms-transform-origin: @origin; // IE9 only
- transform-origin: @origin;
-}
-
-
-// Transitions
-
-.transition(@transition) {
- -webkit-transition: @transition;
- -o-transition: @transition;
- transition: @transition;
-}
-.transition-property(@transition-property) {
- -webkit-transition-property: @transition-property;
- transition-property: @transition-property;
-}
-.transition-delay(@transition-delay) {
- -webkit-transition-delay: @transition-delay;
- transition-delay: @transition-delay;
-}
-.transition-duration(@transition-duration) {
- -webkit-transition-duration: @transition-duration;
- transition-duration: @transition-duration;
-}
-.transition-timing-function(@timing-function) {
- -webkit-transition-timing-function: @timing-function;
- transition-timing-function: @timing-function;
-}
-.transition-transform(@transition) {
- -webkit-transition: -webkit-transform @transition;
- -moz-transition: -moz-transform @transition;
- -o-transition: -o-transform @transition;
- transition: transform @transition;
-}
-
-
-// User select
-// For selecting text on the page
-
-.user-select(@select) {
- -webkit-user-select: @select;
- -moz-user-select: @select;
- -ms-user-select: @select; // IE10+
- user-select: @select;
-}
diff --git a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/modals.less b/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/modals.less
deleted file mode 100755
index 767ce36ba37..00000000000
--- a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/modals.less
+++ /dev/null
@@ -1,150 +0,0 @@
-//
-// Modals
-// --------------------------------------------------
-
-// .modal-open - body class for killing the scroll
-// .modal - container to scroll within
-// .modal-dialog - positioning shell for the actual modal
-// .modal-content - actual modal w/ bg and corners and shit
-
-// Kill the scroll on the body
-.modal-open {
- overflow: hidden;
-}
-
-// Container that the modal scrolls within
-.modal {
- display: none;
- overflow: hidden;
- position: fixed;
- top: 0;
- right: 0;
- bottom: 0;
- left: 0;
- z-index: @zindex-modal;
- -webkit-overflow-scrolling: touch;
-
- // Prevent Chrome on Windows from adding a focus outline. For details, see
- // https://github.com/twbs/bootstrap/pull/10951.
- outline: 0;
-
- // When fading in the modal, animate it to slide down
- &.fade .modal-dialog {
- .translate(0, -25%);
- .transition-transform(~"0.3s ease-out");
- }
- &.in .modal-dialog { .translate(0, 0) }
-}
-.modal-open .modal {
- overflow-x: hidden;
- overflow-y: auto;
-}
-
-// Shell div to position the modal with bottom padding
-.modal-dialog {
- position: relative;
- width: auto;
- margin: 10px;
-}
-
-// Actual modal
-.modal-content {
- position: relative;
- background-color: @modal-content-bg;
- border: 1px solid @modal-content-fallback-border-color; //old browsers fallback (ie8 etc)
- border: 1px solid @modal-content-border-color;
- border-radius: @border-radius-large;
- .box-shadow(0 3px 9px rgba(0,0,0,.5));
- background-clip: padding-box;
- // Remove focus outline from opened modal
- outline: 0;
-}
-
-// Modal background
-.modal-backdrop {
- position: fixed;
- top: 0;
- right: 0;
- bottom: 0;
- left: 0;
- z-index: @zindex-modal-background;
- background-color: @modal-backdrop-bg;
- // Fade for backdrop
- &.fade { .opacity(0); }
- &.in { .opacity(@modal-backdrop-opacity); }
-}
-
-// Modal header
-// Top section of the modal w/ title and dismiss
-.modal-header {
- padding: @modal-title-padding;
- border-bottom: 1px solid @modal-header-border-color;
- &:extend(.clearfix all);
-}
-// Close icon
-.modal-header .close {
- margin-top: -2px;
-}
-
-// Title text within header
-.modal-title {
- margin: 0;
- line-height: @modal-title-line-height;
-}
-
-// Modal body
-// Where all modal content resides (sibling of .modal-header and .modal-footer)
-.modal-body {
- position: relative;
- padding: @modal-inner-padding;
-}
-
-// Footer (for actions)
-.modal-footer {
- padding: @modal-inner-padding;
- text-align: right; // right align buttons
- border-top: 1px solid @modal-footer-border-color;
- &:extend(.clearfix all); // clear it in case folks use .pull-* classes on buttons
-
- // Properly space out buttons
- .btn + .btn {
- margin-left: 5px;
- margin-bottom: 0; // account for input[type="submit"] which gets the bottom margin like all other inputs
- }
- // but override that for button groups
- .btn-group .btn + .btn {
- margin-left: -1px;
- }
- // and override it for block buttons as well
- .btn-block + .btn-block {
- margin-left: 0;
- }
-}
-
-// Measure scrollbar width for padding body during modal show/hide
-.modal-scrollbar-measure {
- position: absolute;
- top: -9999px;
- width: 50px;
- height: 50px;
- overflow: scroll;
-}
-
-// Scale up the modal
-@media (min-width: @screen-sm-min) {
- // Automatically set modal's width for larger viewports
- .modal-dialog {
- width: @modal-md;
- margin: 30px auto;
- }
- .modal-content {
- .box-shadow(0 5px 15px rgba(0,0,0,.5));
- }
-
- // Modal sizes
- .modal-sm { width: @modal-sm; }
-}
-
-@media (min-width: @screen-md-min) {
- .modal-lg { width: @modal-lg; }
-}
diff --git a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/navbar.less b/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/navbar.less
deleted file mode 100755
index 6d751bb9ce0..00000000000
--- a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/navbar.less
+++ /dev/null
@@ -1,660 +0,0 @@
-//
-// Navbars
-// --------------------------------------------------
-
-
-// Wrapper and base class
-//
-// Provide a static navbar from which we expand to create full-width, fixed, and
-// other navbar variations.
-
-.navbar {
- position: relative;
- min-height: @navbar-height; // Ensure a navbar always shows (e.g., without a .navbar-brand in collapsed mode)
- margin-bottom: @navbar-margin-bottom;
- border: 1px solid transparent;
-
- // Prevent floats from breaking the navbar
- &:extend(.clearfix all);
-
- @media (min-width: @grid-float-breakpoint) {
- border-radius: @navbar-border-radius;
- }
-}
-
-
-// Navbar heading
-//
-// Groups `.navbar-brand` and `.navbar-toggle` into a single component for easy
-// styling of responsive aspects.
-
-.navbar-header {
- &:extend(.clearfix all);
-
- @media (min-width: @grid-float-breakpoint) {
- float: left;
- }
-}
-
-
-// Navbar collapse (body)
-//
-// Group your navbar content into this for easy collapsing and expanding across
-// various device sizes. By default, this content is collapsed when <768px, but
-// will expand past that for a horizontal display.
-//
-// To start (on mobile devices) the navbar links, forms, and buttons are stacked
-// vertically and include a `max-height` to overflow in case you have too much
-// content for the user's viewport.
-
-.navbar-collapse {
- overflow-x: visible;
- padding-right: @navbar-padding-horizontal;
- padding-left: @navbar-padding-horizontal;
- border-top: 1px solid transparent;
- box-shadow: inset 0 1px 0 rgba(255,255,255,.1);
- &:extend(.clearfix all);
- -webkit-overflow-scrolling: touch;
-
- &.in {
- overflow-y: auto;
- }
-
- @media (min-width: @grid-float-breakpoint) {
- width: auto;
- border-top: 0;
- box-shadow: none;
-
- &.collapse {
- display: block !important;
- height: auto !important;
- padding-bottom: 0; // Override default setting
- overflow: visible !important;
- }
-
- &.in {
- overflow-y: visible;
- }
-
- // Undo the collapse side padding for navbars with containers to ensure
- // alignment of right-aligned contents.
- .navbar-fixed-top &,
- .navbar-static-top &,
- .navbar-fixed-bottom & {
- padding-left: 0;
- padding-right: 0;
- }
- }
-}
-
-.navbar-fixed-top,
-.navbar-fixed-bottom {
- .navbar-collapse {
- max-height: @navbar-collapse-max-height;
-
- @media (max-device-width: @screen-xs-min) and (orientation: landscape) {
- max-height: 200px;
- }
- }
-}
-
-
-// Both navbar header and collapse
-//
-// When a container is present, change the behavior of the header and collapse.
-
-.container,
-.container-fluid {
- > .navbar-header,
- > .navbar-collapse {
- margin-right: -@navbar-padding-horizontal;
- margin-left: -@navbar-padding-horizontal;
-
- @media (min-width: @grid-float-breakpoint) {
- margin-right: 0;
- margin-left: 0;
- }
- }
-}
-
-
-//
-// Navbar alignment options
-//
-// Display the navbar across the entirety of the page or fixed it to the top or
-// bottom of the page.
-
-// Static top (unfixed, but 100% wide) navbar
-.navbar-static-top {
- z-index: @zindex-navbar;
- border-width: 0 0 1px;
-
- @media (min-width: @grid-float-breakpoint) {
- border-radius: 0;
- }
-}
-
-// Fix the top/bottom navbars when screen real estate supports it
-.navbar-fixed-top,
-.navbar-fixed-bottom {
- position: fixed;
- right: 0;
- left: 0;
- z-index: @zindex-navbar-fixed;
-
- // Undo the rounded corners
- @media (min-width: @grid-float-breakpoint) {
- border-radius: 0;
- }
-}
-.navbar-fixed-top {
- top: 0;
- border-width: 0 0 1px;
-}
-.navbar-fixed-bottom {
- bottom: 0;
- margin-bottom: 0; // override .navbar defaults
- border-width: 1px 0 0;
-}
-
-
-// Brand/project name
-
-.navbar-brand {
- float: left;
- padding: @navbar-padding-vertical @navbar-padding-horizontal;
- font-size: @font-size-large;
- line-height: @line-height-computed;
- height: @navbar-height;
-
- &:hover,
- &:focus {
- text-decoration: none;
- }
-
- > img {
- display: block;
- }
-
- @media (min-width: @grid-float-breakpoint) {
- .navbar > .container &,
- .navbar > .container-fluid & {
- margin-left: -@navbar-padding-horizontal;
- }
- }
-}
-
-
-// Navbar toggle
-//
-// Custom button for toggling the `.navbar-collapse`, powered by the collapse
-// JavaScript plugin.
-
-.navbar-toggle {
- position: relative;
- float: right;
- margin-right: @navbar-padding-horizontal;
- padding: 9px 10px;
- .navbar-vertical-align(34px);
- background-color: transparent;
- background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214
- border: 1px solid transparent;
- border-radius: @border-radius-base;
-
- // We remove the `outline` here, but later compensate by attaching `:hover`
- // styles to `:focus`.
- &:focus {
- outline: 0;
- }
-
- // Bars
- .icon-bar {
- display: block;
- width: 22px;
- height: 2px;
- border-radius: 1px;
- }
- .icon-bar + .icon-bar {
- margin-top: 4px;
- }
-
- @media (min-width: @grid-float-breakpoint) {
- display: none;
- }
-}
-
-
-// Navbar nav links
-//
-// Builds on top of the `.nav` components with its own modifier class to make
-// the nav the full height of the horizontal nav (above 768px).
-
-.navbar-nav {
- margin: (@navbar-padding-vertical / 2) -@navbar-padding-horizontal;
-
- > li > a {
- padding-top: 10px;
- padding-bottom: 10px;
- line-height: @line-height-computed;
- }
-
- @media (max-width: @grid-float-breakpoint-max) {
- // Dropdowns get custom display when collapsed
- .open .dropdown-menu {
- position: static;
- float: none;
- width: auto;
- margin-top: 0;
- background-color: transparent;
- border: 0;
- box-shadow: none;
- > li > a,
- .dropdown-header {
- padding: 5px 15px 5px 25px;
- }
- > li > a {
- line-height: @line-height-computed;
- &:hover,
- &:focus {
- background-image: none;
- }
- }
- }
- }
-
- // Uncollapse the nav
- @media (min-width: @grid-float-breakpoint) {
- float: left;
- margin: 0;
-
- > li {
- float: left;
- > a {
- padding-top: @navbar-padding-vertical;
- padding-bottom: @navbar-padding-vertical;
- }
- }
- }
-}
-
-
-// Navbar form
-//
-// Extension of the `.form-inline` with some extra flavor for optimum display in
-// our navbars.
-
-.navbar-form {
- margin-left: -@navbar-padding-horizontal;
- margin-right: -@navbar-padding-horizontal;
- padding: 10px @navbar-padding-horizontal;
- border-top: 1px solid transparent;
- border-bottom: 1px solid transparent;
- @shadow: inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.1);
- .box-shadow(@shadow);
-
- // Mixin behavior for optimum display
- .form-inline();
-
- .form-group {
- @media (max-width: @grid-float-breakpoint-max) {
- margin-bottom: 5px;
-
- &:last-child {
- margin-bottom: 0;
- }
- }
- }
-
- // Vertically center in expanded, horizontal navbar
- .navbar-vertical-align(@input-height-base);
-
- // Undo 100% width for pull classes
- @media (min-width: @grid-float-breakpoint) {
- width: auto;
- border: 0;
- margin-left: 0;
- margin-right: 0;
- padding-top: 0;
- padding-bottom: 0;
- .box-shadow(none);
- }
-}
-
-
-// Dropdown menus
-
-// Menu position and menu carets
-.navbar-nav > li > .dropdown-menu {
- margin-top: 0;
- .border-top-radius(0);
-}
-// Menu position and menu caret support for dropups via extra dropup class
-.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu {
- margin-bottom: 0;
- .border-top-radius(@navbar-border-radius);
- .border-bottom-radius(0);
-}
-
-
-// Buttons in navbars
-//
-// Vertically center a button within a navbar (when *not* in a form).
-
-.navbar-btn {
- .navbar-vertical-align(@input-height-base);
-
- &.btn-sm {
- .navbar-vertical-align(@input-height-small);
- }
- &.btn-xs {
- .navbar-vertical-align(22);
- }
-}
-
-
-// Text in navbars
-//
-// Add a class to make any element properly align itself vertically within the navbars.
-
-.navbar-text {
- .navbar-vertical-align(@line-height-computed);
-
- @media (min-width: @grid-float-breakpoint) {
- float: left;
- margin-left: @navbar-padding-horizontal;
- margin-right: @navbar-padding-horizontal;
- }
-}
-
-
-// Component alignment
-//
-// Repurpose the pull utilities as their own navbar utilities to avoid specificity
-// issues with parents and chaining. Only do this when the navbar is uncollapsed
-// though so that navbar contents properly stack and align in mobile.
-//
-// Declared after the navbar components to ensure more specificity on the margins.
-
-@media (min-width: @grid-float-breakpoint) {
- .navbar-left { .pull-left(); }
- .navbar-right {
- .pull-right();
- margin-right: -@navbar-padding-horizontal;
-
- ~ .navbar-right {
- margin-right: 0;
- }
- }
-}
-
-
-// Alternate navbars
-// --------------------------------------------------
-
-// Default navbar
-.navbar-default {
- background-color: @navbar-default-bg;
- border-color: @navbar-default-border;
-
- .navbar-brand {
- color: @navbar-default-brand-color;
- &:hover,
- &:focus {
- color: @navbar-default-brand-hover-color;
- background-color: @navbar-default-brand-hover-bg;
- }
- }
-
- .navbar-text {
- color: @navbar-default-color;
- }
-
- .navbar-nav {
- > li > a {
- color: @navbar-default-link-color;
-
- &:hover,
- &:focus {
- color: @navbar-default-link-hover-color;
- background-color: @navbar-default-link-hover-bg;
- }
- }
- > .active > a {
- &,
- &:hover,
- &:focus {
- color: @navbar-default-link-active-color;
- background-color: @navbar-default-link-active-bg;
- }
- }
- > .disabled > a {
- &,
- &:hover,
- &:focus {
- color: @navbar-default-link-disabled-color;
- background-color: @navbar-default-link-disabled-bg;
- }
- }
- }
-
- .navbar-toggle {
- border-color: @navbar-default-toggle-border-color;
- &:hover,
- &:focus {
- background-color: @navbar-default-toggle-hover-bg;
- }
- .icon-bar {
- background-color: @navbar-default-toggle-icon-bar-bg;
- }
- }
-
- .navbar-collapse,
- .navbar-form {
- border-color: @navbar-default-border;
- }
-
- // Dropdown menu items
- .navbar-nav {
- // Remove background color from open dropdown
- > .open > a {
- &,
- &:hover,
- &:focus {
- background-color: @navbar-default-link-active-bg;
- color: @navbar-default-link-active-color;
- }
- }
-
- @media (max-width: @grid-float-breakpoint-max) {
- // Dropdowns get custom display when collapsed
- .open .dropdown-menu {
- > li > a {
- color: @navbar-default-link-color;
- &:hover,
- &:focus {
- color: @navbar-default-link-hover-color;
- background-color: @navbar-default-link-hover-bg;
- }
- }
- > .active > a {
- &,
- &:hover,
- &:focus {
- color: @navbar-default-link-active-color;
- background-color: @navbar-default-link-active-bg;
- }
- }
- > .disabled > a {
- &,
- &:hover,
- &:focus {
- color: @navbar-default-link-disabled-color;
- background-color: @navbar-default-link-disabled-bg;
- }
- }
- }
- }
- }
-
-
- // Links in navbars
- //
- // Add a class to ensure links outside the navbar nav are colored correctly.
-
- .navbar-link {
- color: @navbar-default-link-color;
- &:hover {
- color: @navbar-default-link-hover-color;
- }
- }
-
- .btn-link {
- color: @navbar-default-link-color;
- &:hover,
- &:focus {
- color: @navbar-default-link-hover-color;
- }
- &[disabled],
- fieldset[disabled] & {
- &:hover,
- &:focus {
- color: @navbar-default-link-disabled-color;
- }
- }
- }
-}
-
-// Inverse navbar
-
-.navbar-inverse {
- background-color: @navbar-inverse-bg;
- border-color: @navbar-inverse-border;
-
- .navbar-brand {
- color: @navbar-inverse-brand-color;
- &:hover,
- &:focus {
- color: @navbar-inverse-brand-hover-color;
- background-color: @navbar-inverse-brand-hover-bg;
- }
- }
-
- .navbar-text {
- color: @navbar-inverse-color;
- }
-
- .navbar-nav {
- > li > a {
- color: @navbar-inverse-link-color;
-
- &:hover,
- &:focus {
- color: @navbar-inverse-link-hover-color;
- background-color: @navbar-inverse-link-hover-bg;
- }
- }
- > .active > a {
- &,
- &:hover,
- &:focus {
- color: @navbar-inverse-link-active-color;
- background-color: @navbar-inverse-link-active-bg;
- }
- }
- > .disabled > a {
- &,
- &:hover,
- &:focus {
- color: @navbar-inverse-link-disabled-color;
- background-color: @navbar-inverse-link-disabled-bg;
- }
- }
- }
-
- // Darken the responsive nav toggle
- .navbar-toggle {
- border-color: @navbar-inverse-toggle-border-color;
- &:hover,
- &:focus {
- background-color: @navbar-inverse-toggle-hover-bg;
- }
- .icon-bar {
- background-color: @navbar-inverse-toggle-icon-bar-bg;
- }
- }
-
- .navbar-collapse,
- .navbar-form {
- border-color: darken(@navbar-inverse-bg, 7%);
- }
-
- // Dropdowns
- .navbar-nav {
- > .open > a {
- &,
- &:hover,
- &:focus {
- background-color: @navbar-inverse-link-active-bg;
- color: @navbar-inverse-link-active-color;
- }
- }
-
- @media (max-width: @grid-float-breakpoint-max) {
- // Dropdowns get custom display
- .open .dropdown-menu {
- > .dropdown-header {
- border-color: @navbar-inverse-border;
- }
- .divider {
- background-color: @navbar-inverse-border;
- }
- > li > a {
- color: @navbar-inverse-link-color;
- &:hover,
- &:focus {
- color: @navbar-inverse-link-hover-color;
- background-color: @navbar-inverse-link-hover-bg;
- }
- }
- > .active > a {
- &,
- &:hover,
- &:focus {
- color: @navbar-inverse-link-active-color;
- background-color: @navbar-inverse-link-active-bg;
- }
- }
- > .disabled > a {
- &,
- &:hover,
- &:focus {
- color: @navbar-inverse-link-disabled-color;
- background-color: @navbar-inverse-link-disabled-bg;
- }
- }
- }
- }
- }
-
- .navbar-link {
- color: @navbar-inverse-link-color;
- &:hover {
- color: @navbar-inverse-link-hover-color;
- }
- }
-
- .btn-link {
- color: @navbar-inverse-link-color;
- &:hover,
- &:focus {
- color: @navbar-inverse-link-hover-color;
- }
- &[disabled],
- fieldset[disabled] & {
- &:hover,
- &:focus {
- color: @navbar-inverse-link-disabled-color;
- }
- }
- }
-}
diff --git a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/navs.less b/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/navs.less
deleted file mode 100755
index a3d11b13621..00000000000
--- a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/navs.less
+++ /dev/null
@@ -1,242 +0,0 @@
-//
-// Navs
-// --------------------------------------------------
-
-
-// Base class
-// --------------------------------------------------
-
-.nav {
- margin-bottom: 0;
- padding-left: 0; // Override default ul/ol
- list-style: none;
- &:extend(.clearfix all);
-
- > li {
- position: relative;
- display: block;
-
- > a {
- position: relative;
- display: block;
- padding: @nav-link-padding;
- &:hover,
- &:focus {
- text-decoration: none;
- background-color: @nav-link-hover-bg;
- }
- }
-
- // Disabled state sets text to gray and nukes hover/tab effects
- &.disabled > a {
- color: @nav-disabled-link-color;
-
- &:hover,
- &:focus {
- color: @nav-disabled-link-hover-color;
- text-decoration: none;
- background-color: transparent;
- cursor: @cursor-disabled;
- }
- }
- }
-
- // Open dropdowns
- .open > a {
- &,
- &:hover,
- &:focus {
- background-color: @nav-link-hover-bg;
- border-color: @link-color;
- }
- }
-
- // Nav dividers (deprecated with v3.0.1)
- //
- // This should have been removed in v3 with the dropping of `.nav-list`, but
- // we missed it. We don't currently support this anywhere, but in the interest
- // of maintaining backward compatibility in case you use it, it's deprecated.
- .nav-divider {
- .nav-divider();
- }
-
- // Prevent IE8 from misplacing imgs
- //
- // See https://github.com/h5bp/html5-boilerplate/issues/984#issuecomment-3985989
- > li > a > img {
- max-width: none;
- }
-}
-
-
-// Tabs
-// -------------------------
-
-// Give the tabs something to sit on
-.nav-tabs {
- border-bottom: 1px solid @nav-tabs-border-color;
- > li {
- float: left;
- // Make the list-items overlay the bottom border
- margin-bottom: -1px;
-
- // Actual tabs (as links)
- > a {
- margin-right: 2px;
- line-height: @line-height-base;
- border: 1px solid transparent;
- border-radius: @border-radius-base @border-radius-base 0 0;
- &:hover {
- border-color: @nav-tabs-link-hover-border-color @nav-tabs-link-hover-border-color @nav-tabs-border-color;
- }
- }
-
- // Active state, and its :hover to override normal :hover
- &.active > a {
- &,
- &:hover,
- &:focus {
- color: @nav-tabs-active-link-hover-color;
- background-color: @nav-tabs-active-link-hover-bg;
- border: 1px solid @nav-tabs-active-link-hover-border-color;
- border-bottom-color: transparent;
- cursor: default;
- }
- }
- }
- // pulling this in mainly for less shorthand
- &.nav-justified {
- .nav-justified();
- .nav-tabs-justified();
- }
-}
-
-
-// Pills
-// -------------------------
-.nav-pills {
- > li {
- float: left;
-
- // Links rendered as pills
- > a {
- border-radius: @nav-pills-border-radius;
- }
- + li {
- margin-left: 2px;
- }
-
- // Active state
- &.active > a {
- &,
- &:hover,
- &:focus {
- color: @nav-pills-active-link-hover-color;
- background-color: @nav-pills-active-link-hover-bg;
- }
- }
- }
-}
-
-
-// Stacked pills
-.nav-stacked {
- > li {
- float: none;
- + li {
- margin-top: 2px;
- margin-left: 0; // no need for this gap between nav items
- }
- }
-}
-
-
-// Nav variations
-// --------------------------------------------------
-
-// Justified nav links
-// -------------------------
-
-.nav-justified {
- width: 100%;
-
- > li {
- float: none;
- > a {
- text-align: center;
- margin-bottom: 5px;
- }
- }
-
- > .dropdown .dropdown-menu {
- top: auto;
- left: auto;
- }
-
- @media (min-width: @screen-sm-min) {
- > li {
- display: table-cell;
- width: 1%;
- > a {
- margin-bottom: 0;
- }
- }
- }
-}
-
-// Move borders to anchors instead of bottom of list
-//
-// Mixin for adding on top the shared `.nav-justified` styles for our tabs
-.nav-tabs-justified {
- border-bottom: 0;
-
- > li > a {
- // Override margin from .nav-tabs
- margin-right: 0;
- border-radius: @border-radius-base;
- }
-
- > .active > a,
- > .active > a:hover,
- > .active > a:focus {
- border: 1px solid @nav-tabs-justified-link-border-color;
- }
-
- @media (min-width: @screen-sm-min) {
- > li > a {
- border-bottom: 1px solid @nav-tabs-justified-link-border-color;
- border-radius: @border-radius-base @border-radius-base 0 0;
- }
- > .active > a,
- > .active > a:hover,
- > .active > a:focus {
- border-bottom-color: @nav-tabs-justified-active-link-border-color;
- }
- }
-}
-
-
-// Tabbable tabs
-// -------------------------
-
-// Hide tabbable panes to start, show them when `.active`
-.tab-content {
- > .tab-pane {
- display: none;
- }
- > .active {
- display: block;
- }
-}
-
-
-// Dropdowns
-// -------------------------
-
-// Specific dropdowns
-.nav-tabs .dropdown-menu {
- // make dropdown border overlap tab border
- margin-top: -1px;
- // Remove the top rounded corners here since there is a hard edge above the menu
- .border-top-radius(0);
-}
diff --git a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/normalize.less b/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/normalize.less
deleted file mode 100755
index 9dddf73ad29..00000000000
--- a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/normalize.less
+++ /dev/null
@@ -1,424 +0,0 @@
-/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */
-
-//
-// 1. Set default font family to sans-serif.
-// 2. Prevent iOS and IE text size adjust after device orientation change,
-// without disabling user zoom.
-//
-
-html {
- font-family: sans-serif; // 1
- -ms-text-size-adjust: 100%; // 2
- -webkit-text-size-adjust: 100%; // 2
-}
-
-//
-// Remove default margin.
-//
-
-body {
- margin: 0;
-}
-
-// HTML5 display definitions
-// ==========================================================================
-
-//
-// Correct `block` display not defined for any HTML5 element in IE 8/9.
-// Correct `block` display not defined for `details` or `summary` in IE 10/11
-// and Firefox.
-// Correct `block` display not defined for `main` in IE 11.
-//
-
-article,
-aside,
-details,
-figcaption,
-figure,
-footer,
-header,
-hgroup,
-main,
-menu,
-nav,
-section,
-summary {
- display: block;
-}
-
-//
-// 1. Correct `inline-block` display not defined in IE 8/9.
-// 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.
-//
-
-audio,
-canvas,
-progress,
-video {
- display: inline-block; // 1
- vertical-align: baseline; // 2
-}
-
-//
-// Prevent modern browsers from displaying `audio` without controls.
-// Remove excess height in iOS 5 devices.
-//
-
-audio:not([controls]) {
- display: none;
- height: 0;
-}
-
-//
-// Address `[hidden]` styling not present in IE 8/9/10.
-// Hide the `template` element in IE 8/9/10/11, Safari, and Firefox < 22.
-//
-
-[hidden],
-template {
- display: none;
-}
-
-// Links
-// ==========================================================================
-
-//
-// Remove the gray background color from active links in IE 10.
-//
-
-a {
- background-color: transparent;
-}
-
-//
-// Improve readability of focused elements when they are also in an
-// active/hover state.
-//
-
-a:active,
-a:hover {
- outline: 0;
-}
-
-// Text-level semantics
-// ==========================================================================
-
-//
-// Address styling not present in IE 8/9/10/11, Safari, and Chrome.
-//
-
-abbr[title] {
- border-bottom: 1px dotted;
-}
-
-//
-// Address style set to `bolder` in Firefox 4+, Safari, and Chrome.
-//
-
-b,
-strong {
- font-weight: bold;
-}
-
-//
-// Address styling not present in Safari and Chrome.
-//
-
-dfn {
- font-style: italic;
-}
-
-//
-// Address variable `h1` font-size and margin within `section` and `article`
-// contexts in Firefox 4+, Safari, and Chrome.
-//
-
-h1 {
- font-size: 2em;
- margin: 0.67em 0;
-}
-
-//
-// Address styling not present in IE 8/9.
-//
-
-mark {
- background: #ff0;
- color: #000;
-}
-
-//
-// Address inconsistent and variable font size in all browsers.
-//
-
-small {
- font-size: 80%;
-}
-
-//
-// Prevent `sub` and `sup` affecting `line-height` in all browsers.
-//
-
-sub,
-sup {
- font-size: 75%;
- line-height: 0;
- position: relative;
- vertical-align: baseline;
-}
-
-sup {
- top: -0.5em;
-}
-
-sub {
- bottom: -0.25em;
-}
-
-// Embedded content
-// ==========================================================================
-
-//
-// Remove border when inside `a` element in IE 8/9/10.
-//
-
-img {
- border: 0;
-}
-
-//
-// Correct overflow not hidden in IE 9/10/11.
-//
-
-svg:not(:root) {
- overflow: hidden;
-}
-
-// Grouping content
-// ==========================================================================
-
-//
-// Address margin not present in IE 8/9 and Safari.
-//
-
-figure {
- margin: 1em 40px;
-}
-
-//
-// Address differences between Firefox and other browsers.
-//
-
-hr {
- box-sizing: content-box;
- height: 0;
-}
-
-//
-// Contain overflow in all browsers.
-//
-
-pre {
- overflow: auto;
-}
-
-//
-// Address odd `em`-unit font size rendering in all browsers.
-//
-
-code,
-kbd,
-pre,
-samp {
- font-family: monospace, monospace;
- font-size: 1em;
-}
-
-// Forms
-// ==========================================================================
-
-//
-// Known limitation: by default, Chrome and Safari on OS X allow very limited
-// styling of `select`, unless a `border` property is set.
-//
-
-//
-// 1. Correct color not being inherited.
-// Known issue: affects color of disabled elements.
-// 2. Correct font properties not being inherited.
-// 3. Address margins set differently in Firefox 4+, Safari, and Chrome.
-//
-
-button,
-input,
-optgroup,
-select,
-textarea {
- color: inherit; // 1
- font: inherit; // 2
- margin: 0; // 3
-}
-
-//
-// Address `overflow` set to `hidden` in IE 8/9/10/11.
-//
-
-button {
- overflow: visible;
-}
-
-//
-// Address inconsistent `text-transform` inheritance for `button` and `select`.
-// All other form control elements do not inherit `text-transform` values.
-// Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera.
-// Correct `select` style inheritance in Firefox.
-//
-
-button,
-select {
- text-transform: none;
-}
-
-//
-// 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
-// and `video` controls.
-// 2. Correct inability to style clickable `input` types in iOS.
-// 3. Improve usability and consistency of cursor style between image-type
-// `input` and others.
-//
-
-button,
-html input[type="button"], // 1
-input[type="reset"],
-input[type="submit"] {
- -webkit-appearance: button; // 2
- cursor: pointer; // 3
-}
-
-//
-// Re-set default cursor for disabled elements.
-//
-
-button[disabled],
-html input[disabled] {
- cursor: default;
-}
-
-//
-// Remove inner padding and border in Firefox 4+.
-//
-
-button::-moz-focus-inner,
-input::-moz-focus-inner {
- border: 0;
- padding: 0;
-}
-
-//
-// Address Firefox 4+ setting `line-height` on `input` using `!important` in
-// the UA stylesheet.
-//
-
-input {
- line-height: normal;
-}
-
-//
-// It's recommended that you don't attempt to style these elements.
-// Firefox's implementation doesn't respect box-sizing, padding, or width.
-//
-// 1. Address box sizing set to `content-box` in IE 8/9/10.
-// 2. Remove excess padding in IE 8/9/10.
-//
-
-input[type="checkbox"],
-input[type="radio"] {
- box-sizing: border-box; // 1
- padding: 0; // 2
-}
-
-//
-// Fix the cursor style for Chrome's increment/decrement buttons. For certain
-// `font-size` values of the `input`, it causes the cursor style of the
-// decrement button to change from `default` to `text`.
-//
-
-input[type="number"]::-webkit-inner-spin-button,
-input[type="number"]::-webkit-outer-spin-button {
- height: auto;
-}
-
-//
-// 1. Address `appearance` set to `searchfield` in Safari and Chrome.
-// 2. Address `box-sizing` set to `border-box` in Safari and Chrome.
-//
-
-input[type="search"] {
- -webkit-appearance: textfield; // 1
- box-sizing: content-box; //2
-}
-
-//
-// Remove inner padding and search cancel button in Safari and Chrome on OS X.
-// Safari (but not Chrome) clips the cancel button when the search input has
-// padding (and `textfield` appearance).
-//
-
-input[type="search"]::-webkit-search-cancel-button,
-input[type="search"]::-webkit-search-decoration {
- -webkit-appearance: none;
-}
-
-//
-// Define consistent border, margin, and padding.
-//
-
-fieldset {
- border: 1px solid #c0c0c0;
- margin: 0 2px;
- padding: 0.35em 0.625em 0.75em;
-}
-
-//
-// 1. Correct `color` not being inherited in IE 8/9/10/11.
-// 2. Remove padding so people aren't caught out if they zero out fieldsets.
-//
-
-legend {
- border: 0; // 1
- padding: 0; // 2
-}
-
-//
-// Remove default vertical scrollbar in IE 8/9/10/11.
-//
-
-textarea {
- overflow: auto;
-}
-
-//
-// Don't inherit the `font-weight` (applied by a rule above).
-// NOTE: the default cannot safely be changed in Chrome and Safari on OS X.
-//
-
-optgroup {
- font-weight: bold;
-}
-
-// Tables
-// ==========================================================================
-
-//
-// Remove most spacing between table cells.
-//
-
-table {
- border-collapse: collapse;
- border-spacing: 0;
-}
-
-td,
-th {
- padding: 0;
-}
diff --git a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/pager.less b/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/pager.less
deleted file mode 100755
index 41abaaadc5d..00000000000
--- a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/pager.less
+++ /dev/null
@@ -1,54 +0,0 @@
-//
-// Pager pagination
-// --------------------------------------------------
-
-
-.pager {
- padding-left: 0;
- margin: @line-height-computed 0;
- list-style: none;
- text-align: center;
- &:extend(.clearfix all);
- li {
- display: inline;
- > a,
- > span {
- display: inline-block;
- padding: 5px 14px;
- background-color: @pager-bg;
- border: 1px solid @pager-border;
- border-radius: @pager-border-radius;
- }
-
- > a:hover,
- > a:focus {
- text-decoration: none;
- background-color: @pager-hover-bg;
- }
- }
-
- .next {
- > a,
- > span {
- float: right;
- }
- }
-
- .previous {
- > a,
- > span {
- float: left;
- }
- }
-
- .disabled {
- > a,
- > a:hover,
- > a:focus,
- > span {
- color: @pager-disabled-color;
- background-color: @pager-bg;
- cursor: @cursor-disabled;
- }
- }
-}
diff --git a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/pagination.less b/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/pagination.less
deleted file mode 100755
index 31f77aae4ed..00000000000
--- a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/pagination.less
+++ /dev/null
@@ -1,89 +0,0 @@
-//
-// Pagination (multiple pages)
-// --------------------------------------------------
-.pagination {
- display: inline-block;
- padding-left: 0;
- margin: @line-height-computed 0;
- border-radius: @border-radius-base;
-
- > li {
- display: inline; // Remove list-style and block-level defaults
- > a,
- > span {
- position: relative;
- float: left; // Collapse white-space
- padding: @padding-base-vertical @padding-base-horizontal;
- line-height: @line-height-base;
- text-decoration: none;
- color: @pagination-color;
- background-color: @pagination-bg;
- border: 1px solid @pagination-border;
- margin-left: -1px;
- }
- &:first-child {
- > a,
- > span {
- margin-left: 0;
- .border-left-radius(@border-radius-base);
- }
- }
- &:last-child {
- > a,
- > span {
- .border-right-radius(@border-radius-base);
- }
- }
- }
-
- > li > a,
- > li > span {
- &:hover,
- &:focus {
- z-index: 2;
- color: @pagination-hover-color;
- background-color: @pagination-hover-bg;
- border-color: @pagination-hover-border;
- }
- }
-
- > .active > a,
- > .active > span {
- &,
- &:hover,
- &:focus {
- z-index: 3;
- color: @pagination-active-color;
- background-color: @pagination-active-bg;
- border-color: @pagination-active-border;
- cursor: default;
- }
- }
-
- > .disabled {
- > span,
- > span:hover,
- > span:focus,
- > a,
- > a:hover,
- > a:focus {
- color: @pagination-disabled-color;
- background-color: @pagination-disabled-bg;
- border-color: @pagination-disabled-border;
- cursor: @cursor-disabled;
- }
- }
-}
-
-// Sizing
-// --------------------------------------------------
-
-// Large
-.pagination-lg {
- .pagination-size(@padding-large-vertical; @padding-large-horizontal; @font-size-large; @line-height-large; @border-radius-large);
-}
-
-// Small
-.pagination-sm {
- .pagination-size(@padding-small-vertical; @padding-small-horizontal; @font-size-small; @line-height-small; @border-radius-small);
-}
diff --git a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/panels.less b/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/panels.less
deleted file mode 100755
index 425eb5e642c..00000000000
--- a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/panels.less
+++ /dev/null
@@ -1,271 +0,0 @@
-//
-// Panels
-// --------------------------------------------------
-
-
-// Base class
-.panel {
- margin-bottom: @line-height-computed;
- background-color: @panel-bg;
- border: 1px solid transparent;
- border-radius: @panel-border-radius;
- .box-shadow(0 1px 1px rgba(0,0,0,.05));
-}
-
-// Panel contents
-.panel-body {
- padding: @panel-body-padding;
- &:extend(.clearfix all);
-}
-
-// Optional heading
-.panel-heading {
- padding: @panel-heading-padding;
- border-bottom: 1px solid transparent;
- .border-top-radius((@panel-border-radius - 1));
-
- > .dropdown .dropdown-toggle {
- color: inherit;
- }
-}
-
-// Within heading, strip any `h*` tag of its default margins for spacing.
-.panel-title {
- margin-top: 0;
- margin-bottom: 0;
- font-size: ceil((@font-size-base * 1.125));
- color: inherit;
-
- > a,
- > small,
- > .small,
- > small > a,
- > .small > a {
- color: inherit;
- }
-}
-
-// Optional footer (stays gray in every modifier class)
-.panel-footer {
- padding: @panel-footer-padding;
- background-color: @panel-footer-bg;
- border-top: 1px solid @panel-inner-border;
- .border-bottom-radius((@panel-border-radius - 1));
-}
-
-
-// List groups in panels
-//
-// By default, space out list group content from panel headings to account for
-// any kind of custom content between the two.
-
-.panel {
- > .list-group,
- > .panel-collapse > .list-group {
- margin-bottom: 0;
-
- .list-group-item {
- border-width: 1px 0;
- border-radius: 0;
- }
-
- // Add border top radius for first one
- &:first-child {
- .list-group-item:first-child {
- border-top: 0;
- .border-top-radius((@panel-border-radius - 1));
- }
- }
-
- // Add border bottom radius for last one
- &:last-child {
- .list-group-item:last-child {
- border-bottom: 0;
- .border-bottom-radius((@panel-border-radius - 1));
- }
- }
- }
- > .panel-heading + .panel-collapse > .list-group {
- .list-group-item:first-child {
- .border-top-radius(0);
- }
- }
-}
-// Collapse space between when there's no additional content.
-.panel-heading + .list-group {
- .list-group-item:first-child {
- border-top-width: 0;
- }
-}
-.list-group + .panel-footer {
- border-top-width: 0;
-}
-
-// Tables in panels
-//
-// Place a non-bordered `.table` within a panel (not within a `.panel-body`) and
-// watch it go full width.
-
-.panel {
- > .table,
- > .table-responsive > .table,
- > .panel-collapse > .table {
- margin-bottom: 0;
-
- caption {
- padding-left: @panel-body-padding;
- padding-right: @panel-body-padding;
- }
- }
- // Add border top radius for first one
- > .table:first-child,
- > .table-responsive:first-child > .table:first-child {
- .border-top-radius((@panel-border-radius - 1));
-
- > thead:first-child,
- > tbody:first-child {
- > tr:first-child {
- border-top-left-radius: (@panel-border-radius - 1);
- border-top-right-radius: (@panel-border-radius - 1);
-
- td:first-child,
- th:first-child {
- border-top-left-radius: (@panel-border-radius - 1);
- }
- td:last-child,
- th:last-child {
- border-top-right-radius: (@panel-border-radius - 1);
- }
- }
- }
- }
- // Add border bottom radius for last one
- > .table:last-child,
- > .table-responsive:last-child > .table:last-child {
- .border-bottom-radius((@panel-border-radius - 1));
-
- > tbody:last-child,
- > tfoot:last-child {
- > tr:last-child {
- border-bottom-left-radius: (@panel-border-radius - 1);
- border-bottom-right-radius: (@panel-border-radius - 1);
-
- td:first-child,
- th:first-child {
- border-bottom-left-radius: (@panel-border-radius - 1);
- }
- td:last-child,
- th:last-child {
- border-bottom-right-radius: (@panel-border-radius - 1);
- }
- }
- }
- }
- > .panel-body + .table,
- > .panel-body + .table-responsive,
- > .table + .panel-body,
- > .table-responsive + .panel-body {
- border-top: 1px solid @table-border-color;
- }
- > .table > tbody:first-child > tr:first-child th,
- > .table > tbody:first-child > tr:first-child td {
- border-top: 0;
- }
- > .table-bordered,
- > .table-responsive > .table-bordered {
- border: 0;
- > thead,
- > tbody,
- > tfoot {
- > tr {
- > th:first-child,
- > td:first-child {
- border-left: 0;
- }
- > th:last-child,
- > td:last-child {
- border-right: 0;
- }
- }
- }
- > thead,
- > tbody {
- > tr:first-child {
- > td,
- > th {
- border-bottom: 0;
- }
- }
- }
- > tbody,
- > tfoot {
- > tr:last-child {
- > td,
- > th {
- border-bottom: 0;
- }
- }
- }
- }
- > .table-responsive {
- border: 0;
- margin-bottom: 0;
- }
-}
-
-
-// Collapsable panels (aka, accordion)
-//
-// Wrap a series of panels in `.panel-group` to turn them into an accordion with
-// the help of our collapse JavaScript plugin.
-
-.panel-group {
- margin-bottom: @line-height-computed;
-
- // Tighten up margin so it's only between panels
- .panel {
- margin-bottom: 0;
- border-radius: @panel-border-radius;
-
- + .panel {
- margin-top: 5px;
- }
- }
-
- .panel-heading {
- border-bottom: 0;
-
- + .panel-collapse > .panel-body,
- + .panel-collapse > .list-group {
- border-top: 1px solid @panel-inner-border;
- }
- }
-
- .panel-footer {
- border-top: 0;
- + .panel-collapse .panel-body {
- border-bottom: 1px solid @panel-inner-border;
- }
- }
-}
-
-
-// Contextual variations
-.panel-default {
- .panel-variant(@panel-default-border; @panel-default-text; @panel-default-heading-bg; @panel-default-border);
-}
-.panel-primary {
- .panel-variant(@panel-primary-border; @panel-primary-text; @panel-primary-heading-bg; @panel-primary-border);
-}
-.panel-success {
- .panel-variant(@panel-success-border; @panel-success-text; @panel-success-heading-bg; @panel-success-border);
-}
-.panel-info {
- .panel-variant(@panel-info-border; @panel-info-text; @panel-info-heading-bg; @panel-info-border);
-}
-.panel-warning {
- .panel-variant(@panel-warning-border; @panel-warning-text; @panel-warning-heading-bg; @panel-warning-border);
-}
-.panel-danger {
- .panel-variant(@panel-danger-border; @panel-danger-text; @panel-danger-heading-bg; @panel-danger-border);
-}
diff --git a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/popovers.less b/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/popovers.less
deleted file mode 100755
index 3a62a6455ac..00000000000
--- a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/popovers.less
+++ /dev/null
@@ -1,131 +0,0 @@
-//
-// Popovers
-// --------------------------------------------------
-
-
-.popover {
- position: absolute;
- top: 0;
- left: 0;
- z-index: @zindex-popover;
- display: none;
- max-width: @popover-max-width;
- padding: 1px;
- // Our parent element can be arbitrary since popovers are by default inserted as a sibling of their target element.
- // So reset our font and text properties to avoid inheriting weird values.
- .reset-text();
- font-size: @font-size-base;
-
- background-color: @popover-bg;
- background-clip: padding-box;
- border: 1px solid @popover-fallback-border-color;
- border: 1px solid @popover-border-color;
- border-radius: @border-radius-large;
- .box-shadow(0 5px 10px rgba(0,0,0,.2));
-
- // Offset the popover to account for the popover arrow
- &.top { margin-top: -@popover-arrow-width; }
- &.right { margin-left: @popover-arrow-width; }
- &.bottom { margin-top: @popover-arrow-width; }
- &.left { margin-left: -@popover-arrow-width; }
-}
-
-.popover-title {
- margin: 0; // reset heading margin
- padding: 8px 14px;
- font-size: @font-size-base;
- background-color: @popover-title-bg;
- border-bottom: 1px solid darken(@popover-title-bg, 5%);
- border-radius: (@border-radius-large - 1) (@border-radius-large - 1) 0 0;
-}
-
-.popover-content {
- padding: 9px 14px;
-}
-
-// Arrows
-//
-// .arrow is outer, .arrow:after is inner
-
-.popover > .arrow {
- &,
- &:after {
- position: absolute;
- display: block;
- width: 0;
- height: 0;
- border-color: transparent;
- border-style: solid;
- }
-}
-.popover > .arrow {
- border-width: @popover-arrow-outer-width;
-}
-.popover > .arrow:after {
- border-width: @popover-arrow-width;
- content: "";
-}
-
-.popover {
- &.top > .arrow {
- left: 50%;
- margin-left: -@popover-arrow-outer-width;
- border-bottom-width: 0;
- border-top-color: @popover-arrow-outer-fallback-color; // IE8 fallback
- border-top-color: @popover-arrow-outer-color;
- bottom: -@popover-arrow-outer-width;
- &:after {
- content: " ";
- bottom: 1px;
- margin-left: -@popover-arrow-width;
- border-bottom-width: 0;
- border-top-color: @popover-arrow-color;
- }
- }
- &.right > .arrow {
- top: 50%;
- left: -@popover-arrow-outer-width;
- margin-top: -@popover-arrow-outer-width;
- border-left-width: 0;
- border-right-color: @popover-arrow-outer-fallback-color; // IE8 fallback
- border-right-color: @popover-arrow-outer-color;
- &:after {
- content: " ";
- left: 1px;
- bottom: -@popover-arrow-width;
- border-left-width: 0;
- border-right-color: @popover-arrow-color;
- }
- }
- &.bottom > .arrow {
- left: 50%;
- margin-left: -@popover-arrow-outer-width;
- border-top-width: 0;
- border-bottom-color: @popover-arrow-outer-fallback-color; // IE8 fallback
- border-bottom-color: @popover-arrow-outer-color;
- top: -@popover-arrow-outer-width;
- &:after {
- content: " ";
- top: 1px;
- margin-left: -@popover-arrow-width;
- border-top-width: 0;
- border-bottom-color: @popover-arrow-color;
- }
- }
-
- &.left > .arrow {
- top: 50%;
- right: -@popover-arrow-outer-width;
- margin-top: -@popover-arrow-outer-width;
- border-right-width: 0;
- border-left-color: @popover-arrow-outer-fallback-color; // IE8 fallback
- border-left-color: @popover-arrow-outer-color;
- &:after {
- content: " ";
- right: 1px;
- border-right-width: 0;
- border-left-color: @popover-arrow-color;
- bottom: -@popover-arrow-width;
- }
- }
-}
diff --git a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/print.less b/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/print.less
deleted file mode 100755
index 66e54ab489e..00000000000
--- a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/print.less
+++ /dev/null
@@ -1,101 +0,0 @@
-/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */
-
-// ==========================================================================
-// Print styles.
-// Inlined to avoid the additional HTTP request: h5bp.com/r
-// ==========================================================================
-
-@media print {
- *,
- *:before,
- *:after {
- background: transparent !important;
- color: #000 !important; // Black prints faster: h5bp.com/s
- box-shadow: none !important;
- text-shadow: none !important;
- }
-
- a,
- a:visited {
- text-decoration: underline;
- }
-
- a[href]:after {
- content: " (" attr(href) ")";
- }
-
- abbr[title]:after {
- content: " (" attr(title) ")";
- }
-
- // Don't show links that are fragment identifiers,
- // or use the `javascript:` pseudo protocol
- a[href^="#"]:after,
- a[href^="javascript:"]:after {
- content: "";
- }
-
- pre,
- blockquote {
- border: 1px solid #999;
- page-break-inside: avoid;
- }
-
- thead {
- display: table-header-group; // h5bp.com/t
- }
-
- tr,
- img {
- page-break-inside: avoid;
- }
-
- img {
- max-width: 100% !important;
- }
-
- p,
- h2,
- h3 {
- orphans: 3;
- widows: 3;
- }
-
- h2,
- h3 {
- page-break-after: avoid;
- }
-
- // Bootstrap specific changes start
-
- // Bootstrap components
- .navbar {
- display: none;
- }
- .btn,
- .dropup > .btn {
- > .caret {
- border-top-color: #000 !important;
- }
- }
- .label {
- border: 1px solid #000;
- }
-
- .table {
- border-collapse: collapse !important;
-
- td,
- th {
- background-color: #fff !important;
- }
- }
- .table-bordered {
- th,
- td {
- border: 1px solid #ddd !important;
- }
- }
-
- // Bootstrap specific changes end
-}
diff --git a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/progress-bars.less b/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/progress-bars.less
deleted file mode 100755
index 8868a1feef0..00000000000
--- a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/progress-bars.less
+++ /dev/null
@@ -1,87 +0,0 @@
-//
-// Progress bars
-// --------------------------------------------------
-
-
-// Bar animations
-// -------------------------
-
-// WebKit
-@-webkit-keyframes progress-bar-stripes {
- from { background-position: 40px 0; }
- to { background-position: 0 0; }
-}
-
-// Spec and IE10+
-@keyframes progress-bar-stripes {
- from { background-position: 40px 0; }
- to { background-position: 0 0; }
-}
-
-
-// Bar itself
-// -------------------------
-
-// Outer container
-.progress {
- overflow: hidden;
- height: @line-height-computed;
- margin-bottom: @line-height-computed;
- background-color: @progress-bg;
- border-radius: @progress-border-radius;
- .box-shadow(inset 0 1px 2px rgba(0,0,0,.1));
-}
-
-// Bar of progress
-.progress-bar {
- float: left;
- width: 0%;
- height: 100%;
- font-size: @font-size-small;
- line-height: @line-height-computed;
- color: @progress-bar-color;
- text-align: center;
- background-color: @progress-bar-bg;
- .box-shadow(inset 0 -1px 0 rgba(0,0,0,.15));
- .transition(width .6s ease);
-}
-
-// Striped bars
-//
-// `.progress-striped .progress-bar` is deprecated as of v3.2.0 in favor of the
-// `.progress-bar-striped` class, which you just add to an existing
-// `.progress-bar`.
-.progress-striped .progress-bar,
-.progress-bar-striped {
- #gradient > .striped();
- background-size: 40px 40px;
-}
-
-// Call animation for the active one
-//
-// `.progress.active .progress-bar` is deprecated as of v3.2.0 in favor of the
-// `.progress-bar.active` approach.
-.progress.active .progress-bar,
-.progress-bar.active {
- .animation(progress-bar-stripes 2s linear infinite);
-}
-
-
-// Variations
-// -------------------------
-
-.progress-bar-success {
- .progress-bar-variant(@progress-bar-success-bg);
-}
-
-.progress-bar-info {
- .progress-bar-variant(@progress-bar-info-bg);
-}
-
-.progress-bar-warning {
- .progress-bar-variant(@progress-bar-warning-bg);
-}
-
-.progress-bar-danger {
- .progress-bar-variant(@progress-bar-danger-bg);
-}
diff --git a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/responsive-embed.less b/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/responsive-embed.less
deleted file mode 100755
index 080a5118fe9..00000000000
--- a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/responsive-embed.less
+++ /dev/null
@@ -1,35 +0,0 @@
-// Embeds responsive
-//
-// Credit: Nicolas Gallagher and SUIT CSS.
-
-.embed-responsive {
- position: relative;
- display: block;
- height: 0;
- padding: 0;
- overflow: hidden;
-
- .embed-responsive-item,
- iframe,
- embed,
- object,
- video {
- position: absolute;
- top: 0;
- left: 0;
- bottom: 0;
- height: 100%;
- width: 100%;
- border: 0;
- }
-}
-
-// Modifier class for 16:9 aspect ratio
-.embed-responsive-16by9 {
- padding-bottom: 56.25%;
-}
-
-// Modifier class for 4:3 aspect ratio
-.embed-responsive-4by3 {
- padding-bottom: 75%;
-}
diff --git a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/responsive-utilities.less b/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/responsive-utilities.less
deleted file mode 100755
index b1db31d7bfc..00000000000
--- a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/responsive-utilities.less
+++ /dev/null
@@ -1,194 +0,0 @@
-//
-// Responsive: Utility classes
-// --------------------------------------------------
-
-
-// IE10 in Windows (Phone) 8
-//
-// Support for responsive views via media queries is kind of borked in IE10, for
-// Surface/desktop in split view and for Windows Phone 8. This particular fix
-// must be accompanied by a snippet of JavaScript to sniff the user agent and
-// apply some conditional CSS to *only* the Surface/desktop Windows 8. Look at
-// our Getting Started page for more information on this bug.
-//
-// For more information, see the following:
-//
-// Issue: https://github.com/twbs/bootstrap/issues/10497
-// Docs: http://getbootstrap.com/getting-started/#support-ie10-width
-// Source: http://timkadlec.com/2013/01/windows-phone-8-and-device-width/
-// Source: http://timkadlec.com/2012/10/ie10-snap-mode-and-responsive-design/
-
-@-ms-viewport {
- width: device-width;
-}
-
-
-// Visibility utilities
-// Note: Deprecated .visible-xs, .visible-sm, .visible-md, and .visible-lg as of v3.2.0
-.visible-xs,
-.visible-sm,
-.visible-md,
-.visible-lg {
- .responsive-invisibility();
-}
-
-.visible-xs-block,
-.visible-xs-inline,
-.visible-xs-inline-block,
-.visible-sm-block,
-.visible-sm-inline,
-.visible-sm-inline-block,
-.visible-md-block,
-.visible-md-inline,
-.visible-md-inline-block,
-.visible-lg-block,
-.visible-lg-inline,
-.visible-lg-inline-block {
- display: none !important;
-}
-
-.visible-xs {
- @media (max-width: @screen-xs-max) {
- .responsive-visibility();
- }
-}
-.visible-xs-block {
- @media (max-width: @screen-xs-max) {
- display: block !important;
- }
-}
-.visible-xs-inline {
- @media (max-width: @screen-xs-max) {
- display: inline !important;
- }
-}
-.visible-xs-inline-block {
- @media (max-width: @screen-xs-max) {
- display: inline-block !important;
- }
-}
-
-.visible-sm {
- @media (min-width: @screen-sm-min) and (max-width: @screen-sm-max) {
- .responsive-visibility();
- }
-}
-.visible-sm-block {
- @media (min-width: @screen-sm-min) and (max-width: @screen-sm-max) {
- display: block !important;
- }
-}
-.visible-sm-inline {
- @media (min-width: @screen-sm-min) and (max-width: @screen-sm-max) {
- display: inline !important;
- }
-}
-.visible-sm-inline-block {
- @media (min-width: @screen-sm-min) and (max-width: @screen-sm-max) {
- display: inline-block !important;
- }
-}
-
-.visible-md {
- @media (min-width: @screen-md-min) and (max-width: @screen-md-max) {
- .responsive-visibility();
- }
-}
-.visible-md-block {
- @media (min-width: @screen-md-min) and (max-width: @screen-md-max) {
- display: block !important;
- }
-}
-.visible-md-inline {
- @media (min-width: @screen-md-min) and (max-width: @screen-md-max) {
- display: inline !important;
- }
-}
-.visible-md-inline-block {
- @media (min-width: @screen-md-min) and (max-width: @screen-md-max) {
- display: inline-block !important;
- }
-}
-
-.visible-lg {
- @media (min-width: @screen-lg-min) {
- .responsive-visibility();
- }
-}
-.visible-lg-block {
- @media (min-width: @screen-lg-min) {
- display: block !important;
- }
-}
-.visible-lg-inline {
- @media (min-width: @screen-lg-min) {
- display: inline !important;
- }
-}
-.visible-lg-inline-block {
- @media (min-width: @screen-lg-min) {
- display: inline-block !important;
- }
-}
-
-.hidden-xs {
- @media (max-width: @screen-xs-max) {
- .responsive-invisibility();
- }
-}
-.hidden-sm {
- @media (min-width: @screen-sm-min) and (max-width: @screen-sm-max) {
- .responsive-invisibility();
- }
-}
-.hidden-md {
- @media (min-width: @screen-md-min) and (max-width: @screen-md-max) {
- .responsive-invisibility();
- }
-}
-.hidden-lg {
- @media (min-width: @screen-lg-min) {
- .responsive-invisibility();
- }
-}
-
-
-// Print utilities
-//
-// Media queries are placed on the inside to be mixin-friendly.
-
-// Note: Deprecated .visible-print as of v3.2.0
-.visible-print {
- .responsive-invisibility();
-
- @media print {
- .responsive-visibility();
- }
-}
-.visible-print-block {
- display: none !important;
-
- @media print {
- display: block !important;
- }
-}
-.visible-print-inline {
- display: none !important;
-
- @media print {
- display: inline !important;
- }
-}
-.visible-print-inline-block {
- display: none !important;
-
- @media print {
- display: inline-block !important;
- }
-}
-
-.hidden-print {
- @media print {
- .responsive-invisibility();
- }
-}
diff --git a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/scaffolding.less b/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/scaffolding.less
deleted file mode 100755
index 1929bfc5cfa..00000000000
--- a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/scaffolding.less
+++ /dev/null
@@ -1,161 +0,0 @@
-//
-// Scaffolding
-// --------------------------------------------------
-
-
-// Reset the box-sizing
-//
-// Heads up! This reset may cause conflicts with some third-party widgets.
-// For recommendations on resolving such conflicts, see
-// http://getbootstrap.com/getting-started/#third-box-sizing
-* {
- .box-sizing(border-box);
-}
-*:before,
-*:after {
- .box-sizing(border-box);
-}
-
-
-// Body reset
-
-html {
- font-size: 10px;
- -webkit-tap-highlight-color: rgba(0,0,0,0);
-}
-
-body {
- font-family: @font-family-base;
- font-size: @font-size-base;
- line-height: @line-height-base;
- color: @text-color;
- background-color: @body-bg;
-}
-
-// Reset fonts for relevant elements
-input,
-button,
-select,
-textarea {
- font-family: inherit;
- font-size: inherit;
- line-height: inherit;
-}
-
-
-// Links
-
-a {
- color: @link-color;
- text-decoration: none;
-
- &:hover,
- &:focus {
- color: @link-hover-color;
- text-decoration: @link-hover-decoration;
- }
-
- &:focus {
- .tab-focus();
- }
-}
-
-
-// Figures
-//
-// We reset this here because previously Normalize had no `figure` margins. This
-// ensures we don't break anyone's use of the element.
-
-figure {
- margin: 0;
-}
-
-
-// Images
-
-img {
- vertical-align: middle;
-}
-
-// Responsive images (ensure images don't scale beyond their parents)
-.img-responsive {
- .img-responsive();
-}
-
-// Rounded corners
-.img-rounded {
- border-radius: @border-radius-large;
-}
-
-// Image thumbnails
-//
-// Heads up! This is mixin-ed into thumbnails.less for `.thumbnail`.
-.img-thumbnail {
- padding: @thumbnail-padding;
- line-height: @line-height-base;
- background-color: @thumbnail-bg;
- border: 1px solid @thumbnail-border;
- border-radius: @thumbnail-border-radius;
- .transition(all .2s ease-in-out);
-
- // Keep them at most 100% wide
- .img-responsive(inline-block);
-}
-
-// Perfect circle
-.img-circle {
- border-radius: 50%; // set radius in percents
-}
-
-
-// Horizontal rules
-
-hr {
- margin-top: @line-height-computed;
- margin-bottom: @line-height-computed;
- border: 0;
- border-top: 1px solid @hr-border;
-}
-
-
-// Only display content to screen readers
-//
-// See: http://a11yproject.com/posts/how-to-hide-content/
-
-.sr-only {
- position: absolute;
- width: 1px;
- height: 1px;
- margin: -1px;
- padding: 0;
- overflow: hidden;
- clip: rect(0,0,0,0);
- border: 0;
-}
-
-// Use in conjunction with .sr-only to only display content when it's focused.
-// Useful for "Skip to main content" links; see http://www.w3.org/TR/2013/NOTE-WCAG20-TECHS-20130905/G1
-// Credit: HTML5 Boilerplate
-
-.sr-only-focusable {
- &:active,
- &:focus {
- position: static;
- width: auto;
- height: auto;
- margin: 0;
- overflow: visible;
- clip: auto;
- }
-}
-
-
-// iOS "clickable elements" fix for role="button"
-//
-// Fixes "clickability" issue (and more generally, the firing of events such as focus as well)
-// for traditionally non-focusable elements with role="button"
-// see https://developer.mozilla.org/en-US/docs/Web/Events/click#Safari_Mobile
-
-[role="button"] {
- cursor: pointer;
-}
diff --git a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/tables.less b/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/tables.less
deleted file mode 100755
index 2242c036868..00000000000
--- a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/tables.less
+++ /dev/null
@@ -1,234 +0,0 @@
-//
-// Tables
-// --------------------------------------------------
-
-
-table {
- background-color: @table-bg;
-}
-caption {
- padding-top: @table-cell-padding;
- padding-bottom: @table-cell-padding;
- color: @text-muted;
- text-align: left;
-}
-th {
- text-align: left;
-}
-
-
-// Baseline styles
-
-.table {
- width: 100%;
- max-width: 100%;
- margin-bottom: @line-height-computed;
- // Cells
- > thead,
- > tbody,
- > tfoot {
- > tr {
- > th,
- > td {
- padding: @table-cell-padding;
- line-height: @line-height-base;
- vertical-align: top;
- border-top: 1px solid @table-border-color;
- }
- }
- }
- // Bottom align for column headings
- > thead > tr > th {
- vertical-align: bottom;
- border-bottom: 2px solid @table-border-color;
- }
- // Remove top border from thead by default
- > caption + thead,
- > colgroup + thead,
- > thead:first-child {
- > tr:first-child {
- > th,
- > td {
- border-top: 0;
- }
- }
- }
- // Account for multiple tbody instances
- > tbody + tbody {
- border-top: 2px solid @table-border-color;
- }
-
- // Nesting
- .table {
- background-color: @body-bg;
- }
-}
-
-
-// Condensed table w/ half padding
-
-.table-condensed {
- > thead,
- > tbody,
- > tfoot {
- > tr {
- > th,
- > td {
- padding: @table-condensed-cell-padding;
- }
- }
- }
-}
-
-
-// Bordered version
-//
-// Add borders all around the table and between all the columns.
-
-.table-bordered {
- border: 1px solid @table-border-color;
- > thead,
- > tbody,
- > tfoot {
- > tr {
- > th,
- > td {
- border: 1px solid @table-border-color;
- }
- }
- }
- > thead > tr {
- > th,
- > td {
- border-bottom-width: 2px;
- }
- }
-}
-
-
-// Zebra-striping
-//
-// Default zebra-stripe styles (alternating gray and transparent backgrounds)
-
-.table-striped {
- > tbody > tr:nth-of-type(odd) {
- background-color: @table-bg-accent;
- }
-}
-
-
-// Hover effect
-//
-// Placed here since it has to come after the potential zebra striping
-
-.table-hover {
- > tbody > tr:hover {
- background-color: @table-bg-hover;
- }
-}
-
-
-// Table cell sizing
-//
-// Reset default table behavior
-
-table col[class*="col-"] {
- position: static; // Prevent border hiding in Firefox and IE9-11 (see https://github.com/twbs/bootstrap/issues/11623)
- float: none;
- display: table-column;
-}
-table {
- td,
- th {
- &[class*="col-"] {
- position: static; // Prevent border hiding in Firefox and IE9-11 (see https://github.com/twbs/bootstrap/issues/11623)
- float: none;
- display: table-cell;
- }
- }
-}
-
-
-// Table backgrounds
-//
-// Exact selectors below required to override `.table-striped` and prevent
-// inheritance to nested tables.
-
-// Generate the contextual variants
-.table-row-variant(active; @table-bg-active);
-.table-row-variant(success; @state-success-bg);
-.table-row-variant(info; @state-info-bg);
-.table-row-variant(warning; @state-warning-bg);
-.table-row-variant(danger; @state-danger-bg);
-
-
-// Responsive tables
-//
-// Wrap your tables in `.table-responsive` and we'll make them mobile friendly
-// by enabling horizontal scrolling. Only applies <768px. Everything above that
-// will display normally.
-
-.table-responsive {
- overflow-x: auto;
- min-height: 0.01%; // Workaround for IE9 bug (see https://github.com/twbs/bootstrap/issues/14837)
-
- @media screen and (max-width: @screen-xs-max) {
- width: 100%;
- margin-bottom: (@line-height-computed * 0.75);
- overflow-y: hidden;
- -ms-overflow-style: -ms-autohiding-scrollbar;
- border: 1px solid @table-border-color;
-
- // Tighten up spacing
- > .table {
- margin-bottom: 0;
-
- // Ensure the content doesn't wrap
- > thead,
- > tbody,
- > tfoot {
- > tr {
- > th,
- > td {
- white-space: nowrap;
- }
- }
- }
- }
-
- // Special overrides for the bordered tables
- > .table-bordered {
- border: 0;
-
- // Nuke the appropriate borders so that the parent can handle them
- > thead,
- > tbody,
- > tfoot {
- > tr {
- > th:first-child,
- > td:first-child {
- border-left: 0;
- }
- > th:last-child,
- > td:last-child {
- border-right: 0;
- }
- }
- }
-
- // Only nuke the last row's bottom-border in `tbody` and `tfoot` since
- // chances are there will be only one `tr` in a `thead` and that would
- // remove the border altogether.
- > tbody,
- > tfoot {
- > tr:last-child {
- > th,
- > td {
- border-bottom: 0;
- }
- }
- }
-
- }
- }
-}
diff --git a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/theme.less b/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/theme.less
deleted file mode 100755
index 8f51d913dc9..00000000000
--- a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/theme.less
+++ /dev/null
@@ -1,291 +0,0 @@
-/*!
- * Bootstrap v3.3.6 (http://getbootstrap.com)
- * Copyright 2011-2015 Twitter, Inc.
- * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
- */
-
-//
-// Load core variables and mixins
-// --------------------------------------------------
-
-@import "variables.less";
-@import "mixins.less";
-
-
-//
-// Buttons
-// --------------------------------------------------
-
-// Common styles
-.btn-default,
-.btn-primary,
-.btn-success,
-.btn-info,
-.btn-warning,
-.btn-danger {
- text-shadow: 0 -1px 0 rgba(0,0,0,.2);
- @shadow: inset 0 1px 0 rgba(255,255,255,.15), 0 1px 1px rgba(0,0,0,.075);
- .box-shadow(@shadow);
-
- // Reset the shadow
- &:active,
- &.active {
- .box-shadow(inset 0 3px 5px rgba(0,0,0,.125));
- }
-
- &.disabled,
- &[disabled],
- fieldset[disabled] & {
- .box-shadow(none);
- }
-
- .badge {
- text-shadow: none;
- }
-}
-
-// Mixin for generating new styles
-.btn-styles(@btn-color: #555) {
- #gradient > .vertical(@start-color: @btn-color; @end-color: darken(@btn-color, 12%));
- .reset-filter(); // Disable gradients for IE9 because filter bleeds through rounded corners; see https://github.com/twbs/bootstrap/issues/10620
- background-repeat: repeat-x;
- border-color: darken(@btn-color, 14%);
-
- &:hover,
- &:focus {
- background-color: darken(@btn-color, 12%);
- background-position: 0 -15px;
- }
-
- &:active,
- &.active {
- background-color: darken(@btn-color, 12%);
- border-color: darken(@btn-color, 14%);
- }
-
- &.disabled,
- &[disabled],
- fieldset[disabled] & {
- &,
- &:hover,
- &:focus,
- &.focus,
- &:active,
- &.active {
- background-color: darken(@btn-color, 12%);
- background-image: none;
- }
- }
-}
-
-// Common styles
-.btn {
- // Remove the gradient for the pressed/active state
- &:active,
- &.active {
- background-image: none;
- }
-}
-
-// Apply the mixin to the buttons
-.btn-default { .btn-styles(@btn-default-bg); text-shadow: 0 1px 0 #fff; border-color: #ccc; }
-.btn-primary { .btn-styles(@btn-primary-bg); }
-.btn-success { .btn-styles(@btn-success-bg); }
-.btn-info { .btn-styles(@btn-info-bg); }
-.btn-warning { .btn-styles(@btn-warning-bg); }
-.btn-danger { .btn-styles(@btn-danger-bg); }
-
-
-//
-// Images
-// --------------------------------------------------
-
-.thumbnail,
-.img-thumbnail {
- .box-shadow(0 1px 2px rgba(0,0,0,.075));
-}
-
-
-//
-// Dropdowns
-// --------------------------------------------------
-
-.dropdown-menu > li > a:hover,
-.dropdown-menu > li > a:focus {
- #gradient > .vertical(@start-color: @dropdown-link-hover-bg; @end-color: darken(@dropdown-link-hover-bg, 5%));
- background-color: darken(@dropdown-link-hover-bg, 5%);
-}
-.dropdown-menu > .active > a,
-.dropdown-menu > .active > a:hover,
-.dropdown-menu > .active > a:focus {
- #gradient > .vertical(@start-color: @dropdown-link-active-bg; @end-color: darken(@dropdown-link-active-bg, 5%));
- background-color: darken(@dropdown-link-active-bg, 5%);
-}
-
-
-//
-// Navbar
-// --------------------------------------------------
-
-// Default navbar
-.navbar-default {
- #gradient > .vertical(@start-color: lighten(@navbar-default-bg, 10%); @end-color: @navbar-default-bg);
- .reset-filter(); // Remove gradient in IE<10 to fix bug where dropdowns don't get triggered
- border-radius: @navbar-border-radius;
- @shadow: inset 0 1px 0 rgba(255,255,255,.15), 0 1px 5px rgba(0,0,0,.075);
- .box-shadow(@shadow);
-
- .navbar-nav > .open > a,
- .navbar-nav > .active > a {
- #gradient > .vertical(@start-color: darken(@navbar-default-link-active-bg, 5%); @end-color: darken(@navbar-default-link-active-bg, 2%));
- .box-shadow(inset 0 3px 9px rgba(0,0,0,.075));
- }
-}
-.navbar-brand,
-.navbar-nav > li > a {
- text-shadow: 0 1px 0 rgba(255,255,255,.25);
-}
-
-// Inverted navbar
-.navbar-inverse {
- #gradient > .vertical(@start-color: lighten(@navbar-inverse-bg, 10%); @end-color: @navbar-inverse-bg);
- .reset-filter(); // Remove gradient in IE<10 to fix bug where dropdowns don't get triggered; see https://github.com/twbs/bootstrap/issues/10257
- border-radius: @navbar-border-radius;
- .navbar-nav > .open > a,
- .navbar-nav > .active > a {
- #gradient > .vertical(@start-color: @navbar-inverse-link-active-bg; @end-color: lighten(@navbar-inverse-link-active-bg, 2.5%));
- .box-shadow(inset 0 3px 9px rgba(0,0,0,.25));
- }
-
- .navbar-brand,
- .navbar-nav > li > a {
- text-shadow: 0 -1px 0 rgba(0,0,0,.25);
- }
-}
-
-// Undo rounded corners in static and fixed navbars
-.navbar-static-top,
-.navbar-fixed-top,
-.navbar-fixed-bottom {
- border-radius: 0;
-}
-
-// Fix active state of dropdown items in collapsed mode
-@media (max-width: @grid-float-breakpoint-max) {
- .navbar .navbar-nav .open .dropdown-menu > .active > a {
- &,
- &:hover,
- &:focus {
- color: #fff;
- #gradient > .vertical(@start-color: @dropdown-link-active-bg; @end-color: darken(@dropdown-link-active-bg, 5%));
- }
- }
-}
-
-
-//
-// Alerts
-// --------------------------------------------------
-
-// Common styles
-.alert {
- text-shadow: 0 1px 0 rgba(255,255,255,.2);
- @shadow: inset 0 1px 0 rgba(255,255,255,.25), 0 1px 2px rgba(0,0,0,.05);
- .box-shadow(@shadow);
-}
-
-// Mixin for generating new styles
-.alert-styles(@color) {
- #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 7.5%));
- border-color: darken(@color, 15%);
-}
-
-// Apply the mixin to the alerts
-.alert-success { .alert-styles(@alert-success-bg); }
-.alert-info { .alert-styles(@alert-info-bg); }
-.alert-warning { .alert-styles(@alert-warning-bg); }
-.alert-danger { .alert-styles(@alert-danger-bg); }
-
-
-//
-// Progress bars
-// --------------------------------------------------
-
-// Give the progress background some depth
-.progress {
- #gradient > .vertical(@start-color: darken(@progress-bg, 4%); @end-color: @progress-bg)
-}
-
-// Mixin for generating new styles
-.progress-bar-styles(@color) {
- #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 10%));
-}
-
-// Apply the mixin to the progress bars
-.progress-bar { .progress-bar-styles(@progress-bar-bg); }
-.progress-bar-success { .progress-bar-styles(@progress-bar-success-bg); }
-.progress-bar-info { .progress-bar-styles(@progress-bar-info-bg); }
-.progress-bar-warning { .progress-bar-styles(@progress-bar-warning-bg); }
-.progress-bar-danger { .progress-bar-styles(@progress-bar-danger-bg); }
-
-// Reset the striped class because our mixins don't do multiple gradients and
-// the above custom styles override the new `.progress-bar-striped` in v3.2.0.
-.progress-bar-striped {
- #gradient > .striped();
-}
-
-
-//
-// List groups
-// --------------------------------------------------
-
-.list-group {
- border-radius: @border-radius-base;
- .box-shadow(0 1px 2px rgba(0,0,0,.075));
-}
-.list-group-item.active,
-.list-group-item.active:hover,
-.list-group-item.active:focus {
- text-shadow: 0 -1px 0 darken(@list-group-active-bg, 10%);
- #gradient > .vertical(@start-color: @list-group-active-bg; @end-color: darken(@list-group-active-bg, 7.5%));
- border-color: darken(@list-group-active-border, 7.5%);
-
- .badge {
- text-shadow: none;
- }
-}
-
-
-//
-// Panels
-// --------------------------------------------------
-
-// Common styles
-.panel {
- .box-shadow(0 1px 2px rgba(0,0,0,.05));
-}
-
-// Mixin for generating new styles
-.panel-heading-styles(@color) {
- #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 5%));
-}
-
-// Apply the mixin to the panel headings only
-.panel-default > .panel-heading { .panel-heading-styles(@panel-default-heading-bg); }
-.panel-primary > .panel-heading { .panel-heading-styles(@panel-primary-heading-bg); }
-.panel-success > .panel-heading { .panel-heading-styles(@panel-success-heading-bg); }
-.panel-info > .panel-heading { .panel-heading-styles(@panel-info-heading-bg); }
-.panel-warning > .panel-heading { .panel-heading-styles(@panel-warning-heading-bg); }
-.panel-danger > .panel-heading { .panel-heading-styles(@panel-danger-heading-bg); }
-
-
-//
-// Wells
-// --------------------------------------------------
-
-.well {
- #gradient > .vertical(@start-color: darken(@well-bg, 5%); @end-color: @well-bg);
- border-color: darken(@well-bg, 10%);
- @shadow: inset 0 1px 3px rgba(0,0,0,.05), 0 1px 0 rgba(255,255,255,.1);
- .box-shadow(@shadow);
-}
diff --git a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/thumbnails.less b/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/thumbnails.less
deleted file mode 100755
index 0713e67d006..00000000000
--- a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/thumbnails.less
+++ /dev/null
@@ -1,36 +0,0 @@
-//
-// Thumbnails
-// --------------------------------------------------
-
-
-// Mixin and adjust the regular image class
-.thumbnail {
- display: block;
- padding: @thumbnail-padding;
- margin-bottom: @line-height-computed;
- line-height: @line-height-base;
- background-color: @thumbnail-bg;
- border: 1px solid @thumbnail-border;
- border-radius: @thumbnail-border-radius;
- .transition(border .2s ease-in-out);
-
- > img,
- a > img {
- &:extend(.img-responsive);
- margin-left: auto;
- margin-right: auto;
- }
-
- // Add a hover state for linked versions only
- a&:hover,
- a&:focus,
- a&.active {
- border-color: @link-color;
- }
-
- // Image captions
- .caption {
- padding: @thumbnail-caption-padding;
- color: @thumbnail-caption-color;
- }
-}
diff --git a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/tooltip.less b/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/tooltip.less
deleted file mode 100755
index b48d63e07ad..00000000000
--- a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/tooltip.less
+++ /dev/null
@@ -1,101 +0,0 @@
-//
-// Tooltips
-// --------------------------------------------------
-
-
-// Base class
-.tooltip {
- position: absolute;
- z-index: @zindex-tooltip;
- display: block;
- // Our parent element can be arbitrary since tooltips are by default inserted as a sibling of their target element.
- // So reset our font and text properties to avoid inheriting weird values.
- .reset-text();
- font-size: @font-size-small;
-
- .opacity(0);
-
- &.in { .opacity(@tooltip-opacity); }
- &.top { margin-top: -3px; padding: @tooltip-arrow-width 0; }
- &.right { margin-left: 3px; padding: 0 @tooltip-arrow-width; }
- &.bottom { margin-top: 3px; padding: @tooltip-arrow-width 0; }
- &.left { margin-left: -3px; padding: 0 @tooltip-arrow-width; }
-}
-
-// Wrapper for the tooltip content
-.tooltip-inner {
- max-width: @tooltip-max-width;
- padding: 3px 8px;
- color: @tooltip-color;
- text-align: center;
- background-color: @tooltip-bg;
- border-radius: @border-radius-base;
-}
-
-// Arrows
-.tooltip-arrow {
- position: absolute;
- width: 0;
- height: 0;
- border-color: transparent;
- border-style: solid;
-}
-// Note: Deprecated .top-left, .top-right, .bottom-left, and .bottom-right as of v3.3.1
-.tooltip {
- &.top .tooltip-arrow {
- bottom: 0;
- left: 50%;
- margin-left: -@tooltip-arrow-width;
- border-width: @tooltip-arrow-width @tooltip-arrow-width 0;
- border-top-color: @tooltip-arrow-color;
- }
- &.top-left .tooltip-arrow {
- bottom: 0;
- right: @tooltip-arrow-width;
- margin-bottom: -@tooltip-arrow-width;
- border-width: @tooltip-arrow-width @tooltip-arrow-width 0;
- border-top-color: @tooltip-arrow-color;
- }
- &.top-right .tooltip-arrow {
- bottom: 0;
- left: @tooltip-arrow-width;
- margin-bottom: -@tooltip-arrow-width;
- border-width: @tooltip-arrow-width @tooltip-arrow-width 0;
- border-top-color: @tooltip-arrow-color;
- }
- &.right .tooltip-arrow {
- top: 50%;
- left: 0;
- margin-top: -@tooltip-arrow-width;
- border-width: @tooltip-arrow-width @tooltip-arrow-width @tooltip-arrow-width 0;
- border-right-color: @tooltip-arrow-color;
- }
- &.left .tooltip-arrow {
- top: 50%;
- right: 0;
- margin-top: -@tooltip-arrow-width;
- border-width: @tooltip-arrow-width 0 @tooltip-arrow-width @tooltip-arrow-width;
- border-left-color: @tooltip-arrow-color;
- }
- &.bottom .tooltip-arrow {
- top: 0;
- left: 50%;
- margin-left: -@tooltip-arrow-width;
- border-width: 0 @tooltip-arrow-width @tooltip-arrow-width;
- border-bottom-color: @tooltip-arrow-color;
- }
- &.bottom-left .tooltip-arrow {
- top: 0;
- right: @tooltip-arrow-width;
- margin-top: -@tooltip-arrow-width;
- border-width: 0 @tooltip-arrow-width @tooltip-arrow-width;
- border-bottom-color: @tooltip-arrow-color;
- }
- &.bottom-right .tooltip-arrow {
- top: 0;
- left: @tooltip-arrow-width;
- margin-top: -@tooltip-arrow-width;
- border-width: 0 @tooltip-arrow-width @tooltip-arrow-width;
- border-bottom-color: @tooltip-arrow-color;
- }
-}
diff --git a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/type.less b/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/type.less
deleted file mode 100755
index 0d4fee48486..00000000000
--- a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/type.less
+++ /dev/null
@@ -1,302 +0,0 @@
-//
-// Typography
-// --------------------------------------------------
-
-
-// Headings
-// -------------------------
-
-h1, h2, h3, h4, h5, h6,
-.h1, .h2, .h3, .h4, .h5, .h6 {
- font-family: @headings-font-family;
- font-weight: @headings-font-weight;
- line-height: @headings-line-height;
- color: @headings-color;
-
- small,
- .small {
- font-weight: normal;
- line-height: 1;
- color: @headings-small-color;
- }
-}
-
-h1, .h1,
-h2, .h2,
-h3, .h3 {
- margin-top: @line-height-computed;
- margin-bottom: (@line-height-computed / 2);
-
- small,
- .small {
- font-size: 65%;
- }
-}
-h4, .h4,
-h5, .h5,
-h6, .h6 {
- margin-top: (@line-height-computed / 2);
- margin-bottom: (@line-height-computed / 2);
-
- small,
- .small {
- font-size: 75%;
- }
-}
-
-h1, .h1 { font-size: @font-size-h1; }
-h2, .h2 { font-size: @font-size-h2; }
-h3, .h3 { font-size: @font-size-h3; }
-h4, .h4 { font-size: @font-size-h4; }
-h5, .h5 { font-size: @font-size-h5; }
-h6, .h6 { font-size: @font-size-h6; }
-
-
-// Body text
-// -------------------------
-
-p {
- margin: 0 0 (@line-height-computed / 2);
-}
-
-.lead {
- margin-bottom: @line-height-computed;
- font-size: floor((@font-size-base * 1.15));
- font-weight: 300;
- line-height: 1.4;
-
- @media (min-width: @screen-sm-min) {
- font-size: (@font-size-base * 1.5);
- }
-}
-
-
-// Emphasis & misc
-// -------------------------
-
-// Ex: (12px small font / 14px base font) * 100% = about 85%
-small,
-.small {
- font-size: floor((100% * @font-size-small / @font-size-base));
-}
-
-mark,
-.mark {
- background-color: @state-warning-bg;
- padding: .2em;
-}
-
-// Alignment
-.text-left { text-align: left; }
-.text-right { text-align: right; }
-.text-center { text-align: center; }
-.text-justify { text-align: justify; }
-.text-nowrap { white-space: nowrap; }
-
-// Transformation
-.text-lowercase { text-transform: lowercase; }
-.text-uppercase { text-transform: uppercase; }
-.text-capitalize { text-transform: capitalize; }
-
-// Contextual colors
-.text-muted {
- color: @text-muted;
-}
-.text-primary {
- .text-emphasis-variant(@brand-primary);
-}
-.text-success {
- .text-emphasis-variant(@state-success-text);
-}
-.text-info {
- .text-emphasis-variant(@state-info-text);
-}
-.text-warning {
- .text-emphasis-variant(@state-warning-text);
-}
-.text-danger {
- .text-emphasis-variant(@state-danger-text);
-}
-
-// Contextual backgrounds
-// For now we'll leave these alongside the text classes until v4 when we can
-// safely shift things around (per SemVer rules).
-.bg-primary {
- // Given the contrast here, this is the only class to have its color inverted
- // automatically.
- color: #fff;
- .bg-variant(@brand-primary);
-}
-.bg-success {
- .bg-variant(@state-success-bg);
-}
-.bg-info {
- .bg-variant(@state-info-bg);
-}
-.bg-warning {
- .bg-variant(@state-warning-bg);
-}
-.bg-danger {
- .bg-variant(@state-danger-bg);
-}
-
-
-// Page header
-// -------------------------
-
-.page-header {
- padding-bottom: ((@line-height-computed / 2) - 1);
- margin: (@line-height-computed * 2) 0 @line-height-computed;
- border-bottom: 1px solid @page-header-border-color;
-}
-
-
-// Lists
-// -------------------------
-
-// Unordered and Ordered lists
-ul,
-ol {
- margin-top: 0;
- margin-bottom: (@line-height-computed / 2);
- ul,
- ol {
- margin-bottom: 0;
- }
-}
-
-// List options
-
-// Unstyled keeps list items block level, just removes default browser padding and list-style
-.list-unstyled {
- padding-left: 0;
- list-style: none;
-}
-
-// Inline turns list items into inline-block
-.list-inline {
- .list-unstyled();
- margin-left: -5px;
-
- > li {
- display: inline-block;
- padding-left: 5px;
- padding-right: 5px;
- }
-}
-
-// Description Lists
-dl {
- margin-top: 0; // Remove browser default
- margin-bottom: @line-height-computed;
-}
-dt,
-dd {
- line-height: @line-height-base;
-}
-dt {
- font-weight: bold;
-}
-dd {
- margin-left: 0; // Undo browser default
-}
-
-// Horizontal description lists
-//
-// Defaults to being stacked without any of the below styles applied, until the
-// grid breakpoint is reached (default of ~768px).
-
-.dl-horizontal {
- dd {
- &:extend(.clearfix all); // Clear the floated `dt` if an empty `dd` is present
- }
-
- @media (min-width: @dl-horizontal-breakpoint) {
- dt {
- float: left;
- width: (@dl-horizontal-offset - 20);
- clear: left;
- text-align: right;
- .text-overflow();
- }
- dd {
- margin-left: @dl-horizontal-offset;
- }
- }
-}
-
-
-// Misc
-// -------------------------
-
-// Abbreviations and acronyms
-abbr[title],
-// Add data-* attribute to help out our tooltip plugin, per https://github.com/twbs/bootstrap/issues/5257
-abbr[data-original-title] {
- cursor: help;
- border-bottom: 1px dotted @abbr-border-color;
-}
-.initialism {
- font-size: 90%;
- .text-uppercase();
-}
-
-// Blockquotes
-blockquote {
- padding: (@line-height-computed / 2) @line-height-computed;
- margin: 0 0 @line-height-computed;
- font-size: @blockquote-font-size;
- border-left: 5px solid @blockquote-border-color;
-
- p,
- ul,
- ol {
- &:last-child {
- margin-bottom: 0;
- }
- }
-
- // Note: Deprecated small and .small as of v3.1.0
- // Context: https://github.com/twbs/bootstrap/issues/11660
- footer,
- small,
- .small {
- display: block;
- font-size: 80%; // back to default font-size
- line-height: @line-height-base;
- color: @blockquote-small-color;
-
- &:before {
- content: '\2014 \00A0'; // em dash, nbsp
- }
- }
-}
-
-// Opposite alignment of blockquote
-//
-// Heads up: `blockquote.pull-right` has been deprecated as of v3.1.0.
-.blockquote-reverse,
-blockquote.pull-right {
- padding-right: 15px;
- padding-left: 0;
- border-right: 5px solid @blockquote-border-color;
- border-left: 0;
- text-align: right;
-
- // Account for citation
- footer,
- small,
- .small {
- &:before { content: ''; }
- &:after {
- content: '\00A0 \2014'; // nbsp, em dash
- }
- }
-}
-
-// Addresses
-address {
- margin-bottom: @line-height-computed;
- font-style: normal;
- line-height: @line-height-base;
-}
diff --git a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/utilities.less b/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/utilities.less
deleted file mode 100755
index 7a8ca27a8ff..00000000000
--- a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/utilities.less
+++ /dev/null
@@ -1,55 +0,0 @@
-//
-// Utility classes
-// --------------------------------------------------
-
-
-// Floats
-// -------------------------
-
-.clearfix {
- .clearfix();
-}
-.center-block {
- .center-block();
-}
-.pull-right {
- float: right !important;
-}
-.pull-left {
- float: left !important;
-}
-
-
-// Toggling content
-// -------------------------
-
-// Note: Deprecated .hide in favor of .hidden or .sr-only (as appropriate) in v3.0.1
-.hide {
- display: none !important;
-}
-.show {
- display: block !important;
-}
-.invisible {
- visibility: hidden;
-}
-.text-hide {
- .text-hide();
-}
-
-
-// Hide from screenreaders and browsers
-//
-// Credit: HTML5 Boilerplate
-
-.hidden {
- display: none !important;
-}
-
-
-// For Affix plugin
-// -------------------------
-
-.affix {
- position: fixed;
-}
diff --git a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/variables.less b/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/variables.less
deleted file mode 100755
index b057ef5bf90..00000000000
--- a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/variables.less
+++ /dev/null
@@ -1,869 +0,0 @@
-//
-// Variables
-// --------------------------------------------------
-
-
-//== Colors
-//
-//## Gray and brand colors for use across Bootstrap.
-
-@gray-base: #000;
-@gray-darker: lighten(@gray-base, 13.5%); // #222
-@gray-dark: lighten(@gray-base, 20%); // #333
-@gray: lighten(@gray-base, 33.5%); // #555
-@gray-light: lighten(@gray-base, 46.7%); // #777
-@gray-lighter: lighten(@gray-base, 93.5%); // #eee
-
-@brand-primary: darken(#428bca, 6.5%); // #337ab7
-@brand-success: #5cb85c;
-@brand-info: #5bc0de;
-@brand-warning: #f0ad4e;
-@brand-danger: #d9534f;
-
-
-//== Scaffolding
-//
-//## Settings for some of the most global styles.
-
-//** Background color for `<body>`.
-@body-bg: #fff;
-//** Global text color on `<body>`.
-@text-color: @gray-dark;
-
-//** Global textual link color.
-@link-color: @brand-primary;
-//** Link hover color set via `darken()` function.
-@link-hover-color: darken(@link-color, 15%);
-//** Link hover decoration.
-@link-hover-decoration: underline;
-
-
-//== Typography
-//
-//## Font, line-height, and color for body text, headings, and more.
-
-@font-family-sans-serif: "Helvetica Neue", Helvetica, Arial, sans-serif;
-@font-family-serif: Georgia, "Times New Roman", Times, serif;
-//** Default monospace fonts for `<code>`, `<kbd>`, and `<pre>`.
-@font-family-monospace: Menlo, Monaco, Consolas, "Courier New", monospace;
-@font-family-base: @font-family-sans-serif;
-
-@font-size-base: 14px;
-@font-size-large: ceil((@font-size-base * 1.25)); // ~18px
-@font-size-small: ceil((@font-size-base * 0.85)); // ~12px
-
-@font-size-h1: floor((@font-size-base * 2.6)); // ~36px
-@font-size-h2: floor((@font-size-base * 2.15)); // ~30px
-@font-size-h3: ceil((@font-size-base * 1.7)); // ~24px
-@font-size-h4: ceil((@font-size-base * 1.25)); // ~18px
-@font-size-h5: @font-size-base;
-@font-size-h6: ceil((@font-size-base * 0.85)); // ~12px
-
-//** Unit-less `line-height` for use in components like buttons.
-@line-height-base: 1.428571429; // 20/14
-//** Computed "line-height" (`font-size` * `line-height`) for use with `margin`, `padding`, etc.
-@line-height-computed: floor((@font-size-base * @line-height-base)); // ~20px
-
-//** By default, this inherits from the `<body>`.
-@headings-font-family: inherit;
-@headings-font-weight: 500;
-@headings-line-height: 1.1;
-@headings-color: inherit;
-
-
-//== Iconography
-//
-//## Specify custom location and filename of the included Glyphicons icon font. Useful for those including Bootstrap via Bower.
-
-//** Load fonts from this directory.
-@icon-font-path: "../fonts/";
-//** File name for all font files.
-@icon-font-name: "glyphicons-halflings-regular";
-//** Element ID within SVG icon file.
-@icon-font-svg-id: "glyphicons_halflingsregular";
-
-
-//== Components
-//
-//## Define common padding and border radius sizes and more. Values based on 14px text and 1.428 line-height (~20px to start).
-
-@padding-base-vertical: 6px;
-@padding-base-horizontal: 12px;
-
-@padding-large-vertical: 10px;
-@padding-large-horizontal: 16px;
-
-@padding-small-vertical: 5px;
-@padding-small-horizontal: 10px;
-
-@padding-xs-vertical: 1px;
-@padding-xs-horizontal: 5px;
-
-@line-height-large: 1.3333333; // extra decimals for Win 8.1 Chrome
-@line-height-small: 1.5;
-
-@border-radius-base: 4px;
-@border-radius-large: 6px;
-@border-radius-small: 3px;
-
-//** Global color for active items (e.g., navs or dropdowns).
-@component-active-color: #fff;
-//** Global background color for active items (e.g., navs or dropdowns).
-@component-active-bg: @brand-primary;
-
-//** Width of the `border` for generating carets that indicator dropdowns.
-@caret-width-base: 4px;
-//** Carets increase slightly in size for larger components.
-@caret-width-large: 5px;
-
-
-//== Tables
-//
-//## Customizes the `.table` component with basic values, each used across all table variations.
-
-//** Padding for `<th>`s and `<td>`s.
-@table-cell-padding: 8px;
-//** Padding for cells in `.table-condensed`.
-@table-condensed-cell-padding: 5px;
-
-//** Default background color used for all tables.
-@table-bg: transparent;
-//** Background color used for `.table-striped`.
-@table-bg-accent: #f9f9f9;
-//** Background color used for `.table-hover`.
-@table-bg-hover: #f5f5f5;
-@table-bg-active: @table-bg-hover;
-
-//** Border color for table and cell borders.
-@table-border-color: #ddd;
-
-
-//== Buttons
-//
-//## For each of Bootstrap's buttons, define text, background and border color.
-
-@btn-font-weight: normal;
-
-@btn-default-color: #333;
-@btn-default-bg: #fff;
-@btn-default-border: #ccc;
-
-@btn-primary-color: #fff;
-@btn-primary-bg: @brand-primary;
-@btn-primary-border: darken(@btn-primary-bg, 5%);
-
-@btn-success-color: #fff;
-@btn-success-bg: @brand-success;
-@btn-success-border: darken(@btn-success-bg, 5%);
-
-@btn-info-color: #fff;
-@btn-info-bg: @brand-info;
-@btn-info-border: darken(@btn-info-bg, 5%);
-
-@btn-warning-color: #fff;
-@btn-warning-bg: @brand-warning;
-@btn-warning-border: darken(@btn-warning-bg, 5%);
-
-@btn-danger-color: #fff;
-@btn-danger-bg: @brand-danger;
-@btn-danger-border: darken(@btn-danger-bg, 5%);
-
-@btn-link-disabled-color: @gray-light;
-
-// Allows for customizing button radius independently from global border radius
-@btn-border-radius-base: @border-radius-base;
-@btn-border-radius-large: @border-radius-large;
-@btn-border-radius-small: @border-radius-small;
-
-
-//== Forms
-//
-//##
-
-//** `<input>` background color
-@input-bg: #fff;
-//** `<input disabled>` background color
-@input-bg-disabled: @gray-lighter;
-
-//** Text color for `<input>`s
-@input-color: @gray;
-//** `<input>` border color
-@input-border: #ccc;
-
-// TODO: Rename `@input-border-radius` to `@input-border-radius-base` in v4
-//** Default `.form-control` border radius
-// This has no effect on `<select>`s in some browsers, due to the limited stylability of `<select>`s in CSS.
-@input-border-radius: @border-radius-base;
-//** Large `.form-control` border radius
-@input-border-radius-large: @border-radius-large;
-//** Small `.form-control` border radius
-@input-border-radius-small: @border-radius-small;
-
-//** Border color for inputs on focus
-@input-border-focus: #66afe9;
-
-//** Placeholder text color
-@input-color-placeholder: #999;
-
-//** Default `.form-control` height
-@input-height-base: (@line-height-computed + (@padding-base-vertical * 2) + 2);
-//** Large `.form-control` height
-@input-height-large: (ceil(@font-size-large * @line-height-large) + (@padding-large-vertical * 2) + 2);
-//** Small `.form-control` height
-@input-height-small: (floor(@font-size-small * @line-height-small) + (@padding-small-vertical * 2) + 2);
-
-//** `.form-group` margin
-@form-group-margin-bottom: 15px;
-
-@legend-color: @gray-dark;
-@legend-border-color: #e5e5e5;
-
-//** Background color for textual input addons
-@input-group-addon-bg: @gray-lighter;
-//** Border color for textual input addons
-@input-group-addon-border-color: @input-border;
-
-//** Disabled cursor for form controls and buttons.
-@cursor-disabled: not-allowed;
-
-
-//== Dropdowns
-//
-//## Dropdown menu container and contents.
-
-//** Background for the dropdown menu.
-@dropdown-bg: #fff;
-//** Dropdown menu `border-color`.
-@dropdown-border: rgba(0,0,0,.15);
-//** Dropdown menu `border-color` **for IE8**.
-@dropdown-fallback-border: #ccc;
-//** Divider color for between dropdown items.
-@dropdown-divider-bg: #e5e5e5;
-
-//** Dropdown link text color.
-@dropdown-link-color: @gray-dark;
-//** Hover color for dropdown links.
-@dropdown-link-hover-color: darken(@gray-dark, 5%);
-//** Hover background for dropdown links.
-@dropdown-link-hover-bg: #f5f5f5;
-
-//** Active dropdown menu item text color.
-@dropdown-link-active-color: @component-active-color;
-//** Active dropdown menu item background color.
-@dropdown-link-active-bg: @component-active-bg;
-
-//** Disabled dropdown menu item background color.
-@dropdown-link-disabled-color: @gray-light;
-
-//** Text color for headers within dropdown menus.
-@dropdown-header-color: @gray-light;
-
-//** Deprecated `@dropdown-caret-color` as of v3.1.0
-@dropdown-caret-color: #000;
-
-
-//-- Z-index master list
-//
-// Warning: Avoid customizing these values. They're used for a bird's eye view
-// of components dependent on the z-axis and are designed to all work together.
-//
-// Note: These variables are not generated into the Customizer.
-
-@zindex-navbar: 1000;
-@zindex-dropdown: 1000;
-@zindex-popover: 1060;
-@zindex-tooltip: 1070;
-@zindex-navbar-fixed: 1030;
-@zindex-modal-background: 1040;
-@zindex-modal: 1050;
-
-
-//== Media queries breakpoints
-//
-//## Define the breakpoints at which your layout will change, adapting to different screen sizes.
-
-// Extra small screen / phone
-//** Deprecated `@screen-xs` as of v3.0.1
-@screen-xs: 480px;
-//** Deprecated `@screen-xs-min` as of v3.2.0
-@screen-xs-min: @screen-xs;
-//** Deprecated `@screen-phone` as of v3.0.1
-@screen-phone: @screen-xs-min;
-
-// Small screen / tablet
-//** Deprecated `@screen-sm` as of v3.0.1
-@screen-sm: 768px;
-@screen-sm-min: @screen-sm;
-//** Deprecated `@screen-tablet` as of v3.0.1
-@screen-tablet: @screen-sm-min;
-
-// Medium screen / desktop
-//** Deprecated `@screen-md` as of v3.0.1
-@screen-md: 992px;
-@screen-md-min: @screen-md;
-//** Deprecated `@screen-desktop` as of v3.0.1
-@screen-desktop: @screen-md-min;
-
-// Large screen / wide desktop
-//** Deprecated `@screen-lg` as of v3.0.1
-@screen-lg: 1200px;
-@screen-lg-min: @screen-lg;
-//** Deprecated `@screen-lg-desktop` as of v3.0.1
-@screen-lg-desktop: @screen-lg-min;
-
-// So media queries don't overlap when required, provide a maximum
-@screen-xs-max: (@screen-sm-min - 1);
-@screen-sm-max: (@screen-md-min - 1);
-@screen-md-max: (@screen-lg-min - 1);
-
-
-//== Grid system
-//
-//## Define your custom responsive grid.
-
-//** Number of columns in the grid.
-@grid-columns: 12;
-//** Padding between columns. Gets divided in half for the left and right.
-@grid-gutter-width: 30px;
-// Navbar collapse
-//** Point at which the navbar becomes uncollapsed.
-@grid-float-breakpoint: @screen-sm-min;
-//** Point at which the navbar begins collapsing.
-@grid-float-breakpoint-max: (@grid-float-breakpoint - 1);
-
-
-//== Container sizes
-//
-//## Define the maximum width of `.container` for different screen sizes.
-
-// Small screen / tablet
-@container-tablet: (720px + @grid-gutter-width);
-//** For `@screen-sm-min` and up.
-@container-sm: @container-tablet;
-
-// Medium screen / desktop
-@container-desktop: (940px + @grid-gutter-width);
-//** For `@screen-md-min` and up.
-@container-md: @container-desktop;
-
-// Large screen / wide desktop
-@container-large-desktop: (1140px + @grid-gutter-width);
-//** For `@screen-lg-min` and up.
-@container-lg: @container-large-desktop;
-
-
-//== Navbar
-//
-//##
-
-// Basics of a navbar
-@navbar-height: 50px;
-@navbar-margin-bottom: @line-height-computed;
-@navbar-border-radius: @border-radius-base;
-@navbar-padding-horizontal: floor((@grid-gutter-width / 2));
-@navbar-padding-vertical: ((@navbar-height - @line-height-computed) / 2);
-@navbar-collapse-max-height: 340px;
-
-@navbar-default-color: #777;
-@navbar-default-bg: #f8f8f8;
-@navbar-default-border: darken(@navbar-default-bg, 6.5%);
-
-// Navbar links
-@navbar-default-link-color: #777;
-@navbar-default-link-hover-color: #333;
-@navbar-default-link-hover-bg: transparent;
-@navbar-default-link-active-color: #555;
-@navbar-default-link-active-bg: darken(@navbar-default-bg, 6.5%);
-@navbar-default-link-disabled-color: #ccc;
-@navbar-default-link-disabled-bg: transparent;
-
-// Navbar brand label
-@navbar-default-brand-color: @navbar-default-link-color;
-@navbar-default-brand-hover-color: darken(@navbar-default-brand-color, 10%);
-@navbar-default-brand-hover-bg: transparent;
-
-// Navbar toggle
-@navbar-default-toggle-hover-bg: #ddd;
-@navbar-default-toggle-icon-bar-bg: #888;
-@navbar-default-toggle-border-color: #ddd;
-
-
-//=== Inverted navbar
-// Reset inverted navbar basics
-@navbar-inverse-color: lighten(@gray-light, 15%);
-@navbar-inverse-bg: #222;
-@navbar-inverse-border: darken(@navbar-inverse-bg, 10%);
-
-// Inverted navbar links
-@navbar-inverse-link-color: lighten(@gray-light, 15%);
-@navbar-inverse-link-hover-color: #fff;
-@navbar-inverse-link-hover-bg: transparent;
-@navbar-inverse-link-active-color: @navbar-inverse-link-hover-color;
-@navbar-inverse-link-active-bg: darken(@navbar-inverse-bg, 10%);
-@navbar-inverse-link-disabled-color: #444;
-@navbar-inverse-link-disabled-bg: transparent;
-
-// Inverted navbar brand label
-@navbar-inverse-brand-color: @navbar-inverse-link-color;
-@navbar-inverse-brand-hover-color: #fff;
-@navbar-inverse-brand-hover-bg: transparent;
-
-// Inverted navbar toggle
-@navbar-inverse-toggle-hover-bg: #333;
-@navbar-inverse-toggle-icon-bar-bg: #fff;
-@navbar-inverse-toggle-border-color: #333;
-
-
-//== Navs
-//
-//##
-
-//=== Shared nav styles
-@nav-link-padding: 10px 15px;
-@nav-link-hover-bg: @gray-lighter;
-
-@nav-disabled-link-color: @gray-light;
-@nav-disabled-link-hover-color: @gray-light;
-
-//== Tabs
-@nav-tabs-border-color: #ddd;
-
-@nav-tabs-link-hover-border-color: @gray-lighter;
-
-@nav-tabs-active-link-hover-bg: @body-bg;
-@nav-tabs-active-link-hover-color: @gray;
-@nav-tabs-active-link-hover-border-color: #ddd;
-
-@nav-tabs-justified-link-border-color: #ddd;
-@nav-tabs-justified-active-link-border-color: @body-bg;
-
-//== Pills
-@nav-pills-border-radius: @border-radius-base;
-@nav-pills-active-link-hover-bg: @component-active-bg;
-@nav-pills-active-link-hover-color: @component-active-color;
-
-
-//== Pagination
-//
-//##
-
-@pagination-color: @link-color;
-@pagination-bg: #fff;
-@pagination-border: #ddd;
-
-@pagination-hover-color: @link-hover-color;
-@pagination-hover-bg: @gray-lighter;
-@pagination-hover-border: #ddd;
-
-@pagination-active-color: #fff;
-@pagination-active-bg: @brand-primary;
-@pagination-active-border: @brand-primary;
-
-@pagination-disabled-color: @gray-light;
-@pagination-disabled-bg: #fff;
-@pagination-disabled-border: #ddd;
-
-
-//== Pager
-//
-//##
-
-@pager-bg: @pagination-bg;
-@pager-border: @pagination-border;
-@pager-border-radius: 15px;
-
-@pager-hover-bg: @pagination-hover-bg;
-
-@pager-active-bg: @pagination-active-bg;
-@pager-active-color: @pagination-active-color;
-
-@pager-disabled-color: @pagination-disabled-color;
-
-
-//== Jumbotron
-//
-//##
-
-@jumbotron-padding: 30px;
-@jumbotron-color: inherit;
-@jumbotron-bg: @gray-lighter;
-@jumbotron-heading-color: inherit;
-@jumbotron-font-size: ceil((@font-size-base * 1.5));
-@jumbotron-heading-font-size: ceil((@font-size-base * 4.5));
-
-
-//== Form states and alerts
-//
-//## Define colors for form feedback states and, by default, alerts.
-
-@state-success-text: #3c763d;
-@state-success-bg: #dff0d8;
-@state-success-border: darken(spin(@state-success-bg, -10), 5%);
-
-@state-info-text: #31708f;
-@state-info-bg: #d9edf7;
-@state-info-border: darken(spin(@state-info-bg, -10), 7%);
-
-@state-warning-text: #8a6d3b;
-@state-warning-bg: #fcf8e3;
-@state-warning-border: darken(spin(@state-warning-bg, -10), 5%);
-
-@state-danger-text: #a94442;
-@state-danger-bg: #f2dede;
-@state-danger-border: darken(spin(@state-danger-bg, -10), 5%);
-
-
-//== Tooltips
-//
-//##
-
-//** Tooltip max width
-@tooltip-max-width: 200px;
-//** Tooltip text color
-@tooltip-color: #fff;
-//** Tooltip background color
-@tooltip-bg: #000;
-@tooltip-opacity: .9;
-
-//** Tooltip arrow width
-@tooltip-arrow-width: 5px;
-//** Tooltip arrow color
-@tooltip-arrow-color: @tooltip-bg;
-
-
-//== Popovers
-//
-//##
-
-//** Popover body background color
-@popover-bg: #fff;
-//** Popover maximum width
-@popover-max-width: 276px;
-//** Popover border color
-@popover-border-color: rgba(0,0,0,.2);
-//** Popover fallback border color
-@popover-fallback-border-color: #ccc;
-
-//** Popover title background color
-@popover-title-bg: darken(@popover-bg, 3%);
-
-//** Popover arrow width
-@popover-arrow-width: 10px;
-//** Popover arrow color
-@popover-arrow-color: @popover-bg;
-
-//** Popover outer arrow width
-@popover-arrow-outer-width: (@popover-arrow-width + 1);
-//** Popover outer arrow color
-@popover-arrow-outer-color: fadein(@popover-border-color, 5%);
-//** Popover outer arrow fallback color
-@popover-arrow-outer-fallback-color: darken(@popover-fallback-border-color, 20%);
-
-
-//== Labels
-//
-//##
-
-//** Default label background color
-@label-default-bg: @gray-light;
-//** Primary label background color
-@label-primary-bg: @brand-primary;
-//** Success label background color
-@label-success-bg: @brand-success;
-//** Info label background color
-@label-info-bg: @brand-info;
-//** Warning label background color
-@label-warning-bg: @brand-warning;
-//** Danger label background color
-@label-danger-bg: @brand-danger;
-
-//** Default label text color
-@label-color: #fff;
-//** Default text color of a linked label
-@label-link-hover-color: #fff;
-
-
-//== Modals
-//
-//##
-
-//** Padding applied to the modal body
-@modal-inner-padding: 15px;
-
-//** Padding applied to the modal title
-@modal-title-padding: 15px;
-//** Modal title line-height
-@modal-title-line-height: @line-height-base;
-
-//** Background color of modal content area
-@modal-content-bg: #fff;
-//** Modal content border color
-@modal-content-border-color: rgba(0,0,0,.2);
-//** Modal content border color **for IE8**
-@modal-content-fallback-border-color: #999;
-
-//** Modal backdrop background color
-@modal-backdrop-bg: #000;
-//** Modal backdrop opacity
-@modal-backdrop-opacity: .5;
-//** Modal header border color
-@modal-header-border-color: #e5e5e5;
-//** Modal footer border color
-@modal-footer-border-color: @modal-header-border-color;
-
-@modal-lg: 900px;
-@modal-md: 600px;
-@modal-sm: 300px;
-
-
-//== Alerts
-//
-//## Define alert colors, border radius, and padding.
-
-@alert-padding: 15px;
-@alert-border-radius: @border-radius-base;
-@alert-link-font-weight: bold;
-
-@alert-success-bg: @state-success-bg;
-@alert-success-text: @state-success-text;
-@alert-success-border: @state-success-border;
-
-@alert-info-bg: @state-info-bg;
-@alert-info-text: @state-info-text;
-@alert-info-border: @state-info-border;
-
-@alert-warning-bg: @state-warning-bg;
-@alert-warning-text: @state-warning-text;
-@alert-warning-border: @state-warning-border;
-
-@alert-danger-bg: @state-danger-bg;
-@alert-danger-text: @state-danger-text;
-@alert-danger-border: @state-danger-border;
-
-
-//== Progress bars
-//
-//##
-
-//** Background color of the whole progress component
-@progress-bg: #f5f5f5;
-//** Progress bar text color
-@progress-bar-color: #fff;
-//** Variable for setting rounded corners on progress bar.
-@progress-border-radius: @border-radius-base;
-
-//** Default progress bar color
-@progress-bar-bg: @brand-primary;
-//** Success progress bar color
-@progress-bar-success-bg: @brand-success;
-//** Warning progress bar color
-@progress-bar-warning-bg: @brand-warning;
-//** Danger progress bar color
-@progress-bar-danger-bg: @brand-danger;
-//** Info progress bar color
-@progress-bar-info-bg: @brand-info;
-
-
-//== List group
-//
-//##
-
-//** Background color on `.list-group-item`
-@list-group-bg: #fff;
-//** `.list-group-item` border color
-@list-group-border: #ddd;
-//** List group border radius
-@list-group-border-radius: @border-radius-base;
-
-//** Background color of single list items on hover
-@list-group-hover-bg: #f5f5f5;
-//** Text color of active list items
-@list-group-active-color: @component-active-color;
-//** Background color of active list items
-@list-group-active-bg: @component-active-bg;
-//** Border color of active list elements
-@list-group-active-border: @list-group-active-bg;
-//** Text color for content within active list items
-@list-group-active-text-color: lighten(@list-group-active-bg, 40%);
-
-//** Text color of disabled list items
-@list-group-disabled-color: @gray-light;
-//** Background color of disabled list items
-@list-group-disabled-bg: @gray-lighter;
-//** Text color for content within disabled list items
-@list-group-disabled-text-color: @list-group-disabled-color;
-
-@list-group-link-color: #555;
-@list-group-link-hover-color: @list-group-link-color;
-@list-group-link-heading-color: #333;
-
-
-//== Panels
-//
-//##
-
-@panel-bg: #fff;
-@panel-body-padding: 15px;
-@panel-heading-padding: 10px 15px;
-@panel-footer-padding: @panel-heading-padding;
-@panel-border-radius: @border-radius-base;
-
-//** Border color for elements within panels
-@panel-inner-border: #ddd;
-@panel-footer-bg: #f5f5f5;
-
-@panel-default-text: @gray-dark;
-@panel-default-border: #ddd;
-@panel-default-heading-bg: #f5f5f5;
-
-@panel-primary-text: #fff;
-@panel-primary-border: @brand-primary;
-@panel-primary-heading-bg: @brand-primary;
-
-@panel-success-text: @state-success-text;
-@panel-success-border: @state-success-border;
-@panel-success-heading-bg: @state-success-bg;
-
-@panel-info-text: @state-info-text;
-@panel-info-border: @state-info-border;
-@panel-info-heading-bg: @state-info-bg;
-
-@panel-warning-text: @state-warning-text;
-@panel-warning-border: @state-warning-border;
-@panel-warning-heading-bg: @state-warning-bg;
-
-@panel-danger-text: @state-danger-text;
-@panel-danger-border: @state-danger-border;
-@panel-danger-heading-bg: @state-danger-bg;
-
-
-//== Thumbnails
-//
-//##
-
-//** Padding around the thumbnail image
-@thumbnail-padding: 4px;
-//** Thumbnail background color
-@thumbnail-bg: @body-bg;
-//** Thumbnail border color
-@thumbnail-border: #ddd;
-//** Thumbnail border radius
-@thumbnail-border-radius: @border-radius-base;
-
-//** Custom text color for thumbnail captions
-@thumbnail-caption-color: @text-color;
-//** Padding around the thumbnail caption
-@thumbnail-caption-padding: 9px;
-
-
-//== Wells
-//
-//##
-
-@well-bg: #f5f5f5;
-@well-border: darken(@well-bg, 7%);
-
-
-//== Badges
-//
-//##
-
-@badge-color: #fff;
-//** Linked badge text color on hover
-@badge-link-hover-color: #fff;
-@badge-bg: @gray-light;
-
-//** Badge text color in active nav link
-@badge-active-color: @link-color;
-//** Badge background color in active nav link
-@badge-active-bg: #fff;
-
-@badge-font-weight: bold;
-@badge-line-height: 1;
-@badge-border-radius: 10px;
-
-
-//== Breadcrumbs
-//
-//##
-
-@breadcrumb-padding-vertical: 8px;
-@breadcrumb-padding-horizontal: 15px;
-//** Breadcrumb background color
-@breadcrumb-bg: #f5f5f5;
-//** Breadcrumb text color
-@breadcrumb-color: #ccc;
-//** Text color of current page in the breadcrumb
-@breadcrumb-active-color: @gray-light;
-//** Textual separator for between breadcrumb elements
-@breadcrumb-separator: "/";
-
-
-//== Carousel
-//
-//##
-
-@carousel-text-shadow: 0 1px 2px rgba(0,0,0,.6);
-
-@carousel-control-color: #fff;
-@carousel-control-width: 15%;
-@carousel-control-opacity: .5;
-@carousel-control-font-size: 20px;
-
-@carousel-indicator-active-bg: #fff;
-@carousel-indicator-border-color: #fff;
-
-@carousel-caption-color: #fff;
-
-
-//== Close
-//
-//##
-
-@close-font-weight: bold;
-@close-color: #000;
-@close-text-shadow: 0 1px 0 #fff;
-
-
-//== Code
-//
-//##
-
-@code-color: #c7254e;
-@code-bg: #f9f2f4;
-
-@kbd-color: #fff;
-@kbd-bg: #333;
-
-@pre-bg: #f5f5f5;
-@pre-color: @gray-dark;
-@pre-border-color: #ccc;
-@pre-scrollable-max-height: 340px;
-
-
-//== Type
-//
-//##
-
-//** Horizontal offset for forms and lists.
-@component-offset-horizontal: 180px;
-//** Text muted color
-@text-muted: @gray-light;
-//** Abbreviations and acronyms border color
-@abbr-border-color: @gray-light;
-//** Headings small color
-@headings-small-color: @gray-light;
-//** Blockquote small color
-@blockquote-small-color: @gray-light;
-//** Blockquote font size
-@blockquote-font-size: (@font-size-base * 1.25);
-//** Blockquote border color
-@blockquote-border-color: @gray-lighter;
-//** Page header border color
-@page-header-border-color: @gray-lighter;
-//** Width of horizontal description list titles
-@dl-horizontal-offset: @component-offset-horizontal;
-//** Point at which .dl-horizontal becomes horizontal
-@dl-horizontal-breakpoint: @grid-float-breakpoint;
-//** Horizontal line color.
-@hr-border: @gray-lighter;
diff --git a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/wells.less b/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/wells.less
deleted file mode 100755
index 15d072b0cd0..00000000000
--- a/doc/_extensions/odoo_ext/static/bootstrap-3.3.6/less/wells.less
+++ /dev/null
@@ -1,29 +0,0 @@
-//
-// Wells
-// --------------------------------------------------
-
-
-// Base class
-.well {
- min-height: 20px;
- padding: 19px;
- margin-bottom: 20px;
- background-color: @well-bg;
- border: 1px solid @well-border;
- border-radius: @border-radius-base;
- .box-shadow(inset 0 1px 1px rgba(0,0,0,.05));
- blockquote {
- border-color: #ddd;
- border-color: rgba(0,0,0,.15);
- }
-}
-
-// Sizes
-.well-lg {
- padding: 24px;
- border-radius: @border-radius-large;
-}
-.well-sm {
- padding: 9px;
- border-radius: @border-radius-small;
-}
diff --git a/doc/_extensions/odoo_ext/static/bootstrap.css.map b/doc/_extensions/odoo_ext/static/bootstrap.css.map
deleted file mode 100644
index 2fd84f36ebe..00000000000
--- a/doc/_extensions/odoo_ext/static/bootstrap.css.map
+++ /dev/null
@@ -1 +0,0 @@
-{"version":3,"sources":["bootstrap.css","less/normalize.less","less/print.less","less/glyphicons.less","less/scaffolding.less","less/mixins/vendor-prefixes.less","less/mixins/tab-focus.less","less/mixins/image.less","less/type.less","less/mixins/text-emphasis.less","less/mixins/background-variant.less","less/mixins/text-overflow.less","less/code.less","less/grid.less","less/mixins/grid.less","less/mixins/grid-framework.less","less/tables.less","less/mixins/table-row.less","less/forms.less","less/mixins/forms.less","less/buttons.less","less/mixins/buttons.less","less/mixins/opacity.less","less/component-animations.less","less/dropdowns.less","less/mixins/nav-divider.less","less/mixins/reset-filter.less","less/button-groups.less","less/mixins/border-radius.less","less/input-groups.less","less/navs.less","less/navbar.less","less/mixins/nav-vertical-align.less","less/utilities.less","less/breadcrumbs.less","less/pagination.less","less/mixins/pagination.less","less/pager.less","less/labels.less","less/mixins/labels.less","less/badges.less","less/jumbotron.less","less/thumbnails.less","less/alerts.less","less/mixins/alerts.less","less/progress-bars.less","less/mixins/gradients.less","less/mixins/progress-bar.less","less/media.less","less/list-group.less","less/mixins/list-group.less","less/panels.less","less/mixins/panels.less","less/responsive-embed.less","less/wells.less","less/close.less","less/modals.less","less/tooltip.less","less/popovers.less","less/carousel.less","less/mixins/clearfix.less","less/mixins/center-block.less","less/mixins/hide-text.less","less/responsive-utilities.less","less/mixins/responsive-visibility.less"],"names":[],"mappings":"AAAA,6DAA4D;ACQ5D;EACE,yBAAA;EACA,4BAAA;EACA,gCAAA;EDND;ACaD;EACE,WAAA;EDXD;ACwBD;;;;;;;;;;;;;EAaE,gBAAA;EDtBD;AC8BD;;;;EAIE,uBAAA;EACA,0BAAA;ED5BD;ACoCD;EACE,eAAA;EACA,WAAA;EDlCD;AC0CD;;EAEE,eAAA;EDxCD;ACkDD;EACE,+BAAA;EDhDD;ACuDD;;EAEE,YAAA;EDrDD;AC+DD;EACE,2BAAA;ED7DD;ACoED;;EAEE,mBAAA;EDlED;ACyED;EACE,oBAAA;EDvED;AC+ED;EACE,gBAAA;EACA,kBAAA;ED7ED;ACoFD;EACE,kBAAA;EACA,aAAA;EDlFD;ACyFD;EACE,gBAAA;EDvFD;AC8FD;;EAEE,gBAAA;EACA,gBAAA;EACA,oBAAA;EACA,0BAAA;ED5FD;AC+FD;EACE,aAAA;ED7FD;ACgGD;EACE,iBAAA;ED9FD;ACwGD;EACE,WAAA;EDtGD;AC6GD;EACE,kBAAA;ED3GD;ACqHD;EACE,kBAAA;EDnHD;AC0HD;EACE,8BAAA;EACA,iCAAA;UAAA,yBAAA;EACA,WAAA;EDxHD;AC+HD;EACE,gBAAA;ED7HD;ACoID;;;;EAIE,mCAAA;EACA,gBAAA;EDlID;ACoJD;;;;;EAKE,gBAAA;EACA,eAAA;EACA,WAAA;EDlJD;ACyJD;EACE,mBAAA;EDvJD;ACiKD;;EAEE,sBAAA;ED/JD;AC0KD;;;;EAIE,4BAAA;EACA,iBAAA;EDxKD;AC+KD;;EAEE,iBAAA;ED7KD;ACoLD;;EAEE,WAAA;EACA,YAAA;EDlLD;AC0LD;EACE,qBAAA;EDxLD;ACmMD;;EAEE,gCAAA;KAAA,6BAAA;UAAA,wBAAA;EACA,YAAA;EDjMD;AC0MD;;EAEE,cAAA;EDxMD;ACiND;EACE,+BAAA;EACA,8BAAA;EACA,iCAAA;EACA,yBAAA;ED/MD;ACwND;;EAEE,0BAAA;EDtND;AC6ND;EACE,2BAAA;EACA,eAAA;EACA,gCAAA;ED3ND;ACmOD;EACE,WAAA;EACA,YAAA;EDjOD;ACwOD;EACE,gBAAA;EDtOD;AC8OD;EACE,mBAAA;ED5OD;ACsPD;EACE,2BAAA;EACA,mBAAA;EDpPD;ACuPD;;EAEE,YAAA;EDrPD;AACD,sFAAqF;AE1ErF;EAnGI;;;IAGI,oCAAA;IACA,wBAAA;IACA,qCAAA;YAAA,6BAAA;IACA,8BAAA;IFgLL;EE7KC;;IAEI,4BAAA;IF+KL;EE5KC;IACI,8BAAA;IF8KL;EE3KC;IACI,+BAAA;IF6KL;EExKC;;IAEI,aAAA;IF0KL;EEvKC;;IAEI,wBAAA;IACA,0BAAA;IFyKL;EEtKC;IACI,6BAAA;IFwKL;EErKC;;IAEI,0BAAA;IFuKL;EEpKC;IACI,4BAAA;IFsKL;EEnKC;;;IAGI,YAAA;IACA,WAAA;IFqKL;EElKC;;IAEI,yBAAA;IFoKL;EE7JC;IACI,6BAAA;IF+JL;EE3JC;IACI,eAAA;IF6JL;EE3JC;;IAGQ,mCAAA;IF4JT;EEzJC;IACI,wBAAA;IF2JL;EExJC;IACI,sCAAA;IF0JL;EE3JC;;IAKQ,mCAAA;IF0JT;EEvJC;;IAGQ,mCAAA;IFwJT;EACF;AGpPD;EACE,qCAAA;EACA,uDAAA;EACA,iYAAA;EHsPD;AG9OD;EACE,oBAAA;EACA,UAAA;EACA,uBAAA;EACA,qCAAA;EACA,oBAAA;EACA,qBAAA;EACA,gBAAA;EACA,qCAAA;EACA,oCAAA;EHgPD;AG5OmC;EAAW,gBAAA;EH+O9C;AG9OmC;EAAW,gBAAA;EHiP9C;AG/OmC;;EAAW,kBAAA;EHmP9C;AGlPmC;EAAW,kBAAA;EHqP9C;AGpPmC;EAAW,kBAAA;EHuP9C;AGtPmC;EAAW,kBAAA;EHyP9C;AGxPmC;EAAW,kBAAA;EH2P9C;AG1PmC;EAAW,kBAAA;EH6P9C;AG5PmC;EAAW,kBAAA;EH+P9C;AG9PmC;EAAW,kBAAA;EHiQ9C;AGhQmC;EAAW,kBAAA;EHmQ9C;AGlQmC;EAAW,kBAAA;EHqQ9C;AGpQmC;EAAW,kBAAA;EHuQ9C;AGtQmC;EAAW,kBAAA;EHyQ9C;AGxQmC;EAAW,kBAAA;EH2Q9C;AG1QmC;EAAW,kBAAA;EH6Q9C;AG5QmC;EAAW,kBAAA;EH+Q9C;AG9QmC;EAAW,kBAAA;EHiR9C;AGhRmC;EAAW,kBAAA;EHmR9C;AGlRmC;EAAW,kBAAA;EHqR9C;AGpRmC;EAAW,kBAAA;EHuR9C;AGtRmC;EAAW,kBAAA;EHyR9C;AGxRmC;EAAW,kBAAA;EH2R9C;AG1RmC;EAAW,kBAAA;EH6R9C;AG5RmC;EAAW,kBAAA;EH+R9C;AG9RmC;EAAW,kBAAA;EHiS9C;AGhSmC;EAAW,kBAAA;EHmS9C;AGlSmC;EAAW,kBAAA;EHqS9C;AGpSmC;EAAW,kBAAA;EHuS9C;AGtSmC;EAAW,kBAAA;EHyS9C;AGxSmC;EAAW,kBAAA;EH2S9C;AG1SmC;EAAW,kBAAA;EH6S9C;AG5SmC;EAAW,kBAAA;EH+S9C;AG9SmC;EAAW,kBAAA;EHiT9C;AGhTmC;EAAW,kBAAA;EHmT9C;AGlTmC;EAAW,kBAAA;EHqT9C;AGpTmC;EAAW,kBAAA;EHuT9C;AGtTmC;EAAW,kBAAA;EHyT9C;AGxTmC;EAAW,kBAAA;EH2T9C;AG1TmC;EAAW,kBAAA;EH6T9C;AG5TmC;EAAW,kBAAA;EH+T9C;AG9TmC;EAAW,kBAAA;EHiU9C;AGhUmC;EAAW,kBAAA;EHmU9C;AGlUmC;EAAW,kBAAA;EHqU9C;AGpUmC;EAAW,kBAAA;EHuU9C;AGtUmC;EAAW,kBAAA;EHyU9C;AGxUmC;EAAW,kBAAA;EH2U9C;AG1UmC;EAAW,kBAAA;EH6U9C;AG5UmC;EAAW,kBAAA;EH+U9C;AG9UmC;EAAW,kBAAA;EHiV9C;AGhVmC;EAAW,kBAAA;EHmV9C;AGlVmC;EAAW,kBAAA;EHqV9C;AGpVmC;EAAW,kBAAA;EHuV9C;AGtVmC;EAAW,kBAAA;EHyV9C;AGxVmC;EAAW,kBAAA;EH2V9C;AG1VmC;EAAW,kBAAA;EH6V9C;AG5VmC;EAAW,kBAAA;EH+V9C;AG9VmC;EAAW,kBAAA;EHiW9C;AGhWmC;EAAW,kBAAA;EHmW9C;AGlWmC;EAAW,kBAAA;EHqW9C;AGpWmC;EAAW,kBAAA;EHuW9C;AGtWmC;EAAW,kBAAA;EHyW9C;AGxWmC;EAAW,kBAAA;EH2W9C;AG1WmC;EAAW,kBAAA;EH6W9C;AG5WmC;EAAW,kBAAA;EH+W9C;AG9WmC;EAAW,kBAAA;EHiX9C;AGhXmC;EAAW,kBAAA;EHmX9C;AGlXmC;EAAW,kBAAA;EHqX9C;AGpXmC;EAAW,kBAAA;EHuX9C;AGtXmC;EAAW,kBAAA;EHyX9C;AGxXmC;EAAW,kBAAA;EH2X9C;AG1XmC;EAAW,kBAAA;EH6X9C;AG5XmC;EAAW,kBAAA;EH+X9C;AG9XmC;EAAW,kBAAA;EHiY9C;AGhYmC;EAAW,kBAAA;EHmY9C;AGlYmC;EAAW,kBAAA;EHqY9C;AGpYmC;EAAW,kBAAA;EHuY9C;AGtYmC;EAAW,kBAAA;EHyY9C;AGxYmC;EAAW,kBAAA;EH2Y9C;AG1YmC;EAAW,kBAAA;EH6Y9C;AG5YmC;EAAW,kBAAA;EH+Y9C;AG9YmC;EAAW,kBAAA;EHiZ9C;AGhZmC;EAAW,kBAAA;EHmZ9C;AGlZmC;EAAW,kBAAA;EHqZ9C;AGpZmC;EAAW,kBAAA;EHuZ9C;AGtZmC;EAAW,kBAAA;EHyZ9C;AGxZmC;EAAW,kBAAA;EH2Z9C;AG1ZmC;EAAW,kBAAA;EH6Z9C;AG5ZmC;EAAW,kBAAA;EH+Z9C;AG9ZmC;EAAW,kBAAA;EHia9C;AGhamC;EAAW,kBAAA;EHma9C;AGlamC;EAAW,kBAAA;EHqa9C;AGpamC;EAAW,kBAAA;EHua9C;AGtamC;EAAW,kBAAA;EHya9C;AGxamC;EAAW,kBAAA;EH2a9C;AG1amC;EAAW,kBAAA;EH6a9C;AG5amC;EAAW,kBAAA;EH+a9C;AG9amC;EAAW,kBAAA;EHib9C;AGhbmC;EAAW,kBAAA;EHmb9C;AGlbmC;EAAW,kBAAA;EHqb9C;AGpbmC;EAAW,kBAAA;EHub9C;AGtbmC;EAAW,kBAAA;EHyb9C;AGxbmC;EAAW,kBAAA;EH2b9C;AG1bmC;EAAW,kBAAA;EH6b9C;AG5bmC;EAAW,kBAAA;EH+b9C;AG9bmC;EAAW,kBAAA;EHic9C;AGhcmC;EAAW,kBAAA;EHmc9C;AGlcmC;EAAW,kBAAA;EHqc9C;AGpcmC;EAAW,kBAAA;EHuc9C;AGtcmC;EAAW,kBAAA;EHyc9C;AGxcmC;EAAW,kBAAA;EH2c9C;AG1cmC;EAAW,kBAAA;EH6c9C;AG5cmC;EAAW,kBAAA;EH+c9C;AG9cmC;EAAW,kBAAA;EHid9C;AGhdmC;EAAW,kBAAA;EHmd9C;AGldmC;EAAW,kBAAA;EHqd9C;AGpdmC;EAAW,kBAAA;EHud9C;AGtdmC;EAAW,kBAAA;EHyd9C;AGxdmC;EAAW,kBAAA;EH2d9C;AG1dmC;EAAW,kBAAA;EH6d9C;AG5dmC;EAAW,kBAAA;EH+d9C;AG9dmC;EAAW,kBAAA;EHie9C;AGhemC;EAAW,kBAAA;EHme9C;AGlemC;EAAW,kBAAA;EHqe9C;AGpemC;EAAW,kBAAA;EHue9C;AGtemC;EAAW,kBAAA;EHye9C;AGxemC;EAAW,kBAAA;EH2e9C;AG1emC;EAAW,kBAAA;EH6e9C;AG5emC;EAAW,kBAAA;EH+e9C;AG9emC;EAAW,kBAAA;EHif9C;AGhfmC;EAAW,kBAAA;EHmf9C;AGlfmC;EAAW,kBAAA;EHqf9C;AGpfmC;EAAW,kBAAA;EHuf9C;AGtfmC;EAAW,kBAAA;EHyf9C;AGxfmC;EAAW,kBAAA;EH2f9C;AG1fmC;EAAW,kBAAA;EH6f9C;AG5fmC;EAAW,kBAAA;EH+f9C;AG9fmC;EAAW,kBAAA;EHigB9C;AGhgBmC;EAAW,kBAAA;EHmgB9C;AGlgBmC;EAAW,kBAAA;EHqgB9C;AGpgBmC;EAAW,kBAAA;EHugB9C;AGtgBmC;EAAW,kBAAA;EHygB9C;AGxgBmC;EAAW,kBAAA;EH2gB9C;AG1gBmC;EAAW,kBAAA;EH6gB9C;AG5gBmC;EAAW,kBAAA;EH+gB9C;AG9gBmC;EAAW,kBAAA;EHihB9C;AGhhBmC;EAAW,kBAAA;EHmhB9C;AGlhBmC;EAAW,kBAAA;EHqhB9C;AGphBmC;EAAW,kBAAA;EHuhB9C;AGthBmC;EAAW,kBAAA;EHyhB9C;AGxhBmC;EAAW,kBAAA;EH2hB9C;AG1hBmC;EAAW,kBAAA;EH6hB9C;AG5hBmC;EAAW,kBAAA;EH+hB9C;AG9hBmC;EAAW,kBAAA;EHiiB9C;AGhiBmC;EAAW,kBAAA;EHmiB9C;AGliBmC;EAAW,kBAAA;EHqiB9C;AGpiBmC;EAAW,kBAAA;EHuiB9C;AGtiBmC;EAAW,kBAAA;EHyiB9C;AGxiBmC;EAAW,kBAAA;EH2iB9C;AG1iBmC;EAAW,kBAAA;EH6iB9C;AG5iBmC;EAAW,kBAAA;EH+iB9C;AG9iBmC;EAAW,kBAAA;EHijB9C;AGhjBmC;EAAW,kBAAA;EHmjB9C;AGljBmC;EAAW,kBAAA;EHqjB9C;AGpjBmC;EAAW,kBAAA;EHujB9C;AGtjBmC;EAAW,kBAAA;EHyjB9C;AGxjBmC;EAAW,kBAAA;EH2jB9C;AG1jBmC;EAAW,kBAAA;EH6jB9C;AG5jBmC;EAAW,kBAAA;EH+jB9C;AG9jBmC;EAAW,kBAAA;EHikB9C;AGhkBmC;EAAW,kBAAA;EHmkB9C;AGlkBmC;EAAW,kBAAA;EHqkB9C;AGpkBmC;EAAW,kBAAA;EHukB9C;AGtkBmC;EAAW,kBAAA;EHykB9C;AGxkBmC;EAAW,kBAAA;EH2kB9C;AG1kBmC;EAAW,kBAAA;EH6kB9C;AG5kBmC;EAAW,kBAAA;EH+kB9C;AG9kBmC;EAAW,kBAAA;EHilB9C;AGhlBmC;EAAW,kBAAA;EHmlB9C;AGllBmC;EAAW,kBAAA;EHqlB9C;AGplBmC;EAAW,kBAAA;EHulB9C;AGtlBmC;EAAW,kBAAA;EHylB9C;AGxlBmC;EAAW,kBAAA;EH2lB9C;AG1lBmC;EAAW,kBAAA;EH6lB9C;AG5lBmC;EAAW,kBAAA;EH+lB9C;AG9lBmC;EAAW,kBAAA;EHimB9C;AGhmBmC;EAAW,kBAAA;EHmmB9C;AGlmBmC;EAAW,kBAAA;EHqmB9C;AGpmBmC;EAAW,kBAAA;EHumB9C;AGtmBmC;EAAW,kBAAA;EHymB9C;AGxmBmC;EAAW,kBAAA;EH2mB9C;AG1mBmC;EAAW,kBAAA;EH6mB9C;AG5mBmC;EAAW,kBAAA;EH+mB9C;AG9mBmC;EAAW,kBAAA;EHinB9C;AGhnBmC;EAAW,kBAAA;EHmnB9C;AGlnBmC;EAAW,kBAAA;EHqnB9C;AGpnBmC;EAAW,kBAAA;EHunB9C;AGtnBmC;EAAW,kBAAA;EHynB9C;AGxnBmC;EAAW,kBAAA;EH2nB9C;AG1nBmC;EAAW,kBAAA;EH6nB9C;AG5nBmC;EAAW,kBAAA;EH+nB9C;AG9nBmC;EAAW,kBAAA;EHioB9C;AGhoBmC;EAAW,kBAAA;EHmoB9C;AGloBmC;EAAW,kBAAA;EHqoB9C;AGpoBmC;EAAW,kBAAA;EHuoB9C;AGtoBmC;EAAW,kBAAA;EHyoB9C;AGhoBmC;EAAW,kBAAA;EHmoB9C;AGloBmC;EAAW,kBAAA;EHqoB9C;AGpoBmC;EAAW,kBAAA;EHuoB9C;AGtoBmC;EAAW,kBAAA;EHyoB9C;AGxoBmC;EAAW,kBAAA;EH2oB9C;AG1oBmC;EAAW,kBAAA;EH6oB9C;AG5oBmC;EAAW,kBAAA;EH+oB9C;AG9oBmC;EAAW,kBAAA;EHipB9C;AGhpBmC;EAAW,kBAAA;EHmpB9C;AGlpBmC;EAAW,kBAAA;EHqpB9C;AGppBmC;EAAW,kBAAA;EHupB9C;AGtpBmC;EAAW,kBAAA;EHypB9C;AGxpBmC;EAAW,kBAAA;EH2pB9C;AG1pBmC;EAAW,kBAAA;EH6pB9C;AG5pBmC;EAAW,kBAAA;EH+pB9C;AG9pBmC;EAAW,kBAAA;EHiqB9C;AGhqBmC;EAAW,kBAAA;EHmqB9C;AGlqBmC;EAAW,kBAAA;EHqqB9C;AGpqBmC;EAAW,kBAAA;EHuqB9C;AGtqBmC;EAAW,kBAAA;EHyqB9C;AGxqBmC;EAAW,kBAAA;EH2qB9C;AG1qBmC;EAAW,kBAAA;EH6qB9C;AG5qBmC;EAAW,kBAAA;EH+qB9C;AG9qBmC;EAAW,kBAAA;EHirB9C;AGhrBmC;EAAW,kBAAA;EHmrB9C;AGlrBmC;EAAW,kBAAA;EHqrB9C;AGprBmC;EAAW,kBAAA;EHurB9C;AGtrBmC;EAAW,kBAAA;EHyrB9C;AGxrBmC;EAAW,kBAAA;EH2rB9C;AG1rBmC;EAAW,kBAAA;EH6rB9C;AG5rBmC;EAAW,kBAAA;EH+rB9C;AG9rBmC;EAAW,kBAAA;EHisB9C;AGhsBmC;EAAW,kBAAA;EHmsB9C;AGlsBmC;EAAW,kBAAA;EHqsB9C;AGpsBmC;EAAW,kBAAA;EHusB9C;AGtsBmC;EAAW,kBAAA;EHysB9C;AGxsBmC;EAAW,kBAAA;EH2sB9C;AG1sBmC;EAAW,kBAAA;EH6sB9C;AG5sBmC;EAAW,kBAAA;EH+sB9C;AG9sBmC;EAAW,kBAAA;EHitB9C;AGhtBmC;EAAW,kBAAA;EHmtB9C;AGltBmC;EAAW,kBAAA;EHqtB9C;AGptBmC;EAAW,kBAAA;EHutB9C;AGttBmC;EAAW,kBAAA;EHytB9C;AGxtBmC;EAAW,kBAAA;EH2tB9C;AG1tBmC;EAAW,kBAAA;EH6tB9C;AG5tBmC;EAAW,kBAAA;EH+tB9C;AG9tBmC;EAAW,kBAAA;EHiuB9C;AGhuBmC;EAAW,kBAAA;EHmuB9C;AGluBmC;EAAW,kBAAA;EHquB9C;AGpuBmC;EAAW,kBAAA;EHuuB9C;AGtuBmC;EAAW,kBAAA;EHyuB9C;AGxuBmC;EAAW,kBAAA;EH2uB9C;AG1uBmC;EAAW,kBAAA;EH6uB9C;AG5uBmC;EAAW,kBAAA;EH+uB9C;AG9uBmC;EAAW,kBAAA;EHivB9C;AIvhCD;ECgEE,gCAAA;EACG,6BAAA;EACK,wBAAA;EL09BT;AIzhCD;;EC6DE,gCAAA;EACG,6BAAA;EACK,wBAAA;ELg+BT;AIvhCD;EACE,iBAAA;EACA,+CAAA;EJyhCD;AIthCD;EACE,6DAAA;EACA,iBAAA;EACA,yBAAA;EACA,gBAAA;EACA,2BAAA;EJwhCD;AIphCD;;;;EAIE,sBAAA;EACA,oBAAA;EACA,sBAAA;EJshCD;AIhhCD;EACE,gBAAA;EACA,uBAAA;EJkhCD;AIhhCC;;EAEE,gBAAA;EACA,4BAAA;EJkhCH;AI/gCC;EErDA,sBAAA;EAEA,4CAAA;EACA,sBAAA;ENskCD;AIzgCD;EACE,WAAA;EJ2gCD;AIrgCD;EACE,wBAAA;EJugCD;AIngCD;;;;;EGvEE,gBAAA;EACA,iBAAA;EACA,cAAA;EPilCD;AIvgCD;EACE,oBAAA;EJygCD;AIngCD;EACE,cAAA;EACA,yBAAA;EACA,2BAAA;EACA,2BAAA;EACA,oBAAA;EC6FA,0CAAA;EACK,qCAAA;EACG,kCAAA;EEvLR,uBAAA;EACA,iBAAA;EACA,cAAA;EPimCD;AIngCD;EACE,oBAAA;EJqgCD;AI//BD;EACE,kBAAA;EACA,qBAAA;EACA,WAAA;EACA,+BAAA;EJigCD;AIz/BD;EACE,oBAAA;EACA,YAAA;EACA,aAAA;EACA,cAAA;EACA,YAAA;EACA,kBAAA;EACA,wBAAA;EACA,WAAA;EJ2/BD;AIn/BC;;EAEE,kBAAA;EACA,aAAA;EACA,cAAA;EACA,WAAA;EACA,mBAAA;EACA,YAAA;EJq/BH;AIz+BD;EACE,iBAAA;EJ2+BD;AQnoCD;;;;;;;;;;;;EAEE,sBAAA;EACA,kBAAA;EACA,kBAAA;EACA,gBAAA;ER+oCD;AQppCD;;;;;;;;;;;;;;;;;;;;;;;;EASI,qBAAA;EACA,gBAAA;EACA,gBAAA;ERqqCH;AQjqCD;;;;;;EAGE,kBAAA;EACA,qBAAA;ERsqCD;AQ1qCD;;;;;;;;;;;;EAQI,gBAAA;ERgrCH;AQ7qCD;;;;;;EAGE,kBAAA;EACA,qBAAA;ERkrCD;AQtrCD;;;;;;;;;;;;EAQI,gBAAA;ER4rCH;AQxrCD;;EAAU,iBAAA;ER4rCT;AQ3rCD;;EAAU,iBAAA;ER+rCT;AQ9rCD;;EAAU,iBAAA;ERksCT;AQjsCD;;EAAU,iBAAA;ERqsCT;AQpsCD;;EAAU,iBAAA;ERwsCT;AQvsCD;;EAAU,iBAAA;ER2sCT;AQrsCD;EACE,kBAAA;ERusCD;AQpsCD;EACE,qBAAA;EACA,iBAAA;EACA,kBAAA;EACA,kBAAA;ERssCD;AQjsCD;EAAA;IAFI,iBAAA;IRusCD;EACF;AQ/rCD;;EAEE,gBAAA;ERisCD;AQ9rCD;;EAEE,2BAAA;EACA,eAAA;ERgsCD;AQ5rCD;EAAuB,kBAAA;ER+rCtB;AQ9rCD;EAAuB,mBAAA;ERisCtB;AQhsCD;EAAuB,oBAAA;ERmsCtB;AQlsCD;EAAuB,qBAAA;ERqsCtB;AQpsCD;EAAuB,qBAAA;ERusCtB;AQpsCD;EAAuB,2BAAA;ERusCtB;AQtsCD;EAAuB,2BAAA;ERysCtB;AQxsCD;EAAuB,4BAAA;ER2sCtB;AQxsCD;EACE,gBAAA;ER0sCD;AQxsCD;ECrGE,gBAAA;ETgzCD;AS/yCC;EACE,gBAAA;ETizCH;AQ3sCD;ECxGE,gBAAA;ETszCD;ASrzCC;EACE,gBAAA;ETuzCH;AQ9sCD;EC3GE,gBAAA;ET4zCD;AS3zCC;EACE,gBAAA;ET6zCH;AQjtCD;EC9GE,gBAAA;ETk0CD;ASj0CC;EACE,gBAAA;ETm0CH;AQptCD;ECjHE,gBAAA;ETw0CD;ASv0CC;EACE,gBAAA;ETy0CH;AQntCD;EAGE,aAAA;EE3HA,2BAAA;EV+0CD;AU90CC;EACE,2BAAA;EVg1CH;AQptCD;EE9HE,2BAAA;EVq1CD;AUp1CC;EACE,2BAAA;EVs1CH;AQvtCD;EEjIE,2BAAA;EV21CD;AU11CC;EACE,2BAAA;EV41CH;AQ1tCD;EEpIE,2BAAA;EVi2CD;AUh2CC;EACE,2BAAA;EVk2CH;AQ7tCD;EEvIE,2BAAA;EVu2CD;AUt2CC;EACE,2BAAA;EVw2CH;AQ3tCD;EACE,qBAAA;EACA,qBAAA;EACA,kCAAA;ER6tCD;AQrtCD;;EAEE,eAAA;EACA,qBAAA;ERutCD;AQ1tCD;;;;EAMI,kBAAA;ER0tCH;AQntCD;EACE,iBAAA;EACA,kBAAA;ERqtCD;AQjtCD;EALE,iBAAA;EACA,kBAAA;EAMA,mBAAA;ERotCD;AQttCD;EAKI,uBAAA;EACA,mBAAA;EACA,oBAAA;ERotCH;AQ/sCD;EACE,eAAA;EACA,qBAAA;ERitCD;AQ/sCD;;EAEE,yBAAA;ERitCD;AQ/sCD;EACE,mBAAA;ERitCD;AQ/sCD;EACE,gBAAA;ERitCD;AQxrCD;EAAA;IAVM,aAAA;IACA,cAAA;IACA,aAAA;IACA,mBAAA;IGtNJ,kBAAA;IACA,yBAAA;IACA,qBAAA;IX65CC;EQlsCH;IAHM,oBAAA;IRwsCH;EACF;AQ/rCD;;EAGE,cAAA;EACA,mCAAA;ERgsCD;AQ9rCD;EACE,gBAAA;EA9IqB,2BAAA;ER+0CtB;AQ5rCD;EACE,oBAAA;EACA,kBAAA;EACA,mBAAA;EACA,gCAAA;ER8rCD;AQzrCG;;;EACE,kBAAA;ER6rCL;AQvsCD;;;EAmBI,gBAAA;EACA,gBAAA;EACA,yBAAA;EACA,gBAAA;ERyrCH;AQvrCG;;;EACE,wBAAA;ER2rCL;AQnrCD;;EAEE,qBAAA;EACA,iBAAA;EACA,iCAAA;EACA,gBAAA;EACA,mBAAA;ERqrCD;AQ/qCG;;;;;;EAAW,aAAA;ERurCd;AQtrCG;;;;;;EACE,wBAAA;ER6rCL;AQvrCD;EACE,qBAAA;EACA,oBAAA;EACA,yBAAA;ERyrCD;AY/9CD;;;;EAIE,gEAAA;EZi+CD;AY79CD;EACE,kBAAA;EACA,gBAAA;EACA,gBAAA;EACA,2BAAA;EACA,oBAAA;EZ+9CD;AY39CD;EACE,kBAAA;EACA,gBAAA;EACA,gBAAA;EACA,2BAAA;EACA,oBAAA;EACA,wDAAA;UAAA,gDAAA;EZ69CD;AYn+CD;EASI,YAAA;EACA,iBAAA;EACA,mBAAA;EACA,0BAAA;UAAA,kBAAA;EZ69CH;AYx9CD;EACE,gBAAA;EACA,gBAAA;EACA,kBAAA;EACA,iBAAA;EACA,yBAAA;EACA,uBAAA;EACA,uBAAA;EACA,gBAAA;EACA,2BAAA;EACA,2BAAA;EACA,oBAAA;EZ09CD;AYr+CD;EAeI,YAAA;EACA,oBAAA;EACA,gBAAA;EACA,uBAAA;EACA,+BAAA;EACA,kBAAA;EZy9CH;AYp9CD;EACE,mBAAA;EACA,oBAAA;EZs9CD;AahhDD;ECHE,oBAAA;EACA,mBAAA;EACA,oBAAA;EACA,qBAAA;EdshDD;AahhDC;EAAA;IAFE,cAAA;IbshDD;EACF;AalhDC;EAAA;IAFE,cAAA;IbwhDD;EACF;AaphDD;EAAA;IAFI,eAAA;Ib0hDD;EACF;AajhDD;ECvBE,oBAAA;EACA,mBAAA;EACA,oBAAA;EACA,qBAAA;Ed2iDD;Aa9gDD;ECvBE,oBAAA;EACA,qBAAA;EdwiDD;AexiDG;EACE,oBAAA;EAEA,iBAAA;EAEA,oBAAA;EACA,qBAAA;EfwiDL;AexhDG;EACE,aAAA;Ef0hDL;AenhDC;EACE,aAAA;EfqhDH;AethDC;EACE,qBAAA;EfwhDH;AezhDC;EACE,qBAAA;Ef2hDH;Ae5hDC;EACE,YAAA;Ef8hDH;Ae/hDC;EACE,qBAAA;EfiiDH;AeliDC;EACE,qBAAA;EfoiDH;AeriDC;EACE,YAAA;EfuiDH;AexiDC;EACE,qBAAA;Ef0iDH;Ae3iDC;EACE,qBAAA;Ef6iDH;Ae9iDC;EACE,YAAA;EfgjDH;AejjDC;EACE,qBAAA;EfmjDH;AepjDC;EACE,oBAAA;EfsjDH;AexiDC;EACE,aAAA;Ef0iDH;Ae3iDC;EACE,qBAAA;Ef6iDH;Ae9iDC;EACE,qBAAA;EfgjDH;AejjDC;EACE,YAAA;EfmjDH;AepjDC;EACE,qBAAA;EfsjDH;AevjDC;EACE,qBAAA;EfyjDH;Ae1jDC;EACE,YAAA;Ef4jDH;Ae7jDC;EACE,qBAAA;Ef+jDH;AehkDC;EACE,qBAAA;EfkkDH;AenkDC;EACE,YAAA;EfqkDH;AetkDC;EACE,qBAAA;EfwkDH;AezkDC;EACE,oBAAA;Ef2kDH;AevkDC;EACE,aAAA;EfykDH;AezlDC;EACE,YAAA;Ef2lDH;Ae5lDC;EACE,oBAAA;Ef8lDH;Ae/lDC;EACE,oBAAA;EfimDH;AelmDC;EACE,WAAA;EfomDH;AermDC;EACE,oBAAA;EfumDH;AexmDC;EACE,oBAAA;Ef0mDH;Ae3mDC;EACE,WAAA;Ef6mDH;Ae9mDC;EACE,oBAAA;EfgnDH;AejnDC;EACE,oBAAA;EfmnDH;AepnDC;EACE,WAAA;EfsnDH;AevnDC;EACE,oBAAA;EfynDH;Ae1nDC;EACE,mBAAA;Ef4nDH;AexnDC;EACE,YAAA;Ef0nDH;Ae5mDC;EACE,mBAAA;Ef8mDH;Ae/mDC;EACE,2BAAA;EfinDH;AelnDC;EACE,2BAAA;EfonDH;AernDC;EACE,kBAAA;EfunDH;AexnDC;EACE,2BAAA;Ef0nDH;Ae3nDC;EACE,2BAAA;Ef6nDH;Ae9nDC;EACE,kBAAA;EfgoDH;AejoDC;EACE,2BAAA;EfmoDH;AepoDC;EACE,2BAAA;EfsoDH;AevoDC;EACE,kBAAA;EfyoDH;Ae1oDC;EACE,2BAAA;Ef4oDH;Ae7oDC;EACE,0BAAA;Ef+oDH;AehpDC;EACE,iBAAA;EfkpDH;AalpDD;EElCI;IACE,aAAA;IfurDH;EehrDD;IACE,aAAA;IfkrDD;EenrDD;IACE,qBAAA;IfqrDD;EetrDD;IACE,qBAAA;IfwrDD;EezrDD;IACE,YAAA;If2rDD;Ee5rDD;IACE,qBAAA;If8rDD;Ee/rDD;IACE,qBAAA;IfisDD;EelsDD;IACE,YAAA;IfosDD;EersDD;IACE,qBAAA;IfusDD;EexsDD;IACE,qBAAA;If0sDD;Ee3sDD;IACE,YAAA;If6sDD;Ee9sDD;IACE,qBAAA;IfgtDD;EejtDD;IACE,oBAAA;IfmtDD;EersDD;IACE,aAAA;IfusDD;EexsDD;IACE,qBAAA;If0sDD;Ee3sDD;IACE,qBAAA;If6sDD;Ee9sDD;IACE,YAAA;IfgtDD;EejtDD;IACE,qBAAA;IfmtDD;EeptDD;IACE,qBAAA;IfstDD;EevtDD;IACE,YAAA;IfytDD;Ee1tDD;IACE,qBAAA;If4tDD;Ee7tDD;IACE,qBAAA;If+tDD;EehuDD;IACE,YAAA;IfkuDD;EenuDD;IACE,qBAAA;IfquDD;EetuDD;IACE,oBAAA;IfwuDD;EepuDD;IACE,aAAA;IfsuDD;EetvDD;IACE,YAAA;IfwvDD;EezvDD;IACE,oBAAA;If2vDD;Ee5vDD;IACE,oBAAA;If8vDD;Ee/vDD;IACE,WAAA;IfiwDD;EelwDD;IACE,oBAAA;IfowDD;EerwDD;IACE,oBAAA;IfuwDD;EexwDD;IACE,WAAA;If0wDD;Ee3wDD;IACE,oBAAA;If6wDD;Ee9wDD;IACE,oBAAA;IfgxDD;EejxDD;IACE,WAAA;IfmxDD;EepxDD;IACE,oBAAA;IfsxDD;EevxDD;IACE,mBAAA;IfyxDD;EerxDD;IACE,YAAA;IfuxDD;EezwDD;IACE,mBAAA;If2wDD;Ee5wDD;IACE,2BAAA;If8wDD;Ee/wDD;IACE,2BAAA;IfixDD;EelxDD;IACE,kBAAA;IfoxDD;EerxDD;IACE,2BAAA;IfuxDD;EexxDD;IACE,2BAAA;If0xDD;Ee3xDD;IACE,kBAAA;If6xDD;Ee9xDD;IACE,2BAAA;IfgyDD;EejyDD;IACE,2BAAA;IfmyDD;EepyDD;IACE,kBAAA;IfsyDD;EevyDD;IACE,2BAAA;IfyyDD;Ee1yDD;IACE,0BAAA;If4yDD;Ee7yDD;IACE,iBAAA;If+yDD;EACF;AavyDD;EE3CI;IACE,aAAA;Ifq1DH;Ee90DD;IACE,aAAA;Ifg1DD;Eej1DD;IACE,qBAAA;Ifm1DD;Eep1DD;IACE,qBAAA;Ifs1DD;Eev1DD;IACE,YAAA;Ify1DD;Ee11DD;IACE,qBAAA;If41DD;Ee71DD;IACE,qBAAA;If+1DD;Eeh2DD;IACE,YAAA;Ifk2DD;Een2DD;IACE,qBAAA;Ifq2DD;Eet2DD;IACE,qBAAA;Ifw2DD;Eez2DD;IACE,YAAA;If22DD;Ee52DD;IACE,qBAAA;If82DD;Ee/2DD;IACE,oBAAA;Ifi3DD;Een2DD;IACE,aAAA;Ifq2DD;Eet2DD;IACE,qBAAA;Ifw2DD;Eez2DD;IACE,qBAAA;If22DD;Ee52DD;IACE,YAAA;If82DD;Ee/2DD;IACE,qBAAA;Ifi3DD;Eel3DD;IACE,qBAAA;Ifo3DD;Eer3DD;IACE,YAAA;Ifu3DD;Eex3DD;IACE,qBAAA;If03DD;Ee33DD;IACE,qBAAA;If63DD;Ee93DD;IACE,YAAA;Ifg4DD;Eej4DD;IACE,qBAAA;Ifm4DD;Eep4DD;IACE,oBAAA;Ifs4DD;Eel4DD;IACE,aAAA;Ifo4DD;Eep5DD;IACE,YAAA;Ifs5DD;Eev5DD;IACE,oBAAA;Ify5DD;Ee15DD;IACE,oBAAA;If45DD;Ee75DD;IACE,WAAA;If+5DD;Eeh6DD;IACE,oBAAA;Ifk6DD;Een6DD;IACE,oBAAA;Ifq6DD;Eet6DD;IACE,WAAA;Ifw6DD;Eez6DD;IACE,oBAAA;If26DD;Ee56DD;IACE,oBAAA;If86DD;Ee/6DD;IACE,WAAA;Ifi7DD;Eel7DD;IACE,oBAAA;Ifo7DD;Eer7DD;IACE,mBAAA;Ifu7DD;Een7DD;IACE,YAAA;Ifq7DD;Eev6DD;IACE,mBAAA;Ify6DD;Ee16DD;IACE,2BAAA;If46DD;Ee76DD;IACE,2BAAA;If+6DD;Eeh7DD;IACE,kBAAA;Ifk7DD;Een7DD;IACE,2BAAA;Ifq7DD;Eet7DD;IACE,2BAAA;Ifw7DD;Eez7DD;IACE,kBAAA;If27DD;Ee57DD;IACE,2BAAA;If87DD;Ee/7DD;IACE,2BAAA;Ifi8DD;Eel8DD;IACE,kBAAA;Ifo8DD;Eer8DD;IACE,2BAAA;Ifu8DD;Eex8DD;IACE,0BAAA;If08DD;Ee38DD;IACE,iBAAA;If68DD;EACF;Aal8DD;EE9CI;IACE,aAAA;Ifm/DH;Ee5+DD;IACE,aAAA;If8+DD;Ee/+DD;IACE,qBAAA;Ifi/DD;Eel/DD;IACE,qBAAA;Ifo/DD;Eer/DD;IACE,YAAA;Ifu/DD;Eex/DD;IACE,qBAAA;If0/DD;Ee3/DD;IACE,qBAAA;If6/DD;Ee9/DD;IACE,YAAA;IfggED;EejgED;IACE,qBAAA;IfmgED;EepgED;IACE,qBAAA;IfsgED;EevgED;IACE,YAAA;IfygED;Ee1gED;IACE,qBAAA;If4gED;Ee7gED;IACE,oBAAA;If+gED;EejgED;IACE,aAAA;IfmgED;EepgED;IACE,qBAAA;IfsgED;EevgED;IACE,qBAAA;IfygED;Ee1gED;IACE,YAAA;If4gED;Ee7gED;IACE,qBAAA;If+gED;EehhED;IACE,qBAAA;IfkhED;EenhED;IACE,YAAA;IfqhED;EethED;IACE,qBAAA;IfwhED;EezhED;IACE,qBAAA;If2hED;Ee5hED;IACE,YAAA;If8hED;Ee/hED;IACE,qBAAA;IfiiED;EeliED;IACE,oBAAA;IfoiED;EehiED;IACE,aAAA;IfkiED;EeljED;IACE,YAAA;IfojED;EerjED;IACE,oBAAA;IfujED;EexjED;IACE,oBAAA;If0jED;Ee3jED;IACE,WAAA;If6jED;Ee9jED;IACE,oBAAA;IfgkED;EejkED;IACE,oBAAA;IfmkED;EepkED;IACE,WAAA;IfskED;EevkED;IACE,oBAAA;IfykED;Ee1kED;IACE,oBAAA;If4kED;Ee7kED;IACE,WAAA;If+kED;EehlED;IACE,oBAAA;IfklED;EenlED;IACE,mBAAA;IfqlED;EejlED;IACE,YAAA;IfmlED;EerkED;IACE,mBAAA;IfukED;EexkED;IACE,2BAAA;If0kED;Ee3kED;IACE,2BAAA;If6kED;Ee9kED;IACE,kBAAA;IfglED;EejlED;IACE,2BAAA;IfmlED;EeplED;IACE,2BAAA;IfslED;EevlED;IACE,kBAAA;IfylED;Ee1lED;IACE,2BAAA;If4lED;Ee7lED;IACE,2BAAA;If+lED;EehmED;IACE,kBAAA;IfkmED;EenmED;IACE,2BAAA;IfqmED;EetmED;IACE,0BAAA;IfwmED;EezmED;IACE,iBAAA;If2mED;EACF;AgB/qED;EACE,+BAAA;EhBirED;AgB/qED;EACE,kBAAA;EACA,qBAAA;EACA,gBAAA;EACA,kBAAA;EhBirED;AgB/qED;EACE,kBAAA;EhBirED;AgB3qED;EACE,aAAA;EACA,iBAAA;EACA,qBAAA;EhB6qED;AgBhrED;;;;;;EAWQ,cAAA;EACA,yBAAA;EACA,qBAAA;EACA,+BAAA;EhB6qEP;AgB3rED;EAoBI,wBAAA;EACA,kCAAA;EhB0qEH;AgB/rED;;;;;;EA8BQ,eAAA;EhByqEP;AgBvsED;EAoCI,+BAAA;EhBsqEH;AgB1sED;EAyCI,2BAAA;EhBoqEH;AgB7pED;;;;;;EAOQ,cAAA;EhB8pEP;AgBnpED;EACE,2BAAA;EhBqpED;AgBtpED;;;;;;EAQQ,2BAAA;EhBspEP;AgB9pED;;EAeM,0BAAA;EhBmpEL;AgBzoED;EAEI,2BAAA;EhB0oEH;AgBjoED;EAEI,2BAAA;EhBkoEH;AgBznED;EACE,kBAAA;EACA,aAAA;EACA,uBAAA;EhB2nED;AgBtnEG;;EACE,kBAAA;EACA,aAAA;EACA,qBAAA;EhBynEL;AiBrwEC;;;;;;;;;;;;EAOI,2BAAA;EjB4wEL;AiBtwEC;;;;;EAMI,2BAAA;EjBuwEL;AiB1xEC;;;;;;;;;;;;EAOI,2BAAA;EjBiyEL;AiB3xEC;;;;;EAMI,2BAAA;EjB4xEL;AiB/yEC;;;;;;;;;;;;EAOI,2BAAA;EjBszEL;AiBhzEC;;;;;EAMI,2BAAA;EjBizEL;AiBp0EC;;;;;;;;;;;;EAOI,2BAAA;EjB20EL;AiBr0EC;;;;;EAMI,2BAAA;EjBs0EL;AiBz1EC;;;;;;;;;;;;EAOI,2BAAA;EjBg2EL;AiB11EC;;;;;EAMI,2BAAA;EjB21EL;AgBzsED;EACE,kBAAA;EACA,mBAAA;EhB2sED;AgB9oED;EAAA;IA1DI,aAAA;IACA,qBAAA;IACA,oBAAA;IACA,8CAAA;IACA,2BAAA;IhB4sED;EgBtpEH;IAlDM,kBAAA;IhB2sEH;EgBzpEH;;;;;;IAzCY,qBAAA;IhB0sET;EgBjqEH;IAjCM,WAAA;IhBqsEH;EgBpqEH;;;;;;IAxBY,gBAAA;IhBosET;EgB5qEH;;;;;;IApBY,iBAAA;IhBwsET;EgBprEH;;;;IAPY,kBAAA;IhBisET;EACF;AkB35ED;EACE,YAAA;EACA,WAAA;EACA,WAAA;EAIA,cAAA;ElB05ED;AkBv5ED;EACE,gBAAA;EACA,aAAA;EACA,YAAA;EACA,qBAAA;EACA,iBAAA;EACA,sBAAA;EACA,gBAAA;EACA,WAAA;EACA,kCAAA;ElBy5ED;AkBt5ED;EACE,uBAAA;EACA,iBAAA;EACA,oBAAA;EACA,mBAAA;ElBw5ED;AkB74ED;Eb4BE,gCAAA;EACG,6BAAA;EACK,wBAAA;ELo3ET;AkB74ED;;EAEE,iBAAA;EACA,oBAAA;EACA,qBAAA;ElB+4ED;AkB34ED;EACE,gBAAA;ElB64ED;AkBz4ED;EACE,gBAAA;EACA,aAAA;ElB24ED;AkBv4ED;;EAEE,cAAA;ElBy4ED;AkBr4ED;;;EZxEE,sBAAA;EAEA,4CAAA;EACA,sBAAA;ENi9ED;AkBr4ED;EACE,gBAAA;EACA,kBAAA;EACA,iBAAA;EACA,yBAAA;EACA,gBAAA;ElBu4ED;AkB72ED;EACE,gBAAA;EACA,aAAA;EACA,cAAA;EACA,mBAAA;EACA,iBAAA;EACA,yBAAA;EACA,gBAAA;EACA,2BAAA;EACA,wBAAA;EACA,2BAAA;EACA,oBAAA;EbzDA,0DAAA;EACQ,kDAAA;EAyHR,wFAAA;EACK,2EAAA;EACG,wEAAA;ELizET;AmBz7EC;EACE,uBAAA;EACA,YAAA;EdUF,wFAAA;EACQ,gFAAA;ELk7ET;AKj5EC;EACE,gBAAA;EACA,YAAA;ELm5EH;AKj5EC;EAA0B,gBAAA;ELo5E3B;AKn5EC;EAAgC,gBAAA;ELs5EjC;AkBr3EC;;;EAGE,2BAAA;EACA,YAAA;ElBu3EH;AkBp3EC;;EAEE,qBAAA;ElBs3EH;AkBl3EC;EACE,cAAA;ElBo3EH;AkBx2ED;EACE,0BAAA;ElB02ED;AkBt0ED;EAxBE;;;;IAIE,mBAAA;IlBi2ED;EkB/1EC;;;;;;;;IAEE,mBAAA;IlBu2EH;EkBp2EC;;;;;;;;IAEE,mBAAA;IlB42EH;EACF;AkBl2ED;EACE,qBAAA;ElBo2ED;AkB51ED;;EAEE,oBAAA;EACA,gBAAA;EACA,kBAAA;EACA,qBAAA;ElB81ED;AkBn2ED;;EAQI,kBAAA;EACA,oBAAA;EACA,kBAAA;EACA,qBAAA;EACA,iBAAA;ElB+1EH;AkB51ED;;;;EAIE,oBAAA;EACA,oBAAA;EACA,oBAAA;ElB81ED;AkB31ED;;EAEE,kBAAA;ElB61ED;AkBz1ED;;EAEE,oBAAA;EACA,uBAAA;EACA,oBAAA;EACA,kBAAA;EACA,wBAAA;EACA,qBAAA;EACA,iBAAA;ElB21ED;AkBz1ED;;EAEE,eAAA;EACA,mBAAA;ElB21ED;AkBl1EC;;;;;;EAGE,qBAAA;ElBu1EH;AkBj1EC;;;;EAEE,qBAAA;ElBq1EH;AkB/0EC;;;;EAGI,qBAAA;ElBk1EL;AkBv0ED;EAEE,kBAAA;EACA,qBAAA;EAEA,kBAAA;EACA,kBAAA;ElBu0ED;AkBr0EC;;EAEE,iBAAA;EACA,kBAAA;ElBu0EH;AkB1zED;EC1PE,cAAA;EACA,mBAAA;EACA,iBAAA;EACA,kBAAA;EACA,oBAAA;EnBujFD;AmBrjFC;EACE,cAAA;EACA,mBAAA;EnBujFH;AmBpjFC;;EAEE,cAAA;EnBsjFH;AkBt0ED;EC7PE,cAAA;EACA,mBAAA;EACA,iBAAA;EACA,kBAAA;EACA,oBAAA;EnBskFD;AmBpkFC;EACE,cAAA;EACA,mBAAA;EnBskFH;AmBnkFC;;EAEE,cAAA;EnBqkFH;AkBr1ED;EAKI,cAAA;EACA,mBAAA;EACA,iBAAA;EACA,kBAAA;EACA,kBAAA;ElBm1EH;AkB/0ED;EC1QE,cAAA;EACA,oBAAA;EACA,iBAAA;EACA,wBAAA;EACA,oBAAA;EnB4lFD;AmB1lFC;EACE,cAAA;EACA,mBAAA;EnB4lFH;AmBzlFC;;EAEE,cAAA;EnB2lFH;AkB31ED;EC7QE,cAAA;EACA,oBAAA;EACA,iBAAA;EACA,wBAAA;EACA,oBAAA;EnB2mFD;AmBzmFC;EACE,cAAA;EACA,mBAAA;EnB2mFH;AmBxmFC;;EAEE,cAAA;EnB0mFH;AkB12ED;EAKI,cAAA;EACA,oBAAA;EACA,iBAAA;EACA,wBAAA;EACA,kBAAA;ElBw2EH;AkB/1ED;EAEE,oBAAA;ElBg2ED;AkBl2ED;EAMI,uBAAA;ElB+1EH;AkB31ED;EACE,oBAAA;EACA,QAAA;EACA,UAAA;EACA,YAAA;EACA,gBAAA;EACA,aAAA;EACA,cAAA;EACA,mBAAA;EACA,oBAAA;EACA,sBAAA;ElB61ED;AkB31ED;EACE,aAAA;EACA,cAAA;EACA,mBAAA;ElB61ED;AkB31ED;EACE,aAAA;EACA,cAAA;EACA,mBAAA;ElB61ED;AkBz1ED;;;;;;;;;;ECrXI,gBAAA;EnB0tFH;AkBr2ED;ECjXI,uBAAA;Ed+CF,0DAAA;EACQ,kDAAA;EL2qFT;AmBztFG;EACE,uBAAA;Ed4CJ,2EAAA;EACQ,mEAAA;ELgrFT;AkB/2ED;ECvWI,gBAAA;EACA,uBAAA;EACA,2BAAA;EnBytFH;AkBp3ED;ECjWI,gBAAA;EnBwtFH;AkBp3ED;;;;;;;;;;ECxXI,gBAAA;EnBwvFH;AkBh4ED;ECpXI,uBAAA;Ed+CF,0DAAA;EACQ,kDAAA;ELysFT;AmBvvFG;EACE,uBAAA;Ed4CJ,2EAAA;EACQ,mEAAA;EL8sFT;AkB14ED;EC1WI,gBAAA;EACA,uBAAA;EACA,2BAAA;EnBuvFH;AkB/4ED;ECpWI,gBAAA;EnBsvFH;AkB/4ED;;;;;;;;;;EC3XI,gBAAA;EnBsxFH;AkB35ED;ECvXI,uBAAA;Ed+CF,0DAAA;EACQ,kDAAA;ELuuFT;AmBrxFG;EACE,uBAAA;Ed4CJ,2EAAA;EACQ,mEAAA;EL4uFT;AkBr6ED;EC7WI,gBAAA;EACA,uBAAA;EACA,2BAAA;EnBqxFH;AkB16ED;ECvWI,gBAAA;EnBoxFH;AkBt6EC;EACG,WAAA;ElBw6EJ;AkBt6EC;EACG,QAAA;ElBw6EJ;AkB95ED;EACE,gBAAA;EACA,iBAAA;EACA,qBAAA;EACA,gBAAA;ElBg6ED;AkB70ED;EAAA;IA9DM,uBAAA;IACA,kBAAA;IACA,wBAAA;IlB+4EH;EkBn1EH;IAvDM,uBAAA;IACA,aAAA;IACA,wBAAA;IlB64EH;EkBx1EH;IAhDM,uBAAA;IlB24EH;EkB31EH;IA5CM,uBAAA;IACA,wBAAA;IlB04EH;EkB/1EH;;;IAtCQ,aAAA;IlB04EL;EkBp2EH;IAhCM,aAAA;IlBu4EH;EkBv2EH;IA5BM,kBAAA;IACA,wBAAA;IlBs4EH;EkB32EH;;IApBM,uBAAA;IACA,eAAA;IACA,kBAAA;IACA,wBAAA;IlBm4EH;EkBl3EH;;IAdQ,iBAAA;IlBo4EL;EkBt3EH;;IATM,oBAAA;IACA,gBAAA;IlBm4EH;EkB33EH;IAHM,QAAA;IlBi4EH;EACF;AkBv3ED;;;;EASI,eAAA;EACA,kBAAA;EACA,kBAAA;ElBo3EH;AkB/3ED;;EAiBI,kBAAA;ElBk3EH;AkBn4ED;EJjfE,oBAAA;EACA,qBAAA;Edu3FD;AkBh2EC;EAAA;IAVI,mBAAA;IACA,kBAAA;IACA,kBAAA;IlB82EH;EACF;AkB94ED;EAwCI,aAAA;ElBy2EH;AkB51EC;EAAA;IAHM,0BAAA;IlBm2EL;EACF;AkB11EC;EAAA;IAHM,kBAAA;IlBi2EL;EACF;AoBn5FD;EACE,uBAAA;EACA,kBAAA;EACA,qBAAA;EACA,oBAAA;EACA,wBAAA;EACA,gCAAA;MAAA,4BAAA;EACA,iBAAA;EACA,wBAAA;EACA,+BAAA;EACA,qBAAA;EC6BA,mBAAA;EACA,iBAAA;EACA,yBAAA;EACA,oBAAA;EhB4KA,2BAAA;EACG,wBAAA;EACC,uBAAA;EACI,mBAAA;EL8sFT;AoBt5FG;;;;;;EdrBF,sBAAA;EAEA,4CAAA;EACA,sBAAA;ENk7FD;AoB15FC;;;EAGE,gBAAA;EACA,uBAAA;EpB45FH;AoBz5FC;;EAEE,YAAA;EACA,wBAAA;Ef2BF,0DAAA;EACQ,kDAAA;ELi4FT;AoBz5FC;;;EAGE,qBAAA;EACA,sBAAA;EE9CF,eAAA;EAGA,2BAAA;EjB8DA,0BAAA;EACQ,kBAAA;EL24FT;AoBr5FD;ECrDE,gBAAA;EACA,2BAAA;EACA,uBAAA;ErB68FD;AqB38FC;;;;;;EAME,gBAAA;EACA,2BAAA;EACI,uBAAA;ErB68FP;AqB38FC;;;EAGE,wBAAA;ErB68FH;AqBx8FG;;;;;;;;;;;;;;;;;;EAME,2BAAA;EACI,uBAAA;ErBs9FT;AoB97FD;ECnBI,gBAAA;EACA,2BAAA;ErBo9FH;AoB/7FD;ECxDE,gBAAA;EACA,2BAAA;EACA,uBAAA;ErB0/FD;AqBx/FC;;;;;;EAME,gBAAA;EACA,2BAAA;EACI,uBAAA;ErB0/FP;AqBx/FC;;;EAGE,wBAAA;ErB0/FH;AqBr/FG;;;;;;;;;;;;;;;;;;EAME,2BAAA;EACI,uBAAA;ErBmgGT;AoBx+FD;ECtBI,gBAAA;EACA,2BAAA;ErBigGH;AoBx+FD;EC5DE,gBAAA;EACA,2BAAA;EACA,uBAAA;ErBuiGD;AqBriGC;;;;;;EAME,gBAAA;EACA,2BAAA;EACI,uBAAA;ErBuiGP;AqBriGC;;;EAGE,wBAAA;ErBuiGH;AqBliGG;;;;;;;;;;;;;;;;;;EAME,2BAAA;EACI,uBAAA;ErBgjGT;AoBjhGD;EC1BI,gBAAA;EACA,2BAAA;ErB8iGH;AoBjhGD;EChEE,gBAAA;EACA,2BAAA;EACA,uBAAA;ErBolGD;AqBllGC;;;;;;EAME,gBAAA;EACA,2BAAA;EACI,uBAAA;ErBolGP;AqBllGC;;;EAGE,wBAAA;ErBolGH;AqB/kGG;;;;;;;;;;;;;;;;;;EAME,2BAAA;EACI,uBAAA;ErB6lGT;AoB1jGD;EC9BI,gBAAA;EACA,2BAAA;ErB2lGH;AoB1jGD;ECpEE,gBAAA;EACA,2BAAA;EACA,uBAAA;ErBioGD;AqB/nGC;;;;;;EAME,gBAAA;EACA,2BAAA;EACI,uBAAA;ErBioGP;AqB/nGC;;;EAGE,wBAAA;ErBioGH;AqB5nGG;;;;;;;;;;;;;;;;;;EAME,2BAAA;EACI,uBAAA;ErB0oGT;AoBnmGD;EClCI,gBAAA;EACA,2BAAA;ErBwoGH;AoBnmGD;ECxEE,gBAAA;EACA,2BAAA;EACA,uBAAA;ErB8qGD;AqB5qGC;;;;;;EAME,gBAAA;EACA,2BAAA;EACI,uBAAA;ErB8qGP;AqB5qGC;;;EAGE,wBAAA;ErB8qGH;AqBzqGG;;;;;;;;;;;;;;;;;;EAME,2BAAA;EACI,uBAAA;ErBurGT;AoB5oGD;ECtCI,gBAAA;EACA,2BAAA;ErBqrGH;AoBvoGD;EACE,gBAAA;EACA,qBAAA;EACA,kBAAA;EpByoGD;AoBvoGC;;;;;EAKE,+BAAA;Ef7BF,0BAAA;EACQ,kBAAA;ELuqGT;AoBxoGC;;;;EAIE,2BAAA;EpB0oGH;AoBxoGC;;EAEE,gBAAA;EACA,4BAAA;EACA,+BAAA;EpB0oGH;AoBtoGG;;;;EAEE,gBAAA;EACA,uBAAA;EpB0oGL;AoBjoGD;;EC/EE,oBAAA;EACA,iBAAA;EACA,wBAAA;EACA,oBAAA;ErBotGD;AoBpoGD;;ECnFE,mBAAA;EACA,iBAAA;EACA,kBAAA;EACA,oBAAA;ErB2tGD;AoBvoGD;;ECvFE,kBAAA;EACA,iBAAA;EACA,kBAAA;EACA,oBAAA;ErBkuGD;AoBtoGD;EACE,gBAAA;EACA,aAAA;EpBwoGD;AoBpoGD;EACE,iBAAA;EpBsoGD;AoB/nGC;;;EACE,aAAA;EpBmoGH;AuBvxGD;EACE,YAAA;ElBoLA,0CAAA;EACK,qCAAA;EACG,kCAAA;ELsmGT;AuB1xGC;EACE,YAAA;EvB4xGH;AuBxxGD;EACE,eAAA;EvB0xGD;AuBxxGC;EAAY,gBAAA;EvB2xGb;AuB1xGC;EAAY,oBAAA;EvB6xGb;AuB5xGC;EAAY,0BAAA;EvB+xGb;AuB5xGD;EACE,oBAAA;EACA,WAAA;EACA,kBAAA;ElBuKA,iDAAA;EACQ,4CAAA;KAAA,yCAAA;EAOR,oCAAA;EACQ,+BAAA;KAAA,4BAAA;EAGR,0CAAA;EACQ,qCAAA;KAAA,kCAAA;ELgnGT;AwB1zGD;EACE,uBAAA;EACA,UAAA;EACA,WAAA;EACA,kBAAA;EACA,wBAAA;EACA,wBAAA;EACA,qCAAA;EACA,oCAAA;ExB4zGD;AwBxzGD;;EAEE,oBAAA;ExB0zGD;AwBtzGD;EACE,YAAA;ExBwzGD;AwBpzGD;EACE,oBAAA;EACA,WAAA;EACA,SAAA;EACA,eAAA;EACA,eAAA;EACA,aAAA;EACA,kBAAA;EACA,gBAAA;EACA,iBAAA;EACA,kBAAA;EACA,iBAAA;EACA,kBAAA;EACA,2BAAA;EACA,2BAAA;EACA,uCAAA;EACA,oBAAA;EnBuBA,qDAAA;EACQ,6CAAA;EmBtBR,sCAAA;UAAA,8BAAA;ExBuzGD;AwBlzGC;EACE,UAAA;EACA,YAAA;ExBozGH;AwB70GD;ECxBE,aAAA;EACA,eAAA;EACA,kBAAA;EACA,2BAAA;EzBw2GD;AwBn1GD;EAmCI,gBAAA;EACA,mBAAA;EACA,aAAA;EACA,qBAAA;EACA,yBAAA;EACA,gBAAA;EACA,qBAAA;ExBmzGH;AwB7yGC;;EAEE,uBAAA;EACA,gBAAA;EACA,2BAAA;ExB+yGH;AwBzyGC;;;EAGE,gBAAA;EACA,uBAAA;EACA,YAAA;EACA,2BAAA;ExB2yGH;AwBlyGC;;;EAGE,gBAAA;ExBoyGH;AwBhyGC;;EAEE,uBAAA;EACA,+BAAA;EACA,wBAAA;EE1GF,qEAAA;EF4GE,qBAAA;ExBkyGH;AwB7xGD;EAGI,gBAAA;ExB6xGH;AwBhyGD;EAQI,YAAA;ExB2xGH;AwBnxGD;EACE,YAAA;EACA,UAAA;ExBqxGD;AwB7wGD;EACE,SAAA;EACA,aAAA;ExB+wGD;AwB3wGD;EACE,gBAAA;EACA,mBAAA;EACA,iBAAA;EACA,yBAAA;EACA,gBAAA;EACA,qBAAA;ExB6wGD;AwBzwGD;EACE,iBAAA;EACA,SAAA;EACA,UAAA;EACA,WAAA;EACA,QAAA;EACA,cAAA;ExB2wGD;AwBvwGD;EACE,UAAA;EACA,YAAA;ExBywGD;AwBjwGD;;EAII,eAAA;EACA,0BAAA;EACA,aAAA;ExBiwGH;AwBvwGD;;EAUI,WAAA;EACA,cAAA;EACA,oBAAA;ExBiwGH;AwB5uGD;EAXE;IAnEA,YAAA;IACA,UAAA;IxB8zGC;EwB5vGD;IAzDA,SAAA;IACA,aAAA;IxBwzGC;EACF;A2Bv8GD;;EAEE,oBAAA;EACA,uBAAA;EACA,wBAAA;E3By8GD;A2B78GD;;EAMI,oBAAA;EACA,aAAA;E3B28GH;A2Bz8GG;;;;;;;;EAIE,YAAA;E3B+8GL;A2Bz8GD;;;;EAKI,mBAAA;E3B08GH;A2Br8GD;EACE,mBAAA;E3Bu8GD;A2Bx8GD;;EAMI,aAAA;E3Bs8GH;A2B58GD;;;EAWI,kBAAA;E3Bs8GH;A2Bl8GD;EACE,kBAAA;E3Bo8GD;A2Bh8GD;EACE,gBAAA;E3Bk8GD;A2Bj8GC;ECjDA,+BAAA;EACG,4BAAA;E5Bq/GJ;A2Bh8GD;;EC9CE,8BAAA;EACG,2BAAA;E5Bk/GJ;A2B/7GD;EACE,aAAA;E3Bi8GD;A2B/7GD;EACE,kBAAA;E3Bi8GD;A2B/7GD;;EClEE,+BAAA;EACG,4BAAA;E5BqgHJ;A2B97GD;EChEE,8BAAA;EACG,2BAAA;E5BigHJ;A2B77GD;;EAEE,YAAA;E3B+7GD;A2B96GD;EACE,mBAAA;EACA,oBAAA;E3Bg7GD;A2B96GD;EACE,oBAAA;EACA,qBAAA;E3Bg7GD;A2B36GD;EtB9CE,0DAAA;EACQ,kDAAA;EL49GT;A2B36GC;EtBlDA,0BAAA;EACQ,kBAAA;ELg+GT;A2Bx6GD;EACE,gBAAA;E3B06GD;A2Bv6GD;EACE,yBAAA;EACA,wBAAA;E3By6GD;A2Bt6GD;EACE,yBAAA;E3Bw6GD;A2Bj6GD;;;EAII,gBAAA;EACA,aAAA;EACA,aAAA;EACA,iBAAA;E3Bk6GH;A2Bz6GD;EAcM,aAAA;E3B85GL;A2B56GD;;;;EAsBI,kBAAA;EACA,gBAAA;E3B45GH;A2Bv5GC;EACE,kBAAA;E3By5GH;A2Bv5GC;EACE,8BAAA;ECnKF,+BAAA;EACC,8BAAA;E5B6jHF;A2Bx5GC;EACE,gCAAA;EC/KF,4BAAA;EACC,2BAAA;E5B0kHF;A2Bx5GD;EACE,kBAAA;E3B05GD;A2Bx5GD;;EC9KE,+BAAA;EACC,8BAAA;E5B0kHF;A2Bv5GD;EC5LE,4BAAA;EACC,2BAAA;E5BslHF;A2Bn5GD;EACE,gBAAA;EACA,aAAA;EACA,qBAAA;EACA,2BAAA;E3Bq5GD;A2Bz5GD;;EAOI,aAAA;EACA,qBAAA;EACA,WAAA;E3Bs5GH;A2B/5GD;EAYI,aAAA;E3Bs5GH;A2Bl6GD;EAgBI,YAAA;E3Bq5GH;A2Bp4GD;;;;EAKM,oBAAA;EACA,wBAAA;EACA,sBAAA;E3Bq4GL;A6B9mHD;EACE,oBAAA;EACA,gBAAA;EACA,2BAAA;E7BgnHD;A6B7mHC;EACE,aAAA;EACA,iBAAA;EACA,kBAAA;E7B+mHH;A6BxnHD;EAeI,oBAAA;EACA,YAAA;EAKA,aAAA;EAEA,aAAA;EACA,kBAAA;E7BumHH;A6B9lHD;;;EV8BE,cAAA;EACA,oBAAA;EACA,iBAAA;EACA,wBAAA;EACA,oBAAA;EnBqkHD;AmBnkHC;;;EACE,cAAA;EACA,mBAAA;EnBukHH;AmBpkHC;;;;;;EAEE,cAAA;EnB0kHH;A6BhnHD;;;EVyBE,cAAA;EACA,mBAAA;EACA,iBAAA;EACA,kBAAA;EACA,oBAAA;EnB4lHD;AmB1lHC;;;EACE,cAAA;EACA,mBAAA;EnB8lHH;AmB3lHC;;;;;;EAEE,cAAA;EnBimHH;A6B9nHD;;;EAGE,qBAAA;E7BgoHD;A6B9nHC;;;EACE,kBAAA;E7BkoHH;A6B9nHD;;EAEE,WAAA;EACA,qBAAA;EACA,wBAAA;E7BgoHD;A6B3nHD;EACE,mBAAA;EACA,iBAAA;EACA,qBAAA;EACA,gBAAA;EACA,gBAAA;EACA,oBAAA;EACA,2BAAA;EACA,2BAAA;EACA,oBAAA;E7B6nHD;A6B1nHC;EACE,mBAAA;EACA,iBAAA;EACA,oBAAA;E7B4nHH;A6B1nHC;EACE,oBAAA;EACA,iBAAA;EACA,oBAAA;E7B4nHH;A6BhpHD;;EA0BI,eAAA;E7B0nHH;A6BrnHD;;;;;;;EDhGE,+BAAA;EACG,4BAAA;E5B8tHJ;A6BtnHD;EACE,iBAAA;E7BwnHD;A6BtnHD;;;;;;;EDpGE,8BAAA;EACG,2BAAA;E5BmuHJ;A6BvnHD;EACE,gBAAA;E7BynHD;A6BpnHD;EACE,oBAAA;EAGA,cAAA;EACA,qBAAA;E7BonHD;A6BznHD;EAUI,oBAAA;E7BknHH;A6B5nHD;EAYM,mBAAA;E7BmnHL;A6BhnHG;;;EAGE,YAAA;E7BknHL;A6B7mHC;;EAGI,oBAAA;E7B8mHL;A6B3mHC;;EAGI,mBAAA;E7B4mHL;A8BtwHD;EACE,kBAAA;EACA,iBAAA;EACA,kBAAA;E9BwwHD;A8B3wHD;EAOI,oBAAA;EACA,gBAAA;E9BuwHH;A8B/wHD;EAWM,oBAAA;EACA,gBAAA;EACA,oBAAA;E9BuwHL;A8BtwHK;;EAEE,uBAAA;EACA,2BAAA;E9BwwHP;A8BnwHG;EACE,gBAAA;E9BqwHL;A8BnwHK;;EAEE,gBAAA;EACA,uBAAA;EACA,+BAAA;EACA,qBAAA;E9BqwHP;A8B9vHG;;;EAGE,2BAAA;EACA,uBAAA;E9BgwHL;A8BzyHD;ELHE,aAAA;EACA,eAAA;EACA,kBAAA;EACA,2BAAA;EzB+yHD;A8B/yHD;EA0DI,iBAAA;E9BwvHH;A8B/uHD;EACE,kCAAA;E9BivHD;A8BlvHD;EAGI,aAAA;EAEA,qBAAA;E9BivHH;A8BtvHD;EASM,mBAAA;EACA,yBAAA;EACA,+BAAA;EACA,4BAAA;E9BgvHL;A8B/uHK;EACE,uCAAA;E9BivHP;A8B3uHK;;;EAGE,gBAAA;EACA,2BAAA;EACA,2BAAA;EACA,kCAAA;EACA,iBAAA;E9B6uHP;A8BxuHC;EAqDA,aAAA;EA8BA,kBAAA;E9BypHD;A8B5uHC;EAwDE,aAAA;E9BurHH;A8B/uHC;EA0DI,oBAAA;EACA,oBAAA;E9BwrHL;A8BnvHC;EAgEE,WAAA;EACA,YAAA;E9BsrHH;A8B1qHD;EAAA;IAPM,qBAAA;IACA,WAAA;I9BqrHH;E8B/qHH;IAJQ,kBAAA;I9BsrHL;EACF;A8BhwHC;EAuFE,iBAAA;EACA,oBAAA;E9B4qHH;A8BpwHC;;;EA8FE,2BAAA;E9B2qHH;A8B7pHD;EAAA;IATM,kCAAA;IACA,4BAAA;I9B0qHH;E8BlqHH;;;IAHM,8BAAA;I9B0qHH;EACF;A8B3wHD;EAEI,aAAA;E9B4wHH;A8B9wHD;EAMM,oBAAA;E9B2wHL;A8BjxHD;EASM,kBAAA;E9B2wHL;A8BtwHK;;;EAGE,gBAAA;EACA,2BAAA;E9BwwHP;A8BhwHD;EAEI,aAAA;E9BiwHH;A8BnwHD;EAIM,iBAAA;EACA,gBAAA;E9BkwHL;A8BtvHD;EACE,aAAA;E9BwvHD;A8BzvHD;EAII,aAAA;E9BwvHH;A8B5vHD;EAMM,oBAAA;EACA,oBAAA;E9ByvHL;A8BhwHD;EAYI,WAAA;EACA,YAAA;E9BuvHH;A8B3uHD;EAAA;IAPM,qBAAA;IACA,WAAA;I9BsvHH;E8BhvHH;IAJQ,kBAAA;I9BuvHL;EACF;A8B/uHD;EACE,kBAAA;E9BivHD;A8BlvHD;EAKI,iBAAA;EACA,oBAAA;E9BgvHH;A8BtvHD;;;EAYI,2BAAA;E9B+uHH;A8BjuHD;EAAA;IATM,kCAAA;IACA,4BAAA;I9B8uHH;E8BtuHH;;;IAHM,8BAAA;I9B8uHH;EACF;A8BruHD;EAEI,eAAA;E9BsuHH;A8BxuHD;EAKI,gBAAA;E9BsuHH;A8B7tHD;EAEE,kBAAA;EF3OA,4BAAA;EACC,2BAAA;E5B08HF;A+Bp8HD;EACE,oBAAA;EACA,kBAAA;EACA,qBAAA;EACA,+BAAA;E/Bs8HD;A+B97HD;EAAA;IAFI,oBAAA;I/Bo8HD;EACF;A+Br7HD;EAAA;IAFI,aAAA;I/B27HD;EACF;A+B76HD;EACE,qBAAA;EACA,qBAAA;EACA,oBAAA;EACA,mCAAA;EACA,4DAAA;UAAA,oDAAA;EAEA,mCAAA;E/B86HD;A+B56HC;EACE,kBAAA;E/B86HH;A+Bl5HD;EAAA;IAxBI,aAAA;IACA,eAAA;IACA,0BAAA;YAAA,kBAAA;I/B86HD;E+B56HC;IACE,2BAAA;IACA,yBAAA;IACA,mBAAA;IACA,8BAAA;I/B86HH;E+B36HC;IACE,qBAAA;I/B66HH;E+Bx6HC;;;IAGE,iBAAA;IACA,kBAAA;I/B06HH;EACF;A+Bt6HD;;EAGI,mBAAA;E/Bu6HH;A+Bl6HC;EAAA;;IAFI,mBAAA;I/By6HH;EACF;A+Bh6HD;;;;EAII,qBAAA;EACA,oBAAA;E/Bk6HH;A+B55HC;EAAA;;;;IAHI,iBAAA;IACA,gBAAA;I/Bs6HH;EACF;A+B15HD;EACE,eAAA;EACA,uBAAA;E/B45HD;A+Bv5HD;EAAA;IAFI,kBAAA;I/B65HD;EACF;A+Bz5HD;;EAEE,iBAAA;EACA,UAAA;EACA,SAAA;EACA,eAAA;E/B25HD;A+Br5HD;EAAA;;IAFI,kBAAA;I/B45HD;EACF;A+B15HD;EACE,QAAA;EACA,uBAAA;E/B45HD;A+B15HD;EACE,WAAA;EACA,kBAAA;EACA,uBAAA;E/B45HD;A+Bt5HD;EACE,aAAA;EACA,oBAAA;EACA,iBAAA;EACA,mBAAA;EACA,cAAA;E/Bw5HD;A+Bt5HC;;EAEE,uBAAA;E/Bw5HH;A+Bj6HD;EAaI,gBAAA;E/Bu5HH;A+B94HD;EALI;;IAEE,oBAAA;I/Bs5HH;EACF;A+B54HD;EACE,oBAAA;EACA,cAAA;EACA,oBAAA;EACA,mBAAA;EC9LA,iBAAA;EACA,oBAAA;ED+LA,+BAAA;EACA,wBAAA;EACA,+BAAA;EACA,oBAAA;E/B+4HD;A+B34HC;EACE,YAAA;E/B64HH;A+B35HD;EAmBI,gBAAA;EACA,aAAA;EACA,aAAA;EACA,oBAAA;E/B24HH;A+Bj6HD;EAyBI,iBAAA;E/B24HH;A+Br4HD;EAAA;IAFI,eAAA;I/B24HD;EACF;A+Bl4HD;EACE,qBAAA;E/Bo4HD;A+Br4HD;EAII,mBAAA;EACA,sBAAA;EACA,mBAAA;E/Bo4HH;A+Bx2HC;EAAA;IAtBI,kBAAA;IACA,aAAA;IACA,aAAA;IACA,eAAA;IACA,+BAAA;IACA,WAAA;IACA,0BAAA;YAAA,kBAAA;I/Bk4HH;E+Bl3HD;;IAbM,4BAAA;I/Bm4HL;E+Bt3HD;IAVM,mBAAA;I/Bm4HL;E+Bl4HK;;IAEE,wBAAA;I/Bo4HP;EACF;A+Bl3HD;EAAA;IAXI,aAAA;IACA,WAAA;I/Bi4HD;E+Bv3HH;IAPM,aAAA;I/Bi4HH;E+B13HH;IALQ,mBAAA;IACA,sBAAA;I/Bk4HL;EACF;A+Bv3HD;EACE,oBAAA;EACA,qBAAA;EACA,oBAAA;EACA,mCAAA;EACA,sCAAA;E1B9NA,8FAAA;EACQ,sFAAA;E2B/DR,iBAAA;EACA,oBAAA;EhCwpID;AkBvqHD;EAAA;IA9DM,uBAAA;IACA,kBAAA;IACA,wBAAA;IlByuHH;EkB7qHH;IAvDM,uBAAA;IACA,aAAA;IACA,wBAAA;IlBuuHH;EkBlrHH;IAhDM,uBAAA;IlBquHH;EkBrrHH;IA5CM,uBAAA;IACA,wBAAA;IlBouHH;EkBzrHH;;;IAtCQ,aAAA;IlBouHL;EkB9rHH;IAhCM,aAAA;IlBiuHH;EkBjsHH;IA5BM,kBAAA;IACA,wBAAA;IlBguHH;EkBrsHH;;IApBM,uBAAA;IACA,eAAA;IACA,kBAAA;IACA,wBAAA;IlB6tHH;EkB5sHH;;IAdQ,iBAAA;IlB8tHL;EkBhtHH;;IATM,oBAAA;IACA,gBAAA;IlB6tHH;EkBrtHH;IAHM,QAAA;IlB2tHH;EACF;A+Bh6HC;EAAA;IANI,oBAAA;I/B06HH;E+Bx6HG;IACE,kBAAA;I/B06HL;EACF;A+Bz5HD;EAAA;IARI,aAAA;IACA,WAAA;IACA,gBAAA;IACA,iBAAA;IACA,gBAAA;IACA,mBAAA;I1BzPF,0BAAA;IACQ,kBAAA;IL+pIP;EACF;A+B/5HD;EACE,eAAA;EHpUA,4BAAA;EACC,2BAAA;E5BsuIF;A+B/5HD;EACE,kBAAA;EHzUA,8BAAA;EACC,6BAAA;EAOD,+BAAA;EACC,8BAAA;E5BquIF;A+B35HD;EChVE,iBAAA;EACA,oBAAA;EhC8uID;A+B55HC;ECnVA,kBAAA;EACA,qBAAA;EhCkvID;A+B75HC;ECtVA,kBAAA;EACA,qBAAA;EhCsvID;A+Bv5HD;EChWE,kBAAA;EACA,qBAAA;EhC0vID;A+Bn5HD;EAAA;IAJI,aAAA;IACA,mBAAA;IACA,oBAAA;I/B25HD;EACF;A+B93HD;EAhBE;IExWA,wBAAA;IjC0vIC;E+Bj5HD;IE5WA,yBAAA;IF8WE,qBAAA;I/Bm5HD;E+Br5HD;IAKI,iBAAA;I/Bm5HH;EACF;A+B14HD;EACE,2BAAA;EACA,uBAAA;E/B44HD;A+B94HD;EAKI,gBAAA;E/B44HH;A+B34HG;;EAEE,gBAAA;EACA,+BAAA;E/B64HL;A+Bt5HD;EAcI,gBAAA;E/B24HH;A+Bz5HD;EAmBM,gBAAA;E/By4HL;A+Bv4HK;;EAEE,gBAAA;EACA,+BAAA;E/By4HP;A+Br4HK;;;EAGE,gBAAA;EACA,2BAAA;E/Bu4HP;A+Bn4HK;;;EAGE,gBAAA;EACA,+BAAA;E/Bq4HP;A+B76HD;EA8CI,uBAAA;E/Bk4HH;A+Bj4HG;;EAEE,2BAAA;E/Bm4HL;A+Bp7HD;EAoDM,2BAAA;E/Bm4HL;A+Bv7HD;;EA0DI,uBAAA;E/Bi4HH;A+B13HK;;;EAGE,2BAAA;EACA,gBAAA;E/B43HP;A+B31HC;EAAA;IAzBQ,gBAAA;I/Bw3HP;E+Bv3HO;;IAEE,gBAAA;IACA,+BAAA;I/By3HT;E+Br3HO;;;IAGE,gBAAA;IACA,2BAAA;I/Bu3HT;E+Bn3HO;;;IAGE,gBAAA;IACA,+BAAA;I/Bq3HT;EACF;A+Bv9HD;EA8GI,gBAAA;E/B42HH;A+B32HG;EACE,gBAAA;E/B62HL;A+B79HD;EAqHI,gBAAA;E/B22HH;A+B12HG;;EAEE,gBAAA;E/B42HL;A+Bx2HK;;;;EAEE,gBAAA;E/B42HP;A+Bp2HD;EACE,2BAAA;EACA,uBAAA;E/Bs2HD;A+Bx2HD;EAKI,gBAAA;E/Bs2HH;A+Br2HG;;EAEE,gBAAA;EACA,+BAAA;E/Bu2HL;A+Bh3HD;EAcI,gBAAA;E/Bq2HH;A+Bn3HD;EAmBM,gBAAA;E/Bm2HL;A+Bj2HK;;EAEE,gBAAA;EACA,+BAAA;E/Bm2HP;A+B/1HK;;;EAGE,gBAAA;EACA,2BAAA;E/Bi2HP;A+B71HK;;;EAGE,gBAAA;EACA,+BAAA;E/B+1HP;A+Bv4HD;EA+CI,uBAAA;E/B21HH;A+B11HG;;EAEE,2BAAA;E/B41HL;A+B94HD;EAqDM,2BAAA;E/B41HL;A+Bj5HD;;EA2DI,uBAAA;E/B01HH;A+Bp1HK;;;EAGE,2BAAA;EACA,gBAAA;E/Bs1HP;A+B/yHC;EAAA;IA/BQ,uBAAA;I/Bk1HP;E+BnzHD;IA5BQ,2BAAA;I/Bk1HP;E+BtzHD;IAzBQ,gBAAA;I/Bk1HP;E+Bj1HO;;IAEE,gBAAA;IACA,+BAAA;I/Bm1HT;E+B/0HO;;;IAGE,gBAAA;IACA,2BAAA;I/Bi1HT;E+B70HO;;;IAGE,gBAAA;IACA,+BAAA;I/B+0HT;EACF;A+Bv7HD;EA+GI,gBAAA;E/B20HH;A+B10HG;EACE,gBAAA;E/B40HL;A+B77HD;EAsHI,gBAAA;E/B00HH;A+Bz0HG;;EAEE,gBAAA;E/B20HL;A+Bv0HK;;;;EAEE,gBAAA;E/B20HP;AkCr9ID;EACE,mBAAA;EACA,qBAAA;EACA,kBAAA;EACA,2BAAA;EACA,oBAAA;ElCu9ID;AkC59ID;EAQI,uBAAA;ElCu9IH;AkC/9ID;EAWM,mBAAA;EACA,gBAAA;EACA,gBAAA;ElCu9IL;AkCp+ID;EAkBI,gBAAA;ElCq9IH;AmCz+ID;EACE,uBAAA;EACA,iBAAA;EACA,gBAAA;EACA,oBAAA;EnC2+ID;AmC/+ID;EAOI,iBAAA;EnC2+IH;AmCl/ID;;EAUM,oBAAA;EACA,aAAA;EACA,mBAAA;EACA,yBAAA;EACA,uBAAA;EACA,gBAAA;EACA,2BAAA;EACA,2BAAA;EACA,mBAAA;EnC4+IL;AmC1+IG;;EAGI,gBAAA;EPXN,gCAAA;EACG,6BAAA;E5Bu/IJ;AmCz+IG;;EPvBF,iCAAA;EACG,8BAAA;E5BogJJ;AmCp+IG;;;;EAEE,gBAAA;EACA,2BAAA;EACA,uBAAA;EnCw+IL;AmCl+IG;;;;;;EAGE,YAAA;EACA,gBAAA;EACA,2BAAA;EACA,uBAAA;EACA,iBAAA;EnCu+IL;AmC7hJD;;;;;;EAiEM,gBAAA;EACA,2BAAA;EACA,uBAAA;EACA,qBAAA;EnCo+IL;AmC39ID;;EC1EM,oBAAA;EACA,iBAAA;EpCyiJL;AoCviJG;;ERMF,gCAAA;EACG,6BAAA;E5BqiJJ;AoCtiJG;;ERRF,iCAAA;EACG,8BAAA;E5BkjJJ;AmCr+ID;;EC/EM,mBAAA;EACA,iBAAA;EpCwjJL;AoCtjJG;;ERMF,gCAAA;EACG,6BAAA;E5BojJJ;AoCrjJG;;ERRF,iCAAA;EACG,8BAAA;E5BikJJ;AqCpkJD;EACE,iBAAA;EACA,gBAAA;EACA,kBAAA;EACA,oBAAA;ErCskJD;AqC1kJD;EAOI,iBAAA;ErCskJH;AqC7kJD;;EAUM,uBAAA;EACA,mBAAA;EACA,2BAAA;EACA,2BAAA;EACA,qBAAA;ErCukJL;AqCrlJD;;EAmBM,uBAAA;EACA,2BAAA;ErCskJL;AqC1lJD;;EA2BM,cAAA;ErCmkJL;AqC9lJD;;EAkCM,aAAA;ErCgkJL;AqClmJD;;;;EA2CM,gBAAA;EACA,2BAAA;EACA,qBAAA;ErC6jJL;AsC3mJD;EACE,iBAAA;EACA,yBAAA;EACA,gBAAA;EACA,mBAAA;EACA,gBAAA;EACA,gBAAA;EACA,oBAAA;EACA,qBAAA;EACA,0BAAA;EACA,sBAAA;EtC6mJD;AsCzmJG;;EAEE,gBAAA;EACA,uBAAA;EACA,iBAAA;EtC2mJL;AsCtmJC;EACE,eAAA;EtCwmJH;AsCpmJC;EACE,oBAAA;EACA,WAAA;EtCsmJH;AsC/lJD;ECtCE,2BAAA;EvCwoJD;AuCroJG;;EAEE,2BAAA;EvCuoJL;AsClmJD;EC1CE,2BAAA;EvC+oJD;AuC5oJG;;EAEE,2BAAA;EvC8oJL;AsCrmJD;EC9CE,2BAAA;EvCspJD;AuCnpJG;;EAEE,2BAAA;EvCqpJL;AsCxmJD;EClDE,2BAAA;EvC6pJD;AuC1pJG;;EAEE,2BAAA;EvC4pJL;AsC3mJD;ECtDE,2BAAA;EvCoqJD;AuCjqJG;;EAEE,2BAAA;EvCmqJL;AsC9mJD;EC1DE,2BAAA;EvC2qJD;AuCxqJG;;EAEE,2BAAA;EvC0qJL;AwC5qJD;EACE,uBAAA;EACA,iBAAA;EACA,kBAAA;EACA,iBAAA;EACA,mBAAA;EACA,gBAAA;EACA,gBAAA;EACA,0BAAA;EACA,qBAAA;EACA,oBAAA;EACA,2BAAA;EACA,qBAAA;ExC8qJD;AwC3qJC;EACE,eAAA;ExC6qJH;AwCzqJC;EACE,oBAAA;EACA,WAAA;ExC2qJH;AwCxqJC;;EAEE,QAAA;EACA,kBAAA;ExC0qJH;AwCrqJG;;EAEE,gBAAA;EACA,uBAAA;EACA,iBAAA;ExCuqJL;AwClqJC;;EAEE,gBAAA;EACA,2BAAA;ExCoqJH;AwCjqJC;EACE,cAAA;ExCmqJH;AwChqJC;EACE,mBAAA;ExCkqJH;AwC/pJC;EACE,kBAAA;ExCiqJH;AyC3tJD;EACE,oBAAA;EACA,qBAAA;EACA,gBAAA;EACA,2BAAA;EzC6tJD;AyCjuJD;;EAQI,gBAAA;EzC6tJH;AyCruJD;EAYI,qBAAA;EACA,iBAAA;EACA,kBAAA;EzC4tJH;AyC1uJD;EAkBI,2BAAA;EzC2tJH;AyCxtJC;;EAEE,oBAAA;EzC0tJH;AyCjvJD;EA2BI,iBAAA;EzCytJH;AyCxsJD;EAAA;IAbI,iBAAA;IzCytJD;EyCvtJC;;IAEE,oBAAA;IACA,qBAAA;IzCytJH;EyCjtJH;;IAHM,iBAAA;IzCwtJH;EACF;A0CjwJD;EACE,gBAAA;EACA,cAAA;EACA,qBAAA;EACA,yBAAA;EACA,2BAAA;EACA,2BAAA;EACA,oBAAA;ErCiLA,6CAAA;EACK,wCAAA;EACG,qCAAA;ELmlJT;A0C7wJD;;EAaI,mBAAA;EACA,oBAAA;E1CowJH;A0ChwJC;;;EAGE,uBAAA;E1CkwJH;A0CvxJD;EA0BI,cAAA;EACA,gBAAA;E1CgwJH;A2CzxJD;EACE,eAAA;EACA,qBAAA;EACA,+BAAA;EACA,oBAAA;E3C2xJD;A2C/xJD;EAQI,eAAA;EAEA,gBAAA;E3CyxJH;A2CnyJD;EAeI,mBAAA;E3CuxJH;A2CtyJD;;EAqBI,kBAAA;E3CqxJH;A2C1yJD;EAyBI,iBAAA;E3CoxJH;A2C5wJD;;EAEE,qBAAA;E3C8wJD;A2ChxJD;;EAMI,oBAAA;EACA,WAAA;EACA,cAAA;EACA,gBAAA;E3C8wJH;A2CtwJD;ECvDE,2BAAA;EACA,uBAAA;EACA,gBAAA;E5Cg0JD;A2C3wJD;EClDI,2BAAA;E5Cg0JH;A2C9wJD;EC/CI,gBAAA;E5Cg0JH;A2C7wJD;EC3DE,2BAAA;EACA,uBAAA;EACA,gBAAA;E5C20JD;A2ClxJD;ECtDI,2BAAA;E5C20JH;A2CrxJD;ECnDI,gBAAA;E5C20JH;A2CpxJD;EC/DE,2BAAA;EACA,uBAAA;EACA,gBAAA;E5Cs1JD;A2CzxJD;EC1DI,2BAAA;E5Cs1JH;A2C5xJD;ECvDI,gBAAA;E5Cs1JH;A2C3xJD;ECnEE,2BAAA;EACA,uBAAA;EACA,gBAAA;E5Ci2JD;A2ChyJD;EC9DI,2BAAA;E5Ci2JH;A2CnyJD;EC3DI,gBAAA;E5Ci2JH;A6Cn2JD;EACE;IAAQ,6BAAA;I7Cs2JP;E6Cr2JD;IAAQ,0BAAA;I7Cw2JP;EACF;A6Cr2JD;EACE;IAAQ,6BAAA;I7Cw2JP;E6Cv2JD;IAAQ,0BAAA;I7C02JP;EACF;A6C72JD;EACE;IAAQ,6BAAA;I7Cw2JP;E6Cv2JD;IAAQ,0BAAA;I7C02JP;EACF;A6Cn2JD;EACE,kBAAA;EACA,cAAA;EACA,qBAAA;EACA,2BAAA;EACA,oBAAA;ExCsCA,wDAAA;EACQ,gDAAA;ELg0JT;A6Cl2JD;EACE,aAAA;EACA,WAAA;EACA,cAAA;EACA,iBAAA;EACA,mBAAA;EACA,gBAAA;EACA,oBAAA;EACA,2BAAA;ExCyBA,wDAAA;EACQ,gDAAA;EAyHR,qCAAA;EACK,gCAAA;EACG,6BAAA;ELotJT;A6C/1JD;;ECCI,+MAAA;EACA,0MAAA;EACA,uMAAA;EDAF,oCAAA;UAAA,4BAAA;E7Cm2JD;A6C51JD;;ExC5CE,4DAAA;EACK,uDAAA;EACG,oDAAA;EL44JT;A6Cz1JD;EErEE,2BAAA;E/Ci6JD;A+C95JC;EDgDE,+MAAA;EACA,0MAAA;EACA,uMAAA;E9Ci3JH;A6C71JD;EEzEE,2BAAA;E/Cy6JD;A+Ct6JC;EDgDE,+MAAA;EACA,0MAAA;EACA,uMAAA;E9Cy3JH;A6Cj2JD;EE7EE,2BAAA;E/Ci7JD;A+C96JC;EDgDE,+MAAA;EACA,0MAAA;EACA,uMAAA;E9Ci4JH;A6Cr2JD;EEjFE,2BAAA;E/Cy7JD;A+Ct7JC;EDgDE,+MAAA;EACA,0MAAA;EACA,uMAAA;E9Cy4JH;AgDj8JD;EAEE,kBAAA;EhDk8JD;AgDh8JC;EACE,eAAA;EhDk8JH;AgD97JD;;EAEE,SAAA;EACA,kBAAA;EhDg8JD;AgD77JD;EACE,gBAAA;EhD+7JD;AgD57JD;EACE,gBAAA;EhD87JD;AgD37JD;;EAEE,oBAAA;EhD67JD;AgD17JD;;EAEE,qBAAA;EhD47JD;AgDz7JD;;;EAGE,qBAAA;EACA,qBAAA;EhD27JD;AgDx7JD;EACE,wBAAA;EhD07JD;AgDv7JD;EACE,wBAAA;EhDy7JD;AgDr7JD;EACE,eAAA;EACA,oBAAA;EhDu7JD;AgDj7JD;EACE,iBAAA;EACA,kBAAA;EhDm7JD;AiDr+JD;EAEE,qBAAA;EACA,iBAAA;EjDs+JD;AiD99JD;EACE,oBAAA;EACA,gBAAA;EACA,oBAAA;EAEA,qBAAA;EACA,2BAAA;EACA,2BAAA;EjD+9JD;AiD59JC;ErB3BA,8BAAA;EACC,6BAAA;E5B0/JF;AiD79JC;EACE,kBAAA;ErBvBF,iCAAA;EACC,gCAAA;E5Bu/JF;AiDt9JD;EACE,gBAAA;EjDw9JD;AiDz9JD;EAII,gBAAA;EjDw9JH;AiDp9JC;;EAEE,uBAAA;EACA,gBAAA;EACA,2BAAA;EjDs9JH;AiDh9JC;;;EAGE,2BAAA;EACA,gBAAA;EACA,qBAAA;EjDk9JH;AiDv9JC;;;EASI,gBAAA;EjDm9JL;AiD59JC;;;EAYI,gBAAA;EjDq9JL;AiDh9JC;;;EAGE,YAAA;EACA,gBAAA;EACA,2BAAA;EACA,uBAAA;EjDk9JH;AiDx9JC;;;;;;;;;EAYI,gBAAA;EjDu9JL;AiDn+JC;;;EAeI,gBAAA;EjDy9JL;AkDrjKC;EACE,gBAAA;EACA,2BAAA;ElDujKH;AkDrjKG;EACE,gBAAA;ElDujKL;AkDxjKG;EAII,gBAAA;ElDujKP;AkDpjKK;;EAEE,gBAAA;EACA,2BAAA;ElDsjKP;AkDpjKK;;;EAGE,aAAA;EACA,2BAAA;EACA,uBAAA;ElDsjKP;AkD3kKC;EACE,gBAAA;EACA,2BAAA;ElD6kKH;AkD3kKG;EACE,gBAAA;ElD6kKL;AkD9kKG;EAII,gBAAA;ElD6kKP;AkD1kKK;;EAEE,gBAAA;EACA,2BAAA;ElD4kKP;AkD1kKK;;;EAGE,aAAA;EACA,2BAAA;EACA,uBAAA;ElD4kKP;AkDjmKC;EACE,gBAAA;EACA,2BAAA;ElDmmKH;AkDjmKG;EACE,gBAAA;ElDmmKL;AkDpmKG;EAII,gBAAA;ElDmmKP;AkDhmKK;;EAEE,gBAAA;EACA,2BAAA;ElDkmKP;AkDhmKK;;;EAGE,aAAA;EACA,2BAAA;EACA,uBAAA;ElDkmKP;AkDvnKC;EACE,gBAAA;EACA,2BAAA;ElDynKH;AkDvnKG;EACE,gBAAA;ElDynKL;AkD1nKG;EAII,gBAAA;ElDynKP;AkDtnKK;;EAEE,gBAAA;EACA,2BAAA;ElDwnKP;AkDtnKK;;;EAGE,aAAA;EACA,2BAAA;EACA,uBAAA;ElDwnKP;AiD5hKD;EACE,eAAA;EACA,oBAAA;EjD8hKD;AiD5hKD;EACE,kBAAA;EACA,kBAAA;EjD8hKD;AmDlpKD;EACE,qBAAA;EACA,2BAAA;EACA,+BAAA;EACA,oBAAA;E9C0DA,mDAAA;EACQ,2CAAA;EL2lKT;AmDjpKD;EACE,eAAA;EnDmpKD;AmD9oKD;EACE,oBAAA;EACA,sCAAA;EvBpBA,8BAAA;EACC,6BAAA;E5BqqKF;AmDppKD;EAMI,gBAAA;EnDipKH;AmD5oKD;EACE,eAAA;EACA,kBAAA;EACA,iBAAA;EACA,gBAAA;EnD8oKD;AmDlpKD;;;;;EAWI,gBAAA;EnD8oKH;AmDzoKD;EACE,oBAAA;EACA,2BAAA;EACA,+BAAA;EvBxCA,iCAAA;EACC,gCAAA;E5BorKF;AmDnoKD;;EAGI,kBAAA;EnDooKH;AmDvoKD;;EAMM,qBAAA;EACA,kBAAA;EnDqoKL;AmDjoKG;;EAEI,eAAA;EvBvEN,8BAAA;EACC,6BAAA;E5B2sKF;AmDhoKG;;EAEI,kBAAA;EvBtEN,iCAAA;EACC,gCAAA;E5BysKF;AmD7nKD;EAEI,qBAAA;EnD8nKH;AmD3nKD;EACE,qBAAA;EnD6nKD;AmDrnKD;;;EAII,kBAAA;EnDsnKH;AmD1nKD;;;EAOM,oBAAA;EACA,qBAAA;EnDwnKL;AmDhoKD;;EvBnGE,8BAAA;EACC,6BAAA;E5BuuKF;AmDroKD;;;;EAmBQ,6BAAA;EACA,8BAAA;EnDwnKP;AmD5oKD;;;;;;;;EAwBU,6BAAA;EnD8nKT;AmDtpKD;;;;;;;;EA4BU,8BAAA;EnDooKT;AmDhqKD;;EvB3FE,iCAAA;EACC,gCAAA;E5B+vKF;AmDrqKD;;;;EAyCQ,gCAAA;EACA,iCAAA;EnDkoKP;AmD5qKD;;;;;;;;EA8CU,gCAAA;EnDwoKT;AmDtrKD;;;;;;;;EAkDU,iCAAA;EnD8oKT;AmDhsKD;;;;EA2DI,+BAAA;EnD2oKH;AmDtsKD;;EA+DI,eAAA;EnD2oKH;AmD1sKD;;EAmEI,WAAA;EnD2oKH;AmD9sKD;;;;;;;;;;;;EA0EU,gBAAA;EnDkpKT;AmD5tKD;;;;;;;;;;;;EA8EU,iBAAA;EnD4pKT;AmD1uKD;;;;;;;;EAuFU,kBAAA;EnD6pKT;AmDpvKD;;;;;;;;EAgGU,kBAAA;EnD8pKT;AmD9vKD;EAsGI,WAAA;EACA,kBAAA;EnD2pKH;AmDjpKD;EACE,qBAAA;EnDmpKD;AmDppKD;EAKI,kBAAA;EACA,oBAAA;EnDkpKH;AmDxpKD;EASM,iBAAA;EnDkpKL;AmD3pKD;EAcI,kBAAA;EnDgpKH;AmD9pKD;;EAkBM,+BAAA;EnDgpKL;AmDlqKD;EAuBI,eAAA;EnD8oKH;AmDrqKD;EAyBM,kCAAA;EnD+oKL;AmDxoKD;ECpPE,uBAAA;EpD+3KD;AoD73KC;EACE,gBAAA;EACA,2BAAA;EACA,uBAAA;EpD+3KH;AoDl4KC;EAMI,2BAAA;EpD+3KL;AoDr4KC;EASI,gBAAA;EACA,2BAAA;EpD+3KL;AoD53KC;EAEI,8BAAA;EpD63KL;AmDvpKD;ECvPE,uBAAA;EpDi5KD;AoD/4KC;EACE,gBAAA;EACA,2BAAA;EACA,uBAAA;EpDi5KH;AoDp5KC;EAMI,2BAAA;EpDi5KL;AoDv5KC;EASI,gBAAA;EACA,2BAAA;EpDi5KL;AoD94KC;EAEI,8BAAA;EpD+4KL;AmDtqKD;EC1PE,uBAAA;EpDm6KD;AoDj6KC;EACE,gBAAA;EACA,2BAAA;EACA,uBAAA;EpDm6KH;AoDt6KC;EAMI,2BAAA;EpDm6KL;AoDz6KC;EASI,gBAAA;EACA,2BAAA;EpDm6KL;AoDh6KC;EAEI,8BAAA;EpDi6KL;AmDrrKD;EC7PE,uBAAA;EpDq7KD;AoDn7KC;EACE,gBAAA;EACA,2BAAA;EACA,uBAAA;EpDq7KH;AoDx7KC;EAMI,2BAAA;EpDq7KL;AoD37KC;EASI,gBAAA;EACA,2BAAA;EpDq7KL;AoDl7KC;EAEI,8BAAA;EpDm7KL;AmDpsKD;EChQE,uBAAA;EpDu8KD;AoDr8KC;EACE,gBAAA;EACA,2BAAA;EACA,uBAAA;EpDu8KH;AoD18KC;EAMI,2BAAA;EpDu8KL;AoD78KC;EASI,gBAAA;EACA,2BAAA;EpDu8KL;AoDp8KC;EAEI,8BAAA;EpDq8KL;AmDntKD;ECnQE,uBAAA;EpDy9KD;AoDv9KC;EACE,gBAAA;EACA,2BAAA;EACA,uBAAA;EpDy9KH;AoD59KC;EAMI,2BAAA;EpDy9KL;AoD/9KC;EASI,gBAAA;EACA,2BAAA;EpDy9KL;AoDt9KC;EAEI,8BAAA;EpDu9KL;AqDv+KD;EACE,oBAAA;EACA,gBAAA;EACA,WAAA;EACA,YAAA;EACA,kBAAA;ErDy+KD;AqD9+KD;;;;;EAYI,oBAAA;EACA,QAAA;EACA,SAAA;EACA,WAAA;EACA,cAAA;EACA,aAAA;EACA,WAAA;ErDy+KH;AqDp+KD;EACE,wBAAA;ErDs+KD;AqDl+KD;EACE,qBAAA;ErDo+KD;AsD//KD;EACE,kBAAA;EACA,eAAA;EACA,qBAAA;EACA,2BAAA;EACA,2BAAA;EACA,oBAAA;EjDwDA,yDAAA;EACQ,iDAAA;EL08KT;AsDzgLD;EASI,oBAAA;EACA,mCAAA;EtDmgLH;AsD9/KD;EACE,eAAA;EACA,oBAAA;EtDggLD;AsD9/KD;EACE,cAAA;EACA,oBAAA;EtDggLD;AuDthLD;EACE,cAAA;EACA,iBAAA;EACA,mBAAA;EACA,gBAAA;EACA,gBAAA;EACA,8BAAA;EjCRA,cAAA;EAGA,2BAAA;EtB+hLD;AuDvhLC;;EAEE,gBAAA;EACA,uBAAA;EACA,iBAAA;EjCfF,cAAA;EAGA,2BAAA;EtBuiLD;AuDnhLC;EACE,YAAA;EACA,iBAAA;EACA,yBAAA;EACA,WAAA;EACA,0BAAA;EvDqhLH;AwD1iLD;EACE,kBAAA;ExD4iLD;AwDxiLD;EACE,eAAA;EACA,kBAAA;EACA,iBAAA;EACA,QAAA;EACA,UAAA;EACA,WAAA;EACA,SAAA;EACA,eAAA;EACA,mCAAA;EAIA,YAAA;ExDuiLD;AwDpiLC;EnD+GA,uCAAA;EACI,mCAAA;EACC,kCAAA;EACG,+BAAA;EAkER,qDAAA;EAEK,2CAAA;EACG,qCAAA;ELu3KT;AwD1iLC;EnD2GA,oCAAA;EACI,gCAAA;EACC,+BAAA;EACG,4BAAA;ELk8KT;AwD9iLD;EACE,oBAAA;EACA,kBAAA;ExDgjLD;AwD5iLD;EACE,oBAAA;EACA,aAAA;EACA,cAAA;ExD8iLD;AwD1iLD;EACE,oBAAA;EACA,2BAAA;EACA,2BAAA;EACA,sCAAA;EACA,oBAAA;EnDaA,kDAAA;EACQ,0CAAA;EmDZR,sCAAA;UAAA,8BAAA;EAEA,YAAA;ExD4iLD;AwDxiLD;EACE,iBAAA;EACA,QAAA;EACA,UAAA;EACA,WAAA;EACA,SAAA;EACA,eAAA;EACA,2BAAA;ExD0iLD;AwDxiLC;ElCrEA,YAAA;EAGA,0BAAA;EtB8mLD;AwD3iLC;ElCtEA,cAAA;EAGA,2BAAA;EtBknLD;AwD1iLD;EACE,eAAA;EACA,kCAAA;EACA,2BAAA;ExD4iLD;AwDziLD;EACE,kBAAA;ExD2iLD;AwDviLD;EACE,WAAA;EACA,yBAAA;ExDyiLD;AwDpiLD;EACE,oBAAA;EACA,eAAA;ExDsiLD;AwDliLD;EACE,eAAA;EACA,mBAAA;EACA,+BAAA;ExDoiLD;AwDviLD;EAQI,kBAAA;EACA,kBAAA;ExDkiLH;AwD3iLD;EAaI,mBAAA;ExDiiLH;AwD9iLD;EAiBI,gBAAA;ExDgiLH;AwD3hLD;EACE,oBAAA;EACA,cAAA;EACA,aAAA;EACA,cAAA;EACA,kBAAA;ExD6hLD;AwD3gLD;EAZE;IACE,cAAA;IACA,mBAAA;IxD0hLD;EwDxhLD;InDvEA,mDAAA;IACQ,2CAAA;ILkmLP;EwDvhLD;IAAY,cAAA;IxD0hLX;EACF;AwDrhLD;EAFE;IAAY,cAAA;IxD2hLX;EACF;AyD1qLD;EACE,oBAAA;EACA,eAAA;EACA,gBAAA;EAEA,6DAAA;EACA,iBAAA;EACA,qBAAA;EACA,kBAAA;EnCXA,YAAA;EAGA,0BAAA;EtBqrLD;AyD1qLC;EnCdA,cAAA;EAGA,2BAAA;EtByrLD;AyD7qLC;EAAW,kBAAA;EAAmB,gBAAA;EzDirL/B;AyDhrLC;EAAW,kBAAA;EAAmB,gBAAA;EzDorL/B;AyDnrLC;EAAW,iBAAA;EAAmB,gBAAA;EzDurL/B;AyDtrLC;EAAW,mBAAA;EAAmB,gBAAA;EzD0rL/B;AyDtrLD;EACE,kBAAA;EACA,kBAAA;EACA,gBAAA;EACA,oBAAA;EACA,uBAAA;EACA,2BAAA;EACA,oBAAA;EzDwrLD;AyDprLD;EACE,oBAAA;EACA,UAAA;EACA,WAAA;EACA,2BAAA;EACA,qBAAA;EzDsrLD;AyDlrLC;EACE,WAAA;EACA,WAAA;EACA,mBAAA;EACA,yBAAA;EACA,2BAAA;EzDorLH;AyDlrLC;EACE,WAAA;EACA,YAAA;EACA,qBAAA;EACA,yBAAA;EACA,2BAAA;EzDorLH;AyDlrLC;EACE,WAAA;EACA,WAAA;EACA,qBAAA;EACA,yBAAA;EACA,2BAAA;EzDorLH;AyDlrLC;EACE,UAAA;EACA,SAAA;EACA,kBAAA;EACA,6BAAA;EACA,6BAAA;EzDorLH;AyDlrLC;EACE,UAAA;EACA,UAAA;EACA,kBAAA;EACA,6BAAA;EACA,4BAAA;EzDorLH;AyDlrLC;EACE,QAAA;EACA,WAAA;EACA,mBAAA;EACA,yBAAA;EACA,8BAAA;EzDorLH;AyDlrLC;EACE,QAAA;EACA,YAAA;EACA,kBAAA;EACA,yBAAA;EACA,8BAAA;EzDorLH;AyDlrLC;EACE,QAAA;EACA,WAAA;EACA,kBAAA;EACA,yBAAA;EACA,8BAAA;EzDorLH;A0DlxLD;EACE,oBAAA;EACA,QAAA;EACA,SAAA;EACA,eAAA;EACA,eAAA;EACA,kBAAA;EACA,cAAA;EAEA,6DAAA;EACA,iBAAA;EACA,qBAAA;EACA,yBAAA;EACA,kBAAA;EACA,2BAAA;EACA,sCAAA;UAAA,8BAAA;EACA,2BAAA;EACA,sCAAA;EACA,oBAAA;ErD6CA,mDAAA;EACQ,2CAAA;EqD1CR,qBAAA;E1DkxLD;A0D/wLC;EAAY,mBAAA;E1DkxLb;A0DjxLC;EAAY,mBAAA;E1DoxLb;A0DnxLC;EAAY,kBAAA;E1DsxLb;A0DrxLC;EAAY,oBAAA;E1DwxLb;A0DrxLD;EACE,WAAA;EACA,mBAAA;EACA,iBAAA;EACA,2BAAA;EACA,kCAAA;EACA,4BAAA;E1DuxLD;A0DpxLD;EACE,mBAAA;E1DsxLD;A0D9wLC;;EAEE,oBAAA;EACA,gBAAA;EACA,UAAA;EACA,WAAA;EACA,2BAAA;EACA,qBAAA;E1DgxLH;A0D7wLD;EACE,oBAAA;E1D+wLD;A0D7wLD;EACE,oBAAA;EACA,aAAA;E1D+wLD;A0D3wLC;EACE,WAAA;EACA,oBAAA;EACA,wBAAA;EACA,2BAAA;EACA,uCAAA;EACA,eAAA;E1D6wLH;A0D5wLG;EACE,cAAA;EACA,aAAA;EACA,oBAAA;EACA,wBAAA;EACA,2BAAA;E1D8wLL;A0D3wLC;EACE,UAAA;EACA,aAAA;EACA,mBAAA;EACA,sBAAA;EACA,6BAAA;EACA,yCAAA;E1D6wLH;A0D5wLG;EACE,cAAA;EACA,WAAA;EACA,eAAA;EACA,sBAAA;EACA,6BAAA;E1D8wLL;A0D3wLC;EACE,WAAA;EACA,oBAAA;EACA,qBAAA;EACA,8BAAA;EACA,0CAAA;EACA,YAAA;E1D6wLH;A0D5wLG;EACE,cAAA;EACA,UAAA;EACA,oBAAA;EACA,qBAAA;EACA,8BAAA;E1D8wLL;A0D1wLC;EACE,UAAA;EACA,cAAA;EACA,mBAAA;EACA,uBAAA;EACA,4BAAA;EACA,wCAAA;E1D4wLH;A0D3wLG;EACE,cAAA;EACA,YAAA;EACA,uBAAA;EACA,4BAAA;EACA,eAAA;E1D6wLL;A2D14LD;EACE,oBAAA;E3D44LD;A2Dz4LD;EACE,oBAAA;EACA,kBAAA;EACA,aAAA;E3D24LD;A2D94LD;EAMI,eAAA;EACA,oBAAA;EtD6KF,2CAAA;EACK,sCAAA;EACG,mCAAA;EL+tLT;A2Dr5LD;;EAcM,gBAAA;E3D24LL;A2Dj3LC;EAAA;ItDiKA,wDAAA;IAEK,8CAAA;IACG,wCAAA;IA7JR,qCAAA;IAEQ,6BAAA;IA+GR,2BAAA;IAEQ,mBAAA;ILowLP;E2D/4LG;;ItDmHJ,4CAAA;IACQ,oCAAA;IsDjHF,SAAA;I3Dk5LL;E2Dh5LG;;ItD8GJ,6CAAA;IACQ,qCAAA;IsD5GF,SAAA;I3Dm5LL;E2Dj5LG;;;ItDyGJ,yCAAA;IACQ,iCAAA;IsDtGF,SAAA;I3Do5LL;EACF;A2D17LD;;;EA6CI,gBAAA;E3Dk5LH;A2D/7LD;EAiDI,SAAA;E3Di5LH;A2Dl8LD;;EAsDI,oBAAA;EACA,QAAA;EACA,aAAA;E3Dg5LH;A2Dx8LD;EA4DI,YAAA;E3D+4LH;A2D38LD;EA+DI,aAAA;E3D+4LH;A2D98LD;;EAmEI,SAAA;E3D+4LH;A2Dl9LD;EAuEI,aAAA;E3D84LH;A2Dr9LD;EA0EI,YAAA;E3D84LH;A2Dt4LD;EACE,oBAAA;EACA,QAAA;EACA,SAAA;EACA,WAAA;EACA,YAAA;ErC9FA,cAAA;EAGA,2BAAA;EqC6FA,iBAAA;EACA,gBAAA;EACA,oBAAA;EACA,2CAAA;E3Dy4LD;A2Dp4LC;EblGE,oGAAA;EACA,+FAAA;EACA,sHAAA;EAAA,gGAAA;EACA,6BAAA;EACA,wHAAA;E9Cy+LH;A2Dx4LC;EACE,YAAA;EACA,UAAA;EbvGA,oGAAA;EACA,+FAAA;EACA,sHAAA;EAAA,gGAAA;EACA,6BAAA;EACA,wHAAA;E9Ck/LH;A2D14LC;;EAEE,YAAA;EACA,gBAAA;EACA,uBAAA;ErCtHF,cAAA;EAGA,2BAAA;EtBigMD;A2D36LD;;;;EAsCI,oBAAA;EACA,UAAA;EACA,YAAA;EACA,uBAAA;E3D24LH;A2Dp7LD;;EA6CI,WAAA;EACA,oBAAA;E3D24LH;A2Dz7LD;;EAkDI,YAAA;EACA,qBAAA;E3D24LH;A2D97LD;;EAuDI,aAAA;EACA,cAAA;EACA,mBAAA;EACA,gBAAA;EACA,oBAAA;E3D24LH;A2Dt4LG;EACE,kBAAA;E3Dw4LL;A2Dp4LG;EACE,kBAAA;E3Ds4LL;A2D53LD;EACE,oBAAA;EACA,cAAA;EACA,WAAA;EACA,aAAA;EACA,YAAA;EACA,mBAAA;EACA,iBAAA;EACA,kBAAA;EACA,oBAAA;E3D83LD;A2Dv4LD;EAYI,uBAAA;EACA,aAAA;EACA,cAAA;EACA,aAAA;EACA,qBAAA;EACA,2BAAA;EACA,qBAAA;EACA,iBAAA;EAWA,2BAAA;EACA,oCAAA;E3Do3LH;A2Dn5LD;EAkCI,WAAA;EACA,aAAA;EACA,cAAA;EACA,2BAAA;E3Do3LH;A2D72LD;EACE,oBAAA;EACA,WAAA;EACA,YAAA;EACA,cAAA;EACA,aAAA;EACA,mBAAA;EACA,sBAAA;EACA,gBAAA;EACA,oBAAA;EACA,2CAAA;E3D+2LD;A2D92LC;EACE,mBAAA;E3Dg3LH;A2Dv0LD;EAhCE;;;;IAKI,aAAA;IACA,cAAA;IACA,mBAAA;IACA,iBAAA;I3Dy2LH;E2Dj3LD;;IAYI,oBAAA;I3Dy2LH;E2Dr3LD;;IAgBI,qBAAA;I3Dy2LH;E2Dp2LD;IACE,WAAA;IACA,YAAA;IACA,sBAAA;I3Ds2LD;E2Dl2LD;IACE,cAAA;I3Do2LD;EACF;A4DlmMC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAEE,cAAA;EACA,gBAAA;E5DgoMH;A4D9nMC;;;;;;;;;;;;;;;EACE,aAAA;E5D8oMH;AiCtpMD;E4BRE,gBAAA;EACA,mBAAA;EACA,oBAAA;E7DiqMD;AiCxpMD;EACE,yBAAA;EjC0pMD;AiCxpMD;EACE,wBAAA;EjC0pMD;AiClpMD;EACE,0BAAA;EjCopMD;AiClpMD;EACE,2BAAA;EjCopMD;AiClpMD;EACE,oBAAA;EjCopMD;AiClpMD;E6BzBE,aAAA;EACA,oBAAA;EACA,mBAAA;EACA,+BAAA;EACA,WAAA;E9D8qMD;AiChpMD;EACE,0BAAA;EjCkpMD;AiC3oMD;EACE,iBAAA;EjC6oMD;A+D9qMD;EACE,qBAAA;E/DgrMD;A+D1qMD;;;;ECdE,0BAAA;EhE8rMD;A+DzqMD;;;;;;;;;;;;EAYE,0BAAA;E/D2qMD;A+DpqMD;EAAA;IChDE,2BAAA;IhEwtMC;EgEvtMD;IAAU,gBAAA;IhE0tMT;EgEztMD;IAAU,+BAAA;IhE4tMT;EgE3tMD;;IACU,gCAAA;IhE8tMT;EACF;A+D9qMD;EAAA;IAFI,2BAAA;I/DorMD;EACF;A+D9qMD;EAAA;IAFI,4BAAA;I/DorMD;EACF;A+D9qMD;EAAA;IAFI,kCAAA;I/DorMD;EACF;A+D7qMD;EAAA;ICrEE,2BAAA;IhEsvMC;EgErvMD;IAAU,gBAAA;IhEwvMT;EgEvvMD;IAAU,+BAAA;IhE0vMT;EgEzvMD;;IACU,gCAAA;IhE4vMT;EACF;A+DvrMD;EAAA;IAFI,2BAAA;I/D6rMD;EACF;A+DvrMD;EAAA;IAFI,4BAAA;I/D6rMD;EACF;A+DvrMD;EAAA;IAFI,kCAAA;I/D6rMD;EACF;A+DtrMD;EAAA;IC1FE,2BAAA;IhEoxMC;EgEnxMD;IAAU,gBAAA;IhEsxMT;EgErxMD;IAAU,+BAAA;IhEwxMT;EgEvxMD;;IACU,gCAAA;IhE0xMT;EACF;A+DhsMD;EAAA;IAFI,2BAAA;I/DssMD;EACF;A+DhsMD;EAAA;IAFI,4BAAA;I/DssMD;EACF;A+DhsMD;EAAA;IAFI,kCAAA;I/DssMD;EACF;A+D/rMD;EAAA;IC/GE,2BAAA;IhEkzMC;EgEjzMD;IAAU,gBAAA;IhEozMT;EgEnzMD;IAAU,+BAAA;IhEszMT;EgErzMD;;IACU,gCAAA;IhEwzMT;EACF;A+DzsMD;EAAA;IAFI,2BAAA;I/D+sMD;EACF;A+DzsMD;EAAA;IAFI,4BAAA;I/D+sMD;EACF;A+DzsMD;EAAA;IAFI,kCAAA;I/D+sMD;EACF;A+DxsMD;EAAA;IC5HE,0BAAA;IhEw0MC;EACF;A+DxsMD;EAAA;ICjIE,0BAAA;IhE60MC;EACF;A+DxsMD;EAAA;ICtIE,0BAAA;IhEk1MC;EACF;A+DxsMD;EAAA;IC3IE,0BAAA;IhEu1MC;EACF;A+DrsMD;ECnJE,0BAAA;EhE21MD;A+DlsMD;EAAA;ICjKE,2BAAA;IhEu2MC;EgEt2MD;IAAU,gBAAA;IhEy2MT;EgEx2MD;IAAU,+BAAA;IhE22MT;EgE12MD;;IACU,gCAAA;IhE62MT;EACF;A+DhtMD;EACE,0BAAA;E/DktMD;A+D7sMD;EAAA;IAFI,2BAAA;I/DmtMD;EACF;A+DjtMD;EACE,0BAAA;E/DmtMD;A+D9sMD;EAAA;IAFI,4BAAA;I/DotMD;EACF;A+DltMD;EACE,0BAAA;E/DotMD;A+D/sMD;EAAA;IAFI,kCAAA;I/DqtMD;EACF;A+D9sMD;EAAA;ICpLE,0BAAA;IhEs4MC;EACF","file":"bootstrap.css","sourcesContent":["/*! normalize.css v3.0.2 | MIT License | git.io/normalize */\nhtml {\n font-family: sans-serif;\n -ms-text-size-adjust: 100%;\n -webkit-text-size-adjust: 100%;\n}\nbody {\n margin: 0;\n}\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nmain,\nmenu,\nnav,\nsection,\nsummary {\n display: block;\n}\naudio,\ncanvas,\nprogress,\nvideo {\n display: inline-block;\n vertical-align: baseline;\n}\naudio:not([controls]) {\n display: none;\n height: 0;\n}\n[hidden],\ntemplate {\n display: none;\n}\na {\n background-color: transparent;\n}\na:active,\na:hover {\n outline: 0;\n}\nabbr[title] {\n border-bottom: 1px dotted;\n}\nb,\nstrong {\n font-weight: bold;\n}\ndfn {\n font-style: italic;\n}\nh1 {\n font-size: 2em;\n margin: 0.67em 0;\n}\nmark {\n background: #ff0;\n color: #000;\n}\nsmall {\n font-size: 80%;\n}\nsub,\nsup {\n font-size: 75%;\n line-height: 0;\n position: relative;\n vertical-align: baseline;\n}\nsup {\n top: -0.5em;\n}\nsub {\n bottom: -0.25em;\n}\nimg {\n border: 0;\n}\nsvg:not(:root) {\n overflow: hidden;\n}\nfigure {\n margin: 1em 40px;\n}\nhr {\n -moz-box-sizing: content-box;\n box-sizing: content-box;\n height: 0;\n}\npre {\n overflow: auto;\n}\ncode,\nkbd,\npre,\nsamp {\n font-family: monospace, monospace;\n font-size: 1em;\n}\nbutton,\ninput,\noptgroup,\nselect,\ntextarea {\n color: inherit;\n font: inherit;\n margin: 0;\n}\nbutton {\n overflow: visible;\n}\nbutton,\nselect {\n text-transform: none;\n}\nbutton,\nhtml input[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n -webkit-appearance: button;\n cursor: pointer;\n}\nbutton[disabled],\nhtml input[disabled] {\n cursor: default;\n}\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n border: 0;\n padding: 0;\n}\ninput {\n line-height: normal;\n}\ninput[type=\"checkbox\"],\ninput[type=\"radio\"] {\n box-sizing: border-box;\n padding: 0;\n}\ninput[type=\"number\"]::-webkit-inner-spin-button,\ninput[type=\"number\"]::-webkit-outer-spin-button {\n height: auto;\n}\ninput[type=\"search\"] {\n -webkit-appearance: textfield;\n -moz-box-sizing: content-box;\n -webkit-box-sizing: content-box;\n box-sizing: content-box;\n}\ninput[type=\"search\"]::-webkit-search-cancel-button,\ninput[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none;\n}\nfieldset {\n border: 1px solid #c0c0c0;\n margin: 0 2px;\n padding: 0.35em 0.625em 0.75em;\n}\nlegend {\n border: 0;\n padding: 0;\n}\ntextarea {\n overflow: auto;\n}\noptgroup {\n font-weight: bold;\n}\ntable {\n border-collapse: collapse;\n border-spacing: 0;\n}\ntd,\nth {\n padding: 0;\n}\n/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */\n@media print {\n *,\n *:before,\n *:after {\n background: transparent !important;\n color: #000 !important;\n box-shadow: none !important;\n text-shadow: none !important;\n }\n a,\n a:visited {\n text-decoration: underline;\n }\n a[href]:after {\n content: \" (\" attr(href) \")\";\n }\n abbr[title]:after {\n content: \" (\" attr(title) \")\";\n }\n a[href^=\"#\"]:after,\n a[href^=\"javascript:\"]:after {\n content: \"\";\n }\n pre,\n blockquote {\n border: 1px solid #999;\n page-break-inside: avoid;\n }\n thead {\n display: table-header-group;\n }\n tr,\n img {\n page-break-inside: avoid;\n }\n img {\n max-width: 100% !important;\n }\n p,\n h2,\n h3 {\n orphans: 3;\n widows: 3;\n }\n h2,\n h3 {\n page-break-after: avoid;\n }\n select {\n background: #fff !important;\n }\n .navbar {\n display: none;\n }\n .btn > .caret,\n .dropup > .btn > .caret {\n border-top-color: #000 !important;\n }\n .label {\n border: 1px solid #000;\n }\n .table {\n border-collapse: collapse !important;\n }\n .table td,\n .table th {\n background-color: #fff !important;\n }\n .table-bordered th,\n .table-bordered td {\n border: 1px solid #ddd !important;\n }\n}\n@font-face {\n font-family: 'Glyphicons Halflings';\n src: url('../fonts/glyphicons-halflings-regular.eot');\n src: url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('../fonts/glyphicons-halflings-regular.woff2') format('woff2'), url('../fonts/glyphicons-halflings-regular.woff') format('woff'), url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg');\n}\n.glyphicon {\n position: relative;\n top: 1px;\n display: inline-block;\n font-family: 'Glyphicons Halflings';\n font-style: normal;\n font-weight: normal;\n line-height: 1;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n.glyphicon-asterisk:before {\n content: \"\\2a\";\n}\n.glyphicon-plus:before {\n content: \"\\2b\";\n}\n.glyphicon-euro:before,\n.glyphicon-eur:before {\n content: \"\\20ac\";\n}\n.glyphicon-minus:before {\n content: \"\\2212\";\n}\n.glyphicon-cloud:before {\n content: \"\\2601\";\n}\n.glyphicon-envelope:before {\n content: \"\\2709\";\n}\n.glyphicon-pencil:before {\n content: \"\\270f\";\n}\n.glyphicon-glass:before {\n content: \"\\e001\";\n}\n.glyphicon-music:before {\n content: \"\\e002\";\n}\n.glyphicon-search:before {\n content: \"\\e003\";\n}\n.glyphicon-heart:before {\n content: \"\\e005\";\n}\n.glyphicon-star:before {\n content: \"\\e006\";\n}\n.glyphicon-star-empty:before {\n content: \"\\e007\";\n}\n.glyphicon-user:before {\n content: \"\\e008\";\n}\n.glyphicon-film:before {\n content: \"\\e009\";\n}\n.glyphicon-th-large:before {\n content: \"\\e010\";\n}\n.glyphicon-th:before {\n content: \"\\e011\";\n}\n.glyphicon-th-list:before {\n content: \"\\e012\";\n}\n.glyphicon-ok:before {\n content: \"\\e013\";\n}\n.glyphicon-remove:before {\n content: \"\\e014\";\n}\n.glyphicon-zoom-in:before {\n content: \"\\e015\";\n}\n.glyphicon-zoom-out:before {\n content: \"\\e016\";\n}\n.glyphicon-off:before {\n content: \"\\e017\";\n}\n.glyphicon-signal:before {\n content: \"\\e018\";\n}\n.glyphicon-cog:before {\n content: \"\\e019\";\n}\n.glyphicon-trash:before {\n content: \"\\e020\";\n}\n.glyphicon-home:before {\n content: \"\\e021\";\n}\n.glyphicon-file:before {\n content: \"\\e022\";\n}\n.glyphicon-time:before {\n content: \"\\e023\";\n}\n.glyphicon-road:before {\n content: \"\\e024\";\n}\n.glyphicon-download-alt:before {\n content: \"\\e025\";\n}\n.glyphicon-download:before {\n content: \"\\e026\";\n}\n.glyphicon-upload:before {\n content: \"\\e027\";\n}\n.glyphicon-inbox:before {\n content: \"\\e028\";\n}\n.glyphicon-play-circle:before {\n content: \"\\e029\";\n}\n.glyphicon-repeat:before {\n content: \"\\e030\";\n}\n.glyphicon-refresh:before {\n content: \"\\e031\";\n}\n.glyphicon-list-alt:before {\n content: \"\\e032\";\n}\n.glyphicon-lock:before {\n content: \"\\e033\";\n}\n.glyphicon-flag:before {\n content: \"\\e034\";\n}\n.glyphicon-headphones:before {\n content: \"\\e035\";\n}\n.glyphicon-volume-off:before {\n content: \"\\e036\";\n}\n.glyphicon-volume-down:before {\n content: \"\\e037\";\n}\n.glyphicon-volume-up:before {\n content: \"\\e038\";\n}\n.glyphicon-qrcode:before {\n content: \"\\e039\";\n}\n.glyphicon-barcode:before {\n content: \"\\e040\";\n}\n.glyphicon-tag:before {\n content: \"\\e041\";\n}\n.glyphicon-tags:before {\n content: \"\\e042\";\n}\n.glyphicon-book:before {\n content: \"\\e043\";\n}\n.glyphicon-bookmark:before {\n content: \"\\e044\";\n}\n.glyphicon-print:before {\n content: \"\\e045\";\n}\n.glyphicon-camera:before {\n content: \"\\e046\";\n}\n.glyphicon-font:before {\n content: \"\\e047\";\n}\n.glyphicon-bold:before {\n content: \"\\e048\";\n}\n.glyphicon-italic:before {\n content: \"\\e049\";\n}\n.glyphicon-text-height:before {\n content: \"\\e050\";\n}\n.glyphicon-text-width:before {\n content: \"\\e051\";\n}\n.glyphicon-align-left:before {\n content: \"\\e052\";\n}\n.glyphicon-align-center:before {\n content: \"\\e053\";\n}\n.glyphicon-align-right:before {\n content: \"\\e054\";\n}\n.glyphicon-align-justify:before {\n content: \"\\e055\";\n}\n.glyphicon-list:before {\n content: \"\\e056\";\n}\n.glyphicon-indent-left:before {\n content: \"\\e057\";\n}\n.glyphicon-indent-right:before {\n content: \"\\e058\";\n}\n.glyphicon-facetime-video:before {\n content: \"\\e059\";\n}\n.glyphicon-picture:before {\n content: \"\\e060\";\n}\n.glyphicon-map-marker:before {\n content: \"\\e062\";\n}\n.glyphicon-adjust:before {\n content: \"\\e063\";\n}\n.glyphicon-tint:before {\n content: \"\\e064\";\n}\n.glyphicon-edit:before {\n content: \"\\e065\";\n}\n.glyphicon-share:before {\n content: \"\\e066\";\n}\n.glyphicon-check:before {\n content: \"\\e067\";\n}\n.glyphicon-move:before {\n content: \"\\e068\";\n}\n.glyphicon-step-backward:before {\n content: \"\\e069\";\n}\n.glyphicon-fast-backward:before {\n content: \"\\e070\";\n}\n.glyphicon-backward:before {\n content: \"\\e071\";\n}\n.glyphicon-play:before {\n content: \"\\e072\";\n}\n.glyphicon-pause:before {\n content: \"\\e073\";\n}\n.glyphicon-stop:before {\n content: \"\\e074\";\n}\n.glyphicon-forward:before {\n content: \"\\e075\";\n}\n.glyphicon-fast-forward:before {\n content: \"\\e076\";\n}\n.glyphicon-step-forward:before {\n content: \"\\e077\";\n}\n.glyphicon-eject:before {\n content: \"\\e078\";\n}\n.glyphicon-chevron-left:before {\n content: \"\\e079\";\n}\n.glyphicon-chevron-right:before {\n content: \"\\e080\";\n}\n.glyphicon-plus-sign:before {\n content: \"\\e081\";\n}\n.glyphicon-minus-sign:before {\n content: \"\\e082\";\n}\n.glyphicon-remove-sign:before {\n content: \"\\e083\";\n}\n.glyphicon-ok-sign:before {\n content: \"\\e084\";\n}\n.glyphicon-question-sign:before {\n content: \"\\e085\";\n}\n.glyphicon-info-sign:before {\n content: \"\\e086\";\n}\n.glyphicon-screenshot:before {\n content: \"\\e087\";\n}\n.glyphicon-remove-circle:before {\n content: \"\\e088\";\n}\n.glyphicon-ok-circle:before {\n content: \"\\e089\";\n}\n.glyphicon-ban-circle:before {\n content: \"\\e090\";\n}\n.glyphicon-arrow-left:before {\n content: \"\\e091\";\n}\n.glyphicon-arrow-right:before {\n content: \"\\e092\";\n}\n.glyphicon-arrow-up:before {\n content: \"\\e093\";\n}\n.glyphicon-arrow-down:before {\n content: \"\\e094\";\n}\n.glyphicon-share-alt:before {\n content: \"\\e095\";\n}\n.glyphicon-resize-full:before {\n content: \"\\e096\";\n}\n.glyphicon-resize-small:before {\n content: \"\\e097\";\n}\n.glyphicon-exclamation-sign:before {\n content: \"\\e101\";\n}\n.glyphicon-gift:before {\n content: \"\\e102\";\n}\n.glyphicon-leaf:before {\n content: \"\\e103\";\n}\n.glyphicon-fire:before {\n content: \"\\e104\";\n}\n.glyphicon-eye-open:before {\n content: \"\\e105\";\n}\n.glyphicon-eye-close:before {\n content: \"\\e106\";\n}\n.glyphicon-warning-sign:before {\n content: \"\\e107\";\n}\n.glyphicon-plane:before {\n content: \"\\e108\";\n}\n.glyphicon-calendar:before {\n content: \"\\e109\";\n}\n.glyphicon-random:before {\n content: \"\\e110\";\n}\n.glyphicon-comment:before {\n content: \"\\e111\";\n}\n.glyphicon-magnet:before {\n content: \"\\e112\";\n}\n.glyphicon-chevron-up:before {\n content: \"\\e113\";\n}\n.glyphicon-chevron-down:before {\n content: \"\\e114\";\n}\n.glyphicon-retweet:before {\n content: \"\\e115\";\n}\n.glyphicon-shopping-cart:before {\n content: \"\\e116\";\n}\n.glyphicon-folder-close:before {\n content: \"\\e117\";\n}\n.glyphicon-folder-open:before {\n content: \"\\e118\";\n}\n.glyphicon-resize-vertical:before {\n content: \"\\e119\";\n}\n.glyphicon-resize-horizontal:before {\n content: \"\\e120\";\n}\n.glyphicon-hdd:before {\n content: \"\\e121\";\n}\n.glyphicon-bullhorn:before {\n content: \"\\e122\";\n}\n.glyphicon-bell:before {\n content: \"\\e123\";\n}\n.glyphicon-certificate:before {\n content: \"\\e124\";\n}\n.glyphicon-thumbs-up:before {\n content: \"\\e125\";\n}\n.glyphicon-thumbs-down:before {\n content: \"\\e126\";\n}\n.glyphicon-hand-right:before {\n content: \"\\e127\";\n}\n.glyphicon-hand-left:before {\n content: \"\\e128\";\n}\n.glyphicon-hand-up:before {\n content: \"\\e129\";\n}\n.glyphicon-hand-down:before {\n content: \"\\e130\";\n}\n.glyphicon-circle-arrow-right:before {\n content: \"\\e131\";\n}\n.glyphicon-circle-arrow-left:before {\n content: \"\\e132\";\n}\n.glyphicon-circle-arrow-up:before {\n content: \"\\e133\";\n}\n.glyphicon-circle-arrow-down:before {\n content: \"\\e134\";\n}\n.glyphicon-globe:before {\n content: \"\\e135\";\n}\n.glyphicon-wrench:before {\n content: \"\\e136\";\n}\n.glyphicon-tasks:before {\n content: \"\\e137\";\n}\n.glyphicon-filter:before {\n content: \"\\e138\";\n}\n.glyphicon-briefcase:before {\n content: \"\\e139\";\n}\n.glyphicon-fullscreen:before {\n content: \"\\e140\";\n}\n.glyphicon-dashboard:before {\n content: \"\\e141\";\n}\n.glyphicon-paperclip:before {\n content: \"\\e142\";\n}\n.glyphicon-heart-empty:before {\n content: \"\\e143\";\n}\n.glyphicon-link:before {\n content: \"\\e144\";\n}\n.glyphicon-phone:before {\n content: \"\\e145\";\n}\n.glyphicon-pushpin:before {\n content: \"\\e146\";\n}\n.glyphicon-usd:before {\n content: \"\\e148\";\n}\n.glyphicon-gbp:before {\n content: \"\\e149\";\n}\n.glyphicon-sort:before {\n content: \"\\e150\";\n}\n.glyphicon-sort-by-alphabet:before {\n content: \"\\e151\";\n}\n.glyphicon-sort-by-alphabet-alt:before {\n content: \"\\e152\";\n}\n.glyphicon-sort-by-order:before {\n content: \"\\e153\";\n}\n.glyphicon-sort-by-order-alt:before {\n content: \"\\e154\";\n}\n.glyphicon-sort-by-attributes:before {\n content: \"\\e155\";\n}\n.glyphicon-sort-by-attributes-alt:before {\n content: \"\\e156\";\n}\n.glyphicon-unchecked:before {\n content: \"\\e157\";\n}\n.glyphicon-expand:before {\n content: \"\\e158\";\n}\n.glyphicon-collapse-down:before {\n content: \"\\e159\";\n}\n.glyphicon-collapse-up:before {\n content: \"\\e160\";\n}\n.glyphicon-log-in:before {\n content: \"\\e161\";\n}\n.glyphicon-flash:before {\n content: \"\\e162\";\n}\n.glyphicon-log-out:before {\n content: \"\\e163\";\n}\n.glyphicon-new-window:before {\n content: \"\\e164\";\n}\n.glyphicon-record:before {\n content: \"\\e165\";\n}\n.glyphicon-save:before {\n content: \"\\e166\";\n}\n.glyphicon-open:before {\n content: \"\\e167\";\n}\n.glyphicon-saved:before {\n content: \"\\e168\";\n}\n.glyphicon-import:before {\n content: \"\\e169\";\n}\n.glyphicon-export:before {\n content: \"\\e170\";\n}\n.glyphicon-send:before {\n content: \"\\e171\";\n}\n.glyphicon-floppy-disk:before {\n content: \"\\e172\";\n}\n.glyphicon-floppy-saved:before {\n content: \"\\e173\";\n}\n.glyphicon-floppy-remove:before {\n content: \"\\e174\";\n}\n.glyphicon-floppy-save:before {\n content: \"\\e175\";\n}\n.glyphicon-floppy-open:before {\n content: \"\\e176\";\n}\n.glyphicon-credit-card:before {\n content: \"\\e177\";\n}\n.glyphicon-transfer:before {\n content: \"\\e178\";\n}\n.glyphicon-cutlery:before {\n content: \"\\e179\";\n}\n.glyphicon-header:before {\n content: \"\\e180\";\n}\n.glyphicon-compressed:before {\n content: \"\\e181\";\n}\n.glyphicon-earphone:before {\n content: \"\\e182\";\n}\n.glyphicon-phone-alt:before {\n content: \"\\e183\";\n}\n.glyphicon-tower:before {\n content: \"\\e184\";\n}\n.glyphicon-stats:before {\n content: \"\\e185\";\n}\n.glyphicon-sd-video:before {\n content: \"\\e186\";\n}\n.glyphicon-hd-video:before {\n content: \"\\e187\";\n}\n.glyphicon-subtitles:before {\n content: \"\\e188\";\n}\n.glyphicon-sound-stereo:before {\n content: \"\\e189\";\n}\n.glyphicon-sound-dolby:before {\n content: \"\\e190\";\n}\n.glyphicon-sound-5-1:before {\n content: \"\\e191\";\n}\n.glyphicon-sound-6-1:before {\n content: \"\\e192\";\n}\n.glyphicon-sound-7-1:before {\n content: \"\\e193\";\n}\n.glyphicon-copyright-mark:before {\n content: \"\\e194\";\n}\n.glyphicon-registration-mark:before {\n content: \"\\e195\";\n}\n.glyphicon-cloud-download:before {\n content: \"\\e197\";\n}\n.glyphicon-cloud-upload:before {\n content: \"\\e198\";\n}\n.glyphicon-tree-conifer:before {\n content: \"\\e199\";\n}\n.glyphicon-tree-deciduous:before {\n content: \"\\e200\";\n}\n.glyphicon-cd:before {\n content: \"\\e201\";\n}\n.glyphicon-save-file:before {\n content: \"\\e202\";\n}\n.glyphicon-open-file:before {\n content: \"\\e203\";\n}\n.glyphicon-level-up:before {\n content: \"\\e204\";\n}\n.glyphicon-copy:before {\n content: \"\\e205\";\n}\n.glyphicon-paste:before {\n content: \"\\e206\";\n}\n.glyphicon-alert:before {\n content: \"\\e209\";\n}\n.glyphicon-equalizer:before {\n content: \"\\e210\";\n}\n.glyphicon-king:before {\n content: \"\\e211\";\n}\n.glyphicon-queen:before {\n content: \"\\e212\";\n}\n.glyphicon-pawn:before {\n content: \"\\e213\";\n}\n.glyphicon-bishop:before {\n content: \"\\e214\";\n}\n.glyphicon-knight:before {\n content: \"\\e215\";\n}\n.glyphicon-baby-formula:before {\n content: \"\\e216\";\n}\n.glyphicon-tent:before {\n content: \"\\26fa\";\n}\n.glyphicon-blackboard:before {\n content: \"\\e218\";\n}\n.glyphicon-bed:before {\n content: \"\\e219\";\n}\n.glyphicon-apple:before {\n content: \"\\f8ff\";\n}\n.glyphicon-erase:before {\n content: \"\\e221\";\n}\n.glyphicon-hourglass:before {\n content: \"\\231b\";\n}\n.glyphicon-lamp:before {\n content: \"\\e223\";\n}\n.glyphicon-duplicate:before {\n content: \"\\e224\";\n}\n.glyphicon-piggy-bank:before {\n content: \"\\e225\";\n}\n.glyphicon-scissors:before {\n content: \"\\e226\";\n}\n.glyphicon-bitcoin:before {\n content: \"\\e227\";\n}\n.glyphicon-btc:before {\n content: \"\\e227\";\n}\n.glyphicon-xbt:before {\n content: \"\\e227\";\n}\n.glyphicon-yen:before {\n content: \"\\00a5\";\n}\n.glyphicon-jpy:before {\n content: \"\\00a5\";\n}\n.glyphicon-ruble:before {\n content: \"\\20bd\";\n}\n.glyphicon-rub:before {\n content: \"\\20bd\";\n}\n.glyphicon-scale:before {\n content: \"\\e230\";\n}\n.glyphicon-ice-lolly:before {\n content: \"\\e231\";\n}\n.glyphicon-ice-lolly-tasted:before {\n content: \"\\e232\";\n}\n.glyphicon-education:before {\n content: \"\\e233\";\n}\n.glyphicon-option-horizontal:before {\n content: \"\\e234\";\n}\n.glyphicon-option-vertical:before {\n content: \"\\e235\";\n}\n.glyphicon-menu-hamburger:before {\n content: \"\\e236\";\n}\n.glyphicon-modal-window:before {\n content: \"\\e237\";\n}\n.glyphicon-oil:before {\n content: \"\\e238\";\n}\n.glyphicon-grain:before {\n content: \"\\e239\";\n}\n.glyphicon-sunglasses:before {\n content: \"\\e240\";\n}\n.glyphicon-text-size:before {\n content: \"\\e241\";\n}\n.glyphicon-text-color:before {\n content: \"\\e242\";\n}\n.glyphicon-text-background:before {\n content: \"\\e243\";\n}\n.glyphicon-object-align-top:before {\n content: \"\\e244\";\n}\n.glyphicon-object-align-bottom:before {\n content: \"\\e245\";\n}\n.glyphicon-object-align-horizontal:before {\n content: \"\\e246\";\n}\n.glyphicon-object-align-left:before {\n content: \"\\e247\";\n}\n.glyphicon-object-align-vertical:before {\n content: \"\\e248\";\n}\n.glyphicon-object-align-right:before {\n content: \"\\e249\";\n}\n.glyphicon-triangle-right:before {\n content: \"\\e250\";\n}\n.glyphicon-triangle-left:before {\n content: \"\\e251\";\n}\n.glyphicon-triangle-bottom:before {\n content: \"\\e252\";\n}\n.glyphicon-triangle-top:before {\n content: \"\\e253\";\n}\n.glyphicon-console:before {\n content: \"\\e254\";\n}\n.glyphicon-superscript:before {\n content: \"\\e255\";\n}\n.glyphicon-subscript:before {\n content: \"\\e256\";\n}\n.glyphicon-menu-left:before {\n content: \"\\e257\";\n}\n.glyphicon-menu-right:before {\n content: \"\\e258\";\n}\n.glyphicon-menu-down:before {\n content: \"\\e259\";\n}\n.glyphicon-menu-up:before {\n content: \"\\e260\";\n}\n* {\n -webkit-box-sizing: border-box;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\n*:before,\n*:after {\n -webkit-box-sizing: border-box;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\nhtml {\n font-size: 10px;\n -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n}\nbody {\n font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n font-size: 14px;\n line-height: 1.42857143;\n color: #333333;\n background-color: #ffffff;\n}\ninput,\nbutton,\nselect,\ntextarea {\n font-family: inherit;\n font-size: inherit;\n line-height: inherit;\n}\na {\n color: #337ab7;\n text-decoration: none;\n}\na:hover,\na:focus {\n color: #23527c;\n text-decoration: underline;\n}\na:focus {\n outline: thin dotted;\n outline: 5px auto -webkit-focus-ring-color;\n outline-offset: -2px;\n}\nfigure {\n margin: 0;\n}\nimg {\n vertical-align: middle;\n}\n.img-responsive,\n.thumbnail > img,\n.thumbnail a > img,\n.carousel-inner > .item > img,\n.carousel-inner > .item > a > img {\n display: block;\n max-width: 100%;\n height: auto;\n}\n.img-rounded {\n border-radius: 6px;\n}\n.img-thumbnail {\n padding: 4px;\n line-height: 1.42857143;\n background-color: #ffffff;\n border: 1px solid #dddddd;\n border-radius: 4px;\n -webkit-transition: all 0.2s ease-in-out;\n -o-transition: all 0.2s ease-in-out;\n transition: all 0.2s ease-in-out;\n display: inline-block;\n max-width: 100%;\n height: auto;\n}\n.img-circle {\n border-radius: 50%;\n}\nhr {\n margin-top: 20px;\n margin-bottom: 20px;\n border: 0;\n border-top: 1px solid #eeeeee;\n}\n.sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n margin: -1px;\n padding: 0;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n border: 0;\n}\n.sr-only-focusable:active,\n.sr-only-focusable:focus {\n position: static;\n width: auto;\n height: auto;\n margin: 0;\n overflow: visible;\n clip: auto;\n}\n[role=\"button\"] {\n cursor: pointer;\n}\nh1,\nh2,\nh3,\nh4,\nh5,\nh6,\n.h1,\n.h2,\n.h3,\n.h4,\n.h5,\n.h6 {\n font-family: inherit;\n font-weight: 500;\n line-height: 1.1;\n color: inherit;\n}\nh1 small,\nh2 small,\nh3 small,\nh4 small,\nh5 small,\nh6 small,\n.h1 small,\n.h2 small,\n.h3 small,\n.h4 small,\n.h5 small,\n.h6 small,\nh1 .small,\nh2 .small,\nh3 .small,\nh4 .small,\nh5 .small,\nh6 .small,\n.h1 .small,\n.h2 .small,\n.h3 .small,\n.h4 .small,\n.h5 .small,\n.h6 .small {\n font-weight: normal;\n line-height: 1;\n color: #777777;\n}\nh1,\n.h1,\nh2,\n.h2,\nh3,\n.h3 {\n margin-top: 20px;\n margin-bottom: 10px;\n}\nh1 small,\n.h1 small,\nh2 small,\n.h2 small,\nh3 small,\n.h3 small,\nh1 .small,\n.h1 .small,\nh2 .small,\n.h2 .small,\nh3 .small,\n.h3 .small {\n font-size: 65%;\n}\nh4,\n.h4,\nh5,\n.h5,\nh6,\n.h6 {\n margin-top: 10px;\n margin-bottom: 10px;\n}\nh4 small,\n.h4 small,\nh5 small,\n.h5 small,\nh6 small,\n.h6 small,\nh4 .small,\n.h4 .small,\nh5 .small,\n.h5 .small,\nh6 .small,\n.h6 .small {\n font-size: 75%;\n}\nh1,\n.h1 {\n font-size: 36px;\n}\nh2,\n.h2 {\n font-size: 30px;\n}\nh3,\n.h3 {\n font-size: 24px;\n}\nh4,\n.h4 {\n font-size: 18px;\n}\nh5,\n.h5 {\n font-size: 14px;\n}\nh6,\n.h6 {\n font-size: 12px;\n}\np {\n margin: 0 0 10px;\n}\n.lead {\n margin-bottom: 20px;\n font-size: 16px;\n font-weight: 300;\n line-height: 1.4;\n}\n@media (min-width: 768px) {\n .lead {\n font-size: 21px;\n }\n}\nsmall,\n.small {\n font-size: 85%;\n}\nmark,\n.mark {\n background-color: #fcf8e3;\n padding: .2em;\n}\n.text-left {\n text-align: left;\n}\n.text-right {\n text-align: right;\n}\n.text-center {\n text-align: center;\n}\n.text-justify {\n text-align: justify;\n}\n.text-nowrap {\n white-space: nowrap;\n}\n.text-lowercase {\n text-transform: lowercase;\n}\n.text-uppercase {\n text-transform: uppercase;\n}\n.text-capitalize {\n text-transform: capitalize;\n}\n.text-muted {\n color: #777777;\n}\n.text-primary {\n color: #337ab7;\n}\na.text-primary:hover {\n color: #286090;\n}\n.text-success {\n color: #3c763d;\n}\na.text-success:hover {\n color: #2b542c;\n}\n.text-info {\n color: #31708f;\n}\na.text-info:hover {\n color: #245269;\n}\n.text-warning {\n color: #8a6d3b;\n}\na.text-warning:hover {\n color: #66512c;\n}\n.text-danger {\n color: #a94442;\n}\na.text-danger:hover {\n color: #843534;\n}\n.bg-primary {\n color: #fff;\n background-color: #337ab7;\n}\na.bg-primary:hover {\n background-color: #286090;\n}\n.bg-success {\n background-color: #dff0d8;\n}\na.bg-success:hover {\n background-color: #c1e2b3;\n}\n.bg-info {\n background-color: #d9edf7;\n}\na.bg-info:hover {\n background-color: #afd9ee;\n}\n.bg-warning {\n background-color: #fcf8e3;\n}\na.bg-warning:hover {\n background-color: #f7ecb5;\n}\n.bg-danger {\n background-color: #f2dede;\n}\na.bg-danger:hover {\n background-color: #e4b9b9;\n}\n.page-header {\n padding-bottom: 9px;\n margin: 40px 0 20px;\n border-bottom: 1px solid #eeeeee;\n}\nul,\nol {\n margin-top: 0;\n margin-bottom: 10px;\n}\nul ul,\nol ul,\nul ol,\nol ol {\n margin-bottom: 0;\n}\n.list-unstyled {\n padding-left: 0;\n list-style: none;\n}\n.list-inline {\n padding-left: 0;\n list-style: none;\n margin-left: -5px;\n}\n.list-inline > li {\n display: inline-block;\n padding-left: 5px;\n padding-right: 5px;\n}\ndl {\n margin-top: 0;\n margin-bottom: 20px;\n}\ndt,\ndd {\n line-height: 1.42857143;\n}\ndt {\n font-weight: bold;\n}\ndd {\n margin-left: 0;\n}\n@media (min-width: 768px) {\n .dl-horizontal dt {\n float: left;\n width: 160px;\n clear: left;\n text-align: right;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n .dl-horizontal dd {\n margin-left: 180px;\n }\n}\nabbr[title],\nabbr[data-original-title] {\n cursor: help;\n border-bottom: 1px dotted #777777;\n}\n.initialism {\n font-size: 90%;\n text-transform: uppercase;\n}\nblockquote {\n padding: 10px 20px;\n margin: 0 0 20px;\n font-size: 17.5px;\n border-left: 5px solid #eeeeee;\n}\nblockquote p:last-child,\nblockquote ul:last-child,\nblockquote ol:last-child {\n margin-bottom: 0;\n}\nblockquote footer,\nblockquote small,\nblockquote .small {\n display: block;\n font-size: 80%;\n line-height: 1.42857143;\n color: #777777;\n}\nblockquote footer:before,\nblockquote small:before,\nblockquote .small:before {\n content: '\\2014 \\00A0';\n}\n.blockquote-reverse,\nblockquote.pull-right {\n padding-right: 15px;\n padding-left: 0;\n border-right: 5px solid #eeeeee;\n border-left: 0;\n text-align: right;\n}\n.blockquote-reverse footer:before,\nblockquote.pull-right footer:before,\n.blockquote-reverse small:before,\nblockquote.pull-right small:before,\n.blockquote-reverse .small:before,\nblockquote.pull-right .small:before {\n content: '';\n}\n.blockquote-reverse footer:after,\nblockquote.pull-right footer:after,\n.blockquote-reverse small:after,\nblockquote.pull-right small:after,\n.blockquote-reverse .small:after,\nblockquote.pull-right .small:after {\n content: '\\00A0 \\2014';\n}\naddress {\n margin-bottom: 20px;\n font-style: normal;\n line-height: 1.42857143;\n}\ncode,\nkbd,\npre,\nsamp {\n font-family: Menlo, Monaco, Consolas, \"Courier New\", monospace;\n}\ncode {\n padding: 2px 4px;\n font-size: 90%;\n color: #c7254e;\n background-color: #f9f2f4;\n border-radius: 4px;\n}\nkbd {\n padding: 2px 4px;\n font-size: 90%;\n color: #ffffff;\n background-color: #333333;\n border-radius: 3px;\n box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\nkbd kbd {\n padding: 0;\n font-size: 100%;\n font-weight: bold;\n box-shadow: none;\n}\npre {\n display: block;\n padding: 9.5px;\n margin: 0 0 10px;\n font-size: 13px;\n line-height: 1.42857143;\n word-break: break-all;\n word-wrap: break-word;\n color: #333333;\n background-color: #f5f5f5;\n border: 1px solid #cccccc;\n border-radius: 4px;\n}\npre code {\n padding: 0;\n font-size: inherit;\n color: inherit;\n white-space: pre-wrap;\n background-color: transparent;\n border-radius: 0;\n}\n.pre-scrollable {\n max-height: 340px;\n overflow-y: scroll;\n}\n.container {\n margin-right: auto;\n margin-left: auto;\n padding-left: 15px;\n padding-right: 15px;\n}\n@media (min-width: 768px) {\n .container {\n width: 750px;\n }\n}\n@media (min-width: 992px) {\n .container {\n width: 970px;\n }\n}\n@media (min-width: 1200px) {\n .container {\n width: 1170px;\n }\n}\n.container-fluid {\n margin-right: auto;\n margin-left: auto;\n padding-left: 15px;\n padding-right: 15px;\n}\n.row {\n margin-left: -15px;\n margin-right: -15px;\n}\n.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 {\n position: relative;\n min-height: 1px;\n padding-left: 15px;\n padding-right: 15px;\n}\n.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12 {\n float: left;\n}\n.col-xs-12 {\n width: 100%;\n}\n.col-xs-11 {\n width: 91.66666667%;\n}\n.col-xs-10 {\n width: 83.33333333%;\n}\n.col-xs-9 {\n width: 75%;\n}\n.col-xs-8 {\n width: 66.66666667%;\n}\n.col-xs-7 {\n width: 58.33333333%;\n}\n.col-xs-6 {\n width: 50%;\n}\n.col-xs-5 {\n width: 41.66666667%;\n}\n.col-xs-4 {\n width: 33.33333333%;\n}\n.col-xs-3 {\n width: 25%;\n}\n.col-xs-2 {\n width: 16.66666667%;\n}\n.col-xs-1 {\n width: 8.33333333%;\n}\n.col-xs-pull-12 {\n right: 100%;\n}\n.col-xs-pull-11 {\n right: 91.66666667%;\n}\n.col-xs-pull-10 {\n right: 83.33333333%;\n}\n.col-xs-pull-9 {\n right: 75%;\n}\n.col-xs-pull-8 {\n right: 66.66666667%;\n}\n.col-xs-pull-7 {\n right: 58.33333333%;\n}\n.col-xs-pull-6 {\n right: 50%;\n}\n.col-xs-pull-5 {\n right: 41.66666667%;\n}\n.col-xs-pull-4 {\n right: 33.33333333%;\n}\n.col-xs-pull-3 {\n right: 25%;\n}\n.col-xs-pull-2 {\n right: 16.66666667%;\n}\n.col-xs-pull-1 {\n right: 8.33333333%;\n}\n.col-xs-pull-0 {\n right: auto;\n}\n.col-xs-push-12 {\n left: 100%;\n}\n.col-xs-push-11 {\n left: 91.66666667%;\n}\n.col-xs-push-10 {\n left: 83.33333333%;\n}\n.col-xs-push-9 {\n left: 75%;\n}\n.col-xs-push-8 {\n left: 66.66666667%;\n}\n.col-xs-push-7 {\n left: 58.33333333%;\n}\n.col-xs-push-6 {\n left: 50%;\n}\n.col-xs-push-5 {\n left: 41.66666667%;\n}\n.col-xs-push-4 {\n left: 33.33333333%;\n}\n.col-xs-push-3 {\n left: 25%;\n}\n.col-xs-push-2 {\n left: 16.66666667%;\n}\n.col-xs-push-1 {\n left: 8.33333333%;\n}\n.col-xs-push-0 {\n left: auto;\n}\n.col-xs-offset-12 {\n margin-left: 100%;\n}\n.col-xs-offset-11 {\n margin-left: 91.66666667%;\n}\n.col-xs-offset-10 {\n margin-left: 83.33333333%;\n}\n.col-xs-offset-9 {\n margin-left: 75%;\n}\n.col-xs-offset-8 {\n margin-left: 66.66666667%;\n}\n.col-xs-offset-7 {\n margin-left: 58.33333333%;\n}\n.col-xs-offset-6 {\n margin-left: 50%;\n}\n.col-xs-offset-5 {\n margin-left: 41.66666667%;\n}\n.col-xs-offset-4 {\n margin-left: 33.33333333%;\n}\n.col-xs-offset-3 {\n margin-left: 25%;\n}\n.col-xs-offset-2 {\n margin-left: 16.66666667%;\n}\n.col-xs-offset-1 {\n margin-left: 8.33333333%;\n}\n.col-xs-offset-0 {\n margin-left: 0%;\n}\n@media (min-width: 768px) {\n .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12 {\n float: left;\n }\n .col-sm-12 {\n width: 100%;\n }\n .col-sm-11 {\n width: 91.66666667%;\n }\n .col-sm-10 {\n width: 83.33333333%;\n }\n .col-sm-9 {\n width: 75%;\n }\n .col-sm-8 {\n width: 66.66666667%;\n }\n .col-sm-7 {\n width: 58.33333333%;\n }\n .col-sm-6 {\n width: 50%;\n }\n .col-sm-5 {\n width: 41.66666667%;\n }\n .col-sm-4 {\n width: 33.33333333%;\n }\n .col-sm-3 {\n width: 25%;\n }\n .col-sm-2 {\n width: 16.66666667%;\n }\n .col-sm-1 {\n width: 8.33333333%;\n }\n .col-sm-pull-12 {\n right: 100%;\n }\n .col-sm-pull-11 {\n right: 91.66666667%;\n }\n .col-sm-pull-10 {\n right: 83.33333333%;\n }\n .col-sm-pull-9 {\n right: 75%;\n }\n .col-sm-pull-8 {\n right: 66.66666667%;\n }\n .col-sm-pull-7 {\n right: 58.33333333%;\n }\n .col-sm-pull-6 {\n right: 50%;\n }\n .col-sm-pull-5 {\n right: 41.66666667%;\n }\n .col-sm-pull-4 {\n right: 33.33333333%;\n }\n .col-sm-pull-3 {\n right: 25%;\n }\n .col-sm-pull-2 {\n right: 16.66666667%;\n }\n .col-sm-pull-1 {\n right: 8.33333333%;\n }\n .col-sm-pull-0 {\n right: auto;\n }\n .col-sm-push-12 {\n left: 100%;\n }\n .col-sm-push-11 {\n left: 91.66666667%;\n }\n .col-sm-push-10 {\n left: 83.33333333%;\n }\n .col-sm-push-9 {\n left: 75%;\n }\n .col-sm-push-8 {\n left: 66.66666667%;\n }\n .col-sm-push-7 {\n left: 58.33333333%;\n }\n .col-sm-push-6 {\n left: 50%;\n }\n .col-sm-push-5 {\n left: 41.66666667%;\n }\n .col-sm-push-4 {\n left: 33.33333333%;\n }\n .col-sm-push-3 {\n left: 25%;\n }\n .col-sm-push-2 {\n left: 16.66666667%;\n }\n .col-sm-push-1 {\n left: 8.33333333%;\n }\n .col-sm-push-0 {\n left: auto;\n }\n .col-sm-offset-12 {\n margin-left: 100%;\n }\n .col-sm-offset-11 {\n margin-left: 91.66666667%;\n }\n .col-sm-offset-10 {\n margin-left: 83.33333333%;\n }\n .col-sm-offset-9 {\n margin-left: 75%;\n }\n .col-sm-offset-8 {\n margin-left: 66.66666667%;\n }\n .col-sm-offset-7 {\n margin-left: 58.33333333%;\n }\n .col-sm-offset-6 {\n margin-left: 50%;\n }\n .col-sm-offset-5 {\n margin-left: 41.66666667%;\n }\n .col-sm-offset-4 {\n margin-left: 33.33333333%;\n }\n .col-sm-offset-3 {\n margin-left: 25%;\n }\n .col-sm-offset-2 {\n margin-left: 16.66666667%;\n }\n .col-sm-offset-1 {\n margin-left: 8.33333333%;\n }\n .col-sm-offset-0 {\n margin-left: 0%;\n }\n}\n@media (min-width: 992px) {\n .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12 {\n float: left;\n }\n .col-md-12 {\n width: 100%;\n }\n .col-md-11 {\n width: 91.66666667%;\n }\n .col-md-10 {\n width: 83.33333333%;\n }\n .col-md-9 {\n width: 75%;\n }\n .col-md-8 {\n width: 66.66666667%;\n }\n .col-md-7 {\n width: 58.33333333%;\n }\n .col-md-6 {\n width: 50%;\n }\n .col-md-5 {\n width: 41.66666667%;\n }\n .col-md-4 {\n width: 33.33333333%;\n }\n .col-md-3 {\n width: 25%;\n }\n .col-md-2 {\n width: 16.66666667%;\n }\n .col-md-1 {\n width: 8.33333333%;\n }\n .col-md-pull-12 {\n right: 100%;\n }\n .col-md-pull-11 {\n right: 91.66666667%;\n }\n .col-md-pull-10 {\n right: 83.33333333%;\n }\n .col-md-pull-9 {\n right: 75%;\n }\n .col-md-pull-8 {\n right: 66.66666667%;\n }\n .col-md-pull-7 {\n right: 58.33333333%;\n }\n .col-md-pull-6 {\n right: 50%;\n }\n .col-md-pull-5 {\n right: 41.66666667%;\n }\n .col-md-pull-4 {\n right: 33.33333333%;\n }\n .col-md-pull-3 {\n right: 25%;\n }\n .col-md-pull-2 {\n right: 16.66666667%;\n }\n .col-md-pull-1 {\n right: 8.33333333%;\n }\n .col-md-pull-0 {\n right: auto;\n }\n .col-md-push-12 {\n left: 100%;\n }\n .col-md-push-11 {\n left: 91.66666667%;\n }\n .col-md-push-10 {\n left: 83.33333333%;\n }\n .col-md-push-9 {\n left: 75%;\n }\n .col-md-push-8 {\n left: 66.66666667%;\n }\n .col-md-push-7 {\n left: 58.33333333%;\n }\n .col-md-push-6 {\n left: 50%;\n }\n .col-md-push-5 {\n left: 41.66666667%;\n }\n .col-md-push-4 {\n left: 33.33333333%;\n }\n .col-md-push-3 {\n left: 25%;\n }\n .col-md-push-2 {\n left: 16.66666667%;\n }\n .col-md-push-1 {\n left: 8.33333333%;\n }\n .col-md-push-0 {\n left: auto;\n }\n .col-md-offset-12 {\n margin-left: 100%;\n }\n .col-md-offset-11 {\n margin-left: 91.66666667%;\n }\n .col-md-offset-10 {\n margin-left: 83.33333333%;\n }\n .col-md-offset-9 {\n margin-left: 75%;\n }\n .col-md-offset-8 {\n margin-left: 66.66666667%;\n }\n .col-md-offset-7 {\n margin-left: 58.33333333%;\n }\n .col-md-offset-6 {\n margin-left: 50%;\n }\n .col-md-offset-5 {\n margin-left: 41.66666667%;\n }\n .col-md-offset-4 {\n margin-left: 33.33333333%;\n }\n .col-md-offset-3 {\n margin-left: 25%;\n }\n .col-md-offset-2 {\n margin-left: 16.66666667%;\n }\n .col-md-offset-1 {\n margin-left: 8.33333333%;\n }\n .col-md-offset-0 {\n margin-left: 0%;\n }\n}\n@media (min-width: 1200px) {\n .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12 {\n float: left;\n }\n .col-lg-12 {\n width: 100%;\n }\n .col-lg-11 {\n width: 91.66666667%;\n }\n .col-lg-10 {\n width: 83.33333333%;\n }\n .col-lg-9 {\n width: 75%;\n }\n .col-lg-8 {\n width: 66.66666667%;\n }\n .col-lg-7 {\n width: 58.33333333%;\n }\n .col-lg-6 {\n width: 50%;\n }\n .col-lg-5 {\n width: 41.66666667%;\n }\n .col-lg-4 {\n width: 33.33333333%;\n }\n .col-lg-3 {\n width: 25%;\n }\n .col-lg-2 {\n width: 16.66666667%;\n }\n .col-lg-1 {\n width: 8.33333333%;\n }\n .col-lg-pull-12 {\n right: 100%;\n }\n .col-lg-pull-11 {\n right: 91.66666667%;\n }\n .col-lg-pull-10 {\n right: 83.33333333%;\n }\n .col-lg-pull-9 {\n right: 75%;\n }\n .col-lg-pull-8 {\n right: 66.66666667%;\n }\n .col-lg-pull-7 {\n right: 58.33333333%;\n }\n .col-lg-pull-6 {\n right: 50%;\n }\n .col-lg-pull-5 {\n right: 41.66666667%;\n }\n .col-lg-pull-4 {\n right: 33.33333333%;\n }\n .col-lg-pull-3 {\n right: 25%;\n }\n .col-lg-pull-2 {\n right: 16.66666667%;\n }\n .col-lg-pull-1 {\n right: 8.33333333%;\n }\n .col-lg-pull-0 {\n right: auto;\n }\n .col-lg-push-12 {\n left: 100%;\n }\n .col-lg-push-11 {\n left: 91.66666667%;\n }\n .col-lg-push-10 {\n left: 83.33333333%;\n }\n .col-lg-push-9 {\n left: 75%;\n }\n .col-lg-push-8 {\n left: 66.66666667%;\n }\n .col-lg-push-7 {\n left: 58.33333333%;\n }\n .col-lg-push-6 {\n left: 50%;\n }\n .col-lg-push-5 {\n left: 41.66666667%;\n }\n .col-lg-push-4 {\n left: 33.33333333%;\n }\n .col-lg-push-3 {\n left: 25%;\n }\n .col-lg-push-2 {\n left: 16.66666667%;\n }\n .col-lg-push-1 {\n left: 8.33333333%;\n }\n .col-lg-push-0 {\n left: auto;\n }\n .col-lg-offset-12 {\n margin-left: 100%;\n }\n .col-lg-offset-11 {\n margin-left: 91.66666667%;\n }\n .col-lg-offset-10 {\n margin-left: 83.33333333%;\n }\n .col-lg-offset-9 {\n margin-left: 75%;\n }\n .col-lg-offset-8 {\n margin-left: 66.66666667%;\n }\n .col-lg-offset-7 {\n margin-left: 58.33333333%;\n }\n .col-lg-offset-6 {\n margin-left: 50%;\n }\n .col-lg-offset-5 {\n margin-left: 41.66666667%;\n }\n .col-lg-offset-4 {\n margin-left: 33.33333333%;\n }\n .col-lg-offset-3 {\n margin-left: 25%;\n }\n .col-lg-offset-2 {\n margin-left: 16.66666667%;\n }\n .col-lg-offset-1 {\n margin-left: 8.33333333%;\n }\n .col-lg-offset-0 {\n margin-left: 0%;\n }\n}\ntable {\n background-color: transparent;\n}\ncaption {\n padding-top: 8px;\n padding-bottom: 8px;\n color: #777777;\n text-align: left;\n}\nth {\n text-align: left;\n}\n.table {\n width: 100%;\n max-width: 100%;\n margin-bottom: 20px;\n}\n.table > thead > tr > th,\n.table > tbody > tr > th,\n.table > tfoot > tr > th,\n.table > thead > tr > td,\n.table > tbody > tr > td,\n.table > tfoot > tr > td {\n padding: 8px;\n line-height: 1.42857143;\n vertical-align: top;\n border-top: 1px solid #dddddd;\n}\n.table > thead > tr > th {\n vertical-align: bottom;\n border-bottom: 2px solid #dddddd;\n}\n.table > caption + thead > tr:first-child > th,\n.table > colgroup + thead > tr:first-child > th,\n.table > thead:first-child > tr:first-child > th,\n.table > caption + thead > tr:first-child > td,\n.table > colgroup + thead > tr:first-child > td,\n.table > thead:first-child > tr:first-child > td {\n border-top: 0;\n}\n.table > tbody + tbody {\n border-top: 2px solid #dddddd;\n}\n.table .table {\n background-color: #ffffff;\n}\n.table-condensed > thead > tr > th,\n.table-condensed > tbody > tr > th,\n.table-condensed > tfoot > tr > th,\n.table-condensed > thead > tr > td,\n.table-condensed > tbody > tr > td,\n.table-condensed > tfoot > tr > td {\n padding: 5px;\n}\n.table-bordered {\n border: 1px solid #dddddd;\n}\n.table-bordered > thead > tr > th,\n.table-bordered > tbody > tr > th,\n.table-bordered > tfoot > tr > th,\n.table-bordered > thead > tr > td,\n.table-bordered > tbody > tr > td,\n.table-bordered > tfoot > tr > td {\n border: 1px solid #dddddd;\n}\n.table-bordered > thead > tr > th,\n.table-bordered > thead > tr > td {\n border-bottom-width: 2px;\n}\n.table-striped > tbody > tr:nth-of-type(odd) {\n background-color: #f9f9f9;\n}\n.table-hover > tbody > tr:hover {\n background-color: #f5f5f5;\n}\ntable col[class*=\"col-\"] {\n position: static;\n float: none;\n display: table-column;\n}\ntable td[class*=\"col-\"],\ntable th[class*=\"col-\"] {\n position: static;\n float: none;\n display: table-cell;\n}\n.table > thead > tr > td.active,\n.table > tbody > tr > td.active,\n.table > tfoot > tr > td.active,\n.table > thead > tr > th.active,\n.table > tbody > tr > th.active,\n.table > tfoot > tr > th.active,\n.table > thead > tr.active > td,\n.table > tbody > tr.active > td,\n.table > tfoot > tr.active > td,\n.table > thead > tr.active > th,\n.table > tbody > tr.active > th,\n.table > tfoot > tr.active > th {\n background-color: #f5f5f5;\n}\n.table-hover > tbody > tr > td.active:hover,\n.table-hover > tbody > tr > th.active:hover,\n.table-hover > tbody > tr.active:hover > td,\n.table-hover > tbody > tr:hover > .active,\n.table-hover > tbody > tr.active:hover > th {\n background-color: #e8e8e8;\n}\n.table > thead > tr > td.success,\n.table > tbody > tr > td.success,\n.table > tfoot > tr > td.success,\n.table > thead > tr > th.success,\n.table > tbody > tr > th.success,\n.table > tfoot > tr > th.success,\n.table > thead > tr.success > td,\n.table > tbody > tr.success > td,\n.table > tfoot > tr.success > td,\n.table > thead > tr.success > th,\n.table > tbody > tr.success > th,\n.table > tfoot > tr.success > th {\n background-color: #dff0d8;\n}\n.table-hover > tbody > tr > td.success:hover,\n.table-hover > tbody > tr > th.success:hover,\n.table-hover > tbody > tr.success:hover > td,\n.table-hover > tbody > tr:hover > .success,\n.table-hover > tbody > tr.success:hover > th {\n background-color: #d0e9c6;\n}\n.table > thead > tr > td.info,\n.table > tbody > tr > td.info,\n.table > tfoot > tr > td.info,\n.table > thead > tr > th.info,\n.table > tbody > tr > th.info,\n.table > tfoot > tr > th.info,\n.table > thead > tr.info > td,\n.table > tbody > tr.info > td,\n.table > tfoot > tr.info > td,\n.table > thead > tr.info > th,\n.table > tbody > tr.info > th,\n.table > tfoot > tr.info > th {\n background-color: #d9edf7;\n}\n.table-hover > tbody > tr > td.info:hover,\n.table-hover > tbody > tr > th.info:hover,\n.table-hover > tbody > tr.info:hover > td,\n.table-hover > tbody > tr:hover > .info,\n.table-hover > tbody > tr.info:hover > th {\n background-color: #c4e3f3;\n}\n.table > thead > tr > td.warning,\n.table > tbody > tr > td.warning,\n.table > tfoot > tr > td.warning,\n.table > thead > tr > th.warning,\n.table > tbody > tr > th.warning,\n.table > tfoot > tr > th.warning,\n.table > thead > tr.warning > td,\n.table > tbody > tr.warning > td,\n.table > tfoot > tr.warning > td,\n.table > thead > tr.warning > th,\n.table > tbody > tr.warning > th,\n.table > tfoot > tr.warning > th {\n background-color: #fcf8e3;\n}\n.table-hover > tbody > tr > td.warning:hover,\n.table-hover > tbody > tr > th.warning:hover,\n.table-hover > tbody > tr.warning:hover > td,\n.table-hover > tbody > tr:hover > .warning,\n.table-hover > tbody > tr.warning:hover > th {\n background-color: #faf2cc;\n}\n.table > thead > tr > td.danger,\n.table > tbody > tr > td.danger,\n.table > tfoot > tr > td.danger,\n.table > thead > tr > th.danger,\n.table > tbody > tr > th.danger,\n.table > tfoot > tr > th.danger,\n.table > thead > tr.danger > td,\n.table > tbody > tr.danger > td,\n.table > tfoot > tr.danger > td,\n.table > thead > tr.danger > th,\n.table > tbody > tr.danger > th,\n.table > tfoot > tr.danger > th {\n background-color: #f2dede;\n}\n.table-hover > tbody > tr > td.danger:hover,\n.table-hover > tbody > tr > th.danger:hover,\n.table-hover > tbody > tr.danger:hover > td,\n.table-hover > tbody > tr:hover > .danger,\n.table-hover > tbody > tr.danger:hover > th {\n background-color: #ebcccc;\n}\n.table-responsive {\n overflow-x: auto;\n min-height: 0.01%;\n}\n@media screen and (max-width: 767px) {\n .table-responsive {\n width: 100%;\n margin-bottom: 15px;\n overflow-y: hidden;\n -ms-overflow-style: -ms-autohiding-scrollbar;\n border: 1px solid #dddddd;\n }\n .table-responsive > .table {\n margin-bottom: 0;\n }\n .table-responsive > .table > thead > tr > th,\n .table-responsive > .table > tbody > tr > th,\n .table-responsive > .table > tfoot > tr > th,\n .table-responsive > .table > thead > tr > td,\n .table-responsive > .table > tbody > tr > td,\n .table-responsive > .table > tfoot > tr > td {\n white-space: nowrap;\n }\n .table-responsive > .table-bordered {\n border: 0;\n }\n .table-responsive > .table-bordered > thead > tr > th:first-child,\n .table-responsive > .table-bordered > tbody > tr > th:first-child,\n .table-responsive > .table-bordered > tfoot > tr > th:first-child,\n .table-responsive > .table-bordered > thead > tr > td:first-child,\n .table-responsive > .table-bordered > tbody > tr > td:first-child,\n .table-responsive > .table-bordered > tfoot > tr > td:first-child {\n border-left: 0;\n }\n .table-responsive > .table-bordered > thead > tr > th:last-child,\n .table-responsive > .table-bordered > tbody > tr > th:last-child,\n .table-responsive > .table-bordered > tfoot > tr > th:last-child,\n .table-responsive > .table-bordered > thead > tr > td:last-child,\n .table-responsive > .table-bordered > tbody > tr > td:last-child,\n .table-responsive > .table-bordered > tfoot > tr > td:last-child {\n border-right: 0;\n }\n .table-responsive > .table-bordered > tbody > tr:last-child > th,\n .table-responsive > .table-bordered > tfoot > tr:last-child > th,\n .table-responsive > .table-bordered > tbody > tr:last-child > td,\n .table-responsive > .table-bordered > tfoot > tr:last-child > td {\n border-bottom: 0;\n }\n}\nfieldset {\n padding: 0;\n margin: 0;\n border: 0;\n min-width: 0;\n}\nlegend {\n display: block;\n width: 100%;\n padding: 0;\n margin-bottom: 20px;\n font-size: 21px;\n line-height: inherit;\n color: #333333;\n border: 0;\n border-bottom: 1px solid #e5e5e5;\n}\nlabel {\n display: inline-block;\n max-width: 100%;\n margin-bottom: 5px;\n font-weight: bold;\n}\ninput[type=\"search\"] {\n -webkit-box-sizing: border-box;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n margin: 4px 0 0;\n margin-top: 1px \\9;\n line-height: normal;\n}\ninput[type=\"file\"] {\n display: block;\n}\ninput[type=\"range\"] {\n display: block;\n width: 100%;\n}\nselect[multiple],\nselect[size] {\n height: auto;\n}\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n outline: thin dotted;\n outline: 5px auto -webkit-focus-ring-color;\n outline-offset: -2px;\n}\noutput {\n display: block;\n padding-top: 7px;\n font-size: 14px;\n line-height: 1.42857143;\n color: #555555;\n}\n.form-control {\n display: block;\n width: 100%;\n height: 34px;\n padding: 6px 12px;\n font-size: 14px;\n line-height: 1.42857143;\n color: #555555;\n background-color: #ffffff;\n background-image: none;\n border: 1px solid #cccccc;\n border-radius: 4px;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n -webkit-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;\n -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;\n transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;\n}\n.form-control:focus {\n border-color: #66afe9;\n outline: 0;\n -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);\n box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);\n}\n.form-control::-moz-placeholder {\n color: #999999;\n opacity: 1;\n}\n.form-control:-ms-input-placeholder {\n color: #999999;\n}\n.form-control::-webkit-input-placeholder {\n color: #999999;\n}\n.form-control[disabled],\n.form-control[readonly],\nfieldset[disabled] .form-control {\n background-color: #eeeeee;\n opacity: 1;\n}\n.form-control[disabled],\nfieldset[disabled] .form-control {\n cursor: not-allowed;\n}\ntextarea.form-control {\n height: auto;\n}\ninput[type=\"search\"] {\n -webkit-appearance: none;\n}\n@media screen and (-webkit-min-device-pixel-ratio: 0) {\n input[type=\"date\"],\n input[type=\"time\"],\n input[type=\"datetime-local\"],\n input[type=\"month\"] {\n line-height: 34px;\n }\n input[type=\"date\"].input-sm,\n input[type=\"time\"].input-sm,\n input[type=\"datetime-local\"].input-sm,\n input[type=\"month\"].input-sm,\n .input-group-sm input[type=\"date\"],\n .input-group-sm input[type=\"time\"],\n .input-group-sm input[type=\"datetime-local\"],\n .input-group-sm input[type=\"month\"] {\n line-height: 30px;\n }\n input[type=\"date\"].input-lg,\n input[type=\"time\"].input-lg,\n input[type=\"datetime-local\"].input-lg,\n input[type=\"month\"].input-lg,\n .input-group-lg input[type=\"date\"],\n .input-group-lg input[type=\"time\"],\n .input-group-lg input[type=\"datetime-local\"],\n .input-group-lg input[type=\"month\"] {\n line-height: 46px;\n }\n}\n.form-group {\n margin-bottom: 15px;\n}\n.radio,\n.checkbox {\n position: relative;\n display: block;\n margin-top: 10px;\n margin-bottom: 10px;\n}\n.radio label,\n.checkbox label {\n min-height: 20px;\n padding-left: 20px;\n margin-bottom: 0;\n font-weight: normal;\n cursor: pointer;\n}\n.radio input[type=\"radio\"],\n.radio-inline input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"],\n.checkbox-inline input[type=\"checkbox\"] {\n position: absolute;\n margin-left: -20px;\n margin-top: 4px \\9;\n}\n.radio + .radio,\n.checkbox + .checkbox {\n margin-top: -5px;\n}\n.radio-inline,\n.checkbox-inline {\n position: relative;\n display: inline-block;\n padding-left: 20px;\n margin-bottom: 0;\n vertical-align: middle;\n font-weight: normal;\n cursor: pointer;\n}\n.radio-inline + .radio-inline,\n.checkbox-inline + .checkbox-inline {\n margin-top: 0;\n margin-left: 10px;\n}\ninput[type=\"radio\"][disabled],\ninput[type=\"checkbox\"][disabled],\ninput[type=\"radio\"].disabled,\ninput[type=\"checkbox\"].disabled,\nfieldset[disabled] input[type=\"radio\"],\nfieldset[disabled] input[type=\"checkbox\"] {\n cursor: not-allowed;\n}\n.radio-inline.disabled,\n.checkbox-inline.disabled,\nfieldset[disabled] .radio-inline,\nfieldset[disabled] .checkbox-inline {\n cursor: not-allowed;\n}\n.radio.disabled label,\n.checkbox.disabled label,\nfieldset[disabled] .radio label,\nfieldset[disabled] .checkbox label {\n cursor: not-allowed;\n}\n.form-control-static {\n padding-top: 7px;\n padding-bottom: 7px;\n margin-bottom: 0;\n min-height: 34px;\n}\n.form-control-static.input-lg,\n.form-control-static.input-sm {\n padding-left: 0;\n padding-right: 0;\n}\n.input-sm {\n height: 30px;\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\nselect.input-sm {\n height: 30px;\n line-height: 30px;\n}\ntextarea.input-sm,\nselect[multiple].input-sm {\n height: auto;\n}\n.form-group-sm .form-control {\n height: 30px;\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\nselect.form-group-sm .form-control {\n height: 30px;\n line-height: 30px;\n}\ntextarea.form-group-sm .form-control,\nselect[multiple].form-group-sm .form-control {\n height: auto;\n}\n.form-group-sm .form-control-static {\n height: 30px;\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n min-height: 32px;\n}\n.input-lg {\n height: 46px;\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n border-radius: 6px;\n}\nselect.input-lg {\n height: 46px;\n line-height: 46px;\n}\ntextarea.input-lg,\nselect[multiple].input-lg {\n height: auto;\n}\n.form-group-lg .form-control {\n height: 46px;\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n border-radius: 6px;\n}\nselect.form-group-lg .form-control {\n height: 46px;\n line-height: 46px;\n}\ntextarea.form-group-lg .form-control,\nselect[multiple].form-group-lg .form-control {\n height: auto;\n}\n.form-group-lg .form-control-static {\n height: 46px;\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n min-height: 38px;\n}\n.has-feedback {\n position: relative;\n}\n.has-feedback .form-control {\n padding-right: 42.5px;\n}\n.form-control-feedback {\n position: absolute;\n top: 0;\n right: 0;\n z-index: 2;\n display: block;\n width: 34px;\n height: 34px;\n line-height: 34px;\n text-align: center;\n pointer-events: none;\n}\n.input-lg + .form-control-feedback {\n width: 46px;\n height: 46px;\n line-height: 46px;\n}\n.input-sm + .form-control-feedback {\n width: 30px;\n height: 30px;\n line-height: 30px;\n}\n.has-success .help-block,\n.has-success .control-label,\n.has-success .radio,\n.has-success .checkbox,\n.has-success .radio-inline,\n.has-success .checkbox-inline,\n.has-success.radio label,\n.has-success.checkbox label,\n.has-success.radio-inline label,\n.has-success.checkbox-inline label {\n color: #3c763d;\n}\n.has-success .form-control {\n border-color: #3c763d;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n.has-success .form-control:focus {\n border-color: #2b542c;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168;\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168;\n}\n.has-success .input-group-addon {\n color: #3c763d;\n border-color: #3c763d;\n background-color: #dff0d8;\n}\n.has-success .form-control-feedback {\n color: #3c763d;\n}\n.has-warning .help-block,\n.has-warning .control-label,\n.has-warning .radio,\n.has-warning .checkbox,\n.has-warning .radio-inline,\n.has-warning .checkbox-inline,\n.has-warning.radio label,\n.has-warning.checkbox label,\n.has-warning.radio-inline label,\n.has-warning.checkbox-inline label {\n color: #8a6d3b;\n}\n.has-warning .form-control {\n border-color: #8a6d3b;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n.has-warning .form-control:focus {\n border-color: #66512c;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b;\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b;\n}\n.has-warning .input-group-addon {\n color: #8a6d3b;\n border-color: #8a6d3b;\n background-color: #fcf8e3;\n}\n.has-warning .form-control-feedback {\n color: #8a6d3b;\n}\n.has-error .help-block,\n.has-error .control-label,\n.has-error .radio,\n.has-error .checkbox,\n.has-error .radio-inline,\n.has-error .checkbox-inline,\n.has-error.radio label,\n.has-error.checkbox label,\n.has-error.radio-inline label,\n.has-error.checkbox-inline label {\n color: #a94442;\n}\n.has-error .form-control {\n border-color: #a94442;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n.has-error .form-control:focus {\n border-color: #843534;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483;\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483;\n}\n.has-error .input-group-addon {\n color: #a94442;\n border-color: #a94442;\n background-color: #f2dede;\n}\n.has-error .form-control-feedback {\n color: #a94442;\n}\n.has-feedback label ~ .form-control-feedback {\n top: 25px;\n}\n.has-feedback label.sr-only ~ .form-control-feedback {\n top: 0;\n}\n.help-block {\n display: block;\n margin-top: 5px;\n margin-bottom: 10px;\n color: #737373;\n}\n@media (min-width: 768px) {\n .form-inline .form-group {\n display: inline-block;\n margin-bottom: 0;\n vertical-align: middle;\n }\n .form-inline .form-control {\n display: inline-block;\n width: auto;\n vertical-align: middle;\n }\n .form-inline .form-control-static {\n display: inline-block;\n }\n .form-inline .input-group {\n display: inline-table;\n vertical-align: middle;\n }\n .form-inline .input-group .input-group-addon,\n .form-inline .input-group .input-group-btn,\n .form-inline .input-group .form-control {\n width: auto;\n }\n .form-inline .input-group > .form-control {\n width: 100%;\n }\n .form-inline .control-label {\n margin-bottom: 0;\n vertical-align: middle;\n }\n .form-inline .radio,\n .form-inline .checkbox {\n display: inline-block;\n margin-top: 0;\n margin-bottom: 0;\n vertical-align: middle;\n }\n .form-inline .radio label,\n .form-inline .checkbox label {\n padding-left: 0;\n }\n .form-inline .radio input[type=\"radio\"],\n .form-inline .checkbox input[type=\"checkbox\"] {\n position: relative;\n margin-left: 0;\n }\n .form-inline .has-feedback .form-control-feedback {\n top: 0;\n }\n}\n.form-horizontal .radio,\n.form-horizontal .checkbox,\n.form-horizontal .radio-inline,\n.form-horizontal .checkbox-inline {\n margin-top: 0;\n margin-bottom: 0;\n padding-top: 7px;\n}\n.form-horizontal .radio,\n.form-horizontal .checkbox {\n min-height: 27px;\n}\n.form-horizontal .form-group {\n margin-left: -15px;\n margin-right: -15px;\n}\n@media (min-width: 768px) {\n .form-horizontal .control-label {\n text-align: right;\n margin-bottom: 0;\n padding-top: 7px;\n }\n}\n.form-horizontal .has-feedback .form-control-feedback {\n right: 15px;\n}\n@media (min-width: 768px) {\n .form-horizontal .form-group-lg .control-label {\n padding-top: 14.333333px;\n }\n}\n@media (min-width: 768px) {\n .form-horizontal .form-group-sm .control-label {\n padding-top: 6px;\n }\n}\n.btn {\n display: inline-block;\n margin-bottom: 0;\n font-weight: normal;\n text-align: center;\n vertical-align: middle;\n touch-action: manipulation;\n cursor: pointer;\n background-image: none;\n border: 1px solid transparent;\n white-space: nowrap;\n padding: 6px 12px;\n font-size: 14px;\n line-height: 1.42857143;\n border-radius: 4px;\n -webkit-user-select: none;\n -moz-user-select: none;\n -ms-user-select: none;\n user-select: none;\n}\n.btn:focus,\n.btn:active:focus,\n.btn.active:focus,\n.btn.focus,\n.btn:active.focus,\n.btn.active.focus {\n outline: thin dotted;\n outline: 5px auto -webkit-focus-ring-color;\n outline-offset: -2px;\n}\n.btn:hover,\n.btn:focus,\n.btn.focus {\n color: #333333;\n text-decoration: none;\n}\n.btn:active,\n.btn.active {\n outline: 0;\n background-image: none;\n -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n}\n.btn.disabled,\n.btn[disabled],\nfieldset[disabled] .btn {\n cursor: not-allowed;\n pointer-events: none;\n opacity: 0.65;\n filter: alpha(opacity=65);\n -webkit-box-shadow: none;\n box-shadow: none;\n}\n.btn-default {\n color: #333333;\n background-color: #ffffff;\n border-color: #cccccc;\n}\n.btn-default:hover,\n.btn-default:focus,\n.btn-default.focus,\n.btn-default:active,\n.btn-default.active,\n.open > .dropdown-toggle.btn-default {\n color: #333333;\n background-color: #e6e6e6;\n border-color: #adadad;\n}\n.btn-default:active,\n.btn-default.active,\n.open > .dropdown-toggle.btn-default {\n background-image: none;\n}\n.btn-default.disabled,\n.btn-default[disabled],\nfieldset[disabled] .btn-default,\n.btn-default.disabled:hover,\n.btn-default[disabled]:hover,\nfieldset[disabled] .btn-default:hover,\n.btn-default.disabled:focus,\n.btn-default[disabled]:focus,\nfieldset[disabled] .btn-default:focus,\n.btn-default.disabled.focus,\n.btn-default[disabled].focus,\nfieldset[disabled] .btn-default.focus,\n.btn-default.disabled:active,\n.btn-default[disabled]:active,\nfieldset[disabled] .btn-default:active,\n.btn-default.disabled.active,\n.btn-default[disabled].active,\nfieldset[disabled] .btn-default.active {\n background-color: #ffffff;\n border-color: #cccccc;\n}\n.btn-default .badge {\n color: #ffffff;\n background-color: #333333;\n}\n.btn-primary {\n color: #ffffff;\n background-color: #337ab7;\n border-color: #2e6da4;\n}\n.btn-primary:hover,\n.btn-primary:focus,\n.btn-primary.focus,\n.btn-primary:active,\n.btn-primary.active,\n.open > .dropdown-toggle.btn-primary {\n color: #ffffff;\n background-color: #286090;\n border-color: #204d74;\n}\n.btn-primary:active,\n.btn-primary.active,\n.open > .dropdown-toggle.btn-primary {\n background-image: none;\n}\n.btn-primary.disabled,\n.btn-primary[disabled],\nfieldset[disabled] .btn-primary,\n.btn-primary.disabled:hover,\n.btn-primary[disabled]:hover,\nfieldset[disabled] .btn-primary:hover,\n.btn-primary.disabled:focus,\n.btn-primary[disabled]:focus,\nfieldset[disabled] .btn-primary:focus,\n.btn-primary.disabled.focus,\n.btn-primary[disabled].focus,\nfieldset[disabled] .btn-primary.focus,\n.btn-primary.disabled:active,\n.btn-primary[disabled]:active,\nfieldset[disabled] .btn-primary:active,\n.btn-primary.disabled.active,\n.btn-primary[disabled].active,\nfieldset[disabled] .btn-primary.active {\n background-color: #337ab7;\n border-color: #2e6da4;\n}\n.btn-primary .badge {\n color: #337ab7;\n background-color: #ffffff;\n}\n.btn-success {\n color: #ffffff;\n background-color: #5cb85c;\n border-color: #4cae4c;\n}\n.btn-success:hover,\n.btn-success:focus,\n.btn-success.focus,\n.btn-success:active,\n.btn-success.active,\n.open > .dropdown-toggle.btn-success {\n color: #ffffff;\n background-color: #449d44;\n border-color: #398439;\n}\n.btn-success:active,\n.btn-success.active,\n.open > .dropdown-toggle.btn-success {\n background-image: none;\n}\n.btn-success.disabled,\n.btn-success[disabled],\nfieldset[disabled] .btn-success,\n.btn-success.disabled:hover,\n.btn-success[disabled]:hover,\nfieldset[disabled] .btn-success:hover,\n.btn-success.disabled:focus,\n.btn-success[disabled]:focus,\nfieldset[disabled] .btn-success:focus,\n.btn-success.disabled.focus,\n.btn-success[disabled].focus,\nfieldset[disabled] .btn-success.focus,\n.btn-success.disabled:active,\n.btn-success[disabled]:active,\nfieldset[disabled] .btn-success:active,\n.btn-success.disabled.active,\n.btn-success[disabled].active,\nfieldset[disabled] .btn-success.active {\n background-color: #5cb85c;\n border-color: #4cae4c;\n}\n.btn-success .badge {\n color: #5cb85c;\n background-color: #ffffff;\n}\n.btn-info {\n color: #ffffff;\n background-color: #5bc0de;\n border-color: #46b8da;\n}\n.btn-info:hover,\n.btn-info:focus,\n.btn-info.focus,\n.btn-info:active,\n.btn-info.active,\n.open > .dropdown-toggle.btn-info {\n color: #ffffff;\n background-color: #31b0d5;\n border-color: #269abc;\n}\n.btn-info:active,\n.btn-info.active,\n.open > .dropdown-toggle.btn-info {\n background-image: none;\n}\n.btn-info.disabled,\n.btn-info[disabled],\nfieldset[disabled] .btn-info,\n.btn-info.disabled:hover,\n.btn-info[disabled]:hover,\nfieldset[disabled] .btn-info:hover,\n.btn-info.disabled:focus,\n.btn-info[disabled]:focus,\nfieldset[disabled] .btn-info:focus,\n.btn-info.disabled.focus,\n.btn-info[disabled].focus,\nfieldset[disabled] .btn-info.focus,\n.btn-info.disabled:active,\n.btn-info[disabled]:active,\nfieldset[disabled] .btn-info:active,\n.btn-info.disabled.active,\n.btn-info[disabled].active,\nfieldset[disabled] .btn-info.active {\n background-color: #5bc0de;\n border-color: #46b8da;\n}\n.btn-info .badge {\n color: #5bc0de;\n background-color: #ffffff;\n}\n.btn-warning {\n color: #ffffff;\n background-color: #f0ad4e;\n border-color: #eea236;\n}\n.btn-warning:hover,\n.btn-warning:focus,\n.btn-warning.focus,\n.btn-warning:active,\n.btn-warning.active,\n.open > .dropdown-toggle.btn-warning {\n color: #ffffff;\n background-color: #ec971f;\n border-color: #d58512;\n}\n.btn-warning:active,\n.btn-warning.active,\n.open > .dropdown-toggle.btn-warning {\n background-image: none;\n}\n.btn-warning.disabled,\n.btn-warning[disabled],\nfieldset[disabled] .btn-warning,\n.btn-warning.disabled:hover,\n.btn-warning[disabled]:hover,\nfieldset[disabled] .btn-warning:hover,\n.btn-warning.disabled:focus,\n.btn-warning[disabled]:focus,\nfieldset[disabled] .btn-warning:focus,\n.btn-warning.disabled.focus,\n.btn-warning[disabled].focus,\nfieldset[disabled] .btn-warning.focus,\n.btn-warning.disabled:active,\n.btn-warning[disabled]:active,\nfieldset[disabled] .btn-warning:active,\n.btn-warning.disabled.active,\n.btn-warning[disabled].active,\nfieldset[disabled] .btn-warning.active {\n background-color: #f0ad4e;\n border-color: #eea236;\n}\n.btn-warning .badge {\n color: #f0ad4e;\n background-color: #ffffff;\n}\n.btn-danger {\n color: #ffffff;\n background-color: #d9534f;\n border-color: #d43f3a;\n}\n.btn-danger:hover,\n.btn-danger:focus,\n.btn-danger.focus,\n.btn-danger:active,\n.btn-danger.active,\n.open > .dropdown-toggle.btn-danger {\n color: #ffffff;\n background-color: #c9302c;\n border-color: #ac2925;\n}\n.btn-danger:active,\n.btn-danger.active,\n.open > .dropdown-toggle.btn-danger {\n background-image: none;\n}\n.btn-danger.disabled,\n.btn-danger[disabled],\nfieldset[disabled] .btn-danger,\n.btn-danger.disabled:hover,\n.btn-danger[disabled]:hover,\nfieldset[disabled] .btn-danger:hover,\n.btn-danger.disabled:focus,\n.btn-danger[disabled]:focus,\nfieldset[disabled] .btn-danger:focus,\n.btn-danger.disabled.focus,\n.btn-danger[disabled].focus,\nfieldset[disabled] .btn-danger.focus,\n.btn-danger.disabled:active,\n.btn-danger[disabled]:active,\nfieldset[disabled] .btn-danger:active,\n.btn-danger.disabled.active,\n.btn-danger[disabled].active,\nfieldset[disabled] .btn-danger.active {\n background-color: #d9534f;\n border-color: #d43f3a;\n}\n.btn-danger .badge {\n color: #d9534f;\n background-color: #ffffff;\n}\n.btn-link {\n color: #337ab7;\n font-weight: normal;\n border-radius: 0;\n}\n.btn-link,\n.btn-link:active,\n.btn-link.active,\n.btn-link[disabled],\nfieldset[disabled] .btn-link {\n background-color: transparent;\n -webkit-box-shadow: none;\n box-shadow: none;\n}\n.btn-link,\n.btn-link:hover,\n.btn-link:focus,\n.btn-link:active {\n border-color: transparent;\n}\n.btn-link:hover,\n.btn-link:focus {\n color: #23527c;\n text-decoration: underline;\n background-color: transparent;\n}\n.btn-link[disabled]:hover,\nfieldset[disabled] .btn-link:hover,\n.btn-link[disabled]:focus,\nfieldset[disabled] .btn-link:focus {\n color: #777777;\n text-decoration: none;\n}\n.btn-lg,\n.btn-group-lg > .btn {\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n border-radius: 6px;\n}\n.btn-sm,\n.btn-group-sm > .btn {\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\n.btn-xs,\n.btn-group-xs > .btn {\n padding: 1px 5px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\n.btn-block {\n display: block;\n width: 100%;\n}\n.btn-block + .btn-block {\n margin-top: 5px;\n}\ninput[type=\"submit\"].btn-block,\ninput[type=\"reset\"].btn-block,\ninput[type=\"button\"].btn-block {\n width: 100%;\n}\n.fade {\n opacity: 0;\n -webkit-transition: opacity 0.15s linear;\n -o-transition: opacity 0.15s linear;\n transition: opacity 0.15s linear;\n}\n.fade.in {\n opacity: 1;\n}\n.collapse {\n display: none;\n}\n.collapse.in {\n display: block;\n}\ntr.collapse.in {\n display: table-row;\n}\ntbody.collapse.in {\n display: table-row-group;\n}\n.collapsing {\n position: relative;\n height: 0;\n overflow: hidden;\n -webkit-transition-property: height, visibility;\n transition-property: height, visibility;\n -webkit-transition-duration: 0.35s;\n transition-duration: 0.35s;\n -webkit-transition-timing-function: ease;\n transition-timing-function: ease;\n}\n.caret {\n display: inline-block;\n width: 0;\n height: 0;\n margin-left: 2px;\n vertical-align: middle;\n border-top: 4px dashed;\n border-right: 4px solid transparent;\n border-left: 4px solid transparent;\n}\n.dropup,\n.dropdown {\n position: relative;\n}\n.dropdown-toggle:focus {\n outline: 0;\n}\n.dropdown-menu {\n position: absolute;\n top: 100%;\n left: 0;\n z-index: 1000;\n display: none;\n float: left;\n min-width: 160px;\n padding: 5px 0;\n margin: 2px 0 0;\n list-style: none;\n font-size: 14px;\n text-align: left;\n background-color: #ffffff;\n border: 1px solid #cccccc;\n border: 1px solid rgba(0, 0, 0, 0.15);\n border-radius: 4px;\n -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);\n box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);\n background-clip: padding-box;\n}\n.dropdown-menu.pull-right {\n right: 0;\n left: auto;\n}\n.dropdown-menu .divider {\n height: 1px;\n margin: 9px 0;\n overflow: hidden;\n background-color: #e5e5e5;\n}\n.dropdown-menu > li > a {\n display: block;\n padding: 3px 20px;\n clear: both;\n font-weight: normal;\n line-height: 1.42857143;\n color: #333333;\n white-space: nowrap;\n}\n.dropdown-menu > li > a:hover,\n.dropdown-menu > li > a:focus {\n text-decoration: none;\n color: #262626;\n background-color: #f5f5f5;\n}\n.dropdown-menu > .active > a,\n.dropdown-menu > .active > a:hover,\n.dropdown-menu > .active > a:focus {\n color: #ffffff;\n text-decoration: none;\n outline: 0;\n background-color: #337ab7;\n}\n.dropdown-menu > .disabled > a,\n.dropdown-menu > .disabled > a:hover,\n.dropdown-menu > .disabled > a:focus {\n color: #777777;\n}\n.dropdown-menu > .disabled > a:hover,\n.dropdown-menu > .disabled > a:focus {\n text-decoration: none;\n background-color: transparent;\n background-image: none;\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n cursor: not-allowed;\n}\n.open > .dropdown-menu {\n display: block;\n}\n.open > a {\n outline: 0;\n}\n.dropdown-menu-right {\n left: auto;\n right: 0;\n}\n.dropdown-menu-left {\n left: 0;\n right: auto;\n}\n.dropdown-header {\n display: block;\n padding: 3px 20px;\n font-size: 12px;\n line-height: 1.42857143;\n color: #777777;\n white-space: nowrap;\n}\n.dropdown-backdrop {\n position: fixed;\n left: 0;\n right: 0;\n bottom: 0;\n top: 0;\n z-index: 990;\n}\n.pull-right > .dropdown-menu {\n right: 0;\n left: auto;\n}\n.dropup .caret,\n.navbar-fixed-bottom .dropdown .caret {\n border-top: 0;\n border-bottom: 4px solid;\n content: \"\";\n}\n.dropup .dropdown-menu,\n.navbar-fixed-bottom .dropdown .dropdown-menu {\n top: auto;\n bottom: 100%;\n margin-bottom: 2px;\n}\n@media (min-width: 768px) {\n .navbar-right .dropdown-menu {\n left: auto;\n right: 0;\n }\n .navbar-right .dropdown-menu-left {\n left: 0;\n right: auto;\n }\n}\n.btn-group,\n.btn-group-vertical {\n position: relative;\n display: inline-block;\n vertical-align: middle;\n}\n.btn-group > .btn,\n.btn-group-vertical > .btn {\n position: relative;\n float: left;\n}\n.btn-group > .btn:hover,\n.btn-group-vertical > .btn:hover,\n.btn-group > .btn:focus,\n.btn-group-vertical > .btn:focus,\n.btn-group > .btn:active,\n.btn-group-vertical > .btn:active,\n.btn-group > .btn.active,\n.btn-group-vertical > .btn.active {\n z-index: 2;\n}\n.btn-group .btn + .btn,\n.btn-group .btn + .btn-group,\n.btn-group .btn-group + .btn,\n.btn-group .btn-group + .btn-group {\n margin-left: -1px;\n}\n.btn-toolbar {\n margin-left: -5px;\n}\n.btn-toolbar .btn-group,\n.btn-toolbar .input-group {\n float: left;\n}\n.btn-toolbar > .btn,\n.btn-toolbar > .btn-group,\n.btn-toolbar > .input-group {\n margin-left: 5px;\n}\n.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) {\n border-radius: 0;\n}\n.btn-group > .btn:first-child {\n margin-left: 0;\n}\n.btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) {\n border-bottom-right-radius: 0;\n border-top-right-radius: 0;\n}\n.btn-group > .btn:last-child:not(:first-child),\n.btn-group > .dropdown-toggle:not(:first-child) {\n border-bottom-left-radius: 0;\n border-top-left-radius: 0;\n}\n.btn-group > .btn-group {\n float: left;\n}\n.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn {\n border-radius: 0;\n}\n.btn-group > .btn-group:first-child:not(:last-child) > .btn:last-child,\n.btn-group > .btn-group:first-child:not(:last-child) > .dropdown-toggle {\n border-bottom-right-radius: 0;\n border-top-right-radius: 0;\n}\n.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child {\n border-bottom-left-radius: 0;\n border-top-left-radius: 0;\n}\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n outline: 0;\n}\n.btn-group > .btn + .dropdown-toggle {\n padding-left: 8px;\n padding-right: 8px;\n}\n.btn-group > .btn-lg + .dropdown-toggle {\n padding-left: 12px;\n padding-right: 12px;\n}\n.btn-group.open .dropdown-toggle {\n -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n}\n.btn-group.open .dropdown-toggle.btn-link {\n -webkit-box-shadow: none;\n box-shadow: none;\n}\n.btn .caret {\n margin-left: 0;\n}\n.btn-lg .caret {\n border-width: 5px 5px 0;\n border-bottom-width: 0;\n}\n.dropup .btn-lg .caret {\n border-width: 0 5px 5px;\n}\n.btn-group-vertical > .btn,\n.btn-group-vertical > .btn-group,\n.btn-group-vertical > .btn-group > .btn {\n display: block;\n float: none;\n width: 100%;\n max-width: 100%;\n}\n.btn-group-vertical > .btn-group > .btn {\n float: none;\n}\n.btn-group-vertical > .btn + .btn,\n.btn-group-vertical > .btn + .btn-group,\n.btn-group-vertical > .btn-group + .btn,\n.btn-group-vertical > .btn-group + .btn-group {\n margin-top: -1px;\n margin-left: 0;\n}\n.btn-group-vertical > .btn:not(:first-child):not(:last-child) {\n border-radius: 0;\n}\n.btn-group-vertical > .btn:first-child:not(:last-child) {\n border-top-right-radius: 4px;\n border-bottom-right-radius: 0;\n border-bottom-left-radius: 0;\n}\n.btn-group-vertical > .btn:last-child:not(:first-child) {\n border-bottom-left-radius: 4px;\n border-top-right-radius: 0;\n border-top-left-radius: 0;\n}\n.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn {\n border-radius: 0;\n}\n.btn-group-vertical > .btn-group:first-child:not(:last-child) > .btn:last-child,\n.btn-group-vertical > .btn-group:first-child:not(:last-child) > .dropdown-toggle {\n border-bottom-right-radius: 0;\n border-bottom-left-radius: 0;\n}\n.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child {\n border-top-right-radius: 0;\n border-top-left-radius: 0;\n}\n.btn-group-justified {\n display: table;\n width: 100%;\n table-layout: fixed;\n border-collapse: separate;\n}\n.btn-group-justified > .btn,\n.btn-group-justified > .btn-group {\n float: none;\n display: table-cell;\n width: 1%;\n}\n.btn-group-justified > .btn-group .btn {\n width: 100%;\n}\n.btn-group-justified > .btn-group .dropdown-menu {\n left: auto;\n}\n[data-toggle=\"buttons\"] > .btn input[type=\"radio\"],\n[data-toggle=\"buttons\"] > .btn-group > .btn input[type=\"radio\"],\n[data-toggle=\"buttons\"] > .btn input[type=\"checkbox\"],\n[data-toggle=\"buttons\"] > .btn-group > .btn input[type=\"checkbox\"] {\n position: absolute;\n clip: rect(0, 0, 0, 0);\n pointer-events: none;\n}\n.input-group {\n position: relative;\n display: table;\n border-collapse: separate;\n}\n.input-group[class*=\"col-\"] {\n float: none;\n padding-left: 0;\n padding-right: 0;\n}\n.input-group .form-control {\n position: relative;\n z-index: 2;\n float: left;\n width: 100%;\n margin-bottom: 0;\n}\n.input-group-lg > .form-control,\n.input-group-lg > .input-group-addon,\n.input-group-lg > .input-group-btn > .btn {\n height: 46px;\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n border-radius: 6px;\n}\nselect.input-group-lg > .form-control,\nselect.input-group-lg > .input-group-addon,\nselect.input-group-lg > .input-group-btn > .btn {\n height: 46px;\n line-height: 46px;\n}\ntextarea.input-group-lg > .form-control,\ntextarea.input-group-lg > .input-group-addon,\ntextarea.input-group-lg > .input-group-btn > .btn,\nselect[multiple].input-group-lg > .form-control,\nselect[multiple].input-group-lg > .input-group-addon,\nselect[multiple].input-group-lg > .input-group-btn > .btn {\n height: auto;\n}\n.input-group-sm > .form-control,\n.input-group-sm > .input-group-addon,\n.input-group-sm > .input-group-btn > .btn {\n height: 30px;\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\nselect.input-group-sm > .form-control,\nselect.input-group-sm > .input-group-addon,\nselect.input-group-sm > .input-group-btn > .btn {\n height: 30px;\n line-height: 30px;\n}\ntextarea.input-group-sm > .form-control,\ntextarea.input-group-sm > .input-group-addon,\ntextarea.input-group-sm > .input-group-btn > .btn,\nselect[multiple].input-group-sm > .form-control,\nselect[multiple].input-group-sm > .input-group-addon,\nselect[multiple].input-group-sm > .input-group-btn > .btn {\n height: auto;\n}\n.input-group-addon,\n.input-group-btn,\n.input-group .form-control {\n display: table-cell;\n}\n.input-group-addon:not(:first-child):not(:last-child),\n.input-group-btn:not(:first-child):not(:last-child),\n.input-group .form-control:not(:first-child):not(:last-child) {\n border-radius: 0;\n}\n.input-group-addon,\n.input-group-btn {\n width: 1%;\n white-space: nowrap;\n vertical-align: middle;\n}\n.input-group-addon {\n padding: 6px 12px;\n font-size: 14px;\n font-weight: normal;\n line-height: 1;\n color: #555555;\n text-align: center;\n background-color: #eeeeee;\n border: 1px solid #cccccc;\n border-radius: 4px;\n}\n.input-group-addon.input-sm {\n padding: 5px 10px;\n font-size: 12px;\n border-radius: 3px;\n}\n.input-group-addon.input-lg {\n padding: 10px 16px;\n font-size: 18px;\n border-radius: 6px;\n}\n.input-group-addon input[type=\"radio\"],\n.input-group-addon input[type=\"checkbox\"] {\n margin-top: 0;\n}\n.input-group .form-control:first-child,\n.input-group-addon:first-child,\n.input-group-btn:first-child > .btn,\n.input-group-btn:first-child > .btn-group > .btn,\n.input-group-btn:first-child > .dropdown-toggle,\n.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle),\n.input-group-btn:last-child > .btn-group:not(:last-child) > .btn {\n border-bottom-right-radius: 0;\n border-top-right-radius: 0;\n}\n.input-group-addon:first-child {\n border-right: 0;\n}\n.input-group .form-control:last-child,\n.input-group-addon:last-child,\n.input-group-btn:last-child > .btn,\n.input-group-btn:last-child > .btn-group > .btn,\n.input-group-btn:last-child > .dropdown-toggle,\n.input-group-btn:first-child > .btn:not(:first-child),\n.input-group-btn:first-child > .btn-group:not(:first-child) > .btn {\n border-bottom-left-radius: 0;\n border-top-left-radius: 0;\n}\n.input-group-addon:last-child {\n border-left: 0;\n}\n.input-group-btn {\n position: relative;\n font-size: 0;\n white-space: nowrap;\n}\n.input-group-btn > .btn {\n position: relative;\n}\n.input-group-btn > .btn + .btn {\n margin-left: -1px;\n}\n.input-group-btn > .btn:hover,\n.input-group-btn > .btn:focus,\n.input-group-btn > .btn:active {\n z-index: 2;\n}\n.input-group-btn:first-child > .btn,\n.input-group-btn:first-child > .btn-group {\n margin-right: -1px;\n}\n.input-group-btn:last-child > .btn,\n.input-group-btn:last-child > .btn-group {\n margin-left: -1px;\n}\n.nav {\n margin-bottom: 0;\n padding-left: 0;\n list-style: none;\n}\n.nav > li {\n position: relative;\n display: block;\n}\n.nav > li > a {\n position: relative;\n display: block;\n padding: 10px 15px;\n}\n.nav > li > a:hover,\n.nav > li > a:focus {\n text-decoration: none;\n background-color: #eeeeee;\n}\n.nav > li.disabled > a {\n color: #777777;\n}\n.nav > li.disabled > a:hover,\n.nav > li.disabled > a:focus {\n color: #777777;\n text-decoration: none;\n background-color: transparent;\n cursor: not-allowed;\n}\n.nav .open > a,\n.nav .open > a:hover,\n.nav .open > a:focus {\n background-color: #eeeeee;\n border-color: #337ab7;\n}\n.nav .nav-divider {\n height: 1px;\n margin: 9px 0;\n overflow: hidden;\n background-color: #e5e5e5;\n}\n.nav > li > a > img {\n max-width: none;\n}\n.nav-tabs {\n border-bottom: 1px solid #dddddd;\n}\n.nav-tabs > li {\n float: left;\n margin-bottom: -1px;\n}\n.nav-tabs > li > a {\n margin-right: 2px;\n line-height: 1.42857143;\n border: 1px solid transparent;\n border-radius: 4px 4px 0 0;\n}\n.nav-tabs > li > a:hover {\n border-color: #eeeeee #eeeeee #dddddd;\n}\n.nav-tabs > li.active > a,\n.nav-tabs > li.active > a:hover,\n.nav-tabs > li.active > a:focus {\n color: #555555;\n background-color: #ffffff;\n border: 1px solid #dddddd;\n border-bottom-color: transparent;\n cursor: default;\n}\n.nav-tabs.nav-justified {\n width: 100%;\n border-bottom: 0;\n}\n.nav-tabs.nav-justified > li {\n float: none;\n}\n.nav-tabs.nav-justified > li > a {\n text-align: center;\n margin-bottom: 5px;\n}\n.nav-tabs.nav-justified > .dropdown .dropdown-menu {\n top: auto;\n left: auto;\n}\n@media (min-width: 768px) {\n .nav-tabs.nav-justified > li {\n display: table-cell;\n width: 1%;\n }\n .nav-tabs.nav-justified > li > a {\n margin-bottom: 0;\n }\n}\n.nav-tabs.nav-justified > li > a {\n margin-right: 0;\n border-radius: 4px;\n}\n.nav-tabs.nav-justified > .active > a,\n.nav-tabs.nav-justified > .active > a:hover,\n.nav-tabs.nav-justified > .active > a:focus {\n border: 1px solid #dddddd;\n}\n@media (min-width: 768px) {\n .nav-tabs.nav-justified > li > a {\n border-bottom: 1px solid #dddddd;\n border-radius: 4px 4px 0 0;\n }\n .nav-tabs.nav-justified > .active > a,\n .nav-tabs.nav-justified > .active > a:hover,\n .nav-tabs.nav-justified > .active > a:focus {\n border-bottom-color: #ffffff;\n }\n}\n.nav-pills > li {\n float: left;\n}\n.nav-pills > li > a {\n border-radius: 4px;\n}\n.nav-pills > li + li {\n margin-left: 2px;\n}\n.nav-pills > li.active > a,\n.nav-pills > li.active > a:hover,\n.nav-pills > li.active > a:focus {\n color: #ffffff;\n background-color: #337ab7;\n}\n.nav-stacked > li {\n float: none;\n}\n.nav-stacked > li + li {\n margin-top: 2px;\n margin-left: 0;\n}\n.nav-justified {\n width: 100%;\n}\n.nav-justified > li {\n float: none;\n}\n.nav-justified > li > a {\n text-align: center;\n margin-bottom: 5px;\n}\n.nav-justified > .dropdown .dropdown-menu {\n top: auto;\n left: auto;\n}\n@media (min-width: 768px) {\n .nav-justified > li {\n display: table-cell;\n width: 1%;\n }\n .nav-justified > li > a {\n margin-bottom: 0;\n }\n}\n.nav-tabs-justified {\n border-bottom: 0;\n}\n.nav-tabs-justified > li > a {\n margin-right: 0;\n border-radius: 4px;\n}\n.nav-tabs-justified > .active > a,\n.nav-tabs-justified > .active > a:hover,\n.nav-tabs-justified > .active > a:focus {\n border: 1px solid #dddddd;\n}\n@media (min-width: 768px) {\n .nav-tabs-justified > li > a {\n border-bottom: 1px solid #dddddd;\n border-radius: 4px 4px 0 0;\n }\n .nav-tabs-justified > .active > a,\n .nav-tabs-justified > .active > a:hover,\n .nav-tabs-justified > .active > a:focus {\n border-bottom-color: #ffffff;\n }\n}\n.tab-content > .tab-pane {\n display: none;\n}\n.tab-content > .active {\n display: block;\n}\n.nav-tabs .dropdown-menu {\n margin-top: -1px;\n border-top-right-radius: 0;\n border-top-left-radius: 0;\n}\n.navbar {\n position: relative;\n min-height: 50px;\n margin-bottom: 20px;\n border: 1px solid transparent;\n}\n@media (min-width: 768px) {\n .navbar {\n border-radius: 4px;\n }\n}\n@media (min-width: 768px) {\n .navbar-header {\n float: left;\n }\n}\n.navbar-collapse {\n overflow-x: visible;\n padding-right: 15px;\n padding-left: 15px;\n border-top: 1px solid transparent;\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1);\n -webkit-overflow-scrolling: touch;\n}\n.navbar-collapse.in {\n overflow-y: auto;\n}\n@media (min-width: 768px) {\n .navbar-collapse {\n width: auto;\n border-top: 0;\n box-shadow: none;\n }\n .navbar-collapse.collapse {\n display: block !important;\n height: auto !important;\n padding-bottom: 0;\n overflow: visible !important;\n }\n .navbar-collapse.in {\n overflow-y: visible;\n }\n .navbar-fixed-top .navbar-collapse,\n .navbar-static-top .navbar-collapse,\n .navbar-fixed-bottom .navbar-collapse {\n padding-left: 0;\n padding-right: 0;\n }\n}\n.navbar-fixed-top .navbar-collapse,\n.navbar-fixed-bottom .navbar-collapse {\n max-height: 340px;\n}\n@media (max-device-width: 480px) and (orientation: landscape) {\n .navbar-fixed-top .navbar-collapse,\n .navbar-fixed-bottom .navbar-collapse {\n max-height: 200px;\n }\n}\n.container > .navbar-header,\n.container-fluid > .navbar-header,\n.container > .navbar-collapse,\n.container-fluid > .navbar-collapse {\n margin-right: -15px;\n margin-left: -15px;\n}\n@media (min-width: 768px) {\n .container > .navbar-header,\n .container-fluid > .navbar-header,\n .container > .navbar-collapse,\n .container-fluid > .navbar-collapse {\n margin-right: 0;\n margin-left: 0;\n }\n}\n.navbar-static-top {\n z-index: 1000;\n border-width: 0 0 1px;\n}\n@media (min-width: 768px) {\n .navbar-static-top {\n border-radius: 0;\n }\n}\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n position: fixed;\n right: 0;\n left: 0;\n z-index: 1030;\n}\n@media (min-width: 768px) {\n .navbar-fixed-top,\n .navbar-fixed-bottom {\n border-radius: 0;\n }\n}\n.navbar-fixed-top {\n top: 0;\n border-width: 0 0 1px;\n}\n.navbar-fixed-bottom {\n bottom: 0;\n margin-bottom: 0;\n border-width: 1px 0 0;\n}\n.navbar-brand {\n float: left;\n padding: 15px 15px;\n font-size: 18px;\n line-height: 20px;\n height: 50px;\n}\n.navbar-brand:hover,\n.navbar-brand:focus {\n text-decoration: none;\n}\n.navbar-brand > img {\n display: block;\n}\n@media (min-width: 768px) {\n .navbar > .container .navbar-brand,\n .navbar > .container-fluid .navbar-brand {\n margin-left: -15px;\n }\n}\n.navbar-toggle {\n position: relative;\n float: right;\n margin-right: 15px;\n padding: 9px 10px;\n margin-top: 8px;\n margin-bottom: 8px;\n background-color: transparent;\n background-image: none;\n border: 1px solid transparent;\n border-radius: 4px;\n}\n.navbar-toggle:focus {\n outline: 0;\n}\n.navbar-toggle .icon-bar {\n display: block;\n width: 22px;\n height: 2px;\n border-radius: 1px;\n}\n.navbar-toggle .icon-bar + .icon-bar {\n margin-top: 4px;\n}\n@media (min-width: 768px) {\n .navbar-toggle {\n display: none;\n }\n}\n.navbar-nav {\n margin: 7.5px -15px;\n}\n.navbar-nav > li > a {\n padding-top: 10px;\n padding-bottom: 10px;\n line-height: 20px;\n}\n@media (max-width: 767px) {\n .navbar-nav .open .dropdown-menu {\n position: static;\n float: none;\n width: auto;\n margin-top: 0;\n background-color: transparent;\n border: 0;\n box-shadow: none;\n }\n .navbar-nav .open .dropdown-menu > li > a,\n .navbar-nav .open .dropdown-menu .dropdown-header {\n padding: 5px 15px 5px 25px;\n }\n .navbar-nav .open .dropdown-menu > li > a {\n line-height: 20px;\n }\n .navbar-nav .open .dropdown-menu > li > a:hover,\n .navbar-nav .open .dropdown-menu > li > a:focus {\n background-image: none;\n }\n}\n@media (min-width: 768px) {\n .navbar-nav {\n float: left;\n margin: 0;\n }\n .navbar-nav > li {\n float: left;\n }\n .navbar-nav > li > a {\n padding-top: 15px;\n padding-bottom: 15px;\n }\n}\n.navbar-form {\n margin-left: -15px;\n margin-right: -15px;\n padding: 10px 15px;\n border-top: 1px solid transparent;\n border-bottom: 1px solid transparent;\n -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);\n margin-top: 8px;\n margin-bottom: 8px;\n}\n@media (min-width: 768px) {\n .navbar-form .form-group {\n display: inline-block;\n margin-bottom: 0;\n vertical-align: middle;\n }\n .navbar-form .form-control {\n display: inline-block;\n width: auto;\n vertical-align: middle;\n }\n .navbar-form .form-control-static {\n display: inline-block;\n }\n .navbar-form .input-group {\n display: inline-table;\n vertical-align: middle;\n }\n .navbar-form .input-group .input-group-addon,\n .navbar-form .input-group .input-group-btn,\n .navbar-form .input-group .form-control {\n width: auto;\n }\n .navbar-form .input-group > .form-control {\n width: 100%;\n }\n .navbar-form .control-label {\n margin-bottom: 0;\n vertical-align: middle;\n }\n .navbar-form .radio,\n .navbar-form .checkbox {\n display: inline-block;\n margin-top: 0;\n margin-bottom: 0;\n vertical-align: middle;\n }\n .navbar-form .radio label,\n .navbar-form .checkbox label {\n padding-left: 0;\n }\n .navbar-form .radio input[type=\"radio\"],\n .navbar-form .checkbox input[type=\"checkbox\"] {\n position: relative;\n margin-left: 0;\n }\n .navbar-form .has-feedback .form-control-feedback {\n top: 0;\n }\n}\n@media (max-width: 767px) {\n .navbar-form .form-group {\n margin-bottom: 5px;\n }\n .navbar-form .form-group:last-child {\n margin-bottom: 0;\n }\n}\n@media (min-width: 768px) {\n .navbar-form {\n width: auto;\n border: 0;\n margin-left: 0;\n margin-right: 0;\n padding-top: 0;\n padding-bottom: 0;\n -webkit-box-shadow: none;\n box-shadow: none;\n }\n}\n.navbar-nav > li > .dropdown-menu {\n margin-top: 0;\n border-top-right-radius: 0;\n border-top-left-radius: 0;\n}\n.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu {\n margin-bottom: 0;\n border-top-right-radius: 4px;\n border-top-left-radius: 4px;\n border-bottom-right-radius: 0;\n border-bottom-left-radius: 0;\n}\n.navbar-btn {\n margin-top: 8px;\n margin-bottom: 8px;\n}\n.navbar-btn.btn-sm {\n margin-top: 10px;\n margin-bottom: 10px;\n}\n.navbar-btn.btn-xs {\n margin-top: 14px;\n margin-bottom: 14px;\n}\n.navbar-text {\n margin-top: 15px;\n margin-bottom: 15px;\n}\n@media (min-width: 768px) {\n .navbar-text {\n float: left;\n margin-left: 15px;\n margin-right: 15px;\n }\n}\n@media (min-width: 768px) {\n .navbar-left {\n float: left !important;\n }\n .navbar-right {\n float: right !important;\n margin-right: -15px;\n }\n .navbar-right ~ .navbar-right {\n margin-right: 0;\n }\n}\n.navbar-default {\n background-color: #f8f8f8;\n border-color: #e7e7e7;\n}\n.navbar-default .navbar-brand {\n color: #777777;\n}\n.navbar-default .navbar-brand:hover,\n.navbar-default .navbar-brand:focus {\n color: #5e5e5e;\n background-color: transparent;\n}\n.navbar-default .navbar-text {\n color: #777777;\n}\n.navbar-default .navbar-nav > li > a {\n color: #777777;\n}\n.navbar-default .navbar-nav > li > a:hover,\n.navbar-default .navbar-nav > li > a:focus {\n color: #333333;\n background-color: transparent;\n}\n.navbar-default .navbar-nav > .active > a,\n.navbar-default .navbar-nav > .active > a:hover,\n.navbar-default .navbar-nav > .active > a:focus {\n color: #555555;\n background-color: #e7e7e7;\n}\n.navbar-default .navbar-nav > .disabled > a,\n.navbar-default .navbar-nav > .disabled > a:hover,\n.navbar-default .navbar-nav > .disabled > a:focus {\n color: #cccccc;\n background-color: transparent;\n}\n.navbar-default .navbar-toggle {\n border-color: #dddddd;\n}\n.navbar-default .navbar-toggle:hover,\n.navbar-default .navbar-toggle:focus {\n background-color: #dddddd;\n}\n.navbar-default .navbar-toggle .icon-bar {\n background-color: #888888;\n}\n.navbar-default .navbar-collapse,\n.navbar-default .navbar-form {\n border-color: #e7e7e7;\n}\n.navbar-default .navbar-nav > .open > a,\n.navbar-default .navbar-nav > .open > a:hover,\n.navbar-default .navbar-nav > .open > a:focus {\n background-color: #e7e7e7;\n color: #555555;\n}\n@media (max-width: 767px) {\n .navbar-default .navbar-nav .open .dropdown-menu > li > a {\n color: #777777;\n }\n .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover,\n .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus {\n color: #333333;\n background-color: transparent;\n }\n .navbar-default .navbar-nav .open .dropdown-menu > .active > a,\n .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover,\n .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus {\n color: #555555;\n background-color: #e7e7e7;\n }\n .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a,\n .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover,\n .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:focus {\n color: #cccccc;\n background-color: transparent;\n }\n}\n.navbar-default .navbar-link {\n color: #777777;\n}\n.navbar-default .navbar-link:hover {\n color: #333333;\n}\n.navbar-default .btn-link {\n color: #777777;\n}\n.navbar-default .btn-link:hover,\n.navbar-default .btn-link:focus {\n color: #333333;\n}\n.navbar-default .btn-link[disabled]:hover,\nfieldset[disabled] .navbar-default .btn-link:hover,\n.navbar-default .btn-link[disabled]:focus,\nfieldset[disabled] .navbar-default .btn-link:focus {\n color: #cccccc;\n}\n.navbar-inverse {\n background-color: #222222;\n border-color: #080808;\n}\n.navbar-inverse .navbar-brand {\n color: #9d9d9d;\n}\n.navbar-inverse .navbar-brand:hover,\n.navbar-inverse .navbar-brand:focus {\n color: #ffffff;\n background-color: transparent;\n}\n.navbar-inverse .navbar-text {\n color: #9d9d9d;\n}\n.navbar-inverse .navbar-nav > li > a {\n color: #9d9d9d;\n}\n.navbar-inverse .navbar-nav > li > a:hover,\n.navbar-inverse .navbar-nav > li > a:focus {\n color: #ffffff;\n background-color: transparent;\n}\n.navbar-inverse .navbar-nav > .active > a,\n.navbar-inverse .navbar-nav > .active > a:hover,\n.navbar-inverse .navbar-nav > .active > a:focus {\n color: #ffffff;\n background-color: #080808;\n}\n.navbar-inverse .navbar-nav > .disabled > a,\n.navbar-inverse .navbar-nav > .disabled > a:hover,\n.navbar-inverse .navbar-nav > .disabled > a:focus {\n color: #444444;\n background-color: transparent;\n}\n.navbar-inverse .navbar-toggle {\n border-color: #333333;\n}\n.navbar-inverse .navbar-toggle:hover,\n.navbar-inverse .navbar-toggle:focus {\n background-color: #333333;\n}\n.navbar-inverse .navbar-toggle .icon-bar {\n background-color: #ffffff;\n}\n.navbar-inverse .navbar-collapse,\n.navbar-inverse .navbar-form {\n border-color: #101010;\n}\n.navbar-inverse .navbar-nav > .open > a,\n.navbar-inverse .navbar-nav > .open > a:hover,\n.navbar-inverse .navbar-nav > .open > a:focus {\n background-color: #080808;\n color: #ffffff;\n}\n@media (max-width: 767px) {\n .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header {\n border-color: #080808;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu .divider {\n background-color: #080808;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu > li > a {\n color: #9d9d9d;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover,\n .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus {\n color: #ffffff;\n background-color: transparent;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a,\n .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover,\n .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus {\n color: #ffffff;\n background-color: #080808;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a,\n .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:hover,\n .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:focus {\n color: #444444;\n background-color: transparent;\n }\n}\n.navbar-inverse .navbar-link {\n color: #9d9d9d;\n}\n.navbar-inverse .navbar-link:hover {\n color: #ffffff;\n}\n.navbar-inverse .btn-link {\n color: #9d9d9d;\n}\n.navbar-inverse .btn-link:hover,\n.navbar-inverse .btn-link:focus {\n color: #ffffff;\n}\n.navbar-inverse .btn-link[disabled]:hover,\nfieldset[disabled] .navbar-inverse .btn-link:hover,\n.navbar-inverse .btn-link[disabled]:focus,\nfieldset[disabled] .navbar-inverse .btn-link:focus {\n color: #444444;\n}\n.breadcrumb {\n padding: 8px 15px;\n margin-bottom: 20px;\n list-style: none;\n background-color: #f5f5f5;\n border-radius: 4px;\n}\n.breadcrumb > li {\n display: inline-block;\n}\n.breadcrumb > li + li:before {\n content: \"/\\00a0\";\n padding: 0 5px;\n color: #cccccc;\n}\n.breadcrumb > .active {\n color: #777777;\n}\n.pagination {\n display: inline-block;\n padding-left: 0;\n margin: 20px 0;\n border-radius: 4px;\n}\n.pagination > li {\n display: inline;\n}\n.pagination > li > a,\n.pagination > li > span {\n position: relative;\n float: left;\n padding: 6px 12px;\n line-height: 1.42857143;\n text-decoration: none;\n color: #337ab7;\n background-color: #ffffff;\n border: 1px solid #dddddd;\n margin-left: -1px;\n}\n.pagination > li:first-child > a,\n.pagination > li:first-child > span {\n margin-left: 0;\n border-bottom-left-radius: 4px;\n border-top-left-radius: 4px;\n}\n.pagination > li:last-child > a,\n.pagination > li:last-child > span {\n border-bottom-right-radius: 4px;\n border-top-right-radius: 4px;\n}\n.pagination > li > a:hover,\n.pagination > li > span:hover,\n.pagination > li > a:focus,\n.pagination > li > span:focus {\n color: #23527c;\n background-color: #eeeeee;\n border-color: #dddddd;\n}\n.pagination > .active > a,\n.pagination > .active > span,\n.pagination > .active > a:hover,\n.pagination > .active > span:hover,\n.pagination > .active > a:focus,\n.pagination > .active > span:focus {\n z-index: 2;\n color: #ffffff;\n background-color: #337ab7;\n border-color: #337ab7;\n cursor: default;\n}\n.pagination > .disabled > span,\n.pagination > .disabled > span:hover,\n.pagination > .disabled > span:focus,\n.pagination > .disabled > a,\n.pagination > .disabled > a:hover,\n.pagination > .disabled > a:focus {\n color: #777777;\n background-color: #ffffff;\n border-color: #dddddd;\n cursor: not-allowed;\n}\n.pagination-lg > li > a,\n.pagination-lg > li > span {\n padding: 10px 16px;\n font-size: 18px;\n}\n.pagination-lg > li:first-child > a,\n.pagination-lg > li:first-child > span {\n border-bottom-left-radius: 6px;\n border-top-left-radius: 6px;\n}\n.pagination-lg > li:last-child > a,\n.pagination-lg > li:last-child > span {\n border-bottom-right-radius: 6px;\n border-top-right-radius: 6px;\n}\n.pagination-sm > li > a,\n.pagination-sm > li > span {\n padding: 5px 10px;\n font-size: 12px;\n}\n.pagination-sm > li:first-child > a,\n.pagination-sm > li:first-child > span {\n border-bottom-left-radius: 3px;\n border-top-left-radius: 3px;\n}\n.pagination-sm > li:last-child > a,\n.pagination-sm > li:last-child > span {\n border-bottom-right-radius: 3px;\n border-top-right-radius: 3px;\n}\n.pager {\n padding-left: 0;\n margin: 20px 0;\n list-style: none;\n text-align: center;\n}\n.pager li {\n display: inline;\n}\n.pager li > a,\n.pager li > span {\n display: inline-block;\n padding: 5px 14px;\n background-color: #ffffff;\n border: 1px solid #dddddd;\n border-radius: 15px;\n}\n.pager li > a:hover,\n.pager li > a:focus {\n text-decoration: none;\n background-color: #eeeeee;\n}\n.pager .next > a,\n.pager .next > span {\n float: right;\n}\n.pager .previous > a,\n.pager .previous > span {\n float: left;\n}\n.pager .disabled > a,\n.pager .disabled > a:hover,\n.pager .disabled > a:focus,\n.pager .disabled > span {\n color: #777777;\n background-color: #ffffff;\n cursor: not-allowed;\n}\n.label {\n display: inline;\n padding: .2em .6em .3em;\n font-size: 75%;\n font-weight: bold;\n line-height: 1;\n color: #ffffff;\n text-align: center;\n white-space: nowrap;\n vertical-align: baseline;\n border-radius: .25em;\n}\na.label:hover,\na.label:focus {\n color: #ffffff;\n text-decoration: none;\n cursor: pointer;\n}\n.label:empty {\n display: none;\n}\n.btn .label {\n position: relative;\n top: -1px;\n}\n.label-default {\n background-color: #777777;\n}\n.label-default[href]:hover,\n.label-default[href]:focus {\n background-color: #5e5e5e;\n}\n.label-primary {\n background-color: #337ab7;\n}\n.label-primary[href]:hover,\n.label-primary[href]:focus {\n background-color: #286090;\n}\n.label-success {\n background-color: #5cb85c;\n}\n.label-success[href]:hover,\n.label-success[href]:focus {\n background-color: #449d44;\n}\n.label-info {\n background-color: #5bc0de;\n}\n.label-info[href]:hover,\n.label-info[href]:focus {\n background-color: #31b0d5;\n}\n.label-warning {\n background-color: #f0ad4e;\n}\n.label-warning[href]:hover,\n.label-warning[href]:focus {\n background-color: #ec971f;\n}\n.label-danger {\n background-color: #d9534f;\n}\n.label-danger[href]:hover,\n.label-danger[href]:focus {\n background-color: #c9302c;\n}\n.badge {\n display: inline-block;\n min-width: 10px;\n padding: 3px 7px;\n font-size: 12px;\n font-weight: bold;\n color: #ffffff;\n line-height: 1;\n vertical-align: baseline;\n white-space: nowrap;\n text-align: center;\n background-color: #777777;\n border-radius: 10px;\n}\n.badge:empty {\n display: none;\n}\n.btn .badge {\n position: relative;\n top: -1px;\n}\n.btn-xs .badge,\n.btn-group-xs > .btn .badge {\n top: 0;\n padding: 1px 5px;\n}\na.badge:hover,\na.badge:focus {\n color: #ffffff;\n text-decoration: none;\n cursor: pointer;\n}\n.list-group-item.active > .badge,\n.nav-pills > .active > a > .badge {\n color: #337ab7;\n background-color: #ffffff;\n}\n.list-group-item > .badge {\n float: right;\n}\n.list-group-item > .badge + .badge {\n margin-right: 5px;\n}\n.nav-pills > li > a > .badge {\n margin-left: 3px;\n}\n.jumbotron {\n padding: 30px 15px;\n margin-bottom: 30px;\n color: inherit;\n background-color: #eeeeee;\n}\n.jumbotron h1,\n.jumbotron .h1 {\n color: inherit;\n}\n.jumbotron p {\n margin-bottom: 15px;\n font-size: 21px;\n font-weight: 200;\n}\n.jumbotron > hr {\n border-top-color: #d5d5d5;\n}\n.container .jumbotron,\n.container-fluid .jumbotron {\n border-radius: 6px;\n}\n.jumbotron .container {\n max-width: 100%;\n}\n@media screen and (min-width: 768px) {\n .jumbotron {\n padding: 48px 0;\n }\n .container .jumbotron,\n .container-fluid .jumbotron {\n padding-left: 60px;\n padding-right: 60px;\n }\n .jumbotron h1,\n .jumbotron .h1 {\n font-size: 63px;\n }\n}\n.thumbnail {\n display: block;\n padding: 4px;\n margin-bottom: 20px;\n line-height: 1.42857143;\n background-color: #ffffff;\n border: 1px solid #dddddd;\n border-radius: 4px;\n -webkit-transition: border 0.2s ease-in-out;\n -o-transition: border 0.2s ease-in-out;\n transition: border 0.2s ease-in-out;\n}\n.thumbnail > img,\n.thumbnail a > img {\n margin-left: auto;\n margin-right: auto;\n}\na.thumbnail:hover,\na.thumbnail:focus,\na.thumbnail.active {\n border-color: #337ab7;\n}\n.thumbnail .caption {\n padding: 9px;\n color: #333333;\n}\n.alert {\n padding: 15px;\n margin-bottom: 20px;\n border: 1px solid transparent;\n border-radius: 4px;\n}\n.alert h4 {\n margin-top: 0;\n color: inherit;\n}\n.alert .alert-link {\n font-weight: bold;\n}\n.alert > p,\n.alert > ul {\n margin-bottom: 0;\n}\n.alert > p + p {\n margin-top: 5px;\n}\n.alert-dismissable,\n.alert-dismissible {\n padding-right: 35px;\n}\n.alert-dismissable .close,\n.alert-dismissible .close {\n position: relative;\n top: -2px;\n right: -21px;\n color: inherit;\n}\n.alert-success {\n background-color: #dff0d8;\n border-color: #d6e9c6;\n color: #3c763d;\n}\n.alert-success hr {\n border-top-color: #c9e2b3;\n}\n.alert-success .alert-link {\n color: #2b542c;\n}\n.alert-info {\n background-color: #d9edf7;\n border-color: #bce8f1;\n color: #31708f;\n}\n.alert-info hr {\n border-top-color: #a6e1ec;\n}\n.alert-info .alert-link {\n color: #245269;\n}\n.alert-warning {\n background-color: #fcf8e3;\n border-color: #faebcc;\n color: #8a6d3b;\n}\n.alert-warning hr {\n border-top-color: #f7e1b5;\n}\n.alert-warning .alert-link {\n color: #66512c;\n}\n.alert-danger {\n background-color: #f2dede;\n border-color: #ebccd1;\n color: #a94442;\n}\n.alert-danger hr {\n border-top-color: #e4b9c0;\n}\n.alert-danger .alert-link {\n color: #843534;\n}\n@-webkit-keyframes progress-bar-stripes {\n from {\n background-position: 40px 0;\n }\n to {\n background-position: 0 0;\n }\n}\n@keyframes progress-bar-stripes {\n from {\n background-position: 40px 0;\n }\n to {\n background-position: 0 0;\n }\n}\n.progress {\n overflow: hidden;\n height: 20px;\n margin-bottom: 20px;\n background-color: #f5f5f5;\n border-radius: 4px;\n -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n}\n.progress-bar {\n float: left;\n width: 0%;\n height: 100%;\n font-size: 12px;\n line-height: 20px;\n color: #ffffff;\n text-align: center;\n background-color: #337ab7;\n -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n -webkit-transition: width 0.6s ease;\n -o-transition: width 0.6s ease;\n transition: width 0.6s ease;\n}\n.progress-striped .progress-bar,\n.progress-bar-striped {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-size: 40px 40px;\n}\n.progress.active .progress-bar,\n.progress-bar.active {\n -webkit-animation: progress-bar-stripes 2s linear infinite;\n -o-animation: progress-bar-stripes 2s linear infinite;\n animation: progress-bar-stripes 2s linear infinite;\n}\n.progress-bar-success {\n background-color: #5cb85c;\n}\n.progress-striped .progress-bar-success {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.progress-bar-info {\n background-color: #5bc0de;\n}\n.progress-striped .progress-bar-info {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.progress-bar-warning {\n background-color: #f0ad4e;\n}\n.progress-striped .progress-bar-warning {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.progress-bar-danger {\n background-color: #d9534f;\n}\n.progress-striped .progress-bar-danger {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.media {\n margin-top: 15px;\n}\n.media:first-child {\n margin-top: 0;\n}\n.media,\n.media-body {\n zoom: 1;\n overflow: hidden;\n}\n.media-body {\n width: 10000px;\n}\n.media-object {\n display: block;\n}\n.media-right,\n.media > .pull-right {\n padding-left: 10px;\n}\n.media-left,\n.media > .pull-left {\n padding-right: 10px;\n}\n.media-left,\n.media-right,\n.media-body {\n display: table-cell;\n vertical-align: top;\n}\n.media-middle {\n vertical-align: middle;\n}\n.media-bottom {\n vertical-align: bottom;\n}\n.media-heading {\n margin-top: 0;\n margin-bottom: 5px;\n}\n.media-list {\n padding-left: 0;\n list-style: none;\n}\n.list-group {\n margin-bottom: 20px;\n padding-left: 0;\n}\n.list-group-item {\n position: relative;\n display: block;\n padding: 10px 15px;\n margin-bottom: -1px;\n background-color: #ffffff;\n border: 1px solid #dddddd;\n}\n.list-group-item:first-child {\n border-top-right-radius: 4px;\n border-top-left-radius: 4px;\n}\n.list-group-item:last-child {\n margin-bottom: 0;\n border-bottom-right-radius: 4px;\n border-bottom-left-radius: 4px;\n}\na.list-group-item {\n color: #555555;\n}\na.list-group-item .list-group-item-heading {\n color: #333333;\n}\na.list-group-item:hover,\na.list-group-item:focus {\n text-decoration: none;\n color: #555555;\n background-color: #f5f5f5;\n}\n.list-group-item.disabled,\n.list-group-item.disabled:hover,\n.list-group-item.disabled:focus {\n background-color: #eeeeee;\n color: #777777;\n cursor: not-allowed;\n}\n.list-group-item.disabled .list-group-item-heading,\n.list-group-item.disabled:hover .list-group-item-heading,\n.list-group-item.disabled:focus .list-group-item-heading {\n color: inherit;\n}\n.list-group-item.disabled .list-group-item-text,\n.list-group-item.disabled:hover .list-group-item-text,\n.list-group-item.disabled:focus .list-group-item-text {\n color: #777777;\n}\n.list-group-item.active,\n.list-group-item.active:hover,\n.list-group-item.active:focus {\n z-index: 2;\n color: #ffffff;\n background-color: #337ab7;\n border-color: #337ab7;\n}\n.list-group-item.active .list-group-item-heading,\n.list-group-item.active:hover .list-group-item-heading,\n.list-group-item.active:focus .list-group-item-heading,\n.list-group-item.active .list-group-item-heading > small,\n.list-group-item.active:hover .list-group-item-heading > small,\n.list-group-item.active:focus .list-group-item-heading > small,\n.list-group-item.active .list-group-item-heading > .small,\n.list-group-item.active:hover .list-group-item-heading > .small,\n.list-group-item.active:focus .list-group-item-heading > .small {\n color: inherit;\n}\n.list-group-item.active .list-group-item-text,\n.list-group-item.active:hover .list-group-item-text,\n.list-group-item.active:focus .list-group-item-text {\n color: #c7ddef;\n}\n.list-group-item-success {\n color: #3c763d;\n background-color: #dff0d8;\n}\na.list-group-item-success {\n color: #3c763d;\n}\na.list-group-item-success .list-group-item-heading {\n color: inherit;\n}\na.list-group-item-success:hover,\na.list-group-item-success:focus {\n color: #3c763d;\n background-color: #d0e9c6;\n}\na.list-group-item-success.active,\na.list-group-item-success.active:hover,\na.list-group-item-success.active:focus {\n color: #fff;\n background-color: #3c763d;\n border-color: #3c763d;\n}\n.list-group-item-info {\n color: #31708f;\n background-color: #d9edf7;\n}\na.list-group-item-info {\n color: #31708f;\n}\na.list-group-item-info .list-group-item-heading {\n color: inherit;\n}\na.list-group-item-info:hover,\na.list-group-item-info:focus {\n color: #31708f;\n background-color: #c4e3f3;\n}\na.list-group-item-info.active,\na.list-group-item-info.active:hover,\na.list-group-item-info.active:focus {\n color: #fff;\n background-color: #31708f;\n border-color: #31708f;\n}\n.list-group-item-warning {\n color: #8a6d3b;\n background-color: #fcf8e3;\n}\na.list-group-item-warning {\n color: #8a6d3b;\n}\na.list-group-item-warning .list-group-item-heading {\n color: inherit;\n}\na.list-group-item-warning:hover,\na.list-group-item-warning:focus {\n color: #8a6d3b;\n background-color: #faf2cc;\n}\na.list-group-item-warning.active,\na.list-group-item-warning.active:hover,\na.list-group-item-warning.active:focus {\n color: #fff;\n background-color: #8a6d3b;\n border-color: #8a6d3b;\n}\n.list-group-item-danger {\n color: #a94442;\n background-color: #f2dede;\n}\na.list-group-item-danger {\n color: #a94442;\n}\na.list-group-item-danger .list-group-item-heading {\n color: inherit;\n}\na.list-group-item-danger:hover,\na.list-group-item-danger:focus {\n color: #a94442;\n background-color: #ebcccc;\n}\na.list-group-item-danger.active,\na.list-group-item-danger.active:hover,\na.list-group-item-danger.active:focus {\n color: #fff;\n background-color: #a94442;\n border-color: #a94442;\n}\n.list-group-item-heading {\n margin-top: 0;\n margin-bottom: 5px;\n}\n.list-group-item-text {\n margin-bottom: 0;\n line-height: 1.3;\n}\n.panel {\n margin-bottom: 20px;\n background-color: #ffffff;\n border: 1px solid transparent;\n border-radius: 4px;\n -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);\n box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n.panel-body {\n padding: 15px;\n}\n.panel-heading {\n padding: 10px 15px;\n border-bottom: 1px solid transparent;\n border-top-right-radius: 3px;\n border-top-left-radius: 3px;\n}\n.panel-heading > .dropdown .dropdown-toggle {\n color: inherit;\n}\n.panel-title {\n margin-top: 0;\n margin-bottom: 0;\n font-size: 16px;\n color: inherit;\n}\n.panel-title > a,\n.panel-title > small,\n.panel-title > .small,\n.panel-title > small > a,\n.panel-title > .small > a {\n color: inherit;\n}\n.panel-footer {\n padding: 10px 15px;\n background-color: #f5f5f5;\n border-top: 1px solid #dddddd;\n border-bottom-right-radius: 3px;\n border-bottom-left-radius: 3px;\n}\n.panel > .list-group,\n.panel > .panel-collapse > .list-group {\n margin-bottom: 0;\n}\n.panel > .list-group .list-group-item,\n.panel > .panel-collapse > .list-group .list-group-item {\n border-width: 1px 0;\n border-radius: 0;\n}\n.panel > .list-group:first-child .list-group-item:first-child,\n.panel > .panel-collapse > .list-group:first-child .list-group-item:first-child {\n border-top: 0;\n border-top-right-radius: 3px;\n border-top-left-radius: 3px;\n}\n.panel > .list-group:last-child .list-group-item:last-child,\n.panel > .panel-collapse > .list-group:last-child .list-group-item:last-child {\n border-bottom: 0;\n border-bottom-right-radius: 3px;\n border-bottom-left-radius: 3px;\n}\n.panel-heading + .list-group .list-group-item:first-child {\n border-top-width: 0;\n}\n.list-group + .panel-footer {\n border-top-width: 0;\n}\n.panel > .table,\n.panel > .table-responsive > .table,\n.panel > .panel-collapse > .table {\n margin-bottom: 0;\n}\n.panel > .table caption,\n.panel > .table-responsive > .table caption,\n.panel > .panel-collapse > .table caption {\n padding-left: 15px;\n padding-right: 15px;\n}\n.panel > .table:first-child,\n.panel > .table-responsive:first-child > .table:first-child {\n border-top-right-radius: 3px;\n border-top-left-radius: 3px;\n}\n.panel > .table:first-child > thead:first-child > tr:first-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child {\n border-top-left-radius: 3px;\n border-top-right-radius: 3px;\n}\n.panel > .table:first-child > thead:first-child > tr:first-child td:first-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:first-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child td:first-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:first-child,\n.panel > .table:first-child > thead:first-child > tr:first-child th:first-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:first-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child th:first-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:first-child {\n border-top-left-radius: 3px;\n}\n.panel > .table:first-child > thead:first-child > tr:first-child td:last-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:last-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child td:last-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:last-child,\n.panel > .table:first-child > thead:first-child > tr:first-child th:last-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:last-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child th:last-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:last-child {\n border-top-right-radius: 3px;\n}\n.panel > .table:last-child,\n.panel > .table-responsive:last-child > .table:last-child {\n border-bottom-right-radius: 3px;\n border-bottom-left-radius: 3px;\n}\n.panel > .table:last-child > tbody:last-child > tr:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child {\n border-bottom-left-radius: 3px;\n border-bottom-right-radius: 3px;\n}\n.panel > .table:last-child > tbody:last-child > tr:last-child td:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:first-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child td:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:first-child,\n.panel > .table:last-child > tbody:last-child > tr:last-child th:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:first-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child th:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:first-child {\n border-bottom-left-radius: 3px;\n}\n.panel > .table:last-child > tbody:last-child > tr:last-child td:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:last-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child td:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:last-child,\n.panel > .table:last-child > tbody:last-child > tr:last-child th:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:last-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child th:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:last-child {\n border-bottom-right-radius: 3px;\n}\n.panel > .panel-body + .table,\n.panel > .panel-body + .table-responsive,\n.panel > .table + .panel-body,\n.panel > .table-responsive + .panel-body {\n border-top: 1px solid #dddddd;\n}\n.panel > .table > tbody:first-child > tr:first-child th,\n.panel > .table > tbody:first-child > tr:first-child td {\n border-top: 0;\n}\n.panel > .table-bordered,\n.panel > .table-responsive > .table-bordered {\n border: 0;\n}\n.panel > .table-bordered > thead > tr > th:first-child,\n.panel > .table-responsive > .table-bordered > thead > tr > th:first-child,\n.panel > .table-bordered > tbody > tr > th:first-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > th:first-child,\n.panel > .table-bordered > tfoot > tr > th:first-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > th:first-child,\n.panel > .table-bordered > thead > tr > td:first-child,\n.panel > .table-responsive > .table-bordered > thead > tr > td:first-child,\n.panel > .table-bordered > tbody > tr > td:first-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > td:first-child,\n.panel > .table-bordered > tfoot > tr > td:first-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > td:first-child {\n border-left: 0;\n}\n.panel > .table-bordered > thead > tr > th:last-child,\n.panel > .table-responsive > .table-bordered > thead > tr > th:last-child,\n.panel > .table-bordered > tbody > tr > th:last-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > th:last-child,\n.panel > .table-bordered > tfoot > tr > th:last-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > th:last-child,\n.panel > .table-bordered > thead > tr > td:last-child,\n.panel > .table-responsive > .table-bordered > thead > tr > td:last-child,\n.panel > .table-bordered > tbody > tr > td:last-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > td:last-child,\n.panel > .table-bordered > tfoot > tr > td:last-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > td:last-child {\n border-right: 0;\n}\n.panel > .table-bordered > thead > tr:first-child > td,\n.panel > .table-responsive > .table-bordered > thead > tr:first-child > td,\n.panel > .table-bordered > tbody > tr:first-child > td,\n.panel > .table-responsive > .table-bordered > tbody > tr:first-child > td,\n.panel > .table-bordered > thead > tr:first-child > th,\n.panel > .table-responsive > .table-bordered > thead > tr:first-child > th,\n.panel > .table-bordered > tbody > tr:first-child > th,\n.panel > .table-responsive > .table-bordered > tbody > tr:first-child > th {\n border-bottom: 0;\n}\n.panel > .table-bordered > tbody > tr:last-child > td,\n.panel > .table-responsive > .table-bordered > tbody > tr:last-child > td,\n.panel > .table-bordered > tfoot > tr:last-child > td,\n.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > td,\n.panel > .table-bordered > tbody > tr:last-child > th,\n.panel > .table-responsive > .table-bordered > tbody > tr:last-child > th,\n.panel > .table-bordered > tfoot > tr:last-child > th,\n.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > th {\n border-bottom: 0;\n}\n.panel > .table-responsive {\n border: 0;\n margin-bottom: 0;\n}\n.panel-group {\n margin-bottom: 20px;\n}\n.panel-group .panel {\n margin-bottom: 0;\n border-radius: 4px;\n}\n.panel-group .panel + .panel {\n margin-top: 5px;\n}\n.panel-group .panel-heading {\n border-bottom: 0;\n}\n.panel-group .panel-heading + .panel-collapse > .panel-body,\n.panel-group .panel-heading + .panel-collapse > .list-group {\n border-top: 1px solid #dddddd;\n}\n.panel-group .panel-footer {\n border-top: 0;\n}\n.panel-group .panel-footer + .panel-collapse .panel-body {\n border-bottom: 1px solid #dddddd;\n}\n.panel-default {\n border-color: #dddddd;\n}\n.panel-default > .panel-heading {\n color: #333333;\n background-color: #f5f5f5;\n border-color: #dddddd;\n}\n.panel-default > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #dddddd;\n}\n.panel-default > .panel-heading .badge {\n color: #f5f5f5;\n background-color: #333333;\n}\n.panel-default > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #dddddd;\n}\n.panel-primary {\n border-color: #337ab7;\n}\n.panel-primary > .panel-heading {\n color: #ffffff;\n background-color: #337ab7;\n border-color: #337ab7;\n}\n.panel-primary > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #337ab7;\n}\n.panel-primary > .panel-heading .badge {\n color: #337ab7;\n background-color: #ffffff;\n}\n.panel-primary > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #337ab7;\n}\n.panel-success {\n border-color: #d6e9c6;\n}\n.panel-success > .panel-heading {\n color: #3c763d;\n background-color: #dff0d8;\n border-color: #d6e9c6;\n}\n.panel-success > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #d6e9c6;\n}\n.panel-success > .panel-heading .badge {\n color: #dff0d8;\n background-color: #3c763d;\n}\n.panel-success > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #d6e9c6;\n}\n.panel-info {\n border-color: #bce8f1;\n}\n.panel-info > .panel-heading {\n color: #31708f;\n background-color: #d9edf7;\n border-color: #bce8f1;\n}\n.panel-info > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #bce8f1;\n}\n.panel-info > .panel-heading .badge {\n color: #d9edf7;\n background-color: #31708f;\n}\n.panel-info > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #bce8f1;\n}\n.panel-warning {\n border-color: #faebcc;\n}\n.panel-warning > .panel-heading {\n color: #8a6d3b;\n background-color: #fcf8e3;\n border-color: #faebcc;\n}\n.panel-warning > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #faebcc;\n}\n.panel-warning > .panel-heading .badge {\n color: #fcf8e3;\n background-color: #8a6d3b;\n}\n.panel-warning > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #faebcc;\n}\n.panel-danger {\n border-color: #ebccd1;\n}\n.panel-danger > .panel-heading {\n color: #a94442;\n background-color: #f2dede;\n border-color: #ebccd1;\n}\n.panel-danger > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #ebccd1;\n}\n.panel-danger > .panel-heading .badge {\n color: #f2dede;\n background-color: #a94442;\n}\n.panel-danger > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #ebccd1;\n}\n.embed-responsive {\n position: relative;\n display: block;\n height: 0;\n padding: 0;\n overflow: hidden;\n}\n.embed-responsive .embed-responsive-item,\n.embed-responsive iframe,\n.embed-responsive embed,\n.embed-responsive object,\n.embed-responsive video {\n position: absolute;\n top: 0;\n left: 0;\n bottom: 0;\n height: 100%;\n width: 100%;\n border: 0;\n}\n.embed-responsive-16by9 {\n padding-bottom: 56.25%;\n}\n.embed-responsive-4by3 {\n padding-bottom: 75%;\n}\n.well {\n min-height: 20px;\n padding: 19px;\n margin-bottom: 20px;\n background-color: #f5f5f5;\n border: 1px solid #e3e3e3;\n border-radius: 4px;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n.well blockquote {\n border-color: #ddd;\n border-color: rgba(0, 0, 0, 0.15);\n}\n.well-lg {\n padding: 24px;\n border-radius: 6px;\n}\n.well-sm {\n padding: 9px;\n border-radius: 3px;\n}\n.close {\n float: right;\n font-size: 21px;\n font-weight: bold;\n line-height: 1;\n color: #000000;\n text-shadow: 0 1px 0 #ffffff;\n opacity: 0.2;\n filter: alpha(opacity=20);\n}\n.close:hover,\n.close:focus {\n color: #000000;\n text-decoration: none;\n cursor: pointer;\n opacity: 0.5;\n filter: alpha(opacity=50);\n}\nbutton.close {\n padding: 0;\n cursor: pointer;\n background: transparent;\n border: 0;\n -webkit-appearance: none;\n}\n.modal-open {\n overflow: hidden;\n}\n.modal {\n display: none;\n overflow: hidden;\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: 1050;\n -webkit-overflow-scrolling: touch;\n outline: 0;\n}\n.modal.fade .modal-dialog {\n -webkit-transform: translate(0, -25%);\n -ms-transform: translate(0, -25%);\n -o-transform: translate(0, -25%);\n transform: translate(0, -25%);\n -webkit-transition: -webkit-transform 0.3s ease-out;\n -moz-transition: -moz-transform 0.3s ease-out;\n -o-transition: -o-transform 0.3s ease-out;\n transition: transform 0.3s ease-out;\n}\n.modal.in .modal-dialog {\n -webkit-transform: translate(0, 0);\n -ms-transform: translate(0, 0);\n -o-transform: translate(0, 0);\n transform: translate(0, 0);\n}\n.modal-open .modal {\n overflow-x: hidden;\n overflow-y: auto;\n}\n.modal-dialog {\n position: relative;\n width: auto;\n margin: 10px;\n}\n.modal-content {\n position: relative;\n background-color: #ffffff;\n border: 1px solid #999999;\n border: 1px solid rgba(0, 0, 0, 0.2);\n border-radius: 6px;\n -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5);\n box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5);\n background-clip: padding-box;\n outline: 0;\n}\n.modal-backdrop {\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: 1040;\n background-color: #000000;\n}\n.modal-backdrop.fade {\n opacity: 0;\n filter: alpha(opacity=0);\n}\n.modal-backdrop.in {\n opacity: 0.5;\n filter: alpha(opacity=50);\n}\n.modal-header {\n padding: 15px;\n border-bottom: 1px solid #e5e5e5;\n min-height: 16.42857143px;\n}\n.modal-header .close {\n margin-top: -2px;\n}\n.modal-title {\n margin: 0;\n line-height: 1.42857143;\n}\n.modal-body {\n position: relative;\n padding: 15px;\n}\n.modal-footer {\n padding: 15px;\n text-align: right;\n border-top: 1px solid #e5e5e5;\n}\n.modal-footer .btn + .btn {\n margin-left: 5px;\n margin-bottom: 0;\n}\n.modal-footer .btn-group .btn + .btn {\n margin-left: -1px;\n}\n.modal-footer .btn-block + .btn-block {\n margin-left: 0;\n}\n.modal-scrollbar-measure {\n position: absolute;\n top: -9999px;\n width: 50px;\n height: 50px;\n overflow: scroll;\n}\n@media (min-width: 768px) {\n .modal-dialog {\n width: 600px;\n margin: 30px auto;\n }\n .modal-content {\n -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);\n box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);\n }\n .modal-sm {\n width: 300px;\n }\n}\n@media (min-width: 992px) {\n .modal-lg {\n width: 900px;\n }\n}\n.tooltip {\n position: absolute;\n z-index: 1070;\n display: block;\n font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n font-size: 12px;\n font-weight: normal;\n line-height: 1.4;\n opacity: 0;\n filter: alpha(opacity=0);\n}\n.tooltip.in {\n opacity: 0.9;\n filter: alpha(opacity=90);\n}\n.tooltip.top {\n margin-top: -3px;\n padding: 5px 0;\n}\n.tooltip.right {\n margin-left: 3px;\n padding: 0 5px;\n}\n.tooltip.bottom {\n margin-top: 3px;\n padding: 5px 0;\n}\n.tooltip.left {\n margin-left: -3px;\n padding: 0 5px;\n}\n.tooltip-inner {\n max-width: 200px;\n padding: 3px 8px;\n color: #ffffff;\n text-align: center;\n text-decoration: none;\n background-color: #000000;\n border-radius: 4px;\n}\n.tooltip-arrow {\n position: absolute;\n width: 0;\n height: 0;\n border-color: transparent;\n border-style: solid;\n}\n.tooltip.top .tooltip-arrow {\n bottom: 0;\n left: 50%;\n margin-left: -5px;\n border-width: 5px 5px 0;\n border-top-color: #000000;\n}\n.tooltip.top-left .tooltip-arrow {\n bottom: 0;\n right: 5px;\n margin-bottom: -5px;\n border-width: 5px 5px 0;\n border-top-color: #000000;\n}\n.tooltip.top-right .tooltip-arrow {\n bottom: 0;\n left: 5px;\n margin-bottom: -5px;\n border-width: 5px 5px 0;\n border-top-color: #000000;\n}\n.tooltip.right .tooltip-arrow {\n top: 50%;\n left: 0;\n margin-top: -5px;\n border-width: 5px 5px 5px 0;\n border-right-color: #000000;\n}\n.tooltip.left .tooltip-arrow {\n top: 50%;\n right: 0;\n margin-top: -5px;\n border-width: 5px 0 5px 5px;\n border-left-color: #000000;\n}\n.tooltip.bottom .tooltip-arrow {\n top: 0;\n left: 50%;\n margin-left: -5px;\n border-width: 0 5px 5px;\n border-bottom-color: #000000;\n}\n.tooltip.bottom-left .tooltip-arrow {\n top: 0;\n right: 5px;\n margin-top: -5px;\n border-width: 0 5px 5px;\n border-bottom-color: #000000;\n}\n.tooltip.bottom-right .tooltip-arrow {\n top: 0;\n left: 5px;\n margin-top: -5px;\n border-width: 0 5px 5px;\n border-bottom-color: #000000;\n}\n.popover {\n position: absolute;\n top: 0;\n left: 0;\n z-index: 1060;\n display: none;\n max-width: 276px;\n padding: 1px;\n font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n font-size: 14px;\n font-weight: normal;\n line-height: 1.42857143;\n text-align: left;\n background-color: #ffffff;\n background-clip: padding-box;\n border: 1px solid #cccccc;\n border: 1px solid rgba(0, 0, 0, 0.2);\n border-radius: 6px;\n -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n white-space: normal;\n}\n.popover.top {\n margin-top: -10px;\n}\n.popover.right {\n margin-left: 10px;\n}\n.popover.bottom {\n margin-top: 10px;\n}\n.popover.left {\n margin-left: -10px;\n}\n.popover-title {\n margin: 0;\n padding: 8px 14px;\n font-size: 14px;\n background-color: #f7f7f7;\n border-bottom: 1px solid #ebebeb;\n border-radius: 5px 5px 0 0;\n}\n.popover-content {\n padding: 9px 14px;\n}\n.popover > .arrow,\n.popover > .arrow:after {\n position: absolute;\n display: block;\n width: 0;\n height: 0;\n border-color: transparent;\n border-style: solid;\n}\n.popover > .arrow {\n border-width: 11px;\n}\n.popover > .arrow:after {\n border-width: 10px;\n content: \"\";\n}\n.popover.top > .arrow {\n left: 50%;\n margin-left: -11px;\n border-bottom-width: 0;\n border-top-color: #999999;\n border-top-color: rgba(0, 0, 0, 0.25);\n bottom: -11px;\n}\n.popover.top > .arrow:after {\n content: \" \";\n bottom: 1px;\n margin-left: -10px;\n border-bottom-width: 0;\n border-top-color: #ffffff;\n}\n.popover.right > .arrow {\n top: 50%;\n left: -11px;\n margin-top: -11px;\n border-left-width: 0;\n border-right-color: #999999;\n border-right-color: rgba(0, 0, 0, 0.25);\n}\n.popover.right > .arrow:after {\n content: \" \";\n left: 1px;\n bottom: -10px;\n border-left-width: 0;\n border-right-color: #ffffff;\n}\n.popover.bottom > .arrow {\n left: 50%;\n margin-left: -11px;\n border-top-width: 0;\n border-bottom-color: #999999;\n border-bottom-color: rgba(0, 0, 0, 0.25);\n top: -11px;\n}\n.popover.bottom > .arrow:after {\n content: \" \";\n top: 1px;\n margin-left: -10px;\n border-top-width: 0;\n border-bottom-color: #ffffff;\n}\n.popover.left > .arrow {\n top: 50%;\n right: -11px;\n margin-top: -11px;\n border-right-width: 0;\n border-left-color: #999999;\n border-left-color: rgba(0, 0, 0, 0.25);\n}\n.popover.left > .arrow:after {\n content: \" \";\n right: 1px;\n border-right-width: 0;\n border-left-color: #ffffff;\n bottom: -10px;\n}\n.carousel {\n position: relative;\n}\n.carousel-inner {\n position: relative;\n overflow: hidden;\n width: 100%;\n}\n.carousel-inner > .item {\n display: none;\n position: relative;\n -webkit-transition: 0.6s ease-in-out left;\n -o-transition: 0.6s ease-in-out left;\n transition: 0.6s ease-in-out left;\n}\n.carousel-inner > .item > img,\n.carousel-inner > .item > a > img {\n line-height: 1;\n}\n@media all and (transform-3d), (-webkit-transform-3d) {\n .carousel-inner > .item {\n -webkit-transition: -webkit-transform 0.6s ease-in-out;\n -moz-transition: -moz-transform 0.6s ease-in-out;\n -o-transition: -o-transform 0.6s ease-in-out;\n transition: transform 0.6s ease-in-out;\n -webkit-backface-visibility: hidden;\n -moz-backface-visibility: hidden;\n backface-visibility: hidden;\n -webkit-perspective: 1000;\n -moz-perspective: 1000;\n perspective: 1000;\n }\n .carousel-inner > .item.next,\n .carousel-inner > .item.active.right {\n -webkit-transform: translate3d(100%, 0, 0);\n transform: translate3d(100%, 0, 0);\n left: 0;\n }\n .carousel-inner > .item.prev,\n .carousel-inner > .item.active.left {\n -webkit-transform: translate3d(-100%, 0, 0);\n transform: translate3d(-100%, 0, 0);\n left: 0;\n }\n .carousel-inner > .item.next.left,\n .carousel-inner > .item.prev.right,\n .carousel-inner > .item.active {\n -webkit-transform: translate3d(0, 0, 0);\n transform: translate3d(0, 0, 0);\n left: 0;\n }\n}\n.carousel-inner > .active,\n.carousel-inner > .next,\n.carousel-inner > .prev {\n display: block;\n}\n.carousel-inner > .active {\n left: 0;\n}\n.carousel-inner > .next,\n.carousel-inner > .prev {\n position: absolute;\n top: 0;\n width: 100%;\n}\n.carousel-inner > .next {\n left: 100%;\n}\n.carousel-inner > .prev {\n left: -100%;\n}\n.carousel-inner > .next.left,\n.carousel-inner > .prev.right {\n left: 0;\n}\n.carousel-inner > .active.left {\n left: -100%;\n}\n.carousel-inner > .active.right {\n left: 100%;\n}\n.carousel-control {\n position: absolute;\n top: 0;\n left: 0;\n bottom: 0;\n width: 15%;\n opacity: 0.5;\n filter: alpha(opacity=50);\n font-size: 20px;\n color: #ffffff;\n text-align: center;\n text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);\n}\n.carousel-control.left {\n background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);\n background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);\n background-image: linear-gradient(to right, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);\n}\n.carousel-control.right {\n left: auto;\n right: 0;\n background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);\n background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);\n background-image: linear-gradient(to right, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);\n}\n.carousel-control:hover,\n.carousel-control:focus {\n outline: 0;\n color: #ffffff;\n text-decoration: none;\n opacity: 0.9;\n filter: alpha(opacity=90);\n}\n.carousel-control .icon-prev,\n.carousel-control .icon-next,\n.carousel-control .glyphicon-chevron-left,\n.carousel-control .glyphicon-chevron-right {\n position: absolute;\n top: 50%;\n z-index: 5;\n display: inline-block;\n}\n.carousel-control .icon-prev,\n.carousel-control .glyphicon-chevron-left {\n left: 50%;\n margin-left: -10px;\n}\n.carousel-control .icon-next,\n.carousel-control .glyphicon-chevron-right {\n right: 50%;\n margin-right: -10px;\n}\n.carousel-control .icon-prev,\n.carousel-control .icon-next {\n width: 20px;\n height: 20px;\n margin-top: -10px;\n line-height: 1;\n font-family: serif;\n}\n.carousel-control .icon-prev:before {\n content: '\\2039';\n}\n.carousel-control .icon-next:before {\n content: '\\203a';\n}\n.carousel-indicators {\n position: absolute;\n bottom: 10px;\n left: 50%;\n z-index: 15;\n width: 60%;\n margin-left: -30%;\n padding-left: 0;\n list-style: none;\n text-align: center;\n}\n.carousel-indicators li {\n display: inline-block;\n width: 10px;\n height: 10px;\n margin: 1px;\n text-indent: -999px;\n border: 1px solid #ffffff;\n border-radius: 10px;\n cursor: pointer;\n background-color: #000 \\9;\n background-color: rgba(0, 0, 0, 0);\n}\n.carousel-indicators .active {\n margin: 0;\n width: 12px;\n height: 12px;\n background-color: #ffffff;\n}\n.carousel-caption {\n position: absolute;\n left: 15%;\n right: 15%;\n bottom: 20px;\n z-index: 10;\n padding-top: 20px;\n padding-bottom: 20px;\n color: #ffffff;\n text-align: center;\n text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);\n}\n.carousel-caption .btn {\n text-shadow: none;\n}\n@media screen and (min-width: 768px) {\n .carousel-control .glyphicon-chevron-left,\n .carousel-control .glyphicon-chevron-right,\n .carousel-control .icon-prev,\n .carousel-control .icon-next {\n width: 30px;\n height: 30px;\n margin-top: -15px;\n font-size: 30px;\n }\n .carousel-control .glyphicon-chevron-left,\n .carousel-control .icon-prev {\n margin-left: -15px;\n }\n .carousel-control .glyphicon-chevron-right,\n .carousel-control .icon-next {\n margin-right: -15px;\n }\n .carousel-caption {\n left: 20%;\n right: 20%;\n padding-bottom: 30px;\n }\n .carousel-indicators {\n bottom: 20px;\n }\n}\n.clearfix:before,\n.clearfix:after,\n.dl-horizontal dd:before,\n.dl-horizontal dd:after,\n.container:before,\n.container:after,\n.container-fluid:before,\n.container-fluid:after,\n.row:before,\n.row:after,\n.form-horizontal .form-group:before,\n.form-horizontal .form-group:after,\n.btn-toolbar:before,\n.btn-toolbar:after,\n.btn-group-vertical > .btn-group:before,\n.btn-group-vertical > .btn-group:after,\n.nav:before,\n.nav:after,\n.navbar:before,\n.navbar:after,\n.navbar-header:before,\n.navbar-header:after,\n.navbar-collapse:before,\n.navbar-collapse:after,\n.pager:before,\n.pager:after,\n.panel-body:before,\n.panel-body:after,\n.modal-footer:before,\n.modal-footer:after {\n content: \" \";\n display: table;\n}\n.clearfix:after,\n.dl-horizontal dd:after,\n.container:after,\n.container-fluid:after,\n.row:after,\n.form-horizontal .form-group:after,\n.btn-toolbar:after,\n.btn-group-vertical > .btn-group:after,\n.nav:after,\n.navbar:after,\n.navbar-header:after,\n.navbar-collapse:after,\n.pager:after,\n.panel-body:after,\n.modal-footer:after {\n clear: both;\n}\n.center-block {\n display: block;\n margin-left: auto;\n margin-right: auto;\n}\n.pull-right {\n float: right !important;\n}\n.pull-left {\n float: left !important;\n}\n.hide {\n display: none !important;\n}\n.show {\n display: block !important;\n}\n.invisible {\n visibility: hidden;\n}\n.text-hide {\n font: 0/0 a;\n color: transparent;\n text-shadow: none;\n background-color: transparent;\n border: 0;\n}\n.hidden {\n display: none !important;\n}\n.affix {\n position: fixed;\n}\n@-ms-viewport {\n width: device-width;\n}\n.visible-xs,\n.visible-sm,\n.visible-md,\n.visible-lg {\n display: none !important;\n}\n.visible-xs-block,\n.visible-xs-inline,\n.visible-xs-inline-block,\n.visible-sm-block,\n.visible-sm-inline,\n.visible-sm-inline-block,\n.visible-md-block,\n.visible-md-inline,\n.visible-md-inline-block,\n.visible-lg-block,\n.visible-lg-inline,\n.visible-lg-inline-block {\n display: none !important;\n}\n@media (max-width: 767px) {\n .visible-xs {\n display: block !important;\n }\n table.visible-xs {\n display: table;\n }\n tr.visible-xs {\n display: table-row !important;\n }\n th.visible-xs,\n td.visible-xs {\n display: table-cell !important;\n }\n}\n@media (max-width: 767px) {\n .visible-xs-block {\n display: block !important;\n }\n}\n@media (max-width: 767px) {\n .visible-xs-inline {\n display: inline !important;\n }\n}\n@media (max-width: 767px) {\n .visible-xs-inline-block {\n display: inline-block !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .visible-sm {\n display: block !important;\n }\n table.visible-sm {\n display: table;\n }\n tr.visible-sm {\n display: table-row !important;\n }\n th.visible-sm,\n td.visible-sm {\n display: table-cell !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .visible-sm-block {\n display: block !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .visible-sm-inline {\n display: inline !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .visible-sm-inline-block {\n display: inline-block !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .visible-md {\n display: block !important;\n }\n table.visible-md {\n display: table;\n }\n tr.visible-md {\n display: table-row !important;\n }\n th.visible-md,\n td.visible-md {\n display: table-cell !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .visible-md-block {\n display: block !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .visible-md-inline {\n display: inline !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .visible-md-inline-block {\n display: inline-block !important;\n }\n}\n@media (min-width: 1200px) {\n .visible-lg {\n display: block !important;\n }\n table.visible-lg {\n display: table;\n }\n tr.visible-lg {\n display: table-row !important;\n }\n th.visible-lg,\n td.visible-lg {\n display: table-cell !important;\n }\n}\n@media (min-width: 1200px) {\n .visible-lg-block {\n display: block !important;\n }\n}\n@media (min-width: 1200px) {\n .visible-lg-inline {\n display: inline !important;\n }\n}\n@media (min-width: 1200px) {\n .visible-lg-inline-block {\n display: inline-block !important;\n }\n}\n@media (max-width: 767px) {\n .hidden-xs {\n display: none !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .hidden-sm {\n display: none !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .hidden-md {\n display: none !important;\n }\n}\n@media (min-width: 1200px) {\n .hidden-lg {\n display: none !important;\n }\n}\n.visible-print {\n display: none !important;\n}\n@media print {\n .visible-print {\n display: block !important;\n }\n table.visible-print {\n display: table;\n }\n tr.visible-print {\n display: table-row !important;\n }\n th.visible-print,\n td.visible-print {\n display: table-cell !important;\n }\n}\n.visible-print-block {\n display: none !important;\n}\n@media print {\n .visible-print-block {\n display: block !important;\n }\n}\n.visible-print-inline {\n display: none !important;\n}\n@media print {\n .visible-print-inline {\n display: inline !important;\n }\n}\n.visible-print-inline-block {\n display: none !important;\n}\n@media print {\n .visible-print-inline-block {\n display: inline-block !important;\n }\n}\n@media print {\n .hidden-print {\n display: none !important;\n }\n}\n/*# sourceMappingURL=bootstrap.css.map */","/*! normalize.css v3.0.2 | MIT License | git.io/normalize */\n\n//\n// 1. Set default font family to sans-serif.\n// 2. Prevent iOS text size adjust after orientation change, without disabling\n// user zoom.\n//\n\nhtml {\n font-family: sans-serif; // 1\n -ms-text-size-adjust: 100%; // 2\n -webkit-text-size-adjust: 100%; // 2\n}\n\n//\n// Remove default margin.\n//\n\nbody {\n margin: 0;\n}\n\n// HTML5 display definitions\n// ==========================================================================\n\n//\n// Correct `block` display not defined for any HTML5 element in IE 8/9.\n// Correct `block` display not defined for `details` or `summary` in IE 10/11\n// and Firefox.\n// Correct `block` display not defined for `main` in IE 11.\n//\n\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nmain,\nmenu,\nnav,\nsection,\nsummary {\n display: block;\n}\n\n//\n// 1. Correct `inline-block` display not defined in IE 8/9.\n// 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.\n//\n\naudio,\ncanvas,\nprogress,\nvideo {\n display: inline-block; // 1\n vertical-align: baseline; // 2\n}\n\n//\n// Prevent modern browsers from displaying `audio` without controls.\n// Remove excess height in iOS 5 devices.\n//\n\naudio:not([controls]) {\n display: none;\n height: 0;\n}\n\n//\n// Address `[hidden]` styling not present in IE 8/9/10.\n// Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22.\n//\n\n[hidden],\ntemplate {\n display: none;\n}\n\n// Links\n// ==========================================================================\n\n//\n// Remove the gray background color from active links in IE 10.\n//\n\na {\n background-color: transparent;\n}\n\n//\n// Improve readability when focused and also mouse hovered in all browsers.\n//\n\na:active,\na:hover {\n outline: 0;\n}\n\n// Text-level semantics\n// ==========================================================================\n\n//\n// Address styling not present in IE 8/9/10/11, Safari, and Chrome.\n//\n\nabbr[title] {\n border-bottom: 1px dotted;\n}\n\n//\n// Address style set to `bolder` in Firefox 4+, Safari, and Chrome.\n//\n\nb,\nstrong {\n font-weight: bold;\n}\n\n//\n// Address styling not present in Safari and Chrome.\n//\n\ndfn {\n font-style: italic;\n}\n\n//\n// Address variable `h1` font-size and margin within `section` and `article`\n// contexts in Firefox 4+, Safari, and Chrome.\n//\n\nh1 {\n font-size: 2em;\n margin: 0.67em 0;\n}\n\n//\n// Address styling not present in IE 8/9.\n//\n\nmark {\n background: #ff0;\n color: #000;\n}\n\n//\n// Address inconsistent and variable font size in all browsers.\n//\n\nsmall {\n font-size: 80%;\n}\n\n//\n// Prevent `sub` and `sup` affecting `line-height` in all browsers.\n//\n\nsub,\nsup {\n font-size: 75%;\n line-height: 0;\n position: relative;\n vertical-align: baseline;\n}\n\nsup {\n top: -0.5em;\n}\n\nsub {\n bottom: -0.25em;\n}\n\n// Embedded content\n// ==========================================================================\n\n//\n// Remove border when inside `a` element in IE 8/9/10.\n//\n\nimg {\n border: 0;\n}\n\n//\n// Correct overflow not hidden in IE 9/10/11.\n//\n\nsvg:not(:root) {\n overflow: hidden;\n}\n\n// Grouping content\n// ==========================================================================\n\n//\n// Address margin not present in IE 8/9 and Safari.\n//\n\nfigure {\n margin: 1em 40px;\n}\n\n//\n// Address differences between Firefox and other browsers.\n//\n\nhr {\n -moz-box-sizing: content-box;\n box-sizing: content-box;\n height: 0;\n}\n\n//\n// Contain overflow in all browsers.\n//\n\npre {\n overflow: auto;\n}\n\n//\n// Address odd `em`-unit font size rendering in all browsers.\n//\n\ncode,\nkbd,\npre,\nsamp {\n font-family: monospace, monospace;\n font-size: 1em;\n}\n\n// Forms\n// ==========================================================================\n\n//\n// Known limitation: by default, Chrome and Safari on OS X allow very limited\n// styling of `select`, unless a `border` property is set.\n//\n\n//\n// 1. Correct color not being inherited.\n// Known issue: affects color of disabled elements.\n// 2. Correct font properties not being inherited.\n// 3. Address margins set differently in Firefox 4+, Safari, and Chrome.\n//\n\nbutton,\ninput,\noptgroup,\nselect,\ntextarea {\n color: inherit; // 1\n font: inherit; // 2\n margin: 0; // 3\n}\n\n//\n// Address `overflow` set to `hidden` in IE 8/9/10/11.\n//\n\nbutton {\n overflow: visible;\n}\n\n//\n// Address inconsistent `text-transform` inheritance for `button` and `select`.\n// All other form control elements do not inherit `text-transform` values.\n// Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera.\n// Correct `select` style inheritance in Firefox.\n//\n\nbutton,\nselect {\n text-transform: none;\n}\n\n//\n// 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`\n// and `video` controls.\n// 2. Correct inability to style clickable `input` types in iOS.\n// 3. Improve usability and consistency of cursor style between image-type\n// `input` and others.\n//\n\nbutton,\nhtml input[type=\"button\"], // 1\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n -webkit-appearance: button; // 2\n cursor: pointer; // 3\n}\n\n//\n// Re-set default cursor for disabled elements.\n//\n\nbutton[disabled],\nhtml input[disabled] {\n cursor: default;\n}\n\n//\n// Remove inner padding and border in Firefox 4+.\n//\n\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n border: 0;\n padding: 0;\n}\n\n//\n// Address Firefox 4+ setting `line-height` on `input` using `!important` in\n// the UA stylesheet.\n//\n\ninput {\n line-height: normal;\n}\n\n//\n// It's recommended that you don't attempt to style these elements.\n// Firefox's implementation doesn't respect box-sizing, padding, or width.\n//\n// 1. Address box sizing set to `content-box` in IE 8/9/10.\n// 2. Remove excess padding in IE 8/9/10.\n//\n\ninput[type=\"checkbox\"],\ninput[type=\"radio\"] {\n box-sizing: border-box; // 1\n padding: 0; // 2\n}\n\n//\n// Fix the cursor style for Chrome's increment/decrement buttons. For certain\n// `font-size` values of the `input`, it causes the cursor style of the\n// decrement button to change from `default` to `text`.\n//\n\ninput[type=\"number\"]::-webkit-inner-spin-button,\ninput[type=\"number\"]::-webkit-outer-spin-button {\n height: auto;\n}\n\n//\n// 1. Address `appearance` set to `searchfield` in Safari and Chrome.\n// 2. Address `box-sizing` set to `border-box` in Safari and Chrome\n// (include `-moz` to future-proof).\n//\n\ninput[type=\"search\"] {\n -webkit-appearance: textfield; // 1\n -moz-box-sizing: content-box;\n -webkit-box-sizing: content-box; // 2\n box-sizing: content-box;\n}\n\n//\n// Remove inner padding and search cancel button in Safari and Chrome on OS X.\n// Safari (but not Chrome) clips the cancel button when the search input has\n// padding (and `textfield` appearance).\n//\n\ninput[type=\"search\"]::-webkit-search-cancel-button,\ninput[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none;\n}\n\n//\n// Define consistent border, margin, and padding.\n//\n\nfieldset {\n border: 1px solid #c0c0c0;\n margin: 0 2px;\n padding: 0.35em 0.625em 0.75em;\n}\n\n//\n// 1. Correct `color` not being inherited in IE 8/9/10/11.\n// 2. Remove padding so people aren't caught out if they zero out fieldsets.\n//\n\nlegend {\n border: 0; // 1\n padding: 0; // 2\n}\n\n//\n// Remove default vertical scrollbar in IE 8/9/10/11.\n//\n\ntextarea {\n overflow: auto;\n}\n\n//\n// Don't inherit the `font-weight` (applied by a rule above).\n// NOTE: the default cannot safely be changed in Chrome and Safari on OS X.\n//\n\noptgroup {\n font-weight: bold;\n}\n\n// Tables\n// ==========================================================================\n\n//\n// Remove most spacing between table cells.\n//\n\ntable {\n border-collapse: collapse;\n border-spacing: 0;\n}\n\ntd,\nth {\n padding: 0;\n}\n","/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */\n\n// ==========================================================================\n// Print styles.\n// Inlined to avoid the additional HTTP request: h5bp.com/r\n// ==========================================================================\n\n@media print {\n *,\n *:before,\n *:after {\n background: transparent !important;\n color: #000 !important; // Black prints faster: h5bp.com/s\n box-shadow: none !important;\n text-shadow: none !important;\n }\n\n a,\n a:visited {\n text-decoration: underline;\n }\n\n a[href]:after {\n content: \" (\" attr(href) \")\";\n }\n\n abbr[title]:after {\n content: \" (\" attr(title) \")\";\n }\n\n // Don't show links that are fragment identifiers,\n // or use the `javascript:` pseudo protocol\n a[href^=\"#\"]:after,\n a[href^=\"javascript:\"]:after {\n content: \"\";\n }\n\n pre,\n blockquote {\n border: 1px solid #999;\n page-break-inside: avoid;\n }\n\n thead {\n display: table-header-group; // h5bp.com/t\n }\n\n tr,\n img {\n page-break-inside: avoid;\n }\n\n img {\n max-width: 100% !important;\n }\n\n p,\n h2,\n h3 {\n orphans: 3;\n widows: 3;\n }\n\n h2,\n h3 {\n page-break-after: avoid;\n }\n\n // Bootstrap specific changes start\n //\n // Chrome (OSX) fix for https://github.com/twbs/bootstrap/issues/11245\n // Once fixed, we can just straight up remove this.\n select {\n background: #fff !important;\n }\n\n // Bootstrap components\n .navbar {\n display: none;\n }\n .btn,\n .dropup > .btn {\n > .caret {\n border-top-color: #000 !important;\n }\n }\n .label {\n border: 1px solid #000;\n }\n\n .table {\n border-collapse: collapse !important;\n\n td,\n th {\n background-color: #fff !important;\n }\n }\n .table-bordered {\n th,\n td {\n border: 1px solid #ddd !important;\n }\n }\n\n // Bootstrap specific changes end\n}\n","//\n// Glyphicons for Bootstrap\n//\n// Since icons are fonts, they can be placed anywhere text is placed and are\n// thus automatically sized to match the surrounding child. To use, create an\n// inline element with the appropriate classes, like so:\n//\n// <a href=\"#\"><span class=\"glyphicon glyphicon-star\"></span> Star</a>\n\n// Import the fonts\n@font-face {\n font-family: 'Glyphicons Halflings';\n src: url('@{icon-font-path}@{icon-font-name}.eot');\n src: url('@{icon-font-path}@{icon-font-name}.eot?#iefix') format('embedded-opentype'),\n url('@{icon-font-path}@{icon-font-name}.woff2') format('woff2'),\n url('@{icon-font-path}@{icon-font-name}.woff') format('woff'),\n url('@{icon-font-path}@{icon-font-name}.ttf') format('truetype'),\n url('@{icon-font-path}@{icon-font-name}.svg#@{icon-font-svg-id}') format('svg');\n}\n\n// Catchall baseclass\n.glyphicon {\n position: relative;\n top: 1px;\n display: inline-block;\n font-family: 'Glyphicons Halflings';\n font-style: normal;\n font-weight: normal;\n line-height: 1;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n\n// Individual icons\n.glyphicon-asterisk { &:before { content: \"\\2a\"; } }\n.glyphicon-plus { &:before { content: \"\\2b\"; } }\n.glyphicon-euro,\n.glyphicon-eur { &:before { content: \"\\20ac\"; } }\n.glyphicon-minus { &:before { content: \"\\2212\"; } }\n.glyphicon-cloud { &:before { content: \"\\2601\"; } }\n.glyphicon-envelope { &:before { content: \"\\2709\"; } }\n.glyphicon-pencil { &:before { content: \"\\270f\"; } }\n.glyphicon-glass { &:before { content: \"\\e001\"; } }\n.glyphicon-music { &:before { content: \"\\e002\"; } }\n.glyphicon-search { &:before { content: \"\\e003\"; } }\n.glyphicon-heart { &:before { content: \"\\e005\"; } }\n.glyphicon-star { &:before { content: \"\\e006\"; } }\n.glyphicon-star-empty { &:before { content: \"\\e007\"; } }\n.glyphicon-user { &:before { content: \"\\e008\"; } }\n.glyphicon-film { &:before { content: \"\\e009\"; } }\n.glyphicon-th-large { &:before { content: \"\\e010\"; } }\n.glyphicon-th { &:before { content: \"\\e011\"; } }\n.glyphicon-th-list { &:before { content: \"\\e012\"; } }\n.glyphicon-ok { &:before { content: \"\\e013\"; } }\n.glyphicon-remove { &:before { content: \"\\e014\"; } }\n.glyphicon-zoom-in { &:before { content: \"\\e015\"; } }\n.glyphicon-zoom-out { &:before { content: \"\\e016\"; } }\n.glyphicon-off { &:before { content: \"\\e017\"; } }\n.glyphicon-signal { &:before { content: \"\\e018\"; } }\n.glyphicon-cog { &:before { content: \"\\e019\"; } }\n.glyphicon-trash { &:before { content: \"\\e020\"; } }\n.glyphicon-home { &:before { content: \"\\e021\"; } }\n.glyphicon-file { &:before { content: \"\\e022\"; } }\n.glyphicon-time { &:before { content: \"\\e023\"; } }\n.glyphicon-road { &:before { content: \"\\e024\"; } }\n.glyphicon-download-alt { &:before { content: \"\\e025\"; } }\n.glyphicon-download { &:before { content: \"\\e026\"; } }\n.glyphicon-upload { &:before { content: \"\\e027\"; } }\n.glyphicon-inbox { &:before { content: \"\\e028\"; } }\n.glyphicon-play-circle { &:before { content: \"\\e029\"; } }\n.glyphicon-repeat { &:before { content: \"\\e030\"; } }\n.glyphicon-refresh { &:before { content: \"\\e031\"; } }\n.glyphicon-list-alt { &:before { content: \"\\e032\"; } }\n.glyphicon-lock { &:before { content: \"\\e033\"; } }\n.glyphicon-flag { &:before { content: \"\\e034\"; } }\n.glyphicon-headphones { &:before { content: \"\\e035\"; } }\n.glyphicon-volume-off { &:before { content: \"\\e036\"; } }\n.glyphicon-volume-down { &:before { content: \"\\e037\"; } }\n.glyphicon-volume-up { &:before { content: \"\\e038\"; } }\n.glyphicon-qrcode { &:before { content: \"\\e039\"; } }\n.glyphicon-barcode { &:before { content: \"\\e040\"; } }\n.glyphicon-tag { &:before { content: \"\\e041\"; } }\n.glyphicon-tags { &:before { content: \"\\e042\"; } }\n.glyphicon-book { &:before { content: \"\\e043\"; } }\n.glyphicon-bookmark { &:before { content: \"\\e044\"; } }\n.glyphicon-print { &:before { content: \"\\e045\"; } }\n.glyphicon-camera { &:before { content: \"\\e046\"; } }\n.glyphicon-font { &:before { content: \"\\e047\"; } }\n.glyphicon-bold { &:before { content: \"\\e048\"; } }\n.glyphicon-italic { &:before { content: \"\\e049\"; } }\n.glyphicon-text-height { &:before { content: \"\\e050\"; } }\n.glyphicon-text-width { &:before { content: \"\\e051\"; } }\n.glyphicon-align-left { &:before { content: \"\\e052\"; } }\n.glyphicon-align-center { &:before { content: \"\\e053\"; } }\n.glyphicon-align-right { &:before { content: \"\\e054\"; } }\n.glyphicon-align-justify { &:before { content: \"\\e055\"; } }\n.glyphicon-list { &:before { content: \"\\e056\"; } }\n.glyphicon-indent-left { &:before { content: \"\\e057\"; } }\n.glyphicon-indent-right { &:before { content: \"\\e058\"; } }\n.glyphicon-facetime-video { &:before { content: \"\\e059\"; } }\n.glyphicon-picture { &:before { content: \"\\e060\"; } }\n.glyphicon-map-marker { &:before { content: \"\\e062\"; } }\n.glyphicon-adjust { &:before { content: \"\\e063\"; } }\n.glyphicon-tint { &:before { content: \"\\e064\"; } }\n.glyphicon-edit { &:before { content: \"\\e065\"; } }\n.glyphicon-share { &:before { content: \"\\e066\"; } }\n.glyphicon-check { &:before { content: \"\\e067\"; } }\n.glyphicon-move { &:before { content: \"\\e068\"; } }\n.glyphicon-step-backward { &:before { content: \"\\e069\"; } }\n.glyphicon-fast-backward { &:before { content: \"\\e070\"; } }\n.glyphicon-backward { &:before { content: \"\\e071\"; } }\n.glyphicon-play { &:before { content: \"\\e072\"; } }\n.glyphicon-pause { &:before { content: \"\\e073\"; } }\n.glyphicon-stop { &:before { content: \"\\e074\"; } }\n.glyphicon-forward { &:before { content: \"\\e075\"; } }\n.glyphicon-fast-forward { &:before { content: \"\\e076\"; } }\n.glyphicon-step-forward { &:before { content: \"\\e077\"; } }\n.glyphicon-eject { &:before { content: \"\\e078\"; } }\n.glyphicon-chevron-left { &:before { content: \"\\e079\"; } }\n.glyphicon-chevron-right { &:before { content: \"\\e080\"; } }\n.glyphicon-plus-sign { &:before { content: \"\\e081\"; } }\n.glyphicon-minus-sign { &:before { content: \"\\e082\"; } }\n.glyphicon-remove-sign { &:before { content: \"\\e083\"; } }\n.glyphicon-ok-sign { &:before { content: \"\\e084\"; } }\n.glyphicon-question-sign { &:before { content: \"\\e085\"; } }\n.glyphicon-info-sign { &:before { content: \"\\e086\"; } }\n.glyphicon-screenshot { &:before { content: \"\\e087\"; } }\n.glyphicon-remove-circle { &:before { content: \"\\e088\"; } }\n.glyphicon-ok-circle { &:before { content: \"\\e089\"; } }\n.glyphicon-ban-circle { &:before { content: \"\\e090\"; } }\n.glyphicon-arrow-left { &:before { content: \"\\e091\"; } }\n.glyphicon-arrow-right { &:before { content: \"\\e092\"; } }\n.glyphicon-arrow-up { &:before { content: \"\\e093\"; } }\n.glyphicon-arrow-down { &:before { content: \"\\e094\"; } }\n.glyphicon-share-alt { &:before { content: \"\\e095\"; } }\n.glyphicon-resize-full { &:before { content: \"\\e096\"; } }\n.glyphicon-resize-small { &:before { content: \"\\e097\"; } }\n.glyphicon-exclamation-sign { &:before { content: \"\\e101\"; } }\n.glyphicon-gift { &:before { content: \"\\e102\"; } }\n.glyphicon-leaf { &:before { content: \"\\e103\"; } }\n.glyphicon-fire { &:before { content: \"\\e104\"; } }\n.glyphicon-eye-open { &:before { content: \"\\e105\"; } }\n.glyphicon-eye-close { &:before { content: \"\\e106\"; } }\n.glyphicon-warning-sign { &:before { content: \"\\e107\"; } }\n.glyphicon-plane { &:before { content: \"\\e108\"; } }\n.glyphicon-calendar { &:before { content: \"\\e109\"; } }\n.glyphicon-random { &:before { content: \"\\e110\"; } }\n.glyphicon-comment { &:before { content: \"\\e111\"; } }\n.glyphicon-magnet { &:before { content: \"\\e112\"; } }\n.glyphicon-chevron-up { &:before { content: \"\\e113\"; } }\n.glyphicon-chevron-down { &:before { content: \"\\e114\"; } }\n.glyphicon-retweet { &:before { content: \"\\e115\"; } }\n.glyphicon-shopping-cart { &:before { content: \"\\e116\"; } }\n.glyphicon-folder-close { &:before { content: \"\\e117\"; } }\n.glyphicon-folder-open { &:before { content: \"\\e118\"; } }\n.glyphicon-resize-vertical { &:before { content: \"\\e119\"; } }\n.glyphicon-resize-horizontal { &:before { content: \"\\e120\"; } }\n.glyphicon-hdd { &:before { content: \"\\e121\"; } }\n.glyphicon-bullhorn { &:before { content: \"\\e122\"; } }\n.glyphicon-bell { &:before { content: \"\\e123\"; } }\n.glyphicon-certificate { &:before { content: \"\\e124\"; } }\n.glyphicon-thumbs-up { &:before { content: \"\\e125\"; } }\n.glyphicon-thumbs-down { &:before { content: \"\\e126\"; } }\n.glyphicon-hand-right { &:before { content: \"\\e127\"; } }\n.glyphicon-hand-left { &:before { content: \"\\e128\"; } }\n.glyphicon-hand-up { &:before { content: \"\\e129\"; } }\n.glyphicon-hand-down { &:before { content: \"\\e130\"; } }\n.glyphicon-circle-arrow-right { &:before { content: \"\\e131\"; } }\n.glyphicon-circle-arrow-left { &:before { content: \"\\e132\"; } }\n.glyphicon-circle-arrow-up { &:before { content: \"\\e133\"; } }\n.glyphicon-circle-arrow-down { &:before { content: \"\\e134\"; } }\n.glyphicon-globe { &:before { content: \"\\e135\"; } }\n.glyphicon-wrench { &:before { content: \"\\e136\"; } }\n.glyphicon-tasks { &:before { content: \"\\e137\"; } }\n.glyphicon-filter { &:before { content: \"\\e138\"; } }\n.glyphicon-briefcase { &:before { content: \"\\e139\"; } }\n.glyphicon-fullscreen { &:before { content: \"\\e140\"; } }\n.glyphicon-dashboard { &:before { content: \"\\e141\"; } }\n.glyphicon-paperclip { &:before { content: \"\\e142\"; } }\n.glyphicon-heart-empty { &:before { content: \"\\e143\"; } }\n.glyphicon-link { &:before { content: \"\\e144\"; } }\n.glyphicon-phone { &:before { content: \"\\e145\"; } }\n.glyphicon-pushpin { &:before { content: \"\\e146\"; } }\n.glyphicon-usd { &:before { content: \"\\e148\"; } }\n.glyphicon-gbp { &:before { content: \"\\e149\"; } }\n.glyphicon-sort { &:before { content: \"\\e150\"; } }\n.glyphicon-sort-by-alphabet { &:before { content: \"\\e151\"; } }\n.glyphicon-sort-by-alphabet-alt { &:before { content: \"\\e152\"; } }\n.glyphicon-sort-by-order { &:before { content: \"\\e153\"; } }\n.glyphicon-sort-by-order-alt { &:before { content: \"\\e154\"; } }\n.glyphicon-sort-by-attributes { &:before { content: \"\\e155\"; } }\n.glyphicon-sort-by-attributes-alt { &:before { content: \"\\e156\"; } }\n.glyphicon-unchecked { &:before { content: \"\\e157\"; } }\n.glyphicon-expand { &:before { content: \"\\e158\"; } }\n.glyphicon-collapse-down { &:before { content: \"\\e159\"; } }\n.glyphicon-collapse-up { &:before { content: \"\\e160\"; } }\n.glyphicon-log-in { &:before { content: \"\\e161\"; } }\n.glyphicon-flash { &:before { content: \"\\e162\"; } }\n.glyphicon-log-out { &:before { content: \"\\e163\"; } }\n.glyphicon-new-window { &:before { content: \"\\e164\"; } }\n.glyphicon-record { &:before { content: \"\\e165\"; } }\n.glyphicon-save { &:before { content: \"\\e166\"; } }\n.glyphicon-open { &:before { content: \"\\e167\"; } }\n.glyphicon-saved { &:before { content: \"\\e168\"; } }\n.glyphicon-import { &:before { content: \"\\e169\"; } }\n.glyphicon-export { &:before { content: \"\\e170\"; } }\n.glyphicon-send { &:before { content: \"\\e171\"; } }\n.glyphicon-floppy-disk { &:before { content: \"\\e172\"; } }\n.glyphicon-floppy-saved { &:before { content: \"\\e173\"; } }\n.glyphicon-floppy-remove { &:before { content: \"\\e174\"; } }\n.glyphicon-floppy-save { &:before { content: \"\\e175\"; } }\n.glyphicon-floppy-open { &:before { content: \"\\e176\"; } }\n.glyphicon-credit-card { &:before { content: \"\\e177\"; } }\n.glyphicon-transfer { &:before { content: \"\\e178\"; } }\n.glyphicon-cutlery { &:before { content: \"\\e179\"; } }\n.glyphicon-header { &:before { content: \"\\e180\"; } }\n.glyphicon-compressed { &:before { content: \"\\e181\"; } }\n.glyphicon-earphone { &:before { content: \"\\e182\"; } }\n.glyphicon-phone-alt { &:before { content: \"\\e183\"; } }\n.glyphicon-tower { &:before { content: \"\\e184\"; } }\n.glyphicon-stats { &:before { content: \"\\e185\"; } }\n.glyphicon-sd-video { &:before { content: \"\\e186\"; } }\n.glyphicon-hd-video { &:before { content: \"\\e187\"; } }\n.glyphicon-subtitles { &:before { content: \"\\e188\"; } }\n.glyphicon-sound-stereo { &:before { content: \"\\e189\"; } }\n.glyphicon-sound-dolby { &:before { content: \"\\e190\"; } }\n.glyphicon-sound-5-1 { &:before { content: \"\\e191\"; } }\n.glyphicon-sound-6-1 { &:before { content: \"\\e192\"; } }\n.glyphicon-sound-7-1 { &:before { content: \"\\e193\"; } }\n.glyphicon-copyright-mark { &:before { content: \"\\e194\"; } }\n.glyphicon-registration-mark { &:before { content: \"\\e195\"; } }\n.glyphicon-cloud-download { &:before { content: \"\\e197\"; } }\n.glyphicon-cloud-upload { &:before { content: \"\\e198\"; } }\n.glyphicon-tree-conifer { &:before { content: \"\\e199\"; } }\n.glyphicon-tree-deciduous { &:before { content: \"\\e200\"; } }\n.glyphicon-cd { &:before { content: \"\\e201\"; } }\n.glyphicon-save-file { &:before { content: \"\\e202\"; } }\n.glyphicon-open-file { &:before { content: \"\\e203\"; } }\n.glyphicon-level-up { &:before { content: \"\\e204\"; } }\n.glyphicon-copy { &:before { content: \"\\e205\"; } }\n.glyphicon-paste { &:before { content: \"\\e206\"; } }\n// The following 2 Glyphicons are omitted for the time being because\n// they currently use Unicode codepoints that are outside the\n// Basic Multilingual Plane (BMP). Older buggy versions of WebKit can't handle\n// non-BMP codepoints in CSS string escapes, and thus can't display these two icons.\n// Notably, the bug affects some older versions of the Android Browser.\n// More info: https://github.com/twbs/bootstrap/issues/10106\n// .glyphicon-door { &:before { content: \"\\1f6aa\"; } }\n// .glyphicon-key { &:before { content: \"\\1f511\"; } }\n.glyphicon-alert { &:before { content: \"\\e209\"; } }\n.glyphicon-equalizer { &:before { content: \"\\e210\"; } }\n.glyphicon-king { &:before { content: \"\\e211\"; } }\n.glyphicon-queen { &:before { content: \"\\e212\"; } }\n.glyphicon-pawn { &:before { content: \"\\e213\"; } }\n.glyphicon-bishop { &:before { content: \"\\e214\"; } }\n.glyphicon-knight { &:before { content: \"\\e215\"; } }\n.glyphicon-baby-formula { &:before { content: \"\\e216\"; } }\n.glyphicon-tent { &:before { content: \"\\26fa\"; } }\n.glyphicon-blackboard { &:before { content: \"\\e218\"; } }\n.glyphicon-bed { &:before { content: \"\\e219\"; } }\n.glyphicon-apple { &:before { content: \"\\f8ff\"; } }\n.glyphicon-erase { &:before { content: \"\\e221\"; } }\n.glyphicon-hourglass { &:before { content: \"\\231b\"; } }\n.glyphicon-lamp { &:before { content: \"\\e223\"; } }\n.glyphicon-duplicate { &:before { content: \"\\e224\"; } }\n.glyphicon-piggy-bank { &:before { content: \"\\e225\"; } }\n.glyphicon-scissors { &:before { content: \"\\e226\"; } }\n.glyphicon-bitcoin { &:before { content: \"\\e227\"; } }\n.glyphicon-btc { &:before { content: \"\\e227\"; } }\n.glyphicon-xbt { &:before { content: \"\\e227\"; } }\n.glyphicon-yen { &:before { content: \"\\00a5\"; } }\n.glyphicon-jpy { &:before { content: \"\\00a5\"; } }\n.glyphicon-ruble { &:before { content: \"\\20bd\"; } }\n.glyphicon-rub { &:before { content: \"\\20bd\"; } }\n.glyphicon-scale { &:before { content: \"\\e230\"; } }\n.glyphicon-ice-lolly { &:before { content: \"\\e231\"; } }\n.glyphicon-ice-lolly-tasted { &:before { content: \"\\e232\"; } }\n.glyphicon-education { &:before { content: \"\\e233\"; } }\n.glyphicon-option-horizontal { &:before { content: \"\\e234\"; } }\n.glyphicon-option-vertical { &:before { content: \"\\e235\"; } }\n.glyphicon-menu-hamburger { &:before { content: \"\\e236\"; } }\n.glyphicon-modal-window { &:before { content: \"\\e237\"; } }\n.glyphicon-oil { &:before { content: \"\\e238\"; } }\n.glyphicon-grain { &:before { content: \"\\e239\"; } }\n.glyphicon-sunglasses { &:before { content: \"\\e240\"; } }\n.glyphicon-text-size { &:before { content: \"\\e241\"; } }\n.glyphicon-text-color { &:before { content: \"\\e242\"; } }\n.glyphicon-text-background { &:before { content: \"\\e243\"; } }\n.glyphicon-object-align-top { &:before { content: \"\\e244\"; } }\n.glyphicon-object-align-bottom { &:before { content: \"\\e245\"; } }\n.glyphicon-object-align-horizontal{ &:before { content: \"\\e246\"; } }\n.glyphicon-object-align-left { &:before { content: \"\\e247\"; } }\n.glyphicon-object-align-vertical { &:before { content: \"\\e248\"; } }\n.glyphicon-object-align-right { &:before { content: \"\\e249\"; } }\n.glyphicon-triangle-right { &:before { content: \"\\e250\"; } }\n.glyphicon-triangle-left { &:before { content: \"\\e251\"; } }\n.glyphicon-triangle-bottom { &:before { content: \"\\e252\"; } }\n.glyphicon-triangle-top { &:before { content: \"\\e253\"; } }\n.glyphicon-console { &:before { content: \"\\e254\"; } }\n.glyphicon-superscript { &:before { content: \"\\e255\"; } }\n.glyphicon-subscript { &:before { content: \"\\e256\"; } }\n.glyphicon-menu-left { &:before { content: \"\\e257\"; } }\n.glyphicon-menu-right { &:before { content: \"\\e258\"; } }\n.glyphicon-menu-down { &:before { content: \"\\e259\"; } }\n.glyphicon-menu-up { &:before { content: \"\\e260\"; } }\n","//\n// Scaffolding\n// --------------------------------------------------\n\n\n// Reset the box-sizing\n//\n// Heads up! This reset may cause conflicts with some third-party widgets.\n// For recommendations on resolving such conflicts, see\n// http://getbootstrap.com/getting-started/#third-box-sizing\n* {\n .box-sizing(border-box);\n}\n*:before,\n*:after {\n .box-sizing(border-box);\n}\n\n\n// Body reset\n\nhtml {\n font-size: 10px;\n -webkit-tap-highlight-color: rgba(0,0,0,0);\n}\n\nbody {\n font-family: @font-family-base;\n font-size: @font-size-base;\n line-height: @line-height-base;\n color: @text-color;\n background-color: @body-bg;\n}\n\n// Reset fonts for relevant elements\ninput,\nbutton,\nselect,\ntextarea {\n font-family: inherit;\n font-size: inherit;\n line-height: inherit;\n}\n\n\n// Links\n\na {\n color: @link-color;\n text-decoration: none;\n\n &:hover,\n &:focus {\n color: @link-hover-color;\n text-decoration: @link-hover-decoration;\n }\n\n &:focus {\n .tab-focus();\n }\n}\n\n\n// Figures\n//\n// We reset this here because previously Normalize had no `figure` margins. This\n// ensures we don't break anyone's use of the element.\n\nfigure {\n margin: 0;\n}\n\n\n// Images\n\nimg {\n vertical-align: middle;\n}\n\n// Responsive images (ensure images don't scale beyond their parents)\n.img-responsive {\n .img-responsive();\n}\n\n// Rounded corners\n.img-rounded {\n border-radius: @border-radius-large;\n}\n\n// Image thumbnails\n//\n// Heads up! This is mixin-ed into thumbnails.less for `.thumbnail`.\n.img-thumbnail {\n padding: @thumbnail-padding;\n line-height: @line-height-base;\n background-color: @thumbnail-bg;\n border: 1px solid @thumbnail-border;\n border-radius: @thumbnail-border-radius;\n .transition(all .2s ease-in-out);\n\n // Keep them at most 100% wide\n .img-responsive(inline-block);\n}\n\n// Perfect circle\n.img-circle {\n border-radius: 50%; // set radius in percents\n}\n\n\n// Horizontal rules\n\nhr {\n margin-top: @line-height-computed;\n margin-bottom: @line-height-computed;\n border: 0;\n border-top: 1px solid @hr-border;\n}\n\n\n// Only display content to screen readers\n//\n// See: http://a11yproject.com/posts/how-to-hide-content/\n\n.sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n margin: -1px;\n padding: 0;\n overflow: hidden;\n clip: rect(0,0,0,0);\n border: 0;\n}\n\n// Use in conjunction with .sr-only to only display content when it's focused.\n// Useful for \"Skip to main content\" links; see http://www.w3.org/TR/2013/NOTE-WCAG20-TECHS-20130905/G1\n// Credit: HTML5 Boilerplate\n\n.sr-only-focusable {\n &:active,\n &:focus {\n position: static;\n width: auto;\n height: auto;\n margin: 0;\n overflow: visible;\n clip: auto;\n }\n}\n\n\n// iOS \"clickable elements\" fix for role=\"button\"\n//\n// Fixes \"clickability\" issue (and more generally, the firing of events such as focus as well)\n// for traditionally non-focusable elements with role=\"button\"\n// see https://developer.mozilla.org/en-US/docs/Web/Events/click#Safari_Mobile\n// Upstream patch for normalize.css submitted: https://github.com/necolas/normalize.css/pull/379 - remove this fix once that is merged\n\n[role=\"button\"] {\n cursor: pointer;\n}","// Vendor Prefixes\n//\n// All vendor mixins are deprecated as of v3.2.0 due to the introduction of\n// Autoprefixer in our Gruntfile. They will be removed in v4.\n\n// - Animations\n// - Backface visibility\n// - Box shadow\n// - Box sizing\n// - Content columns\n// - Hyphens\n// - Placeholder text\n// - Transformations\n// - Transitions\n// - User Select\n\n\n// Animations\n.animation(@animation) {\n -webkit-animation: @animation;\n -o-animation: @animation;\n animation: @animation;\n}\n.animation-name(@name) {\n -webkit-animation-name: @name;\n animation-name: @name;\n}\n.animation-duration(@duration) {\n -webkit-animation-duration: @duration;\n animation-duration: @duration;\n}\n.animation-timing-function(@timing-function) {\n -webkit-animation-timing-function: @timing-function;\n animation-timing-function: @timing-function;\n}\n.animation-delay(@delay) {\n -webkit-animation-delay: @delay;\n animation-delay: @delay;\n}\n.animation-iteration-count(@iteration-count) {\n -webkit-animation-iteration-count: @iteration-count;\n animation-iteration-count: @iteration-count;\n}\n.animation-direction(@direction) {\n -webkit-animation-direction: @direction;\n animation-direction: @direction;\n}\n.animation-fill-mode(@fill-mode) {\n -webkit-animation-fill-mode: @fill-mode;\n animation-fill-mode: @fill-mode;\n}\n\n// Backface visibility\n// Prevent browsers from flickering when using CSS 3D transforms.\n// Default value is `visible`, but can be changed to `hidden`\n\n.backface-visibility(@visibility){\n -webkit-backface-visibility: @visibility;\n -moz-backface-visibility: @visibility;\n backface-visibility: @visibility;\n}\n\n// Drop shadows\n//\n// Note: Deprecated `.box-shadow()` as of v3.1.0 since all of Bootstrap's\n// supported browsers that have box shadow capabilities now support it.\n\n.box-shadow(@shadow) {\n -webkit-box-shadow: @shadow; // iOS <4.3 & Android <4.1\n box-shadow: @shadow;\n}\n\n// Box sizing\n.box-sizing(@boxmodel) {\n -webkit-box-sizing: @boxmodel;\n -moz-box-sizing: @boxmodel;\n box-sizing: @boxmodel;\n}\n\n// CSS3 Content Columns\n.content-columns(@column-count; @column-gap: @grid-gutter-width) {\n -webkit-column-count: @column-count;\n -moz-column-count: @column-count;\n column-count: @column-count;\n -webkit-column-gap: @column-gap;\n -moz-column-gap: @column-gap;\n column-gap: @column-gap;\n}\n\n// Optional hyphenation\n.hyphens(@mode: auto) {\n word-wrap: break-word;\n -webkit-hyphens: @mode;\n -moz-hyphens: @mode;\n -ms-hyphens: @mode; // IE10+\n -o-hyphens: @mode;\n hyphens: @mode;\n}\n\n// Placeholder text\n.placeholder(@color: @input-color-placeholder) {\n // Firefox\n &::-moz-placeholder {\n color: @color;\n opacity: 1; // Override Firefox's unusual default opacity; see https://github.com/twbs/bootstrap/pull/11526\n }\n &:-ms-input-placeholder { color: @color; } // Internet Explorer 10+\n &::-webkit-input-placeholder { color: @color; } // Safari and Chrome\n}\n\n// Transformations\n.scale(@ratio) {\n -webkit-transform: scale(@ratio);\n -ms-transform: scale(@ratio); // IE9 only\n -o-transform: scale(@ratio);\n transform: scale(@ratio);\n}\n.scale(@ratioX; @ratioY) {\n -webkit-transform: scale(@ratioX, @ratioY);\n -ms-transform: scale(@ratioX, @ratioY); // IE9 only\n -o-transform: scale(@ratioX, @ratioY);\n transform: scale(@ratioX, @ratioY);\n}\n.scaleX(@ratio) {\n -webkit-transform: scaleX(@ratio);\n -ms-transform: scaleX(@ratio); // IE9 only\n -o-transform: scaleX(@ratio);\n transform: scaleX(@ratio);\n}\n.scaleY(@ratio) {\n -webkit-transform: scaleY(@ratio);\n -ms-transform: scaleY(@ratio); // IE9 only\n -o-transform: scaleY(@ratio);\n transform: scaleY(@ratio);\n}\n.skew(@x; @y) {\n -webkit-transform: skewX(@x) skewY(@y);\n -ms-transform: skewX(@x) skewY(@y); // See https://github.com/twbs/bootstrap/issues/4885; IE9+\n -o-transform: skewX(@x) skewY(@y);\n transform: skewX(@x) skewY(@y);\n}\n.translate(@x; @y) {\n -webkit-transform: translate(@x, @y);\n -ms-transform: translate(@x, @y); // IE9 only\n -o-transform: translate(@x, @y);\n transform: translate(@x, @y);\n}\n.translate3d(@x; @y; @z) {\n -webkit-transform: translate3d(@x, @y, @z);\n transform: translate3d(@x, @y, @z);\n}\n.rotate(@degrees) {\n -webkit-transform: rotate(@degrees);\n -ms-transform: rotate(@degrees); // IE9 only\n -o-transform: rotate(@degrees);\n transform: rotate(@degrees);\n}\n.rotateX(@degrees) {\n -webkit-transform: rotateX(@degrees);\n -ms-transform: rotateX(@degrees); // IE9 only\n -o-transform: rotateX(@degrees);\n transform: rotateX(@degrees);\n}\n.rotateY(@degrees) {\n -webkit-transform: rotateY(@degrees);\n -ms-transform: rotateY(@degrees); // IE9 only\n -o-transform: rotateY(@degrees);\n transform: rotateY(@degrees);\n}\n.perspective(@perspective) {\n -webkit-perspective: @perspective;\n -moz-perspective: @perspective;\n perspective: @perspective;\n}\n.perspective-origin(@perspective) {\n -webkit-perspective-origin: @perspective;\n -moz-perspective-origin: @perspective;\n perspective-origin: @perspective;\n}\n.transform-origin(@origin) {\n -webkit-transform-origin: @origin;\n -moz-transform-origin: @origin;\n -ms-transform-origin: @origin; // IE9 only\n transform-origin: @origin;\n}\n\n\n// Transitions\n\n.transition(@transition) {\n -webkit-transition: @transition;\n -o-transition: @transition;\n transition: @transition;\n}\n.transition-property(@transition-property) {\n -webkit-transition-property: @transition-property;\n transition-property: @transition-property;\n}\n.transition-delay(@transition-delay) {\n -webkit-transition-delay: @transition-delay;\n transition-delay: @transition-delay;\n}\n.transition-duration(@transition-duration) {\n -webkit-transition-duration: @transition-duration;\n transition-duration: @transition-duration;\n}\n.transition-timing-function(@timing-function) {\n -webkit-transition-timing-function: @timing-function;\n transition-timing-function: @timing-function;\n}\n.transition-transform(@transition) {\n -webkit-transition: -webkit-transform @transition;\n -moz-transition: -moz-transform @transition;\n -o-transition: -o-transform @transition;\n transition: transform @transition;\n}\n\n\n// User select\n// For selecting text on the page\n\n.user-select(@select) {\n -webkit-user-select: @select;\n -moz-user-select: @select;\n -ms-user-select: @select; // IE10+\n user-select: @select;\n}\n","// WebKit-style focus\n\n.tab-focus() {\n // Default\n outline: thin dotted;\n // WebKit\n outline: 5px auto -webkit-focus-ring-color;\n outline-offset: -2px;\n}\n","// Image Mixins\n// - Responsive image\n// - Retina image\n\n\n// Responsive image\n//\n// Keep images from scaling beyond the width of their parents.\n.img-responsive(@display: block) {\n display: @display;\n max-width: 100%; // Part 1: Set a maximum relative to the parent\n height: auto; // Part 2: Scale the height according to the width, otherwise you get stretching\n}\n\n\n// Retina image\n//\n// Short retina mixin for setting background-image and -size. Note that the\n// spelling of `min--moz-device-pixel-ratio` is intentional.\n.img-retina(@file-1x; @file-2x; @width-1x; @height-1x) {\n background-image: url(\"@{file-1x}\");\n\n @media\n only screen and (-webkit-min-device-pixel-ratio: 2),\n only screen and ( min--moz-device-pixel-ratio: 2),\n only screen and ( -o-min-device-pixel-ratio: 2/1),\n only screen and ( min-device-pixel-ratio: 2),\n only screen and ( min-resolution: 192dpi),\n only screen and ( min-resolution: 2dppx) {\n background-image: url(\"@{file-2x}\");\n background-size: @width-1x @height-1x;\n }\n}\n","//\n// Typography\n// --------------------------------------------------\n\n\n// Headings\n// -------------------------\n\nh1, h2, h3, h4, h5, h6,\n.h1, .h2, .h3, .h4, .h5, .h6 {\n font-family: @headings-font-family;\n font-weight: @headings-font-weight;\n line-height: @headings-line-height;\n color: @headings-color;\n\n small,\n .small {\n font-weight: normal;\n line-height: 1;\n color: @headings-small-color;\n }\n}\n\nh1, .h1,\nh2, .h2,\nh3, .h3 {\n margin-top: @line-height-computed;\n margin-bottom: (@line-height-computed / 2);\n\n small,\n .small {\n font-size: 65%;\n }\n}\nh4, .h4,\nh5, .h5,\nh6, .h6 {\n margin-top: (@line-height-computed / 2);\n margin-bottom: (@line-height-computed / 2);\n\n small,\n .small {\n font-size: 75%;\n }\n}\n\nh1, .h1 { font-size: @font-size-h1; }\nh2, .h2 { font-size: @font-size-h2; }\nh3, .h3 { font-size: @font-size-h3; }\nh4, .h4 { font-size: @font-size-h4; }\nh5, .h5 { font-size: @font-size-h5; }\nh6, .h6 { font-size: @font-size-h6; }\n\n\n// Body text\n// -------------------------\n\np {\n margin: 0 0 (@line-height-computed / 2);\n}\n\n.lead {\n margin-bottom: @line-height-computed;\n font-size: floor((@font-size-base * 1.15));\n font-weight: 300;\n line-height: 1.4;\n\n @media (min-width: @screen-sm-min) {\n font-size: (@font-size-base * 1.5);\n }\n}\n\n\n// Emphasis & misc\n// -------------------------\n\n// Ex: (12px small font / 14px base font) * 100% = about 85%\nsmall,\n.small {\n font-size: floor((100% * @font-size-small / @font-size-base));\n}\n\nmark,\n.mark {\n background-color: @state-warning-bg;\n padding: .2em;\n}\n\n// Alignment\n.text-left { text-align: left; }\n.text-right { text-align: right; }\n.text-center { text-align: center; }\n.text-justify { text-align: justify; }\n.text-nowrap { white-space: nowrap; }\n\n// Transformation\n.text-lowercase { text-transform: lowercase; }\n.text-uppercase { text-transform: uppercase; }\n.text-capitalize { text-transform: capitalize; }\n\n// Contextual colors\n.text-muted {\n color: @text-muted;\n}\n.text-primary {\n .text-emphasis-variant(@brand-primary);\n}\n.text-success {\n .text-emphasis-variant(@state-success-text);\n}\n.text-info {\n .text-emphasis-variant(@state-info-text);\n}\n.text-warning {\n .text-emphasis-variant(@state-warning-text);\n}\n.text-danger {\n .text-emphasis-variant(@state-danger-text);\n}\n\n// Contextual backgrounds\n// For now we'll leave these alongside the text classes until v4 when we can\n// safely shift things around (per SemVer rules).\n.bg-primary {\n // Given the contrast here, this is the only class to have its color inverted\n // automatically.\n color: #fff;\n .bg-variant(@brand-primary);\n}\n.bg-success {\n .bg-variant(@state-success-bg);\n}\n.bg-info {\n .bg-variant(@state-info-bg);\n}\n.bg-warning {\n .bg-variant(@state-warning-bg);\n}\n.bg-danger {\n .bg-variant(@state-danger-bg);\n}\n\n\n// Page header\n// -------------------------\n\n.page-header {\n padding-bottom: ((@line-height-computed / 2) - 1);\n margin: (@line-height-computed * 2) 0 @line-height-computed;\n border-bottom: 1px solid @page-header-border-color;\n}\n\n\n// Lists\n// -------------------------\n\n// Unordered and Ordered lists\nul,\nol {\n margin-top: 0;\n margin-bottom: (@line-height-computed / 2);\n ul,\n ol {\n margin-bottom: 0;\n }\n}\n\n// List options\n\n// Unstyled keeps list items block level, just removes default browser padding and list-style\n.list-unstyled {\n padding-left: 0;\n list-style: none;\n}\n\n// Inline turns list items into inline-block\n.list-inline {\n .list-unstyled();\n margin-left: -5px;\n\n > li {\n display: inline-block;\n padding-left: 5px;\n padding-right: 5px;\n }\n}\n\n// Description Lists\ndl {\n margin-top: 0; // Remove browser default\n margin-bottom: @line-height-computed;\n}\ndt,\ndd {\n line-height: @line-height-base;\n}\ndt {\n font-weight: bold;\n}\ndd {\n margin-left: 0; // Undo browser default\n}\n\n// Horizontal description lists\n//\n// Defaults to being stacked without any of the below styles applied, until the\n// grid breakpoint is reached (default of ~768px).\n\n.dl-horizontal {\n dd {\n &:extend(.clearfix all); // Clear the floated `dt` if an empty `dd` is present\n }\n\n @media (min-width: @grid-float-breakpoint) {\n dt {\n float: left;\n width: (@dl-horizontal-offset - 20);\n clear: left;\n text-align: right;\n .text-overflow();\n }\n dd {\n margin-left: @dl-horizontal-offset;\n }\n }\n}\n\n\n// Misc\n// -------------------------\n\n// Abbreviations and acronyms\nabbr[title],\n// Add data-* attribute to help out our tooltip plugin, per https://github.com/twbs/bootstrap/issues/5257\nabbr[data-original-title] {\n cursor: help;\n border-bottom: 1px dotted @abbr-border-color;\n}\n.initialism {\n font-size: 90%;\n .text-uppercase();\n}\n\n// Blockquotes\nblockquote {\n padding: (@line-height-computed / 2) @line-height-computed;\n margin: 0 0 @line-height-computed;\n font-size: @blockquote-font-size;\n border-left: 5px solid @blockquote-border-color;\n\n p,\n ul,\n ol {\n &:last-child {\n margin-bottom: 0;\n }\n }\n\n // Note: Deprecated small and .small as of v3.1.0\n // Context: https://github.com/twbs/bootstrap/issues/11660\n footer,\n small,\n .small {\n display: block;\n font-size: 80%; // back to default font-size\n line-height: @line-height-base;\n color: @blockquote-small-color;\n\n &:before {\n content: '\\2014 \\00A0'; // em dash, nbsp\n }\n }\n}\n\n// Opposite alignment of blockquote\n//\n// Heads up: `blockquote.pull-right` has been deprecated as of v3.1.0.\n.blockquote-reverse,\nblockquote.pull-right {\n padding-right: 15px;\n padding-left: 0;\n border-right: 5px solid @blockquote-border-color;\n border-left: 0;\n text-align: right;\n\n // Account for citation\n footer,\n small,\n .small {\n &:before { content: ''; }\n &:after {\n content: '\\00A0 \\2014'; // nbsp, em dash\n }\n }\n}\n\n// Addresses\naddress {\n margin-bottom: @line-height-computed;\n font-style: normal;\n line-height: @line-height-base;\n}\n","// Typography\n\n.text-emphasis-variant(@color) {\n color: @color;\n a&:hover {\n color: darken(@color, 10%);\n }\n}\n","// Contextual backgrounds\n\n.bg-variant(@color) {\n background-color: @color;\n a&:hover {\n background-color: darken(@color, 10%);\n }\n}\n","// Text overflow\n// Requires inline-block or block for proper styling\n\n.text-overflow() {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n","//\n// Code (inline and block)\n// --------------------------------------------------\n\n\n// Inline and block code styles\ncode,\nkbd,\npre,\nsamp {\n font-family: @font-family-monospace;\n}\n\n// Inline code\ncode {\n padding: 2px 4px;\n font-size: 90%;\n color: @code-color;\n background-color: @code-bg;\n border-radius: @border-radius-base;\n}\n\n// User input typically entered via keyboard\nkbd {\n padding: 2px 4px;\n font-size: 90%;\n color: @kbd-color;\n background-color: @kbd-bg;\n border-radius: @border-radius-small;\n box-shadow: inset 0 -1px 0 rgba(0,0,0,.25);\n\n kbd {\n padding: 0;\n font-size: 100%;\n font-weight: bold;\n box-shadow: none;\n }\n}\n\n// Blocks of code\npre {\n display: block;\n padding: ((@line-height-computed - 1) / 2);\n margin: 0 0 (@line-height-computed / 2);\n font-size: (@font-size-base - 1); // 14px to 13px\n line-height: @line-height-base;\n word-break: break-all;\n word-wrap: break-word;\n color: @pre-color;\n background-color: @pre-bg;\n border: 1px solid @pre-border-color;\n border-radius: @border-radius-base;\n\n // Account for some code outputs that place code tags in pre tags\n code {\n padding: 0;\n font-size: inherit;\n color: inherit;\n white-space: pre-wrap;\n background-color: transparent;\n border-radius: 0;\n }\n}\n\n// Enable scrollable blocks of code\n.pre-scrollable {\n max-height: @pre-scrollable-max-height;\n overflow-y: scroll;\n}\n","//\n// Grid system\n// --------------------------------------------------\n\n\n// Container widths\n//\n// Set the container width, and override it for fixed navbars in media queries.\n\n.container {\n .container-fixed();\n\n @media (min-width: @screen-sm-min) {\n width: @container-sm;\n }\n @media (min-width: @screen-md-min) {\n width: @container-md;\n }\n @media (min-width: @screen-lg-min) {\n width: @container-lg;\n }\n}\n\n\n// Fluid container\n//\n// Utilizes the mixin meant for fixed width containers, but without any defined\n// width for fluid, full width layouts.\n\n.container-fluid {\n .container-fixed();\n}\n\n\n// Row\n//\n// Rows contain and clear the floats of your columns.\n\n.row {\n .make-row();\n}\n\n\n// Columns\n//\n// Common styles for small and large grid columns\n\n.make-grid-columns();\n\n\n// Extra small grid\n//\n// Columns, offsets, pushes, and pulls for extra small devices like\n// smartphones.\n\n.make-grid(xs);\n\n\n// Small grid\n//\n// Columns, offsets, pushes, and pulls for the small device range, from phones\n// to tablets.\n\n@media (min-width: @screen-sm-min) {\n .make-grid(sm);\n}\n\n\n// Medium grid\n//\n// Columns, offsets, pushes, and pulls for the desktop device range.\n\n@media (min-width: @screen-md-min) {\n .make-grid(md);\n}\n\n\n// Large grid\n//\n// Columns, offsets, pushes, and pulls for the large desktop device range.\n\n@media (min-width: @screen-lg-min) {\n .make-grid(lg);\n}\n","// Grid system\n//\n// Generate semantic grid columns with these mixins.\n\n// Centered container element\n.container-fixed(@gutter: @grid-gutter-width) {\n margin-right: auto;\n margin-left: auto;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n &:extend(.clearfix all);\n}\n\n// Creates a wrapper for a series of columns\n.make-row(@gutter: @grid-gutter-width) {\n margin-left: (@gutter / -2);\n margin-right: (@gutter / -2);\n &:extend(.clearfix all);\n}\n\n// Generate the extra small columns\n.make-xs-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n float: left;\n width: percentage((@columns / @grid-columns));\n min-height: 1px;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n}\n.make-xs-column-offset(@columns) {\n margin-left: percentage((@columns / @grid-columns));\n}\n.make-xs-column-push(@columns) {\n left: percentage((@columns / @grid-columns));\n}\n.make-xs-column-pull(@columns) {\n right: percentage((@columns / @grid-columns));\n}\n\n// Generate the small columns\n.make-sm-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n min-height: 1px;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n\n @media (min-width: @screen-sm-min) {\n float: left;\n width: percentage((@columns / @grid-columns));\n }\n}\n.make-sm-column-offset(@columns) {\n @media (min-width: @screen-sm-min) {\n margin-left: percentage((@columns / @grid-columns));\n }\n}\n.make-sm-column-push(@columns) {\n @media (min-width: @screen-sm-min) {\n left: percentage((@columns / @grid-columns));\n }\n}\n.make-sm-column-pull(@columns) {\n @media (min-width: @screen-sm-min) {\n right: percentage((@columns / @grid-columns));\n }\n}\n\n// Generate the medium columns\n.make-md-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n min-height: 1px;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n\n @media (min-width: @screen-md-min) {\n float: left;\n width: percentage((@columns / @grid-columns));\n }\n}\n.make-md-column-offset(@columns) {\n @media (min-width: @screen-md-min) {\n margin-left: percentage((@columns / @grid-columns));\n }\n}\n.make-md-column-push(@columns) {\n @media (min-width: @screen-md-min) {\n left: percentage((@columns / @grid-columns));\n }\n}\n.make-md-column-pull(@columns) {\n @media (min-width: @screen-md-min) {\n right: percentage((@columns / @grid-columns));\n }\n}\n\n// Generate the large columns\n.make-lg-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n min-height: 1px;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n\n @media (min-width: @screen-lg-min) {\n float: left;\n width: percentage((@columns / @grid-columns));\n }\n}\n.make-lg-column-offset(@columns) {\n @media (min-width: @screen-lg-min) {\n margin-left: percentage((@columns / @grid-columns));\n }\n}\n.make-lg-column-push(@columns) {\n @media (min-width: @screen-lg-min) {\n left: percentage((@columns / @grid-columns));\n }\n}\n.make-lg-column-pull(@columns) {\n @media (min-width: @screen-lg-min) {\n right: percentage((@columns / @grid-columns));\n }\n}\n","// Framework grid generation\n//\n// Used only by Bootstrap to generate the correct number of grid classes given\n// any value of `@grid-columns`.\n\n.make-grid-columns() {\n // Common styles for all sizes of grid columns, widths 1-12\n .col(@index) { // initial\n @item: ~\".col-xs-@{index}, .col-sm-@{index}, .col-md-@{index}, .col-lg-@{index}\";\n .col((@index + 1), @item);\n }\n .col(@index, @list) when (@index =< @grid-columns) { // general; \"=<\" isn't a typo\n @item: ~\".col-xs-@{index}, .col-sm-@{index}, .col-md-@{index}, .col-lg-@{index}\";\n .col((@index + 1), ~\"@{list}, @{item}\");\n }\n .col(@index, @list) when (@index > @grid-columns) { // terminal\n @{list} {\n position: relative;\n // Prevent columns from collapsing when empty\n min-height: 1px;\n // Inner gutter via padding\n padding-left: (@grid-gutter-width / 2);\n padding-right: (@grid-gutter-width / 2);\n }\n }\n .col(1); // kickstart it\n}\n\n.float-grid-columns(@class) {\n .col(@index) { // initial\n @item: ~\".col-@{class}-@{index}\";\n .col((@index + 1), @item);\n }\n .col(@index, @list) when (@index =< @grid-columns) { // general\n @item: ~\".col-@{class}-@{index}\";\n .col((@index + 1), ~\"@{list}, @{item}\");\n }\n .col(@index, @list) when (@index > @grid-columns) { // terminal\n @{list} {\n float: left;\n }\n }\n .col(1); // kickstart it\n}\n\n.calc-grid-column(@index, @class, @type) when (@type = width) and (@index > 0) {\n .col-@{class}-@{index} {\n width: percentage((@index / @grid-columns));\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = push) and (@index > 0) {\n .col-@{class}-push-@{index} {\n left: percentage((@index / @grid-columns));\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = push) and (@index = 0) {\n .col-@{class}-push-0 {\n left: auto;\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = pull) and (@index > 0) {\n .col-@{class}-pull-@{index} {\n right: percentage((@index / @grid-columns));\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = pull) and (@index = 0) {\n .col-@{class}-pull-0 {\n right: auto;\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = offset) {\n .col-@{class}-offset-@{index} {\n margin-left: percentage((@index / @grid-columns));\n }\n}\n\n// Basic looping in LESS\n.loop-grid-columns(@index, @class, @type) when (@index >= 0) {\n .calc-grid-column(@index, @class, @type);\n // next iteration\n .loop-grid-columns((@index - 1), @class, @type);\n}\n\n// Create grid for specific class\n.make-grid(@class) {\n .float-grid-columns(@class);\n .loop-grid-columns(@grid-columns, @class, width);\n .loop-grid-columns(@grid-columns, @class, pull);\n .loop-grid-columns(@grid-columns, @class, push);\n .loop-grid-columns(@grid-columns, @class, offset);\n}\n","//\n// Tables\n// --------------------------------------------------\n\n\ntable {\n background-color: @table-bg;\n}\ncaption {\n padding-top: @table-cell-padding;\n padding-bottom: @table-cell-padding;\n color: @text-muted;\n text-align: left;\n}\nth {\n text-align: left;\n}\n\n\n// Baseline styles\n\n.table {\n width: 100%;\n max-width: 100%;\n margin-bottom: @line-height-computed;\n // Cells\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n padding: @table-cell-padding;\n line-height: @line-height-base;\n vertical-align: top;\n border-top: 1px solid @table-border-color;\n }\n }\n }\n // Bottom align for column headings\n > thead > tr > th {\n vertical-align: bottom;\n border-bottom: 2px solid @table-border-color;\n }\n // Remove top border from thead by default\n > caption + thead,\n > colgroup + thead,\n > thead:first-child {\n > tr:first-child {\n > th,\n > td {\n border-top: 0;\n }\n }\n }\n // Account for multiple tbody instances\n > tbody + tbody {\n border-top: 2px solid @table-border-color;\n }\n\n // Nesting\n .table {\n background-color: @body-bg;\n }\n}\n\n\n// Condensed table w/ half padding\n\n.table-condensed {\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n padding: @table-condensed-cell-padding;\n }\n }\n }\n}\n\n\n// Bordered version\n//\n// Add borders all around the table and between all the columns.\n\n.table-bordered {\n border: 1px solid @table-border-color;\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n border: 1px solid @table-border-color;\n }\n }\n }\n > thead > tr {\n > th,\n > td {\n border-bottom-width: 2px;\n }\n }\n}\n\n\n// Zebra-striping\n//\n// Default zebra-stripe styles (alternating gray and transparent backgrounds)\n\n.table-striped {\n > tbody > tr:nth-of-type(odd) {\n background-color: @table-bg-accent;\n }\n}\n\n\n// Hover effect\n//\n// Placed here since it has to come after the potential zebra striping\n\n.table-hover {\n > tbody > tr:hover {\n background-color: @table-bg-hover;\n }\n}\n\n\n// Table cell sizing\n//\n// Reset default table behavior\n\ntable col[class*=\"col-\"] {\n position: static; // Prevent border hiding in Firefox and IE9-11 (see https://github.com/twbs/bootstrap/issues/11623)\n float: none;\n display: table-column;\n}\ntable {\n td,\n th {\n &[class*=\"col-\"] {\n position: static; // Prevent border hiding in Firefox and IE9-11 (see https://github.com/twbs/bootstrap/issues/11623)\n float: none;\n display: table-cell;\n }\n }\n}\n\n\n// Table backgrounds\n//\n// Exact selectors below required to override `.table-striped` and prevent\n// inheritance to nested tables.\n\n// Generate the contextual variants\n.table-row-variant(active; @table-bg-active);\n.table-row-variant(success; @state-success-bg);\n.table-row-variant(info; @state-info-bg);\n.table-row-variant(warning; @state-warning-bg);\n.table-row-variant(danger; @state-danger-bg);\n\n\n// Responsive tables\n//\n// Wrap your tables in `.table-responsive` and we'll make them mobile friendly\n// by enabling horizontal scrolling. Only applies <768px. Everything above that\n// will display normally.\n\n.table-responsive {\n overflow-x: auto;\n min-height: 0.01%; // Workaround for IE9 bug (see https://github.com/twbs/bootstrap/issues/14837)\n\n @media screen and (max-width: @screen-xs-max) {\n width: 100%;\n margin-bottom: (@line-height-computed * 0.75);\n overflow-y: hidden;\n -ms-overflow-style: -ms-autohiding-scrollbar;\n border: 1px solid @table-border-color;\n\n // Tighten up spacing\n > .table {\n margin-bottom: 0;\n\n // Ensure the content doesn't wrap\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n white-space: nowrap;\n }\n }\n }\n }\n\n // Special overrides for the bordered tables\n > .table-bordered {\n border: 0;\n\n // Nuke the appropriate borders so that the parent can handle them\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th:first-child,\n > td:first-child {\n border-left: 0;\n }\n > th:last-child,\n > td:last-child {\n border-right: 0;\n }\n }\n }\n\n // Only nuke the last row's bottom-border in `tbody` and `tfoot` since\n // chances are there will be only one `tr` in a `thead` and that would\n // remove the border altogether.\n > tbody,\n > tfoot {\n > tr:last-child {\n > th,\n > td {\n border-bottom: 0;\n }\n }\n }\n\n }\n }\n}\n","// Tables\n\n.table-row-variant(@state; @background) {\n // Exact selectors below required to override `.table-striped` and prevent\n // inheritance to nested tables.\n .table > thead > tr,\n .table > tbody > tr,\n .table > tfoot > tr {\n > td.@{state},\n > th.@{state},\n &.@{state} > td,\n &.@{state} > th {\n background-color: @background;\n }\n }\n\n // Hover states for `.table-hover`\n // Note: this is not available for cells or rows within `thead` or `tfoot`.\n .table-hover > tbody > tr {\n > td.@{state}:hover,\n > th.@{state}:hover,\n &.@{state}:hover > td,\n &:hover > .@{state},\n &.@{state}:hover > th {\n background-color: darken(@background, 5%);\n }\n }\n}\n","//\n// Forms\n// --------------------------------------------------\n\n\n// Normalize non-controls\n//\n// Restyle and baseline non-control form elements.\n\nfieldset {\n padding: 0;\n margin: 0;\n border: 0;\n // Chrome and Firefox set a `min-width: min-content;` on fieldsets,\n // so we reset that to ensure it behaves more like a standard block element.\n // See https://github.com/twbs/bootstrap/issues/12359.\n min-width: 0;\n}\n\nlegend {\n display: block;\n width: 100%;\n padding: 0;\n margin-bottom: @line-height-computed;\n font-size: (@font-size-base * 1.5);\n line-height: inherit;\n color: @legend-color;\n border: 0;\n border-bottom: 1px solid @legend-border-color;\n}\n\nlabel {\n display: inline-block;\n max-width: 100%; // Force IE8 to wrap long content (see https://github.com/twbs/bootstrap/issues/13141)\n margin-bottom: 5px;\n font-weight: bold;\n}\n\n\n// Normalize form controls\n//\n// While most of our form styles require extra classes, some basic normalization\n// is required to ensure optimum display with or without those classes to better\n// address browser inconsistencies.\n\n// Override content-box in Normalize (* isn't specific enough)\ninput[type=\"search\"] {\n .box-sizing(border-box);\n}\n\n// Position radios and checkboxes better\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n margin: 4px 0 0;\n margin-top: 1px \\9; // IE8-9\n line-height: normal;\n}\n\n// Set the height of file controls to match text inputs\ninput[type=\"file\"] {\n display: block;\n}\n\n// Make range inputs behave like textual form controls\ninput[type=\"range\"] {\n display: block;\n width: 100%;\n}\n\n// Make multiple select elements height not fixed\nselect[multiple],\nselect[size] {\n height: auto;\n}\n\n// Focus for file, radio, and checkbox\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n .tab-focus();\n}\n\n// Adjust output element\noutput {\n display: block;\n padding-top: (@padding-base-vertical + 1);\n font-size: @font-size-base;\n line-height: @line-height-base;\n color: @input-color;\n}\n\n\n// Common form controls\n//\n// Shared size and type resets for form controls. Apply `.form-control` to any\n// of the following form controls:\n//\n// select\n// textarea\n// input[type=\"text\"]\n// input[type=\"password\"]\n// input[type=\"datetime\"]\n// input[type=\"datetime-local\"]\n// input[type=\"date\"]\n// input[type=\"month\"]\n// input[type=\"time\"]\n// input[type=\"week\"]\n// input[type=\"number\"]\n// input[type=\"email\"]\n// input[type=\"url\"]\n// input[type=\"search\"]\n// input[type=\"tel\"]\n// input[type=\"color\"]\n\n.form-control {\n display: block;\n width: 100%;\n height: @input-height-base; // Make inputs at least the height of their button counterpart (base line-height + padding + border)\n padding: @padding-base-vertical @padding-base-horizontal;\n font-size: @font-size-base;\n line-height: @line-height-base;\n color: @input-color;\n background-color: @input-bg;\n background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214\n border: 1px solid @input-border;\n border-radius: @input-border-radius; // Note: This has no effect on <select>s in some browsers, due to the limited stylability of <select>s in CSS.\n .box-shadow(inset 0 1px 1px rgba(0,0,0,.075));\n .transition(~\"border-color ease-in-out .15s, box-shadow ease-in-out .15s\");\n\n // Customize the `:focus` state to imitate native WebKit styles.\n .form-control-focus();\n\n // Placeholder\n .placeholder();\n\n // Disabled and read-only inputs\n //\n // HTML5 says that controls under a fieldset > legend:first-child won't be\n // disabled if the fieldset is disabled. Due to implementation difficulty, we\n // don't honor that edge case; we style them as disabled anyway.\n &[disabled],\n &[readonly],\n fieldset[disabled] & {\n background-color: @input-bg-disabled;\n opacity: 1; // iOS fix for unreadable disabled content; see https://github.com/twbs/bootstrap/issues/11655\n }\n\n &[disabled],\n fieldset[disabled] & {\n cursor: @cursor-disabled;\n }\n\n // Reset height for `textarea`s\n textarea& {\n height: auto;\n }\n}\n\n\n// Search inputs in iOS\n//\n// This overrides the extra rounded corners on search inputs in iOS so that our\n// `.form-control` class can properly style them. Note that this cannot simply\n// be added to `.form-control` as it's not specific enough. For details, see\n// https://github.com/twbs/bootstrap/issues/11586.\n\ninput[type=\"search\"] {\n -webkit-appearance: none;\n}\n\n\n// Special styles for iOS temporal inputs\n//\n// In Mobile Safari, setting `display: block` on temporal inputs causes the\n// text within the input to become vertically misaligned. As a workaround, we\n// set a pixel line-height that matches the given height of the input, but only\n// for Safari. See https://bugs.webkit.org/show_bug.cgi?id=139848\n\n@media screen and (-webkit-min-device-pixel-ratio: 0) {\n input[type=\"date\"],\n input[type=\"time\"],\n input[type=\"datetime-local\"],\n input[type=\"month\"] {\n line-height: @input-height-base;\n\n &.input-sm,\n .input-group-sm & {\n line-height: @input-height-small;\n }\n\n &.input-lg,\n .input-group-lg & {\n line-height: @input-height-large;\n }\n }\n}\n\n\n// Form groups\n//\n// Designed to help with the organization and spacing of vertical forms. For\n// horizontal forms, use the predefined grid classes.\n\n.form-group {\n margin-bottom: @form-group-margin-bottom;\n}\n\n\n// Checkboxes and radios\n//\n// Indent the labels to position radios/checkboxes as hanging controls.\n\n.radio,\n.checkbox {\n position: relative;\n display: block;\n margin-top: 10px;\n margin-bottom: 10px;\n\n label {\n min-height: @line-height-computed; // Ensure the input doesn't jump when there is no text\n padding-left: 20px;\n margin-bottom: 0;\n font-weight: normal;\n cursor: pointer;\n }\n}\n.radio input[type=\"radio\"],\n.radio-inline input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"],\n.checkbox-inline input[type=\"checkbox\"] {\n position: absolute;\n margin-left: -20px;\n margin-top: 4px \\9;\n}\n\n.radio + .radio,\n.checkbox + .checkbox {\n margin-top: -5px; // Move up sibling radios or checkboxes for tighter spacing\n}\n\n// Radios and checkboxes on same line\n.radio-inline,\n.checkbox-inline {\n position: relative;\n display: inline-block;\n padding-left: 20px;\n margin-bottom: 0;\n vertical-align: middle;\n font-weight: normal;\n cursor: pointer;\n}\n.radio-inline + .radio-inline,\n.checkbox-inline + .checkbox-inline {\n margin-top: 0;\n margin-left: 10px; // space out consecutive inline controls\n}\n\n// Apply same disabled cursor tweak as for inputs\n// Some special care is needed because <label>s don't inherit their parent's `cursor`.\n//\n// Note: Neither radios nor checkboxes can be readonly.\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n &[disabled],\n &.disabled,\n fieldset[disabled] & {\n cursor: @cursor-disabled;\n }\n}\n// These classes are used directly on <label>s\n.radio-inline,\n.checkbox-inline {\n &.disabled,\n fieldset[disabled] & {\n cursor: @cursor-disabled;\n }\n}\n// These classes are used on elements with <label> descendants\n.radio,\n.checkbox {\n &.disabled,\n fieldset[disabled] & {\n label {\n cursor: @cursor-disabled;\n }\n }\n}\n\n\n// Static form control text\n//\n// Apply class to a `p` element to make any string of text align with labels in\n// a horizontal form layout.\n\n.form-control-static {\n // Size it appropriately next to real form controls\n padding-top: (@padding-base-vertical + 1);\n padding-bottom: (@padding-base-vertical + 1);\n // Remove default margin from `p`\n margin-bottom: 0;\n min-height: (@line-height-computed + @font-size-base);\n\n &.input-lg,\n &.input-sm {\n padding-left: 0;\n padding-right: 0;\n }\n}\n\n\n// Form control sizing\n//\n// Build on `.form-control` with modifier classes to decrease or increase the\n// height and font-size of form controls.\n//\n// The `.form-group-* form-control` variations are sadly duplicated to avoid the\n// issue documented in https://github.com/twbs/bootstrap/issues/15074.\n\n.input-sm {\n .input-size(@input-height-small; @padding-small-vertical; @padding-small-horizontal; @font-size-small; @line-height-small; @input-border-radius-small);\n}\n.form-group-sm {\n .form-control {\n .input-size(@input-height-small; @padding-small-vertical; @padding-small-horizontal; @font-size-small; @line-height-small; @input-border-radius-small);\n }\n .form-control-static {\n height: @input-height-small;\n padding: @padding-small-vertical @padding-small-horizontal;\n font-size: @font-size-small;\n line-height: @line-height-small;\n min-height: (@line-height-computed + @font-size-small);\n }\n}\n\n.input-lg {\n .input-size(@input-height-large; @padding-large-vertical; @padding-large-horizontal; @font-size-large; @line-height-large; @input-border-radius-large);\n}\n.form-group-lg {\n .form-control {\n .input-size(@input-height-large; @padding-large-vertical; @padding-large-horizontal; @font-size-large; @line-height-large; @input-border-radius-large);\n }\n .form-control-static {\n height: @input-height-large;\n padding: @padding-large-vertical @padding-large-horizontal;\n font-size: @font-size-large;\n line-height: @line-height-large;\n min-height: (@line-height-computed + @font-size-large);\n }\n}\n\n\n// Form control feedback states\n//\n// Apply contextual and semantic states to individual form controls.\n\n.has-feedback {\n // Enable absolute positioning\n position: relative;\n\n // Ensure icons don't overlap text\n .form-control {\n padding-right: (@input-height-base * 1.25);\n }\n}\n// Feedback icon (requires .glyphicon classes)\n.form-control-feedback {\n position: absolute;\n top: 0;\n right: 0;\n z-index: 2; // Ensure icon is above input groups\n display: block;\n width: @input-height-base;\n height: @input-height-base;\n line-height: @input-height-base;\n text-align: center;\n pointer-events: none;\n}\n.input-lg + .form-control-feedback {\n width: @input-height-large;\n height: @input-height-large;\n line-height: @input-height-large;\n}\n.input-sm + .form-control-feedback {\n width: @input-height-small;\n height: @input-height-small;\n line-height: @input-height-small;\n}\n\n// Feedback states\n.has-success {\n .form-control-validation(@state-success-text; @state-success-text; @state-success-bg);\n}\n.has-warning {\n .form-control-validation(@state-warning-text; @state-warning-text; @state-warning-bg);\n}\n.has-error {\n .form-control-validation(@state-danger-text; @state-danger-text; @state-danger-bg);\n}\n\n// Reposition feedback icon if input has visible label above\n.has-feedback label {\n\n & ~ .form-control-feedback {\n top: (@line-height-computed + 5); // Height of the `label` and its margin\n }\n &.sr-only ~ .form-control-feedback {\n top: 0;\n }\n}\n\n\n// Help text\n//\n// Apply to any element you wish to create light text for placement immediately\n// below a form control. Use for general help, formatting, or instructional text.\n\n.help-block {\n display: block; // account for any element using help-block\n margin-top: 5px;\n margin-bottom: 10px;\n color: lighten(@text-color, 25%); // lighten the text some for contrast\n}\n\n\n// Inline forms\n//\n// Make forms appear inline(-block) by adding the `.form-inline` class. Inline\n// forms begin stacked on extra small (mobile) devices and then go inline when\n// viewports reach <768px.\n//\n// Requires wrapping inputs and labels with `.form-group` for proper display of\n// default HTML form controls and our custom form controls (e.g., input groups).\n//\n// Heads up! This is mixin-ed into `.navbar-form` in navbars.less.\n\n.form-inline {\n\n // Kick in the inline\n @media (min-width: @screen-sm-min) {\n // Inline-block all the things for \"inline\"\n .form-group {\n display: inline-block;\n margin-bottom: 0;\n vertical-align: middle;\n }\n\n // In navbar-form, allow folks to *not* use `.form-group`\n .form-control {\n display: inline-block;\n width: auto; // Prevent labels from stacking above inputs in `.form-group`\n vertical-align: middle;\n }\n\n // Make static controls behave like regular ones\n .form-control-static {\n display: inline-block;\n }\n\n .input-group {\n display: inline-table;\n vertical-align: middle;\n\n .input-group-addon,\n .input-group-btn,\n .form-control {\n width: auto;\n }\n }\n\n // Input groups need that 100% width though\n .input-group > .form-control {\n width: 100%;\n }\n\n .control-label {\n margin-bottom: 0;\n vertical-align: middle;\n }\n\n // Remove default margin on radios/checkboxes that were used for stacking, and\n // then undo the floating of radios and checkboxes to match.\n .radio,\n .checkbox {\n display: inline-block;\n margin-top: 0;\n margin-bottom: 0;\n vertical-align: middle;\n\n label {\n padding-left: 0;\n }\n }\n .radio input[type=\"radio\"],\n .checkbox input[type=\"checkbox\"] {\n position: relative;\n margin-left: 0;\n }\n\n // Re-override the feedback icon.\n .has-feedback .form-control-feedback {\n top: 0;\n }\n }\n}\n\n\n// Horizontal forms\n//\n// Horizontal forms are built on grid classes and allow you to create forms with\n// labels on the left and inputs on the right.\n\n.form-horizontal {\n\n // Consistent vertical alignment of radios and checkboxes\n //\n // Labels also get some reset styles, but that is scoped to a media query below.\n .radio,\n .checkbox,\n .radio-inline,\n .checkbox-inline {\n margin-top: 0;\n margin-bottom: 0;\n padding-top: (@padding-base-vertical + 1); // Default padding plus a border\n }\n // Account for padding we're adding to ensure the alignment and of help text\n // and other content below items\n .radio,\n .checkbox {\n min-height: (@line-height-computed + (@padding-base-vertical + 1));\n }\n\n // Make form groups behave like rows\n .form-group {\n .make-row();\n }\n\n // Reset spacing and right align labels, but scope to media queries so that\n // labels on narrow viewports stack the same as a default form example.\n @media (min-width: @screen-sm-min) {\n .control-label {\n text-align: right;\n margin-bottom: 0;\n padding-top: (@padding-base-vertical + 1); // Default padding plus a border\n }\n }\n\n // Validation states\n //\n // Reposition the icon because it's now within a grid column and columns have\n // `position: relative;` on them. Also accounts for the grid gutter padding.\n .has-feedback .form-control-feedback {\n right: (@grid-gutter-width / 2);\n }\n\n // Form group sizes\n //\n // Quick utility class for applying `.input-lg` and `.input-sm` styles to the\n // inputs and labels within a `.form-group`.\n .form-group-lg {\n @media (min-width: @screen-sm-min) {\n .control-label {\n padding-top: ((@padding-large-vertical * @line-height-large) + 1);\n }\n }\n }\n .form-group-sm {\n @media (min-width: @screen-sm-min) {\n .control-label {\n padding-top: (@padding-small-vertical + 1);\n }\n }\n }\n}\n","// Form validation states\n//\n// Used in forms.less to generate the form validation CSS for warnings, errors,\n// and successes.\n\n.form-control-validation(@text-color: #555; @border-color: #ccc; @background-color: #f5f5f5) {\n // Color the label and help text\n .help-block,\n .control-label,\n .radio,\n .checkbox,\n .radio-inline,\n .checkbox-inline,\n &.radio label,\n &.checkbox label,\n &.radio-inline label,\n &.checkbox-inline label {\n color: @text-color;\n }\n // Set the border and box shadow on specific inputs to match\n .form-control {\n border-color: @border-color;\n .box-shadow(inset 0 1px 1px rgba(0,0,0,.075)); // Redeclare so transitions work\n &:focus {\n border-color: darken(@border-color, 10%);\n @shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 6px lighten(@border-color, 20%);\n .box-shadow(@shadow);\n }\n }\n // Set validation states also for addons\n .input-group-addon {\n color: @text-color;\n border-color: @border-color;\n background-color: @background-color;\n }\n // Optional feedback icon\n .form-control-feedback {\n color: @text-color;\n }\n}\n\n\n// Form control focus state\n//\n// Generate a customized focus state and for any input with the specified color,\n// which defaults to the `@input-border-focus` variable.\n//\n// We highly encourage you to not customize the default value, but instead use\n// this to tweak colors on an as-needed basis. This aesthetic change is based on\n// WebKit's default styles, but applicable to a wider range of browsers. Its\n// usability and accessibility should be taken into account with any change.\n//\n// Example usage: change the default blue border and shadow to white for better\n// contrast against a dark gray background.\n.form-control-focus(@color: @input-border-focus) {\n @color-rgba: rgba(red(@color), green(@color), blue(@color), .6);\n &:focus {\n border-color: @color;\n outline: 0;\n .box-shadow(~\"inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px @{color-rgba}\");\n }\n}\n\n// Form control sizing\n//\n// Relative text size, padding, and border-radii changes for form controls. For\n// horizontal sizing, wrap controls in the predefined grid classes. `<select>`\n// element gets special love because it's special, and that's a fact!\n.input-size(@input-height; @padding-vertical; @padding-horizontal; @font-size; @line-height; @border-radius) {\n height: @input-height;\n padding: @padding-vertical @padding-horizontal;\n font-size: @font-size;\n line-height: @line-height;\n border-radius: @border-radius;\n\n select& {\n height: @input-height;\n line-height: @input-height;\n }\n\n textarea&,\n select[multiple]& {\n height: auto;\n }\n}\n","//\n// Buttons\n// --------------------------------------------------\n\n\n// Base styles\n// --------------------------------------------------\n\n.btn {\n display: inline-block;\n margin-bottom: 0; // For input.btn\n font-weight: @btn-font-weight;\n text-align: center;\n vertical-align: middle;\n touch-action: manipulation;\n cursor: pointer;\n background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214\n border: 1px solid transparent;\n white-space: nowrap;\n .button-size(@padding-base-vertical; @padding-base-horizontal; @font-size-base; @line-height-base; @border-radius-base);\n .user-select(none);\n\n &,\n &:active,\n &.active {\n &:focus,\n &.focus {\n .tab-focus();\n }\n }\n\n &:hover,\n &:focus,\n &.focus {\n color: @btn-default-color;\n text-decoration: none;\n }\n\n &:active,\n &.active {\n outline: 0;\n background-image: none;\n .box-shadow(inset 0 3px 5px rgba(0,0,0,.125));\n }\n\n &.disabled,\n &[disabled],\n fieldset[disabled] & {\n cursor: @cursor-disabled;\n pointer-events: none; // Future-proof disabling of clicks\n .opacity(.65);\n .box-shadow(none);\n }\n}\n\n\n// Alternate buttons\n// --------------------------------------------------\n\n.btn-default {\n .button-variant(@btn-default-color; @btn-default-bg; @btn-default-border);\n}\n.btn-primary {\n .button-variant(@btn-primary-color; @btn-primary-bg; @btn-primary-border);\n}\n// Success appears as green\n.btn-success {\n .button-variant(@btn-success-color; @btn-success-bg; @btn-success-border);\n}\n// Info appears as blue-green\n.btn-info {\n .button-variant(@btn-info-color; @btn-info-bg; @btn-info-border);\n}\n// Warning appears as orange\n.btn-warning {\n .button-variant(@btn-warning-color; @btn-warning-bg; @btn-warning-border);\n}\n// Danger and error appear as red\n.btn-danger {\n .button-variant(@btn-danger-color; @btn-danger-bg; @btn-danger-border);\n}\n\n\n// Link buttons\n// -------------------------\n\n// Make a button look and behave like a link\n.btn-link {\n color: @link-color;\n font-weight: normal;\n border-radius: 0;\n\n &,\n &:active,\n &.active,\n &[disabled],\n fieldset[disabled] & {\n background-color: transparent;\n .box-shadow(none);\n }\n &,\n &:hover,\n &:focus,\n &:active {\n border-color: transparent;\n }\n &:hover,\n &:focus {\n color: @link-hover-color;\n text-decoration: @link-hover-decoration;\n background-color: transparent;\n }\n &[disabled],\n fieldset[disabled] & {\n &:hover,\n &:focus {\n color: @btn-link-disabled-color;\n text-decoration: none;\n }\n }\n}\n\n\n// Button Sizes\n// --------------------------------------------------\n\n.btn-lg {\n // line-height: ensure even-numbered height of button next to large input\n .button-size(@padding-large-vertical; @padding-large-horizontal; @font-size-large; @line-height-large; @border-radius-large);\n}\n.btn-sm {\n // line-height: ensure proper height of button next to small input\n .button-size(@padding-small-vertical; @padding-small-horizontal; @font-size-small; @line-height-small; @border-radius-small);\n}\n.btn-xs {\n .button-size(@padding-xs-vertical; @padding-xs-horizontal; @font-size-small; @line-height-small; @border-radius-small);\n}\n\n\n// Block button\n// --------------------------------------------------\n\n.btn-block {\n display: block;\n width: 100%;\n}\n\n// Vertically space out multiple block buttons\n.btn-block + .btn-block {\n margin-top: 5px;\n}\n\n// Specificity overrides\ninput[type=\"submit\"],\ninput[type=\"reset\"],\ninput[type=\"button\"] {\n &.btn-block {\n width: 100%;\n }\n}\n","// Button variants\n//\n// Easily pump out default styles, as well as :hover, :focus, :active,\n// and disabled options for all buttons\n\n.button-variant(@color; @background; @border) {\n color: @color;\n background-color: @background;\n border-color: @border;\n\n &:hover,\n &:focus,\n &.focus,\n &:active,\n &.active,\n .open > .dropdown-toggle& {\n color: @color;\n background-color: darken(@background, 10%);\n border-color: darken(@border, 12%);\n }\n &:active,\n &.active,\n .open > .dropdown-toggle& {\n background-image: none;\n }\n &.disabled,\n &[disabled],\n fieldset[disabled] & {\n &,\n &:hover,\n &:focus,\n &.focus,\n &:active,\n &.active {\n background-color: @background;\n border-color: @border;\n }\n }\n\n .badge {\n color: @background;\n background-color: @color;\n }\n}\n\n// Button sizes\n.button-size(@padding-vertical; @padding-horizontal; @font-size; @line-height; @border-radius) {\n padding: @padding-vertical @padding-horizontal;\n font-size: @font-size;\n line-height: @line-height;\n border-radius: @border-radius;\n}\n","// Opacity\n\n.opacity(@opacity) {\n opacity: @opacity;\n // IE8 filter\n @opacity-ie: (@opacity * 100);\n filter: ~\"alpha(opacity=@{opacity-ie})\";\n}\n","//\n// Component animations\n// --------------------------------------------------\n\n// Heads up!\n//\n// We don't use the `.opacity()` mixin here since it causes a bug with text\n// fields in IE7-8. Source: https://github.com/twbs/bootstrap/pull/3552.\n\n.fade {\n opacity: 0;\n .transition(opacity .15s linear);\n &.in {\n opacity: 1;\n }\n}\n\n.collapse {\n display: none;\n\n &.in { display: block; }\n tr&.in { display: table-row; }\n tbody&.in { display: table-row-group; }\n}\n\n.collapsing {\n position: relative;\n height: 0;\n overflow: hidden;\n .transition-property(~\"height, visibility\");\n .transition-duration(.35s);\n .transition-timing-function(ease);\n}\n","//\n// Dropdown menus\n// --------------------------------------------------\n\n\n// Dropdown arrow/caret\n.caret {\n display: inline-block;\n width: 0;\n height: 0;\n margin-left: 2px;\n vertical-align: middle;\n border-top: @caret-width-base dashed;\n border-right: @caret-width-base solid transparent;\n border-left: @caret-width-base solid transparent;\n}\n\n// The dropdown wrapper (div)\n.dropup,\n.dropdown {\n position: relative;\n}\n\n// Prevent the focus on the dropdown toggle when closing dropdowns\n.dropdown-toggle:focus {\n outline: 0;\n}\n\n// The dropdown menu (ul)\n.dropdown-menu {\n position: absolute;\n top: 100%;\n left: 0;\n z-index: @zindex-dropdown;\n display: none; // none by default, but block on \"open\" of the menu\n float: left;\n min-width: 160px;\n padding: 5px 0;\n margin: 2px 0 0; // override default ul\n list-style: none;\n font-size: @font-size-base;\n text-align: left; // Ensures proper alignment if parent has it changed (e.g., modal footer)\n background-color: @dropdown-bg;\n border: 1px solid @dropdown-fallback-border; // IE8 fallback\n border: 1px solid @dropdown-border;\n border-radius: @border-radius-base;\n .box-shadow(0 6px 12px rgba(0,0,0,.175));\n background-clip: padding-box;\n\n // Aligns the dropdown menu to right\n //\n // Deprecated as of 3.1.0 in favor of `.dropdown-menu-[dir]`\n &.pull-right {\n right: 0;\n left: auto;\n }\n\n // Dividers (basically an hr) within the dropdown\n .divider {\n .nav-divider(@dropdown-divider-bg);\n }\n\n // Links within the dropdown menu\n > li > a {\n display: block;\n padding: 3px 20px;\n clear: both;\n font-weight: normal;\n line-height: @line-height-base;\n color: @dropdown-link-color;\n white-space: nowrap; // prevent links from randomly breaking onto new lines\n }\n}\n\n// Hover/Focus state\n.dropdown-menu > li > a {\n &:hover,\n &:focus {\n text-decoration: none;\n color: @dropdown-link-hover-color;\n background-color: @dropdown-link-hover-bg;\n }\n}\n\n// Active state\n.dropdown-menu > .active > a {\n &,\n &:hover,\n &:focus {\n color: @dropdown-link-active-color;\n text-decoration: none;\n outline: 0;\n background-color: @dropdown-link-active-bg;\n }\n}\n\n// Disabled state\n//\n// Gray out text and ensure the hover/focus state remains gray\n\n.dropdown-menu > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @dropdown-link-disabled-color;\n }\n\n // Nuke hover/focus effects\n &:hover,\n &:focus {\n text-decoration: none;\n background-color: transparent;\n background-image: none; // Remove CSS gradient\n .reset-filter();\n cursor: @cursor-disabled;\n }\n}\n\n// Open state for the dropdown\n.open {\n // Show the menu\n > .dropdown-menu {\n display: block;\n }\n\n // Remove the outline when :focus is triggered\n > a {\n outline: 0;\n }\n}\n\n// Menu positioning\n//\n// Add extra class to `.dropdown-menu` to flip the alignment of the dropdown\n// menu with the parent.\n.dropdown-menu-right {\n left: auto; // Reset the default from `.dropdown-menu`\n right: 0;\n}\n// With v3, we enabled auto-flipping if you have a dropdown within a right\n// aligned nav component. To enable the undoing of that, we provide an override\n// to restore the default dropdown menu alignment.\n//\n// This is only for left-aligning a dropdown menu within a `.navbar-right` or\n// `.pull-right` nav component.\n.dropdown-menu-left {\n left: 0;\n right: auto;\n}\n\n// Dropdown section headers\n.dropdown-header {\n display: block;\n padding: 3px 20px;\n font-size: @font-size-small;\n line-height: @line-height-base;\n color: @dropdown-header-color;\n white-space: nowrap; // as with > li > a\n}\n\n// Backdrop to catch body clicks on mobile, etc.\n.dropdown-backdrop {\n position: fixed;\n left: 0;\n right: 0;\n bottom: 0;\n top: 0;\n z-index: (@zindex-dropdown - 10);\n}\n\n// Right aligned dropdowns\n.pull-right > .dropdown-menu {\n right: 0;\n left: auto;\n}\n\n// Allow for dropdowns to go bottom up (aka, dropup-menu)\n//\n// Just add .dropup after the standard .dropdown class and you're set, bro.\n// TODO: abstract this so that the navbar fixed styles are not placed here?\n\n.dropup,\n.navbar-fixed-bottom .dropdown {\n // Reverse the caret\n .caret {\n border-top: 0;\n border-bottom: @caret-width-base solid;\n content: \"\";\n }\n // Different positioning for bottom up menu\n .dropdown-menu {\n top: auto;\n bottom: 100%;\n margin-bottom: 2px;\n }\n}\n\n\n// Component alignment\n//\n// Reiterate per navbar.less and the modified component alignment there.\n\n@media (min-width: @grid-float-breakpoint) {\n .navbar-right {\n .dropdown-menu {\n .dropdown-menu-right();\n }\n // Necessary for overrides of the default right aligned menu.\n // Will remove come v4 in all likelihood.\n .dropdown-menu-left {\n .dropdown-menu-left();\n }\n }\n}\n","// Horizontal dividers\n//\n// Dividers (basically an hr) within dropdowns and nav lists\n\n.nav-divider(@color: #e5e5e5) {\n height: 1px;\n margin: ((@line-height-computed / 2) - 1) 0;\n overflow: hidden;\n background-color: @color;\n}\n","// Reset filters for IE\n//\n// When you need to remove a gradient background, do not forget to use this to reset\n// the IE filter for IE9 and below.\n\n.reset-filter() {\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(enabled = false)\"));\n}\n","//\n// Button groups\n// --------------------------------------------------\n\n// Make the div behave like a button\n.btn-group,\n.btn-group-vertical {\n position: relative;\n display: inline-block;\n vertical-align: middle; // match .btn alignment given font-size hack above\n > .btn {\n position: relative;\n float: left;\n // Bring the \"active\" button to the front\n &:hover,\n &:focus,\n &:active,\n &.active {\n z-index: 2;\n }\n }\n}\n\n// Prevent double borders when buttons are next to each other\n.btn-group {\n .btn + .btn,\n .btn + .btn-group,\n .btn-group + .btn,\n .btn-group + .btn-group {\n margin-left: -1px;\n }\n}\n\n// Optional: Group multiple button groups together for a toolbar\n.btn-toolbar {\n margin-left: -5px; // Offset the first child's margin\n &:extend(.clearfix all);\n\n .btn-group,\n .input-group {\n float: left;\n }\n > .btn,\n > .btn-group,\n > .input-group {\n margin-left: 5px;\n }\n}\n\n.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) {\n border-radius: 0;\n}\n\n// Set corners individual because sometimes a single button can be in a .btn-group and we need :first-child and :last-child to both match\n.btn-group > .btn:first-child {\n margin-left: 0;\n &:not(:last-child):not(.dropdown-toggle) {\n .border-right-radius(0);\n }\n}\n// Need .dropdown-toggle since :last-child doesn't apply given a .dropdown-menu immediately after it\n.btn-group > .btn:last-child:not(:first-child),\n.btn-group > .dropdown-toggle:not(:first-child) {\n .border-left-radius(0);\n}\n\n// Custom edits for including btn-groups within btn-groups (useful for including dropdown buttons within a btn-group)\n.btn-group > .btn-group {\n float: left;\n}\n.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn {\n border-radius: 0;\n}\n.btn-group > .btn-group:first-child:not(:last-child) {\n > .btn:last-child,\n > .dropdown-toggle {\n .border-right-radius(0);\n }\n}\n.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child {\n .border-left-radius(0);\n}\n\n// On active and open, don't show outline\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n outline: 0;\n}\n\n\n// Sizing\n//\n// Remix the default button sizing classes into new ones for easier manipulation.\n\n.btn-group-xs > .btn { &:extend(.btn-xs); }\n.btn-group-sm > .btn { &:extend(.btn-sm); }\n.btn-group-lg > .btn { &:extend(.btn-lg); }\n\n\n// Split button dropdowns\n// ----------------------\n\n// Give the line between buttons some depth\n.btn-group > .btn + .dropdown-toggle {\n padding-left: 8px;\n padding-right: 8px;\n}\n.btn-group > .btn-lg + .dropdown-toggle {\n padding-left: 12px;\n padding-right: 12px;\n}\n\n// The clickable button for toggling the menu\n// Remove the gradient and set the same inset shadow as the :active state\n.btn-group.open .dropdown-toggle {\n .box-shadow(inset 0 3px 5px rgba(0,0,0,.125));\n\n // Show no shadow for `.btn-link` since it has no other button styles.\n &.btn-link {\n .box-shadow(none);\n }\n}\n\n\n// Reposition the caret\n.btn .caret {\n margin-left: 0;\n}\n// Carets in other button sizes\n.btn-lg .caret {\n border-width: @caret-width-large @caret-width-large 0;\n border-bottom-width: 0;\n}\n// Upside down carets for .dropup\n.dropup .btn-lg .caret {\n border-width: 0 @caret-width-large @caret-width-large;\n}\n\n\n// Vertical button groups\n// ----------------------\n\n.btn-group-vertical {\n > .btn,\n > .btn-group,\n > .btn-group > .btn {\n display: block;\n float: none;\n width: 100%;\n max-width: 100%;\n }\n\n // Clear floats so dropdown menus can be properly placed\n > .btn-group {\n &:extend(.clearfix all);\n > .btn {\n float: none;\n }\n }\n\n > .btn + .btn,\n > .btn + .btn-group,\n > .btn-group + .btn,\n > .btn-group + .btn-group {\n margin-top: -1px;\n margin-left: 0;\n }\n}\n\n.btn-group-vertical > .btn {\n &:not(:first-child):not(:last-child) {\n border-radius: 0;\n }\n &:first-child:not(:last-child) {\n border-top-right-radius: @border-radius-base;\n .border-bottom-radius(0);\n }\n &:last-child:not(:first-child) {\n border-bottom-left-radius: @border-radius-base;\n .border-top-radius(0);\n }\n}\n.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn {\n border-radius: 0;\n}\n.btn-group-vertical > .btn-group:first-child:not(:last-child) {\n > .btn:last-child,\n > .dropdown-toggle {\n .border-bottom-radius(0);\n }\n}\n.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child {\n .border-top-radius(0);\n}\n\n\n// Justified button groups\n// ----------------------\n\n.btn-group-justified {\n display: table;\n width: 100%;\n table-layout: fixed;\n border-collapse: separate;\n > .btn,\n > .btn-group {\n float: none;\n display: table-cell;\n width: 1%;\n }\n > .btn-group .btn {\n width: 100%;\n }\n\n > .btn-group .dropdown-menu {\n left: auto;\n }\n}\n\n\n// Checkbox and radio options\n//\n// In order to support the browser's form validation feedback, powered by the\n// `required` attribute, we have to \"hide\" the inputs via `clip`. We cannot use\n// `display: none;` or `visibility: hidden;` as that also hides the popover.\n// Simply visually hiding the inputs via `opacity` would leave them clickable in\n// certain cases which is prevented by using `clip` and `pointer-events`.\n// This way, we ensure a DOM element is visible to position the popover from.\n//\n// See https://github.com/twbs/bootstrap/pull/12794 and\n// https://github.com/twbs/bootstrap/pull/14559 for more information.\n\n[data-toggle=\"buttons\"] {\n > .btn,\n > .btn-group > .btn {\n input[type=\"radio\"],\n input[type=\"checkbox\"] {\n position: absolute;\n clip: rect(0,0,0,0);\n pointer-events: none;\n }\n }\n}\n","// Single side border-radius\n\n.border-top-radius(@radius) {\n border-top-right-radius: @radius;\n border-top-left-radius: @radius;\n}\n.border-right-radius(@radius) {\n border-bottom-right-radius: @radius;\n border-top-right-radius: @radius;\n}\n.border-bottom-radius(@radius) {\n border-bottom-right-radius: @radius;\n border-bottom-left-radius: @radius;\n}\n.border-left-radius(@radius) {\n border-bottom-left-radius: @radius;\n border-top-left-radius: @radius;\n}\n","//\n// Input groups\n// --------------------------------------------------\n\n// Base styles\n// -------------------------\n.input-group {\n position: relative; // For dropdowns\n display: table;\n border-collapse: separate; // prevent input groups from inheriting border styles from table cells when placed within a table\n\n // Undo padding and float of grid classes\n &[class*=\"col-\"] {\n float: none;\n padding-left: 0;\n padding-right: 0;\n }\n\n .form-control {\n // Ensure that the input is always above the *appended* addon button for\n // proper border colors.\n position: relative;\n z-index: 2;\n\n // IE9 fubars the placeholder attribute in text inputs and the arrows on\n // select elements in input groups. To fix it, we float the input. Details:\n // https://github.com/twbs/bootstrap/issues/11561#issuecomment-28936855\n float: left;\n\n width: 100%;\n margin-bottom: 0;\n }\n}\n\n// Sizing options\n//\n// Remix the default form control sizing classes into new ones for easier\n// manipulation.\n\n.input-group-lg > .form-control,\n.input-group-lg > .input-group-addon,\n.input-group-lg > .input-group-btn > .btn {\n .input-lg();\n}\n.input-group-sm > .form-control,\n.input-group-sm > .input-group-addon,\n.input-group-sm > .input-group-btn > .btn {\n .input-sm();\n}\n\n\n// Display as table-cell\n// -------------------------\n.input-group-addon,\n.input-group-btn,\n.input-group .form-control {\n display: table-cell;\n\n &:not(:first-child):not(:last-child) {\n border-radius: 0;\n }\n}\n// Addon and addon wrapper for buttons\n.input-group-addon,\n.input-group-btn {\n width: 1%;\n white-space: nowrap;\n vertical-align: middle; // Match the inputs\n}\n\n// Text input groups\n// -------------------------\n.input-group-addon {\n padding: @padding-base-vertical @padding-base-horizontal;\n font-size: @font-size-base;\n font-weight: normal;\n line-height: 1;\n color: @input-color;\n text-align: center;\n background-color: @input-group-addon-bg;\n border: 1px solid @input-group-addon-border-color;\n border-radius: @border-radius-base;\n\n // Sizing\n &.input-sm {\n padding: @padding-small-vertical @padding-small-horizontal;\n font-size: @font-size-small;\n border-radius: @border-radius-small;\n }\n &.input-lg {\n padding: @padding-large-vertical @padding-large-horizontal;\n font-size: @font-size-large;\n border-radius: @border-radius-large;\n }\n\n // Nuke default margins from checkboxes and radios to vertically center within.\n input[type=\"radio\"],\n input[type=\"checkbox\"] {\n margin-top: 0;\n }\n}\n\n// Reset rounded corners\n.input-group .form-control:first-child,\n.input-group-addon:first-child,\n.input-group-btn:first-child > .btn,\n.input-group-btn:first-child > .btn-group > .btn,\n.input-group-btn:first-child > .dropdown-toggle,\n.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle),\n.input-group-btn:last-child > .btn-group:not(:last-child) > .btn {\n .border-right-radius(0);\n}\n.input-group-addon:first-child {\n border-right: 0;\n}\n.input-group .form-control:last-child,\n.input-group-addon:last-child,\n.input-group-btn:last-child > .btn,\n.input-group-btn:last-child > .btn-group > .btn,\n.input-group-btn:last-child > .dropdown-toggle,\n.input-group-btn:first-child > .btn:not(:first-child),\n.input-group-btn:first-child > .btn-group:not(:first-child) > .btn {\n .border-left-radius(0);\n}\n.input-group-addon:last-child {\n border-left: 0;\n}\n\n// Button input groups\n// -------------------------\n.input-group-btn {\n position: relative;\n // Jankily prevent input button groups from wrapping with `white-space` and\n // `font-size` in combination with `inline-block` on buttons.\n font-size: 0;\n white-space: nowrap;\n\n // Negative margin for spacing, position for bringing hovered/focused/actived\n // element above the siblings.\n > .btn {\n position: relative;\n + .btn {\n margin-left: -1px;\n }\n // Bring the \"active\" button to the front\n &:hover,\n &:focus,\n &:active {\n z-index: 2;\n }\n }\n\n // Negative margin to only have a 1px border between the two\n &:first-child {\n > .btn,\n > .btn-group {\n margin-right: -1px;\n }\n }\n &:last-child {\n > .btn,\n > .btn-group {\n margin-left: -1px;\n }\n }\n}\n","//\n// Navs\n// --------------------------------------------------\n\n\n// Base class\n// --------------------------------------------------\n\n.nav {\n margin-bottom: 0;\n padding-left: 0; // Override default ul/ol\n list-style: none;\n &:extend(.clearfix all);\n\n > li {\n position: relative;\n display: block;\n\n > a {\n position: relative;\n display: block;\n padding: @nav-link-padding;\n &:hover,\n &:focus {\n text-decoration: none;\n background-color: @nav-link-hover-bg;\n }\n }\n\n // Disabled state sets text to gray and nukes hover/tab effects\n &.disabled > a {\n color: @nav-disabled-link-color;\n\n &:hover,\n &:focus {\n color: @nav-disabled-link-hover-color;\n text-decoration: none;\n background-color: transparent;\n cursor: @cursor-disabled;\n }\n }\n }\n\n // Open dropdowns\n .open > a {\n &,\n &:hover,\n &:focus {\n background-color: @nav-link-hover-bg;\n border-color: @link-color;\n }\n }\n\n // Nav dividers (deprecated with v3.0.1)\n //\n // This should have been removed in v3 with the dropping of `.nav-list`, but\n // we missed it. We don't currently support this anywhere, but in the interest\n // of maintaining backward compatibility in case you use it, it's deprecated.\n .nav-divider {\n .nav-divider();\n }\n\n // Prevent IE8 from misplacing imgs\n //\n // See https://github.com/h5bp/html5-boilerplate/issues/984#issuecomment-3985989\n > li > a > img {\n max-width: none;\n }\n}\n\n\n// Tabs\n// -------------------------\n\n// Give the tabs something to sit on\n.nav-tabs {\n border-bottom: 1px solid @nav-tabs-border-color;\n > li {\n float: left;\n // Make the list-items overlay the bottom border\n margin-bottom: -1px;\n\n // Actual tabs (as links)\n > a {\n margin-right: 2px;\n line-height: @line-height-base;\n border: 1px solid transparent;\n border-radius: @border-radius-base @border-radius-base 0 0;\n &:hover {\n border-color: @nav-tabs-link-hover-border-color @nav-tabs-link-hover-border-color @nav-tabs-border-color;\n }\n }\n\n // Active state, and its :hover to override normal :hover\n &.active > a {\n &,\n &:hover,\n &:focus {\n color: @nav-tabs-active-link-hover-color;\n background-color: @nav-tabs-active-link-hover-bg;\n border: 1px solid @nav-tabs-active-link-hover-border-color;\n border-bottom-color: transparent;\n cursor: default;\n }\n }\n }\n // pulling this in mainly for less shorthand\n &.nav-justified {\n .nav-justified();\n .nav-tabs-justified();\n }\n}\n\n\n// Pills\n// -------------------------\n.nav-pills {\n > li {\n float: left;\n\n // Links rendered as pills\n > a {\n border-radius: @nav-pills-border-radius;\n }\n + li {\n margin-left: 2px;\n }\n\n // Active state\n &.active > a {\n &,\n &:hover,\n &:focus {\n color: @nav-pills-active-link-hover-color;\n background-color: @nav-pills-active-link-hover-bg;\n }\n }\n }\n}\n\n\n// Stacked pills\n.nav-stacked {\n > li {\n float: none;\n + li {\n margin-top: 2px;\n margin-left: 0; // no need for this gap between nav items\n }\n }\n}\n\n\n// Nav variations\n// --------------------------------------------------\n\n// Justified nav links\n// -------------------------\n\n.nav-justified {\n width: 100%;\n\n > li {\n float: none;\n > a {\n text-align: center;\n margin-bottom: 5px;\n }\n }\n\n > .dropdown .dropdown-menu {\n top: auto;\n left: auto;\n }\n\n @media (min-width: @screen-sm-min) {\n > li {\n display: table-cell;\n width: 1%;\n > a {\n margin-bottom: 0;\n }\n }\n }\n}\n\n// Move borders to anchors instead of bottom of list\n//\n// Mixin for adding on top the shared `.nav-justified` styles for our tabs\n.nav-tabs-justified {\n border-bottom: 0;\n\n > li > a {\n // Override margin from .nav-tabs\n margin-right: 0;\n border-radius: @border-radius-base;\n }\n\n > .active > a,\n > .active > a:hover,\n > .active > a:focus {\n border: 1px solid @nav-tabs-justified-link-border-color;\n }\n\n @media (min-width: @screen-sm-min) {\n > li > a {\n border-bottom: 1px solid @nav-tabs-justified-link-border-color;\n border-radius: @border-radius-base @border-radius-base 0 0;\n }\n > .active > a,\n > .active > a:hover,\n > .active > a:focus {\n border-bottom-color: @nav-tabs-justified-active-link-border-color;\n }\n }\n}\n\n\n// Tabbable tabs\n// -------------------------\n\n// Hide tabbable panes to start, show them when `.active`\n.tab-content {\n > .tab-pane {\n display: none;\n }\n > .active {\n display: block;\n }\n}\n\n\n// Dropdowns\n// -------------------------\n\n// Specific dropdowns\n.nav-tabs .dropdown-menu {\n // make dropdown border overlap tab border\n margin-top: -1px;\n // Remove the top rounded corners here since there is a hard edge above the menu\n .border-top-radius(0);\n}\n","//\n// Navbars\n// --------------------------------------------------\n\n\n// Wrapper and base class\n//\n// Provide a static navbar from which we expand to create full-width, fixed, and\n// other navbar variations.\n\n.navbar {\n position: relative;\n min-height: @navbar-height; // Ensure a navbar always shows (e.g., without a .navbar-brand in collapsed mode)\n margin-bottom: @navbar-margin-bottom;\n border: 1px solid transparent;\n\n // Prevent floats from breaking the navbar\n &:extend(.clearfix all);\n\n @media (min-width: @grid-float-breakpoint) {\n border-radius: @navbar-border-radius;\n }\n}\n\n\n// Navbar heading\n//\n// Groups `.navbar-brand` and `.navbar-toggle` into a single component for easy\n// styling of responsive aspects.\n\n.navbar-header {\n &:extend(.clearfix all);\n\n @media (min-width: @grid-float-breakpoint) {\n float: left;\n }\n}\n\n\n// Navbar collapse (body)\n//\n// Group your navbar content into this for easy collapsing and expanding across\n// various device sizes. By default, this content is collapsed when <768px, but\n// will expand past that for a horizontal display.\n//\n// To start (on mobile devices) the navbar links, forms, and buttons are stacked\n// vertically and include a `max-height` to overflow in case you have too much\n// content for the user's viewport.\n\n.navbar-collapse {\n overflow-x: visible;\n padding-right: @navbar-padding-horizontal;\n padding-left: @navbar-padding-horizontal;\n border-top: 1px solid transparent;\n box-shadow: inset 0 1px 0 rgba(255,255,255,.1);\n &:extend(.clearfix all);\n -webkit-overflow-scrolling: touch;\n\n &.in {\n overflow-y: auto;\n }\n\n @media (min-width: @grid-float-breakpoint) {\n width: auto;\n border-top: 0;\n box-shadow: none;\n\n &.collapse {\n display: block !important;\n height: auto !important;\n padding-bottom: 0; // Override default setting\n overflow: visible !important;\n }\n\n &.in {\n overflow-y: visible;\n }\n\n // Undo the collapse side padding for navbars with containers to ensure\n // alignment of right-aligned contents.\n .navbar-fixed-top &,\n .navbar-static-top &,\n .navbar-fixed-bottom & {\n padding-left: 0;\n padding-right: 0;\n }\n }\n}\n\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n .navbar-collapse {\n max-height: @navbar-collapse-max-height;\n\n @media (max-device-width: @screen-xs-min) and (orientation: landscape) {\n max-height: 200px;\n }\n }\n}\n\n\n// Both navbar header and collapse\n//\n// When a container is present, change the behavior of the header and collapse.\n\n.container,\n.container-fluid {\n > .navbar-header,\n > .navbar-collapse {\n margin-right: -@navbar-padding-horizontal;\n margin-left: -@navbar-padding-horizontal;\n\n @media (min-width: @grid-float-breakpoint) {\n margin-right: 0;\n margin-left: 0;\n }\n }\n}\n\n\n//\n// Navbar alignment options\n//\n// Display the navbar across the entirety of the page or fixed it to the top or\n// bottom of the page.\n\n// Static top (unfixed, but 100% wide) navbar\n.navbar-static-top {\n z-index: @zindex-navbar;\n border-width: 0 0 1px;\n\n @media (min-width: @grid-float-breakpoint) {\n border-radius: 0;\n }\n}\n\n// Fix the top/bottom navbars when screen real estate supports it\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n position: fixed;\n right: 0;\n left: 0;\n z-index: @zindex-navbar-fixed;\n\n // Undo the rounded corners\n @media (min-width: @grid-float-breakpoint) {\n border-radius: 0;\n }\n}\n.navbar-fixed-top {\n top: 0;\n border-width: 0 0 1px;\n}\n.navbar-fixed-bottom {\n bottom: 0;\n margin-bottom: 0; // override .navbar defaults\n border-width: 1px 0 0;\n}\n\n\n// Brand/project name\n\n.navbar-brand {\n float: left;\n padding: @navbar-padding-vertical @navbar-padding-horizontal;\n font-size: @font-size-large;\n line-height: @line-height-computed;\n height: @navbar-height;\n\n &:hover,\n &:focus {\n text-decoration: none;\n }\n\n > img {\n display: block;\n }\n\n @media (min-width: @grid-float-breakpoint) {\n .navbar > .container &,\n .navbar > .container-fluid & {\n margin-left: -@navbar-padding-horizontal;\n }\n }\n}\n\n\n// Navbar toggle\n//\n// Custom button for toggling the `.navbar-collapse`, powered by the collapse\n// JavaScript plugin.\n\n.navbar-toggle {\n position: relative;\n float: right;\n margin-right: @navbar-padding-horizontal;\n padding: 9px 10px;\n .navbar-vertical-align(34px);\n background-color: transparent;\n background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214\n border: 1px solid transparent;\n border-radius: @border-radius-base;\n\n // We remove the `outline` here, but later compensate by attaching `:hover`\n // styles to `:focus`.\n &:focus {\n outline: 0;\n }\n\n // Bars\n .icon-bar {\n display: block;\n width: 22px;\n height: 2px;\n border-radius: 1px;\n }\n .icon-bar + .icon-bar {\n margin-top: 4px;\n }\n\n @media (min-width: @grid-float-breakpoint) {\n display: none;\n }\n}\n\n\n// Navbar nav links\n//\n// Builds on top of the `.nav` components with its own modifier class to make\n// the nav the full height of the horizontal nav (above 768px).\n\n.navbar-nav {\n margin: (@navbar-padding-vertical / 2) -@navbar-padding-horizontal;\n\n > li > a {\n padding-top: 10px;\n padding-bottom: 10px;\n line-height: @line-height-computed;\n }\n\n @media (max-width: @grid-float-breakpoint-max) {\n // Dropdowns get custom display when collapsed\n .open .dropdown-menu {\n position: static;\n float: none;\n width: auto;\n margin-top: 0;\n background-color: transparent;\n border: 0;\n box-shadow: none;\n > li > a,\n .dropdown-header {\n padding: 5px 15px 5px 25px;\n }\n > li > a {\n line-height: @line-height-computed;\n &:hover,\n &:focus {\n background-image: none;\n }\n }\n }\n }\n\n // Uncollapse the nav\n @media (min-width: @grid-float-breakpoint) {\n float: left;\n margin: 0;\n\n > li {\n float: left;\n > a {\n padding-top: @navbar-padding-vertical;\n padding-bottom: @navbar-padding-vertical;\n }\n }\n }\n}\n\n\n// Navbar form\n//\n// Extension of the `.form-inline` with some extra flavor for optimum display in\n// our navbars.\n\n.navbar-form {\n margin-left: -@navbar-padding-horizontal;\n margin-right: -@navbar-padding-horizontal;\n padding: 10px @navbar-padding-horizontal;\n border-top: 1px solid transparent;\n border-bottom: 1px solid transparent;\n @shadow: inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.1);\n .box-shadow(@shadow);\n\n // Mixin behavior for optimum display\n .form-inline();\n\n .form-group {\n @media (max-width: @grid-float-breakpoint-max) {\n margin-bottom: 5px;\n\n &:last-child {\n margin-bottom: 0;\n }\n }\n }\n\n // Vertically center in expanded, horizontal navbar\n .navbar-vertical-align(@input-height-base);\n\n // Undo 100% width for pull classes\n @media (min-width: @grid-float-breakpoint) {\n width: auto;\n border: 0;\n margin-left: 0;\n margin-right: 0;\n padding-top: 0;\n padding-bottom: 0;\n .box-shadow(none);\n }\n}\n\n\n// Dropdown menus\n\n// Menu position and menu carets\n.navbar-nav > li > .dropdown-menu {\n margin-top: 0;\n .border-top-radius(0);\n}\n// Menu position and menu caret support for dropups via extra dropup class\n.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu {\n margin-bottom: 0;\n .border-top-radius(@navbar-border-radius);\n .border-bottom-radius(0);\n}\n\n\n// Buttons in navbars\n//\n// Vertically center a button within a navbar (when *not* in a form).\n\n.navbar-btn {\n .navbar-vertical-align(@input-height-base);\n\n &.btn-sm {\n .navbar-vertical-align(@input-height-small);\n }\n &.btn-xs {\n .navbar-vertical-align(22);\n }\n}\n\n\n// Text in navbars\n//\n// Add a class to make any element properly align itself vertically within the navbars.\n\n.navbar-text {\n .navbar-vertical-align(@line-height-computed);\n\n @media (min-width: @grid-float-breakpoint) {\n float: left;\n margin-left: @navbar-padding-horizontal;\n margin-right: @navbar-padding-horizontal;\n }\n}\n\n\n// Component alignment\n//\n// Repurpose the pull utilities as their own navbar utilities to avoid specificity\n// issues with parents and chaining. Only do this when the navbar is uncollapsed\n// though so that navbar contents properly stack and align in mobile.\n//\n// Declared after the navbar components to ensure more specificity on the margins.\n\n@media (min-width: @grid-float-breakpoint) {\n .navbar-left { .pull-left(); }\n .navbar-right {\n .pull-right();\n margin-right: -@navbar-padding-horizontal;\n\n ~ .navbar-right {\n margin-right: 0;\n }\n }\n}\n\n\n// Alternate navbars\n// --------------------------------------------------\n\n// Default navbar\n.navbar-default {\n background-color: @navbar-default-bg;\n border-color: @navbar-default-border;\n\n .navbar-brand {\n color: @navbar-default-brand-color;\n &:hover,\n &:focus {\n color: @navbar-default-brand-hover-color;\n background-color: @navbar-default-brand-hover-bg;\n }\n }\n\n .navbar-text {\n color: @navbar-default-color;\n }\n\n .navbar-nav {\n > li > a {\n color: @navbar-default-link-color;\n\n &:hover,\n &:focus {\n color: @navbar-default-link-hover-color;\n background-color: @navbar-default-link-hover-bg;\n }\n }\n > .active > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-default-link-active-color;\n background-color: @navbar-default-link-active-bg;\n }\n }\n > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-default-link-disabled-color;\n background-color: @navbar-default-link-disabled-bg;\n }\n }\n }\n\n .navbar-toggle {\n border-color: @navbar-default-toggle-border-color;\n &:hover,\n &:focus {\n background-color: @navbar-default-toggle-hover-bg;\n }\n .icon-bar {\n background-color: @navbar-default-toggle-icon-bar-bg;\n }\n }\n\n .navbar-collapse,\n .navbar-form {\n border-color: @navbar-default-border;\n }\n\n // Dropdown menu items\n .navbar-nav {\n // Remove background color from open dropdown\n > .open > a {\n &,\n &:hover,\n &:focus {\n background-color: @navbar-default-link-active-bg;\n color: @navbar-default-link-active-color;\n }\n }\n\n @media (max-width: @grid-float-breakpoint-max) {\n // Dropdowns get custom display when collapsed\n .open .dropdown-menu {\n > li > a {\n color: @navbar-default-link-color;\n &:hover,\n &:focus {\n color: @navbar-default-link-hover-color;\n background-color: @navbar-default-link-hover-bg;\n }\n }\n > .active > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-default-link-active-color;\n background-color: @navbar-default-link-active-bg;\n }\n }\n > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-default-link-disabled-color;\n background-color: @navbar-default-link-disabled-bg;\n }\n }\n }\n }\n }\n\n\n // Links in navbars\n //\n // Add a class to ensure links outside the navbar nav are colored correctly.\n\n .navbar-link {\n color: @navbar-default-link-color;\n &:hover {\n color: @navbar-default-link-hover-color;\n }\n }\n\n .btn-link {\n color: @navbar-default-link-color;\n &:hover,\n &:focus {\n color: @navbar-default-link-hover-color;\n }\n &[disabled],\n fieldset[disabled] & {\n &:hover,\n &:focus {\n color: @navbar-default-link-disabled-color;\n }\n }\n }\n}\n\n// Inverse navbar\n\n.navbar-inverse {\n background-color: @navbar-inverse-bg;\n border-color: @navbar-inverse-border;\n\n .navbar-brand {\n color: @navbar-inverse-brand-color;\n &:hover,\n &:focus {\n color: @navbar-inverse-brand-hover-color;\n background-color: @navbar-inverse-brand-hover-bg;\n }\n }\n\n .navbar-text {\n color: @navbar-inverse-color;\n }\n\n .navbar-nav {\n > li > a {\n color: @navbar-inverse-link-color;\n\n &:hover,\n &:focus {\n color: @navbar-inverse-link-hover-color;\n background-color: @navbar-inverse-link-hover-bg;\n }\n }\n > .active > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-inverse-link-active-color;\n background-color: @navbar-inverse-link-active-bg;\n }\n }\n > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-inverse-link-disabled-color;\n background-color: @navbar-inverse-link-disabled-bg;\n }\n }\n }\n\n // Darken the responsive nav toggle\n .navbar-toggle {\n border-color: @navbar-inverse-toggle-border-color;\n &:hover,\n &:focus {\n background-color: @navbar-inverse-toggle-hover-bg;\n }\n .icon-bar {\n background-color: @navbar-inverse-toggle-icon-bar-bg;\n }\n }\n\n .navbar-collapse,\n .navbar-form {\n border-color: darken(@navbar-inverse-bg, 7%);\n }\n\n // Dropdowns\n .navbar-nav {\n > .open > a {\n &,\n &:hover,\n &:focus {\n background-color: @navbar-inverse-link-active-bg;\n color: @navbar-inverse-link-active-color;\n }\n }\n\n @media (max-width: @grid-float-breakpoint-max) {\n // Dropdowns get custom display\n .open .dropdown-menu {\n > .dropdown-header {\n border-color: @navbar-inverse-border;\n }\n .divider {\n background-color: @navbar-inverse-border;\n }\n > li > a {\n color: @navbar-inverse-link-color;\n &:hover,\n &:focus {\n color: @navbar-inverse-link-hover-color;\n background-color: @navbar-inverse-link-hover-bg;\n }\n }\n > .active > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-inverse-link-active-color;\n background-color: @navbar-inverse-link-active-bg;\n }\n }\n > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-inverse-link-disabled-color;\n background-color: @navbar-inverse-link-disabled-bg;\n }\n }\n }\n }\n }\n\n .navbar-link {\n color: @navbar-inverse-link-color;\n &:hover {\n color: @navbar-inverse-link-hover-color;\n }\n }\n\n .btn-link {\n color: @navbar-inverse-link-color;\n &:hover,\n &:focus {\n color: @navbar-inverse-link-hover-color;\n }\n &[disabled],\n fieldset[disabled] & {\n &:hover,\n &:focus {\n color: @navbar-inverse-link-disabled-color;\n }\n }\n }\n}\n","// Navbar vertical align\n//\n// Vertically center elements in the navbar.\n// Example: an element has a height of 30px, so write out `.navbar-vertical-align(30px);` to calculate the appropriate top margin.\n\n.navbar-vertical-align(@element-height) {\n margin-top: ((@navbar-height - @element-height) / 2);\n margin-bottom: ((@navbar-height - @element-height) / 2);\n}\n","//\n// Utility classes\n// --------------------------------------------------\n\n\n// Floats\n// -------------------------\n\n.clearfix {\n .clearfix();\n}\n.center-block {\n .center-block();\n}\n.pull-right {\n float: right !important;\n}\n.pull-left {\n float: left !important;\n}\n\n\n// Toggling content\n// -------------------------\n\n// Note: Deprecated .hide in favor of .hidden or .sr-only (as appropriate) in v3.0.1\n.hide {\n display: none !important;\n}\n.show {\n display: block !important;\n}\n.invisible {\n visibility: hidden;\n}\n.text-hide {\n .text-hide();\n}\n\n\n// Hide from screenreaders and browsers\n//\n// Credit: HTML5 Boilerplate\n\n.hidden {\n display: none !important;\n}\n\n\n// For Affix plugin\n// -------------------------\n\n.affix {\n position: fixed;\n}\n","//\n// Breadcrumbs\n// --------------------------------------------------\n\n\n.breadcrumb {\n padding: @breadcrumb-padding-vertical @breadcrumb-padding-horizontal;\n margin-bottom: @line-height-computed;\n list-style: none;\n background-color: @breadcrumb-bg;\n border-radius: @border-radius-base;\n\n > li {\n display: inline-block;\n\n + li:before {\n content: \"@{breadcrumb-separator}\\00a0\"; // Unicode space added since inline-block means non-collapsing white-space\n padding: 0 5px;\n color: @breadcrumb-color;\n }\n }\n\n > .active {\n color: @breadcrumb-active-color;\n }\n}\n","//\n// Pagination (multiple pages)\n// --------------------------------------------------\n.pagination {\n display: inline-block;\n padding-left: 0;\n margin: @line-height-computed 0;\n border-radius: @border-radius-base;\n\n > li {\n display: inline; // Remove list-style and block-level defaults\n > a,\n > span {\n position: relative;\n float: left; // Collapse white-space\n padding: @padding-base-vertical @padding-base-horizontal;\n line-height: @line-height-base;\n text-decoration: none;\n color: @pagination-color;\n background-color: @pagination-bg;\n border: 1px solid @pagination-border;\n margin-left: -1px;\n }\n &:first-child {\n > a,\n > span {\n margin-left: 0;\n .border-left-radius(@border-radius-base);\n }\n }\n &:last-child {\n > a,\n > span {\n .border-right-radius(@border-radius-base);\n }\n }\n }\n\n > li > a,\n > li > span {\n &:hover,\n &:focus {\n color: @pagination-hover-color;\n background-color: @pagination-hover-bg;\n border-color: @pagination-hover-border;\n }\n }\n\n > .active > a,\n > .active > span {\n &,\n &:hover,\n &:focus {\n z-index: 2;\n color: @pagination-active-color;\n background-color: @pagination-active-bg;\n border-color: @pagination-active-border;\n cursor: default;\n }\n }\n\n > .disabled {\n > span,\n > span:hover,\n > span:focus,\n > a,\n > a:hover,\n > a:focus {\n color: @pagination-disabled-color;\n background-color: @pagination-disabled-bg;\n border-color: @pagination-disabled-border;\n cursor: @cursor-disabled;\n }\n }\n}\n\n// Sizing\n// --------------------------------------------------\n\n// Large\n.pagination-lg {\n .pagination-size(@padding-large-vertical; @padding-large-horizontal; @font-size-large; @border-radius-large);\n}\n\n// Small\n.pagination-sm {\n .pagination-size(@padding-small-vertical; @padding-small-horizontal; @font-size-small; @border-radius-small);\n}\n","// Pagination\n\n.pagination-size(@padding-vertical; @padding-horizontal; @font-size; @border-radius) {\n > li {\n > a,\n > span {\n padding: @padding-vertical @padding-horizontal;\n font-size: @font-size;\n }\n &:first-child {\n > a,\n > span {\n .border-left-radius(@border-radius);\n }\n }\n &:last-child {\n > a,\n > span {\n .border-right-radius(@border-radius);\n }\n }\n }\n}\n","//\n// Pager pagination\n// --------------------------------------------------\n\n\n.pager {\n padding-left: 0;\n margin: @line-height-computed 0;\n list-style: none;\n text-align: center;\n &:extend(.clearfix all);\n li {\n display: inline;\n > a,\n > span {\n display: inline-block;\n padding: 5px 14px;\n background-color: @pager-bg;\n border: 1px solid @pager-border;\n border-radius: @pager-border-radius;\n }\n\n > a:hover,\n > a:focus {\n text-decoration: none;\n background-color: @pager-hover-bg;\n }\n }\n\n .next {\n > a,\n > span {\n float: right;\n }\n }\n\n .previous {\n > a,\n > span {\n float: left;\n }\n }\n\n .disabled {\n > a,\n > a:hover,\n > a:focus,\n > span {\n color: @pager-disabled-color;\n background-color: @pager-bg;\n cursor: @cursor-disabled;\n }\n }\n}\n","//\n// Labels\n// --------------------------------------------------\n\n.label {\n display: inline;\n padding: .2em .6em .3em;\n font-size: 75%;\n font-weight: bold;\n line-height: 1;\n color: @label-color;\n text-align: center;\n white-space: nowrap;\n vertical-align: baseline;\n border-radius: .25em;\n\n // Add hover effects, but only for links\n a& {\n &:hover,\n &:focus {\n color: @label-link-hover-color;\n text-decoration: none;\n cursor: pointer;\n }\n }\n\n // Empty labels collapse automatically (not available in IE8)\n &:empty {\n display: none;\n }\n\n // Quick fix for labels in buttons\n .btn & {\n position: relative;\n top: -1px;\n }\n}\n\n// Colors\n// Contextual variations (linked labels get darker on :hover)\n\n.label-default {\n .label-variant(@label-default-bg);\n}\n\n.label-primary {\n .label-variant(@label-primary-bg);\n}\n\n.label-success {\n .label-variant(@label-success-bg);\n}\n\n.label-info {\n .label-variant(@label-info-bg);\n}\n\n.label-warning {\n .label-variant(@label-warning-bg);\n}\n\n.label-danger {\n .label-variant(@label-danger-bg);\n}\n","// Labels\n\n.label-variant(@color) {\n background-color: @color;\n\n &[href] {\n &:hover,\n &:focus {\n background-color: darken(@color, 10%);\n }\n }\n}\n","//\n// Badges\n// --------------------------------------------------\n\n\n// Base class\n.badge {\n display: inline-block;\n min-width: 10px;\n padding: 3px 7px;\n font-size: @font-size-small;\n font-weight: @badge-font-weight;\n color: @badge-color;\n line-height: @badge-line-height;\n vertical-align: baseline;\n white-space: nowrap;\n text-align: center;\n background-color: @badge-bg;\n border-radius: @badge-border-radius;\n\n // Empty badges collapse automatically (not available in IE8)\n &:empty {\n display: none;\n }\n\n // Quick fix for badges in buttons\n .btn & {\n position: relative;\n top: -1px;\n }\n\n .btn-xs &,\n .btn-group-xs > .btn & {\n top: 0;\n padding: 1px 5px;\n }\n\n // Hover state, but only for links\n a& {\n &:hover,\n &:focus {\n color: @badge-link-hover-color;\n text-decoration: none;\n cursor: pointer;\n }\n }\n\n // Account for badges in navs\n .list-group-item.active > &,\n .nav-pills > .active > a > & {\n color: @badge-active-color;\n background-color: @badge-active-bg;\n }\n\n .list-group-item > & {\n float: right;\n }\n\n .list-group-item > & + & {\n margin-right: 5px;\n }\n\n .nav-pills > li > a > & {\n margin-left: 3px;\n }\n}\n","//\n// Jumbotron\n// --------------------------------------------------\n\n\n.jumbotron {\n padding: @jumbotron-padding (@jumbotron-padding / 2);\n margin-bottom: @jumbotron-padding;\n color: @jumbotron-color;\n background-color: @jumbotron-bg;\n\n h1,\n .h1 {\n color: @jumbotron-heading-color;\n }\n\n p {\n margin-bottom: (@jumbotron-padding / 2);\n font-size: @jumbotron-font-size;\n font-weight: 200;\n }\n\n > hr {\n border-top-color: darken(@jumbotron-bg, 10%);\n }\n\n .container &,\n .container-fluid & {\n border-radius: @border-radius-large; // Only round corners at higher resolutions if contained in a container\n }\n\n .container {\n max-width: 100%;\n }\n\n @media screen and (min-width: @screen-sm-min) {\n padding: (@jumbotron-padding * 1.6) 0;\n\n .container &,\n .container-fluid & {\n padding-left: (@jumbotron-padding * 2);\n padding-right: (@jumbotron-padding * 2);\n }\n\n h1,\n .h1 {\n font-size: (@font-size-base * 4.5);\n }\n }\n}\n","//\n// Thumbnails\n// --------------------------------------------------\n\n\n// Mixin and adjust the regular image class\n.thumbnail {\n display: block;\n padding: @thumbnail-padding;\n margin-bottom: @line-height-computed;\n line-height: @line-height-base;\n background-color: @thumbnail-bg;\n border: 1px solid @thumbnail-border;\n border-radius: @thumbnail-border-radius;\n .transition(border .2s ease-in-out);\n\n > img,\n a > img {\n &:extend(.img-responsive);\n margin-left: auto;\n margin-right: auto;\n }\n\n // Add a hover state for linked versions only\n a&:hover,\n a&:focus,\n a&.active {\n border-color: @link-color;\n }\n\n // Image captions\n .caption {\n padding: @thumbnail-caption-padding;\n color: @thumbnail-caption-color;\n }\n}\n","//\n// Alerts\n// --------------------------------------------------\n\n\n// Base styles\n// -------------------------\n\n.alert {\n padding: @alert-padding;\n margin-bottom: @line-height-computed;\n border: 1px solid transparent;\n border-radius: @alert-border-radius;\n\n // Headings for larger alerts\n h4 {\n margin-top: 0;\n // Specified for the h4 to prevent conflicts of changing @headings-color\n color: inherit;\n }\n\n // Provide class for links that match alerts\n .alert-link {\n font-weight: @alert-link-font-weight;\n }\n\n // Improve alignment and spacing of inner content\n > p,\n > ul {\n margin-bottom: 0;\n }\n\n > p + p {\n margin-top: 5px;\n }\n}\n\n// Dismissible alerts\n//\n// Expand the right padding and account for the close button's positioning.\n\n.alert-dismissable, // The misspelled .alert-dismissable was deprecated in 3.2.0.\n.alert-dismissible {\n padding-right: (@alert-padding + 20);\n\n // Adjust close link position\n .close {\n position: relative;\n top: -2px;\n right: -21px;\n color: inherit;\n }\n}\n\n// Alternate styles\n//\n// Generate contextual modifier classes for colorizing the alert.\n\n.alert-success {\n .alert-variant(@alert-success-bg; @alert-success-border; @alert-success-text);\n}\n\n.alert-info {\n .alert-variant(@alert-info-bg; @alert-info-border; @alert-info-text);\n}\n\n.alert-warning {\n .alert-variant(@alert-warning-bg; @alert-warning-border; @alert-warning-text);\n}\n\n.alert-danger {\n .alert-variant(@alert-danger-bg; @alert-danger-border; @alert-danger-text);\n}\n","// Alerts\n\n.alert-variant(@background; @border; @text-color) {\n background-color: @background;\n border-color: @border;\n color: @text-color;\n\n hr {\n border-top-color: darken(@border, 5%);\n }\n .alert-link {\n color: darken(@text-color, 10%);\n }\n}\n","//\n// Progress bars\n// --------------------------------------------------\n\n\n// Bar animations\n// -------------------------\n\n// WebKit\n@-webkit-keyframes progress-bar-stripes {\n from { background-position: 40px 0; }\n to { background-position: 0 0; }\n}\n\n// Spec and IE10+\n@keyframes progress-bar-stripes {\n from { background-position: 40px 0; }\n to { background-position: 0 0; }\n}\n\n\n// Bar itself\n// -------------------------\n\n// Outer container\n.progress {\n overflow: hidden;\n height: @line-height-computed;\n margin-bottom: @line-height-computed;\n background-color: @progress-bg;\n border-radius: @progress-border-radius;\n .box-shadow(inset 0 1px 2px rgba(0,0,0,.1));\n}\n\n// Bar of progress\n.progress-bar {\n float: left;\n width: 0%;\n height: 100%;\n font-size: @font-size-small;\n line-height: @line-height-computed;\n color: @progress-bar-color;\n text-align: center;\n background-color: @progress-bar-bg;\n .box-shadow(inset 0 -1px 0 rgba(0,0,0,.15));\n .transition(width .6s ease);\n}\n\n// Striped bars\n//\n// `.progress-striped .progress-bar` is deprecated as of v3.2.0 in favor of the\n// `.progress-bar-striped` class, which you just add to an existing\n// `.progress-bar`.\n.progress-striped .progress-bar,\n.progress-bar-striped {\n #gradient > .striped();\n background-size: 40px 40px;\n}\n\n// Call animation for the active one\n//\n// `.progress.active .progress-bar` is deprecated as of v3.2.0 in favor of the\n// `.progress-bar.active` approach.\n.progress.active .progress-bar,\n.progress-bar.active {\n .animation(progress-bar-stripes 2s linear infinite);\n}\n\n\n// Variations\n// -------------------------\n\n.progress-bar-success {\n .progress-bar-variant(@progress-bar-success-bg);\n}\n\n.progress-bar-info {\n .progress-bar-variant(@progress-bar-info-bg);\n}\n\n.progress-bar-warning {\n .progress-bar-variant(@progress-bar-warning-bg);\n}\n\n.progress-bar-danger {\n .progress-bar-variant(@progress-bar-danger-bg);\n}\n","// Gradients\n\n#gradient {\n\n // Horizontal gradient, from left to right\n //\n // Creates two color stops, start and end, by specifying a color and position for each color stop.\n // Color stops are not available in IE9 and below.\n .horizontal(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n background-image: -webkit-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Opera 12\n background-image: linear-gradient(to right, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n background-repeat: repeat-x;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@start-color),argb(@end-color))); // IE9 and down\n }\n\n // Vertical gradient, from top to bottom\n //\n // Creates two color stops, start and end, by specifying a color and position for each color stop.\n // Color stops are not available in IE9 and below.\n .vertical(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n background-image: -webkit-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Opera 12\n background-image: linear-gradient(to bottom, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n background-repeat: repeat-x;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@start-color),argb(@end-color))); // IE9 and down\n }\n\n .directional(@start-color: #555; @end-color: #333; @deg: 45deg) {\n background-repeat: repeat-x;\n background-image: -webkit-linear-gradient(@deg, @start-color, @end-color); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(@deg, @start-color, @end-color); // Opera 12\n background-image: linear-gradient(@deg, @start-color, @end-color); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n }\n .horizontal-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n background-image: -o-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n background-image: linear-gradient(to right, @start-color, @mid-color @color-stop, @end-color);\n background-repeat: no-repeat;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n }\n .vertical-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-image: -o-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-image: linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-repeat: no-repeat;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n }\n .radial(@inner-color: #555; @outer-color: #333) {\n background-image: -webkit-radial-gradient(circle, @inner-color, @outer-color);\n background-image: radial-gradient(circle, @inner-color, @outer-color);\n background-repeat: no-repeat;\n }\n .striped(@color: rgba(255,255,255,.15); @angle: 45deg) {\n background-image: -webkit-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n background-image: linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n }\n}\n","// Progress bars\n\n.progress-bar-variant(@color) {\n background-color: @color;\n\n // Deprecated parent class requirement as of v3.2.0\n .progress-striped & {\n #gradient > .striped();\n }\n}\n",".media {\n // Proper spacing between instances of .media\n margin-top: 15px;\n\n &:first-child {\n margin-top: 0;\n }\n}\n\n.media,\n.media-body {\n zoom: 1;\n overflow: hidden;\n}\n\n.media-body {\n width: 10000px;\n}\n\n.media-object {\n display: block;\n}\n\n.media-right,\n.media > .pull-right {\n padding-left: 10px;\n}\n\n.media-left,\n.media > .pull-left {\n padding-right: 10px;\n}\n\n.media-left,\n.media-right,\n.media-body {\n display: table-cell;\n vertical-align: top;\n}\n\n.media-middle {\n vertical-align: middle;\n}\n\n.media-bottom {\n vertical-align: bottom;\n}\n\n// Reset margins on headings for tighter default spacing\n.media-heading {\n margin-top: 0;\n margin-bottom: 5px;\n}\n\n// Media list variation\n//\n// Undo default ul/ol styles\n.media-list {\n padding-left: 0;\n list-style: none;\n}\n","//\n// List groups\n// --------------------------------------------------\n\n\n// Base class\n//\n// Easily usable on <ul>, <ol>, or <div>.\n\n.list-group {\n // No need to set list-style: none; since .list-group-item is block level\n margin-bottom: 20px;\n padding-left: 0; // reset padding because ul and ol\n}\n\n\n// Individual list items\n//\n// Use on `li`s or `div`s within the `.list-group` parent.\n\n.list-group-item {\n position: relative;\n display: block;\n padding: 10px 15px;\n // Place the border on the list items and negative margin up for better styling\n margin-bottom: -1px;\n background-color: @list-group-bg;\n border: 1px solid @list-group-border;\n\n // Round the first and last items\n &:first-child {\n .border-top-radius(@list-group-border-radius);\n }\n &:last-child {\n margin-bottom: 0;\n .border-bottom-radius(@list-group-border-radius);\n }\n}\n\n\n// Linked list items\n//\n// Use anchor elements instead of `li`s or `div`s to create linked list items.\n// Includes an extra `.active` modifier class for showing selected items.\n\na.list-group-item {\n color: @list-group-link-color;\n\n .list-group-item-heading {\n color: @list-group-link-heading-color;\n }\n\n // Hover state\n &:hover,\n &:focus {\n text-decoration: none;\n color: @list-group-link-hover-color;\n background-color: @list-group-hover-bg;\n }\n}\n\n.list-group-item {\n // Disabled state\n &.disabled,\n &.disabled:hover,\n &.disabled:focus {\n background-color: @list-group-disabled-bg;\n color: @list-group-disabled-color;\n cursor: @cursor-disabled;\n\n // Force color to inherit for custom content\n .list-group-item-heading {\n color: inherit;\n }\n .list-group-item-text {\n color: @list-group-disabled-text-color;\n }\n }\n\n // Active class on item itself, not parent\n &.active,\n &.active:hover,\n &.active:focus {\n z-index: 2; // Place active items above their siblings for proper border styling\n color: @list-group-active-color;\n background-color: @list-group-active-bg;\n border-color: @list-group-active-border;\n\n // Force color to inherit for custom content\n .list-group-item-heading,\n .list-group-item-heading > small,\n .list-group-item-heading > .small {\n color: inherit;\n }\n .list-group-item-text {\n color: @list-group-active-text-color;\n }\n }\n}\n\n\n// Contextual variants\n//\n// Add modifier classes to change text and background color on individual items.\n// Organizationally, this must come after the `:hover` states.\n\n.list-group-item-variant(success; @state-success-bg; @state-success-text);\n.list-group-item-variant(info; @state-info-bg; @state-info-text);\n.list-group-item-variant(warning; @state-warning-bg; @state-warning-text);\n.list-group-item-variant(danger; @state-danger-bg; @state-danger-text);\n\n\n// Custom content options\n//\n// Extra classes for creating well-formatted content within `.list-group-item`s.\n\n.list-group-item-heading {\n margin-top: 0;\n margin-bottom: 5px;\n}\n.list-group-item-text {\n margin-bottom: 0;\n line-height: 1.3;\n}\n","// List Groups\n\n.list-group-item-variant(@state; @background; @color) {\n .list-group-item-@{state} {\n color: @color;\n background-color: @background;\n\n a& {\n color: @color;\n\n .list-group-item-heading {\n color: inherit;\n }\n\n &:hover,\n &:focus {\n color: @color;\n background-color: darken(@background, 5%);\n }\n &.active,\n &.active:hover,\n &.active:focus {\n color: #fff;\n background-color: @color;\n border-color: @color;\n }\n }\n }\n}\n","//\n// Panels\n// --------------------------------------------------\n\n\n// Base class\n.panel {\n margin-bottom: @line-height-computed;\n background-color: @panel-bg;\n border: 1px solid transparent;\n border-radius: @panel-border-radius;\n .box-shadow(0 1px 1px rgba(0,0,0,.05));\n}\n\n// Panel contents\n.panel-body {\n padding: @panel-body-padding;\n &:extend(.clearfix all);\n}\n\n// Optional heading\n.panel-heading {\n padding: @panel-heading-padding;\n border-bottom: 1px solid transparent;\n .border-top-radius((@panel-border-radius - 1));\n\n > .dropdown .dropdown-toggle {\n color: inherit;\n }\n}\n\n// Within heading, strip any `h*` tag of its default margins for spacing.\n.panel-title {\n margin-top: 0;\n margin-bottom: 0;\n font-size: ceil((@font-size-base * 1.125));\n color: inherit;\n\n > a,\n > small,\n > .small,\n > small > a,\n > .small > a {\n color: inherit;\n }\n}\n\n// Optional footer (stays gray in every modifier class)\n.panel-footer {\n padding: @panel-footer-padding;\n background-color: @panel-footer-bg;\n border-top: 1px solid @panel-inner-border;\n .border-bottom-radius((@panel-border-radius - 1));\n}\n\n\n// List groups in panels\n//\n// By default, space out list group content from panel headings to account for\n// any kind of custom content between the two.\n\n.panel {\n > .list-group,\n > .panel-collapse > .list-group {\n margin-bottom: 0;\n\n .list-group-item {\n border-width: 1px 0;\n border-radius: 0;\n }\n\n // Add border top radius for first one\n &:first-child {\n .list-group-item:first-child {\n border-top: 0;\n .border-top-radius((@panel-border-radius - 1));\n }\n }\n // Add border bottom radius for last one\n &:last-child {\n .list-group-item:last-child {\n border-bottom: 0;\n .border-bottom-radius((@panel-border-radius - 1));\n }\n }\n }\n}\n// Collapse space between when there's no additional content.\n.panel-heading + .list-group {\n .list-group-item:first-child {\n border-top-width: 0;\n }\n}\n.list-group + .panel-footer {\n border-top-width: 0;\n}\n\n// Tables in panels\n//\n// Place a non-bordered `.table` within a panel (not within a `.panel-body`) and\n// watch it go full width.\n\n.panel {\n > .table,\n > .table-responsive > .table,\n > .panel-collapse > .table {\n margin-bottom: 0;\n\n caption {\n padding-left: @panel-body-padding;\n padding-right: @panel-body-padding;\n }\n }\n // Add border top radius for first one\n > .table:first-child,\n > .table-responsive:first-child > .table:first-child {\n .border-top-radius((@panel-border-radius - 1));\n\n > thead:first-child,\n > tbody:first-child {\n > tr:first-child {\n border-top-left-radius: (@panel-border-radius - 1);\n border-top-right-radius: (@panel-border-radius - 1);\n\n td:first-child,\n th:first-child {\n border-top-left-radius: (@panel-border-radius - 1);\n }\n td:last-child,\n th:last-child {\n border-top-right-radius: (@panel-border-radius - 1);\n }\n }\n }\n }\n // Add border bottom radius for last one\n > .table:last-child,\n > .table-responsive:last-child > .table:last-child {\n .border-bottom-radius((@panel-border-radius - 1));\n\n > tbody:last-child,\n > tfoot:last-child {\n > tr:last-child {\n border-bottom-left-radius: (@panel-border-radius - 1);\n border-bottom-right-radius: (@panel-border-radius - 1);\n\n td:first-child,\n th:first-child {\n border-bottom-left-radius: (@panel-border-radius - 1);\n }\n td:last-child,\n th:last-child {\n border-bottom-right-radius: (@panel-border-radius - 1);\n }\n }\n }\n }\n > .panel-body + .table,\n > .panel-body + .table-responsive,\n > .table + .panel-body,\n > .table-responsive + .panel-body {\n border-top: 1px solid @table-border-color;\n }\n > .table > tbody:first-child > tr:first-child th,\n > .table > tbody:first-child > tr:first-child td {\n border-top: 0;\n }\n > .table-bordered,\n > .table-responsive > .table-bordered {\n border: 0;\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th:first-child,\n > td:first-child {\n border-left: 0;\n }\n > th:last-child,\n > td:last-child {\n border-right: 0;\n }\n }\n }\n > thead,\n > tbody {\n > tr:first-child {\n > td,\n > th {\n border-bottom: 0;\n }\n }\n }\n > tbody,\n > tfoot {\n > tr:last-child {\n > td,\n > th {\n border-bottom: 0;\n }\n }\n }\n }\n > .table-responsive {\n border: 0;\n margin-bottom: 0;\n }\n}\n\n\n// Collapsable panels (aka, accordion)\n//\n// Wrap a series of panels in `.panel-group` to turn them into an accordion with\n// the help of our collapse JavaScript plugin.\n\n.panel-group {\n margin-bottom: @line-height-computed;\n\n // Tighten up margin so it's only between panels\n .panel {\n margin-bottom: 0;\n border-radius: @panel-border-radius;\n\n + .panel {\n margin-top: 5px;\n }\n }\n\n .panel-heading {\n border-bottom: 0;\n\n + .panel-collapse > .panel-body,\n + .panel-collapse > .list-group {\n border-top: 1px solid @panel-inner-border;\n }\n }\n\n .panel-footer {\n border-top: 0;\n + .panel-collapse .panel-body {\n border-bottom: 1px solid @panel-inner-border;\n }\n }\n}\n\n\n// Contextual variations\n.panel-default {\n .panel-variant(@panel-default-border; @panel-default-text; @panel-default-heading-bg; @panel-default-border);\n}\n.panel-primary {\n .panel-variant(@panel-primary-border; @panel-primary-text; @panel-primary-heading-bg; @panel-primary-border);\n}\n.panel-success {\n .panel-variant(@panel-success-border; @panel-success-text; @panel-success-heading-bg; @panel-success-border);\n}\n.panel-info {\n .panel-variant(@panel-info-border; @panel-info-text; @panel-info-heading-bg; @panel-info-border);\n}\n.panel-warning {\n .panel-variant(@panel-warning-border; @panel-warning-text; @panel-warning-heading-bg; @panel-warning-border);\n}\n.panel-danger {\n .panel-variant(@panel-danger-border; @panel-danger-text; @panel-danger-heading-bg; @panel-danger-border);\n}\n","// Panels\n\n.panel-variant(@border; @heading-text-color; @heading-bg-color; @heading-border) {\n border-color: @border;\n\n & > .panel-heading {\n color: @heading-text-color;\n background-color: @heading-bg-color;\n border-color: @heading-border;\n\n + .panel-collapse > .panel-body {\n border-top-color: @border;\n }\n .badge {\n color: @heading-bg-color;\n background-color: @heading-text-color;\n }\n }\n & > .panel-footer {\n + .panel-collapse > .panel-body {\n border-bottom-color: @border;\n }\n }\n}\n","// Embeds responsive\n//\n// Credit: Nicolas Gallagher and SUIT CSS.\n\n.embed-responsive {\n position: relative;\n display: block;\n height: 0;\n padding: 0;\n overflow: hidden;\n\n .embed-responsive-item,\n iframe,\n embed,\n object,\n video {\n position: absolute;\n top: 0;\n left: 0;\n bottom: 0;\n height: 100%;\n width: 100%;\n border: 0;\n }\n}\n\n// Modifier class for 16:9 aspect ratio\n.embed-responsive-16by9 {\n padding-bottom: 56.25%;\n}\n\n// Modifier class for 4:3 aspect ratio\n.embed-responsive-4by3 {\n padding-bottom: 75%;\n}\n","//\n// Wells\n// --------------------------------------------------\n\n\n// Base class\n.well {\n min-height: 20px;\n padding: 19px;\n margin-bottom: 20px;\n background-color: @well-bg;\n border: 1px solid @well-border;\n border-radius: @border-radius-base;\n .box-shadow(inset 0 1px 1px rgba(0,0,0,.05));\n blockquote {\n border-color: #ddd;\n border-color: rgba(0,0,0,.15);\n }\n}\n\n// Sizes\n.well-lg {\n padding: 24px;\n border-radius: @border-radius-large;\n}\n.well-sm {\n padding: 9px;\n border-radius: @border-radius-small;\n}\n","//\n// Close icons\n// --------------------------------------------------\n\n\n.close {\n float: right;\n font-size: (@font-size-base * 1.5);\n font-weight: @close-font-weight;\n line-height: 1;\n color: @close-color;\n text-shadow: @close-text-shadow;\n .opacity(.2);\n\n &:hover,\n &:focus {\n color: @close-color;\n text-decoration: none;\n cursor: pointer;\n .opacity(.5);\n }\n\n // Additional properties for button version\n // iOS requires the button element instead of an anchor tag.\n // If you want the anchor version, it requires `href=\"#\"`.\n // See https://developer.mozilla.org/en-US/docs/Web/Events/click#Safari_Mobile\n button& {\n padding: 0;\n cursor: pointer;\n background: transparent;\n border: 0;\n -webkit-appearance: none;\n }\n}\n","//\n// Modals\n// --------------------------------------------------\n\n// .modal-open - body class for killing the scroll\n// .modal - container to scroll within\n// .modal-dialog - positioning shell for the actual modal\n// .modal-content - actual modal w/ bg and corners and shit\n\n// Kill the scroll on the body\n.modal-open {\n overflow: hidden;\n}\n\n// Container that the modal scrolls within\n.modal {\n display: none;\n overflow: hidden;\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: @zindex-modal;\n -webkit-overflow-scrolling: touch;\n\n // Prevent Chrome on Windows from adding a focus outline. For details, see\n // https://github.com/twbs/bootstrap/pull/10951.\n outline: 0;\n\n // When fading in the modal, animate it to slide down\n &.fade .modal-dialog {\n .translate(0, -25%);\n .transition-transform(~\"0.3s ease-out\");\n }\n &.in .modal-dialog { .translate(0, 0) }\n}\n.modal-open .modal {\n overflow-x: hidden;\n overflow-y: auto;\n}\n\n// Shell div to position the modal with bottom padding\n.modal-dialog {\n position: relative;\n width: auto;\n margin: 10px;\n}\n\n// Actual modal\n.modal-content {\n position: relative;\n background-color: @modal-content-bg;\n border: 1px solid @modal-content-fallback-border-color; //old browsers fallback (ie8 etc)\n border: 1px solid @modal-content-border-color;\n border-radius: @border-radius-large;\n .box-shadow(0 3px 9px rgba(0,0,0,.5));\n background-clip: padding-box;\n // Remove focus outline from opened modal\n outline: 0;\n}\n\n// Modal background\n.modal-backdrop {\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: @zindex-modal-background;\n background-color: @modal-backdrop-bg;\n // Fade for backdrop\n &.fade { .opacity(0); }\n &.in { .opacity(@modal-backdrop-opacity); }\n}\n\n// Modal header\n// Top section of the modal w/ title and dismiss\n.modal-header {\n padding: @modal-title-padding;\n border-bottom: 1px solid @modal-header-border-color;\n min-height: (@modal-title-padding + @modal-title-line-height);\n}\n// Close icon\n.modal-header .close {\n margin-top: -2px;\n}\n\n// Title text within header\n.modal-title {\n margin: 0;\n line-height: @modal-title-line-height;\n}\n\n// Modal body\n// Where all modal content resides (sibling of .modal-header and .modal-footer)\n.modal-body {\n position: relative;\n padding: @modal-inner-padding;\n}\n\n// Footer (for actions)\n.modal-footer {\n padding: @modal-inner-padding;\n text-align: right; // right align buttons\n border-top: 1px solid @modal-footer-border-color;\n &:extend(.clearfix all); // clear it in case folks use .pull-* classes on buttons\n\n // Properly space out buttons\n .btn + .btn {\n margin-left: 5px;\n margin-bottom: 0; // account for input[type=\"submit\"] which gets the bottom margin like all other inputs\n }\n // but override that for button groups\n .btn-group .btn + .btn {\n margin-left: -1px;\n }\n // and override it for block buttons as well\n .btn-block + .btn-block {\n margin-left: 0;\n }\n}\n\n// Measure scrollbar width for padding body during modal show/hide\n.modal-scrollbar-measure {\n position: absolute;\n top: -9999px;\n width: 50px;\n height: 50px;\n overflow: scroll;\n}\n\n// Scale up the modal\n@media (min-width: @screen-sm-min) {\n // Automatically set modal's width for larger viewports\n .modal-dialog {\n width: @modal-md;\n margin: 30px auto;\n }\n .modal-content {\n .box-shadow(0 5px 15px rgba(0,0,0,.5));\n }\n\n // Modal sizes\n .modal-sm { width: @modal-sm; }\n}\n\n@media (min-width: @screen-md-min) {\n .modal-lg { width: @modal-lg; }\n}\n","//\n// Tooltips\n// --------------------------------------------------\n\n\n// Base class\n.tooltip {\n position: absolute;\n z-index: @zindex-tooltip;\n display: block;\n // Reset font and text properties given new insertion method\n font-family: @font-family-base;\n font-size: @font-size-small;\n font-weight: normal;\n line-height: 1.4;\n .opacity(0);\n\n &.in { .opacity(@tooltip-opacity); }\n &.top { margin-top: -3px; padding: @tooltip-arrow-width 0; }\n &.right { margin-left: 3px; padding: 0 @tooltip-arrow-width; }\n &.bottom { margin-top: 3px; padding: @tooltip-arrow-width 0; }\n &.left { margin-left: -3px; padding: 0 @tooltip-arrow-width; }\n}\n\n// Wrapper for the tooltip content\n.tooltip-inner {\n max-width: @tooltip-max-width;\n padding: 3px 8px;\n color: @tooltip-color;\n text-align: center;\n text-decoration: none;\n background-color: @tooltip-bg;\n border-radius: @border-radius-base;\n}\n\n// Arrows\n.tooltip-arrow {\n position: absolute;\n width: 0;\n height: 0;\n border-color: transparent;\n border-style: solid;\n}\n// Note: Deprecated .top-left, .top-right, .bottom-left, and .bottom-right as of v3.3.1\n.tooltip {\n &.top .tooltip-arrow {\n bottom: 0;\n left: 50%;\n margin-left: -@tooltip-arrow-width;\n border-width: @tooltip-arrow-width @tooltip-arrow-width 0;\n border-top-color: @tooltip-arrow-color;\n }\n &.top-left .tooltip-arrow {\n bottom: 0;\n right: @tooltip-arrow-width;\n margin-bottom: -@tooltip-arrow-width;\n border-width: @tooltip-arrow-width @tooltip-arrow-width 0;\n border-top-color: @tooltip-arrow-color;\n }\n &.top-right .tooltip-arrow {\n bottom: 0;\n left: @tooltip-arrow-width;\n margin-bottom: -@tooltip-arrow-width;\n border-width: @tooltip-arrow-width @tooltip-arrow-width 0;\n border-top-color: @tooltip-arrow-color;\n }\n &.right .tooltip-arrow {\n top: 50%;\n left: 0;\n margin-top: -@tooltip-arrow-width;\n border-width: @tooltip-arrow-width @tooltip-arrow-width @tooltip-arrow-width 0;\n border-right-color: @tooltip-arrow-color;\n }\n &.left .tooltip-arrow {\n top: 50%;\n right: 0;\n margin-top: -@tooltip-arrow-width;\n border-width: @tooltip-arrow-width 0 @tooltip-arrow-width @tooltip-arrow-width;\n border-left-color: @tooltip-arrow-color;\n }\n &.bottom .tooltip-arrow {\n top: 0;\n left: 50%;\n margin-left: -@tooltip-arrow-width;\n border-width: 0 @tooltip-arrow-width @tooltip-arrow-width;\n border-bottom-color: @tooltip-arrow-color;\n }\n &.bottom-left .tooltip-arrow {\n top: 0;\n right: @tooltip-arrow-width;\n margin-top: -@tooltip-arrow-width;\n border-width: 0 @tooltip-arrow-width @tooltip-arrow-width;\n border-bottom-color: @tooltip-arrow-color;\n }\n &.bottom-right .tooltip-arrow {\n top: 0;\n left: @tooltip-arrow-width;\n margin-top: -@tooltip-arrow-width;\n border-width: 0 @tooltip-arrow-width @tooltip-arrow-width;\n border-bottom-color: @tooltip-arrow-color;\n }\n}\n","//\n// Popovers\n// --------------------------------------------------\n\n\n.popover {\n position: absolute;\n top: 0;\n left: 0;\n z-index: @zindex-popover;\n display: none;\n max-width: @popover-max-width;\n padding: 1px;\n // Reset font and text properties given new insertion method\n font-family: @font-family-base;\n font-size: @font-size-base;\n font-weight: normal;\n line-height: @line-height-base;\n text-align: left;\n background-color: @popover-bg;\n background-clip: padding-box;\n border: 1px solid @popover-fallback-border-color;\n border: 1px solid @popover-border-color;\n border-radius: @border-radius-large;\n .box-shadow(0 5px 10px rgba(0,0,0,.2));\n\n // Overrides for proper insertion\n white-space: normal;\n\n // Offset the popover to account for the popover arrow\n &.top { margin-top: -@popover-arrow-width; }\n &.right { margin-left: @popover-arrow-width; }\n &.bottom { margin-top: @popover-arrow-width; }\n &.left { margin-left: -@popover-arrow-width; }\n}\n\n.popover-title {\n margin: 0; // reset heading margin\n padding: 8px 14px;\n font-size: @font-size-base;\n background-color: @popover-title-bg;\n border-bottom: 1px solid darken(@popover-title-bg, 5%);\n border-radius: (@border-radius-large - 1) (@border-radius-large - 1) 0 0;\n}\n\n.popover-content {\n padding: 9px 14px;\n}\n\n// Arrows\n//\n// .arrow is outer, .arrow:after is inner\n\n.popover > .arrow {\n &,\n &:after {\n position: absolute;\n display: block;\n width: 0;\n height: 0;\n border-color: transparent;\n border-style: solid;\n }\n}\n.popover > .arrow {\n border-width: @popover-arrow-outer-width;\n}\n.popover > .arrow:after {\n border-width: @popover-arrow-width;\n content: \"\";\n}\n\n.popover {\n &.top > .arrow {\n left: 50%;\n margin-left: -@popover-arrow-outer-width;\n border-bottom-width: 0;\n border-top-color: @popover-arrow-outer-fallback-color; // IE8 fallback\n border-top-color: @popover-arrow-outer-color;\n bottom: -@popover-arrow-outer-width;\n &:after {\n content: \" \";\n bottom: 1px;\n margin-left: -@popover-arrow-width;\n border-bottom-width: 0;\n border-top-color: @popover-arrow-color;\n }\n }\n &.right > .arrow {\n top: 50%;\n left: -@popover-arrow-outer-width;\n margin-top: -@popover-arrow-outer-width;\n border-left-width: 0;\n border-right-color: @popover-arrow-outer-fallback-color; // IE8 fallback\n border-right-color: @popover-arrow-outer-color;\n &:after {\n content: \" \";\n left: 1px;\n bottom: -@popover-arrow-width;\n border-left-width: 0;\n border-right-color: @popover-arrow-color;\n }\n }\n &.bottom > .arrow {\n left: 50%;\n margin-left: -@popover-arrow-outer-width;\n border-top-width: 0;\n border-bottom-color: @popover-arrow-outer-fallback-color; // IE8 fallback\n border-bottom-color: @popover-arrow-outer-color;\n top: -@popover-arrow-outer-width;\n &:after {\n content: \" \";\n top: 1px;\n margin-left: -@popover-arrow-width;\n border-top-width: 0;\n border-bottom-color: @popover-arrow-color;\n }\n }\n\n &.left > .arrow {\n top: 50%;\n right: -@popover-arrow-outer-width;\n margin-top: -@popover-arrow-outer-width;\n border-right-width: 0;\n border-left-color: @popover-arrow-outer-fallback-color; // IE8 fallback\n border-left-color: @popover-arrow-outer-color;\n &:after {\n content: \" \";\n right: 1px;\n border-right-width: 0;\n border-left-color: @popover-arrow-color;\n bottom: -@popover-arrow-width;\n }\n }\n}\n","//\n// Carousel\n// --------------------------------------------------\n\n\n// Wrapper for the slide container and indicators\n.carousel {\n position: relative;\n}\n\n.carousel-inner {\n position: relative;\n overflow: hidden;\n width: 100%;\n\n > .item {\n display: none;\n position: relative;\n .transition(.6s ease-in-out left);\n\n // Account for jankitude on images\n > img,\n > a > img {\n &:extend(.img-responsive);\n line-height: 1;\n }\n\n // WebKit CSS3 transforms for supported devices\n @media all and (transform-3d), (-webkit-transform-3d) {\n .transition-transform(~'0.6s ease-in-out');\n .backface-visibility(~'hidden');\n .perspective(1000);\n\n &.next,\n &.active.right {\n .translate3d(100%, 0, 0);\n left: 0;\n }\n &.prev,\n &.active.left {\n .translate3d(-100%, 0, 0);\n left: 0;\n }\n &.next.left,\n &.prev.right,\n &.active {\n .translate3d(0, 0, 0);\n left: 0;\n }\n }\n }\n\n > .active,\n > .next,\n > .prev {\n display: block;\n }\n\n > .active {\n left: 0;\n }\n\n > .next,\n > .prev {\n position: absolute;\n top: 0;\n width: 100%;\n }\n\n > .next {\n left: 100%;\n }\n > .prev {\n left: -100%;\n }\n > .next.left,\n > .prev.right {\n left: 0;\n }\n\n > .active.left {\n left: -100%;\n }\n > .active.right {\n left: 100%;\n }\n\n}\n\n// Left/right controls for nav\n// ---------------------------\n\n.carousel-control {\n position: absolute;\n top: 0;\n left: 0;\n bottom: 0;\n width: @carousel-control-width;\n .opacity(@carousel-control-opacity);\n font-size: @carousel-control-font-size;\n color: @carousel-control-color;\n text-align: center;\n text-shadow: @carousel-text-shadow;\n // We can't have this transition here because WebKit cancels the carousel\n // animation if you trip this while in the middle of another animation.\n\n // Set gradients for backgrounds\n &.left {\n #gradient > .horizontal(@start-color: rgba(0,0,0,.5); @end-color: rgba(0,0,0,.0001));\n }\n &.right {\n left: auto;\n right: 0;\n #gradient > .horizontal(@start-color: rgba(0,0,0,.0001); @end-color: rgba(0,0,0,.5));\n }\n\n // Hover/focus state\n &:hover,\n &:focus {\n outline: 0;\n color: @carousel-control-color;\n text-decoration: none;\n .opacity(.9);\n }\n\n // Toggles\n .icon-prev,\n .icon-next,\n .glyphicon-chevron-left,\n .glyphicon-chevron-right {\n position: absolute;\n top: 50%;\n z-index: 5;\n display: inline-block;\n }\n .icon-prev,\n .glyphicon-chevron-left {\n left: 50%;\n margin-left: -10px;\n }\n .icon-next,\n .glyphicon-chevron-right {\n right: 50%;\n margin-right: -10px;\n }\n .icon-prev,\n .icon-next {\n width: 20px;\n height: 20px;\n margin-top: -10px;\n line-height: 1;\n font-family: serif;\n }\n\n\n .icon-prev {\n &:before {\n content: '\\2039';// SINGLE LEFT-POINTING ANGLE QUOTATION MARK (U+2039)\n }\n }\n .icon-next {\n &:before {\n content: '\\203a';// SINGLE RIGHT-POINTING ANGLE QUOTATION MARK (U+203A)\n }\n }\n}\n\n// Optional indicator pips\n//\n// Add an unordered list with the following class and add a list item for each\n// slide your carousel holds.\n\n.carousel-indicators {\n position: absolute;\n bottom: 10px;\n left: 50%;\n z-index: 15;\n width: 60%;\n margin-left: -30%;\n padding-left: 0;\n list-style: none;\n text-align: center;\n\n li {\n display: inline-block;\n width: 10px;\n height: 10px;\n margin: 1px;\n text-indent: -999px;\n border: 1px solid @carousel-indicator-border-color;\n border-radius: 10px;\n cursor: pointer;\n\n // IE8-9 hack for event handling\n //\n // Internet Explorer 8-9 does not support clicks on elements without a set\n // `background-color`. We cannot use `filter` since that's not viewed as a\n // background color by the browser. Thus, a hack is needed.\n // See https://developer.mozilla.org/en-US/docs/Web/Events/click#Internet_Explorer\n //\n // For IE8, we set solid black as it doesn't support `rgba()`. For IE9, we\n // set alpha transparency for the best results possible.\n background-color: #000 \\9; // IE8\n background-color: rgba(0,0,0,0); // IE9\n }\n .active {\n margin: 0;\n width: 12px;\n height: 12px;\n background-color: @carousel-indicator-active-bg;\n }\n}\n\n// Optional captions\n// -----------------------------\n// Hidden by default for smaller viewports\n.carousel-caption {\n position: absolute;\n left: 15%;\n right: 15%;\n bottom: 20px;\n z-index: 10;\n padding-top: 20px;\n padding-bottom: 20px;\n color: @carousel-caption-color;\n text-align: center;\n text-shadow: @carousel-text-shadow;\n & .btn {\n text-shadow: none; // No shadow for button elements in carousel-caption\n }\n}\n\n\n// Scale up controls for tablets and up\n@media screen and (min-width: @screen-sm-min) {\n\n // Scale up the controls a smidge\n .carousel-control {\n .glyphicon-chevron-left,\n .glyphicon-chevron-right,\n .icon-prev,\n .icon-next {\n width: 30px;\n height: 30px;\n margin-top: -15px;\n font-size: 30px;\n }\n .glyphicon-chevron-left,\n .icon-prev {\n margin-left: -15px;\n }\n .glyphicon-chevron-right,\n .icon-next {\n margin-right: -15px;\n }\n }\n\n // Show and left align the captions\n .carousel-caption {\n left: 20%;\n right: 20%;\n padding-bottom: 30px;\n }\n\n // Move up the indicators\n .carousel-indicators {\n bottom: 20px;\n }\n}\n","// Clearfix\n//\n// For modern browsers\n// 1. The space content is one way to avoid an Opera bug when the\n// contenteditable attribute is included anywhere else in the document.\n// Otherwise it causes space to appear at the top and bottom of elements\n// that are clearfixed.\n// 2. The use of `table` rather than `block` is only necessary if using\n// `:before` to contain the top-margins of child elements.\n//\n// Source: http://nicolasgallagher.com/micro-clearfix-hack/\n\n.clearfix() {\n &:before,\n &:after {\n content: \" \"; // 1\n display: table; // 2\n }\n &:after {\n clear: both;\n }\n}\n","// Center-align a block level element\n\n.center-block() {\n display: block;\n margin-left: auto;\n margin-right: auto;\n}\n","// CSS image replacement\n//\n// Heads up! v3 launched with with only `.hide-text()`, but per our pattern for\n// mixins being reused as classes with the same name, this doesn't hold up. As\n// of v3.0.1 we have added `.text-hide()` and deprecated `.hide-text()`.\n//\n// Source: https://github.com/h5bp/html5-boilerplate/commit/aa0396eae757\n\n// Deprecated as of v3.0.1 (will be removed in v4)\n.hide-text() {\n font: ~\"0/0\" a;\n color: transparent;\n text-shadow: none;\n background-color: transparent;\n border: 0;\n}\n\n// New mixin to use as of v3.0.1\n.text-hide() {\n .hide-text();\n}\n","//\n// Responsive: Utility classes\n// --------------------------------------------------\n\n\n// IE10 in Windows (Phone) 8\n//\n// Support for responsive views via media queries is kind of borked in IE10, for\n// Surface/desktop in split view and for Windows Phone 8. This particular fix\n// must be accompanied by a snippet of JavaScript to sniff the user agent and\n// apply some conditional CSS to *only* the Surface/desktop Windows 8. Look at\n// our Getting Started page for more information on this bug.\n//\n// For more information, see the following:\n//\n// Issue: https://github.com/twbs/bootstrap/issues/10497\n// Docs: http://getbootstrap.com/getting-started/#support-ie10-width\n// Source: http://timkadlec.com/2013/01/windows-phone-8-and-device-width/\n// Source: http://timkadlec.com/2012/10/ie10-snap-mode-and-responsive-design/\n\n@-ms-viewport {\n width: device-width;\n}\n\n\n// Visibility utilities\n// Note: Deprecated .visible-xs, .visible-sm, .visible-md, and .visible-lg as of v3.2.0\n.visible-xs,\n.visible-sm,\n.visible-md,\n.visible-lg {\n .responsive-invisibility();\n}\n\n.visible-xs-block,\n.visible-xs-inline,\n.visible-xs-inline-block,\n.visible-sm-block,\n.visible-sm-inline,\n.visible-sm-inline-block,\n.visible-md-block,\n.visible-md-inline,\n.visible-md-inline-block,\n.visible-lg-block,\n.visible-lg-inline,\n.visible-lg-inline-block {\n display: none !important;\n}\n\n.visible-xs {\n @media (max-width: @screen-xs-max) {\n .responsive-visibility();\n }\n}\n.visible-xs-block {\n @media (max-width: @screen-xs-max) {\n display: block !important;\n }\n}\n.visible-xs-inline {\n @media (max-width: @screen-xs-max) {\n display: inline !important;\n }\n}\n.visible-xs-inline-block {\n @media (max-width: @screen-xs-max) {\n display: inline-block !important;\n }\n}\n\n.visible-sm {\n @media (min-width: @screen-sm-min) and (max-width: @screen-sm-max) {\n .responsive-visibility();\n }\n}\n.visible-sm-block {\n @media (min-width: @screen-sm-min) and (max-width: @screen-sm-max) {\n display: block !important;\n }\n}\n.visible-sm-inline {\n @media (min-width: @screen-sm-min) and (max-width: @screen-sm-max) {\n display: inline !important;\n }\n}\n.visible-sm-inline-block {\n @media (min-width: @screen-sm-min) and (max-width: @screen-sm-max) {\n display: inline-block !important;\n }\n}\n\n.visible-md {\n @media (min-width: @screen-md-min) and (max-width: @screen-md-max) {\n .responsive-visibility();\n }\n}\n.visible-md-block {\n @media (min-width: @screen-md-min) and (max-width: @screen-md-max) {\n display: block !important;\n }\n}\n.visible-md-inline {\n @media (min-width: @screen-md-min) and (max-width: @screen-md-max) {\n display: inline !important;\n }\n}\n.visible-md-inline-block {\n @media (min-width: @screen-md-min) and (max-width: @screen-md-max) {\n display: inline-block !important;\n }\n}\n\n.visible-lg {\n @media (min-width: @screen-lg-min) {\n .responsive-visibility();\n }\n}\n.visible-lg-block {\n @media (min-width: @screen-lg-min) {\n display: block !important;\n }\n}\n.visible-lg-inline {\n @media (min-width: @screen-lg-min) {\n display: inline !important;\n }\n}\n.visible-lg-inline-block {\n @media (min-width: @screen-lg-min) {\n display: inline-block !important;\n }\n}\n\n.hidden-xs {\n @media (max-width: @screen-xs-max) {\n .responsive-invisibility();\n }\n}\n.hidden-sm {\n @media (min-width: @screen-sm-min) and (max-width: @screen-sm-max) {\n .responsive-invisibility();\n }\n}\n.hidden-md {\n @media (min-width: @screen-md-min) and (max-width: @screen-md-max) {\n .responsive-invisibility();\n }\n}\n.hidden-lg {\n @media (min-width: @screen-lg-min) {\n .responsive-invisibility();\n }\n}\n\n\n// Print utilities\n//\n// Media queries are placed on the inside to be mixin-friendly.\n\n// Note: Deprecated .visible-print as of v3.2.0\n.visible-print {\n .responsive-invisibility();\n\n @media print {\n .responsive-visibility();\n }\n}\n.visible-print-block {\n display: none !important;\n\n @media print {\n display: block !important;\n }\n}\n.visible-print-inline {\n display: none !important;\n\n @media print {\n display: inline !important;\n }\n}\n.visible-print-inline-block {\n display: none !important;\n\n @media print {\n display: inline-block !important;\n }\n}\n\n.hidden-print {\n @media print {\n .responsive-invisibility();\n }\n}\n","// Responsive utilities\n\n//\n// More easily include all the states for responsive-utilities.less.\n.responsive-visibility() {\n display: block !important;\n table& { display: table; }\n tr& { display: table-row !important; }\n th&,\n td& { display: table-cell !important; }\n}\n\n.responsive-invisibility() {\n display: none !important;\n}\n"]} \ No newline at end of file
diff --git a/doc/_extensions/odoo_ext/static/bootstrap.js b/doc/_extensions/odoo_ext/static/bootstrap.js
deleted file mode 100644
index 1c88b71e8bf..00000000000
--- a/doc/_extensions/odoo_ext/static/bootstrap.js
+++ /dev/null
@@ -1,2317 +0,0 @@
-/*!
- * Bootstrap v3.3.4 (http://getbootstrap.com)
- * Copyright 2011-2015 Twitter, Inc.
- * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
- */
-
-if (typeof jQuery === 'undefined') {
- throw new Error('Bootstrap\'s JavaScript requires jQuery')
-}
-
-+function ($) {
- 'use strict';
- var version = $.fn.jquery.split(' ')[0].split('.')
- if ((version[0] < 2 && version[1] < 9) || (version[0] == 1 && version[1] == 9 && version[2] < 1)) {
- throw new Error('Bootstrap\'s JavaScript requires jQuery version 1.9.1 or higher')
- }
-}(jQuery);
-
-/* ========================================================================
- * Bootstrap: transition.js v3.3.4
- * http://getbootstrap.com/javascript/#transitions
- * ========================================================================
- * Copyright 2011-2015 Twitter, Inc.
- * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
- * ======================================================================== */
-
-
-+function ($) {
- 'use strict';
-
- // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/)
- // ============================================================
-
- function transitionEnd() {
- var el = document.createElement('bootstrap')
-
- var transEndEventNames = {
- WebkitTransition : 'webkitTransitionEnd',
- MozTransition : 'transitionend',
- OTransition : 'oTransitionEnd otransitionend',
- transition : 'transitionend'
- }
-
- for (var name in transEndEventNames) {
- if (el.style[name] !== undefined) {
- return { end: transEndEventNames[name] }
- }
- }
-
- return false // explicit for ie8 ( ._.)
- }
-
- // http://blog.alexmaccaw.com/css-transitions
- $.fn.emulateTransitionEnd = function (duration) {
- var called = false
- var $el = this
- $(this).one('bsTransitionEnd', function () { called = true })
- var callback = function () { if (!called) $($el).trigger($.support.transition.end) }
- setTimeout(callback, duration)
- return this
- }
-
- $(function () {
- $.support.transition = transitionEnd()
-
- if (!$.support.transition) return
-
- $.event.special.bsTransitionEnd = {
- bindType: $.support.transition.end,
- delegateType: $.support.transition.end,
- handle: function (e) {
- if ($(e.target).is(this)) return e.handleObj.handler.apply(this, arguments)
- }
- }
- })
-
-}(jQuery);
-
-/* ========================================================================
- * Bootstrap: alert.js v3.3.4
- * http://getbootstrap.com/javascript/#alerts
- * ========================================================================
- * Copyright 2011-2015 Twitter, Inc.
- * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
- * ======================================================================== */
-
-
-+function ($) {
- 'use strict';
-
- // ALERT CLASS DEFINITION
- // ======================
-
- var dismiss = '[data-dismiss="alert"]'
- var Alert = function (el) {
- $(el).on('click', dismiss, this.close)
- }
-
- Alert.VERSION = '3.3.4'
-
- Alert.TRANSITION_DURATION = 150
-
- Alert.prototype.close = function (e) {
- var $this = $(this)
- var selector = $this.attr('data-target')
-
- if (!selector) {
- selector = $this.attr('href')
- selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
- }
-
- var $parent = $(selector)
-
- if (e) e.preventDefault()
-
- if (!$parent.length) {
- $parent = $this.closest('.alert')
- }
-
- $parent.trigger(e = $.Event('close.bs.alert'))
-
- if (e.isDefaultPrevented()) return
-
- $parent.removeClass('in')
-
- function removeElement() {
- // detach from parent, fire event then clean up data
- $parent.detach().trigger('closed.bs.alert').remove()
- }
-
- $.support.transition && $parent.hasClass('fade') ?
- $parent
- .one('bsTransitionEnd', removeElement)
- .emulateTransitionEnd(Alert.TRANSITION_DURATION) :
- removeElement()
- }
-
-
- // ALERT PLUGIN DEFINITION
- // =======================
-
- function Plugin(option) {
- return this.each(function () {
- var $this = $(this)
- var data = $this.data('bs.alert')
-
- if (!data) $this.data('bs.alert', (data = new Alert(this)))
- if (typeof option == 'string') data[option].call($this)
- })
- }
-
- var old = $.fn.alert
-
- $.fn.alert = Plugin
- $.fn.alert.Constructor = Alert
-
-
- // ALERT NO CONFLICT
- // =================
-
- $.fn.alert.noConflict = function () {
- $.fn.alert = old
- return this
- }
-
-
- // ALERT DATA-API
- // ==============
-
- $(document).on('click.bs.alert.data-api', dismiss, Alert.prototype.close)
-
-}(jQuery);
-
-/* ========================================================================
- * Bootstrap: button.js v3.3.4
- * http://getbootstrap.com/javascript/#buttons
- * ========================================================================
- * Copyright 2011-2015 Twitter, Inc.
- * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
- * ======================================================================== */
-
-
-+function ($) {
- 'use strict';
-
- // BUTTON PUBLIC CLASS DEFINITION
- // ==============================
-
- var Button = function (element, options) {
- this.$element = $(element)
- this.options = $.extend({}, Button.DEFAULTS, options)
- this.isLoading = false
- }
-
- Button.VERSION = '3.3.4'
-
- Button.DEFAULTS = {
- loadingText: 'loading...'
- }
-
- Button.prototype.setState = function (state) {
- var d = 'disabled'
- var $el = this.$element
- var val = $el.is('input') ? 'val' : 'html'
- var data = $el.data()
-
- state = state + 'Text'
-
- if (data.resetText == null) $el.data('resetText', $el[val]())
-
- // push to event loop to allow forms to submit
- setTimeout($.proxy(function () {
- $el[val](data[state] == null ? this.options[state] : data[state])
-
- if (state == 'loadingText') {
- this.isLoading = true
- $el.addClass(d).attr(d, d)
- } else if (this.isLoading) {
- this.isLoading = false
- $el.removeClass(d).removeAttr(d)
- }
- }, this), 0)
- }
-
- Button.prototype.toggle = function () {
- var changed = true
- var $parent = this.$element.closest('[data-toggle="buttons"]')
-
- if ($parent.length) {
- var $input = this.$element.find('input')
- if ($input.prop('type') == 'radio') {
- if ($input.prop('checked') && this.$element.hasClass('active')) changed = false
- else $parent.find('.active').removeClass('active')
- }
- if (changed) $input.prop('checked', !this.$element.hasClass('active')).trigger('change')
- } else {
- this.$element.attr('aria-pressed', !this.$element.hasClass('active'))
- }
-
- if (changed) this.$element.toggleClass('active')
- }
-
-
- // BUTTON PLUGIN DEFINITION
- // ========================
-
- function Plugin(option) {
- return this.each(function () {
- var $this = $(this)
- var data = $this.data('bs.button')
- var options = typeof option == 'object' && option
-
- if (!data) $this.data('bs.button', (data = new Button(this, options)))
-
- if (option == 'toggle') data.toggle()
- else if (option) data.setState(option)
- })
- }
-
- var old = $.fn.button
-
- $.fn.button = Plugin
- $.fn.button.Constructor = Button
-
-
- // BUTTON NO CONFLICT
- // ==================
-
- $.fn.button.noConflict = function () {
- $.fn.button = old
- return this
- }
-
-
- // BUTTON DATA-API
- // ===============
-
- $(document)
- .on('click.bs.button.data-api', '[data-toggle^="button"]', function (e) {
- var $btn = $(e.target)
- if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn')
- Plugin.call($btn, 'toggle')
- e.preventDefault()
- })
- .on('focus.bs.button.data-api blur.bs.button.data-api', '[data-toggle^="button"]', function (e) {
- $(e.target).closest('.btn').toggleClass('focus', /^focus(in)?$/.test(e.type))
- })
-
-}(jQuery);
-
-/* ========================================================================
- * Bootstrap: carousel.js v3.3.4
- * http://getbootstrap.com/javascript/#carousel
- * ========================================================================
- * Copyright 2011-2015 Twitter, Inc.
- * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
- * ======================================================================== */
-
-
-+function ($) {
- 'use strict';
-
- // CAROUSEL CLASS DEFINITION
- // =========================
-
- var Carousel = function (element, options) {
- this.$element = $(element)
- this.$indicators = this.$element.find('.carousel-indicators')
- this.options = options
- this.paused = null
- this.sliding = null
- this.interval = null
- this.$active = null
- this.$items = null
-
- this.options.keyboard && this.$element.on('keydown.bs.carousel', $.proxy(this.keydown, this))
-
- this.options.pause == 'hover' && !('ontouchstart' in document.documentElement) && this.$element
- .on('mouseenter.bs.carousel', $.proxy(this.pause, this))
- .on('mouseleave.bs.carousel', $.proxy(this.cycle, this))
- }
-
- Carousel.VERSION = '3.3.4'
-
- Carousel.TRANSITION_DURATION = 600
-
- Carousel.DEFAULTS = {
- interval: 5000,
- pause: 'hover',
- wrap: true,
- keyboard: true
- }
-
- Carousel.prototype.keydown = function (e) {
- if (/input|textarea/i.test(e.target.tagName)) return
- switch (e.which) {
- case 37: this.prev(); break
- case 39: this.next(); break
- default: return
- }
-
- e.preventDefault()
- }
-
- Carousel.prototype.cycle = function (e) {
- e || (this.paused = false)
-
- this.interval && clearInterval(this.interval)
-
- this.options.interval
- && !this.paused
- && (this.interval = setInterval($.proxy(this.next, this), this.options.interval))
-
- return this
- }
-
- Carousel.prototype.getItemIndex = function (item) {
- this.$items = item.parent().children('.item')
- return this.$items.index(item || this.$active)
- }
-
- Carousel.prototype.getItemForDirection = function (direction, active) {
- var activeIndex = this.getItemIndex(active)
- var willWrap = (direction == 'prev' && activeIndex === 0)
- || (direction == 'next' && activeIndex == (this.$items.length - 1))
- if (willWrap && !this.options.wrap) return active
- var delta = direction == 'prev' ? -1 : 1
- var itemIndex = (activeIndex + delta) % this.$items.length
- return this.$items.eq(itemIndex)
- }
-
- Carousel.prototype.to = function (pos) {
- var that = this
- var activeIndex = this.getItemIndex(this.$active = this.$element.find('.item.active'))
-
- if (pos > (this.$items.length - 1) || pos < 0) return
-
- if (this.sliding) return this.$element.one('slid.bs.carousel', function () { that.to(pos) }) // yes, "slid"
- if (activeIndex == pos) return this.pause().cycle()
-
- return this.slide(pos > activeIndex ? 'next' : 'prev', this.$items.eq(pos))
- }
-
- Carousel.prototype.pause = function (e) {
- e || (this.paused = true)
-
- if (this.$element.find('.next, .prev').length && $.support.transition) {
- this.$element.trigger($.support.transition.end)
- this.cycle(true)
- }
-
- this.interval = clearInterval(this.interval)
-
- return this
- }
-
- Carousel.prototype.next = function () {
- if (this.sliding) return
- return this.slide('next')
- }
-
- Carousel.prototype.prev = function () {
- if (this.sliding) return
- return this.slide('prev')
- }
-
- Carousel.prototype.slide = function (type, next) {
- var $active = this.$element.find('.item.active')
- var $next = next || this.getItemForDirection(type, $active)
- var isCycling = this.interval
- var direction = type == 'next' ? 'left' : 'right'
- var that = this
-
- if ($next.hasClass('active')) return (this.sliding = false)
-
- var relatedTarget = $next[0]
- var slideEvent = $.Event('slide.bs.carousel', {
- relatedTarget: relatedTarget,
- direction: direction
- })
- this.$element.trigger(slideEvent)
- if (slideEvent.isDefaultPrevented()) return
-
- this.sliding = true
-
- isCycling && this.pause()
-
- if (this.$indicators.length) {
- this.$indicators.find('.active').removeClass('active')
- var $nextIndicator = $(this.$indicators.children()[this.getItemIndex($next)])
- $nextIndicator && $nextIndicator.addClass('active')
- }
-
- var slidEvent = $.Event('slid.bs.carousel', { relatedTarget: relatedTarget, direction: direction }) // yes, "slid"
- if ($.support.transition && this.$element.hasClass('slide')) {
- $next.addClass(type)
- $next[0].offsetWidth // force reflow
- $active.addClass(direction)
- $next.addClass(direction)
- $active
- .one('bsTransitionEnd', function () {
- $next.removeClass([type, direction].join(' ')).addClass('active')
- $active.removeClass(['active', direction].join(' '))
- that.sliding = false
- setTimeout(function () {
- that.$element.trigger(slidEvent)
- }, 0)
- })
- .emulateTransitionEnd(Carousel.TRANSITION_DURATION)
- } else {
- $active.removeClass('active')
- $next.addClass('active')
- this.sliding = false
- this.$element.trigger(slidEvent)
- }
-
- isCycling && this.cycle()
-
- return this
- }
-
-
- // CAROUSEL PLUGIN DEFINITION
- // ==========================
-
- function Plugin(option) {
- return this.each(function () {
- var $this = $(this)
- var data = $this.data('bs.carousel')
- var options = $.extend({}, Carousel.DEFAULTS, $this.data(), typeof option == 'object' && option)
- var action = typeof option == 'string' ? option : options.slide
-
- if (!data) $this.data('bs.carousel', (data = new Carousel(this, options)))
- if (typeof option == 'number') data.to(option)
- else if (action) data[action]()
- else if (options.interval) data.pause().cycle()
- })
- }
-
- var old = $.fn.carousel
-
- $.fn.carousel = Plugin
- $.fn.carousel.Constructor = Carousel
-
-
- // CAROUSEL NO CONFLICT
- // ====================
-
- $.fn.carousel.noConflict = function () {
- $.fn.carousel = old
- return this
- }
-
-
- // CAROUSEL DATA-API
- // =================
-
- var clickHandler = function (e) {
- var href
- var $this = $(this)
- var $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) // strip for ie7
- if (!$target.hasClass('carousel')) return
- var options = $.extend({}, $target.data(), $this.data())
- var slideIndex = $this.attr('data-slide-to')
- if (slideIndex) options.interval = false
-
- Plugin.call($target, options)
-
- if (slideIndex) {
- $target.data('bs.carousel').to(slideIndex)
- }
-
- e.preventDefault()
- }
-
- $(document)
- .on('click.bs.carousel.data-api', '[data-slide]', clickHandler)
- .on('click.bs.carousel.data-api', '[data-slide-to]', clickHandler)
-
- $(window).on('load', function () {
- $('[data-ride="carousel"]').each(function () {
- var $carousel = $(this)
- Plugin.call($carousel, $carousel.data())
- })
- })
-
-}(jQuery);
-
-/* ========================================================================
- * Bootstrap: collapse.js v3.3.4
- * http://getbootstrap.com/javascript/#collapse
- * ========================================================================
- * Copyright 2011-2015 Twitter, Inc.
- * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
- * ======================================================================== */
-
-
-+function ($) {
- 'use strict';
-
- // COLLAPSE PUBLIC CLASS DEFINITION
- // ================================
-
- var Collapse = function (element, options) {
- this.$element = $(element)
- this.options = $.extend({}, Collapse.DEFAULTS, options)
- this.$trigger = $('[data-toggle="collapse"][href="#' + element.id + '"],' +
- '[data-toggle="collapse"][data-target="#' + element.id + '"]')
- this.transitioning = null
-
- if (this.options.parent) {
- this.$parent = this.getParent()
- } else {
- this.addAriaAndCollapsedClass(this.$element, this.$trigger)
- }
-
- if (this.options.toggle) this.toggle()
- }
-
- Collapse.VERSION = '3.3.4'
-
- Collapse.TRANSITION_DURATION = 350
-
- Collapse.DEFAULTS = {
- toggle: true
- }
-
- Collapse.prototype.dimension = function () {
- var hasWidth = this.$element.hasClass('width')
- return hasWidth ? 'width' : 'height'
- }
-
- Collapse.prototype.show = function () {
- if (this.transitioning || this.$element.hasClass('in')) return
-
- var activesData
- var actives = this.$parent && this.$parent.children('.panel').children('.in, .collapsing')
-
- if (actives && actives.length) {
- activesData = actives.data('bs.collapse')
- if (activesData && activesData.transitioning) return
- }
-
- var startEvent = $.Event('show.bs.collapse')
- this.$element.trigger(startEvent)
- if (startEvent.isDefaultPrevented()) return
-
- if (actives && actives.length) {
- Plugin.call(actives, 'hide')
- activesData || actives.data('bs.collapse', null)
- }
-
- var dimension = this.dimension()
-
- this.$element
- .removeClass('collapse')
- .addClass('collapsing')[dimension](0)
- .attr('aria-expanded', true)
-
- this.$trigger
- .removeClass('collapsed')
- .attr('aria-expanded', true)
-
- this.transitioning = 1
-
- var complete = function () {
- this.$element
- .removeClass('collapsing')
- .addClass('collapse in')[dimension]('')
- this.transitioning = 0
- this.$element
- .trigger('shown.bs.collapse')
- }
-
- if (!$.support.transition) return complete.call(this)
-
- var scrollSize = $.camelCase(['scroll', dimension].join('-'))
-
- this.$element
- .one('bsTransitionEnd', $.proxy(complete, this))
- .emulateTransitionEnd(Collapse.TRANSITION_DURATION)[dimension](this.$element[0][scrollSize])
- }
-
- Collapse.prototype.hide = function () {
- if (this.transitioning || !this.$element.hasClass('in')) return
-
- var startEvent = $.Event('hide.bs.collapse')
- this.$element.trigger(startEvent)
- if (startEvent.isDefaultPrevented()) return
-
- var dimension = this.dimension()
-
- this.$element[dimension](this.$element[dimension]())[0].offsetHeight
-
- this.$element
- .addClass('collapsing')
- .removeClass('collapse in')
- .attr('aria-expanded', false)
-
- this.$trigger
- .addClass('collapsed')
- .attr('aria-expanded', false)
-
- this.transitioning = 1
-
- var complete = function () {
- this.transitioning = 0
- this.$element
- .removeClass('collapsing')
- .addClass('collapse')
- .trigger('hidden.bs.collapse')
- }
-
- if (!$.support.transition) return complete.call(this)
-
- this.$element
- [dimension](0)
- .one('bsTransitionEnd', $.proxy(complete, this))
- .emulateTransitionEnd(Collapse.TRANSITION_DURATION)
- }
-
- Collapse.prototype.toggle = function () {
- this[this.$element.hasClass('in') ? 'hide' : 'show']()
- }
-
- Collapse.prototype.getParent = function () {
- return $(this.options.parent)
- .find('[data-toggle="collapse"][data-parent="' + this.options.parent + '"]')
- .each($.proxy(function (i, element) {
- var $element = $(element)
- this.addAriaAndCollapsedClass(getTargetFromTrigger($element), $element)
- }, this))
- .end()
- }
-
- Collapse.prototype.addAriaAndCollapsedClass = function ($element, $trigger) {
- var isOpen = $element.hasClass('in')
-
- $element.attr('aria-expanded', isOpen)
- $trigger
- .toggleClass('collapsed', !isOpen)
- .attr('aria-expanded', isOpen)
- }
-
- function getTargetFromTrigger($trigger) {
- var href
- var target = $trigger.attr('data-target')
- || (href = $trigger.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7
-
- return $(target)
- }
-
-
- // COLLAPSE PLUGIN DEFINITION
- // ==========================
-
- function Plugin(option) {
- return this.each(function () {
- var $this = $(this)
- var data = $this.data('bs.collapse')
- var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option)
-
- if (!data && options.toggle && /show|hide/.test(option)) options.toggle = false
- if (!data) $this.data('bs.collapse', (data = new Collapse(this, options)))
- if (typeof option == 'string') data[option]()
- })
- }
-
- var old = $.fn.collapse
-
- $.fn.collapse = Plugin
- $.fn.collapse.Constructor = Collapse
-
-
- // COLLAPSE NO CONFLICT
- // ====================
-
- $.fn.collapse.noConflict = function () {
- $.fn.collapse = old
- return this
- }
-
-
- // COLLAPSE DATA-API
- // =================
-
- $(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) {
- var $this = $(this)
-
- if (!$this.attr('data-target')) e.preventDefault()
-
- var $target = getTargetFromTrigger($this)
- var data = $target.data('bs.collapse')
- var option = data ? 'toggle' : $this.data()
-
- Plugin.call($target, option)
- })
-
-}(jQuery);
-
-/* ========================================================================
- * Bootstrap: dropdown.js v3.3.4
- * http://getbootstrap.com/javascript/#dropdowns
- * ========================================================================
- * Copyright 2011-2015 Twitter, Inc.
- * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
- * ======================================================================== */
-
-
-+function ($) {
- 'use strict';
-
- // DROPDOWN CLASS DEFINITION
- // =========================
-
- var backdrop = '.dropdown-backdrop'
- var toggle = '[data-toggle="dropdown"]'
- var Dropdown = function (element) {
- $(element).on('click.bs.dropdown', this.toggle)
- }
-
- Dropdown.VERSION = '3.3.4'
-
- Dropdown.prototype.toggle = function (e) {
- var $this = $(this)
-
- if ($this.is('.disabled, :disabled')) return
-
- var $parent = getParent($this)
- var isActive = $parent.hasClass('open')
-
- clearMenus()
-
- if (!isActive) {
- if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) {
- // if mobile we use a backdrop because click events don't delegate
- $('<div class="dropdown-backdrop"/>').insertAfter($(this)).on('click', clearMenus)
- }
-
- var relatedTarget = { relatedTarget: this }
- $parent.trigger(e = $.Event('show.bs.dropdown', relatedTarget))
-
- if (e.isDefaultPrevented()) return
-
- $this
- .trigger('focus')
- .attr('aria-expanded', 'true')
-
- $parent
- .toggleClass('open')
- .trigger('shown.bs.dropdown', relatedTarget)
- }
-
- return false
- }
-
- Dropdown.prototype.keydown = function (e) {
- if (!/(38|40|27|32)/.test(e.which) || /input|textarea/i.test(e.target.tagName)) return
-
- var $this = $(this)
-
- e.preventDefault()
- e.stopPropagation()
-
- if ($this.is('.disabled, :disabled')) return
-
- var $parent = getParent($this)
- var isActive = $parent.hasClass('open')
-
- if ((!isActive && e.which != 27) || (isActive && e.which == 27)) {
- if (e.which == 27) $parent.find(toggle).trigger('focus')
- return $this.trigger('click')
- }
-
- var desc = ' li:not(.disabled):visible a'
- var $items = $parent.find('[role="menu"]' + desc + ', [role="listbox"]' + desc)
-
- if (!$items.length) return
-
- var index = $items.index(e.target)
-
- if (e.which == 38 && index > 0) index-- // up
- if (e.which == 40 && index < $items.length - 1) index++ // down
- if (!~index) index = 0
-
- $items.eq(index).trigger('focus')
- }
-
- function clearMenus(e) {
- if (e && e.which === 3) return
- $(backdrop).remove()
- $(toggle).each(function () {
- var $this = $(this)
- var $parent = getParent($this)
- var relatedTarget = { relatedTarget: this }
-
- if (!$parent.hasClass('open')) return
-
- $parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget))
-
- if (e.isDefaultPrevented()) return
-
- $this.attr('aria-expanded', 'false')
- $parent.removeClass('open').trigger('hidden.bs.dropdown', relatedTarget)
- })
- }
-
- function getParent($this) {
- var selector = $this.attr('data-target')
-
- if (!selector) {
- selector = $this.attr('href')
- selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
- }
-
- var $parent = selector && $(selector)
-
- return $parent && $parent.length ? $parent : $this.parent()
- }
-
-
- // DROPDOWN PLUGIN DEFINITION
- // ==========================
-
- function Plugin(option) {
- return this.each(function () {
- var $this = $(this)
- var data = $this.data('bs.dropdown')
-
- if (!data) $this.data('bs.dropdown', (data = new Dropdown(this)))
- if (typeof option == 'string') data[option].call($this)
- })
- }
-
- var old = $.fn.dropdown
-
- $.fn.dropdown = Plugin
- $.fn.dropdown.Constructor = Dropdown
-
-
- // DROPDOWN NO CONFLICT
- // ====================
-
- $.fn.dropdown.noConflict = function () {
- $.fn.dropdown = old
- return this
- }
-
-
- // APPLY TO STANDARD DROPDOWN ELEMENTS
- // ===================================
-
- $(document)
- .on('click.bs.dropdown.data-api', clearMenus)
- .on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })
- .on('click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle)
- .on('keydown.bs.dropdown.data-api', toggle, Dropdown.prototype.keydown)
- .on('keydown.bs.dropdown.data-api', '[role="menu"]', Dropdown.prototype.keydown)
- .on('keydown.bs.dropdown.data-api', '[role="listbox"]', Dropdown.prototype.keydown)
-
-}(jQuery);
-
-/* ========================================================================
- * Bootstrap: modal.js v3.3.4
- * http://getbootstrap.com/javascript/#modals
- * ========================================================================
- * Copyright 2011-2015 Twitter, Inc.
- * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
- * ======================================================================== */
-
-
-+function ($) {
- 'use strict';
-
- // MODAL CLASS DEFINITION
- // ======================
-
- var Modal = function (element, options) {
- this.options = options
- this.$body = $(document.body)
- this.$element = $(element)
- this.$dialog = this.$element.find('.modal-dialog')
- this.$backdrop = null
- this.isShown = null
- this.originalBodyPad = null
- this.scrollbarWidth = 0
- this.ignoreBackdropClick = false
-
- if (this.options.remote) {
- this.$element
- .find('.modal-content')
- .load(this.options.remote, $.proxy(function () {
- this.$element.trigger('loaded.bs.modal')
- }, this))
- }
- }
-
- Modal.VERSION = '3.3.4'
-
- Modal.TRANSITION_DURATION = 300
- Modal.BACKDROP_TRANSITION_DURATION = 150
-
- Modal.DEFAULTS = {
- backdrop: true,
- keyboard: true,
- show: true
- }
-
- Modal.prototype.toggle = function (_relatedTarget) {
- return this.isShown ? this.hide() : this.show(_relatedTarget)
- }
-
- Modal.prototype.show = function (_relatedTarget) {
- var that = this
- var e = $.Event('show.bs.modal', { relatedTarget: _relatedTarget })
-
- this.$element.trigger(e)
-
- if (this.isShown || e.isDefaultPrevented()) return
-
- this.isShown = true
-
- this.checkScrollbar()
- this.setScrollbar()
- this.$body.addClass('modal-open')
-
- this.escape()
- this.resize()
-
- this.$element.on('click.dismiss.bs.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this))
-
- this.$dialog.on('mousedown.dismiss.bs.modal', function () {
- that.$element.one('mouseup.dismiss.bs.modal', function (e) {
- if ($(e.target).is(that.$element)) that.ignoreBackdropClick = true
- })
- })
-
- this.backdrop(function () {
- var transition = $.support.transition && that.$element.hasClass('fade')
-
- if (!that.$element.parent().length) {
- that.$element.appendTo(that.$body) // don't move modals dom position
- }
-
- that.$element
- .show()
- .scrollTop(0)
-
- that.adjustDialog()
-
- if (transition) {
- that.$element[0].offsetWidth // force reflow
- }
-
- that.$element
- .addClass('in')
- .attr('aria-hidden', false)
-
- that.enforceFocus()
-
- var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget })
-
- transition ?
- that.$dialog // wait for modal to slide in
- .one('bsTransitionEnd', function () {
- that.$element.trigger('focus').trigger(e)
- })
- .emulateTransitionEnd(Modal.TRANSITION_DURATION) :
- that.$element.trigger('focus').trigger(e)
- })
- }
-
- Modal.prototype.hide = function (e) {
- if (e) e.preventDefault()
-
- e = $.Event('hide.bs.modal')
-
- this.$element.trigger(e)
-
- if (!this.isShown || e.isDefaultPrevented()) return
-
- this.isShown = false
-
- this.escape()
- this.resize()
-
- $(document).off('focusin.bs.modal')
-
- this.$element
- .removeClass('in')
- .attr('aria-hidden', true)
- .off('click.dismiss.bs.modal')
- .off('mouseup.dismiss.bs.modal')
-
- this.$dialog.off('mousedown.dismiss.bs.modal')
-
- $.support.transition && this.$element.hasClass('fade') ?
- this.$element
- .one('bsTransitionEnd', $.proxy(this.hideModal, this))
- .emulateTransitionEnd(Modal.TRANSITION_DURATION) :
- this.hideModal()
- }
-
- Modal.prototype.enforceFocus = function () {
- $(document)
- .off('focusin.bs.modal') // guard against infinite focus loop
- .on('focusin.bs.modal', $.proxy(function (e) {
- if (this.$element[0] !== e.target && !this.$element.has(e.target).length) {
- this.$element.trigger('focus')
- }
- }, this))
- }
-
- Modal.prototype.escape = function () {
- if (this.isShown && this.options.keyboard) {
- this.$element.on('keydown.dismiss.bs.modal', $.proxy(function (e) {
- e.which == 27 && this.hide()
- }, this))
- } else if (!this.isShown) {
- this.$element.off('keydown.dismiss.bs.modal')
- }
- }
-
- Modal.prototype.resize = function () {
- if (this.isShown) {
- $(window).on('resize.bs.modal', $.proxy(this.handleUpdate, this))
- } else {
- $(window).off('resize.bs.modal')
- }
- }
-
- Modal.prototype.hideModal = function () {
- var that = this
- this.$element.hide()
- this.backdrop(function () {
- that.$body.removeClass('modal-open')
- that.resetAdjustments()
- that.resetScrollbar()
- that.$element.trigger('hidden.bs.modal')
- })
- }
-
- Modal.prototype.removeBackdrop = function () {
- this.$backdrop && this.$backdrop.remove()
- this.$backdrop = null
- }
-
- Modal.prototype.backdrop = function (callback) {
- var that = this
- var animate = this.$element.hasClass('fade') ? 'fade' : ''
-
- if (this.isShown && this.options.backdrop) {
- var doAnimate = $.support.transition && animate
-
- this.$backdrop = $('<div class="modal-backdrop ' + animate + '" />')
- .appendTo(this.$body)
-
- this.$element.on('click.dismiss.bs.modal', $.proxy(function (e) {
- if (this.ignoreBackdropClick) {
- this.ignoreBackdropClick = false
- return
- }
- if (e.target !== e.currentTarget) return
- this.options.backdrop == 'static'
- ? this.$element[0].focus()
- : this.hide()
- }, this))
-
- if (doAnimate) this.$backdrop[0].offsetWidth // force reflow
-
- this.$backdrop.addClass('in')
-
- if (!callback) return
-
- doAnimate ?
- this.$backdrop
- .one('bsTransitionEnd', callback)
- .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :
- callback()
-
- } else if (!this.isShown && this.$backdrop) {
- this.$backdrop.removeClass('in')
-
- var callbackRemove = function () {
- that.removeBackdrop()
- callback && callback()
- }
- $.support.transition && this.$element.hasClass('fade') ?
- this.$backdrop
- .one('bsTransitionEnd', callbackRemove)
- .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :
- callbackRemove()
-
- } else if (callback) {
- callback()
- }
- }
-
- // these following methods are used to handle overflowing modals
-
- Modal.prototype.handleUpdate = function () {
- this.adjustDialog()
- }
-
- Modal.prototype.adjustDialog = function () {
- var modalIsOverflowing = this.$element[0].scrollHeight > document.documentElement.clientHeight
-
- this.$element.css({
- paddingLeft: !this.bodyIsOverflowing && modalIsOverflowing ? this.scrollbarWidth : '',
- paddingRight: this.bodyIsOverflowing && !modalIsOverflowing ? this.scrollbarWidth : ''
- })
- }
-
- Modal.prototype.resetAdjustments = function () {
- this.$element.css({
- paddingLeft: '',
- paddingRight: ''
- })
- }
-
- Modal.prototype.checkScrollbar = function () {
- var fullWindowWidth = window.innerWidth
- if (!fullWindowWidth) { // workaround for missing window.innerWidth in IE8
- var documentElementRect = document.documentElement.getBoundingClientRect()
- fullWindowWidth = documentElementRect.right - Math.abs(documentElementRect.left)
- }
- this.bodyIsOverflowing = document.body.clientWidth < fullWindowWidth
- this.scrollbarWidth = this.measureScrollbar()
- }
-
- Modal.prototype.setScrollbar = function () {
- var bodyPad = parseInt((this.$body.css('padding-right') || 0), 10)
- this.originalBodyPad = document.body.style.paddingRight || ''
- if (this.bodyIsOverflowing) this.$body.css('padding-right', bodyPad + this.scrollbarWidth)
- }
-
- Modal.prototype.resetScrollbar = function () {
- this.$body.css('padding-right', this.originalBodyPad)
- }
-
- Modal.prototype.measureScrollbar = function () { // thx walsh
- var scrollDiv = document.createElement('div')
- scrollDiv.className = 'modal-scrollbar-measure'
- this.$body.append(scrollDiv)
- var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth
- this.$body[0].removeChild(scrollDiv)
- return scrollbarWidth
- }
-
-
- // MODAL PLUGIN DEFINITION
- // =======================
-
- function Plugin(option, _relatedTarget) {
- return this.each(function () {
- var $this = $(this)
- var data = $this.data('bs.modal')
- var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option)
-
- if (!data) $this.data('bs.modal', (data = new Modal(this, options)))
- if (typeof option == 'string') data[option](_relatedTarget)
- else if (options.show) data.show(_relatedTarget)
- })
- }
-
- var old = $.fn.modal
-
- $.fn.modal = Plugin
- $.fn.modal.Constructor = Modal
-
-
- // MODAL NO CONFLICT
- // =================
-
- $.fn.modal.noConflict = function () {
- $.fn.modal = old
- return this
- }
-
-
- // MODAL DATA-API
- // ==============
-
- $(document).on('click.bs.modal.data-api', '[data-toggle="modal"]', function (e) {
- var $this = $(this)
- var href = $this.attr('href')
- var $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) // strip for ie7
- var option = $target.data('bs.modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data())
-
- if ($this.is('a')) e.preventDefault()
-
- $target.one('show.bs.modal', function (showEvent) {
- if (showEvent.isDefaultPrevented()) return // only register focus restorer if modal will actually get shown
- $target.one('hidden.bs.modal', function () {
- $this.is(':visible') && $this.trigger('focus')
- })
- })
- Plugin.call($target, option, this)
- })
-
-}(jQuery);
-
-/* ========================================================================
- * Bootstrap: tooltip.js v3.3.4
- * http://getbootstrap.com/javascript/#tooltip
- * Inspired by the original jQuery.tipsy by Jason Frame
- * ========================================================================
- * Copyright 2011-2015 Twitter, Inc.
- * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
- * ======================================================================== */
-
-
-+function ($) {
- 'use strict';
-
- // TOOLTIP PUBLIC CLASS DEFINITION
- // ===============================
-
- var Tooltip = function (element, options) {
- this.type = null
- this.options = null
- this.enabled = null
- this.timeout = null
- this.hoverState = null
- this.$element = null
-
- this.init('tooltip', element, options)
- }
-
- Tooltip.VERSION = '3.3.4'
-
- Tooltip.TRANSITION_DURATION = 150
-
- Tooltip.DEFAULTS = {
- animation: true,
- placement: 'top',
- selector: false,
- template: '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',
- trigger: 'hover focus',
- title: '',
- delay: 0,
- html: false,
- container: false,
- viewport: {
- selector: 'body',
- padding: 0
- }
- }
-
- Tooltip.prototype.init = function (type, element, options) {
- this.enabled = true
- this.type = type
- this.$element = $(element)
- this.options = this.getOptions(options)
- this.$viewport = this.options.viewport && $(this.options.viewport.selector || this.options.viewport)
-
- if (this.$element[0] instanceof document.constructor && !this.options.selector) {
- throw new Error('`selector` option must be specified when initializing ' + this.type + ' on the window.document object!')
- }
-
- var triggers = this.options.trigger.split(' ')
-
- for (var i = triggers.length; i--;) {
- var trigger = triggers[i]
-
- if (trigger == 'click') {
- this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
- } else if (trigger != 'manual') {
- var eventIn = trigger == 'hover' ? 'mouseenter' : 'focusin'
- var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout'
-
- this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
- this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
- }
- }
-
- this.options.selector ?
- (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
- this.fixTitle()
- }
-
- Tooltip.prototype.getDefaults = function () {
- return Tooltip.DEFAULTS
- }
-
- Tooltip.prototype.getOptions = function (options) {
- options = $.extend({}, this.getDefaults(), this.$element.data(), options)
-
- if (options.delay && typeof options.delay == 'number') {
- options.delay = {
- show: options.delay,
- hide: options.delay
- }
- }
-
- return options
- }
-
- Tooltip.prototype.getDelegateOptions = function () {
- var options = {}
- var defaults = this.getDefaults()
-
- this._options && $.each(this._options, function (key, value) {
- if (defaults[key] != value) options[key] = value
- })
-
- return options
- }
-
- Tooltip.prototype.enter = function (obj) {
- var self = obj instanceof this.constructor ?
- obj : $(obj.currentTarget).data('bs.' + this.type)
-
- if (self && self.$tip && self.$tip.is(':visible')) {
- self.hoverState = 'in'
- return
- }
-
- if (!self) {
- self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
- $(obj.currentTarget).data('bs.' + this.type, self)
- }
-
- clearTimeout(self.timeout)
-
- self.hoverState = 'in'
-
- if (!self.options.delay || !self.options.delay.show) return self.show()
-
- self.timeout = setTimeout(function () {
- if (self.hoverState == 'in') self.show()
- }, self.options.delay.show)
- }
-
- Tooltip.prototype.leave = function (obj) {
- var self = obj instanceof this.constructor ?
- obj : $(obj.currentTarget).data('bs.' + this.type)
-
- if (!self) {
- self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
- $(obj.currentTarget).data('bs.' + this.type, self)
- }
-
- clearTimeout(self.timeout)
-
- self.hoverState = 'out'
-
- if (!self.options.delay || !self.options.delay.hide) return self.hide()
-
- self.timeout = setTimeout(function () {
- if (self.hoverState == 'out') self.hide()
- }, self.options.delay.hide)
- }
-
- Tooltip.prototype.show = function () {
- var e = $.Event('show.bs.' + this.type)
-
- if (this.hasContent() && this.enabled) {
- this.$element.trigger(e)
-
- var inDom = $.contains(this.$element[0].ownerDocument.documentElement, this.$element[0])
- if (e.isDefaultPrevented() || !inDom) return
- var that = this
-
- var $tip = this.tip()
-
- var tipId = this.getUID(this.type)
-
- this.setContent()
- $tip.attr('id', tipId)
- this.$element.attr('aria-describedby', tipId)
-
- if (this.options.animation) $tip.addClass('fade')
-
- var placement = typeof this.options.placement == 'function' ?
- this.options.placement.call(this, $tip[0], this.$element[0]) :
- this.options.placement
-
- var autoToken = /\s?auto?\s?/i
- var autoPlace = autoToken.test(placement)
- if (autoPlace) placement = placement.replace(autoToken, '') || 'top'
-
- $tip
- .detach()
- .css({ top: 0, left: 0, display: 'block' })
- .addClass(placement)
- .data('bs.' + this.type, this)
-
- this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)
-
- var pos = this.getPosition()
- var actualWidth = $tip[0].offsetWidth
- var actualHeight = $tip[0].offsetHeight
-
- if (autoPlace) {
- var orgPlacement = placement
- var $container = this.options.container ? $(this.options.container) : this.$element.parent()
- var containerDim = this.getPosition($container)
-
- placement = placement == 'bottom' && pos.bottom + actualHeight > containerDim.bottom ? 'top' :
- placement == 'top' && pos.top - actualHeight < containerDim.top ? 'bottom' :
- placement == 'right' && pos.right + actualWidth > containerDim.width ? 'left' :
- placement == 'left' && pos.left - actualWidth < containerDim.left ? 'right' :
- placement
-
- $tip
- .removeClass(orgPlacement)
- .addClass(placement)
- }
-
- var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight)
-
- this.applyPlacement(calculatedOffset, placement)
-
- var complete = function () {
- var prevHoverState = that.hoverState
- that.$element.trigger('shown.bs.' + that.type)
- that.hoverState = null
-
- if (prevHoverState == 'out') that.leave(that)
- }
-
- $.support.transition && this.$tip.hasClass('fade') ?
- $tip
- .one('bsTransitionEnd', complete)
- .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
- complete()
- }
- }
-
- Tooltip.prototype.applyPlacement = function (offset, placement) {
- var $tip = this.tip()
- var width = $tip[0].offsetWidth
- var height = $tip[0].offsetHeight
-
- // manually read margins because getBoundingClientRect includes difference
- var marginTop = parseInt($tip.css('margin-top'), 10)
- var marginLeft = parseInt($tip.css('margin-left'), 10)
-
- // we must check for NaN for ie 8/9
- if (isNaN(marginTop)) marginTop = 0
- if (isNaN(marginLeft)) marginLeft = 0
-
- offset.top = offset.top + marginTop
- offset.left = offset.left + marginLeft
-
- // $.fn.offset doesn't round pixel values
- // so we use setOffset directly with our own function B-0
- $.offset.setOffset($tip[0], $.extend({
- using: function (props) {
- $tip.css({
- top: Math.round(props.top),
- left: Math.round(props.left)
- })
- }
- }, offset), 0)
-
- $tip.addClass('in')
-
- // check to see if placing tip in new offset caused the tip to resize itself
- var actualWidth = $tip[0].offsetWidth
- var actualHeight = $tip[0].offsetHeight
-
- if (placement == 'top' && actualHeight != height) {
- offset.top = offset.top + height - actualHeight
- }
-
- var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight)
-
- if (delta.left) offset.left += delta.left
- else offset.top += delta.top
-
- var isVertical = /top|bottom/.test(placement)
- var arrowDelta = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight
- var arrowOffsetPosition = isVertical ? 'offsetWidth' : 'offsetHeight'
-
- $tip.offset(offset)
- this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], isVertical)
- }
-
- Tooltip.prototype.replaceArrow = function (delta, dimension, isVertical) {
- this.arrow()
- .css(isVertical ? 'left' : 'top', 50 * (1 - delta / dimension) + '%')
- .css(isVertical ? 'top' : 'left', '')
- }
-
- Tooltip.prototype.setContent = function () {
- var $tip = this.tip()
- var title = this.getTitle()
-
- $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
- $tip.removeClass('fade in top bottom left right')
- }
-
- Tooltip.prototype.hide = function (callback) {
- var that = this
- var $tip = $(this.$tip)
- var e = $.Event('hide.bs.' + this.type)
-
- function complete() {
- if (that.hoverState != 'in') $tip.detach()
- that.$element
- .removeAttr('aria-describedby')
- .trigger('hidden.bs.' + that.type)
- callback && callback()
- }
-
- this.$element.trigger(e)
-
- if (e.isDefaultPrevented()) return
-
- $tip.removeClass('in')
-
- $.support.transition && $tip.hasClass('fade') ?
- $tip
- .one('bsTransitionEnd', complete)
- .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
- complete()
-
- this.hoverState = null
-
- return this
- }
-
- Tooltip.prototype.fixTitle = function () {
- var $e = this.$element
- if ($e.attr('title') || typeof ($e.attr('data-original-title')) != 'string') {
- $e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
- }
- }
-
- Tooltip.prototype.hasContent = function () {
- return this.getTitle()
- }
-
- Tooltip.prototype.getPosition = function ($element) {
- $element = $element || this.$element
-
- var el = $element[0]
- var isBody = el.tagName == 'BODY'
-
- var elRect = el.getBoundingClientRect()
- if (elRect.width == null) {
- // width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093
- elRect = $.extend({}, elRect, { width: elRect.right - elRect.left, height: elRect.bottom - elRect.top })
- }
- var elOffset = isBody ? { top: 0, left: 0 } : $element.offset()
- var scroll = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop() }
- var outerDims = isBody ? { width: $(window).width(), height: $(window).height() } : null
-
- return $.extend({}, elRect, scroll, outerDims, elOffset)
- }
-
- Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) {
- return placement == 'bottom' ? { top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 } :
- placement == 'top' ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } :
- placement == 'left' ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } :
- /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width }
-
- }
-
- Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) {
- var delta = { top: 0, left: 0 }
- if (!this.$viewport) return delta
-
- var viewportPadding = this.options.viewport && this.options.viewport.padding || 0
- var viewportDimensions = this.getPosition(this.$viewport)
-
- if (/right|left/.test(placement)) {
- var topEdgeOffset = pos.top - viewportPadding - viewportDimensions.scroll
- var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight
- if (topEdgeOffset < viewportDimensions.top) { // top overflow
- delta.top = viewportDimensions.top - topEdgeOffset
- } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow
- delta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset
- }
- } else {
- var leftEdgeOffset = pos.left - viewportPadding
- var rightEdgeOffset = pos.left + viewportPadding + actualWidth
- if (leftEdgeOffset < viewportDimensions.left) { // left overflow
- delta.left = viewportDimensions.left - leftEdgeOffset
- } else if (rightEdgeOffset > viewportDimensions.width) { // right overflow
- delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset
- }
- }
-
- return delta
- }
-
- Tooltip.prototype.getTitle = function () {
- var title
- var $e = this.$element
- var o = this.options
-
- title = $e.attr('data-original-title')
- || (typeof o.title == 'function' ? o.title.call($e[0]) : o.title)
-
- return title
- }
-
- Tooltip.prototype.getUID = function (prefix) {
- do prefix += ~~(Math.random() * 1000000)
- while (document.getElementById(prefix))
- return prefix
- }
-
- Tooltip.prototype.tip = function () {
- return (this.$tip = this.$tip || $(this.options.template))
- }
-
- Tooltip.prototype.arrow = function () {
- return (this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow'))
- }
-
- Tooltip.prototype.enable = function () {
- this.enabled = true
- }
-
- Tooltip.prototype.disable = function () {
- this.enabled = false
- }
-
- Tooltip.prototype.toggleEnabled = function () {
- this.enabled = !this.enabled
- }
-
- Tooltip.prototype.toggle = function (e) {
- var self = this
- if (e) {
- self = $(e.currentTarget).data('bs.' + this.type)
- if (!self) {
- self = new this.constructor(e.currentTarget, this.getDelegateOptions())
- $(e.currentTarget).data('bs.' + this.type, self)
- }
- }
-
- self.tip().hasClass('in') ? self.leave(self) : self.enter(self)
- }
-
- Tooltip.prototype.destroy = function () {
- var that = this
- clearTimeout(this.timeout)
- this.hide(function () {
- that.$element.off('.' + that.type).removeData('bs.' + that.type)
- })
- }
-
-
- // TOOLTIP PLUGIN DEFINITION
- // =========================
-
- function Plugin(option) {
- return this.each(function () {
- var $this = $(this)
- var data = $this.data('bs.tooltip')
- var options = typeof option == 'object' && option
-
- if (!data && /destroy|hide/.test(option)) return
- if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
- if (typeof option == 'string') data[option]()
- })
- }
-
- var old = $.fn.tooltip
-
- $.fn.tooltip = Plugin
- $.fn.tooltip.Constructor = Tooltip
-
-
- // TOOLTIP NO CONFLICT
- // ===================
-
- $.fn.tooltip.noConflict = function () {
- $.fn.tooltip = old
- return this
- }
-
-}(jQuery);
-
-/* ========================================================================
- * Bootstrap: popover.js v3.3.4
- * http://getbootstrap.com/javascript/#popovers
- * ========================================================================
- * Copyright 2011-2015 Twitter, Inc.
- * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
- * ======================================================================== */
-
-
-+function ($) {
- 'use strict';
-
- // POPOVER PUBLIC CLASS DEFINITION
- // ===============================
-
- var Popover = function (element, options) {
- this.init('popover', element, options)
- }
-
- if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js')
-
- Popover.VERSION = '3.3.4'
-
- Popover.DEFAULTS = $.extend({}, $.fn.tooltip.Constructor.DEFAULTS, {
- placement: 'right',
- trigger: 'click',
- content: '',
- template: '<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'
- })
-
-
- // NOTE: POPOVER EXTENDS tooltip.js
- // ================================
-
- Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype)
-
- Popover.prototype.constructor = Popover
-
- Popover.prototype.getDefaults = function () {
- return Popover.DEFAULTS
- }
-
- Popover.prototype.setContent = function () {
- var $tip = this.tip()
- var title = this.getTitle()
- var content = this.getContent()
-
- $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title)
- $tip.find('.popover-content').children().detach().end()[ // we use append for html objects to maintain js events
- this.options.html ? (typeof content == 'string' ? 'html' : 'append') : 'text'
- ](content)
-
- $tip.removeClass('fade top bottom left right in')
-
- // IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do
- // this manually by checking the contents.
- if (!$tip.find('.popover-title').html()) $tip.find('.popover-title').hide()
- }
-
- Popover.prototype.hasContent = function () {
- return this.getTitle() || this.getContent()
- }
-
- Popover.prototype.getContent = function () {
- var $e = this.$element
- var o = this.options
-
- return $e.attr('data-content')
- || (typeof o.content == 'function' ?
- o.content.call($e[0]) :
- o.content)
- }
-
- Popover.prototype.arrow = function () {
- return (this.$arrow = this.$arrow || this.tip().find('.arrow'))
- }
-
-
- // POPOVER PLUGIN DEFINITION
- // =========================
-
- function Plugin(option) {
- return this.each(function () {
- var $this = $(this)
- var data = $this.data('bs.popover')
- var options = typeof option == 'object' && option
-
- if (!data && /destroy|hide/.test(option)) return
- if (!data) $this.data('bs.popover', (data = new Popover(this, options)))
- if (typeof option == 'string') data[option]()
- })
- }
-
- var old = $.fn.popover
-
- $.fn.popover = Plugin
- $.fn.popover.Constructor = Popover
-
-
- // POPOVER NO CONFLICT
- // ===================
-
- $.fn.popover.noConflict = function () {
- $.fn.popover = old
- return this
- }
-
-}(jQuery);
-
-/* ========================================================================
- * Bootstrap: scrollspy.js v3.3.4
- * http://getbootstrap.com/javascript/#scrollspy
- * ========================================================================
- * Copyright 2011-2015 Twitter, Inc.
- * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
- * ======================================================================== */
-
-
-+function ($) {
- 'use strict';
-
- // SCROLLSPY CLASS DEFINITION
- // ==========================
-
- function ScrollSpy(element, options) {
- this.$body = $(document.body)
- this.$scrollElement = $(element).is(document.body) ? $(window) : $(element)
- this.options = $.extend({}, ScrollSpy.DEFAULTS, options)
- this.selector = (this.options.target || '') + ' .nav li > a'
- this.offsets = []
- this.targets = []
- this.activeTarget = null
- this.scrollHeight = 0
-
- this.$scrollElement.on('scroll.bs.scrollspy', $.proxy(this.process, this))
- this.refresh()
- this.process()
- }
-
- ScrollSpy.VERSION = '3.3.4'
-
- ScrollSpy.DEFAULTS = {
- offset: 10
- }
-
- ScrollSpy.prototype.getScrollHeight = function () {
- return this.$scrollElement[0].scrollHeight || Math.max(this.$body[0].scrollHeight, document.documentElement.scrollHeight)
- }
-
- ScrollSpy.prototype.refresh = function () {
- var that = this
- var offsetMethod = 'offset'
- var offsetBase = 0
-
- this.offsets = []
- this.targets = []
- this.scrollHeight = this.getScrollHeight()
-
- if (!$.isWindow(this.$scrollElement[0])) {
- offsetMethod = 'position'
- offsetBase = this.$scrollElement.scrollTop()
- }
-
- this.$body
- .find(this.selector)
- .map(function () {
- var $el = $(this)
- var href = $el.data('target') || $el.attr('href')
- var $href = /^#./.test(href) && $(href)
-
- return ($href
- && $href.length
- && $href.is(':visible')
- && [[$href[offsetMethod]().top + offsetBase, href]]) || null
- })
- .sort(function (a, b) { return a[0] - b[0] })
- .each(function () {
- that.offsets.push(this[0])
- that.targets.push(this[1])
- })
- }
-
- ScrollSpy.prototype.process = function () {
- var scrollTop = this.$scrollElement.scrollTop() + this.options.offset
- var scrollHeight = this.getScrollHeight()
- var maxScroll = this.options.offset + scrollHeight - this.$scrollElement.height()
- var offsets = this.offsets
- var targets = this.targets
- var activeTarget = this.activeTarget
- var i
-
- if (this.scrollHeight != scrollHeight) {
- this.refresh()
- }
-
- if (scrollTop >= maxScroll) {
- return activeTarget != (i = targets[targets.length - 1]) && this.activate(i)
- }
-
- if (activeTarget && scrollTop < offsets[0]) {
- this.activeTarget = null
- return this.clear()
- }
-
- for (i = offsets.length; i--;) {
- activeTarget != targets[i]
- && scrollTop >= offsets[i]
- && (offsets[i + 1] === undefined || scrollTop < offsets[i + 1])
- && this.activate(targets[i])
- }
- }
-
- ScrollSpy.prototype.activate = function (target) {
- this.activeTarget = target
-
- this.clear()
-
- var selector = this.selector +
- '[data-target="' + target + '"],' +
- this.selector + '[href="' + target + '"]'
-
- var active = $(selector)
- .parents('li')
- .addClass('active')
-
- if (active.parent('.dropdown-menu').length) {
- active = active
- .closest('li.dropdown')
- .addClass('active')
- }
-
- active.trigger('activate.bs.scrollspy')
- }
-
- ScrollSpy.prototype.clear = function () {
- $(this.selector)
- .parentsUntil(this.options.target, '.active')
- .removeClass('active')
- }
-
-
- // SCROLLSPY PLUGIN DEFINITION
- // ===========================
-
- function Plugin(option) {
- return this.each(function () {
- var $this = $(this)
- var data = $this.data('bs.scrollspy')
- var options = typeof option == 'object' && option
-
- if (!data) $this.data('bs.scrollspy', (data = new ScrollSpy(this, options)))
- if (typeof option == 'string') data[option]()
- })
- }
-
- var old = $.fn.scrollspy
-
- $.fn.scrollspy = Plugin
- $.fn.scrollspy.Constructor = ScrollSpy
-
-
- // SCROLLSPY NO CONFLICT
- // =====================
-
- $.fn.scrollspy.noConflict = function () {
- $.fn.scrollspy = old
- return this
- }
-
-
- // SCROLLSPY DATA-API
- // ==================
-
- $(window).on('load.bs.scrollspy.data-api', function () {
- $('[data-spy="scroll"]').each(function () {
- var $spy = $(this)
- Plugin.call($spy, $spy.data())
- })
- })
-
-}(jQuery);
-
-/* ========================================================================
- * Bootstrap: tab.js v3.3.4
- * http://getbootstrap.com/javascript/#tabs
- * ========================================================================
- * Copyright 2011-2015 Twitter, Inc.
- * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
- * ======================================================================== */
-
-
-+function ($) {
- 'use strict';
-
- // TAB CLASS DEFINITION
- // ====================
-
- var Tab = function (element) {
- this.element = $(element)
- }
-
- Tab.VERSION = '3.3.4'
-
- Tab.TRANSITION_DURATION = 150
-
- Tab.prototype.show = function () {
- var $this = this.element
- var $ul = $this.closest('ul:not(.dropdown-menu)')
- var selector = $this.data('target')
-
- if (!selector) {
- selector = $this.attr('href')
- selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
- }
-
- if ($this.parent('li').hasClass('active')) return
-
- var $previous = $ul.find('.active:last a')
- var hideEvent = $.Event('hide.bs.tab', {
- relatedTarget: $this[0]
- })
- var showEvent = $.Event('show.bs.tab', {
- relatedTarget: $previous[0]
- })
-
- $previous.trigger(hideEvent)
- $this.trigger(showEvent)
-
- if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) return
-
- var $target = $(selector)
-
- this.activate($this.closest('li'), $ul)
- this.activate($target, $target.parent(), function () {
- $previous.trigger({
- type: 'hidden.bs.tab',
- relatedTarget: $this[0]
- })
- $this.trigger({
- type: 'shown.bs.tab',
- relatedTarget: $previous[0]
- })
- })
- }
-
- Tab.prototype.activate = function (element, container, callback) {
- var $active = container.find('> .active')
- var transition = callback
- && $.support.transition
- && (($active.length && $active.hasClass('fade')) || !!container.find('> .fade').length)
-
- function next() {
- $active
- .removeClass('active')
- .find('> .dropdown-menu > .active')
- .removeClass('active')
- .end()
- .find('[data-toggle="tab"]')
- .attr('aria-expanded', false)
-
- element
- .addClass('active')
- .find('[data-toggle="tab"]')
- .attr('aria-expanded', true)
-
- if (transition) {
- element[0].offsetWidth // reflow for transition
- element.addClass('in')
- } else {
- element.removeClass('fade')
- }
-
- if (element.parent('.dropdown-menu').length) {
- element
- .closest('li.dropdown')
- .addClass('active')
- .end()
- .find('[data-toggle="tab"]')
- .attr('aria-expanded', true)
- }
-
- callback && callback()
- }
-
- $active.length && transition ?
- $active
- .one('bsTransitionEnd', next)
- .emulateTransitionEnd(Tab.TRANSITION_DURATION) :
- next()
-
- $active.removeClass('in')
- }
-
-
- // TAB PLUGIN DEFINITION
- // =====================
-
- function Plugin(option) {
- return this.each(function () {
- var $this = $(this)
- var data = $this.data('bs.tab')
-
- if (!data) $this.data('bs.tab', (data = new Tab(this)))
- if (typeof option == 'string') data[option]()
- })
- }
-
- var old = $.fn.tab
-
- $.fn.tab = Plugin
- $.fn.tab.Constructor = Tab
-
-
- // TAB NO CONFLICT
- // ===============
-
- $.fn.tab.noConflict = function () {
- $.fn.tab = old
- return this
- }
-
-
- // TAB DATA-API
- // ============
-
- var clickHandler = function (e) {
- e.preventDefault()
- Plugin.call($(this), 'show')
- }
-
- $(document)
- .on('click.bs.tab.data-api', '[data-toggle="tab"]', clickHandler)
- .on('click.bs.tab.data-api', '[data-toggle="pill"]', clickHandler)
-
-}(jQuery);
-
-/* ========================================================================
- * Bootstrap: affix.js v3.3.4
- * http://getbootstrap.com/javascript/#affix
- * ========================================================================
- * Copyright 2011-2015 Twitter, Inc.
- * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
- * ======================================================================== */
-
-
-+function ($) {
- 'use strict';
-
- // AFFIX CLASS DEFINITION
- // ======================
-
- var Affix = function (element, options) {
- this.options = $.extend({}, Affix.DEFAULTS, options)
-
- this.$target = $(this.options.target)
- .on('scroll.bs.affix.data-api', $.proxy(this.checkPosition, this))
- .on('click.bs.affix.data-api', $.proxy(this.checkPositionWithEventLoop, this))
-
- this.$element = $(element)
- this.affixed = null
- this.unpin = null
- this.pinnedOffset = null
-
- this.checkPosition()
- }
-
- Affix.VERSION = '3.3.4'
-
- Affix.RESET = 'affix affix-top affix-bottom'
-
- Affix.DEFAULTS = {
- offset: 0,
- target: window
- }
-
- Affix.prototype.getState = function (scrollHeight, height, offsetTop, offsetBottom) {
- var scrollTop = this.$target.scrollTop()
- var position = this.$element.offset()
- var targetHeight = this.$target.height()
-
- if (offsetTop != null && this.affixed == 'top') return scrollTop < offsetTop ? 'top' : false
-
- if (this.affixed == 'bottom') {
- if (offsetTop != null) return (scrollTop + this.unpin <= position.top) ? false : 'bottom'
- return (scrollTop + targetHeight <= scrollHeight - offsetBottom) ? false : 'bottom'
- }
-
- var initializing = this.affixed == null
- var colliderTop = initializing ? scrollTop : position.top
- var colliderHeight = initializing ? targetHeight : height
-
- if (offsetTop != null && scrollTop <= offsetTop) return 'top'
- if (offsetBottom != null && (colliderTop + colliderHeight >= scrollHeight - offsetBottom)) return 'bottom'
-
- return false
- }
-
- Affix.prototype.getPinnedOffset = function () {
- if (this.pinnedOffset) return this.pinnedOffset
- this.$element.removeClass(Affix.RESET).addClass('affix')
- var scrollTop = this.$target.scrollTop()
- var position = this.$element.offset()
- return (this.pinnedOffset = position.top - scrollTop)
- }
-
- Affix.prototype.checkPositionWithEventLoop = function () {
- setTimeout($.proxy(this.checkPosition, this), 1)
- }
-
- Affix.prototype.checkPosition = function () {
- if (!this.$element.is(':visible')) return
-
- var height = this.$element.height()
- var offset = this.options.offset
- var offsetTop = offset.top
- var offsetBottom = offset.bottom
- var scrollHeight = $(document.body).height()
-
- if (typeof offset != 'object') offsetBottom = offsetTop = offset
- if (typeof offsetTop == 'function') offsetTop = offset.top(this.$element)
- if (typeof offsetBottom == 'function') offsetBottom = offset.bottom(this.$element)
-
- var affix = this.getState(scrollHeight, height, offsetTop, offsetBottom)
-
- if (this.affixed != affix) {
- if (this.unpin != null) this.$element.css('top', '')
-
- var affixType = 'affix' + (affix ? '-' + affix : '')
- var e = $.Event(affixType + '.bs.affix')
-
- this.$element.trigger(e)
-
- if (e.isDefaultPrevented()) return
-
- this.affixed = affix
- this.unpin = affix == 'bottom' ? this.getPinnedOffset() : null
-
- this.$element
- .removeClass(Affix.RESET)
- .addClass(affixType)
- .trigger(affixType.replace('affix', 'affixed') + '.bs.affix')
- }
-
- if (affix == 'bottom') {
- this.$element.offset({
- top: scrollHeight - height - offsetBottom
- })
- }
- }
-
-
- // AFFIX PLUGIN DEFINITION
- // =======================
-
- function Plugin(option) {
- return this.each(function () {
- var $this = $(this)
- var data = $this.data('bs.affix')
- var options = typeof option == 'object' && option
-
- if (!data) $this.data('bs.affix', (data = new Affix(this, options)))
- if (typeof option == 'string') data[option]()
- })
- }
-
- var old = $.fn.affix
-
- $.fn.affix = Plugin
- $.fn.affix.Constructor = Affix
-
-
- // AFFIX NO CONFLICT
- // =================
-
- $.fn.affix.noConflict = function () {
- $.fn.affix = old
- return this
- }
-
-
- // AFFIX DATA-API
- // ==============
-
- $(window).on('load', function () {
- $('[data-spy="affix"]').each(function () {
- var $spy = $(this)
- var data = $spy.data()
-
- data.offset = data.offset || {}
-
- if (data.offsetBottom != null) data.offset.bottom = data.offsetBottom
- if (data.offsetTop != null) data.offset.top = data.offsetTop
-
- Plugin.call($spy, data)
- })
- })
-
-}(jQuery);
diff --git a/doc/_extensions/odoo_ext/static/components.less b/doc/_extensions/odoo_ext/static/components.less
deleted file mode 100644
index 7dfd79a29b8..00000000000
--- a/doc/_extensions/odoo_ext/static/components.less
+++ /dev/null
@@ -1,515 +0,0 @@
-// ================================================
-// ================ Components ====================
-// ================================================
-
-// Ripple buttons
-// ----------------------------------------
-@-webkit-keyframes ripple {
- to {
- opacity: 0;
- -webkit-transform: scale(2.5);
- }
-}
-
-@keyframes ripple {
- to {
- opacity: 0;
- .scale(2.5);
- }
-}
-
-.ripple {
- z-index: 2;
-
- .inner-ripple {
- display: block;
- position: absolute;
- border-radius: 100%;
- opacity: 1;
- z-index: -1;
- background: rgba(0, 0, 0, .05);
- pointer-events: none;
- .scale(0);
-
- &.inner-ripple-animated {
- .animation(ripple 0.35s ease-in);
- }
- }
-}
-
-
-// Code Fields
-// ----------------------------------------
-article.doc-body .code-fields {
- display: table;
- width: 100%;
- padding: 5px;
- font-size: 0.8em;
- border: 2px solid @gray-lighter;
-
- .code-field {
- display: table-row;
- }
-
- .code-field-body {
- display: block;
- padding-left: 15px;
- @media screen and (min-width: @screen-md-min) {
- display: table-cell;
- padding-left: 0;
- }
- }
-
- .code-field-name {
- width: auto;
- display: block;
- font-weight: @fw_semibold;
- color: @headings-color;
-
- &:after {
- content: ":";
- }
-
- @media screen and (min-width: @screen-md-min) {
- text-align: right;
- width: 20%;
- padding-right: 10px;
- display: table-cell;
- }
- }
-
- ul {
- list-style: none;
- margin: 0.2em 0;
-
- > li {
- margin: 0 0 8px;
- padding-left: 0px;
- line-height: 1.5;
-
- &:before {
- display: none;
- }
- }
-
- strong {
- color: @headings-color;
- font-family: @font-family-monospace;
- }
-
- em {
- color: @headings-color;
- font-family: @font-family-monospace;
- font-weight: @fw_semibold;
- }
- }
-}
-
-
-// Cards
-// ----------------------------------------
-.card-img {
- .o-gradient();
- .o-position-absolute(0, 0);
- .translate3d(0;0;0);
- .square(100%);
- display: block;
- background-size: cover;
- background-position: 50%;
-}
-
-.card.top {
- position: relative;
- overflow: hidden;
- margin: 0;
- padding: 0 0 2%;
- .transform-origin(50% 0px 0px);
-
- @media screen and (min-width: @screen-sm-min) {
- padding: 12% 0 5%;
- }
-
- @media screen and (min-width: @screen-md-min) {
- padding: 10% 0 5%;
- }
-
- @media screen and (min-width: @screen-lg-min) {
- padding: 8% 0 4%;
- }
-
- &.stacked {
- background: transparent;
- .transition(background 1s);
- }
-
- &:before {
- content: "";
- display: block;
- background-image: url("img/banner_bg.png");
- background-size: cover;
- background-position: 50%;
- .o-position-absolute(0, 0);
- .square(100%);
- }
-
- .card-img {
- background-image: url("img/banner_bg.png");
- }
-
- .container {
- position: relative;
- font-size: 32px;
- @media screen and (min-width: @screen-sm-min) {
- &:not(.o_long_title) {
- font-size: 40px;
- }
-
- &.o_short_title {
- font-size: 50px;
- }
- }
-
- h1 {
- font-weight: @fw_light;
- font-size: 1em;
- color: white;
- line-height: 0.9;
- }
- }
-}
-
-.card.top.has_banner {
- background: @footer-bg-color;
-
- &:before {
- display: none;
- }
-
- .card-img {
- opacity: 0.35;
- }
-}
-
-// Alerts
-// ----------------------------------------
-main .alert {
- padding: 8px 15px;
- border-radius: 0;
- margin: 5px auto 15px;
- border-width: 0 0 0 3px;
- // 'INFO' is the default style
- border-color: @brand-info;
- background-color: lighten(@brand-info, 45%);
-
- &, p {
- line-height: 1.3;
- font-size: 14px;
- }
-
- p {
- margin-bottom: 5px;
-
- &:last-child {
- margin-bottom: 0;
- }
- }
-
- > ul {
- margin: 0.5em 0;
-
- > li {
- margin: 0;
- }
- }
-
- h3.alert-title {
- font-size: 1em;
- line-height: 1em;
- margin: 0 0 5px;
- font-weight: bold;
- font-family: @font-family-base;
- color: darken(@brand-info, 5%);
-
- &:before {
- .mdi-icon( "\e639");
- .translate(0, 0.1em);
- margin-right: 0.2em;
- }
- }
-
- &.alert-info {
- > h3.alert-title {
- display: none;
- }
- }
-
- &.alert-go_to {
- border-color: @o-violet-dark;
- background-color: lighten(@o-violet-dark, 52%);
- color: darken(@o-violet-dark, 5%);
-
- > h3.alert-title {
- color: darken(@o-violet-dark, 15%);
-
- &:before {
- content: "\e70d";
- }
- }
- }
-
- &.alert-success {
- border-color: lighten(@brand-success, 30%);
- background-color: lighten(@brand-success, 45%);
-
- > h3.alert-title {
- color: darken(@brand-success, 10%);
- &:before {
- content: "\e625";
- }
- }
- }
-
- &.alert-warning, &.warning {
- border-color: lighten(@brand-warning, 30%);
- background-color: lighten(@brand-warning, 35%);
-
- > h3.alert-title {
- color: @brand-warning;
- &:before {
- content: "\e6a4";
- }
- }
- }
-
- &.alert-danger {
- border-color: lighten(@brand-danger, 30%);
- background-color: lighten(@brand-danger, 40%);
-
- > h3.alert-title {
- color: darken(@brand-danger, 10%);
- &:before {
- content: "\e6a4";
- }
- }
- }
-
- &.alert-exercise {
- border-color: lighten(@doc_exercise, 30%);
- background-color: lighten(@doc_exercise, 40%);
- color: darken(@doc_exercise, 35%);
-
- > h3.alert-title {
- color: @doc_exercise;
- }
-
- > h3.alert-title:before {
- .translate(0;0);
- top: 28px;
- content: "\e709";
- }
- }
-
- &.doc-content {
- @media (min-width: @screen-lg-min) {
- max-width: 55%;
- }
- }
-}
-
-
-// Elements
-// ----------------------------------------
-hr.divider {
- border-color: fadeout(@gray-lightest, 60%);
- position: absolute;
- width: 900%;
- margin-left: -13px;
-}
-
-img.img-responsive {
- box-shadow: 0 3px 15px @gray-lighter;
- border: 1px solid @gray-lighter;
- margin-bottom: 25px;
-
- &:not(:first-child) {
- margin-top: 25px;
- }
-}
-
-.figure {
- h4 {
- margin: 0.5em 0 1.5em;
- padding-left: 1em;
- font-size: 1em;
- font-style: italic;
- }
-}
-
-.pq-patch {
- em {
- display: block;
- border-radius: 4px 4px 0 0;
- background: @gray-lighter;
- padding-left: 10px;
- font-size: 0.9em;
- font-weight: @fw_semibold;
-
- + .pq-section .highlight {
- border-radius: 0 0 4px 4px;
- }
- }
-}
-
-span.menuselection {
- font-weight: @fw_medium;
-}
-
-.list-group-item {
- border: none;
- background: transparent;
-}
-
-blockquote {
- font-family: @font-family-serif;
- font-weight: @fw_semibold;
- font-style: italic;
-
- footer {
- font-family: @font-family-base;
- background: transparent;
- text-align: left;
- color: @text-color;
- font-weight: normal;
- font-style: normal;
-
- cite {
- font-style: italic;
- }
- }
- @media (min-width:@screen-md-min) {
- border-left: 3px solid fade(@brand-primary, 50%);
- }
-}
-
-.code, code {
- font-size: 0.8em;
- font-weight: @fw_semibold;
- color: darken(@brand-primary, 30%);
- background-color: lighten(@brand-primary, 50%);
-}
-
-.btn {
- border-radius: 0;
-}
-
-.table, table {
- font-size: 0.9em;
-}
-
-.code-attribute, .code-class, .code-classmethod, .code-data, .code-function, .code-method, .code-staticmethod {
- // indents *all* content
- padding-left: 20px;
- margin-bottom: 2em;
- // except for item title which gets dedented back
- > h6 {
- margin-left: -20px;
- margin-bottom: 0.3em;
-
- .viewcode-link {
- display: none;
- float: right;
- }
-
- &:hover .viewcode-link {
- display: inline;
- }
- }
-
- p {
- margin-bottom: 0.5em;
- }
-}
-
-article.doc-body {
- &.index-category {
- min-height: 300px;
- min-height: 30vh;
-
- li.toctree-l1 {
- padding: 5px 0;
- }
- }
-}
-
-
-article.doc-body .content-switcher {
- margin-top: 0;
-
- > ul {
- font-size: 10px;
- padding: 0;
- margin: 0;
- .transition(all .2s ease);
-
- > li {
- font-weight: @fw_semibold;
- color: @gray-light;
- border-bottom: 1px solid transparent;
- margin: 0 20px 0 0;
- padding-left: 0;
- font-size: 1.3em;
- cursor: pointer;
- display: inline-block;
- list-style: none;
- .transition(all .2s);
- opacity: 0.6;
-
- &:before {
- content: none;
- }
-
- &.active {
- border-bottom: 1px solid @brand-primary;
- opacity: 1;
- }
- }
- }
-
- &:hover > ul > li {
- .opacity(1);
- }
-
- > .tabs > * {
- display: none;
- max-width: 100%;
- overflow-x: auto;
- }
-
- > .tabs > .active {
- display: block;
- }
-}
-
-.highlight {
- background: @doc_code-bg;
- color: @gray-light;
- border-radius: @border-radius-base;
- margin-bottom: (@line-height-computed / 2);
-
- pre {
- margin-bottom: 0;
- }
-}
-
-pre {
- font-size: 0.8em;
- color: @gray-light;
- background: @doc_code-bg;
- font-family: @font-family-monospace;
- font-weight: @fw_semibold;
- position: relative;
- border: none;
- max-width: 100%;
- overflow: auto;
- margin: 0 0 (@line-height-computed / 2);
-} \ No newline at end of file
diff --git a/doc/_extensions/odoo_ext/static/doc.js b/doc/_extensions/odoo_ext/static/doc.js
deleted file mode 100644
index af0a1fe0f37..00000000000
--- a/doc/_extensions/odoo_ext/static/doc.js
+++ /dev/null
@@ -1,405 +0,0 @@
-(function ($) {
-
- $(function () {
-
- // -- Initialize fallbacks for requestAnimationFrame
- window.requestAnimationFrame = window.requestAnimationFrame
- || window.webkitRequestAnimationFrame
- || window.mozRequestAnimationFrame
- || window.msRequestAnimationFrame
- || window.oRequestAnimationFrame
- || function (callback) { setTimeout(callback, 10); };
-
-
- // ======= Define variables =======
- // =================================
- // -- Screen resolutions
- var screen_md = 992;
-
- // -- Window, window's properties
- var $win = $(window),
- win_w = $win.width();
-
- // -- Main elements
- var $body = $('body'),
- $header = $body.find('> header'),
- $sub_nav = $header.find(".o_sub_nav"),
- $wrap = $body.find('> #wrap'),
- $main = $wrap.find('main'),
- $footer = $body.find('> footer');
-
- // -- Detect page type
- var page_type = (function () {
- if ($wrap.hasClass('index')) {
- return 'index';
- } else if ($main.find('article').hasClass('doc-tocindex-category')){
- return 'category-index';
- } else {
- return 'article';
- }
- })();
-
- // -- CP > "Card Top"
- var $cp = $wrap.find('> .card.top'),
- $cp_image = $cp.find('> .card-img'),
- $cp_text = $cp.find('> .container'),
-
- cp_h = $cp.outerHeight(),
- has_cp_image = $cp_image.length > 0,
- cp_image_alpha = has_cp_image ? $cp_image.css('opacity') : undefined,
- cp_end_point = has_cp_image ? cp_h/2 : undefined;
-
- // -- Floating action
- var $mask = $body.find('#mask'),
- $float = $body.find("#floating_action"),
- $float_menu = $body.find("#floating_action_menu");
-
- // -- Elements' heights
- var body_h = $body.height(),
- header_h = $header.outerHeight(),
- main_h = $main.height(),
- sub_nav_h = $sub_nav.height();
-
- // -- Aside
- var $aside = $main.find('aside'),
- has_aside = $aside.length > 0,
- $aside_nav = has_aside ? $aside.find('> .navbar-aside') : undefined,
- aside_links = has_aside ? $aside_nav.find("li > a") : undefined;
-
-
-
- // ======= Affix =================
- // ===============================
- function set_affix() {
- var aside_offset_top = $aside.offset().top - sub_nav_h,
- aside_offset_bot = parseInt($wrap.css('padding-bottom')),
- aside_width = $aside.width();
-
- $aside.css('height', main_h);
- $aside_nav.css('width', aside_width).affix({
- offset: {
- top : aside_offset_top,
- bottom : aside_offset_bot,
- }
- });
- }
-
- // ======= Footer animations =====
- // ===============================
- var footer_animation = function () {
- var footer_effect = $main.outerHeight() >= $win.outerHeight();
-
- if (!footer_effect) {
- footer_stop();
- return;
- }
-
- $footer.toggleClass('o_footer_effect', footer_effect);
- $body.css('padding-bottom', $footer.outerHeight());
-
- var checkIfSearch = function (e) {
- if ((e.ctrlKey || e.metaKey) && String.fromCharCode(e.which).toLowerCase() === 'f') {
- footer_stop();
- }
- };
- $win.on('keydown.footer', function (e) {
- checkIfSearch(e);
- });
- };
-
- var footer_stop = function () {
- $footer.removeClass('o_footer_effect');
- $body.css('padding-bottom', 0);
- $win.off('keydown.footer');
- };
-
-
- // ======= Docs Functions ==========
- // =================================
- // -- Layouting
- var init = function () {
- var $floating_container = $body.find("> .floating_action_container");
-
- // Adapt Title font size according to its length
- $cp_text
- .toggleClass('o_short_title', $cp_text.text().trim().length < 15)
- .toggleClass('o_long_title', $cp_text.text().trim().length > 45);
-
- if (page_type == 'index') {
- var half_cols_selector = '.tutorials,.api';
-
- $main.find("#index .index-tree").find(half_cols_selector)
- .wrap('<div class="o_half_col col-sm-6"/>')
- .find('.col-md-3').removeClass('col-md-3 col-sm-6').addClass('col-sm-12 col-md-6');
-
- var half_cols_els = $main.find(".o_half_col");
- for(var i = 0; i < half_cols_els.length; i+=2) {
- half_cols_els.slice(i, i+2).wrapAll("<div class='row'></div>");
- }
- }
-
- if (page_type == 'index' || page_type == 'category-index') {
- $floating_container.add($mask).remove();
- $main.toggleClass('o_slim_page', page_type == 'category-index');
- }
-
- if (page_type == 'article') {
- attach_permalink_markers();
-
- // Hide empty-permalink first sections
- var $f_s = $main.find('article.doc-body > section:first-child');
- $f_s.toggleClass('hidden', $f_s[0].childElementCount == 1 && $f_s.children().is('i:empty'));
-
- if (has_aside) {
- if (aside_links.length < 2) {
- has_aside = false;
- $main.addClass("o_aside_removed");
- $floating_container.add($mask).add($aside).remove();
- return;
- }
-
- floating_menu_layout();
- set_scroll_to(aside_links);
- ripple_animation(aside_links);
- $aside_nav.find("li").has("ul").addClass("parent");
- }
- }
-
- bind_window_events();
- };
-
- // -- Float action menu
- var floating_menu_layout = function () {
- var lis = $aside_nav.find("> ul > li").clone(true)
- .addClass("ripple")
- .css({
- position: 'relative',
- overflow: 'hidden'
- });
- lis.find("ul").remove().end()
- .find("a").removeClass("ripple").on("click", function () {
- _toggle_float();
- });
- $float_menu.find(".content").empty().append(lis);
- $float.add($mask).on("click", function () {
- _toggle_float();
- return false;
- });
- };
-
- // -- Scroll To
- var set_scroll_to = function (el_list) {
- el_list.each(function () {
- var $link = $(this),
- target_id = $link.attr("href");
-
- $link.on("click", function () {
- $aside_nav.find("li").removeClass("active");
- $link.parents("li").addClass("active");
- _scroll_and_set_hash(target_id);
- return false;
- });
- });
-
- $body.scrollspy({
- target: 'aside',
- offset: 200,
- });
- };
-
- // -- Ripple buttons
- var ripple_animation = function (el_list) {
- el_list.each(function () {
- var btn = $(this);
- btn
- .css({
- position: 'relative',
- overflow: 'hidden'
- })
- .bind('mousedown', function (e) {
- var ripple;
- if (btn.find('.inner-ripple').length === 0) {
- ripple = $('<span class="inner-ripple"/>');
- btn.prepend(ripple);
- } else {
- ripple = btn.find('.inner-ripple');
- }
- ripple.removeClass('inner-ripple-animated');
-
- if (!ripple.height() && !ripple.width()) {
- var diameter = Math.max(btn.outerWidth(), btn.outerHeight());
- ripple.css({
- height: diameter,
- width: diameter
- });
- }
- var x = e.pageX - btn.offset().left - ripple.width() / 2;
- var y = e.pageY - btn.offset().top - ripple.height() / 2;
- ripple.css({
- top: y + 'px',
- left: x + 'px'
- }).addClass('inner-ripple-animated');
- setTimeout(function () {
- ripple.removeClass('inner-ripple-animated');
- }, 351);
- });
- });
- };
-
- // -- Header buttons
- var header_buttons = function () {
- var timer;
- $header.on('click', '.o_primary_nav .dropdown-toggle', function (e) {
- e.preventDefault();
-
- var $a = $(this);
- clearTimeout(timer);
-
- $a.parent().toggleClass('open');
- $a.closest('ul').toggleClass('o_sub_opened', $a.parent().hasClass('open'));
- if ($a.closest('.o_primary_nav').children('.open').length > 0) {
- $header.addClass("o_sub_opened");
- } else {
- timer = setTimeout(function () {
- $header.removeClass("o_sub_opened");
- }, 200);
- }
- });
- $header.on('click', '.o_primary_nav .o_secondary_nav', function (e) {
- if (e.target === e.currentTarget) {
- $header.find('.open').removeClass('open');
- $header.find('.o_sub_opened').andSelf().removeClass('o_sub_opened');
- }
- });
-
- // -- Mobile menu opening
- $header.on('click', '.o_mobile_menu_toggle', function (e) {
- e.preventDefault();
- $(this).find('i').toggleClass('fa-bars fa-times');
- $header.toggleClass('o_mobile_menu_opened');
- });
- };
-
- // -- Attach permalink markers to sections' title
- var attach_permalink_markers = function () {
- $main.find('article.doc-body > section').each( function () {
- var $section = $(this),
- $title = $section.find('> h2, > h3, > h4, > h5, > h6'),
- target_id = $section.attr('id'),
- $icon = $('<i/>').addClass('mdi-content-link');
-
- if ($title.length <= 0) {
- return;
- }
-
- $title.addClass('o_has_permalink_marker').append($icon);
-
- $icon.on('click', function () {
- _scroll_and_set_hash("#" + target_id);
-
- $title.addClass('o_marked').delay(1000).queue(function (){
- $title.removeClass('o_marked').dequeue();
- });
- return false;
- });
- });
- };
-
- var cp_animation = function (win_top, cp_end_point){
- var top = Math.min(win_top, cp_h);
-
- $cp_image.css({
- 'opacity' : cp_image_alpha - (top * (cp_image_alpha/cp_end_point)),
- 'transform' : 'scale(' + (1 + (top * (0.1/cp_end_point))) +')'
- });
-
- $cp_text.css({
- 'transform' : 'translateY(' + (top/4) + 'px)',
- 'opacity' : 1 - (top/cp_h)
- });
- };
-
- $(".content-switcher").each(function (index, switcher) {
- var $switcher = $(switcher),
- $links = $switcher.find('> ul > li'),
- $tabs = $switcher.find('> .tabs > *'),
- $all = $links.add($tabs);
-
- function select(index) {
- $all.removeClass('active');
- $links.eq(index).add($tabs.eq(index)).addClass('active');
- }
- select(0);
- $switcher.on('click', '> ul > li', function () {
- select($(this).index());
- return false;
- });
- });
-
-
- // ======= Utils ==================
- // =================================
- var _scroll_and_set_hash = function (target_id) {
- $('html, body').animate({
- scrollTop: $(target_id).offset().top - 60
- }, 100);
- window.location.hash = target_id;
- };
-
- var _toggle_float = function () {
- $float.toggleClass("active");
- setTimeout(function () {
- $float_menu.toggleClass("active");
- $mask.toggleClass("active");
- }, 300);
- };
-
-
- var bind_window_events = function () {
- // ======= On resize ==============
- // Update properties and conditionally call functions according to resolution
- $win.on('resize', function () {
- // Update size variables
- win_w = $win.width();
- body_h = $body.height();
- cp_h = $cp.outerHeight();
- main_h = $main.height();
- cp_end_point = has_cp_image ? cp_h/2 : undefined;
-
- if (win_w >= screen_md){
- footer_animation();
- (has_aside)? set_affix(): '';
- } else {
- footer_stop();
- }
- });
-
- // ======= On scroll ==============
- $win.on('scroll', function () {
- var win_top = $win.scrollTop();
-
- $win[0].requestAnimationFrame(function () {
- cp_animation(win_top, cp_end_point);
- });
-
- if (win_w >= screen_md) {
- $header.toggleClass('o_scrolled', win_top > header_h);
- }
- });
- };
-
-
- // ======= Onload ==================
- // =================================
- // -- Call default functions
- init();
- header_buttons();
- ripple_animation($(".ripple"));
-
- // -- Conditionally call specific functions according to resolution
- if (win_w >= screen_md){
- footer_animation();
- (has_aside)? set_affix(): '';
- }
- });
-})(jQuery);
diff --git a/doc/_extensions/odoo_ext/static/fonts/Material-Design-Icons.eot b/doc/_extensions/odoo_ext/static/fonts/Material-Design-Icons.eot
deleted file mode 100644
index d9c296e41f2..00000000000
--- a/doc/_extensions/odoo_ext/static/fonts/Material-Design-Icons.eot
+++ /dev/null
Binary files differ
diff --git a/doc/_extensions/odoo_ext/static/fonts/Material-Design-Icons.svg b/doc/_extensions/odoo_ext/static/fonts/Material-Design-Icons.svg
deleted file mode 100644
index def1e9b5e9b..00000000000
--- a/doc/_extensions/odoo_ext/static/fonts/Material-Design-Icons.svg
+++ /dev/null
@@ -1,769 +0,0 @@
-<?xml version="1.0" standalone="no"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
-<svg xmlns="http://www.w3.org/2000/svg">
-<metadata>Generated by IcoMoon</metadata>
-<defs>
-<font id="Material-Design-Icons" horiz-adv-x="1024">
-<font-face units-per-em="1024" ascent="960" descent="-64" />
-<missing-glyph horiz-adv-x="1024" />
-<glyph unicode="&#x20;" d="" horiz-adv-x="512" />
-<glyph unicode="&#xe600;" d="M320.853 22.187c-139.52 65.707-239.36 201.387-254.72 361.813h-64c21.76-262.827 241.493-469.333 509.867-469.333l28.16 1.28-162.56 162.56-56.747-56.32zM358.827 300.374c-8.107 0-15.787 1.28-22.187 3.413-6.827 2.56-12.373 5.547-17.067 10.24-4.693 4.267-8.533 9.387-11.093 15.787-2.56 5.973-3.84 12.8-3.84 20.053h-55.467c0-15.36 2.987-29.013 8.96-40.533s14.080-21.333 23.893-29.44c10.24-7.68 21.76-13.653 34.987-17.493 12.8-4.267 26.453-6.4 40.96-6.4 15.787 0 30.72 2.133 43.947 6.4 13.653 4.267 25.6 10.667 35.413 18.773s17.92 18.347 23.467 30.72c5.547 12.373 8.533 26.027 8.533 41.387 0 8.107-0.853 16.213-2.987 23.893s-5.12 14.933-9.813 21.76c-4.267 6.827-10.24 12.8-17.067 18.347-7.253 5.547-15.787 9.813-26.027 13.227 8.533 3.84 15.787 8.533 22.187 14.080s11.52 11.52 15.787 17.92c4.267 6.4 7.253 12.8 9.387 19.627s2.987 13.653 2.987 20.48c0 15.36-2.56 29.013-7.68 40.96s-12.373 21.76-21.76 29.44c-8.533 8.107-20.053 14.080-32.853 18.347-13.227 3.84-27.733 5.973-43.52 5.973-15.36 0-29.44-2.133-42.667-6.827-12.8-4.693-24.32-11.093-33.707-19.2-8.96-8.107-16.213-17.493-21.76-28.587-5.12-11.093-7.68-23.040-7.68-36.267h55.467c0 7.253 1.28 13.653 3.84 19.2s5.973 10.667 10.667 14.507c4.693 3.84 9.813 7.253 16.213 9.387s12.8 3.413 20.48 3.413c17.067 0 29.867-4.267 37.973-13.227 8.107-8.533 12.373-20.907 12.373-36.693 0-7.68-1.28-14.507-3.413-20.907s-5.973-11.52-10.667-15.787c-4.693-4.267-10.667-7.68-17.493-10.24s-15.36-3.84-24.747-3.84h-32.853v-43.947h32.853c9.387 0 17.92-0.853 25.6-2.987s14.080-5.547 19.2-9.813c5.12-4.693 9.387-10.24 12.373-17.067s4.267-14.933 4.267-24.32c0-17.493-5.12-30.72-14.933-39.68-9.813-9.813-23.467-14.080-40.533-14.080zM723.627 552.96c-13.653 14.080-29.867 25.173-48.64 32.853-18.347 7.68-39.253 11.52-62.293 11.52h-100.693v-341.333h98.133c23.467 0 45.227 3.84 64.427 11.52s35.84 18.347 49.493 32.427c13.653 14.080 24.32 31.147 31.573 50.773 7.253 20.053 11.093 42.24 11.093 66.987v17.067c0 24.747-3.84 46.933-11.093 66.987-7.68 20.053-18.347 37.12-32 51.2zM706.987 418.134c0-17.92-2.133-33.707-5.973-48.213-4.267-14.080-10.24-26.453-18.347-36.267s-18.347-17.493-30.293-22.613c-12.373-5.12-26.453-7.68-42.24-7.68h-38.827v246.187h41.387c30.72 0 54.187-9.813 69.973-29.44 16.213-19.627 24.32-47.787 24.32-84.907v-17.067zM512 938.667l-28.16-1.28 162.56-162.56 56.747 56.747c139.52-66.133 239.36-201.387 254.293-361.813h64c-21.333 262.4-241.067 468.907-509.44 468.907z" />
-<glyph unicode="&#xe601;" d="M512 853.334c46.933 0 85.333-38.4 85.333-85.333s-38.4-85.333-85.333-85.333-85.333 38.4-85.333 85.333 38.4 85.333 85.333 85.333zM896 554.667h-256v-554.667h-85.333v256h-85.333v-256h-85.333v554.667h-256v85.333h768v-85.333z" />
-<glyph unicode="&#xe602;" d="M896 170.667v-42.667c0-46.933-38.4-85.333-85.333-85.333h-597.333c-47.36 0-85.333 38.4-85.333 85.333v597.333c0 46.933 37.973 85.333 85.333 85.333h597.333c46.933 0 85.333-38.4 85.333-85.333v-42.667h-384c-47.36 0-85.333-38.4-85.333-85.333v-341.333c0-46.933 37.973-85.333 85.333-85.333h384zM512 256h426.667v341.333h-426.667v-341.333zM682.667 362.667c-35.413 0-64 28.587-64 64s28.587 64 64 64 64-28.587 64-64-28.587-64-64-64z" />
-<glyph unicode="&#xe603;" d="M170.667 512v-298.667h128v298.667h-128zM426.667 512v-298.667h128v298.667h-128zM85.333-0h810.667v128h-810.667v-128zM682.667 512v-298.667h128v298.667h-128zM490.667 896l-405.333-213.333v-85.333h810.667v85.333l-405.333 213.333z" />
-<glyph unicode="&#xe604;" d="M128 725.334v-597.333c0-46.933 37.973-85.333 85.333-85.333h597.333c46.933 0 85.333 38.4 85.333 85.333v597.333c0 46.933-38.4 85.333-85.333 85.333h-597.333c-47.36 0-85.333-38.4-85.333-85.333zM640 554.667c0-70.827-57.173-128-128-128s-128 57.173-128 128 57.173 128 128 128 128-57.173 128-128zM256 213.334c0 85.333 170.667 132.267 256 132.267s256-46.933 256-132.267v-42.667h-512v42.667z" />
-<glyph unicode="&#xe605;" d="M576 363.094c0-35.346-28.654-64-64-64s-64 28.654-64 64c0 35.346 28.654 64 64 64s64-28.654 64-64zM512 853.334c-235.52 0-426.667-191.147-426.667-426.667s191.147-426.667 426.667-426.667 426.667 191.147 426.667 426.667-191.147 426.667-426.667 426.667zM512 746.667c52.907 0 96-43.093 96-96s-43.093-96-96-96-96 43.093-96 96 43.093 96 96 96zM725.333 296.107v-106.667c-19.2-17.493-40.96-32.853-64-44.8v29.013c0 14.507-7.253 27.733-19.627 39.253-27.733 26.453-80.64 43.52-129.707 43.52-40.96 0-83.627-11.947-113.067-31.147l-7.253-5.12-8.96-7.253c33.28-20.053 69.547-30.72 108.373-34.987l56.747-6.4c15.787-1.707 28.16-15.36 28.16-32 0-12.373-6.827-22.613-17.067-28.16-11.947-6.4-27.307-3.84-40.533-3.84-14.933 0-29.44 0.427-43.947 2.133-21.333 2.56-42.24 7.253-62.293 14.080-20.907 6.827-41.387 16.213-60.587 27.307-9.387 5.547-18.773 11.52-27.733 18.347l-13.227 10.24c-1.707 0.853-11.947 7.68-11.947 9.813v182.613c0 67.413 112.213 118.613 213.333 118.613s213.333-51.2 213.333-118.613v-75.947z" />
-<glyph unicode="&#xe606;" d="M512 853.334c-235.52 0-426.667-191.147-426.667-426.667s191.147-426.667 426.667-426.667 426.667 191.147 426.667 426.667-191.147 426.667-426.667 426.667zM512 725.334c70.827 0 128-57.173 128-128s-57.173-128-128-128-128 57.173-128 128 57.173 128 128 128zM512 119.467c-106.667 0-200.96 54.613-256 137.387 1.28 84.907 170.667 131.413 256 131.413 84.907 0 254.72-46.507 256-131.413-55.040-82.773-149.333-137.387-256-137.387z" />
-<glyph unicode="&#xe607;" d="M469.333 554.667h85.333v128h128v85.333h-128v128h-85.333v-128h-128v-85.333h128v-128zM298.667 170.667c-46.933 0-84.907-38.4-84.907-85.333s37.973-85.333 84.907-85.333 85.333 38.4 85.333 85.333-38.4 85.333-85.333 85.333zM725.333 170.667c-46.933 0-84.907-38.4-84.907-85.333s37.973-85.333 84.907-85.333 85.333 38.4 85.333 85.333-38.4 85.333-85.333 85.333zM305.92 309.334l1.28 5.12 38.4 69.547h317.867c32 0 60.16 17.493 74.667 43.947l164.693 299.093-74.24 40.96h-0.427l-46.933-85.333-117.76-213.333h-299.52l-5.547 11.52-95.573 201.813-40.533 85.333-40.107 85.333h-139.52v-85.333h85.333l153.6-323.84-57.6-104.533c-6.827-11.947-10.667-26.027-10.667-40.96 0-46.933 38.4-85.333 85.333-85.333h512v85.333h-494.080c-5.547 0-10.667 4.693-10.667 10.667z" />
-<glyph unicode="&#xe608;" d="M336.213 794.027l-54.613 65.28-196.267-164.267 55.040-65.28 195.84 164.267zM938.667 694.614l-196.267 164.693-55.040-65.28 196.267-164.693 55.040 65.28zM512 768c-212.053 0-384-171.947-384-384s171.52-384 384-384c212.053 0 384 171.947 384 384s-171.947 384-384 384zM512 85.334c-165.12 0-298.667 133.547-298.667 298.667s133.547 298.667 298.667 298.667 298.667-133.547 298.667-298.667-133.547-298.667-298.667-298.667zM554.667 554.667h-85.333v-128h-128v-85.333h128v-128h85.333v128h128v85.333h-128v128z" />
-<glyph unicode="&#xe609;" d="M512 682.667c165.12 0 298.667-133.547 298.667-298.667 0-35.84-6.827-70.4-18.347-102.4l64.853-64.853c24.747 50.773 38.827 107.093 38.827 167.253 0 212.053-171.947 384-384 384-60.16 0-116.48-14.080-167.253-38.827l64.853-64.853c32 11.52 66.56 18.347 102.4 18.347zM938.667 694.614l-196.267 164.693-55.040-65.28 196.267-164.693 55.040 65.28zM124.587 840.96l-54.187-54.613 56.747-56.747-47.36-39.68 60.587-60.587 47.36 40.107 34.133-34.133c-58.453-67.413-93.867-155.307-93.867-251.307 0-212.053 171.52-384 384-384 96 0 183.893 35.413 251.307 93.867l93.867-93.867 54.187 54.187-786.773 786.773zM702.72 154.027c-51.627-42.667-118.187-68.693-190.72-68.693-165.12 0-298.667 133.547-298.667 298.667 0 72.533 26.027 139.093 68.693 190.72l420.693-420.693zM342.187 798.72l-60.587 60.587-36.693-30.293 60.587-60.587 36.693 30.293z" />
-<glyph unicode="&#xe60a;" d="M938.667 694.614l-196.267 164.693-55.040-65.28 196.267-164.693 55.040 65.28zM336.213 794.027l-54.613 65.28-196.267-164.267 55.040-65.28 195.84 164.267zM512 768c-212.053 0-384-171.947-384-384s171.52-384 384-384c212.053 0 384 171.947 384 384s-171.947 384-384 384zM512 85.334c-165.12 0-298.667 133.547-298.667 298.667s133.547 298.667 298.667 298.667 298.667-133.547 298.667-298.667-133.547-298.667-298.667-298.667zM449.707 318.72l-90.88 90.88-45.227-45.227 135.68-135.68 256 256-45.227 45.227-210.347-211.2z" />
-<glyph unicode="&#xe60b;" d="M938.667 694.614l-196.267 164.693-55.040-65.28 196.267-164.693 55.040 65.28zM336.213 794.027l-54.613 65.28-196.267-164.267 55.040-65.28 195.84 164.267zM533.333 597.334h-64v-256l202.667-121.6 32 52.48-170.667 101.12v224zM512 768c-212.053 0-384-171.947-384-384s171.52-384 384-384c212.053 0 384 171.947 384 384s-171.947 384-384 384zM512 85.334c-165.12 0-298.667 133.547-298.667 298.667s133.547 298.667 298.667 298.667 298.667-133.547 298.667-298.667-133.547-298.667-298.667-298.667z" />
-<glyph unicode="&#xe60c;" d="M256 170.667c0-23.467 19.2-42.667 42.667-42.667h42.667v-149.333c0-35.413 28.587-64 64-64s64 28.587 64 64v149.333h85.333v-149.333c0-35.413 28.587-64 64-64s64 28.587 64 64v149.333h42.667c23.467 0 42.667 19.2 42.667 42.667v426.667h-512v-426.667zM149.333 597.334c-35.413 0-64-28.587-64-64v-298.667c0-35.413 28.587-64 64-64s64 28.587 64 64v298.667c0 35.413-28.587 64-64 64zM874.667 597.334c-35.413 0-64-28.587-64-64v-298.667c0-35.413 28.587-64 64-64s64 28.587 64 64v298.667c0 35.413-28.587 64-64 64zM662.613 846.507l55.467 55.467c8.533 8.533 8.533 21.76 0 30.293s-21.76 8.533-30.293 0l-63.147-63.147c-33.707 17.067-72.107 26.88-112.64 26.88-40.96 0-79.36-9.813-113.493-26.88l-63.573 63.147c-8.533 8.533-21.76 8.533-30.293 0s-8.533-21.76 0-30.293l55.893-55.893c-63.147-46.507-104.533-121.173-104.533-206.080h512c0 84.907-41.387 160-105.387 206.507zM426.667 725.334h-42.667v42.667h42.667v-42.667zM640 725.334h-42.667v42.667h42.667v-42.667z" />
-<glyph unicode="&#xe60d;" d="M853.333 853.334h-682.667c-46.933 0-84.907-38.4-84.907-85.333l-0.427-768 170.667 170.667h597.333c46.933 0 85.333 38.4 85.333 85.333v512c0 46.933-38.4 85.333-85.333 85.333zM554.667 469.334h-85.333v256h85.333v-256zM554.667 298.667h-85.333v85.333h85.333v-85.333z" />
-<glyph unicode="&#xe60e;" d="M810.667 426.667h-85.333v-128h-128v-85.333h213.333v213.333zM298.667 554.667h128v85.333h-213.333v-213.333h85.333v128zM896 810.667h-768c-46.933 0-85.333-38.4-85.333-85.333v-597.333c0-46.933 38.4-85.333 85.333-85.333h768c46.933 0 85.333 38.4 85.333 85.333v597.333c0 46.933-38.4 85.333-85.333 85.333zM896 127.574h-768v598.187h768v-598.187z" />
-<glyph unicode="&#xe60f;" d="M810.667 810.667h-597.333c-46.933 0-85.333-38.4-85.333-85.333v-597.333c0-46.933 38.4-85.333 85.333-85.333h597.333c46.933 0 85.333 38.4 85.333 85.333v597.333c0 46.933-38.4 85.333-85.333 85.333zM384 213.334h-85.333v298.667h85.333v-298.667zM554.667 213.334h-85.333v426.667h85.333v-426.667zM725.333 213.334h-85.333v170.667h85.333v-170.667z" />
-<glyph unicode="&#xe610;" d="M810.667 810.667h-178.347c-17.92 49.493-64.853 85.333-120.32 85.333s-102.4-35.84-120.32-85.333h-178.347c-46.933 0-85.333-38.4-85.333-85.333v-597.333c0-46.933 38.4-85.333 85.333-85.333h597.333c46.933 0 85.333 38.4 85.333 85.333v597.333c0 46.933-38.4 85.333-85.333 85.333zM512 810.667c23.467 0 42.667-19.2 42.667-42.667s-19.2-42.667-42.667-42.667-42.667 19.2-42.667 42.667 19.2 42.667 42.667 42.667zM512 640c70.827 0 128-57.173 128-128s-57.173-128-128-128-128 57.173-128 128 57.173 128 128 128zM768 128h-512v59.733c0 85.333 170.667 132.267 256 132.267s256-46.933 256-132.267v-59.733z" />
-<glyph unicode="&#xe611;" d="M810.667 810.667h-178.347c-17.92 49.493-64.853 85.333-120.32 85.333s-102.4-35.84-120.32-85.333h-178.347c-46.933 0-85.333-38.4-85.333-85.333v-597.333c0-46.933 38.4-85.333 85.333-85.333h597.333c46.933 0 85.333 38.4 85.333 85.333v597.333c0 46.933-38.4 85.333-85.333 85.333zM554.667 170.667h-85.333v85.333h85.333v-85.333zM554.667 341.334h-85.333v256h85.333v-256zM512 725.334c-23.467 0-42.667 19.2-42.667 42.667s19.2 42.667 42.667 42.667 42.667-19.2 42.667-42.667-19.2-42.667-42.667-42.667z" />
-<glyph unicode="&#xe612;" d="M810.667 810.667h-178.347c-17.92 49.493-64.853 85.333-120.32 85.333s-102.4-35.84-120.32-85.333h-178.347c-46.933 0-85.333-38.4-85.333-85.333v-597.333c0-46.933 38.4-85.333 85.333-85.333h597.333c46.933 0 85.333 38.4 85.333 85.333v597.333c0 46.933-38.4 85.333-85.333 85.333zM512 810.667c23.467 0 42.667-19.2 42.667-42.667s-19.2-42.667-42.667-42.667-42.667 19.2-42.667 42.667 19.2 42.667 42.667 42.667zM682.667 298.667h-170.667v-128l-213.333 213.333 213.333 213.333v-128h170.667v-170.667z" />
-<glyph unicode="&#xe613;" d="M810.667 810.667h-178.347c-17.92 49.493-64.853 85.333-120.32 85.333s-102.4-35.84-120.32-85.333h-178.347c-46.933 0-85.333-38.4-85.333-85.333v-597.333c0-46.933 38.4-85.333 85.333-85.333h597.333c46.933 0 85.333 38.4 85.333 85.333v597.333c0 46.933-38.4 85.333-85.333 85.333zM512 810.667c23.467 0 42.667-19.2 42.667-42.667s-19.2-42.667-42.667-42.667-42.667 19.2-42.667 42.667 19.2 42.667 42.667 42.667zM512 170.667l-213.333 213.333h128v170.667h170.667v-170.667h128l-213.333-213.333z" />
-<glyph unicode="&#xe614;" d="M810.667 810.667h-178.347c-17.92 49.493-64.853 85.333-120.32 85.333s-102.4-35.84-120.32-85.333h-178.347c-46.933 0-85.333-38.4-85.333-85.333v-597.333c0-46.933 38.4-85.333 85.333-85.333h597.333c46.933 0 85.333 38.4 85.333 85.333v597.333c0 46.933-38.4 85.333-85.333 85.333zM512 810.667c23.467 0 42.667-19.2 42.667-42.667s-19.2-42.667-42.667-42.667-42.667 19.2-42.667 42.667 19.2 42.667 42.667 42.667zM426.667 213.334l-170.667 170.667 60.16 60.16 110.507-110.080 281.173 281.173 60.16-60.587-341.333-341.333z" />
-<glyph unicode="&#xe615;" d="M810.667 810.667h-178.347c-17.92 49.493-64.853 85.333-120.32 85.333s-102.4-35.84-120.32-85.333h-178.347c-46.933 0-85.333-38.4-85.333-85.333v-597.333c0-46.933 38.4-85.333 85.333-85.333h597.333c46.933 0 85.333 38.4 85.333 85.333v597.333c0 46.933-38.4 85.333-85.333 85.333zM512 810.667c23.467 0 42.667-19.2 42.667-42.667s-19.2-42.667-42.667-42.667-42.667 19.2-42.667 42.667 19.2 42.667 42.667 42.667zM597.333 213.334h-298.667v85.333h298.667v-85.333zM725.333 384h-426.667v85.333h426.667v-85.333zM725.333 554.667h-426.667v85.333h426.667v-85.333z" />
-<glyph unicode="&#xe616;" d="M512 682.667v-128l170.667 170.667-170.667 170.667v-128c-188.587 0-341.333-152.747-341.333-341.333 0-66.987 19.627-129.28 52.907-181.76l62.293 62.293c-19.2 35.413-29.867 76.373-29.867 119.467 0 141.227 114.773 256 256 256zM800.427 608.427l-62.293-62.293c18.773-35.84 29.867-76.373 29.867-119.467 0-141.227-114.773-256-256-256v128l-170.667-170.667 170.667-170.667v128c188.587 0 341.333 152.747 341.333 341.333 0 66.987-19.627 129.28-52.907 181.76z" />
-<glyph unicode="&#xe617;" d="M825.6 510.294c-29.013 147.2-158.293 257.707-313.6 257.707-123.307 0-230.4-69.973-283.733-172.373-128.427-13.653-228.267-122.453-228.267-254.293 0-141.227 114.773-256 256-256h554.667c117.76 0 213.333 95.573 213.333 213.333 0 112.64-87.467 203.947-198.4 211.627zM597.333 384v-170.667h-170.667v170.667h-128l213.333 213.333 213.333-213.333h-128z" />
-<glyph unicode="&#xe618;" d="M768 853.334h-512c-46.933 0-85.333-38.4-85.333-85.333v-682.667c0-46.933 38.4-85.333 85.333-85.333h512c46.933 0 85.333 38.4 85.333 85.333v682.667c0 46.933-38.4 85.333-85.333 85.333zM256 768h213.333v-341.333l-106.667 64-106.667-64v341.333z" />
-<glyph unicode="&#xe619;" d="M725.333 810.667h-426.667c-46.933 0-84.907-38.4-84.907-85.333l-0.427-682.667 298.667 128 298.667-128v682.667c0 46.933-38.4 85.333-85.333 85.333zM725.333 170.667l-213.333 93.013-213.333-93.013v554.667h426.667v-554.667z" />
-<glyph unicode="&#xe61a;" d="M725.333 810.667h-426.667c-46.933 0-84.907-38.4-84.907-85.333l-0.427-682.667 298.667 128 298.667-128v682.667c0 46.933-38.4 85.333-85.333 85.333z" />
-<glyph unicode="&#xe61b;" d="M853.333 597.334h-119.893c-19.2 33.28-45.653 61.867-77.653 83.627l69.547 69.547-60.16 60.16-92.587-92.587c-19.627 4.693-39.68 7.253-60.587 7.253s-40.96-2.56-60.16-7.253l-93.013 92.587-60.16-60.16 69.12-69.547c-31.573-21.76-58.027-50.347-77.227-83.627h-119.893v-85.333h89.173c-2.133-14.080-3.84-28.16-3.84-42.667v-42.667h-85.333v-85.333h85.333v-42.667c0-14.507 1.707-28.587 3.84-42.667h-89.173v-85.333h119.893c44.373-76.373 126.72-128 221.44-128s177.067 51.627 221.44 128h119.893v85.333h-89.173c2.133 14.080 3.84 28.16 3.84 42.667v42.667h85.333v85.333h-85.333v42.667c0 14.507-1.707 28.587-3.84 42.667h89.173v85.333zM597.333 256h-170.667v85.333h170.667v-85.333zM597.333 426.667h-170.667v85.333h170.667v-85.333z" />
-<glyph unicode="&#xe61c;" d="M810.667 597.334l-170.667-170.667h128c0-141.227-114.773-256-256-256-43.093 0-84.053 10.667-119.467 29.867l-62.293-62.293c52.48-33.28 114.773-52.907 181.76-52.907 188.587 0 341.333 152.747 341.333 341.333h128l-170.667 170.667zM256 426.667c0 141.227 114.773 256 256 256 43.093 0 84.053-10.667 119.467-29.867l62.293 62.293c-52.48 33.28-114.773 52.907-181.76 52.907-188.587 0-341.333-152.747-341.333-341.333h-128l170.667-170.667 170.667 170.667h-128z" />
-<glyph unicode="&#xe61d;" d="M512 853.334c-235.52 0-426.667-191.147-426.667-426.667s191.147-426.667 426.667-426.667 426.667 191.147 426.667 426.667-191.147 426.667-426.667 426.667zM426.667 213.334l-213.333 213.333 60.16 60.16 153.173-152.747 323.84 323.84 60.16-60.587-384-384z" />
-<glyph unicode="&#xe61e;" d="M768 853.334h-512c-46.933 0-85.333-38.4-85.333-85.333v-682.667c0-46.933 38.4-85.333 85.333-85.333h512c46.933 0 85.333 38.4 85.333 85.333v682.667c0 46.933-38.4 85.333-85.333 85.333zM256 768h213.333v-341.333l-106.667 64-106.667-64v341.333z" />
-<glyph unicode="&#xe61f;" d="M853.333 768h-682.667c-47.36 0-84.907-37.973-84.907-85.333l-0.427-512c0-47.36 37.973-85.333 85.333-85.333h682.667c47.36 0 85.333 37.973 85.333 85.333v512c0 47.36-37.973 85.333-85.333 85.333zM853.333 170.667h-682.667v256h682.667v-256zM853.333 597.334h-682.667v85.333h682.667v-85.333z" />
-<glyph unicode="&#xe620;" d="M128 384h341.333v426.667h-341.333v-426.667zM128 42.667h341.333v256h-341.333v-256zM554.667 42.667h341.333v426.667h-341.333v-426.667zM554.667 810.667v-256h341.333v256h-341.333z" />
-<glyph unicode="&#xe621;" d="M256 128c0-46.933 38.4-85.333 85.333-85.333h341.333c46.933 0 85.333 38.4 85.333 85.333v512h-512v-512zM810.667 768h-149.333l-42.667 42.667h-213.333l-42.667-42.667h-149.333v-85.333h597.333v85.333z" />
-<glyph unicode="&#xe622;" d="M597.333 853.334h-341.333c-46.933 0-84.907-38.4-84.907-85.333l-0.427-682.667c0-46.933 37.973-85.333 84.907-85.333h512.427c46.933 0 85.333 38.4 85.333 85.333v512l-256 256zM682.667 170.667h-341.333v85.333h341.333v-85.333zM682.667 341.334h-341.333v85.333h341.333v-85.333zM554.667 554.667v234.667l234.667-234.667h-234.667z" />
-<glyph unicode="&#xe623;" d="M853.333 384h-682.667c-23.467 0-42.667-19.2-42.667-42.667v-256c0-23.467 19.2-42.667 42.667-42.667h682.667c23.467 0 42.667 19.2 42.667 42.667v256c0 23.467-19.2 42.667-42.667 42.667zM298.667 128c-46.933 0-85.333 38.4-85.333 85.333s38.4 85.333 85.333 85.333 85.333-38.4 85.333-85.333-38.4-85.333-85.333-85.333zM853.333 810.667h-682.667c-23.467 0-42.667-19.2-42.667-42.667v-256c0-23.467 19.2-42.667 42.667-42.667h682.667c23.467 0 42.667 19.2 42.667 42.667v256c0 23.467-19.2 42.667-42.667 42.667zM298.667 554.667c-46.933 0-85.333 38.4-85.333 85.333s38.4 85.333 85.333 85.333 85.333-38.4 85.333-85.333-38.4-85.333-85.333-85.333z" />
-<glyph unicode="&#xe624;" d="M768 640l-60.16 60.16-270.507-270.507 60.16-60.16 270.507 270.507zM948.907 700.16l-451.413-451.413-178.347 177.92-60.16-60.16 238.507-238.507 512 512-60.587 60.16zM17.493 366.507l238.507-238.507 60.16 60.16-238.080 238.507-60.587-60.16z" />
-<glyph unicode="&#xe625;" d="M384 248.747l-177.92 177.92-60.587-60.16 238.507-238.507 512 512-60.16 60.16z" />
-<glyph unicode="&#xe626;" d="M725.333 426.667h-213.333v-213.333h213.333v213.333zM682.667 896v-85.333h-341.333v85.333h-85.333v-85.333h-42.667c-47.36 0-84.907-38.4-84.907-85.333l-0.427-597.333c0-46.933 37.973-85.333 85.333-85.333h597.333c46.933 0 85.333 38.4 85.333 85.333v597.333c0 46.933-38.4 85.333-85.333 85.333h-42.667v85.333h-85.333zM810.667 128h-597.333v469.333h597.333v-469.333z" />
-<glyph unicode="&#xe627;" d="M430.507 273.494l60.16-60.16 213.333 213.333-213.333 213.333-60.16-60.16 110.080-110.507h-412.587v-85.333h412.587l-110.080-110.507zM810.667 810.667h-597.333c-47.36 0-85.333-38.4-85.333-85.333v-170.667h85.333v170.667h597.333v-597.333h-597.333v170.667h-85.333v-170.667c0-46.933 37.973-85.333 85.333-85.333h597.333c46.933 0 85.333 38.4 85.333 85.333v597.333c0 46.933-38.4 85.333-85.333 85.333z" />
-<glyph unicode="&#xe628;" d="M512 473.6c-26.027 0-46.933-20.907-46.933-46.933s20.907-46.933 46.933-46.933c26.027 0 46.933 20.907 46.933 46.933s-20.907 46.933-46.933 46.933zM512 853.334c-235.52 0-426.667-191.147-426.667-426.667s191.147-426.667 426.667-426.667 426.667 191.147 426.667 426.667-191.147 426.667-426.667 426.667zM605.44 333.227l-349.44-162.56 162.56 349.44 349.44 162.56-162.56-349.44z" />
-<glyph unicode="&#xe629;" d="M874.667 469.334h-64v170.667c0 46.933-38.4 85.333-85.333 85.333h-170.667v64c0 58.88-47.787 106.667-106.667 106.667s-106.667-47.787-106.667-106.667v-64h-170.667c-46.933 0-84.907-38.4-84.907-85.333v-162.133h63.573c63.573 0 115.2-51.627 115.2-115.2s-51.627-115.2-115.2-115.2h-64v-162.133c0-46.933 38.4-85.333 85.333-85.333h162.133v64c0 63.573 51.627 115.2 115.2 115.2s115.2-51.627 115.2-115.2v-64h162.133c46.933 0 85.333 38.4 85.333 85.333v170.667h64c58.88 0 106.667 47.787 106.667 106.667s-47.787 106.667-106.667 106.667z" />
-<glyph unicode="&#xe62a;" d="M626.773 209.067c-31.573-24.747-72.533-38.4-114.773-38.4s-83.2 13.653-114.773 38.4c-9.387 7.253-22.613 5.547-29.867-3.84s-5.547-22.613 3.84-29.867c38.827-30.72 89.173-47.36 140.8-47.36s101.973 16.64 141.227 46.933c9.387 7.253 11.093 20.48 3.84 29.867-7.253 9.813-20.907 11.093-30.293 4.267zM405.333 405.334c0-23.564-19.103-42.667-42.667-42.667s-42.667 19.103-42.667 42.667c0 23.564 19.103 42.667 42.667 42.667s42.667-19.103 42.667-42.667zM512 938.667c-282.88 0-512-229.12-512-512s229.12-512 512-512 512 229.12 512 512-229.12 512-512 512zM851.627 306.347c-46.507-159.573-182.187-275.627-343.040-275.627-161.28 0-296.96 116.053-343.040 276.053-50.773 4.693-90.88 50.347-90.88 107.52 0 54.187 36.267 98.56 84.053 106.667 89.173 62.293 162.133 148.907 174.507 215.467v0.427c57.6-112.213 268.8-221.44 504.747-215.893l12.8 1.28c54.613 0 98.56-48.64 98.56-108.373 0-58.88-43.52-107.093-97.707-107.52zM704 405.334c0-23.564-19.103-42.667-42.667-42.667s-42.667 19.103-42.667 42.667c0 23.564 19.103 42.667 42.667 42.667s42.667-19.103 42.667-42.667z" />
-<glyph unicode="&#xe62b;" d="M704 810.667c-74.24 0-145.493-34.56-192-89.173-46.507 54.613-117.76 89.173-192 89.173-131.413 0-234.667-103.253-234.667-234.667 0-161.28 145.067-292.693 364.8-492.373l61.867-55.893 61.867 56.32c219.733 199.253 364.8 330.667 364.8 491.947 0 131.413-103.253 234.667-234.667 234.667zM516.267 147.2l-4.267-4.267-4.267 4.267c-203.093 183.893-337.067 305.493-337.067 428.8 0 85.333 64 149.333 149.333 149.333 65.707 0 129.707-42.24 152.32-100.693h79.787c22.187 58.453 86.187 100.693 151.893 100.693 85.333 0 149.333-64 149.333-149.333 0-123.307-133.973-244.907-337.067-428.8z" />
-<glyph unicode="&#xe62c;" d="M512 27.734l-61.867 56.32c-219.733 199.253-364.8 330.667-364.8 491.947 0 131.413 103.253 234.667 234.667 234.667 74.24 0 145.493-34.56 192-89.173 46.507 54.613 117.76 89.173 192 89.173 131.413 0 234.667-103.253 234.667-234.667 0-161.28-145.067-292.693-364.8-492.373l-61.867-55.893z" />
-<glyph unicode="&#xe62d;" d="M853.333 102.827v494.507l-256 256h-341.333c-46.933 0-84.907-38.4-84.907-85.333l-0.427-682.667c0-46.933 37.973-85.333 84.907-85.333h512.427c19.2 0 36.267 6.4 50.773 17.067l-189.013 189.013c-34.133-22.187-74.24-35.413-117.76-35.413-117.76 0-213.333 95.573-213.333 213.333s95.573 213.333 213.333 213.333 213.333-95.573 213.333-213.333c0-43.52-13.227-83.627-35.413-117.333l163.413-163.84zM384 384c0-70.827 57.173-128 128-128s128 57.173 128 128-57.173 128-128 128-128-57.173-128-128z" />
-<glyph unicode="&#xe62e;" d="M469.333 682.667c58.88 0 112.213-23.893 151.040-62.293l-108.373-108.373h256v256l-87.467-87.467c-54.187 54.187-128.853 87.467-211.2 87.467-150.613 0-274.347-111.36-295.253-256h86.187c19.627 97.28 105.813 170.667 209.067 170.667zM709.973 292.694c28.16 38.4 47.787 84.053 54.613 133.973h-86.187c-19.627-97.28-105.813-170.667-209.067-170.667-58.88 0-112.213 23.893-151.040 62.293l108.373 108.373h-256v-256l87.467 87.467c54.187-54.187 128.853-87.467 211.2-87.467 66.133 0 127.147 21.76 176.64 58.027l207.36-206.933 63.573 63.573-206.933 207.36z" />
-<glyph unicode="&#xe62f;" d="M384 640h-85.333v-85.333h85.333v85.333zM384 469.334h-85.333v-85.333h85.333v85.333zM384 810.667c-47.36 0-85.333-38.4-85.333-85.333h85.333v85.333zM554.667 298.667h-85.333v-85.333h85.333v85.333zM810.667 810.667v-85.333h85.333c0 46.933-38.4 85.333-85.333 85.333zM554.667 810.667h-85.333v-85.333h85.333v85.333zM384 213.334v85.333h-85.333c0-46.933 37.973-85.333 85.333-85.333zM810.667 384h85.333v85.333h-85.333v-85.333zM810.667 554.667h85.333v85.333h-85.333v-85.333zM810.667 213.334c46.933 0 85.333 38.4 85.333 85.333h-85.333v-85.333zM213.333 640h-85.333v-512c0-46.933 37.973-85.333 85.333-85.333h512v85.333h-512v512zM640 725.334h85.333v85.333h-85.333v-85.333zM640 213.334h85.333v85.333h-85.333v-85.333z" />
-<glyph unicode="&#xe630;" d="M128 384h85.333v85.333h-85.333v-85.333zM128 213.334h85.333v85.333h-85.333v-85.333zM213.333 42.667v85.333h-85.333c0-46.933 37.973-85.333 85.333-85.333zM128 554.667h85.333v85.333h-85.333v-85.333zM640 42.667h85.333v85.333h-85.333v-85.333zM810.667 810.667h-426.667c-47.36 0-85.333-38.4-85.333-85.333v-426.667c0-46.933 37.973-85.333 85.333-85.333h426.667c46.933 0 85.333 38.4 85.333 85.333v426.667c0 46.933-38.4 85.333-85.333 85.333zM810.667 298.667h-426.667v426.667h426.667v-426.667zM469.333 42.667h85.333v85.333h-85.333v-85.333zM298.667 42.667h85.333v85.333h-85.333v-85.333z" />
-<glyph unicode="&#xe631;" d="M810.667 554.667h-170.667v256h-256v-256h-170.667l298.667-298.667 298.667 298.667zM213.333 170.667v-85.333h597.333v85.333h-597.333z" />
-<glyph unicode="&#xe632;" d="M512 201.814l263.68-159.147-69.973 299.947 232.96 201.813-306.773 26.027-119.893 282.88-119.893-282.88-306.773-26.027 232.96-201.813-69.973-299.947z" />
-<glyph unicode="&#xe633;" d="M512 853.334c-235.52 0-426.667-191.147-426.667-426.667s191.147-426.667 426.667-426.667 426.667 191.147 426.667 426.667-191.147 426.667-426.667 426.667zM341.333 192c-58.88 0-106.667 47.787-106.667 106.667s47.787 106.667 106.667 106.667 106.667-47.787 106.667-106.667-47.787-106.667-106.667-106.667zM405.333 597.334c0 58.88 47.787 106.667 106.667 106.667s106.667-47.787 106.667-106.667-47.787-106.667-106.667-106.667-106.667 47.787-106.667 106.667zM682.667 192c-58.88 0-106.667 47.787-106.667 106.667s47.787 106.667 106.667 106.667 106.667-47.787 106.667-106.667-47.787-106.667-106.667-106.667z" />
-<glyph unicode="&#xe634;" d="M512 853.334c-235.52 0-426.667-191.147-426.667-426.667s191.147-426.667 426.667-426.667 426.667 191.147 426.667 426.667-191.147 426.667-426.667 426.667zM554.667 128h-85.333v85.333h85.333v-85.333zM642.987 458.667l-38.4-39.253c-30.72-31.147-49.92-56.747-49.92-120.747h-85.333v21.333c0 46.933 19.2 89.6 49.92 120.747l52.907 53.76c15.787 15.36 25.173 36.693 25.173 60.16 0 46.933-38.4 85.333-85.333 85.333s-85.333-38.4-85.333-85.333h-85.333c0 94.293 76.373 170.667 170.667 170.667s170.667-76.373 170.667-170.667c0-37.547-15.36-71.68-39.68-96z" />
-<glyph unicode="&#xe635;" d="M622.507 597.334l-110.507-110.507-110.507 110.507-60.16-60.16 110.507-110.507-110.507-110.507 60.16-60.16 110.507 110.507 110.507-110.507 60.16 60.16-110.507 110.507 110.507 110.507-60.16 60.16zM512 853.334c-235.947 0-426.667-190.72-426.667-426.667s190.72-426.667 426.667-426.667 426.667 190.72 426.667 426.667-190.72 426.667-426.667 426.667zM512 85.334c-188.16 0-341.333 153.173-341.333 341.333s153.173 341.333 341.333 341.333 341.333-153.173 341.333-341.333-153.173-341.333-341.333-341.333z" />
-<glyph unicode="&#xe636;" d="M554.667 810.667c-212.053 0-384-171.947-384-384h-128l165.973-165.973 2.987-5.973 172.373 171.947h-128c0 165.12 133.547 298.667 298.667 298.667s298.667-133.547 298.667-298.667-133.547-298.667-298.667-298.667c-82.347 0-157.013 33.707-210.773 87.893l-60.587-60.587c69.547-69.547 165.12-112.64 271.36-112.64 212.053 0 384 171.947 384 384s-171.947 384-384 384zM512 597.334v-213.333l182.613-108.373 30.72 51.627-149.333 88.747v181.333h-64z" />
-<glyph unicode="&#xe637;" d="M426.667 85.334v256h170.667v-256h213.333v341.333h128l-426.667 384-426.667-384h128v-341.333z" />
-<glyph unicode="&#xe638;" d="M768 597.334h-42.667v85.333c0 117.76-95.573 213.333-213.333 213.333s-213.333-95.573-213.333-213.333v-85.333h-42.667c-46.933 0-85.333-38.4-85.333-85.333v-426.667c0-46.933 38.4-85.333 85.333-85.333h512c46.933 0 85.333 38.4 85.333 85.333v426.667c0 46.933-38.4 85.333-85.333 85.333zM512 213.334c-46.933 0-85.333 38.4-85.333 85.333s38.4 85.333 85.333 85.333 85.333-38.4 85.333-85.333-38.4-85.333-85.333-85.333zM644.267 597.334h-264.533v85.333c0 72.96 59.307 132.267 132.267 132.267s132.267-59.307 132.267-132.267v-85.333z" />
-<glyph unicode="&#xe639;" d="M469.333 213.334h85.333v256h-85.333v-256zM512 853.334c-235.52 0-426.667-191.147-426.667-426.667s191.147-426.667 426.667-426.667 426.667 191.147 426.667 426.667-191.147 426.667-426.667 426.667zM512 85.334c-188.16 0-341.333 153.173-341.333 341.333s153.173 341.333 341.333 341.333 341.333-153.173 341.333-341.333-153.173-341.333-341.333-341.333zM469.333 554.667h85.333v85.333h-85.333v-85.333z" />
-<glyph unicode="&#xe63a;" d="M512 853.334c-235.52 0-426.667-191.147-426.667-426.667s191.147-426.667 426.667-426.667 426.667 191.147 426.667 426.667-191.147 426.667-426.667 426.667zM554.667 213.334h-85.333v256h85.333v-256zM554.667 554.667h-85.333v85.333h85.333v-85.333z" />
-<glyph unicode="&#xe63b;" d="M896 810.24h-768c-46.933 0-85.333-38.4-85.333-85.333v-170.24h85.333v171.093h768v-598.613h-768v171.52h-85.333v-171.093c0-46.933 38.4-84.48 85.333-84.48h768c46.933 0 85.333 37.547 85.333 84.48v597.333c0 47.36-38.4 85.333-85.333 85.333zM469.333 256l170.667 170.667-170.667 170.667v-128h-426.667v-85.333h426.667v-128z" />
-<glyph unicode="&#xe63c;" d="M753.493 600.32l-241.493 241.493-241.493-241.493c-133.12-133.12-133.12-349.44 0-482.56 66.56-66.56 154.027-99.84 241.493-99.84s174.933 33.28 241.493 99.84c133.12 133.12 133.12 349.44 0 482.56zM512 102.827c-68.267 0-132.693 26.453-180.907 75.093-48.64 48.64-75.093 112.64-75.093 180.907s26.453 132.693 75.093 180.907l180.907 181.333v-618.24z" />
-<glyph unicode="&#xe63d;" d="M752.213 689.494c-15.36 21.76-40.96 35.84-69.547 35.84l-469.333-0.427c-46.933 0-85.333-37.973-85.333-84.907v-426.667c0-46.933 38.4-84.907 85.333-84.907l469.333-0.427c28.587 0 54.187 14.080 69.547 35.84l186.453 262.827-186.453 262.827zM682.667 213.334h-469.333v426.667h469.333l151.467-213.333-151.467-213.333z" />
-<glyph unicode="&#xe63e;" d="M752.213 689.494c-15.36 21.76-40.96 35.84-69.547 35.84l-469.333-0.427c-46.933 0-85.333-37.973-85.333-84.907v-426.667c0-46.933 38.4-84.907 85.333-84.907l469.333-0.427c28.587 0 54.187 14.080 69.547 35.84l186.453 262.827-186.453 262.827z" />
-<glyph unicode="&#xe63f;" d="M511.573 853.334c-235.52 0-426.24-191.147-426.24-426.667s190.72-426.667 426.24-426.667c235.947 0 427.093 191.147 427.093 426.667s-191.147 426.667-427.093 426.667zM807.253 597.334h-125.867c-13.653 53.333-33.28 104.533-58.88 151.893 78.507-26.88 143.787-81.493 184.747-151.893zM512 766.294c35.413-51.2 63.147-107.947 81.493-168.96h-162.987c18.347 61.013 46.080 117.76 81.493 168.96zM181.76 341.334c-6.827 27.307-11.093 55.893-11.093 85.333s4.267 58.027 11.093 85.333h144.213c-3.413-28.16-5.973-56.32-5.973-85.333s2.56-57.173 5.973-85.333h-144.213zM216.747 256h125.867c13.653-53.333 33.28-104.533 58.88-151.893-78.507 26.88-143.787 81.067-184.747 151.893zM342.613 597.334h-125.867c40.96 70.827 106.24 125.013 184.747 151.893-25.6-47.36-45.227-98.56-58.88-151.893zM512 87.040c-35.413 51.2-63.147 107.947-81.493 168.96h162.987c-18.347-61.013-46.080-117.76-81.493-168.96zM611.84 341.334h-199.68c-3.84 28.16-6.827 56.32-6.827 85.333s2.987 57.6 6.827 85.333h199.68c3.84-27.733 6.827-56.32 6.827-85.333s-2.987-57.173-6.827-85.333zM622.507 104.107c25.6 47.36 45.227 98.56 58.88 151.893h125.867c-40.96-70.4-106.24-125.013-184.747-151.893zM698.027 341.334c3.413 28.16 5.973 56.32 5.973 85.333s-2.56 57.173-5.973 85.333h144.213c6.827-27.307 11.093-55.893 11.093-85.333s-4.267-58.027-11.093-85.333h-144.213z" />
-<glyph unicode="&#xe640;" d="M810.667 128h-597.333v597.333h298.667v85.333h-298.667c-47.36 0-85.333-38.4-85.333-85.333v-597.333c0-46.933 37.973-85.333 85.333-85.333h597.333c46.933 0 85.333 38.4 85.333 85.333v298.667h-85.333v-298.667zM597.333 810.667v-85.333h153.173l-419.413-419.413 60.16-60.16 419.413 419.413v-153.173h85.333v298.667h-298.667z" />
-<glyph unicode="&#xe641;" d="M128 384h85.333v85.333h-85.333v-85.333zM128 213.334h85.333v85.333h-85.333v-85.333zM128 554.667h85.333v85.333h-85.333v-85.333zM298.667 384h597.333v85.333h-597.333v-85.333zM298.667 213.334h597.333v85.333h-597.333v-85.333zM298.667 640v-85.333h597.333v85.333h-597.333z" />
-<glyph unicode="&#xe642;" d="M512 213.334c46.933 0 85.333 38.4 85.333 85.333s-38.4 85.333-85.333 85.333-85.333-38.4-85.333-85.333 38.4-85.333 85.333-85.333zM768 597.334h-42.667v85.333c0 117.76-95.573 213.333-213.333 213.333s-213.333-95.573-213.333-213.333h81.067c0 72.96 59.307 132.267 132.267 132.267s132.267-59.307 132.267-132.267v-85.333h-388.267c-46.933 0-85.333-38.4-85.333-85.333v-426.667c0-46.933 38.4-85.333 85.333-85.333h512c46.933 0 85.333 38.4 85.333 85.333v426.667c0 46.933-38.4 85.333-85.333 85.333zM768 85.334h-512v426.667h512v-426.667z" />
-<glyph unicode="&#xe643;" d="M768 597.334h-42.667v85.333c0 117.76-95.573 213.333-213.333 213.333s-213.333-95.573-213.333-213.333v-85.333h-42.667c-46.933 0-85.333-38.4-85.333-85.333v-426.667c0-46.933 38.4-85.333 85.333-85.333h512c46.933 0 85.333 38.4 85.333 85.333v426.667c0 46.933-38.4 85.333-85.333 85.333zM512 814.934c72.96 0 132.267-59.307 132.267-132.267v-85.333h-260.267v85.333h-4.267c0 72.96 59.307 132.267 132.267 132.267zM768 85.334h-512v426.667h512v-426.667zM512 213.334c46.933 0 85.333 38.4 85.333 85.333s-38.4 85.333-85.333 85.333-85.333-38.4-85.333-85.333 38.4-85.333 85.333-85.333z" />
-<glyph unicode="&#xe644;" d="M768 597.334h-42.667v85.333c0 117.76-95.573 213.333-213.333 213.333s-213.333-95.573-213.333-213.333v-85.333h-42.667c-46.933 0-85.333-38.4-85.333-85.333v-426.667c0-46.933 38.4-85.333 85.333-85.333h512c46.933 0 85.333 38.4 85.333 85.333v426.667c0 46.933-38.4 85.333-85.333 85.333zM512 213.334c-46.933 0-85.333 38.4-85.333 85.333s38.4 85.333 85.333 85.333 85.333-38.4 85.333-85.333-38.4-85.333-85.333-85.333zM644.267 597.334h-264.533v85.333c0 72.96 59.307 132.267 132.267 132.267s132.267-59.307 132.267-132.267v-85.333z" />
-<glyph unicode="&#xe645;" d="M913.493 444.587l-384 384c-15.36 15.36-36.693 24.747-60.16 24.747h-298.667c-46.933 0-85.333-38.4-85.333-85.333v-298.667c0-23.467 9.387-44.8 25.173-60.587l384-384c15.36-15.36 36.693-24.747 60.16-24.747s44.8 9.387 60.16 25.173l298.667 298.667c15.787 15.36 25.173 36.693 25.173 60.16s-9.813 45.227-25.173 60.587zM234.667 640c-35.413 0-64 28.587-64 64s28.587 64 64 64 64-28.587 64-64-28.587-64-64-64zM736.853 287.147l-182.187-182.187-182.187 182.187c-19.2 19.627-31.147 46.080-31.147 75.52 0 58.88 47.787 106.667 106.667 106.667 29.44 0 56.32-11.947 75.52-31.573l31.147-30.72 31.147 31.147c19.2 19.2 46.080 31.147 75.52 31.147 58.88 0 106.667-47.787 106.667-106.667 0-29.44-11.947-56.32-31.147-75.52z" />
-<glyph unicode="&#xe646;" d="M853.333 682.667h-426.667v-256h-85.333v341.333h256v170.667h-341.333v-256h-85.333c-46.933 0-85.333-38.4-85.333-85.333v-512c0-46.933 38.4-85.333 85.333-85.333h682.667c46.933 0 85.333 38.4 85.333 85.333v512c0 46.933-38.4 85.333-85.333 85.333z" />
-<glyph unicode="&#xe647;" d="M597.333 853.334h-341.333c-46.933 0-84.907-38.4-84.907-85.333l-0.427-682.667c0-46.933 37.973-85.333 84.907-85.333h512.427c46.933 0 85.333 38.4 85.333 85.333v512l-256 256zM682.667 256h-128v-128h-85.333v128h-128v85.333h128v128h85.333v-128h128v-85.333zM554.667 554.667v234.667l234.667-234.667h-234.667z" />
-<glyph unicode="&#xe648;" d="M810.667 768h-597.333c-47.36 0-85.333-38.4-85.333-85.333v-512c0-46.933 37.973-85.333 85.333-85.333h170.667v85.333h-170.667v426.667h597.333v-426.667h-170.667v-85.333h170.667c46.933 0 85.333 38.4 85.333 85.333v512c0 46.933-37.973 85.333-85.333 85.333zM512 512l-170.667-170.667h128v-256h85.333v256h128l-170.667 170.667z" />
-<glyph unicode="&#xe649;" d="M810.667 128h-597.333v597.333h298.667v85.333h-298.667c-47.36 0-85.333-38.4-85.333-85.333v-597.333c0-46.933 37.973-85.333 85.333-85.333h597.333c46.933 0 85.333 38.4 85.333 85.333v298.667h-85.333v-298.667zM597.333 810.667v-85.333h153.173l-419.413-419.413 60.16-60.16 419.413 419.413v-153.173h85.333v298.667h-298.667z" />
-<glyph unicode="&#xe64a;" d="M426.667 554.667h170.667v128h128l-213.333 213.333-213.333-213.333h128v-128zM384 512h-128v128l-213.333-213.333 213.333-213.333v128h128v170.667zM981.333 426.667l-213.333 213.333v-128h-128v-170.667h128v-128l213.333 213.333zM597.333 298.667h-170.667v-128h-128l213.333-213.333 213.333 213.333h-128v128z" />
-<glyph unicode="&#xe64b;" d="M469.333 597.334c-70.827 0-128-57.173-128-128s57.173-128 128-128 128 57.173 128 128-57.173 128-128 128zM810.667 810.667h-597.333c-46.933 0-85.333-38.4-85.333-85.333v-597.333c0-46.933 38.4-85.333 85.333-85.333h597.333c46.933 0 85.333 38.4 85.333 85.333v597.333c0 46.933-38.4 85.333-85.333 85.333zM750.507 128l-163.413 163.413c-34.133-22.187-74.24-35.413-117.76-35.413-117.76 0-213.333 95.573-213.333 213.333s95.573 213.333 213.333 213.333 213.333-95.573 213.333-213.333c0-43.52-13.227-83.627-35.413-117.333l163.413-163.84-60.16-60.16z" />
-<glyph unicode="&#xe64c;" d="M853.333 768h-682.667c-47.36 0-84.907-37.973-84.907-85.333l-0.427-512c0-47.36 37.973-85.333 85.333-85.333h682.667c47.36 0 85.333 37.973 85.333 85.333v512c0 47.36-37.973 85.333-85.333 85.333zM853.333 170.667h-682.667v256h682.667v-256zM853.333 597.334h-682.667v85.333h682.667v-85.333z" />
-<glyph unicode="&#xe64d;" d="M853.333 725.334h-135.253l-78.080 85.333h-256l-78.080-85.333h-135.253c-46.933 0-85.333-38.4-85.333-85.333v-512c0-46.933 38.4-85.333 85.333-85.333h298.667v89.173c-120.747 20.48-213.333 125.44-213.333 252.16h85.333c0-94.293 76.373-170.667 170.667-170.667s170.667 76.373 170.667 170.667h85.333c0-126.72-92.587-231.68-213.333-252.16v-89.173h298.667c46.933 0 85.333 38.4 85.333 85.333v512c0 46.933-38.4 85.333-85.333 85.333zM597.333 384c0-46.933-38.4-85.333-85.333-85.333s-85.333 38.4-85.333 85.333v170.667c0 46.933 38.4 85.333 85.333 85.333s85.333-38.4 85.333-85.333v-170.667z" />
-<glyph unicode="&#xe64e;" d="M810.667 810.667h-42.667v85.333h-85.333v-85.333h-341.333v85.333h-85.333v-85.333h-42.667c-47.36 0-85.333-38.4-85.333-85.333v-597.333c0-46.933 37.973-85.333 85.333-85.333h597.333c46.933 0 85.333 38.4 85.333 85.333v597.333c0 46.933-38.4 85.333-85.333 85.333zM512 682.667c70.827 0 128-57.173 128-128s-57.173-128-128-128-128 57.173-128 128 57.173 128 128 128zM768 170.667h-512v42.667c0 85.333 170.667 132.267 256 132.267s256-46.933 256-132.267v-42.667z" />
-<glyph unicode="&#xe64f;" d="M810.24 448c14.507 0 28.587-1.28 42.667-2.987l0.427 493.653-853.333-853.333h493.227c-1.707 14.080-2.987 28.16-2.987 42.667 0 176.64 143.36 320 320 320zM968.533 107.094c0.853 6.827 1.707 13.653 1.707 20.907s-0.427 14.080-1.707 20.907l45.227 35.413c3.84 3.413 5.12 8.96 2.56 13.653l-42.667 73.813c-2.56 4.693-8.107 6.4-13.227 4.693l-52.907-21.333c-11.093 8.533-23.040 15.787-36.267 20.907l-8.107 56.32c-0.427 5.12-5.12 8.96-10.24 8.96h-85.333c-5.12 0-9.813-3.84-10.667-8.96l-8.107-56.32c-12.8-5.547-25.173-12.373-36.267-20.907l-52.907 21.333c-4.693 1.707-10.24 0-13.227-4.693l-42.667-73.813c-2.56-4.693-1.707-10.24 2.56-13.653l45.227-35.413c-0.853-6.827-1.28-13.653-1.28-20.907s0.427-14.080 1.28-20.907l-45.227-35.413c-3.84-3.413-5.12-8.96-2.56-13.653l42.667-73.813c2.56-4.693 8.107-6.4 13.227-4.693l52.907 21.333c11.093-8.533 23.040-15.787 36.267-20.907l8.107-56.32c0.853-5.12 5.12-8.96 10.667-8.96h85.333c5.12 0 9.813 3.84 10.667 8.96l8.107 56.32c12.8 5.547 25.173 12.373 35.84 20.907l53.333-21.333c4.693-1.707 10.24 0 13.227 4.693l42.667 73.813c2.56 4.693 1.28 10.24-2.56 13.653l-45.653 35.413zM810.24 64c-35.413 0-64 28.587-64 64s28.587 64 64 64 64-28.587 64-64-28.587-64-64-64z" />
-<glyph unicode="&#xe650;" d="M554.667 640h-85.333v-85.333h85.333v85.333zM554.667 469.334h-85.333v-256h85.333v256zM725.333 895.574l-426.667 0.427c-46.933 0-85.333-38.4-85.333-85.333v-768c0-46.933 38.4-85.333 85.333-85.333h426.667c46.933 0 85.333 38.4 85.333 85.333v768c0 46.933-38.4 84.907-85.333 84.907zM725.333 128h-426.667v597.333h426.667v-597.333z" />
-<glyph unicode="&#xe651;" d="M512 686.934c49.493 0 89.6-40.107 89.6-89.6s-40.107-89.6-89.6-89.6-89.6 40.107-89.6 89.6 40.107 89.6 89.6 89.6zM512 302.934c126.72 0 260.267-62.293 260.267-89.6v-46.933h-520.533v46.933c0 27.307 133.547 89.6 260.267 89.6zM512 768c-94.293 0-170.667-76.373-170.667-170.667s76.373-170.667 170.667-170.667 170.667 76.373 170.667 170.667-76.373 170.667-170.667 170.667zM512 384c-113.92 0-341.333-57.173-341.333-170.667v-128h682.667v128c0 113.493-227.413 170.667-341.333 170.667z" />
-<glyph unicode="&#xe652;" d="M85.333 682.667h-85.333v-213.333h0.427l-0.427-384c0-46.933 38.4-85.333 85.333-85.333h768v85.333h-768v597.333zM938.667 768h-341.333l-85.333 85.333h-256c-46.933 0-84.907-38.4-84.907-85.333l-0.427-512c0-46.933 38.4-85.333 85.333-85.333h682.667c46.933 0 85.333 38.4 85.333 85.333v426.667c0 46.933-38.4 85.333-85.333 85.333zM298.667 298.667l192 256 149.333-192.427 106.667 128.427 149.333-192h-597.333z" />
-<glyph unicode="&#xe653;" d="M853.333 277.334c-53.333 0-104.533 8.533-152.32 24.32-14.933 4.693-31.573 1.28-43.52-10.24l-93.867-93.867c-120.747 61.44-219.733 160-281.173 280.747l93.867 94.293c11.947 11.52 15.36 28.16 10.667 43.093-15.787 47.787-24.32 98.987-24.32 152.32 0 23.467-19.2 42.667-42.667 42.667h-149.333c-23.467 0-42.667-19.2-42.667-42.667 0-400.64 324.693-725.333 725.333-725.333 23.467 0 42.667 19.2 42.667 42.667v149.333c0 23.467-19.2 42.667-42.667 42.667zM512 810.667v-426.667l128 128h256v298.667h-384z" />
-<glyph unicode="&#xe654;" d="M512 810.667c-215.467 0-377.6-78.933-512-180.48l512-630.187 512 629.333c-134.4 101.547-296.533 181.333-512 181.333zM554.667 256h-85.333v256h85.333v-256zM469.333 597.334v85.333h85.333v-85.333h-85.333z" />
-<glyph unicode="&#xe655;" d="M810.667 640h-341.333v-256h341.333v256zM896 810.667h-768c-46.933 0-85.333-38.4-85.333-85.333v-597.333c0-46.933 38.4-84.48 85.333-84.48h768c46.933 0 85.333 37.547 85.333 84.48v597.333c0 46.933-38.4 85.333-85.333 85.333zM896 127.574h-768v598.613h768v-598.613z" />
-<glyph unicode="&#xe656;" d="M810.667 768h-170.667l-336.64-538.88-111.36 197.547 192 341.333h-170.667l-192-341.333 192-341.333h170.667l336.64 538.88 111.36-197.547-192-341.333h170.667l192 341.333z" />
-<glyph unicode="&#xe657;" d="M810.667 597.334h-597.333c-70.827 0-128-57.173-128-128v-256h170.667v-170.667h512v170.667h170.667v256c0 70.827-57.173 128-128 128zM682.667 128h-341.333v213.333h341.333v-213.333zM810.667 426.667c-23.467 0-42.667 19.2-42.667 42.667s19.2 42.667 42.667 42.667 42.667-19.2 42.667-42.667-19.2-42.667-42.667-42.667zM768 810.667h-512v-170.667h512v170.667z" />
-<glyph unicode="&#xe658;" d="M511.573 853.334c-235.52 0-426.24-191.147-426.24-426.667s190.72-426.667 426.24-426.667c235.947 0 427.093 191.147 427.093 426.667s-191.147 426.667-427.093 426.667zM512 85.334c-188.587 0-341.333 152.747-341.333 341.333s152.747 341.333 341.333 341.333 341.333-152.747 341.333-341.333-152.747-341.333-341.333-341.333zM533.333 640h-64v-256l224-134.4 32 52.48-192 113.92z" />
-<glyph unicode="&#xe659;" d="M896 682.667h-85.333v-384h-554.667v-85.333c0-23.467 19.2-42.667 42.667-42.667h469.333l170.667-170.667v640c0 23.467-19.2 42.667-42.667 42.667zM725.333 426.667v384c0 23.467-19.2 42.667-42.667 42.667h-554.667c-23.467 0-42.667-19.2-42.667-42.667v-597.333l170.667 170.667h426.667c23.467 0 42.667 19.2 42.667 42.667z" />
-<glyph unicode="&#xe65a;" d="M768 213.334h-512v85.333h512v-85.333zM768 384h-512v85.333h512v-85.333zM768 554.667h-512v85.333h512v-85.333zM128-0l64 64 64-64 64 64 64-64 64 64 64-64 64 64 64-64 64 64 64-64 64 64 64-64v853.333l-64-64-64 64-64-64-64 64-64-64-64 64-64-64-64 64-64-64-64 64-64-64-64 64v-853.333z" />
-<glyph unicode="&#xe65b;" d="M853.333 682.667h-93.013c4.693 13.227 7.68 27.733 7.68 42.667 0 70.827-57.173 128-128 128-44.8 0-83.627-23.040-106.667-57.6l-21.333-28.587-21.333 29.013c-23.040 34.133-61.867 57.173-106.667 57.173-70.827 0-128-57.173-128-128 0-14.933 2.987-29.44 7.68-42.667h-93.013c-47.36 0-84.907-37.973-84.907-85.333l-0.427-469.333c0-47.36 37.973-85.333 85.333-85.333h682.667c47.36 0 85.333 37.973 85.333 85.333v469.333c0 47.36-37.973 85.333-85.333 85.333zM640 768c23.467 0 42.667-19.2 42.667-42.667s-19.2-42.667-42.667-42.667-42.667 19.2-42.667 42.667 19.2 42.667 42.667 42.667zM384 768c23.467 0 42.667-19.2 42.667-42.667s-19.2-42.667-42.667-42.667-42.667 19.2-42.667 42.667 19.2 42.667 42.667 42.667zM853.333 128h-682.667v85.333h682.667v-85.333zM853.333 341.334h-682.667v256h216.747l-88.747-120.747 69.12-49.92 144.213 196.267 144.213-196.267 69.12 49.92-88.747 120.747h216.747v-256z" />
-<glyph unicode="&#xe65c;" d="M128 298.667h768v85.333h-768v-85.333zM128 128h768v85.333h-768v-85.333zM128 469.334h768v85.333h-768v-85.333zM128 725.334v-85.333h768v85.333h-768z" />
-<glyph unicode="&#xe65d;" d="M42.667 42.667h938.667l-469.333 810.667-469.333-810.667zM554.667 170.667h-85.333v85.333h85.333v-85.333zM554.667 341.334h-85.333v170.667h85.333v-170.667z" />
-<glyph unicode="&#xe65e;" d="M554.667 810.667c-212.053 0-384-171.947-384-384h-128l165.973-165.973 2.987-5.973 172.373 171.947h-128c0 165.12 133.547 298.667 298.667 298.667s298.667-133.547 298.667-298.667-133.547-298.667-298.667-298.667c-82.347 0-157.013 33.707-210.773 87.893l-60.587-60.587c69.547-69.547 165.12-112.64 271.36-112.64 212.053 0 384 171.947 384 384s-171.947 384-384 384zM512 597.334v-213.333l182.613-108.373 30.72 51.627-149.333 88.747v181.333h-64z" />
-<glyph unicode="&#xe65f;" d="M512 853.334c-165.12 0-298.667-133.547-298.667-298.667 0-224 298.667-554.667 298.667-554.667s298.667 330.667 298.667 554.667c0 165.12-133.547 298.667-298.667 298.667zM512 448c-58.88 0-106.667 47.787-106.667 106.667s47.787 106.667 106.667 106.667 106.667-47.787 106.667-106.667-47.787-106.667-106.667-106.667z" />
-<glyph unicode="&#xe660;" d="M511.573 853.334c-235.52 0-426.24-191.147-426.24-426.667s190.72-426.667 426.24-426.667c235.947 0 427.093 191.147 427.093 426.667s-191.147 426.667-427.093 426.667zM512 85.334c-188.587 0-341.333 152.747-341.333 341.333s152.747 341.333 341.333 341.333 341.333-152.747 341.333-341.333-152.747-341.333-341.333-341.333zM533.333 640h-64v-256l224-134.4 32 52.48-192 113.92z" />
-<glyph unicode="&#xe661;" d="M661.333 341.334h-33.707l-11.947 11.52c41.813 48.64 66.987 111.787 66.987 180.48 0 153.173-124.16 277.333-277.333 277.333s-277.333-124.16-277.333-277.333 124.16-277.333 277.333-277.333c68.693 0 131.84 25.173 180.48 66.987l11.52-11.947v-33.707l213.333-212.907 63.573 63.573-212.907 213.333zM405.333 341.334c-106.24 0-192 85.76-192 192s85.76 192 192 192 192-85.76 192-192-85.76-192-192-192z" />
-<glyph unicode="&#xe662;" d="M512 512c-46.933 0-85.333-38.4-85.333-85.333s38.4-85.333 85.333-85.333 85.333 38.4 85.333 85.333-38.4 85.333-85.333 85.333zM810.667 810.667h-597.333c-47.36 0-85.333-38.4-85.333-85.333v-597.333c0-46.933 37.973-85.333 85.333-85.333h597.333c47.36 0 85.333 38.4 85.333 85.333v597.333c0 46.933-37.973 85.333-85.333 85.333zM736 426.667c0-9.813-0.853-19.627-2.133-29.013l63.147-49.493c5.547-4.693 7.253-12.8 3.413-19.2l-59.733-103.253c-3.84-6.4-11.52-8.96-18.347-6.4l-74.24 29.867c-15.36-11.947-32.427-21.76-50.347-29.44l-11.093-78.933c-1.28-7.253-7.68-12.8-14.933-12.8h-119.467c-7.253 0-13.653 5.547-14.933 12.373l-11.093 78.933c-18.347 7.68-34.987 17.493-50.347 29.44l-74.24-29.867c-6.827-2.56-14.507 0-18.347 6.4l-59.733 103.253c-3.84 6.4-2.133 14.507 3.413 19.2l63.147 49.493c-1.28 9.813-2.133 19.627-2.133 29.44s0.853 19.627 2.133 29.013l-63.147 49.493c-5.547 4.693-7.253 12.8-3.413 19.2l59.733 103.253c3.84 6.4 11.52 8.96 18.347 6.4l74.24-29.867c15.36 11.947 32.427 21.76 50.347 29.44l11.093 78.933c1.28 7.253 7.68 12.8 14.933 12.8h119.467c7.253 0 13.653-5.547 14.933-12.373l11.093-78.933c18.347-7.68 34.987-17.493 50.347-29.44l74.24 29.867c6.827 2.56 14.507 0 18.347-6.4l59.733-103.253c3.84-6.4 2.133-14.507-3.413-19.2l-63.147-49.493c1.28-9.813 2.133-19.627 2.133-29.44z" />
-<glyph unicode="&#xe663;" d="M597.333 426.667c0 46.933-38.4 85.333-85.333 85.333s-85.333-38.4-85.333-85.333 38.4-85.333 85.333-85.333 85.333 38.4 85.333 85.333zM512 810.667c-212.053 0-384-171.947-384-384h-128l170.667-170.667 170.667 170.667h-128c0 165.12 133.547 298.667 298.667 298.667s298.667-133.547 298.667-298.667-133.547-298.667-298.667-298.667c-64.427 0-124.16 20.907-173.227 55.467l-60.587-61.44c64.853-49.493 145.92-79.36 233.813-79.36 212.053 0 384 171.947 384 384s-171.947 384-384 384z" />
-<glyph unicode="&#xe664;" d="M469.333-85.333h85.333v85.333h-85.333v-85.333zM298.667-85.333h85.333v85.333h-85.333v-85.333zM640-85.333h85.333v85.333h-85.333v-85.333zM755.627 695.040l-243.627 243.627h-42.667v-323.84l-195.84 195.84-60.16-60.16 238.507-238.507-238.507-238.507 60.16-60.16 195.84 195.84v-323.84h42.667l243.627 243.627-183.467 183.040 183.467 183.040zM554.667 775.254l80.213-80.213-80.213-80.213v160.427zM634.88 328.96l-80.213-80.213v160.427l80.213-80.213z" />
-<glyph unicode="&#xe665;" d="M298.667-85.333h85.333v85.333h-85.333v-85.333zM469.333-85.333h85.333v85.333h-85.333v-85.333zM640-85.333h85.333v85.333h-85.333v-85.333zM682.667 938.24l-341.333 0.427c-46.933 0-85.333-38.4-85.333-85.333v-682.667c0-46.933 38.4-85.333 85.333-85.333h341.333c46.933 0 85.333 38.4 85.333 85.333v682.667c0 46.933-38.4 84.907-85.333 84.907zM682.667 256h-341.333v512h341.333v-512z" />
-<glyph unicode="&#xe666;" d="M896 810.667h-768c-46.933 0-85.333-38.4-85.333-85.333v-597.333c0-46.933 38.4-85.333 85.333-85.333h768c46.933 0 85.333 38.4 85.333 85.333v597.333c0 46.933-38.4 85.333-85.333 85.333zM896 127.574h-768v598.187h768v-598.187zM341.333 256h106.667l64-64 64 64h106.667v106.667l64 64-64 64v106.667h-106.667l-64 64-64-64h-106.667v-106.667l-64-64 64-64v-106.667zM512 554.667c70.827 0 128-57.173 128-128s-57.173-128-128-128v256z" />
-<glyph unicode="&#xe667;" d="M331.52 650.24l-65.707 54.613-230.827-278.187 230.827-278.187 65.707 54.613-185.6 223.573 185.6 223.573zM298.667 384h85.333v85.333h-85.333v-85.333zM725.333 469.334h-85.333v-85.333h85.333v85.333zM469.333 384h85.333v85.333h-85.333v-85.333zM758.187 704.854l-65.707-54.613 185.6-223.573-185.6-223.573 65.707-54.613 230.827 278.187-230.827 278.187z" />
-<glyph unicode="&#xe668;" d="M512 725.334c-165.12 0-298.667-133.547-298.667-298.667h85.333c0 117.76 95.573 213.333 213.333 213.333s213.333-95.573 213.333-213.333h85.333c0 165.12-133.547 298.667-298.667 298.667zM554.667 328.96c37.547 16.64 64 53.76 64 97.707 0 58.88-47.787 106.667-106.667 106.667s-106.667-47.787-106.667-106.667c0-43.52 26.453-81.067 64-97.707v-140.8l-145.493-145.493 60.16-60.16 128 128 128-128 60.16 60.16-145.493 145.493v140.8zM512 896c-258.987 0-469.333-210.347-469.333-469.333h85.333c0 212.053 171.947 384 384 384s384-171.947 384-384h85.333c0 258.987-210.347 469.333-469.333 469.333z" />
-<glyph unicode="&#xe669;" d="M213.333 853.334c0 23.467-19.2 42.667-42.667 42.667s-42.667-19.2-42.667-42.667v-170.667h-85.333v-256h256v256h-85.333v170.667zM384 256c0-55.467 35.84-102.4 85.333-120.32v-178.347h85.333v178.347c49.493 17.493 85.333 64.427 85.333 120.32v85.333h-256v-85.333zM42.667 256c0-55.467 35.84-102.4 85.333-120.32v-178.347h85.333v178.347c49.493 17.92 85.333 64.853 85.333 120.32v85.333h-256v-85.333zM896 682.667v170.667c0 23.467-19.2 42.667-42.667 42.667s-42.667-19.2-42.667-42.667v-170.667h-85.333v-256h256v256h-85.333zM554.667 853.334c0 23.467-19.2 42.667-42.667 42.667s-42.667-19.2-42.667-42.667v-170.667h-85.333v-256h256v256h-85.333v170.667zM725.333 256c0-55.467 35.84-102.4 85.333-120.32v-178.347h85.333v178.347c49.493 17.493 85.333 64.427 85.333 120.32v85.333h-256v-85.333z" />
-<glyph unicode="&#xe66a;" d="M213.333 853.334c0 23.467-19.2 42.667-42.667 42.667s-42.667-19.2-42.667-42.667v-170.667h-85.333v-256h256v256h-85.333v170.667zM384 256c0-55.467 35.84-102.4 85.333-120.32v-178.347h85.333v178.347c49.493 17.493 85.333 64.427 85.333 120.32v85.333h-256v-85.333zM42.667 256c0-55.467 35.84-102.4 85.333-120.32v-178.347h85.333v178.347c49.493 17.92 85.333 64.853 85.333 120.32v85.333h-256v-85.333zM896 682.667v170.667c0 23.467-19.2 42.667-42.667 42.667s-42.667-19.2-42.667-42.667v-170.667h-85.333v-256h256v256h-85.333zM554.667 853.334c0 23.467-19.2 42.667-42.667 42.667s-42.667-19.2-42.667-42.667v-170.667h-85.333v-256h256v256h-85.333v170.667zM725.333 256c0-55.467 35.84-102.4 85.333-120.32v-178.347h85.333v178.347c49.493 17.493 85.333 64.427 85.333 120.32v85.333h-256v-85.333z" />
-<glyph unicode="&#xe66b;" d="M768 640v128c0 46.933-38.4 85.333-85.333 85.333h-341.333c-46.933 0-85.333-38.4-85.333-85.333v-128h-42.667v-256l128-256v-128h341.333v128l128 256v256h-42.667zM341.333 768h341.333v-128h-85.333v85.333h-42.667v-85.333h-85.333v85.333h-42.667v-85.333h-85.333v128z" />
-<glyph unicode="&#xe66c;" d="M341.333 448c0 35.413-28.587 64-64 64s-64-28.587-64-64 28.587-64 64-64 64 28.587 64 64zM640 661.334c0 35.413-28.587 64-64 64h-128c-35.413 0-64-28.587-64-64s28.587-64 64-64h128c35.413 0 64 28.587 64 64zM362.667 298.667c-35.413 0-64-28.587-64-64s28.587-64 64-64 64 28.587 64 64-28.587 64-64 64zM512 896c-258.987 0-469.333-210.347-469.333-469.333s210.347-469.333 469.333-469.333 469.333 210.347 469.333 469.333-210.347 469.333-469.333 469.333zM512 42.667c-211.627 0-384 172.373-384 384s172.373 384 384 384 384-172.373 384-384-172.373-384-384-384zM746.667 512c-35.413 0-64-28.587-64-64s28.587-64 64-64 64 28.587 64 64-28.587 64-64 64zM661.333 298.667c-35.413 0-64-28.587-64-64s28.587-64 64-64 64 28.587 64 64-28.587 64-64 64z" />
-<glyph unicode="&#xe66d;" d="M512.427 704l-85.76-106.667h170.667l-84.907 106.667zM768 512v-170.667l106.667 84.907-106.667 85.76zM256 512l-106.667-85.76 106.667-84.907v170.667zM597.333 256h-170.667l85.76-106.667 84.907 106.667zM896 810.667h-768c-46.933 0-85.333-38.4-85.333-85.333v-597.333c0-46.933 38.4-85.333 85.333-85.333h768c46.933 0 85.333 38.4 85.333 85.333v597.333c0 46.933-38.4 85.333-85.333 85.333zM896 127.574h-768v598.187h768v-598.187z" />
-<glyph unicode="&#xe66e;" d="M554.667 554.667h-85.333v-85.333h85.333v85.333zM725.333 554.667h-85.333v-85.333h85.333v85.333zM853.333 277.334c-53.333 0-104.533 8.533-152.32 24.32-14.933 4.693-31.573 1.28-43.52-10.24l-93.867-93.867c-120.747 61.44-219.733 160-281.173 280.747l93.867 94.293c11.947 11.52 15.36 28.16 10.667 43.093-15.787 47.787-24.32 98.987-24.32 152.32 0 23.467-19.2 42.667-42.667 42.667h-149.333c-23.467 0-42.667-19.2-42.667-42.667 0-400.64 324.693-725.333 725.333-725.333 23.467 0 42.667 19.2 42.667 42.667v149.333c0 23.467-19.2 42.667-42.667 42.667zM810.667 554.667v-85.333h85.333v85.333h-85.333z" />
-<glyph unicode="&#xe66f;" d="M298.667-85.333h85.333v85.333h-85.333v-85.333zM469.333-85.333h85.333v85.333h-85.333v-85.333zM554.667 853.334h-85.333v-426.667h85.333v426.667zM706.56 749.227l-61.867-61.867c73.813-44.8 123.307-125.44 123.307-218.027 0-141.227-114.773-256-256-256s-256 114.773-256 256c0 92.587 49.493 173.227 122.88 218.453l-61.44 61.44c-88.747-61.44-146.773-163.84-146.773-279.893 0-188.587 152.747-341.333 341.333-341.333s341.333 152.747 341.333 341.333c0 116.053-58.027 218.453-146.773 279.893zM640-85.333h85.333v85.333h-85.333v-85.333z" />
-<glyph unicode="&#xe670;" d="M640 554.667h-256c-23.467 0-42.667-19.2-42.667-42.667v-512c0-23.467 19.2-42.667 42.667-42.667h256c23.467 0 42.667 19.2 42.667 42.667v512c0 23.467-19.2 42.667-42.667 42.667zM512 298.667c-46.933 0-85.333 38.4-85.333 85.333s38.4 85.333 85.333 85.333 85.333-38.4 85.333-85.333-38.4-85.333-85.333-85.333zM300.8 680.534l60.16-60.16c38.827 38.4 92.16 62.293 151.040 62.293s112.213-23.893 151.040-62.293l60.16 60.16c-54.187 54.187-128.853 87.467-211.2 87.467s-157.013-33.28-211.2-87.467zM512 938.667c-129.707 0-247.040-52.48-331.947-137.387l60.16-60.16c69.547 69.12 165.547 112.213 271.787 112.213s202.24-43.093 271.36-112.64l60.16 60.16c-84.48 85.333-201.813 137.813-331.52 137.813z" />
-<glyph unicode="&#xe671;" d="M298.667-85.333h85.333v85.333h-85.333v-85.333zM512 384c70.827 0 127.573 57.173 127.573 128l0.427 256c0 70.827-57.173 128-128 128s-128-57.173-128-128v-256c0-70.827 57.173-128 128-128zM469.333-85.333h85.333v85.333h-85.333v-85.333zM640-85.333h85.333v85.333h-85.333v-85.333zM810.667 512h-72.533c0-128-108.373-217.6-226.133-217.6s-226.133 89.6-226.133 217.6h-72.533c0-145.493 116.053-265.813 256-286.72v-139.947h85.333v139.947c139.947 20.907 256 141.227 256 286.72z" />
-<glyph unicode="&#xe672;" d="M829.013 384.854c1.707 13.653 2.987 27.307 2.987 41.813s-1.28 28.16-2.987 41.813l90.027 70.4c8.107 6.4 10.24 17.92 5.12 27.307l-85.333 147.627c-5.12 9.387-16.64 12.8-26.027 9.387l-106.24-42.667c-22.187 17.067-46.080 31.147-72.107 41.813l-16.213 113.067c-1.28 10.24-10.24 17.92-20.907 17.92h-170.667c-10.667 0-19.627-7.68-20.907-17.92l-16.213-113.067c-26.027-10.667-49.92-25.173-72.107-41.813l-106.24 42.667c-9.813 3.84-20.907 0-26.027-9.387l-85.333-147.627c-5.547-9.387-2.987-20.907 5.12-27.307l90.027-70.4c-1.707-13.653-2.987-27.733-2.987-41.813s1.28-28.16 2.987-41.813l-90.027-70.4c-8.107-6.4-10.24-17.92-5.12-27.307l85.333-147.627c5.12-9.387 16.64-12.8 26.027-9.387l106.24 42.667c22.187-17.067 46.080-31.147 72.107-41.813l16.213-113.067c1.28-10.24 10.24-17.92 20.907-17.92h170.667c10.667 0 19.627 7.68 20.907 17.92l16.213 113.067c26.027 10.667 49.92 25.173 72.107 41.813l106.24-42.667c9.813-3.84 20.907 0 26.027 9.387l85.333 147.627c5.12 9.387 2.987 20.907-5.12 27.307l-90.027 70.4zM512 277.334c-82.347 0-149.333 66.987-149.333 149.333s66.987 149.333 149.333 149.333 149.333-66.987 149.333-149.333-66.987-149.333-149.333-149.333z" />
-<glyph unicode="&#xe673;" d="M128 554.667h-85.333v-469.333c0-47.36 37.973-85.333 85.333-85.333h597.333c47.36 0 85.333 37.973 85.333 85.333h-682.667v469.333zM768 725.334v85.333c0 47.36-37.973 85.333-85.333 85.333h-170.667c-47.36 0-85.333-37.973-85.333-85.333v-85.333h-213.333v-469.333c0-47.36 37.973-85.333 85.333-85.333h597.333c47.36 0 85.333 37.973 85.333 85.333v469.333h-213.333zM512 810.667h170.667v-85.333h-170.667v85.333zM512 298.667v298.667l234.667-128-234.667-170.667z" />
-<glyph unicode="&#xe674;" d="M682.667 682.667v85.333c0 47.36-37.973 85.333-85.333 85.333h-170.667c-47.36 0-85.333-37.973-85.333-85.333v-85.333h-256v-554.667c0-47.36 37.973-85.333 85.333-85.333h682.667c47.36 0 85.333 37.973 85.333 85.333v554.667h-256zM426.667 768h170.667v-85.333h-170.667v85.333zM384 170.667v384l320-170.667-320-213.333z" />
-<glyph unicode="&#xe675;" d="M734.293 554.667l-186.88 279.893c-8.107 11.947-21.76 17.92-35.413 17.92s-27.307-5.973-35.413-18.347l-186.88-279.467h-204.373c-23.467 0-42.667-19.2-42.667-42.667 0-3.84 0.427-7.68 1.707-11.52l108.373-395.52c9.813-35.84 42.667-62.293 81.92-62.293h554.667c39.253 0 72.107 26.453 82.347 62.293l108.373 395.52 1.28 11.52c0 23.467-19.2 42.667-42.667 42.667h-204.373zM384 554.667l128 187.733 128-187.733h-256zM512 213.334c-46.933 0-85.333 38.4-85.333 85.333s38.4 85.333 85.333 85.333 85.333-38.4 85.333-85.333-38.4-85.333-85.333-85.333z" />
-<glyph unicode="&#xe676;" d="M298.667 170.667c-46.933 0-84.907-38.4-84.907-85.333s37.973-85.333 84.907-85.333 85.333 38.4 85.333 85.333-38.4 85.333-85.333 85.333zM42.667 853.334v-85.333h85.333l153.6-323.84-57.6-104.533c-6.827-11.947-10.667-26.027-10.667-40.96 0-46.933 38.4-85.333 85.333-85.333h512v85.333h-494.080c-5.973 0-10.667 4.693-10.667 10.667l1.28 5.12 38.4 69.547h317.867c32 0 60.16 17.493 74.667 43.947l152.747 276.907c3.413 5.973 5.12 13.227 5.12 20.48 0 23.467-19.2 42.667-42.667 42.667h-631.040l-40.107 85.333h-139.52zM725.333 170.667c-46.933 0-84.907-38.4-84.907-85.333s37.973-85.333 84.907-85.333 85.333 38.4 85.333 85.333-38.4 85.333-85.333 85.333z" />
-<glyph unicode="&#xe677;" d="M853.333 853.334h-682.667c-46.933 0-84.907-38.4-84.907-85.333l-0.427-768 170.667 170.667h597.333c46.933 0 85.333 38.4 85.333 85.333v512c0 46.933-38.4 85.333-85.333 85.333zM341.333 341.334h-85.333v85.333h85.333v-85.333zM341.333 469.334h-85.333v85.333h85.333v-85.333zM341.333 597.334h-85.333v85.333h85.333v-85.333zM640 341.334h-213.333v85.333h213.333v-85.333zM768 469.334h-341.333v85.333h341.333v-85.333zM768 597.334h-341.333v85.333h341.333v-85.333z" />
-<glyph unicode="&#xe678;" d="M531.2 256h89.173l-218.027 554.667h-79.36l-218.027-554.667h89.173l47.787 128h240.64l48.64-128zM274.347 469.334l88.32 235.52 88.32-235.52h-176.64zM921.173 444.16l-345.173-345.173-156.587 157.013-60.16-60.16 217.173-217.173 404.907 405.333-60.16 60.16z" />
-<glyph unicode="&#xe679;" d="M512 328.534l158.293-115.2-60.587 186.027 158.293 112.64h-194.133l-61.867 192-61.867-192h-194.133l158.293-112.64-60.587-186.027z" />
-<glyph unicode="&#xe67a;" d="M511.573 853.334c-235.52 0-426.24-191.147-426.24-426.667s190.72-426.667 426.24-426.667c235.947 0 427.093 191.147 427.093 426.667s-191.147 426.667-427.093 426.667zM692.48 170.667l-180.48 108.8-180.48-108.8 47.787 205.227-159.147 137.813 209.92 17.92 81.92 193.707 81.92-193.28 209.92-17.92-159.147-137.813 47.787-205.653z" />
-<glyph unicode="&#xe67b;" d="M853.333 768h-682.667v-85.333h682.667v85.333zM896 341.334v85.333l-42.667 213.333h-682.667l-42.667-213.333v-85.333h42.667v-256h426.667v256h170.667v-256h85.333v256h42.667zM512 170.667h-256v170.667h256v-170.667z" />
-<glyph unicode="&#xe67c;" d="M597.333 213.334h-426.667v-85.333h426.667v85.333zM853.333 554.667h-682.667v-85.333h682.667v85.333zM170.667 298.667h682.667v85.333h-682.667v-85.333zM170.667 725.334v-85.333h682.667v85.333h-682.667z" />
-<glyph unicode="&#xe67d;" d="M704 426.667c58.88 0 106.24 47.787 106.24 106.667s-47.36 106.667-106.24 106.667c-58.88 0-106.667-47.787-106.667-106.667s47.787-106.667 106.667-106.667zM384 469.334c70.827 0 127.573 57.173 127.573 128s-56.747 128-127.573 128c-70.827 0-128-57.173-128-128s57.173-128 128-128zM704 341.334c-78.080 0-234.667-39.253-234.667-117.333v-96h469.333v96c0 78.080-156.587 117.333-234.667 117.333zM384 384c-99.413 0-298.667-49.92-298.667-149.333v-106.667h298.667v96c0 36.267 14.080 99.84 101.12 148.053-37.12 7.68-72.96 11.947-101.12 11.947z" />
-<glyph unicode="&#xe67e;" d="M298.24 469.334l-170.24-170.667 170.24-170.667v128h299.093v85.333h-299.093v128zM896 554.667l-170.24 170.667v-128h-299.093v-85.333h299.093v-128l170.24 170.667z" />
-<glyph unicode="&#xe67f;" d="M512 853.334c-235.52 0-426.667-191.147-426.667-426.667s191.147-426.667 426.667-426.667 426.667 191.147 426.667 426.667-191.147 426.667-426.667 426.667zM277.333 554.667l149.333 149.333 149.333-149.333h-106.667v-170.667h-85.333v170.667h-106.667zM746.667 298.667l-149.333-149.333-149.333 149.333h106.667v170.667h85.333v-170.667h106.667z" />
-<glyph unicode="&#xe680;" d="M682.667 212.907v299.093h-85.333v-299.093h-128l170.667-170.24 170.667 170.24h-128zM384 810.667l-170.667-170.24h128v-299.093h85.333v299.093h128l-170.667 170.24z" />
-<glyph unicode="&#xe681;" d="M512 234.667l170.667 170.667h-128v384h-85.333v-384h-128l170.667-170.667zM896 789.334h-256v-84.907h256v-598.613h-768v598.613h256v84.907h-256c-46.933 0-85.333-38.4-85.333-85.333v-597.333c0-46.933 38.4-85.333 85.333-85.333h768c46.933 0 85.333 38.4 85.333 85.333v597.333c0 46.933-38.4 85.333-85.333 85.333z" />
-<glyph unicode="&#xe682;" d="M42.667 554.667h85.333v85.333h-85.333v-85.333zM42.667 384h85.333v85.333h-85.333v-85.333zM42.667 725.334h85.333v85.333c-46.933 0-85.333-38.4-85.333-85.333zM384 42.667h85.333v85.333h-85.333v-85.333zM42.667 213.334h85.333v85.333h-85.333v-85.333zM128 42.667v85.333h-85.333c0-46.933 38.4-85.333 85.333-85.333zM896 810.667h-341.333v-256h426.667v170.667c0 46.933-38.4 85.333-85.333 85.333zM896 213.334h85.333v85.333h-85.333v-85.333zM384 725.334h85.333v85.333h-85.333v-85.333zM213.333 42.667h85.333v85.333h-85.333v-85.333zM213.333 725.334h85.333v85.333h-85.333v-85.333zM896 42.667c46.933 0 85.333 38.4 85.333 85.333h-85.333v-85.333zM896 384h85.333v85.333h-85.333v-85.333zM554.667 42.667h85.333v85.333h-85.333v-85.333zM725.333 42.667h85.333v85.333h-85.333v-85.333z" />
-<glyph unicode="&#xe683;" d="M896 810.667h-768c-46.933 0-85.333-38.4-85.333-85.333v-597.333c0-46.933 38.4-85.333 85.333-85.333h768c46.933 0 85.333 38.4 85.333 85.333v597.333c0 46.933-38.4 85.333-85.333 85.333zM896 128h-768v597.333h426.667v-170.667h341.333v-426.667z" />
-<glyph unicode="&#xe684;" d="M768 810.667v-85.333h-85.333v85.333h-341.333v-85.333h-85.333v85.333h-85.333v-768h85.333v85.333h85.333v-85.333h341.333v85.333h85.333v-85.333h85.333v768h-85.333zM341.333 213.334h-85.333v85.333h85.333v-85.333zM341.333 384h-85.333v85.333h85.333v-85.333zM341.333 554.667h-85.333v85.333h85.333v-85.333zM768 213.334h-85.333v85.333h85.333v-85.333zM768 384h-85.333v85.333h85.333v-85.333zM768 554.667h-85.333v85.333h85.333v-85.333z" />
-<glyph unicode="&#xe685;" d="M640 810.667h-384c-35.413 0-65.707-21.333-78.507-52.053l-128.853-300.8c-3.84-9.813-5.973-20.053-5.973-31.147v-81.493l0.427-0.427-0.427-3.413c0-46.933 38.4-85.333 85.333-85.333h269.227l-40.533-194.987-1.28-13.653c0-17.493 7.253-33.707 18.773-45.227l45.227-44.8 281.173 281.173c15.36 15.36 24.747 36.693 24.747 60.16v426.667c0 46.933-38.4 85.333-85.333 85.333zM810.667 810.667v-512h170.667v512h-170.667z" />
-<glyph unicode="&#xe686;" d="M42.667 42.667h170.667v512h-170.667v-512zM981.333 512c0 46.933-38.4 85.333-85.333 85.333h-269.227l40.533 194.987 1.28 13.653c0 17.493-7.253 33.707-18.773 45.227l-45.227 44.8-280.747-281.173c-15.787-15.36-25.173-36.693-25.173-60.16v-426.667c0-46.933 38.4-85.333 85.333-85.333h384c35.413 0 65.707 21.333 78.507 52.053l128.853 300.8c3.84 9.813 5.973 20.053 5.973 31.147v81.493l-0.427 0.427 0.427 3.413z" />
-<glyph unicode="&#xe687;" d="M512 682.667c0 23.467-19.2 42.667-42.667 42.667h-221.013l28.16 135.68 0.853 9.813c0 13.227-5.547 25.173-14.080 34.133l-33.707 33.707-210.773-210.773c-11.52-11.52-18.773-27.733-18.773-45.227v-277.333c0-35.413 28.587-64 64-64h288c26.453 0 49.067 16.213 58.88 38.827l96.427 225.707c2.987 7.253 4.693 15.36 4.693 23.467v53.333zM960 512h-288c-26.453 0-49.067-16.213-58.88-38.827l-96.427-225.707c-2.987-7.253-4.693-15.36-4.693-23.467v-53.333c0-23.467 19.2-42.667 42.667-42.667h221.013l-28.16-135.68-0.853-10.24c0-13.227 5.547-25.173 14.080-34.133l33.707-33.28 210.773 210.773c11.52 11.52 18.773 27.733 18.773 45.227v277.333c0 35.413-28.587 64-64 64z" />
-<glyph unicode="&#xe688;" d="M128 554.667h597.333v85.333h-597.333v-85.333zM128 384h597.333v85.333h-597.333v-85.333zM128 213.334h597.333v85.333h-597.333v-85.333zM810.667 213.334h85.333v85.333h-85.333v-85.333zM810.667 640v-85.333h85.333v85.333h-85.333zM810.667 384h85.333v85.333h-85.333v-85.333z" />
-<glyph unicode="&#xe689;" d="M810.667 810.667h-42.667v85.333h-85.333v-85.333h-341.333v85.333h-85.333v-85.333h-42.667c-47.36 0-84.907-38.4-84.907-85.333l-0.427-597.333c0-46.933 37.973-85.333 85.333-85.333h597.333c46.933 0 85.333 38.4 85.333 85.333v597.333c0 46.933-38.4 85.333-85.333 85.333zM810.667 128h-597.333v469.333h597.333v-469.333zM298.667 512h213.333v-213.333h-213.333z" />
-<glyph unicode="&#xe68a;" d="M813.653 728.32l-60.16-60.16c61.44-61.867 99.84-147.2 99.84-241.493 0-188.587-152.747-341.333-341.333-341.333s-341.333 152.747-341.333 341.333c0 174.080 130.133 317.44 298.667 338.347v-86.187c-121.173-20.48-213.333-125.44-213.333-252.16 0-141.227 114.773-256 256-256s256 114.773 256 256c0 70.827-28.587 134.827-75.093 180.907l-60.16-60.16c30.72-31.147 49.92-73.813 49.92-120.747 0-94.293-76.373-170.667-170.667-170.667s-170.667 76.373-170.667 170.667c0 79.36 54.613 145.493 128 164.693v-91.307c-25.6-14.933-42.667-41.813-42.667-73.387 0-46.933 38.4-85.333 85.333-85.333s85.333 38.4 85.333 85.333c0 31.573-17.067 58.88-42.667 73.387v353.28h-42.667c-235.52 0-426.667-191.147-426.667-426.667s191.147-426.667 426.667-426.667 426.667 191.147 426.667 426.667c0 117.76-47.787 224.427-125.013 301.653z" />
-<glyph unicode="&#xe68b;" d="M549.12 295.68l-108.373 107.093 1.28 1.28c74.24 82.773 127.147 177.92 158.293 278.613h125.013v85.333h-298.667v85.333h-85.333v-85.333h-298.667v-84.907h476.587c-28.587-82.347-73.813-160.427-135.253-228.693-39.68 43.947-72.533 92.16-98.56 142.933h-85.333c31.147-69.547 73.813-135.253 127.147-194.56l-217.173-214.187 60.587-60.587 213.333 213.333 132.693-132.693 32.427 87.040zM789.333 512h-85.333l-192-512h85.333l47.787 128h202.667l48.213-128h85.333l-192 512zM677.547 213.334l69.12 184.747 69.12-184.747h-138.24z" />
-<glyph unicode="&#xe68c;" d="M682.667 170.667l97.707 97.707-208.213 208.213-170.667-170.667-316.16 316.587 60.16 60.16 256-256 170.667 170.667 268.8-268.373 97.707 97.707v-256z" />
-<glyph unicode="&#xe68d;" d="M938.667 426.667l-170.667 170.667v-128h-640v-85.333h640v-128z" />
-<glyph unicode="&#xe68e;" d="M682.667 682.667l97.707-97.707-208.213-208.213-170.667 170.667-316.16-316.587 60.16-60.16 256 256 170.667-170.667 268.8 268.373 97.707-97.707v256z" />
-<glyph unicode="&#xe68f;" d="M725.333 810.667h-426.667c-46.933 0-84.907-38.4-84.907-85.333l-0.427-682.667 298.667 128 298.667-128v682.667c0 46.933-38.4 85.333-85.333 85.333zM725.333 170.667l-213.333 93.013-213.333-93.013v554.667h426.667v-554.667z" />
-<glyph unicode="&#xe690;" d="M725.333 810.667h-426.667c-46.933 0-84.907-38.4-84.907-85.333l-0.427-682.667 298.667 128 298.667-128v682.667c0 46.933-38.4 85.333-85.333 85.333z" />
-<glyph unicode="&#xe691;" d="M512 896l-384-170.667v-256c0-236.8 163.84-458.24 384-512 220.16 53.76 384 275.2 384 512v256l-384 170.667zM426.667 213.334l-170.667 170.667 60.16 60.16 110.507-110.080 281.173 281.173 60.16-60.587-341.333-341.333z" />
-<glyph unicode="&#xe692;" d="M853.333 384h-725.333c-23.467 0-42.667-19.2-42.667-42.667v-256c0-23.467 19.2-42.667 42.667-42.667h725.333c23.467 0 42.667 19.2 42.667 42.667v256c0 23.467-19.2 42.667-42.667 42.667zM853.333 810.667h-725.333c-23.467 0-42.667-19.2-42.667-42.667v-256c0-23.467 19.2-42.667 42.667-42.667h725.333c23.467 0 42.667 19.2 42.667 42.667v256c0 23.467-19.2 42.667-42.667 42.667z" />
-<glyph unicode="&#xe693;" d="M170.667 170.667h128v554.667h-128v-554.667zM768 725.334v-554.667h128v554.667h-128zM341.333 170.667h384v554.667h-384v-554.667z" />
-<glyph unicode="&#xe694;" d="M298.667 128h426.667v640h-426.667v-640zM85.333 213.334h170.667v469.333h-170.667v-469.333zM768 682.667v-469.333h170.667v469.333h-170.667z" />
-<glyph unicode="&#xe695;" d="M426.667 170.667h213.333v554.667h-213.333v-554.667zM170.667 170.667h213.333v554.667h-213.333v-554.667zM682.667 725.334v-554.667h213.333v554.667h-213.333z" />
-<glyph unicode="&#xe696;" d="M85.333 42.667h810.667v128h-810.667v-128zM853.333 597.334h-725.333c-23.467 0-42.667-19.2-42.667-42.667v-256c0-23.467 19.2-42.667 42.667-42.667h725.333c23.467 0 42.667 19.2 42.667 42.667v256c0 23.467-19.2 42.667-42.667 42.667zM85.333 810.667v-128h810.667v128h-810.667z" />
-<glyph unicode="&#xe697;" d="M170.667 298.667h725.333v85.333h-725.333v-85.333zM170.667 128h725.333v85.333h-725.333v-85.333zM170.667 469.334h725.333v85.333h-725.333v-85.333zM170.667 725.334v-85.333h725.333v85.333h-725.333z" />
-<glyph unicode="&#xe698;" d="M170.667 341.334h170.667v170.667h-170.667v-170.667zM170.667 128h170.667v170.667h-170.667v-170.667zM170.667 554.667h170.667v170.667h-170.667v-170.667zM384 341.334h512v170.667h-512v-170.667zM384 128h512v170.667h-512v-170.667zM384 725.334v-170.667h512v170.667h-512z" />
-<glyph unicode="&#xe699;" d="M170.667 469.334h213.333v256h-213.333v-256zM170.667 170.667h213.333v256h-213.333v-256zM426.667 170.667h213.333v256h-213.333v-256zM682.667 170.667h213.333v256h-213.333v-256zM426.667 469.334h213.333v256h-213.333v-256zM682.667 725.334v-256h213.333v256h-213.333z" />
-<glyph unicode="&#xe69a;" d="M426.667 170.667h213.333v256h-213.333v-256zM170.667 170.667h213.333v554.667h-213.333v-554.667zM682.667 170.667h213.333v256h-213.333v-256zM426.667 725.334v-256h469.333v256h-469.333z" />
-<glyph unicode="&#xe69b;" d="M170.667 170.667h725.333v256h-725.333v-256zM170.667 725.334v-256h725.333v256h-725.333z" />
-<glyph unicode="&#xe69c;" d="M256 725.334h-128c-23.467 0-42.667-19.2-42.667-42.667v-512c0-23.467 19.2-42.667 42.667-42.667h128c23.467 0 42.667 19.2 42.667 42.667v512c0 23.467-19.2 42.667-42.667 42.667zM853.333 725.334h-128c-23.467 0-42.667-19.2-42.667-42.667v-512c0-23.467 19.2-42.667 42.667-42.667h128c23.467 0 42.667 19.2 42.667 42.667v512c0 23.467-19.2 42.667-42.667 42.667zM554.667 725.334h-128c-23.467 0-42.667-19.2-42.667-42.667v-512c0-23.467 19.2-42.667 42.667-42.667h128c23.467 0 42.667 19.2 42.667 42.667v512c0 23.467-19.2 42.667-42.667 42.667z" />
-<glyph unicode="&#xe69d;" d="M512 640c117.76 0 213.333-95.573 213.333-213.333 0-27.733-5.547-53.76-15.36-78.080l124.587-124.587c64.427 53.76 115.2 123.307 146.347 202.667-73.813 187.307-256 320-469.333 320-59.733 0-116.907-10.667-169.813-29.867l92.16-92.16c24.32 9.813 50.347 15.36 78.080 15.36zM85.333 756.48l116.907-116.907c-70.827-55.040-126.293-128.427-159.573-212.907 73.813-187.307 256-320 469.333-320 66.133 0 129.28 12.8 186.88 35.84l17.92-17.92 125.013-124.587 54.187 54.187-756.48 756.48-54.187-54.187zM321.28 520.534l66.133-66.133c-2.133-8.96-3.413-18.347-3.413-27.733 0-70.827 57.173-128 128-128 9.387 0 18.773 1.28 27.733 3.413l66.133-66.133c-28.587-14.080-60.16-22.613-93.867-22.613-117.76 0-213.333 95.573-213.333 213.333 0 33.707 8.533 65.28 22.613 93.867zM505.173 553.814l134.4-134.4 0.853 6.827c0 70.827-57.173 128-128 128l-7.253-0.427z" />
-<glyph unicode="&#xe69e;" d="M512 746.667c-213.333 0-395.52-132.693-469.333-320 73.813-187.307 256-320 469.333-320s395.52 132.693 469.333 320c-73.813 187.307-256 320-469.333 320zM512 213.334c-117.76 0-213.333 95.573-213.333 213.333s95.573 213.333 213.333 213.333 213.333-95.573 213.333-213.333-95.573-213.333-213.333-213.333zM512 554.667c-70.827 0-128-57.173-128-128s57.173-128 128-128 128 57.173 128 128-57.173 128-128 128z" />
-<glyph unicode="&#xe69f;" d="M853.333 682.667h-93.013c4.693 13.227 7.68 27.733 7.68 42.667 0 70.827-57.173 128-128 128-44.8 0-83.627-23.040-106.667-57.6l-21.333-28.587-21.333 29.013c-23.040 34.133-61.867 57.173-106.667 57.173-70.827 0-128-57.173-128-128 0-14.933 2.987-29.44 7.68-42.667h-93.013c-47.36 0-84.907-37.973-84.907-85.333l-0.427-469.333c0-47.36 37.973-85.333 85.333-85.333h682.667c47.36 0 85.333 37.973 85.333 85.333v469.333c0 47.36-37.973 85.333-85.333 85.333zM640 768c23.467 0 42.667-19.2 42.667-42.667s-19.2-42.667-42.667-42.667-42.667 19.2-42.667 42.667 19.2 42.667 42.667 42.667zM384 768c23.467 0 42.667-19.2 42.667-42.667s-19.2-42.667-42.667-42.667-42.667 19.2-42.667 42.667 19.2 42.667 42.667 42.667zM853.333 128h-682.667v85.333h682.667v-85.333zM853.333 341.334h-682.667v256h216.747l-88.747-120.747 69.12-49.92 144.213 196.267 144.213-196.267 69.12 49.92-88.747 120.747h216.747v-256z" />
-<glyph unicode="&#xe6a0;" d="M853.333 853.334h-682.667c-47.36 0-85.333-37.973-85.333-85.333v-469.333c0-47.36 37.973-85.333 85.333-85.333h170.667v-213.333l170.667 85.333 170.667-85.333v213.333h170.667c47.36 0 85.333 37.973 85.333 85.333v469.333c0 47.36-37.973 85.333-85.333 85.333zM853.333 298.667h-682.667v85.333h682.667v-85.333zM853.333 512h-682.667v256h682.667v-256z" />
-<glyph unicode="&#xe6a1;" d="M853.333 682.667h-128v85.333c0 47.36-37.973 85.333-85.333 85.333h-256c-47.36 0-85.333-37.973-85.333-85.333v-85.333h-128c-47.36 0-85.333-37.973-85.333-85.333v-469.333c0-47.36 37.973-85.333 85.333-85.333h682.667c47.36 0 85.333 37.973 85.333 85.333v469.333c0 47.36-37.973 85.333-85.333 85.333zM384 768h256v-85.333h-256v85.333zM853.333 128h-682.667v85.333h682.667v-85.333zM853.333 341.334h-682.667v256h128v-85.333h85.333v85.333h256v-85.333h85.333v85.333h128v-256z" />
-<glyph unicode="&#xe6a2;" d="M853.333 682.667h-170.667v85.333c0 47.36-37.973 85.333-85.333 85.333h-170.667c-47.36 0-85.333-37.973-85.333-85.333v-85.333h-170.667c-47.36 0-84.907-37.973-84.907-85.333l-0.427-469.333c0-47.36 37.973-85.333 85.333-85.333h682.667c47.36 0 85.333 37.973 85.333 85.333v469.333c0 47.36-37.973 85.333-85.333 85.333zM597.333 682.667h-170.667v85.333h170.667v-85.333z" />
-<glyph unicode="&#xe6a3;" d="M512 853.334c-235.52 0-426.667-191.147-426.667-426.667s191.147-426.667 426.667-426.667 426.667 191.147 426.667 426.667-191.147 426.667-426.667 426.667zM554.667 213.334h-85.333v85.333h85.333v-85.333zM554.667 384h-85.333v256h85.333v-256z" />
-<glyph unicode="&#xe6a4;" d="M42.667 42.667h938.667l-469.333 810.667-469.333-810.667zM554.667 170.667h-85.333v85.333h85.333v-85.333zM554.667 341.334h-85.333v170.667h85.333v-170.667z" />
-<glyph unicode="&#xe6a5;" d="M512 853.334c-235.52 0-426.667-191.147-426.667-426.667s191.147-426.667 426.667-426.667 426.667 191.147 426.667 426.667-191.147 426.667-426.667 426.667zM512 234.667c-106.24 0-192 85.76-192 192s85.76 192 192 192 192-85.76 192-192-85.76-192-192-192zM512 469.334c-23.467 0-42.667-19.2-42.667-42.667s19.2-42.667 42.667-42.667 42.667 19.2 42.667 42.667-19.2 42.667-42.667 42.667z" />
-<glyph unicode="&#xe6a6;" d="M810.667 768h-597.333c-47.36 0-85.333-38.4-85.333-85.333v-512c0-46.933 37.973-85.333 85.333-85.333h597.333c46.933 0 85.333 38.4 85.333 85.333v512c0 46.933-38.4 85.333-85.333 85.333zM469.333 469.334h-64v21.333h-85.333v-128h85.333v21.333h64v-42.667c0-23.467-19.2-42.667-42.667-42.667h-128c-23.467 0-42.667 19.2-42.667 42.667v170.667c0 23.467 19.2 42.667 42.667 42.667h128c23.467 0 42.667-19.2 42.667-42.667v-42.667zM768 469.334h-64v21.333h-85.333v-128h85.333v21.333h64v-42.667c0-23.467-19.2-42.667-42.667-42.667h-128c-23.467 0-42.667 19.2-42.667 42.667v170.667c0 23.467 19.2 42.667 42.667 42.667h128c23.467 0 42.667-19.2 42.667-42.667v-42.667z" />
-<glyph unicode="&#xe6a7;" d="M426.667 85.334h170.667v682.667h-170.667v-682.667zM170.667 85.334h170.667v341.333h-170.667v-341.333zM682.667 554.667v-469.333h170.667v469.333h-170.667z" />
-<glyph unicode="&#xe6a8;" d="M810.667 810.667h-597.333c-46.933 0-85.333-38.4-85.333-85.333v-597.333c0-46.933 38.4-85.333 85.333-85.333h597.333c46.933 0 85.333 38.4 85.333 85.333v597.333c0 46.933-38.4 85.333-85.333 85.333zM640 554.667h-170.667v-85.333h170.667v-85.333h-170.667v-85.333h170.667v-85.333h-256v426.667h256v-85.333z" />
-<glyph unicode="&#xe6a9;" d="M170.667 170.667l362.667 256-362.667 256v-512zM554.667 682.667v-512l362.667 256-362.667 256z" />
-<glyph unicode="&#xe6aa;" d="M469.333 170.667v512l-362.667-256 362.667-256zM490.667 426.667l362.667-256v512l-362.667-256z" />
-<glyph unicode="&#xe6ab;" d="M640 618.667v234.667h-256v-234.667l128-128 128 128zM320 554.667h-234.667v-256h234.667l128 128-128 128zM384 234.667v-234.667h256v234.667l-128 128-128-128zM704 554.667l-128-128 128-128h234.667v256h-234.667z" />
-<glyph unicode="&#xe6ac;" d="M725.333 85.334c-12.373 0-23.893 2.56-32.427 6.4-30.293 15.787-51.627 37.547-72.96 101.547-21.76 66.56-62.72 97.707-101.973 128-33.707 26.027-68.693 52.907-98.987 107.947-22.613 40.96-34.987 85.76-34.987 125.44 0 119.467 93.867 213.333 213.333 213.333s213.333-93.867 213.333-213.333h85.333c0 167.68-130.987 298.667-298.667 298.667s-298.667-130.987-298.667-298.667c0-53.76 16.213-113.067 45.653-166.4 38.827-70.4 84.48-105.813 121.6-134.4 34.56-26.453 59.307-45.653 72.96-87.467 25.6-77.653 58.453-121.173 116.48-151.467 21.76-9.813 45.653-14.933 69.973-14.933 94.293 0 170.667 76.373 170.667 170.667h-85.333c0-46.933-38.4-85.333-85.333-85.333zM325.973 826.027l-60.587 60.587c-84.907-84.907-137.387-202.24-137.387-331.947s52.48-247.040 137.387-331.947l60.16 60.16c-69.12 69.547-112.213 165.547-112.213 271.787s43.093 202.24 112.64 271.36zM490.667 554.667c0-58.88 47.787-106.667 106.667-106.667s106.667 47.787 106.667 106.667-47.787 106.667-106.667 106.667-106.667-47.787-106.667-106.667z" />
-<glyph unicode="&#xe6ad;" d="M810.667 768h-597.333c-47.36 0-85.333-38.4-85.333-85.333v-512c0-46.933 37.973-85.333 85.333-85.333h597.333c46.933 0 85.333 38.4 85.333 85.333v512c0 46.933-38.4 85.333-85.333 85.333zM469.333 298.667h-64v85.333h-85.333v-85.333h-64v256h64v-106.667h85.333v106.667h64v-256zM768 341.334c0-23.467-19.2-42.667-42.667-42.667h-32v-64h-64v64h-32c-23.467 0-42.667 19.2-42.667 42.667v170.667c0 23.467 19.2 42.667 42.667 42.667h128c23.467 0 42.667-19.2 42.667-42.667v-170.667zM618.667 362.667h85.333v128h-85.333v-128z" />
-<glyph unicode="&#xe6ae;" d="M512 768v128l-170.667-170.667 170.667-170.667v128c141.227 0 256-114.773 256-256 0-43.093-10.667-84.053-29.867-119.467l62.293-62.293c33.28 52.48 52.907 114.773 52.907 181.76 0 188.587-152.747 341.333-341.333 341.333zM512 170.667c-141.227 0-256 114.773-256 256 0 43.093 10.667 84.053 29.867 119.467l-62.293 62.293c-33.28-52.48-52.907-114.773-52.907-181.76 0-188.587 152.747-341.333 341.333-341.333v-128l170.667 170.667-170.667 170.667v-128z" />
-<glyph unicode="&#xe6af;" d="M512 341.334c70.827 0 127.573 57.173 127.573 128l0.427 256c0 70.827-57.173 128-128 128s-128-57.173-128-128v-256c0-70.827 57.173-128 128-128zM460.8 729.6c0 28.16 23.040 51.2 51.2 51.2s51.2-23.040 51.2-51.2l-0.427-264.533c0-28.16-22.613-51.2-50.773-51.2s-51.2 23.040-51.2 51.2v264.533zM738.133 469.334c0-128-108.373-217.6-226.133-217.6s-226.133 89.6-226.133 217.6h-72.533c0-145.493 116.053-265.813 256-286.72v-139.947h85.333v139.947c139.947 20.48 256 140.8 256 286.72h-72.533z" />
-<glyph unicode="&#xe6b0;" d="M810.667 469.334h-72.533c0-31.573-6.827-61.013-18.347-87.467l52.48-52.48c23.893 41.813 38.4 89.173 38.4 139.947zM639.147 462.080c0 2.56 0.853 4.693 0.853 7.253v256c0 70.827-57.173 128-128 128s-128-57.173-128-128v-7.68l255.147-255.573zM182.187 810.667l-54.187-54.187 256.427-256.427v-30.72c0-70.827 56.747-128 127.573-128 9.387 0 18.773 1.28 27.733 3.413l70.827-70.827c-30.293-14.080-64-22.187-98.56-22.187-117.76 0-226.133 89.6-226.133 217.6h-72.533c0-145.493 116.053-265.813 256-286.72v-139.947h85.333v139.947c38.827 5.547 75.52 19.2 108.373 38.4l178.773-178.347 54.187 54.187-713.813 713.813z" />
-<glyph unicode="&#xe6b1;" d="M512 341.334c70.827 0 127.573 57.173 127.573 128l0.427 256c0 70.827-57.173 128-128 128s-128-57.173-128-128v-256c0-70.827 57.173-128 128-128zM738.133 469.334c0-128-108.373-217.6-226.133-217.6s-226.133 89.6-226.133 217.6h-72.533c0-145.493 116.053-265.813 256-286.72v-139.947h85.333v139.947c139.947 20.48 256 140.8 256 286.72h-72.533z" />
-<glyph unicode="&#xe6b2;" d="M768 768l85.333-170.667h-128l-85.333 170.667h-85.333l85.333-170.667h-128l-85.333 170.667h-85.333l85.333-170.667h-128l-85.333 170.667h-42.667c-46.933 0-84.907-38.4-84.907-85.333l-0.427-512c0-46.933 38.4-85.333 85.333-85.333h682.667c46.933 0 85.333 38.4 85.333 85.333v597.333h-170.667z" />
-<glyph unicode="&#xe6b3;" d="M170.667 682.667h-85.333v-597.333c0-46.933 38.4-85.333 85.333-85.333h597.333v85.333h-597.333v597.333zM853.333 853.334h-512c-46.933 0-85.333-38.4-85.333-85.333v-512c0-46.933 38.4-85.333 85.333-85.333h512c46.933 0 85.333 38.4 85.333 85.333v512c0 46.933-38.4 85.333-85.333 85.333zM810.667 469.334h-170.667v-170.667h-85.333v170.667h-170.667v85.333h170.667v170.667h85.333v-170.667h170.667v-85.333z" />
-<glyph unicode="&#xe6b4;" d="M170.667 682.667h-85.333v-597.333c0-46.933 38.4-85.333 85.333-85.333h597.333v85.333h-597.333v597.333zM853.333 853.334h-512c-46.933 0-85.333-38.4-85.333-85.333v-512c0-46.933 38.4-85.333 85.333-85.333h512c46.933 0 85.333 38.4 85.333 85.333v512c0 46.933-38.4 85.333-85.333 85.333zM810.667 469.334h-426.667v85.333h426.667v-85.333zM640 298.667h-256v85.333h256v-85.333zM810.667 640h-426.667v85.333h426.667v-85.333z" />
-<glyph unicode="&#xe6b5;" d="M853.333 853.334h-512c-46.933 0-85.333-38.4-85.333-85.333v-512c0-46.933 38.4-85.333 85.333-85.333h512c46.933 0 85.333 38.4 85.333 85.333v512c0 46.933-38.4 85.333-85.333 85.333zM768 640h-128v-234.667c0-58.88-47.787-106.667-106.667-106.667s-106.667 47.787-106.667 106.667 47.787 106.667 106.667 106.667c24.32 0 46.080-8.107 64-21.76v235.093h170.667v-85.333zM170.667 682.667h-85.333v-597.333c0-46.933 38.4-85.333 85.333-85.333h597.333v85.333h-597.333v597.333z" />
-<glyph unicode="&#xe6b6;" d="M981.333 426.667l-104.107 118.613 14.507 157.013-154.027 34.987-80.64 135.68-145.067-62.293-145.067 62.293-80.64-135.68-154.027-34.56 14.507-157.013-104.107-119.040 104.107-118.613-14.507-157.44 154.027-34.987 80.64-135.68 145.067 62.72 145.067-62.293 80.64 135.68 154.027 34.987-14.507 157.013 104.107 118.613zM554.667 213.334h-85.333v85.333h85.333v-85.333zM554.667 384h-85.333v256h85.333v-256z" />
-<glyph unicode="&#xe6b7;" d="M512 853.334c-235.52 0-426.667-191.147-426.667-426.667s191.147-426.667 426.667-426.667 426.667 191.147 426.667 426.667-191.147 426.667-426.667 426.667zM512 85.334c-188.587 0-341.333 152.747-341.333 341.333 0 78.933 26.88 151.467 72.107 209.067l478.293-478.293c-57.6-45.227-130.133-72.107-209.067-72.107zM781.227 217.6l-478.293 478.293c57.6 45.227 130.133 72.107 209.067 72.107 188.587 0 341.333-152.747 341.333-341.333 0-78.933-26.88-151.467-72.107-209.067z" />
-<glyph unicode="&#xe6b8;" d="M512 853.334c-235.52 0-426.667-191.147-426.667-426.667s191.147-426.667 426.667-426.667 426.667 191.147 426.667 426.667-191.147 426.667-426.667 426.667zM469.333 256h-85.333v341.333h85.333v-341.333zM640 256h-85.333v341.333h85.333v-341.333z" />
-<glyph unicode="&#xe6b9;" d="M384 256h85.333v341.333h-85.333v-341.333zM512 853.334c-235.52 0-426.667-191.147-426.667-426.667s191.147-426.667 426.667-426.667 426.667 191.147 426.667 426.667-191.147 426.667-426.667 426.667zM512 85.334c-188.16 0-341.333 153.173-341.333 341.333s153.173 341.333 341.333 341.333 341.333-153.173 341.333-341.333-153.173-341.333-341.333-341.333zM554.667 256h85.333v341.333h-85.333v-341.333z" />
-<glyph unicode="&#xe6ba;" d="M256 128h170.667v597.333h-170.667v-597.333zM597.333 725.334v-597.333h170.667v597.333h-170.667z" />
-<glyph unicode="&#xe6bb;" d="M341.333 725.334v-597.333l469.333 298.667z" />
-<glyph unicode="&#xe6bc;" d="M512 853.334c-235.52 0-426.667-191.147-426.667-426.667s191.147-426.667 426.667-426.667 426.667 191.147 426.667 426.667-191.147 426.667-426.667 426.667zM426.667 234.667v384l256-192-256-192z" />
-<glyph unicode="&#xe6bd;" d="M426.667 234.667l256 192-256 192v-384zM512 853.334c-235.52 0-426.667-191.147-426.667-426.667s191.147-426.667 426.667-426.667 426.667 191.147 426.667 426.667-191.147 426.667-426.667 426.667zM512 85.334c-188.16 0-341.333 153.173-341.333 341.333s153.173 341.333 341.333 341.333 341.333-153.173 341.333-341.333-153.173-341.333-341.333-341.333z" />
-<glyph unicode="&#xe6be;" d="M682.667 682.667v85.333c0 47.36-37.973 85.333-85.333 85.333h-170.667c-47.36 0-85.333-37.973-85.333-85.333v-85.333h-256v-554.667c0-47.36 37.973-85.333 85.333-85.333h682.667c47.36 0 85.333 37.973 85.333 85.333v554.667h-256zM426.667 768h170.667v-85.333h-170.667v85.333zM384 170.667v384l320-170.667-320-213.333z" />
-<glyph unicode="&#xe6bf;" d="M597.333 512h-512v-85.333h512v85.333zM597.333 682.667h-512v-85.333h512v85.333zM768 341.334v170.667h-85.333v-170.667h-170.667v-85.333h170.667v-170.667h85.333v170.667h170.667v85.333h-170.667zM85.333 256h341.333v85.333h-341.333v-85.333z" />
-<glyph unicode="&#xe6c0;" d="M640 682.667h-512v-85.333h512v85.333zM640 512h-512v-85.333h512v85.333zM128 256h341.333v85.333h-341.333v-85.333zM725.333 682.667v-349.013c-13.227 4.693-27.733 7.68-42.667 7.68-70.827 0-128-57.173-128-128s57.173-128 128-128 128 57.173 128 128v384h128v85.333h-213.333z" />
-<glyph unicode="&#xe6c1;" d="M170.667 682.667h-85.333v-597.333c0-46.933 38.4-85.333 85.333-85.333h597.333v85.333h-597.333v597.333zM853.333 853.334h-512c-46.933 0-85.333-38.4-85.333-85.333v-512c0-46.933 38.4-85.333 85.333-85.333h512c46.933 0 85.333 38.4 85.333 85.333v512c0 46.933-38.4 85.333-85.333 85.333zM810.667 469.334h-170.667v-170.667h-85.333v170.667h-170.667v85.333h170.667v170.667h85.333v-170.667h170.667v-85.333z" />
-<glyph unicode="&#xe6c2;" d="M138.24 676.267c-31.147-11.947-52.907-43.52-52.907-78.933v-512c0-46.933 37.973-85.333 85.333-85.333h682.667c47.36 0 85.333 38.4 85.333 85.333v512c0 47.36-37.973 85.333-85.333 85.333h-499.2l352.427 142.507-29.013 70.827-539.307-219.733zM298.667 85.334c-70.827 0-128 57.173-128 128s57.173 128 128 128 128-57.173 128-128-57.173-128-128-128zM853.333 426.667h-85.333v85.333h-85.333v-85.333h-512v170.667h682.667v-170.667z" />
-<glyph unicode="&#xe6c3;" d="M896 725.334v-597.333h85.333v597.333h-85.333zM725.333 128h85.333v597.333h-85.333v-597.333zM597.333 725.334h-512c-23.467 0-42.667-19.2-42.667-42.667v-512c0-23.467 19.2-42.667 42.667-42.667h512c23.467 0 42.667 19.2 42.667 42.667v512c0 23.467-19.2 42.667-42.667 42.667zM341.333 608c52.907 0 96-43.093 96-96s-43.093-96-96-96-96 43.093-96 96 43.093 96 96 96zM533.333 213.334h-384v32c0 64 128 96 192 96s192-32 192-96v-32z" />
-<glyph unicode="&#xe6c4;" d="M298.667 640h426.667v-128l170.667 170.667-170.667 170.667v-128h-512v-256h85.333v170.667zM725.333 213.334h-426.667v128l-170.667-170.667 170.667-170.667v128h512v256h-85.333v-170.667zM554.667 298.667v256h-42.667l-85.333-42.667v-42.667h64v-170.667h64z" />
-<glyph unicode="&#xe6c5;" d="M298.667 640h426.667v-128l170.667 170.667-170.667 170.667v-128h-512v-256h85.333v170.667zM725.333 213.334h-426.667v128l-170.667-170.667 170.667-170.667v128h512v256h-85.333v-170.667z" />
-<glyph unicode="&#xe6c6;" d="M512 725.334v170.667l-213.333-213.333 213.333-213.333v170.667c141.227 0 256-114.773 256-256s-114.773-256-256-256-256 114.773-256 256h-85.333c0-188.587 152.747-341.333 341.333-341.333s341.333 152.747 341.333 341.333-152.747 341.333-341.333 341.333z" />
-<glyph unicode="&#xe6c7;" d="M451.84 547.414l-221.013 220.587-60.16-60.16 220.587-220.587 60.587 60.16zM618.667 768l87.040-87.040-535.040-535.467 60.16-60.16 535.467 535.040 87.040-87.040v234.667h-234.667zM632.747 366.507l-60.16-60.16 133.547-133.547-87.467-87.467h234.667v234.667l-87.040-87.040-133.547 133.547z" />
-<glyph unicode="&#xe6c8;" d="M256 170.667l362.667 256-362.667 256v-512zM682.667 682.667v-512h85.333v512h-85.333z" />
-<glyph unicode="&#xe6c9;" d="M256 682.667h85.333v-512h-85.333zM405.333 426.667l362.667-256v512z" />
-<glyph unicode="&#xe6ca;" d="M336.213 794.027l-54.613 65.28-196.267-164.267 55.040-65.28 195.84 164.267zM938.667 694.614l-196.267 164.693-55.040-65.28 196.267-164.693 55.040 65.28zM512 768c-212.053 0-384-171.947-384-384s171.52-384 384-384c212.053 0 384 171.947 384 384s-171.947 384-384 384zM512 85.334c-165.12 0-298.667 133.547-298.667 298.667s133.547 298.667 298.667 298.667 298.667-133.547 298.667-298.667-133.547-298.667-298.667-298.667zM384 469.334h154.88l-154.88-179.2v-76.8h256v85.333h-154.88l154.88 179.2v76.8h-256v-85.333z" />
-<glyph unicode="&#xe6cb;" d="M256 682.667h512v-512h-512z" />
-<glyph unicode="&#xe6cc;" d="M853.333 768h-682.667c-46.933 0-85.333-38.4-85.333-85.333v-512c0-46.933 38.4-85.333 85.333-85.333h682.667c46.933 0 85.333 38.4 85.333 85.333v512c0 46.933-38.4 85.333-85.333 85.333zM170.667 426.667h170.667v-85.333h-170.667v85.333zM597.333 170.667h-426.667v85.333h426.667v-85.333zM853.333 170.667h-170.667v85.333h170.667v-85.333zM853.333 341.334h-426.667v85.333h426.667v-85.333z" />
-<glyph unicode="&#xe6cd;" d="M853.333 768h-682.667c-46.933 0-85.333-38.4-85.333-85.333v-512c0-46.933 38.4-85.333 85.333-85.333h682.667c46.933 0 85.333 38.4 85.333 85.333v512c0 46.933-38.4 85.333-85.333 85.333zM331.093 245.76l-60.16-60.16c-66.987 66.133-100.267 153.6-100.267 241.067s33.28 174.933 99.84 241.493l60.16-60.16c-49.493-50.347-74.667-115.627-74.667-181.333s25.173-130.987 75.093-180.907zM512 256c-94.293 0-170.667 76.373-170.667 170.667s76.373 170.667 170.667 170.667 170.667-76.373 170.667-170.667-76.373-170.667-170.667-170.667zM753.493 185.174l-60.16 60.16c49.493 50.347 74.667 115.627 74.667 181.333s-25.173 130.987-75.093 180.907l60.16 60.16c66.987-66.133 100.267-153.6 100.267-241.067s-33.28-174.933-99.84-241.493zM512 512c-46.933 0-85.333-38.4-85.333-85.333s38.4-85.333 85.333-85.333 85.333 38.4 85.333 85.333-38.4 85.333-85.333 85.333z" />
-<glyph unicode="&#xe6ce;" d="M469.333 213.334c0-23.467 19.2-42.667 42.667-42.667s42.667 19.2 42.667 42.667-19.2 42.667-42.667 42.667-42.667-19.2-42.667-42.667zM469.333 810.667v-170.667h85.333v81.92c144.64-20.907 256-144.64 256-295.253 0-165.12-133.547-298.667-298.667-298.667s-298.667 133.547-298.667 298.667c0 71.68 25.173 137.387 67.413 188.587l231.253-231.253 60.16 60.16-290.133 290.133v-0.853c-93.44-69.973-154.027-180.907-154.027-306.773 0-212.053 171.52-384 384-384 212.053 0 384 171.947 384 384s-171.947 384-384 384h-42.667zM768 426.667c0 23.467-19.2 42.667-42.667 42.667s-42.667-19.2-42.667-42.667 19.2-42.667 42.667-42.667 42.667 19.2 42.667 42.667zM256 426.667c0-23.467 19.2-42.667 42.667-42.667s42.667 19.2 42.667 42.667-19.2 42.667-42.667 42.667-42.667-19.2-42.667-42.667z" />
-<glyph unicode="&#xe6cf;" d="M170.667 682.667h-85.333v-597.333c0-46.933 38.4-85.333 85.333-85.333h597.333v85.333h-597.333v597.333zM853.333 853.334h-512c-46.933 0-85.333-38.4-85.333-85.333v-512c0-46.933 38.4-85.333 85.333-85.333h512c46.933 0 85.333 38.4 85.333 85.333v512c0 46.933-38.4 85.333-85.333 85.333zM512 320v384l256-192-256-192z" />
-<glyph unicode="&#xe6d0;" d="M896 661.334l-170.667-170.667v149.333c0 23.467-19.2 42.667-42.667 42.667h-263.68l477.013-477.013v455.68zM139.52 853.334l-54.187-54.187 116.48-116.48h-31.147c-23.467 0-42.667-19.2-42.667-42.667v-426.667c0-23.467 19.2-42.667 42.667-42.667h512c8.96 0 16.64 3.413 23.040 7.68l136.107-135.68 54.187 54.187-756.48 756.48z" />
-<glyph unicode="&#xe6d1;" d="M725.333 490.667v149.333c0 23.467-19.2 42.667-42.667 42.667h-512c-23.467 0-42.667-19.2-42.667-42.667v-426.667c0-23.467 19.2-42.667 42.667-42.667h512c23.467 0 42.667 19.2 42.667 42.667v149.333l170.667-170.667v469.333l-170.667-170.667z" />
-<glyph unicode="&#xe6d2;" d="M789.333 426.667c0 75.52-43.52 140.373-106.667 171.947v-343.467c63.147 31.147 106.667 96 106.667 171.52zM213.333 554.667v-256h170.667l213.333-213.333v682.667l-213.333-213.333h-170.667z" />
-<glyph unicode="&#xe6d3;" d="M298.667 554.667v-256h170.667l213.333-213.333v682.667l-213.333-213.333h-170.667z" />
-<glyph unicode="&#xe6d4;" d="M704 426.667c0 75.52-43.52 140.373-106.667 171.947v-94.293l104.533-104.533c1.28 8.533 2.133 17.493 2.133 26.88zM810.667 426.667c0-40.107-8.533-77.653-23.040-112.64l64.427-64.427c28.16 52.907 43.947 113.067 43.947 177.067 0 182.613-127.573 335.36-298.667 374.187v-87.893c123.307-36.693 213.333-151.040 213.333-286.293zM182.187 810.667l-54.187-54.187 201.813-201.813h-201.813v-256h170.667l213.333-213.333v287.147l181.333-181.333c-28.587-22.187-60.587-39.68-96-50.347v-87.893c58.88 13.227 112.213 40.533 157.44 77.227l87.040-87.467 54.187 54.187-713.813 713.813zM512 768l-89.173-89.173 89.173-89.173v178.347z" />
-<glyph unicode="&#xe6d5;" d="M128 554.667v-256h170.667l213.333-213.333v682.667l-213.333-213.333h-170.667zM704 426.667c0 75.52-43.52 140.373-106.667 171.947v-343.467c63.147 31.147 106.667 96 106.667 171.52zM597.333 800.854v-87.893c123.307-36.693 213.333-151.040 213.333-286.293s-90.027-249.6-213.333-286.293v-87.893c171.093 38.827 298.667 191.573 298.667 374.187s-127.573 335.36-298.667 374.187z" />
-<glyph unicode="&#xe6d6;" d="M853.333 768h-682.667c-46.933 0-84.907-38.4-84.907-85.333l-0.427-512c0-46.933 38.4-85.333 85.333-85.333h682.667c46.933 0 85.333 38.4 85.333 85.333v512c0 46.933-38.4 85.333-85.333 85.333zM640 170.667h-469.333v170.667h469.333v-170.667zM640 384h-469.333v170.667h469.333v-170.667zM853.333 170.667h-170.667v384h170.667v-384z" />
-<glyph unicode="&#xe6d7;" d="M512 640v170.667h-426.667v-768h853.333v597.333h-426.667zM256 128h-85.333v85.333h85.333v-85.333zM256 298.667h-85.333v85.333h85.333v-85.333zM256 469.334h-85.333v85.333h85.333v-85.333zM256 640h-85.333v85.333h85.333v-85.333zM426.667 128h-85.333v85.333h85.333v-85.333zM426.667 298.667h-85.333v85.333h85.333v-85.333zM426.667 469.334h-85.333v85.333h85.333v-85.333zM426.667 640h-85.333v85.333h85.333v-85.333zM853.333 128h-341.333v85.333h85.333v85.333h-85.333v85.333h85.333v85.333h-85.333v85.333h341.333v-426.667zM768 469.334h-85.333v-85.333h85.333v85.333zM768 298.667h-85.333v-85.333h85.333v85.333z" />
-<glyph unicode="&#xe6d8;" d="M512 554.667c-68.267 0-134.4-10.667-196.267-30.72v-132.267c0-16.64-9.813-31.573-23.893-38.4-41.813-20.907-79.787-47.787-113.493-78.933-7.68-7.68-18.347-11.947-29.867-11.947-11.947 0-22.613 4.693-30.293 12.373l-105.813 105.813c-7.68 7.253-12.373 17.92-12.373 29.867s4.693 22.613 12.373 30.293c130.133 123.307 305.92 199.253 499.627 199.253s369.493-75.947 499.627-199.253c7.68-7.68 12.373-18.347 12.373-30.293s-4.693-22.613-12.373-30.293l-105.813-105.813c-7.68-7.68-18.347-12.373-30.293-12.373-11.52 0-22.187 4.693-29.867 11.947-33.707 31.573-72.107 58.027-113.92 78.933-14.080 6.827-23.893 21.333-23.893 38.4v132.267c-61.44 20.48-127.573 31.147-195.84 31.147z" />
-<glyph unicode="&#xe6d9;" d="M384 725.334v-85.333h281.173l-494.507-494.507 60.16-60.16 494.507 494.507v-281.173h85.333v426.667z" />
-<glyph unicode="&#xe6da;" d="M725.333 67.84l60.16 60.16-145.493 145.493-60.16-60.16 145.493-145.493zM320 597.334h149.333v-238.507l-230.827-230.827 60.16-60.16 256 256v273.493h149.333l-192 192-192-192z" />
-<glyph unicode="&#xe6db;" d="M835.84 640l-323.84-323.84-238.507 238.507h195.84v85.333h-341.333v-341.333h85.333v195.84l298.667-298.667 384 384z" />
-<glyph unicode="&#xe6dc;" d="M853.333 707.84l-60.16 60.16-494.507-494.507v281.173h-85.333v-426.667h426.667v85.333h-281.173z" />
-<glyph unicode="&#xe6dd;" d="M597.333 768l97.707-97.707-122.88-122.88 60.587-60.587 122.88 122.88 97.707-97.707v256zM426.667 768h-256v-256l97.707 97.707 200.96-200.533v-323.84h85.333v358.827l-225.707 226.133z" />
-<glyph unicode="&#xe6de;" d="M282.453 478.294c61.44-120.747 160.427-219.307 281.173-281.173l93.867 93.867c11.52 11.52 28.587 15.36 43.52 10.24 47.787-15.787 99.413-24.32 152.32-24.32 23.467 0 42.667-19.2 42.667-42.667v-148.907c0-23.467-19.2-42.667-42.667-42.667-400.64 0-725.333 324.693-725.333 725.333 0 23.467 19.2 42.667 42.667 42.667h149.333c23.467 0 42.667-19.2 42.667-42.667 0-53.333 8.533-104.533 24.32-152.32 4.693-14.933 1.28-31.573-10.667-43.52l-93.867-93.867z" />
-<glyph unicode="&#xe6df;" d="M853.333 853.334h-682.667c-46.933 0-84.907-38.4-84.907-85.333l-0.427-768 170.667 170.667h597.333c46.933 0 85.333 38.4 85.333 85.333v512c0 46.933-38.4 85.333-85.333 85.333zM256 554.667h512v-85.333h-512v85.333zM597.333 341.334h-341.333v85.333h341.333v-85.333zM768 597.334h-512v85.333h512v-85.333z" />
-<glyph unicode="&#xe6e0;" d="M213.333 384h597.333v85.333h-597.333v-85.333zM128 213.334h597.333v85.333h-597.333v-85.333zM298.667 640v-85.333h597.333v85.333h-597.333z" />
-<glyph unicode="&#xe6e1;" d="M938.24 768c0 46.933-37.973 85.333-84.907 85.333h-682.667c-46.933 0-85.333-38.4-85.333-85.333v-512c0-46.933 38.4-85.333 85.333-85.333h597.333l170.667-170.667-0.427 768zM768 341.334h-512v85.333h512v-85.333zM768 469.334h-512v85.333h512v-85.333zM768 597.334h-512v85.333h512v-85.333z" />
-<glyph unicode="&#xe6e2;" d="M853.333 938.667h-682.667v-85.333h682.667v85.333zM170.667-85.333h682.667v85.333h-682.667v-85.333zM853.333 768h-682.667c-46.933 0-85.333-38.4-85.333-85.333v-512c0-46.933 38.4-85.333 85.333-85.333h682.667c46.933 0 85.333 38.4 85.333 85.333v512c0 46.933-38.4 85.333-85.333 85.333zM512 650.667c52.907 0 96-43.093 96-96s-43.093-96-96-96-96 43.093-96 96 43.093 96 96 96zM725.333 213.334h-426.667v64c0 71.253 142.080 106.667 213.333 106.667s213.333-35.413 213.333-106.667v-64z" />
-<glyph unicode="&#xe6e3;" d="M725.333 810.667h-42.667v-213.333h42.667v213.333zM640 725.334h-85.333v42.667h85.333v42.667h-128v-128h85.333v-42.667h-85.333v-42.667h128v128zM768 810.667v-213.333h42.667v85.333h85.333v128h-128zM853.333 725.334h-42.667v42.667h42.667v-42.667zM853.333 277.334c-53.333 0-104.533 8.533-152.32 24.32-14.933 4.693-31.573 1.28-43.093-10.24l-93.867-93.867c-120.747 61.44-219.733 160-281.173 281.173l93.867 94.293c11.52 11.093 14.933 27.733 10.24 42.667-15.787 47.787-24.32 98.987-24.32 152.32 0 23.467-19.2 42.667-42.667 42.667h-149.333c-23.467 0-42.667-19.2-42.667-42.667 0-400.64 324.693-725.333 725.333-725.333 23.467 0 42.667 19.2 42.667 42.667v149.333c0 23.467-19.2 42.667-42.667 42.667z" />
-<glyph unicode="&#xe6e4;" d="M512 128c-46.933 0-85.333-38.4-85.333-85.333s38.4-85.333 85.333-85.333 85.333 38.4 85.333 85.333-38.4 85.333-85.333 85.333zM256 896c-46.933 0-85.333-38.4-85.333-85.333s38.4-85.333 85.333-85.333 85.333 38.4 85.333 85.333-38.4 85.333-85.333 85.333zM256 640c-46.933 0-85.333-38.4-85.333-85.333s38.4-85.333 85.333-85.333 85.333 38.4 85.333 85.333-38.4 85.333-85.333 85.333zM256 384c-46.933 0-85.333-38.4-85.333-85.333s38.4-85.333 85.333-85.333 85.333 38.4 85.333 85.333-38.4 85.333-85.333 85.333zM768 725.334c46.933 0 85.333 38.4 85.333 85.333s-38.4 85.333-85.333 85.333-85.333-38.4-85.333-85.333 38.4-85.333 85.333-85.333zM512 384c-46.933 0-85.333-38.4-85.333-85.333s38.4-85.333 85.333-85.333 85.333 38.4 85.333 85.333-38.4 85.333-85.333 85.333zM768 384c-46.933 0-85.333-38.4-85.333-85.333s38.4-85.333 85.333-85.333 85.333 38.4 85.333 85.333-38.4 85.333-85.333 85.333zM768 640c-46.933 0-85.333-38.4-85.333-85.333s38.4-85.333 85.333-85.333 85.333 38.4 85.333 85.333-38.4 85.333-85.333 85.333zM512 640c-46.933 0-85.333-38.4-85.333-85.333s38.4-85.333 85.333-85.333 85.333 38.4 85.333 85.333-38.4 85.333-85.333 85.333zM512 896c-46.933 0-85.333-38.4-85.333-85.333s38.4-85.333 85.333-85.333 85.333 38.4 85.333 85.333-38.4 85.333-85.333 85.333z" />
-<glyph unicode="&#xe6e5;" d="M512 853.334c-235.52 0-426.667-191.147-426.667-426.667s191.147-426.667 426.667-426.667 426.667 191.147 426.667 426.667-191.147 426.667-426.667 426.667zM512 85.334c-188.587 0-341.333 152.747-341.333 341.333 0 78.933 26.88 151.467 72.107 209.067l478.293-478.293c-57.6-45.227-130.133-72.107-209.067-72.107zM781.227 217.6l-478.293 478.293c57.6 45.227 130.133 72.107 209.067 72.107 188.587 0 341.333-152.747 341.333-341.333 0-78.933-26.88-151.467-72.107-209.067z" />
-<glyph unicode="&#xe6e6;" d="M853.333 768h-682.667c-46.933 0-84.907-38.4-84.907-85.333l-0.427-512c0-46.933 38.4-85.333 85.333-85.333h682.667c46.933 0 85.333 38.4 85.333 85.333v512c0 46.933-38.4 85.333-85.333 85.333zM853.333 597.334l-341.333-213.333-341.333 213.333v85.333l341.333-213.333 341.333 213.333v-85.333z" />
-<glyph unicode="&#xe6e7;" d="M896 682.667h-85.333v-384h-554.667v-85.333c0-23.467 19.2-42.667 42.667-42.667h469.333l170.667-170.667v640c0 23.467-19.2 42.667-42.667 42.667zM725.333 426.667v384c0 23.467-19.2 42.667-42.667 42.667h-554.667c-23.467 0-42.667-19.2-42.667-42.667v-597.333l170.667 170.667h426.667c23.467 0 42.667 19.2 42.667 42.667z" />
-<glyph unicode="&#xe6e8;" d="M384 810.667l-170.667-170.24h128v-299.093h85.333v299.093h128l-170.667 170.24zM682.667 212.907v299.093h-85.333v-299.093h-128l170.667-170.24 170.667 170.24h-128z" />
-<glyph unicode="&#xe6e9;" d="M881.067 48.214l-100.267 100.267-268.8 268.373-151.893 152.32-60.587 60.16-117.333 117.333-54.187-54.187 118.613-118.613c-108.8-133.973-100.693-331.093 23.893-456.107 66.56-66.56 154.027-99.84 241.493-99.84 76.373 0 152.32 25.173 214.613 75.947l115.2-115.2 54.187 54.187-14.933 15.36zM512 102.827c-68.267 0-132.693 26.453-180.907 75.093-48.64 48.64-75.093 112.64-75.093 180.907 0 56.32 18.347 109.653 51.627 153.6l204.373-203.947v-205.653zM512 721.067v-195.413l309.333-309.76c58.453 126.293 35.84 280.32-68.267 384.427l-241.067 241.493-157.867-157.867 60.16-60.16 97.707 97.28z" />
-<glyph unicode="&#xe6ea;" d="M753.493 600.32l-241.493 241.493-241.493-241.493c-133.12-133.12-133.12-349.44 0-482.56 66.56-66.56 154.027-99.84 241.493-99.84s174.933 33.28 241.493 99.84c133.12 133.12 133.12 349.44 0 482.56zM512 102.827c-68.267 0-132.693 26.453-180.907 75.093-48.64 48.64-75.093 112.64-75.093 180.907s26.453 132.693 75.093 180.907l180.907 181.333v-618.24z" />
-<glyph unicode="&#xe6eb;" d="M810.667 853.334h-597.333c-47.36 0-85.333-38.4-85.333-85.333v-597.333c0-46.933 37.973-85.333 85.333-85.333h170.667l128-128 128 128h170.667c46.933 0 85.333 38.4 85.333 85.333v597.333c0 46.933-38.4 85.333-85.333 85.333zM554.667 170.667h-85.333v85.333h85.333v-85.333zM642.987 501.334l-38.4-39.253c-30.72-31.147-49.92-56.747-49.92-120.747h-85.333v21.333c0 46.933 19.2 89.6 49.92 120.747l52.907 53.76c15.787 15.36 25.173 36.693 25.173 60.16 0 46.933-38.4 85.333-85.333 85.333s-85.333-38.4-85.333-85.333h-85.333c0 94.293 76.373 170.667 170.667 170.667s170.667-76.373 170.667-170.667c0-37.547-15.36-71.68-39.68-96z" />
-<glyph unicode="&#xe6ec;" d="M512 661.334c58.88 0 106.667-47.787 106.667-106.667 0-31.573-14.080-59.307-35.413-78.933l154.88-154.88c41.813 79.36 72.533 162.133 72.533 233.813 0 165.12-133.547 298.667-298.667 298.667-84.48 0-160.427-35.413-215.040-91.733l136.107-136.107c19.627 22.187 47.36 35.84 78.933 35.84zM698.453 251.734l-558.933 558.933-54.187-54.187 135.68-135.68c-4.693-21.333-7.68-43.52-7.68-66.133 0-224 298.667-554.667 298.667-554.667s71.253 78.933 144.213 185.6l142.933-142.933 54.187 54.187-154.88 154.88z" />
-<glyph unicode="&#xe6ed;" d="M512 853.334c-165.12 0-298.667-133.547-298.667-298.667 0-224 298.667-554.667 298.667-554.667s298.667 330.667 298.667 554.667c0 165.12-133.547 298.667-298.667 298.667zM512 448c-58.88 0-106.667 47.787-106.667 106.667s47.787 106.667 106.667 106.667 106.667-47.787 106.667-106.667-47.787-106.667-106.667-106.667z" />
-<glyph unicode="&#xe6ee;" d="M853.333 853.334h-682.667c-46.933 0-84.907-38.4-84.907-85.333l-0.427-768 170.667 170.667h597.333c46.933 0 85.333 38.4 85.333 85.333v512c0 46.933-38.4 85.333-85.333 85.333zM768 341.334h-512v85.333h512v-85.333zM768 469.334h-512v85.333h512v-85.333zM768 597.334h-512v85.333h512v-85.333z" />
-<glyph unicode="&#xe6ef;" d="M853.333 853.334h-682.667c-46.933 0-85.333-38.4-85.333-85.333v-768l170.667 170.667h597.333c46.933 0 85.333 38.4 85.333 85.333v512c0 46.933-38.4 85.333-85.333 85.333z" />
-<glyph unicode="&#xe6f0;" d="M810.24 725.334c0 46.933-37.973 85.333-84.907 85.333h-298.667l-99.84-99.84 483.84-483.84-0.427 498.347zM155.733 773.12l-54.187-54.187 111.787-111.787v-479.147c0-46.933 38.4-85.333 85.333-85.333h427.093c14.933 0 28.587 4.267 40.96 11.093l80.213-80.213 54.187 54.187-745.387 745.387z" />
-<glyph unicode="&#xe6f1;" d="M282.453 478.294c61.44-120.747 160.427-219.307 281.173-281.173l93.867 93.867c11.52 11.52 28.587 15.36 43.52 10.24 47.787-15.787 99.413-24.32 152.32-24.32 23.467 0 42.667-19.2 42.667-42.667v-148.907c0-23.467-19.2-42.667-42.667-42.667-400.64 0-725.333 324.693-725.333 725.333 0 23.467 19.2 42.667 42.667 42.667h149.333c23.467 0 42.667-19.2 42.667-42.667 0-53.333 8.533-104.533 24.32-152.32 4.693-14.933 1.28-31.573-10.667-43.52l-93.867-93.867z" />
-<glyph unicode="&#xe6f2;" d="M749.227 331.094c11.947 29.44 18.773 61.867 18.773 95.573 0 141.227-114.773 256-256 256-33.707 0-66.133-6.827-95.573-18.773l69.12-69.12c8.533 1.28 17.493 2.56 26.453 2.56 94.293 0 170.667-76.373 170.667-170.667 0-8.96-0.853-17.92-2.133-26.88l68.693-68.693zM512 768c188.587 0 341.333-152.747 341.333-341.333 0-57.6-14.933-111.787-40.533-159.573l62.72-62.72c40.107 64.853 63.147 140.8 63.147 222.293 0 235.52-191.147 426.667-426.667 426.667-81.493 0-157.44-23.467-222.293-62.72l62.293-62.293c47.787 25.173 102.4 39.68 160 39.68zM139.52 832l-54.187-54.187 89.6-89.6c-55.893-72.533-89.6-162.987-89.6-261.547 0-157.867 85.76-295.253 212.907-369.067l42.667 73.813c-101.547 59.307-170.24 168.96-170.24 295.253 0 75.093 24.32 144.213 65.28 200.107l61.013-61.44c-25.6-39.68-40.96-87.467-40.96-138.667 0-94.72 51.627-177.067 128-221.44l42.667 74.24c-50.773 29.867-85.333 84.053-85.333 147.2 0 27.733 7.253 53.333 18.773 76.373l67.413-67.413-0.853-8.96c0-46.933 38.4-85.333 85.333-85.333l8.96 0.853 320.853-320.853 54.187 54.187-756.48 756.48z" />
-<glyph unicode="&#xe6f3;" d="M938.667 810.667h-853.333c-46.933 0-85.333-38.4-85.333-85.333v-597.333c0-46.933 38.4-85.333 85.333-85.333h853.333c46.933 0 84.907 38.4 84.907 85.333l0.427 597.333c0 46.933-38.4 85.333-85.333 85.333zM341.333 682.667c70.827 0 128-57.173 128-128s-57.173-128-128-128-128 57.173-128 128 57.173 128 128 128zM597.333 170.667h-512v42.667c0 85.333 170.667 132.267 256 132.267s256-46.933 256-132.267v-42.667zM761.6 341.334h69.973l64.427-85.333-84.907-84.907c-55.893 41.813-97.28 101.547-116.48 170.24-7.68 27.307-11.947 55.893-11.947 85.333s4.267 58.027 11.947 85.333c19.2 69.12 60.587 128.427 116.48 170.24l84.907-84.907-64.427-85.333h-69.973c-9.387-26.88-14.933-55.467-14.933-85.333s5.547-58.453 14.933-85.333z" />
-<glyph unicode="&#xe6f4;" d="M896 597.334v42.667l-128-85.333-128 85.333v-42.667l128-85.333 128 85.333zM938.667 810.667h-853.333c-46.933 0-85.333-38.4-85.333-85.333v-597.333c0-46.933 38.4-85.333 85.333-85.333h853.333c46.933 0 84.907 38.4 84.907 85.333l0.427 597.333c0 46.933-38.4 85.333-85.333 85.333zM341.333 682.667c70.827 0 128-57.173 128-128s-57.173-128-128-128-128 57.173-128 128 57.173 128 128 128zM597.333 170.667h-512v42.667c0 85.333 170.667 132.267 256 132.267s256-46.933 256-132.267v-42.667zM938.667 426.667h-341.333v256h341.333v-256z" />
-<glyph unicode="&#xe6f5;" d="M1011.627 227.414c-130.133 123.307-305.92 199.253-499.627 199.253s-369.493-75.947-499.627-199.253c-7.68-7.68-12.373-18.347-12.373-30.293s4.693-22.613 12.373-30.293l105.813-105.813c7.68-7.68 18.347-12.373 30.293-12.373 11.52 0 22.187 4.693 29.867 11.947 33.707 31.573 72.107 58.027 113.493 78.933 14.080 6.827 23.893 21.333 23.893 38.4v132.267c61.867 20.48 128 31.147 196.267 31.147s134.4-10.667 196.267-30.72v-132.267c0-16.64 9.813-31.573 23.893-38.4 41.813-20.907 79.787-47.787 113.493-78.933 7.68-7.68 18.347-11.947 29.867-11.947 11.947 0 22.613 4.693 30.293 12.373l105.813 105.813c7.68 7.68 12.373 18.347 12.373 30.293 0 11.52-4.693 22.187-12.373 29.867zM902.827 671.574l-60.16 60.16-151.893-151.467 60.16-60.16s147.2 150.187 151.893 151.467zM554.667 853.334h-85.333v-213.333h85.333v213.333zM273.067 520.107l60.16 60.16-151.467 151.893-60.587-60.587c4.693-1.28 151.893-151.467 151.893-151.467z" />
-<glyph unicode="&#xe6f6;" d="M43.093 640l-0.427-426.667c0-46.933 38.4-85.333 85.333-85.333h768c46.933 0 85.333 38.4 85.333 85.333v426.667c0 46.933-38.4 85.333-85.333 85.333h-768c-46.933 0-84.907-38.4-84.907-85.333zM810.667 640v-426.667h-597.333v426.667h597.333z" />
-<glyph unicode="&#xe6f7;" d="M725.333 895.574l-426.667 0.427c-46.933 0-84.907-38.4-84.907-85.333v-768c0-46.933 37.973-85.333 84.907-85.333h426.667c46.933 0 85.333 38.4 85.333 85.333v768c0 46.933-38.4 84.907-85.333 84.907zM725.333 128h-426.667v597.333h426.667v-597.333z" />
-<glyph unicode="&#xe6f8;" d="M43.093 640l-0.427-426.667c0-46.933 38.4-85.333 85.333-85.333h768c46.933 0 85.333 38.4 85.333 85.333v426.667c0 46.933-38.4 85.333-85.333 85.333h-768c-46.933 0-84.907-38.4-84.907-85.333zM810.667 640v-426.667h-597.333v426.667h597.333z" />
-<glyph unicode="&#xe6f9;" d="M725.333 895.574l-426.667 0.427c-46.933 0-84.907-38.4-84.907-85.333v-768c0-46.933 37.973-85.333 84.907-85.333h426.667c46.933 0 85.333 38.4 85.333 85.333v768c0 46.933-38.4 84.907-85.333 84.907zM725.333 128h-426.667v597.333h426.667v-597.333z" />
-<glyph unicode="&#xe6fa;" d="M768 768l-170.667-170.667h128v-298.667c0-46.933-38.4-85.333-85.333-85.333s-85.333 38.4-85.333 85.333v298.667c0 94.293-76.373 170.667-170.667 170.667s-170.667-76.373-170.667-170.667v-298.667h-128l170.667-170.667 170.667 170.667h-128v298.667c0 46.933 38.4 85.333 85.333 85.333s85.333-38.4 85.333-85.333v-298.667c0-94.293 76.373-170.667 170.667-170.667s170.667 76.373 170.667 170.667v298.667h128l-170.667 170.667z" />
-<glyph unicode="&#xe6fb;" d="M853.333 853.334h-682.667c-46.933 0-84.907-38.4-84.907-85.333l-0.427-768 170.667 170.667h597.333c46.933 0 85.333 38.4 85.333 85.333v512c0 46.933-38.4 85.333-85.333 85.333zM384 469.334h-85.333v85.333h85.333v-85.333zM554.667 469.334h-85.333v85.333h85.333v-85.333zM725.333 469.334h-85.333v85.333h85.333v-85.333z" />
-<glyph unicode="&#xe6fc;" d="M789.333 682.667c-129.707 0-234.667-104.96-234.667-234.667 0-56.747 20.053-108.8 53.76-149.333h-192.853c33.707 40.533 53.76 92.587 53.76 149.333 0 129.707-104.96 234.667-234.667 234.667s-234.667-104.96-234.667-234.667 104.96-234.667 234.667-234.667h554.667c129.707 0 234.667 104.96 234.667 234.667s-104.96 234.667-234.667 234.667zM234.667 298.667c-82.347 0-149.333 66.987-149.333 149.333s66.987 149.333 149.333 149.333 149.333-66.987 149.333-149.333-66.987-149.333-149.333-149.333zM789.333 298.667c-82.347 0-149.333 66.987-149.333 149.333s66.987 149.333 149.333 149.333 149.333-66.987 149.333-149.333-66.987-149.333-149.333-149.333z" />
-<glyph unicode="&#xe6fd;" d="M539.733 512c-34.987 99.413-129.707 170.667-241.067 170.667-141.227 0-256-114.773-256-256s114.773-256 256-256c111.36 0 206.080 71.253 241.067 170.667h185.6v-170.667h170.667v170.667h85.333v170.667h-441.6zM298.667 341.334c-46.933 0-85.333 38.4-85.333 85.333s38.4 85.333 85.333 85.333 85.333-38.4 85.333-85.333-38.4-85.333-85.333-85.333z" />
-<glyph unicode="&#xe6fe;" d="M810.667 810.667h-597.333c-47.36 0-85.333-38.4-85.333-85.333v-597.333c0-46.933 37.973-85.333 85.333-85.333h597.333c46.933 0 85.333 38.4 85.333 85.333v597.333c0 46.933-38.4 85.333-85.333 85.333zM725.333 384h-170.667v-170.667h-85.333v170.667h-170.667v85.333h170.667v170.667h85.333v-170.667h170.667v-85.333z" />
-<glyph unicode="&#xe6ff;" d="M554.667 640h-85.333v-170.667h-170.667v-85.333h170.667v-170.667h85.333v170.667h170.667v85.333h-170.667v170.667zM512 853.334c-235.52 0-426.667-191.147-426.667-426.667s191.147-426.667 426.667-426.667 426.667 191.147 426.667 426.667-191.147 426.667-426.667 426.667zM512 85.334c-188.16 0-341.333 153.173-341.333 341.333s153.173 341.333 341.333 341.333 341.333-153.173 341.333-341.333-153.173-341.333-341.333-341.333z" />
-<glyph unicode="&#xe700;" d="M512 853.334c-235.52 0-426.667-191.147-426.667-426.667s191.147-426.667 426.667-426.667 426.667 191.147 426.667 426.667-191.147 426.667-426.667 426.667zM725.333 384h-170.667v-170.667h-85.333v170.667h-170.667v85.333h170.667v170.667h85.333v-170.667h170.667v-85.333z" />
-<glyph unicode="&#xe701;" d="M810.667 384h-256v-256h-85.333v256h-256v85.333h256v256h85.333v-256h256v-85.333z" />
-<glyph unicode="&#xe702;" d="M876.373 715.52l-59.307 71.68c-11.52 14.507-29.013 23.467-49.067 23.467h-512c-20.053 0-37.547-8.96-49.493-23.467l-58.88-71.68c-12.373-14.507-19.627-33.707-19.627-54.187v-533.333c0-46.933 38.4-85.333 85.333-85.333h597.333c46.933 0 85.333 38.4 85.333 85.333v533.333c0 20.48-7.253 39.68-19.627 54.187zM512 192l-234.667 234.667h149.333v85.333h170.667v-85.333h149.333l-234.667-234.667zM218.453 725.334l34.56 42.667h512l40.107-42.667h-586.667z" />
-<glyph unicode="&#xe703;" d="M938.667 810.667h-640c-29.44 0-52.48-14.933-67.84-37.547l-230.827-346.453 230.827-346.027c15.36-22.613 38.4-37.973 67.84-37.973h640c46.933 0 85.333 38.4 85.333 85.333v597.333c0 46.933-38.4 85.333-85.333 85.333zM810.667 273.494l-60.16-60.16-153.173 153.173-153.173-153.173-60.16 60.16 153.173 153.173-153.173 153.173 60.16 60.16 153.173-153.173 153.173 153.173 60.16-60.16-153.173-153.173 153.173-153.173z" />
-<glyph unicode="&#xe704;" d="M512 853.334c-235.52 0-426.667-191.147-426.667-426.667s191.147-426.667 426.667-426.667 426.667 191.147 426.667 426.667-191.147 426.667-426.667 426.667zM170.667 426.667c0 188.587 152.747 341.333 341.333 341.333 78.933 0 151.467-26.88 209.067-72.107l-478.293-478.293c-45.227 57.6-72.107 130.133-72.107 209.067zM512 85.334c-78.933 0-151.467 26.88-209.067 72.107l478.293 478.293c45.227-57.6 72.107-130.133 72.107-209.067 0-188.587-152.747-341.333-341.333-341.333z" />
-<glyph unicode="&#xe705;" d="M810.667 665.174l-60.16 60.16-238.507-238.507-238.507 238.507-60.16-60.16 238.507-238.507-238.507-238.507 60.16-60.16 238.507 238.507 238.507-238.507 60.16 60.16-238.507 238.507z" />
-<glyph unicode="&#xe706;" d="M682.667 896h-512c-46.933 0-85.333-38.4-85.333-85.333v-597.333h85.333v597.333h512v85.333zM810.667 725.334h-469.333c-46.933 0-85.333-38.4-85.333-85.333v-597.333c0-46.933 38.4-85.333 85.333-85.333h469.333c46.933 0 85.333 38.4 85.333 85.333v597.333c0 46.933-38.4 85.333-85.333 85.333zM810.667 42.667h-469.333v597.333h469.333v-597.333z" />
-<glyph unicode="&#xe707;" d="M411.307 612.694c9.813 21.333 15.36 44.8 15.36 69.973 0 94.293-76.373 170.667-170.667 170.667s-170.667-76.373-170.667-170.667 76.373-170.667 170.667-170.667c25.173 0 48.64 5.547 69.973 15.36l100.693-100.693-100.693-100.693c-21.333 9.813-44.8 15.36-69.973 15.36-94.293 0-170.667-76.373-170.667-170.667s76.373-170.667 170.667-170.667 170.667 76.373 170.667 170.667c0 25.173-5.547 48.64-15.36 69.973l100.693 100.693 298.667-298.667h128v42.667l-527.36 527.36zM256 597.334c-46.933 0-85.333 37.973-85.333 85.333s38.4 85.333 85.333 85.333 85.333-37.973 85.333-85.333-38.4-85.333-85.333-85.333zM256 85.334c-46.933 0-85.333 37.973-85.333 85.333s38.4 85.333 85.333 85.333 85.333-37.973 85.333-85.333-38.4-85.333-85.333-85.333zM512 405.334c-11.947 0-21.333 9.387-21.333 21.333s9.387 21.333 21.333 21.333 21.333-9.387 21.333-21.333-9.387-21.333-21.333-21.333zM810.667 810.667l-256-256 85.333-85.333 298.667 298.667v42.667z" />
-<glyph unicode="&#xe708;" d="M810.667 853.334h-178.347c-17.92 49.493-64.853 85.333-120.32 85.333s-102.4-35.84-120.32-85.333h-178.347c-46.933 0-85.333-38.4-85.333-85.333v-682.667c0-46.933 38.4-85.333 85.333-85.333h597.333c46.933 0 85.333 38.4 85.333 85.333v682.667c0 46.933-38.4 85.333-85.333 85.333zM512 853.334c23.467 0 42.667-19.2 42.667-42.667s-19.2-42.667-42.667-42.667-42.667 19.2-42.667 42.667 19.2 42.667 42.667 42.667zM810.667 85.334h-597.333v682.667h85.333v-128h426.667v128h85.333v-682.667z" />
-<glyph unicode="&#xe709;" d="M128 202.667v-160h160l471.893 471.893-160 160-471.893-471.893zM883.627 638.294c16.64 16.64 16.64 43.52 0 60.16l-99.84 99.84c-16.64 16.64-43.52 16.64-60.16 0l-78.080-78.080 160-160 78.080 78.080z" />
-<glyph unicode="&#xe70a;" d="M938.24 597.334c0 30.72-15.787 57.6-40.107 72.533l-386.133 226.133-386.133-226.133c-24.32-14.933-40.533-41.813-40.533-72.533v-426.667c0-46.933 38.4-85.333 85.333-85.333h682.667c46.933 0 85.333 38.4 85.333 85.333l-0.427 426.667zM512 384l-352.427 220.16 352.427 206.507 352.427-206.507-352.427-220.16z" />
-<glyph unicode="&#xe70b;" d="M426.667 170.667h170.667v85.333h-170.667v-85.333zM128 682.667v-85.333h768v85.333h-768zM256 384h512v85.333h-512v-85.333z" />
-<glyph unicode="&#xe70c;" d="M614.4 682.667l-17.067 85.333h-384v-725.333h85.333v298.667h238.933l17.067-85.333h298.667v426.667z" />
-<glyph unicode="&#xe70d;" d="M512 597.334v170.667l341.333-341.333-341.333-341.333v170.667h-341.333v341.333z" />
-<glyph unicode="&#xe70e;" d="M195.84 644.694c29.867 30.293 59.733 57.6 72.96 52.053 21.333-8.533 0-43.947-12.8-64.853-10.667-17.92-122.027-165.973-122.027-269.227 0-54.613 20.48-99.84 57.173-127.147 32-23.893 74.24-31.147 112.64-19.627 45.653 13.227 83.2 59.733 130.56 118.187 51.627 63.573 120.747 146.773 174.080 146.773 69.547 0 70.4-43.093 75.093-76.373-161.28-27.307-229.547-156.587-229.547-229.12s61.44-131.84 136.96-131.84c69.547 0 183.040 56.747 200.107 260.267h104.96v106.667h-105.387c-6.4 70.4-46.507 179.2-171.947 179.2-96 0-178.347-81.493-210.773-121.173-24.747-31.147-87.893-105.813-97.707-116.053-10.667-12.8-29.013-35.84-47.36-35.84-19.2 0-30.72 35.413-15.36 81.92 14.933 46.507 59.733 122.027 78.933 150.187 33.28 48.64 55.467 81.92 55.467 139.947 0 92.587-69.973 122.027-107.093 122.027-56.32 0-105.387-42.667-116.053-53.333-15.36-15.36-28.16-28.16-37.547-39.68l74.667-72.96zM592.213 147.2c-13.227 0-31.573 11.093-31.573 30.72 0 25.6 31.147 93.867 122.453 117.76-12.8-114.773-61.013-148.48-90.88-148.48z" />
-<glyph unicode="&#xe70f;" d="M810.667 810.667h-597.76c-46.933 0-84.48-38.4-84.48-85.333l-0.427-597.333c0-46.933 37.973-85.333 84.907-85.333h597.76c46.933 0 85.333 38.4 85.333 85.333v597.333c0 46.933-38.4 85.333-85.333 85.333zM810.667 298.667h-170.667c0-70.827-57.173-128-128-128s-128 57.173-128 128h-171.093v426.667h597.76v-426.667zM682.667 512h-85.333v128h-170.667v-128h-85.333l170.667-170.667 170.667 170.667z" />
-<glyph unicode="&#xe710;" d="M166.4 426.667c0 72.96 59.307 132.267 132.267 132.267h170.667v81.067h-170.667c-117.76 0-213.333-95.573-213.333-213.333s95.573-213.333 213.333-213.333h170.667v81.067h-170.667c-72.96 0-132.267 59.307-132.267 132.267zM341.333 384h341.333v85.333h-341.333v-85.333zM725.333 640h-170.667v-81.067h170.667c72.96 0 132.267-59.307 132.267-132.267s-59.307-132.267-132.267-132.267h-170.667v-81.067h170.667c117.76 0 213.333 95.573 213.333 213.333s-95.573 213.333-213.333 213.333z" />
-<glyph unicode="&#xe711;" d="M853.333 768h-682.667c-46.933 0-84.907-38.4-84.907-85.333l-0.427-512c0-46.933 38.4-85.333 85.333-85.333h682.667c46.933 0 85.333 38.4 85.333 85.333v512c0 46.933-38.4 85.333-85.333 85.333zM853.333 597.334l-341.333-213.333-341.333 213.333v85.333l341.333-213.333 341.333 213.333v-85.333z" />
-<glyph unicode="&#xe712;" d="M853.333 768h-682.667c-46.933 0-84.907-38.4-84.907-85.333l-0.427-512c0-46.933 38.4-85.333 85.333-85.333h682.667c46.933 0 85.333 38.4 85.333 85.333v512c0 46.933-38.4 85.333-85.333 85.333zM853.333 597.334l-341.333-213.333-341.333 213.333v85.333l341.333-213.333 341.333 213.333v-85.333z" />
-<glyph unicode="&#xe713;" d="M785.067 486.4c-78.933 68.693-181.333 110.933-294.4 110.933-198.4 0-366.080-129.28-424.96-308.053l100.693-33.28c44.8 136.107 172.8 234.667 324.267 234.667 83.2 0 159.147-30.72 218.453-80.213l-154.453-154.453h384v384l-153.6-153.6z" />
-<glyph unicode="&#xe714;" d="M298.667 469.334v-85.333h426.667v85.333h-426.667zM512 853.334c-235.52 0-426.667-191.147-426.667-426.667s191.147-426.667 426.667-426.667 426.667 191.147 426.667 426.667-191.147 426.667-426.667 426.667zM512 85.334c-188.16 0-341.333 153.173-341.333 341.333s153.173 341.333 341.333 341.333 341.333-153.173 341.333-341.333-153.173-341.333-341.333-341.333z" />
-<glyph unicode="&#xe715;" d="M512 853.334c-235.52 0-426.667-191.147-426.667-426.667s191.147-426.667 426.667-426.667 426.667 191.147 426.667 426.667-191.147 426.667-426.667 426.667zM725.333 384h-426.667v85.333h426.667v-85.333z" />
-<glyph unicode="&#xe716;" d="M810.667 384h-597.333v85.333h597.333v-85.333z" />
-<glyph unicode="&#xe717;" d="M298.667 597.334v128l-298.667-298.667 298.667-298.667v128l-170.667 170.667 170.667 170.667zM554.667 554.667v170.667l-298.667-298.667 298.667-298.667v174.933c213.333 0 362.667-68.267 469.333-217.6-42.667 213.333-170.667 426.667-469.333 469.333z" />
-<glyph unicode="&#xe718;" d="M426.667 554.667v170.667l-298.667-298.667 298.667-298.667v174.933c213.333 0 362.667-68.267 469.333-217.6-42.667 213.333-170.667 426.667-469.333 469.333z" />
-<glyph unicode="&#xe719;" d="M671.147 810.667h-318.293l-224.853-224.853v-318.293l224.853-224.853h318.293l224.853 224.853v318.293l-224.853 224.853zM512 200.534c-30.72 0-55.467 24.747-55.467 55.467s24.747 55.467 55.467 55.467c30.72 0 55.467-24.747 55.467-55.467s-24.747-55.467-55.467-55.467zM554.667 384h-85.333v256h85.333v-256z" />
-<glyph unicode="&#xe71a;" d="M725.333 810.667h-512c-47.36 0-85.333-38.4-85.333-85.333v-597.333c0-46.933 37.973-85.333 85.333-85.333h597.333c46.933 0 85.333 38.4 85.333 85.333v512l-170.667 170.667zM512 128c-70.827 0-128 57.173-128 128s57.173 128 128 128 128-57.173 128-128-57.173-128-128-128zM640 554.667h-426.667v170.667h426.667v-170.667z" />
-<glyph unicode="&#xe71b;" d="M128 725.334h85.333v85.333c-46.933 0-85.333-38.4-85.333-85.333zM128 384h85.333v85.333h-85.333v-85.333zM298.667 42.667h85.333v85.333h-85.333v-85.333zM128 554.667h85.333v85.333h-85.333v-85.333zM554.667 810.667h-85.333v-85.333h85.333v85.333zM810.667 810.667v-85.333h85.333c0 46.933-38.4 85.333-85.333 85.333zM213.333 42.667v85.333h-85.333c0-46.933 38.4-85.333 85.333-85.333zM128 213.334h85.333v85.333h-85.333v-85.333zM384 810.667h-85.333v-85.333h85.333v85.333zM469.333 42.667h85.333v85.333h-85.333v-85.333zM810.667 384h85.333v85.333h-85.333v-85.333zM810.667 42.667c46.933 0 85.333 38.4 85.333 85.333h-85.333v-85.333zM810.667 554.667h85.333v85.333h-85.333v-85.333zM810.667 213.334h85.333v85.333h-85.333v-85.333zM640 42.667h85.333v85.333h-85.333v-85.333zM640 725.334h85.333v85.333h-85.333v-85.333zM298.667 213.334h426.667v426.667h-426.667v-426.667zM384 554.667h256v-256h-256v256z" />
-<glyph unicode="&#xe71c;" d="M85.76 42.667l895.573 384-895.573 384-0.427-298.667 640-85.333-640-85.333z" />
-<glyph unicode="&#xe71d;" d="M128 170.667h256v85.333h-256v-85.333zM128 682.667v-85.333h768v85.333h-768zM128 384h512v85.333h-512v-85.333z" />
-<glyph unicode="&#xe71e;" d="M213.333 213.334v-85.333h597.333v85.333h-597.333zM405.333 392.534h213.333l38.4-93.867h89.6l-202.667 469.333h-64l-202.667-469.333h89.6l38.4 93.867zM512 683.52l79.787-214.187h-159.573l79.787 214.187z" />
-<glyph unicode="&#xe71f;" d="M533.333 597.334c-113.067 0-215.467-42.24-294.4-110.933l-153.6 153.6v-384h384l-154.453 154.453c59.307 49.493 134.827 80.213 218.453 80.213 151.040 0 279.467-98.56 324.267-234.667l101.12 33.28c-59.307 178.773-226.987 308.053-425.387 308.053z" />
-<glyph unicode="&#xe720;" d="M938.667 694.614l-196.267 164.693-55.040-65.28 196.267-164.693 55.040 65.28zM336.213 794.027l-54.613 65.28-196.267-164.267 55.040-65.28 195.84 164.267zM533.333 597.334h-64v-256l202.667-121.6 32 52.48-170.667 101.12v224zM512 768c-212.053 0-384-171.947-384-384s171.52-384 384-384c212.053 0 384 171.947 384 384s-171.947 384-384 384zM512 85.334c-165.12 0-298.667 133.547-298.667 298.667s133.547 298.667 298.667 298.667 298.667-133.547 298.667-298.667-133.547-298.667-298.667-298.667z" />
-<glyph unicode="&#xe721;" d="M938.667 695.467l-196.267 166.4-55.467-64 196.267-166.4 55.467 64zM337.067 793.6l-55.467 64-196.267-162.133 55.467-64 196.267 162.133zM533.333 597.334h-64v-256l200.533-123.733 34.133 51.2-170.667 102.4v226.133zM512 768c-213.333 0-384-170.667-384-384s170.667-384 384-384 384 170.667 384 384-170.667 384-384 384zM512 85.334c-166.4 0-298.667 132.267-298.667 298.667s132.267 298.667 298.667 298.667 298.667-132.267 298.667-298.667-132.267-298.667-298.667-298.667z" />
-<glyph unicode="&#xe722;" d="M511.573 853.334c-235.52 0-426.24-191.147-426.24-426.667s190.72-426.667 426.24-426.667c235.947 0 427.093 191.147 427.093 426.667s-191.147 426.667-427.093 426.667zM512 85.334c-188.587 0-341.333 152.747-341.333 341.333s152.747 341.333 341.333 341.333 341.333-152.747 341.333-341.333-152.747-341.333-341.333-341.333zM533.333 640h-64v-256l224-134.4 32 52.48-192 113.92z" />
-<glyph unicode="&#xe723;" d="M336.213 794.027l-54.613 65.28-196.267-164.267 55.040-65.28 195.84 164.267zM938.667 694.614l-196.267 164.693-55.040-65.28 196.267-164.693 55.040 65.28zM512 768c-212.053 0-384-171.947-384-384s171.52-384 384-384c212.053 0 384 171.947 384 384s-171.947 384-384 384zM512 85.334c-165.12 0-298.667 133.547-298.667 298.667s133.547 298.667 298.667 298.667 298.667-133.547 298.667-298.667-133.547-298.667-298.667-298.667zM554.667 554.667h-85.333v-128h-128v-85.333h128v-128h85.333v128h128v85.333h-128v128z" />
-<glyph unicode="&#xe724;" d="M554.667 554.667v234.667c0 35.413-28.587 64-64 64s-64-28.587-64-64v-157.013l334.080-334.080 135.253-42.24v85.333l-341.333 213.333zM128 713.814l212.907-212.907-255.573-159.573v-85.333l341.333 106.667v-234.667l-85.333-64v-64l149.333 42.667 149.333-42.667v64l-85.333 64v159.147l244.48-244.48 54.187 54.187-671.147 671.147-54.187-54.187z" />
-<glyph unicode="&#xe725;" d="M896 256v85.333l-341.333 213.333v234.667c0 35.413-28.587 64-64 64s-64-28.587-64-64v-234.667l-341.333-213.333v-85.333l341.333 106.667v-234.667l-85.333-64v-64l149.333 42.667 149.333-42.667v64l-85.333 64v234.667l341.333-106.667z" />
-<glyph unicode="&#xe726;" d="M298.667 213.334v-157.867c0-29.867 25.6-55.467 55.467-55.467h315.733c29.867 0 55.467 25.6 55.467 55.467v157.867h-426.667z" />
-<glyph unicode="&#xe727;" d="M298.667 298.667v-243.2c0-29.867 25.6-55.467 55.467-55.467h315.733c29.867 0 55.467 25.6 55.467 55.467v243.2h-426.667z" />
-<glyph unicode="&#xe728;" d="M298.667 384v-328.533c0-29.867 25.6-55.467 55.467-55.467h315.733c29.867 0 55.467 25.6 55.467 55.467v328.533h-426.667z" />
-<glyph unicode="&#xe729;" d="M298.667 469.334v-413.867c0-29.867 25.6-55.467 55.467-55.467h315.733c29.867 0 55.467 25.6 55.467 55.467v413.867h-426.667z" />
-<glyph unicode="&#xe72a;" d="M298.667 554.667v-499.2c0-29.867 25.6-55.467 55.467-55.467h315.733c29.867 0 55.467 25.6 55.467 55.467v499.2h-426.667z" />
-<glyph unicode="&#xe72b;" d="M298.667 597.334v-541.867c0-29.867 25.6-55.467 55.467-55.467h315.733c29.867 0 55.467 25.6 55.467 55.467v541.867h-426.667z" />
-<glyph unicode="&#xe72c;" d="M668.587 768h-71.253v85.333h-170.667v-85.333h-71.253c-31.147 0-56.747-25.6-56.747-56.747v-654.080c0-31.573 25.6-57.173 56.747-57.173h312.747c31.573 0 57.173 25.6 57.173 56.747v654.507c0 31.147-25.6 56.747-56.747 56.747zM554.667 170.667h-85.333v85.333h85.333v-85.333zM554.667 341.334h-85.333v213.333h85.333v-213.333z" />
-<glyph unicode="&#xe72d;" d="M469.333 85.334v128h-170.667v-157.867c0-29.867 25.6-55.467 55.467-55.467h315.733c29.867 0 55.467 25.6 55.467 55.467v157.867h-192l-64-128z" />
-<glyph unicode="&#xe72e;" d="M469.333 85.334v234.667h-170.667v-264.533c0-29.867 25.6-55.467 55.467-55.467h315.733c29.867 0 55.467 25.6 55.467 55.467v264.533h-136.533l-119.467-234.667z" />
-<glyph unicode="&#xe72f;" d="M618.667 362.667l-149.333-277.333v234.667h-85.333l21.333 42.667h-106.667v-307.2c0-29.867 25.6-55.467 55.467-55.467h315.733c29.867 0 55.467 25.6 55.467 55.467v307.2h-106.667z" />
-<glyph unicode="&#xe730;" d="M554.667 405.334h85.333l-170.667-320v234.667h-85.333l81.067 149.333h-166.4v-413.867c0-29.867 25.6-55.467 55.467-55.467h315.733c29.867 0 55.467 25.6 55.467 55.467v413.867h-170.667v-64z" />
-<glyph unicode="&#xe731;" d="M558.933 405.334h81.067l-170.667-320v234.667h-85.333l123.733 234.667h-209.067v-499.2c0-29.867 25.6-55.467 55.467-55.467h315.733c29.867 0 55.467 25.6 55.467 55.467v499.2h-170.667v-149.333h4.267z" />
-<glyph unicode="&#xe732;" d="M640 405.334l-170.667-320v234.667h-85.333l149.333 277.333h-234.667v-541.867c0-29.867 25.6-55.467 55.467-55.467h315.733c29.867 0 55.467 25.6 55.467 55.467v541.867h-170.667v-192h85.333z" />
-<glyph unicode="&#xe733;" d="M668.587 768h-71.253v85.333h-170.667v-85.333h-71.253c-31.147 0-56.747-25.6-56.747-56.747v-654.080c0-31.573 25.6-57.173 56.747-57.173h312.747c31.573 0 57.173 25.6 57.173 56.747v654.507c0 31.147-25.6 56.747-56.747 56.747zM469.333 85.334v234.667h-85.333l170.667 320v-234.667h85.333l-170.667-320z" />
-<glyph unicode="&#xe734;" d="M668.587 768h-71.253v85.333h-170.667v-85.333h-71.253c-31.147 0-56.747-25.6-56.747-56.747v-654.080c0-31.573 25.6-57.173 56.747-57.173h312.747c31.573 0 57.173 25.6 57.173 56.747v654.507c0 31.147-25.6 56.747-56.747 56.747z" />
-<glyph unicode="&#xe735;" d="M668.587 768h-71.253v85.333h-170.667v-85.333h-71.253c-31.147 0-56.747-25.6-56.747-56.747v-654.080c0-31.573 25.6-57.173 56.747-57.173h312.747c31.573 0 57.173 25.6 57.173 56.747v654.507c0 31.147-25.6 56.747-56.747 56.747z" />
-<glyph unicode="&#xe736;" d="M668.587 768h-71.253v85.333h-170.667v-85.333h-71.253c-31.147 0-56.747-25.6-56.747-56.747v-654.080c0-31.573 25.6-57.173 56.747-57.173h312.747c31.573 0 57.173 25.6 57.173 56.747v654.507c0 31.147-25.6 56.747-56.747 56.747zM552.533 172.8h-81.067v81.067h81.067v-81.067zM610.133 397.227s-16.213-17.92-28.587-30.293c-20.48-20.48-35.413-49.067-35.413-68.267h-68.267c0 35.413 19.627 64.853 39.68 85.333l39.68 40.107c11.52 11.52 18.773 27.733 18.773 45.227 0 35.413-28.587 64-64 64s-64-28.587-64-64h-64c0 70.827 57.173 128 128 128s128-57.173 128-128c0-28.16-11.52-53.76-29.867-72.107z" />
-<glyph unicode="&#xe737;" d="M298.667 426.667l-85.333 85.333-85.333-85.333 85.333-85.333 85.333 85.333zM755.627 609.707l-243.627 243.627h-42.667v-323.84l-195.84 195.84-60.16-60.16 238.507-238.507-238.507-238.507 60.16-60.16 195.84 195.84v-323.84h42.667l243.627 243.627-183.467 183.040 183.467 183.040zM554.667 689.92l80.213-80.213-80.213-80.213v160.427zM634.88 243.627l-80.213-80.213v160.427l80.213-80.213zM810.667 512l-85.333-85.333 85.333-85.333 85.333 85.333-85.333 85.333z" />
-<glyph unicode="&#xe738;" d="M554.667 689.92l80.213-80.213-68.267-68.267 60.16-60.16 128.853 128.853-243.627 243.2h-42.667v-214.613l85.333-85.333v136.533zM230.827 768l-60.16-60.16 281.173-281.173-238.507-238.507 60.16-60.16 195.84 195.84v-323.84h42.667l183.040 183.040 98.133-97.707 60.16 60.16-622.507 622.507zM554.667 163.414v160.427l80.213-80.213-80.213-80.213z" />
-<glyph unicode="&#xe739;" d="M607.573 426.24l98.987-98.987c11.947 30.72 18.773 64.427 18.773 99.413s-6.827 67.84-18.347 98.56l-99.413-98.987zM833.28 652.374l-53.76-53.76c26.88-51.627 41.813-109.653 41.813-171.52s-15.36-120.32-41.813-171.52l51.2-51.2c41.387 65.707 65.707 143.36 65.707 226.56-0.427 80.64-23.467 156.587-63.147 221.44zM670.293 609.707l-243.627 243.627h-42.667v-323.84l-195.84 195.84-60.16-60.16 238.507-238.507-238.507-238.507 60.16-60.16 195.84 195.84v-323.84h42.667l243.627 243.627-183.467 183.040 183.467 183.040zM469.333 689.92l80.213-80.213-80.213-80.213v160.427zM549.547 243.627l-80.213-80.213v160.427l80.213-80.213z" />
-<glyph unicode="&#xe73a;" d="M755.627 609.707l-243.627 243.627h-42.667v-323.84l-195.84 195.84-60.16-60.16 238.507-238.507-238.507-238.507 60.16-60.16 195.84 195.84v-323.84h42.667l243.627 243.627-183.467 183.040 183.467 183.040zM554.667 689.92l80.213-80.213-80.213-80.213v160.427zM634.88 243.627l-80.213-80.213v160.427l80.213-80.213z" />
-<glyph unicode="&#xe73b;" d="M462.933 398.934h98.133l-49.067 155.733-49.067-155.733zM853.333 567.894v200.107h-200.107l-141.227 141.227-141.227-141.227h-200.107v-200.107l-141.227-141.227 141.227-141.227v-200.107h200.107l141.227-141.227 141.227 141.227h200.107v200.107l141.227 141.227-141.227 141.227zM610.133 256l-29.867 85.333h-136.533l-29.867-85.333h-81.067l136.533 384h85.333l136.533-384h-81.067z" />
-<glyph unicode="&#xe73c;" d="M853.333 567.894v200.107h-200.107l-141.227 141.227-141.227-141.227h-200.107v-200.107l-141.227-141.227 141.227-141.227v-200.107h200.107l141.227-141.227 141.227 141.227h200.107v200.107l141.227 141.227-141.227 141.227zM512 170.667c-141.227 0-256 114.773-256 256s114.773 256 256 256 256-114.773 256-256-114.773-256-256-256zM512 597.334c-94.293 0-170.667-76.373-170.667-170.667s76.373-170.667 170.667-170.667 170.667 76.373 170.667 170.667-76.373 170.667-170.667 170.667z" />
-<glyph unicode="&#xe73d;" d="M853.333 285.44l141.227 141.227-141.227 141.227v200.107h-200.107l-141.227 141.227-141.227-141.227h-200.107v-200.107l-141.227-141.227 141.227-141.227v-200.107h200.107l141.227-141.227 141.227 141.227h200.107v200.107zM512 170.667c-141.227 0-256 114.773-256 256s114.773 256 256 256 256-114.773 256-256-114.773-256-256-256z" />
-<glyph unicode="&#xe73e;" d="M853.333 285.44l141.227 141.227-141.227 141.227v200.107h-200.107l-141.227 141.227-141.227-141.227h-200.107v-200.107l-141.227-141.227 141.227-141.227v-200.107h200.107l141.227-141.227 141.227 141.227h200.107v200.107zM512 170.667v512c141.227 0 256-114.773 256-256s-114.773-256-256-256z" />
-<glyph unicode="&#xe73f;" d="M554.667 851.2v-129.28c144.64-20.907 256-144.64 256-295.253 0-38.4-7.68-74.667-20.48-108.373l110.933-65.28c23.893 52.907 37.547 111.787 37.547 173.653 0 221.013-168.533 403.2-384 424.533zM512 128c-165.12 0-298.667 133.547-298.667 298.667 0 150.613 111.36 274.347 256 295.253v129.28c-215.893-21.333-384-203.093-384-424.533 0-235.52 190.72-426.667 426.24-426.667 141.227 0 266.24 68.693 343.893 174.507l-110.933 65.28c-54.613-68.267-138.24-111.787-232.533-111.787z" />
-<glyph unicode="&#xe740;" d="M298.667 725.334h426.667v-85.333h85.333v170.667c0 46.933-38.4 84.907-85.333 84.907l-426.667 0.427c-46.933 0-85.333-38.4-85.333-85.333v-170.667h85.333v85.333zM657.493 230.827l195.84 195.84-195.84 195.84-60.16-60.587 135.253-135.253-135.253-135.253 60.16-60.587zM426.667 291.414l-135.253 135.253 135.253 135.253-60.16 60.587-195.84-195.84 195.84-195.84 60.16 60.587zM725.333 128h-426.667v85.333h-85.333v-170.667c0-46.933 38.4-85.333 85.333-85.333h426.667c46.933 0 85.333 38.4 85.333 85.333v170.667h-85.333v-85.333z" />
-<glyph unicode="&#xe741;" d="M170.667 682.667h768v85.333h-768c-46.933 0-85.333-38.4-85.333-85.333v-469.333h-85.333v-128h597.333v128h-426.667v469.333zM981.333 597.334h-256c-23.467 0-42.667-19.2-42.667-42.667v-426.667c0-23.467 19.2-42.667 42.667-42.667h256c23.467 0 42.667 19.2 42.667 42.667v426.667c0 23.467-19.2 42.667-42.667 42.667zM938.667 213.334h-170.667v298.667h170.667v-298.667z" />
-<glyph unicode="&#xe742;" d="M896 810.667h-768c-46.933 0-85.333-38.4-85.333-85.333v-512c0-46.933 38.4-85.333 85.333-85.333h213.333v-85.333h341.333v85.333h213.333c46.933 0 84.907 38.4 84.907 85.333l0.427 512c0 46.933-38.4 85.333-85.333 85.333zM896 213.334h-768v512h768v-512zM810.667 597.334h-469.333v-85.333h469.333v85.333zM810.667 426.667h-469.333v-85.333h469.333v85.333zM298.667 597.334h-85.333v-85.333h85.333v85.333zM298.667 426.667h-85.333v-85.333h85.333v85.333z" />
-<glyph unicode="&#xe743;" d="M512 597.334c-94.293 0-170.667-76.373-170.667-170.667s76.373-170.667 170.667-170.667 170.667 76.373 170.667 170.667-76.373 170.667-170.667 170.667zM893.44 469.334c-19.627 177.92-160.853 319.147-338.773 338.773v87.893h-85.333v-87.893c-177.92-19.627-319.147-160.853-338.773-338.773h-87.893v-85.333h87.893c19.627-177.92 160.853-319.147 338.773-338.773v-87.893h85.333v87.893c177.92 19.627 319.147 160.853 338.773 338.773h87.893v85.333h-87.893zM512 128c-165.12 0-298.667 133.547-298.667 298.667s133.547 298.667 298.667 298.667 298.667-133.547 298.667-298.667-133.547-298.667-298.667-298.667z" />
-<glyph unicode="&#xe744;" d="M893.44 469.334c-19.627 177.92-160.853 319.147-338.773 338.773v87.893h-85.333v-87.893c-177.92-19.627-319.147-160.853-338.773-338.773h-87.893v-85.333h87.893c19.627-177.92 160.853-319.147 338.773-338.773v-87.893h85.333v87.893c177.92 19.627 319.147 160.853 338.773 338.773h87.893v85.333h-87.893zM512 128c-165.12 0-298.667 133.547-298.667 298.667s133.547 298.667 298.667 298.667 298.667-133.547 298.667-298.667-133.547-298.667-298.667-298.667z" />
-<glyph unicode="&#xe745;" d="M893.44 469.334c-19.627 177.92-160.853 319.147-338.773 338.773v87.893h-85.333v-87.893c-48.213-5.12-93.44-19.627-134.827-41.387l64-64c34.987 14.507 73.387 22.613 113.493 22.613 165.12 0 298.667-133.547 298.667-298.667 0-40.107-8.107-78.507-22.187-113.067l64-64c21.333 40.96 35.84 86.187 41.387 134.4h87.467v85.333h-87.893zM128 756.48l87.040-87.040c-45.653-55.893-76.373-124.587-84.48-200.107h-87.893v-85.333h87.893c19.627-177.92 160.853-319.147 338.773-338.773v-87.893h85.333v87.893c75.52 8.533 144.213 38.827 200.107 84.48l87.040-87.040 54.187 54.187-713.813 713.813-54.187-54.187zM694.187 190.294c-50.347-38.827-113.493-62.293-182.187-62.293-165.12 0-298.667 133.547-298.667 298.667 0 68.693 23.467 131.84 62.293 182.187l418.56-418.56z" />
-<glyph unicode="&#xe746;" d="M893.44 469.334c-19.627 177.92-160.853 319.147-338.773 338.773v87.893h-85.333v-87.893c-48.213-5.12-93.44-19.627-134.827-41.387l64-64c34.987 14.507 73.387 22.613 113.493 22.613 165.12 0 298.667-133.547 298.667-298.667 0-40.107-8.107-78.507-22.187-113.067l64-64c21.333 40.96 35.84 86.187 41.387 134.4h87.467v85.333h-87.893zM128 756.48l87.040-87.040c-45.653-55.893-76.373-124.587-84.48-200.107h-87.893v-85.333h87.893c19.627-177.92 160.853-319.147 338.773-338.773v-87.893h85.333v87.893c75.52 8.533 144.213 38.827 200.107 84.48l87.040-87.040 54.187 54.187-713.813 713.813-54.187-54.187zM694.187 190.294c-50.347-38.827-113.493-62.293-182.187-62.293-165.12 0-298.667 133.547-298.667 298.667 0 68.693 23.467 131.84 62.293 182.187l418.56-418.56z" />
-<glyph unicode="&#xe747;" d="M893.44 469.334c-19.627 177.92-160.853 319.147-338.773 338.773v87.893h-85.333v-87.893c-177.92-19.627-319.147-160.853-338.773-338.773h-87.893v-85.333h87.893c19.627-177.92 160.853-319.147 338.773-338.773v-87.893h85.333v87.893c177.92 19.627 319.147 160.853 338.773 338.773h87.893v85.333h-87.893zM512 128c-165.12 0-298.667 133.547-298.667 298.667s133.547 298.667 298.667 298.667 298.667-133.547 298.667-298.667-133.547-298.667-298.667-298.667z" />
-<glyph unicode="&#xe748;" d="M298.667 170.667h85.333v512h-85.333v-512zM469.333-0h85.333v853.333h-85.333v-853.333zM128 341.334h85.333v170.667h-85.333v-170.667zM640 170.667h85.333v512h-85.333v-512zM810.667 512v-170.667h85.333v170.667h-85.333z" />
-<glyph unicode="&#xe749;" d="M85.333-0h853.333v853.333zM725.333 640l-640-640h640z" />
-<glyph unicode="&#xe74a;" d="M149.333 473.6l362.667-452.267 362.667 448c-21.333 17.067-157.867 128-362.667 128s-341.333-110.933-362.667-123.733z" />
-<glyph unicode="&#xe74b;" d="M853.333 853.334h-682.667c-46.933 0-85.333-38.4-85.333-85.333v-682.667c0-46.933 38.4-85.333 85.333-85.333h682.667c46.933 0 85.333 38.4 85.333 85.333v682.667c0 46.933-38.4 85.333-85.333 85.333zM853.333 85.334h-682.667v682.667h682.667v-682.667zM768 682.667h-213.333c-46.933 0-85.333-38.4-85.333-85.333v-97.28c-25.6-14.933-42.667-41.813-42.667-73.387 0-46.933 38.4-85.333 85.333-85.333s85.333 38.4 85.333 85.333c0 31.573-17.067 58.88-42.667 73.387v97.28h128v-341.333h-341.333v341.333h85.333v85.333h-170.667v-512h512v512z" />
-<glyph unicode="&#xe74c;" d="M170.667 768h298.667v85.333h-298.667c-46.933 0-85.333-38.4-85.333-85.333v-298.667h85.333v298.667zM426.667 384l-170.667-213.333h512l-128 170.667-86.613-115.627-126.72 158.293zM725.333 576c0 35.413-28.587 64-64 64s-64-28.587-64-64 28.587-64 64-64 64 28.587 64 64zM853.333 853.334h-298.667v-85.333h298.667v-298.667h85.333v298.667c0 46.933-38.4 85.333-85.333 85.333zM853.333 85.334h-298.667v-85.333h298.667c46.933 0 85.333 38.4 85.333 85.333v298.667h-85.333v-298.667zM170.667 384h-85.333v-298.667c0-46.933 38.4-85.333 85.333-85.333h298.667v85.333h-298.667v298.667z" />
-<glyph unicode="&#xe74d;" d="M554.667 384v-341.333h341.333v341.333h-341.333zM128 42.667h341.333v341.333h-341.333v-341.333zM128 810.667v-341.333h341.333v341.333h-341.333zM710.827 866.56l-241.493-241.067 241.493-241.493 241.493 241.493-241.493 241.067z" />
-<glyph unicode="&#xe74e;" d="M896 725.334h-768c-46.933 0-85.333-38.4-85.333-85.333v-426.667c0-46.933 38.4-85.333 85.333-85.333h768c46.933 0 85.333 38.4 85.333 85.333v426.667c0 46.933-38.4 85.333-85.333 85.333zM810.667 213.334h-597.333v426.667h597.333v-426.667zM426.667 256h170.667c23.467 0 42.667 19.2 42.667 42.667v128c0 23.467-19.2 42.667-42.667 42.667v42.667c0 47.36-38.4 85.333-85.333 85.333-47.36 0-85.333-38.4-85.333-85.333v-42.667c-23.467 0-42.667-19.2-42.667-42.667v-128c0-23.467 19.2-42.667 42.667-42.667zM460.8 512c0 28.16 23.040 51.2 51.2 51.2s51.2-23.040 51.2-51.2v-42.667h-102.4v42.667z" />
-<glyph unicode="&#xe74f;" d="M426.667 256h170.667c23.467 0 42.667 19.2 42.667 42.667v128c0 23.467-19.2 42.667-42.667 42.667v42.667c0 47.36-38.4 85.333-85.333 85.333-47.36 0-85.333-38.4-85.333-85.333v-42.667c-23.467 0-42.667-19.2-42.667-42.667v-128c0-23.467 19.2-42.667 42.667-42.667zM460.8 512c0 28.16 23.040 51.2 51.2 51.2s51.2-23.040 51.2-51.2v-42.667h-102.4v42.667zM725.333 896h-426.667c-46.933 0-85.333-38.4-85.333-85.333v-768c0-46.933 38.4-85.333 85.333-85.333h426.667c46.933 0 85.333 38.4 85.333 85.333v768c0 46.933-38.4 85.333-85.333 85.333zM725.333 128h-426.667v597.333h426.667v-597.333z" />
-<glyph unicode="&#xe750;" d="M992 393.814l-109.653 109.653-60.16-60.16 94.72-94.72-241.493-241.493-482.987 482.987 241.493 241.493 89.6-89.6 60.16 60.16-104.533 104.533c-25.173 25.173-65.707 25.173-90.453 0l-271.36-271.36c-25.173-25.173-25.173-65.707 0-90.453l512.853-512.853c25.173-25.173 65.707-25.173 90.453 0l271.36 271.36c25.173 25.173 25.173 65.707 0 90.453zM361.387 64.854c-139.52 65.707-239.36 201.387-254.72 361.813h-64c21.76-262.827 241.493-469.333 509.867-469.333l28.16 1.28-162.56 162.987-56.747-56.747zM682.667 554.667h213.333c23.467 0 42.667 19.2 42.667 42.667v170.667c0 23.467-19.2 42.667-42.667 42.667v21.333c0 58.88-47.787 106.667-106.667 106.667s-106.667-47.787-106.667-106.667v-21.333c-23.467 0-42.667-19.2-42.667-42.667v-170.667c0-23.467 19.2-42.667 42.667-42.667zM716.8 832c0 40.107 32.427 72.533 72.533 72.533s72.533-32.427 72.533-72.533v-21.333h-145.067v21.333z" />
-<glyph unicode="&#xe751;" d="M703.147 831.147c139.52-66.133 239.36-201.387 254.72-361.813h64c-21.76 262.827-241.493 469.333-509.867 469.333l-28.16-1.28 162.56-162.56 56.747 56.32zM436.48 864c-25.173 25.173-65.707 25.173-90.453 0l-271.36-271.36c-25.173-25.173-25.173-65.707 0-90.453l512.853-512.853c25.173-25.173 65.707-25.173 90.453 0l271.36 271.36c25.173 25.173 25.173 65.707 0 90.453l-512.853 512.853zM632.747 34.56l-512.853 512.853 271.36 271.36 512.853-512.853-271.36-271.36zM320.853 22.187c-139.52 65.707-239.36 201.387-254.72 361.813h-64c21.76-262.827 241.493-469.333 509.867-469.333l28.16 1.28-162.56 162.56-56.747-56.32z" />
-<glyph unicode="&#xe752;" d="M768 853.334h-341.333l-255.147-256-0.853-512c0-46.933 38.4-85.333 85.333-85.333h512c46.933 0 85.333 38.4 85.333 85.333v682.667c0 46.933-38.4 85.333-85.333 85.333zM512 597.334h-85.333v170.667h85.333v-170.667zM640 597.334h-85.333v170.667h85.333v-170.667zM768 597.334h-85.333v170.667h85.333v-170.667z" />
-<glyph unicode="&#xe753;" d="M384 256h277.333c58.88 0 106.667 47.787 106.667 106.667s-47.787 106.667-106.667 106.667h-2.133c-10.24 72.107-72.107 128-147.2 128-59.733 0-110.933-35.413-134.827-86.187h-6.827c-64.427-6.827-114.347-61.013-114.347-127.147 0-70.827 57.173-128 128-128zM896 810.667h-768c-46.933 0-85.333-38.4-85.333-85.333v-597.333c0-46.933 38.4-85.333 85.333-85.333h768c46.933 0 85.333 38.4 85.333 85.333v597.333c0 46.933-38.4 85.333-85.333 85.333zM896 127.574h-768v598.187h768v-598.187z" />
-<glyph unicode="&#xe755;" d="M512 426.667l-426.667-426.667h426.667v426.667z" />
-<glyph unicode="&#xe756;" d="M597.333 512l-512-512h512v512z" />
-<glyph unicode="&#xe757;" d="M725.333 640l-640-640h640v640z" />
-<glyph unicode="&#xe758;" d="M85.333-0h853.333v853.333z" />
-<glyph unicode="&#xe759;" d="M853.333-0h85.333v85.333h-85.333v-85.333zM853.333 512v-341.333h85.333v341.333h-85.333z" />
-<glyph unicode="&#xe75a;" d="M853.333 512v-341.333h85.333v341.333h-85.333zM512-0v426.667l-426.667-426.667h426.667zM853.333-0h85.333v85.333h-85.333v-85.333z" />
-<glyph unicode="&#xe75b;" d="M597.333-0v512l-512-512h512zM853.333 512v-341.333h85.333v341.333h-85.333zM853.333-0h85.333v85.333h-85.333v-85.333z" />
-<glyph unicode="&#xe75c;" d="M725.333-0v640l-640-640h640zM853.333 512v-341.333h85.333v341.333h-85.333zM853.333-0h85.333v85.333h-85.333v-85.333z" />
-<glyph unicode="&#xe75d;" d="M853.333 170.667h85.333v341.333h-85.333v-341.333zM853.333-0h85.333v85.333h-85.333v-85.333zM85.333-0h682.667v597.333h170.667v256l-853.333-853.333z" />
-<glyph unicode="&#xe75e;" d="M810.24 725.334c0 46.933-37.973 85.333-84.907 85.333h-298.667l-99.84-99.84 483.84-483.84-0.427 498.347zM155.733 773.12l-54.187-54.187 111.787-111.787v-479.147c0-46.933 38.4-85.333 85.333-85.333h427.093c14.933 0 28.587 4.267 40.96 11.093l80.213-80.213 54.187 54.187-745.387 745.387z" />
-<glyph unicode="&#xe75f;" d="M853.333 647.254v-561.92h-561.92l561.92 561.92zM938.667 853.334l-853.333-853.333h853.333v853.333z" />
-<glyph unicode="&#xe760;" d="M896 896l-366.507-366.507 366.507-366.507v733.013zM203.52 746.667l-54.187-54.187 271.36-271.36-378.027-378.453h756.48l85.333-85.333 54.187 54.187-735.147 735.147z" />
-<glyph unicode="&#xe762;" d="M285.867 302.934l226.133-281.6 226.133 281.6c-8.533 12.8-98.133 81.067-226.133 81.067s-217.6-68.267-226.133-81.067z" />
-<glyph unicode="&#xe763;" d="M204.8 405.334l307.2-384 307.2 384c-17.067 12.8-132.267 106.667-307.2 106.667s-294.4-93.867-307.2-106.667z" />
-<glyph unicode="&#xe764;" d="M149.333 473.6l362.667-452.267 362.667 448c-21.333 17.067-157.867 128-362.667 128s-341.333-110.933-362.667-123.733z" />
-<glyph unicode="&#xe765;" d="M512 21.334l494.933 618.667c-17.067 12.8-209.067 170.667-494.933 170.667s-477.867-157.867-494.933-170.667l494.933-618.667c0 0 0 0 0 0z" />
-<glyph unicode="&#xe766;" d="M1008.64 640c-19.2 14.507-210.347 170.667-496.64 170.667-64 0-123.307-8.107-177.067-20.48l440.747-440.32 232.96 290.133zM727.040 289.28l-587.52 587.947-54.187-54.613 87.467-87.893c-91.307-41.813-147.627-87.040-157.44-94.72l496.64-618.667 0.427 0.427 166.4 207.36 141.653-141.653 54.187 54.187-147.627 147.627z" />
-<glyph unicode="&#xe767;" d="M554.667-0l243.2 302.933c-12.8 4.267-102.4 81.067-243.2 81.067s-230.4-76.8-243.2-81.067l243.2-302.933z" horiz-adv-x="1109" />
-<glyph unicode="&#xe768;" d="M554.667-0l320 401.067c-8.533 8.533-132.267 110.933-320 110.933s-311.467-102.4-324.267-110.933l324.267-401.067c0 0 0 0 0 0z" horiz-adv-x="1109" />
-<glyph unicode="&#xe769;" d="M554.667-0l401.067 503.467c-12.8 8.533-170.667 136.533-401.067 136.533s-388.267-128-401.067-136.533l401.067-503.467c0 0 0 0 0 0z" horiz-adv-x="1109" />
-<glyph unicode="&#xe76a;" d="M554.667-0l537.6 669.867c-21.333 12.8-226.133 183.467-537.6 183.467s-516.267-170.667-537.6-183.467l537.6-669.867z" horiz-adv-x="1109" />
-<glyph unicode="&#xe76b;" d="M938.667-0h85.333v85.333h-85.333v-85.333zM938.667 512v-341.333h85.333v341.333h-85.333z" horiz-adv-x="1109" />
-<glyph unicode="&#xe76c;" d="M230.4 401.067l324.267-401.067 298.667 371.2v46.933c-46.933 29.867-153.6 93.867-298.667 93.867-187.733 0-311.467-102.4-324.267-110.933zM938.667 512v-341.333h85.333v341.333h-85.333zM938.667-0h85.333v85.333h-85.333v-85.333z" horiz-adv-x="1109" />
-<glyph unicode="&#xe76d;" d="M853.333 371.2v196.267c-68.267 34.133-174.933 72.533-298.667 72.533-230.4 0-388.267-128-401.067-136.533l401.067-503.467c0 0 298.667 371.2 298.667 371.2zM938.667-0h85.333v85.333h-85.333v-85.333zM938.667 512v-341.333h85.333v341.333h-85.333z" horiz-adv-x="1109" />
-<glyph unicode="&#xe76e;" d="M938.667-0h85.333v85.333h-85.333v-85.333zM554.667 853.334c-311.467 0-516.267-170.667-537.6-183.467l537.6-669.867 298.667 371.2v226.133h179.2l59.733 72.533c-21.333 12.8-226.133 183.467-537.6 183.467zM938.667 170.667h85.333v341.333h-85.333v-341.333z" horiz-adv-x="1109" />
-<glyph unicode="&#xe76f;" d="M311.467 302.934l243.2-298.667 243.2 302.933c-12.8 0-102.4 76.8-243.2 76.8s-230.4-76.8-243.2-81.067zM938.667-0h85.333v85.333h-85.333v-85.333zM938.667 512v-341.333h85.333v341.333h-85.333z" horiz-adv-x="1109" />
-<glyph unicode="&#xe770;" d="M891.733 499.2c-81.067 0-149.333-68.267-149.333-149.333h76.8c0 42.667 34.133 76.8 76.8 76.8s76.8-34.133 76.8-76.8c0-21.333-8.533-38.4-21.333-51.2l-46.933-46.933c-25.6-25.6-42.667-64-42.667-106.667v-17.067h76.8c0 55.467 17.067 76.8 42.667 106.667l34.133 34.133c21.333 21.333 34.133 51.2 34.133 85.333-8.533 76.8-76.8 145.067-157.867 145.067zM853.333-0h85.333v85.333h-85.333v-85.333z" horiz-adv-x="1109" />
-<glyph unicode="&#xe771;" d="M554.667 768c181.333 0 325.12-64.427 413.013-117.333l-413.013-514.133-412.587 514.133c87.467 52.907 231.253 117.333 412.587 117.333zM554.667 853.334c-309.76 0-516.267-168.96-536.747-184.32l536.747-669.013 0.427 0.427 536.32 668.587c-20.48 15.36-226.987 184.32-536.747 184.32z" horiz-adv-x="1109" />
-<glyph unicode="&#xe772;" d="M85.333 85.334h853.333v170.667h-853.333v-170.667zM170.667 213.334h85.333v-85.333h-85.333v85.333zM85.333 768v-170.667h853.333v170.667h-853.333zM256 640h-85.333v85.333h85.333v-85.333zM85.333 341.334h853.333v170.667h-853.333v-170.667zM170.667 469.334h85.333v-85.333h-85.333v85.333z" />
-<glyph unicode="&#xe773;" d="M640 640v-170.667h42.667v-85.333h-128v341.333h85.333l-128 170.667-128-170.667h85.333v-341.333h-128v88.32c29.867 15.787 51.2 46.080 51.2 82.347 0 51.627-42.24 93.867-93.867 93.867s-93.867-42.24-93.867-93.867c0-36.267 21.333-66.56 51.2-82.347v-88.32c0-47.36 37.973-85.333 85.333-85.333h128v-130.133c-30.293-15.787-51.2-46.933-51.2-83.2 0-52.053 42.24-93.867 93.867-93.867s93.867 41.813 93.867 93.867c0 36.267-20.907 67.413-51.2 83.2v130.133h128c47.36 0 85.333 37.973 85.333 85.333v85.333h42.667v170.667h-170.667z" />
-<glyph unicode="&#xe774;" d="M874.667 533.334c11.947 0 23.467-1.707 34.56-3.413l114.773 152.747c-142.507 107.093-320 170.667-512 170.667s-369.493-63.573-512-170.667l512-682.667 149.333 199.253v120.747c0 117.76 95.573 213.333 213.333 213.333zM981.333 256v64c0 58.88-47.787 106.667-106.667 106.667s-106.667-47.787-106.667-106.667v-64c-23.467 0-42.667-19.2-42.667-42.667v-170.667c0-23.467 19.2-42.667 42.667-42.667h213.333c23.467 0 42.667 19.2 42.667 42.667v170.667c0 23.467-19.2 42.667-42.667 42.667zM938.667 256h-128v64c0 35.413 28.587 64 64 64s64-28.587 64-64v-64z" />
-<glyph unicode="&#xe775;" d="M512 469.334c-46.933 0-85.333-38.4-85.333-85.333s38.4-85.333 85.333-85.333 85.333 38.4 85.333 85.333-38.4 85.333-85.333 85.333zM768 384c0 141.227-114.773 256-256 256s-256-114.773-256-256c0-94.72 51.627-177.067 128-221.44l42.667 74.24c-50.773 29.867-85.333 84.053-85.333 147.2 0 94.293 76.373 170.667 170.667 170.667s170.667-76.373 170.667-170.667c0-63.147-34.56-117.333-85.333-147.2l42.667-74.24c76.373 44.373 128 126.72 128 221.44zM512 810.667c-235.52 0-426.667-191.147-426.667-426.667 0-157.867 85.76-295.253 212.907-369.067l42.667 73.813c-101.547 59.307-170.24 168.96-170.24 295.253 0 188.587 152.747 341.333 341.333 341.333s341.333-152.747 341.333-341.333c0-126.293-68.693-235.947-170.667-295.253l42.667-73.813c127.573 73.813 213.333 211.2 213.333 369.067 0 235.52-191.147 426.667-426.667 426.667z" />
-<glyph unicode="&#xe776;" d="M704 682.667v-490.667c0-94.293-76.373-170.667-170.667-170.667s-170.667 76.373-170.667 170.667v533.333c0 58.88 47.787 106.667 106.667 106.667s106.667-47.787 106.667-106.667v-448c0-23.467-19.2-42.667-42.667-42.667s-42.667 19.2-42.667 42.667v405.333h-64v-405.333c0-58.88 47.787-106.667 106.667-106.667s106.667 47.787 106.667 106.667v448c0 94.293-76.373 170.667-170.667 170.667s-170.667-76.373-170.667-170.667v-533.333c0-129.707 104.96-234.667 234.667-234.667s234.667 104.96 234.667 234.667v490.667h-64z" />
-<glyph unicode="&#xe777;" d="M503.467 473.6c-96.853 25.173-128 51.2-128 91.733 0 46.507 43.093 78.933 115.2 78.933 75.947 0 104.107-36.267 106.667-89.6h94.293c-2.987 73.387-47.787 140.8-136.96 162.56v93.44h-128v-92.16c-82.773-17.92-149.333-71.68-149.333-154.027 0-98.56 81.493-147.627 200.533-176.213 106.667-25.6 128-63.147 128-102.827 0-29.44-20.907-76.373-115.2-76.373-87.893 0-122.453 39.253-127.147 89.6h-93.867c5.12-93.44 75.093-145.92 157.013-163.413v-92.587h128v91.733c83.2 15.787 149.333 64 149.333 151.467 0 121.173-103.68 162.56-200.533 187.733z" />
-<glyph unicode="&#xe778;" d="M128 810.667v-768h768v768h-768zM469.333 128h-256v256h256v-256zM469.333 469.334h-256v256h256v-256zM810.667 128h-256v256h256v-256zM810.667 469.334h-256v256h256v-256z" />
-<glyph unicode="&#xe779;" d="M384 469.334h-85.333v-85.333h85.333v85.333zM554.667 298.667h-85.333v-85.333h85.333v85.333zM384 810.667h-85.333v-85.333h85.333v85.333zM554.667 469.334h-85.333v-85.333h85.333v85.333zM213.333 810.667h-85.333v-85.333h85.333v85.333zM554.667 640h-85.333v-85.333h85.333v85.333zM725.333 469.334h-85.333v-85.333h85.333v85.333zM554.667 810.667h-85.333v-85.333h85.333v85.333zM725.333 810.667h-85.333v-85.333h85.333v85.333zM810.667 384h85.333v85.333h-85.333v-85.333zM810.667 213.334h85.333v85.333h-85.333v-85.333zM213.333 640h-85.333v-85.333h85.333v85.333zM810.667 810.667v-85.333h85.333v85.333h-85.333zM810.667 554.667h85.333v85.333h-85.333v-85.333zM213.333 469.334h-85.333v-85.333h85.333v85.333zM128 42.667h768v85.333h-768v-85.333zM213.333 298.667h-85.333v-85.333h85.333v85.333z" />
-<glyph unicode="&#xe77a;" d="M298.667 725.334h85.333v85.333h-85.333v-85.333zM298.667 384h85.333v85.333h-85.333v-85.333zM298.667 42.667h85.333v85.333h-85.333v-85.333zM469.333 213.334h85.333v85.333h-85.333v-85.333zM469.333 42.667h85.333v85.333h-85.333v-85.333zM128 42.667h85.333v85.333h-85.333v-85.333zM128 213.334h85.333v85.333h-85.333v-85.333zM128 384h85.333v85.333h-85.333v-85.333zM128 554.667h85.333v85.333h-85.333v-85.333zM128 725.334h85.333v85.333h-85.333v-85.333zM469.333 384h85.333v85.333h-85.333v-85.333zM810.667 213.334h85.333v85.333h-85.333v-85.333zM810.667 384h85.333v85.333h-85.333v-85.333zM810.667 42.667h85.333v85.333h-85.333v-85.333zM810.667 554.667h85.333v85.333h-85.333v-85.333zM469.333 554.667h85.333v85.333h-85.333v-85.333zM810.667 810.667v-85.333h85.333v85.333h-85.333zM469.333 725.334h85.333v85.333h-85.333v-85.333zM640 42.667h85.333v85.333h-85.333v-85.333zM640 384h85.333v85.333h-85.333v-85.333zM640 725.334h85.333v85.333h-85.333v-85.333z" />
-<glyph unicode="&#xe77b;" d="M757.333 640l-160 160-426.667-426.667v-160h160l426.667 426.667zM883.627 766.294c16.64 16.64 16.64 43.52 0 60.16l-99.84 99.84c-16.64 16.64-43.52 16.64-60.16 0l-83.627-83.627 160-160 83.627 83.627zM0 85.334h1024v-170.667h-1024z" />
-<glyph unicode="&#xe77c;" d="M128 42.667h85.333v85.333h-85.333v-85.333zM213.333 640h-85.333v-85.333h85.333v85.333zM128 213.334h85.333v85.333h-85.333v-85.333zM298.667 42.667h85.333v85.333h-85.333v-85.333zM213.333 810.667h-85.333v-85.333h85.333v85.333zM384 810.667h-85.333v-85.333h85.333v85.333zM725.333 810.667h-85.333v-85.333h85.333v85.333zM554.667 640h-85.333v-85.333h85.333v85.333zM554.667 810.667h-85.333v-85.333h85.333v85.333zM810.667 213.334h85.333v85.333h-85.333v-85.333zM469.333 42.667h85.333v85.333h-85.333v-85.333zM128 384h768v85.333h-768v-85.333zM810.667 810.667v-85.333h85.333v85.333h-85.333zM810.667 554.667h85.333v85.333h-85.333v-85.333zM469.333 213.334h85.333v85.333h-85.333v-85.333zM640 42.667h85.333v85.333h-85.333v-85.333zM810.667 42.667h85.333v85.333h-85.333v-85.333z" />
-<glyph unicode="&#xe77d;" d="M128 42.667h85.333v85.333h-85.333v-85.333zM298.667 42.667h85.333v85.333h-85.333v-85.333zM213.333 640h-85.333v-85.333h85.333v85.333zM128 213.334h85.333v85.333h-85.333v-85.333zM384 810.667h-85.333v-85.333h85.333v85.333zM213.333 810.667h-85.333v-85.333h85.333v85.333zM725.333 810.667h-85.333v-85.333h85.333v85.333zM810.667 554.667h85.333v85.333h-85.333v-85.333zM810.667 810.667v-85.333h85.333v85.333h-85.333zM640 42.667h85.333v85.333h-85.333v-85.333zM554.667 810.667h-85.333v-341.333h-341.333v-85.333h341.333v-341.333h85.333v341.333h341.333v85.333h-341.333v341.333zM810.667 42.667h85.333v85.333h-85.333v-85.333zM810.667 213.334h85.333v85.333h-85.333v-85.333z" />
-<glyph unicode="&#xe77e;" d="M469.333 42.667h85.333v85.333h-85.333v-85.333zM469.333 213.334h85.333v85.333h-85.333v-85.333zM469.333 725.334h85.333v85.333h-85.333v-85.333zM469.333 554.667h85.333v85.333h-85.333v-85.333zM469.333 384h85.333v85.333h-85.333v-85.333zM298.667 42.667h85.333v85.333h-85.333v-85.333zM298.667 725.334h85.333v85.333h-85.333v-85.333zM298.667 384h85.333v85.333h-85.333v-85.333zM128 42.667h85.333v768h-85.333v-768zM810.667 554.667h85.333v85.333h-85.333v-85.333zM640 42.667h85.333v85.333h-85.333v-85.333zM810.667 213.334h85.333v85.333h-85.333v-85.333zM810.667 810.667v-85.333h85.333v85.333h-85.333zM810.667 384h85.333v85.333h-85.333v-85.333zM810.667 42.667h85.333v85.333h-85.333v-85.333zM640 384h85.333v85.333h-85.333v-85.333zM640 725.334h85.333v85.333h-85.333v-85.333z" />
-<glyph unicode="&#xe77f;" d="M554.667 640h-85.333v-85.333h85.333v85.333zM554.667 469.334h-85.333v-85.333h85.333v85.333zM725.333 469.334h-85.333v-85.333h85.333v85.333zM128 810.667v-768h768v768h-768zM810.667 128h-597.333v597.333h597.333v-597.333zM554.667 298.667h-85.333v-85.333h85.333v85.333zM384 469.334h-85.333v-85.333h85.333v85.333z" />
-<glyph unicode="&#xe780;" d="M298.667 42.667h85.333v85.333h-85.333v-85.333zM128 725.334h85.333v85.333h-85.333v-85.333zM298.667 725.334h85.333v85.333h-85.333v-85.333zM298.667 384h85.333v85.333h-85.333v-85.333zM128 42.667h85.333v85.333h-85.333v-85.333zM469.333 42.667h85.333v85.333h-85.333v-85.333zM128 384h85.333v85.333h-85.333v-85.333zM128 213.334h85.333v85.333h-85.333v-85.333zM128 554.667h85.333v85.333h-85.333v-85.333zM469.333 213.334h85.333v85.333h-85.333v-85.333zM640 384h85.333v85.333h-85.333v-85.333zM810.667 810.667v-768h85.333v768h-85.333zM640 42.667h85.333v85.333h-85.333v-85.333zM640 725.334h85.333v85.333h-85.333v-85.333zM469.333 384h85.333v85.333h-85.333v-85.333zM469.333 725.334h85.333v85.333h-85.333v-85.333zM469.333 554.667h85.333v85.333h-85.333v-85.333z" />
-<glyph unicode="&#xe781;" d="M640 42.667h85.333v85.333h-85.333v-85.333zM810.667 42.667h85.333v85.333h-85.333v-85.333zM298.667 42.667h85.333v85.333h-85.333v-85.333zM469.333 42.667h85.333v85.333h-85.333v-85.333zM810.667 213.334h85.333v85.333h-85.333v-85.333zM810.667 384h85.333v85.333h-85.333v-85.333zM128 810.667v-768h85.333v682.667h682.667v85.333h-768zM810.667 554.667h85.333v85.333h-85.333v-85.333z" />
-<glyph unicode="&#xe782;" d="M298.667 42.667h85.333v85.333h-85.333v-85.333zM298.667 384h85.333v85.333h-85.333v-85.333zM469.333 384h85.333v85.333h-85.333v-85.333zM469.333 42.667h85.333v85.333h-85.333v-85.333zM128 213.334h85.333v85.333h-85.333v-85.333zM128 42.667h85.333v85.333h-85.333v-85.333zM128 384h85.333v85.333h-85.333v-85.333zM128 554.667h85.333v85.333h-85.333v-85.333zM469.333 213.334h85.333v85.333h-85.333v-85.333zM810.667 554.667h85.333v85.333h-85.333v-85.333zM810.667 384h85.333v85.333h-85.333v-85.333zM128 810.667v-85.333h768v85.333h-768zM810.667 213.334h85.333v85.333h-85.333v-85.333zM640 42.667h85.333v85.333h-85.333v-85.333zM469.333 554.667h85.333v85.333h-85.333v-85.333zM810.667 42.667h85.333v85.333h-85.333v-85.333zM640 384h85.333v85.333h-85.333v-85.333z" />
-<glyph unicode="&#xe783;" d="M128 554.667h85.333v85.333h-85.333v-85.333zM128 725.334h85.333v85.333h-85.333v-85.333zM298.667 42.667h85.333v85.333h-85.333v-85.333zM298.667 384h85.333v85.333h-85.333v-85.333zM128 384h85.333v85.333h-85.333v-85.333zM128 42.667h85.333v85.333h-85.333v-85.333zM128 213.334h85.333v85.333h-85.333v-85.333zM298.667 725.334h85.333v85.333h-85.333v-85.333zM810.667 213.334h85.333v85.333h-85.333v-85.333zM469.333 42.667h85.333v768h-85.333v-768zM810.667 42.667h85.333v85.333h-85.333v-85.333zM810.667 384h85.333v85.333h-85.333v-85.333zM810.667 810.667v-85.333h85.333v85.333h-85.333zM810.667 554.667h85.333v85.333h-85.333v-85.333zM640 725.334h85.333v85.333h-85.333v-85.333zM640 42.667h85.333v85.333h-85.333v-85.333zM640 384h85.333v85.333h-85.333v-85.333z" />
-<glyph unicode="&#xe784;" d="M298.667 298.667v-85.333h426.667v85.333h-426.667zM128 42.667h768v85.333h-768v-85.333zM128 384h768v85.333h-768v-85.333zM298.667 640v-85.333h426.667v85.333h-426.667zM128 810.667v-85.333h768v85.333h-768z" />
-<glyph unicode="&#xe785;" d="M128 42.667h768v85.333h-768v-85.333zM128 213.334h768v85.333h-768v-85.333zM128 384h768v85.333h-768v-85.333zM128 554.667h768v85.333h-768v-85.333zM128 810.667v-85.333h768v85.333h-768z" />
-<glyph unicode="&#xe786;" d="M640 298.667h-512v-85.333h512v85.333zM640 640h-512v-85.333h512v85.333zM128 384h768v85.333h-768v-85.333zM128 42.667h768v85.333h-768v-85.333zM128 810.667v-85.333h768v85.333h-768z" />
-<glyph unicode="&#xe787;" d="M128 42.667h768v85.333h-768v-85.333zM384 213.334h512v85.333h-512v-85.333zM128 384h768v85.333h-768v-85.333zM384 554.667h512v85.333h-512v-85.333zM128 810.667v-85.333h768v85.333h-768z" />
-<glyph unicode="&#xe788;" d="M665.6 478.294c41.387 28.587 70.4 75.52 70.4 119.040 0 96.427-74.667 170.667-170.667 170.667h-266.667v-597.333h300.373c89.173 0 158.293 72.533 158.293 161.707 0 64.853-36.693 120.32-91.733 145.92zM426.667 661.334h128c35.413 0 64-28.587 64-64s-28.587-64-64-64h-128v128zM576 277.334h-149.333v128h149.333c35.413 0 64-28.587 64-64s-28.587-64-64-64z" />
-<glyph unicode="&#xe789;" d="M139.52 725.334l-54.187-54.187 297.387-297.387-105.387-245.76h128l66.987 156.16 241.493-241.493 54.187 54.187-628.48 628.48zM256 725.334v-7.68l120.32-120.32h102.4l-30.72-71.68 89.6-89.6 68.693 161.28h247.040v128h-597.333z" />
-<glyph unicode="&#xe78a;" d="M706.56 557.227l-381.44 381.44-60.16-60.16 101.547-101.547-219.733-219.733c-25.173-25.173-25.173-65.707 0-90.453l234.667-234.667c12.373-12.373 29.013-18.773 45.227-18.773s32.853 6.4 45.227 18.773l234.667 234.667c25.173 24.747 25.173 65.28 0 90.453zM222.293 512l204.373 204.373 204.373-204.373h-408.747zM810.667 448s-85.333-92.587-85.333-149.333c0-46.933 38.4-85.333 85.333-85.333s85.333 38.4 85.333 85.333c0 56.747-85.333 149.333-85.333 149.333zM0 85.334h1024v-170.667h-1024z" />
-<glyph unicode="&#xe78b;" d="M768 341.334c0 170.667-256 460.8-256 460.8s-56.747-64.427-116.48-150.187l366.507-366.507c3.84 17.92 5.973 36.693 5.973 55.893zM730.453 208.214l-505.6 505.6-54.187-54.613 141.653-141.653c-32.853-61.867-56.32-124.587-56.32-176.213 0-141.227 114.773-256 256-256 64.853 0 123.733 24.32 168.96 64l112.213-112.213 54.187 54.187-116.907 116.907z" />
-<glyph unicode="&#xe78c;" d="M0 85.334h1024v-170.667h-1024zM469.333 810.667l-234.667-597.333h96l47.787 128h266.667l47.787-128h96l-234.24 597.333h-85.333zM410.453 426.667l101.547 270.080 101.547-270.080h-203.093z" />
-<glyph unicode="&#xe78d;" d="M469.333 213.334h426.667v85.333h-426.667v-85.333zM128 426.667l170.667-170.667v341.333l-170.667-170.667zM128 42.667h768v85.333h-768v-85.333zM128 810.667v-85.333h768v85.333h-768zM469.333 554.667h426.667v85.333h-426.667v-85.333zM469.333 384h426.667v85.333h-426.667v-85.333z" />
-<glyph unicode="&#xe78e;" d="M128 42.667h768v85.333h-768v-85.333zM128 597.334v-341.333l170.667 170.667-170.667 170.667zM469.333 213.334h426.667v85.333h-426.667v-85.333zM128 810.667v-85.333h768v85.333h-768zM469.333 554.667h426.667v85.333h-426.667v-85.333zM469.333 384h426.667v85.333h-426.667v-85.333z" />
-<glyph unicode="&#xe78f;" d="M426.667 768v-128h94.293l-145.92-341.333h-119.040v-128h341.333v128h-94.293l145.92 341.333h119.040v128z" />
-<glyph unicode="&#xe790;" d="M256 640h106.667l-149.333 149.333-149.333-149.333h106.667v-426.667h-106.667l149.333-149.333 149.333 149.333h-106.667v426.667zM426.667 725.334v-85.333h512v85.333h-512zM426.667 128h512v85.333h-512v-85.333zM426.667 384h512v85.333h-512v-85.333z" />
-<glyph unicode="&#xe791;" d="M170.667 490.667c-35.413 0-64-28.587-64-64s28.587-64 64-64 64 28.587 64 64-28.587 64-64 64zM170.667 746.667c-35.413 0-64-28.587-64-64s28.587-64 64-64 64 28.587 64 64-28.587 64-64 64zM170.667 227.414c-31.573 0-56.747-25.6-56.747-56.747s25.6-56.747 56.747-56.747 56.747 25.6 56.747 56.747-25.173 56.747-56.747 56.747zM298.667 128h597.333v85.333h-597.333v-85.333zM298.667 384h597.333v85.333h-597.333v-85.333zM298.667 725.334v-85.333h597.333v85.333h-597.333z" />
-<glyph unicode="&#xe792;" d="M85.333 213.334h85.333v-21.333h-42.667v-42.667h42.667v-21.333h-85.333v-42.667h128v170.667h-128v-42.667zM128 597.334h42.667v170.667h-85.333v-42.667h42.667v-128zM85.333 469.334h76.8l-76.8-89.6v-38.4h128v42.667h-76.8l76.8 89.6v38.4h-128v-42.667zM298.667 725.334v-85.333h597.333v85.333h-597.333zM298.667 128h597.333v85.333h-597.333v-85.333zM298.667 384h597.333v85.333h-597.333v-85.333z" />
-<glyph unicode="&#xe793;" d="M768 768v42.667c0 23.467-19.2 42.667-42.667 42.667h-512c-23.467 0-42.667-19.2-42.667-42.667v-170.667c0-23.467 19.2-42.667 42.667-42.667h512c23.467 0 42.667 19.2 42.667 42.667v42.667h42.667v-170.667h-426.667v-469.333c0-23.467 19.2-42.667 42.667-42.667h85.333c23.467 0 42.667 19.2 42.667 42.667v384h341.333v341.333h-128z" />
-<glyph unicode="&#xe794;" d="M256 213.334h128l85.333 170.667v256h-256v-256h128zM597.333 213.334h128l85.333 170.667v256h-256v-256h128z" />
-<glyph unicode="&#xe795;" d="M384 768v-128h213.333v-512h128v512h213.333v128h-554.667zM128 426.667h128v-298.667h128v298.667h128v128h-384v-128z" />
-<glyph unicode="&#xe796;" d="M426.667 128h170.667v128h-170.667v-128zM213.333 768v-128h213.333v-128h170.667v128h213.333v128h-597.333zM128 341.334h768v85.333h-768v-85.333z" />
-<glyph unicode="&#xe797;" d="M384 512v-213.333h85.333v469.333h85.333v-469.333h85.333v469.333h85.333v85.333h-341.333c-94.293 0-170.667-76.373-170.667-170.667s76.373-170.667 170.667-170.667zM896 170.667l-170.667 170.667v-128h-512v-85.333h512v-128l170.667 170.667z" />
-<glyph unicode="&#xe798;" d="M426.667 512v-213.333h85.333v469.333h85.333v-469.333h85.333v469.333h85.333v85.333h-341.333c-94.293 0-170.667-76.373-170.667-170.667s76.373-170.667 170.667-170.667zM341.333 213.334v128l-170.667-170.667 170.667-170.667v128h512v85.333h-512z" />
-<glyph unicode="&#xe799;" d="M512 213.334c141.227 0 256 114.773 256 256v341.333h-106.667v-341.333c0-82.347-66.987-149.333-149.333-149.333s-149.333 66.987-149.333 149.333v341.333h-106.667v-341.333c0-141.227 114.773-256 256-256zM213.333 128v-85.333h597.333v85.333h-597.333z" />
-<glyph unicode="&#xe79a;" d="M768 768h-512v-85.333l277.333-256-277.333-256v-85.333h512v128h-298.667l213.333 213.333-213.333 213.333h298.667z" />
-<glyph unicode="&#xe79b;" d="M810.667 810.667h-597.333c-46.933 0-85.333-38.4-85.333-85.333v-597.333c0-46.933 38.4-85.333 85.333-85.333h597.333c46.933 0 85.333 38.4 85.333 85.333v597.333c0 46.933-38.4 85.333-85.333 85.333zM384 213.334h-85.333v298.667h85.333v-298.667zM554.667 213.334h-85.333v426.667h85.333v-426.667zM725.333 213.334h-85.333v170.667h85.333v-170.667z" />
-<glyph unicode="&#xe79c;" d="M853.333 853.334h-682.667c-46.933 0-85.333-38.4-85.333-85.333v-512c0-46.933 38.4-85.333 85.333-85.333h597.333l170.667-170.667v768c0 46.933-38.4 85.333-85.333 85.333zM768 341.334h-512v85.333h512v-85.333zM768 469.334h-512v85.333h512v-85.333zM768 597.334h-512v85.333h512v-85.333z" />
-<glyph unicode="&#xe79d;" d="M256 853.334c-46.933 0-84.907-38.4-84.907-85.333l-0.427-682.667c0-46.933 37.973-85.333 84.907-85.333h512.427c46.933 0 85.333 38.4 85.333 85.333v512l-256 256h-341.333zM554.667 554.667v234.667l234.667-234.667h-234.667z" />
-<glyph unicode="&#xe79e;" d="M511.573 853.334c-235.52 0-426.24-191.147-426.24-426.667s190.72-426.667 426.24-426.667c235.947 0 427.093 191.147 427.093 426.667s-191.147 426.667-427.093 426.667zM512 85.334c-188.587 0-341.333 152.747-341.333 341.333s152.747 341.333 341.333 341.333 341.333-152.747 341.333-341.333-152.747-341.333-341.333-341.333zM661.333 469.334c35.413 0 64 28.587 64 64s-28.587 64-64 64-64-28.587-64-64 28.587-64 64-64zM362.667 469.334c35.413 0 64 28.587 64 64s-28.587 64-64 64-64-28.587-64-64 28.587-64 64-64zM512 192c99.413 0 183.893 62.293 218.027 149.333h-436.053c34.133-87.040 118.613-149.333 218.027-149.333z" />
-<glyph unicode="&#xe79f;" d="M725.333 426.667h-213.333v-213.333h213.333v213.333zM682.667 896v-85.333h-341.333v85.333h-85.333v-85.333h-42.667c-47.36 0-84.907-38.4-84.907-85.333l-0.427-597.333c0-46.933 37.973-85.333 85.333-85.333h597.333c46.933 0 85.333 38.4 85.333 85.333v597.333c0 46.933-38.4 85.333-85.333 85.333h-42.667v85.333h-85.333zM810.667 128h-597.333v469.333h597.333v-469.333z" />
-<glyph unicode="&#xe7a0;" d="M166.4 426.667c0 72.96 59.307 132.267 132.267 132.267h170.667v81.067h-170.667c-117.76 0-213.333-95.573-213.333-213.333s95.573-213.333 213.333-213.333h170.667v81.067h-170.667c-72.96 0-132.267 59.307-132.267 132.267zM341.333 384h341.333v85.333h-341.333v-85.333zM725.333 640h-170.667v-81.067h170.667c72.96 0 132.267-59.307 132.267-132.267s-59.307-132.267-132.267-132.267h-170.667v-81.067h170.667c117.76 0 213.333 95.573 213.333 213.333s-95.573 213.333-213.333 213.333z" />
-<glyph unicode="&#xe7a1;" d="M896 128v597.333c0 46.933-38.4 85.333-85.333 85.333h-597.333c-46.933 0-85.333-38.4-85.333-85.333v-597.333c0-46.933 38.4-85.333 85.333-85.333h597.333c46.933 0 85.333 38.4 85.333 85.333zM362.667 362.667l106.667-128.427 149.333 192.427 192-256h-597.333l149.333 192z" />
-<glyph unicode="&#xe7a2;" d="M725.333 67.84l60.16 60.16-145.493 145.493-60.16-60.16 145.493-145.493zM320 597.334h149.333v-238.507l-230.827-230.827 60.16-60.16 256 256v273.493h149.333l-192 192-192-192z" />
-<glyph unicode="&#xe7a3;" d="M938.24 768c0 46.933-37.973 85.333-84.907 85.333h-682.667c-46.933 0-85.333-38.4-85.333-85.333v-512c0-46.933 38.4-85.333 85.333-85.333h597.333l170.667-170.667-0.427 768z" />
-<glyph unicode="&#xe7a4;" d="M128 202.667v-160h160l471.893 471.893-160 160-471.893-471.893zM883.627 638.294c16.64 16.64 16.64 43.52 0 60.16l-99.84 99.84c-16.64 16.64-43.52 16.64-60.16 0l-78.080-78.080 160-160 78.080 78.080z" />
-<glyph unicode="&#xe7a5;" d="M213.333 768v-85.333h597.333v85.333h-597.333zM213.333 341.334h170.667v-256h256v256h170.667l-298.667 298.667-298.667-298.667z" />
-<glyph unicode="&#xe7a6;" d="M682.667 384h-128v426.667h-85.333v-426.667h-128l170.667-170.667 170.667 170.667zM170.667 128v-85.333h682.667v85.333h-682.667z" />
-<glyph unicode="&#xe7a7;" d="M341.333 128h128v-170.667h85.333v170.667h128l-170.667 170.667-170.667-170.667zM682.667 725.334h-128v170.667h-85.333v-170.667h-128l170.667-170.667 170.667 170.667zM170.667 469.334v-85.333h682.667v85.333h-682.667z" />
-<glyph unicode="&#xe7a8;" d="M341.333 469.334h128v-426.667h85.333v426.667h128l-170.667 170.667-170.667-170.667zM170.667 810.667v-85.333h682.667v85.333h-682.667z" />
-<glyph unicode="&#xe7a9;" d="M170.667 128h256v85.333h-256v-85.333zM853.333 725.334h-682.667v-85.333h682.667v85.333zM725.333 469.334h-554.667v-85.333h565.333c46.933 0 85.333-38.4 85.333-85.333s-38.4-85.333-85.333-85.333h-96v85.333l-128-128 128-128v85.333h85.333c94.293 0 170.667 76.373 170.667 170.667s-76.373 170.667-170.667 170.667z" />
-<glyph unicode="&#xe7aa;" d="M320 170.667c-129.707 0-234.667 104.96-234.667 234.667s104.96 234.667 234.667 234.667h448c94.293 0 170.667-76.373 170.667-170.667s-76.373-170.667-170.667-170.667h-362.667c-58.88 0-106.667 47.787-106.667 106.667s47.787 106.667 106.667 106.667h320v-64h-320c-23.467 0-42.667-19.2-42.667-42.667s19.2-42.667 42.667-42.667h362.667c58.88 0 106.667 47.787 106.667 106.667s-47.787 106.667-106.667 106.667h-448c-94.293 0-170.667-76.373-170.667-170.667s76.373-170.667 170.667-170.667h405.333v-64h-405.333z" />
-<glyph unicode="&#xe7ab;" d="M512 853.334c-235.52 0-426.667-191.147-426.667-426.667s191.147-426.667 426.667-426.667 426.667 191.147 426.667 426.667-191.147 426.667-426.667 426.667zM704 256h-362.667c-70.827 0-128 57.173-128 128s57.173 128 128 128l5.973-0.427c18.773 73.813 84.907 128.427 164.693 128.427 94.293 0 170.667-76.373 170.667-170.667h21.333c58.88 0 106.667-47.787 106.667-106.667s-47.787-106.667-106.667-106.667z" />
-<glyph unicode="&#xe7ac;" d="M825.6 510.294c-29.013 147.2-158.293 257.707-313.6 257.707-123.307 0-230.4-69.973-283.733-172.373-128.427-13.653-228.267-122.453-228.267-254.293 0-141.227 114.773-256 256-256h554.667c117.76 0 213.333 95.573 213.333 213.333 0 112.64-87.467 203.947-198.4 211.627zM426.667 213.334l-149.333 149.333 60.16 60.16 89.173-88.747 221.013 220.587 60.16-60.16-281.173-281.173z" />
-<glyph unicode="&#xe7ad;" d="M825.6 510.294c-29.013 147.2-158.293 257.707-313.6 257.707-123.307 0-230.4-69.973-283.733-172.373-128.427-13.653-228.267-122.453-228.267-254.293 0-141.227 114.773-256 256-256h554.667c117.76 0 213.333 95.573 213.333 213.333 0 112.64-87.467 203.947-198.4 211.627zM725.333 384l-213.333-213.333-213.333 213.333h128v170.667h170.667v-170.667h128z" />
-<glyph unicode="&#xe7ae;" d="M825.6 510.294c-29.013 147.2-158.293 257.707-313.6 257.707-63.147 0-121.6-18.347-171.093-49.92l62.293-62.293c32.427 17.067 69.547 26.88 108.8 26.88 129.707 0 234.667-104.96 234.667-234.667v-21.333h64c70.827 0 128-57.173 128-128 0-48.213-27.307-90.027-66.56-111.787l61.867-61.867c54.187 38.827 90.027 101.973 90.027 173.653 0 112.64-87.467 203.947-198.4 211.627zM128 713.814l117.333-116.907c-136.107-5.973-245.333-117.76-245.333-255.573 0-141.227 114.773-256 256-256h500.48l85.333-85.333 54.187 54.187-713.813 713.813-54.187-54.187zM329.813 512l341.333-341.333h-415.147c-94.293 0-170.667 76.373-170.667 170.667s76.373 170.667 170.667 170.667h73.813z" />
-<glyph unicode="&#xe7af;" d="M825.6 510.294c-29.013 147.2-158.293 257.707-313.6 257.707-123.307 0-230.4-69.973-283.733-172.373-128.427-13.653-228.267-122.453-228.267-254.293 0-141.227 114.773-256 256-256h554.667c117.76 0 213.333 95.573 213.333 213.333 0 112.64-87.467 203.947-198.4 211.627zM810.667 170.667h-554.667c-94.293 0-170.667 76.373-170.667 170.667s76.373 170.667 170.667 170.667h30.293c28.16 98.56 118.187 170.667 225.707 170.667 129.707 0 234.667-104.96 234.667-234.667v-21.333h64c70.827 0 128-57.173 128-128s-57.173-128-128-128z" />
-<glyph unicode="&#xe7b0;" d="M825.6 510.294c-29.013 147.2-158.293 257.707-313.6 257.707-123.307 0-230.4-69.973-283.733-172.373-128.427-13.653-228.267-122.453-228.267-254.293 0-141.227 114.773-256 256-256h554.667c117.76 0 213.333 95.573 213.333 213.333 0 112.64-87.467 203.947-198.4 211.627zM597.333 384v-170.667h-170.667v170.667h-128l213.333 213.333 213.333-213.333h-128z" />
-<glyph unicode="&#xe7b1;" d="M825.6 510.294c-29.013 147.2-158.293 257.707-313.6 257.707-123.307 0-230.4-69.973-283.733-172.373-128.427-13.653-228.267-122.453-228.267-254.293 0-141.227 114.773-256 256-256h554.667c117.76 0 213.333 95.573 213.333 213.333 0 112.64-87.467 203.947-198.4 211.627z" />
-<glyph unicode="&#xe7b2;" d="M810.667 554.667h-170.667v256h-256v-256h-170.667l298.667-298.667 298.667 298.667zM213.333 170.667v-85.333h597.333v85.333h-597.333z" />
-<glyph unicode="&#xe7b3;" d="M384 256h256v256h170.667l-298.667 298.667-298.667-298.667h170.667zM213.333 170.667h597.333v-85.333h-597.333z" />
-<glyph unicode="&#xe7b4;" d="M853.333 682.667h-341.333l-85.333 85.333h-256c-46.933 0-84.907-38.4-84.907-85.333l-0.427-512c0-46.933 38.4-85.333 85.333-85.333h682.667c46.933 0 85.333 38.4 85.333 85.333v426.667c0 46.933-38.4 85.333-85.333 85.333zM853.333 170.667h-682.667v426.667h682.667v-426.667z" />
-<glyph unicode="&#xe7b5;" d="M853.333 682.667h-341.333l-85.333 85.333h-256c-46.933 0-84.907-38.4-84.907-85.333l-0.427-512c0-46.933 38.4-85.333 85.333-85.333h682.667c46.933 0 85.333 38.4 85.333 85.333v426.667c0 46.933-38.4 85.333-85.333 85.333zM640 554.667c46.933 0 85.333-38.4 85.333-85.333s-38.4-85.333-85.333-85.333-85.333 38.4-85.333 85.333 38.4 85.333 85.333 85.333zM810.667 213.334h-341.333v42.667c0 56.747 113.92 85.333 170.667 85.333s170.667-28.587 170.667-85.333v-42.667z" />
-<glyph unicode="&#xe7b6;" d="M426.667 768h-256c-46.933 0-84.907-38.4-84.907-85.333l-0.427-512c0-46.933 38.4-85.333 85.333-85.333h682.667c46.933 0 85.333 38.4 85.333 85.333v426.667c0 46.933-38.4 85.333-85.333 85.333h-341.333l-85.333 85.333z" />
-<glyph unicode="&#xe7b7;" d="M42.667 170.667v-128h128c0 70.827-57.173 128-128 128zM42.667 341.334v-85.333c117.76 0 213.333-95.573 213.333-213.333h85.333c0 165.12-133.547 298.667-298.667 298.667zM810.667 640h-597.333v-69.547c168.96-54.613 302.507-188.16 357.12-357.12h240.213v426.667zM42.667 512v-85.333c212.053 0 384-171.947 384-384h85.333c0 259.413-210.347 469.333-469.333 469.333zM896 810.667h-768c-46.933 0-85.333-38.4-85.333-85.333v-128h85.333v128h768v-597.333h-298.667v-85.333h298.667c46.933 0 85.333 38.4 85.333 85.333v597.333c0 46.933-38.4 85.333-85.333 85.333z" />
-<glyph unicode="&#xe7b8;" d="M896 810.667h-768c-46.933 0-85.333-38.4-85.333-85.333v-128h85.333v128h768v-597.333h-298.667v-85.333h298.667c46.933 0 85.333 38.4 85.333 85.333v597.333c0 46.933-38.4 85.333-85.333 85.333zM42.667 170.667v-128h128c0 70.827-57.173 128-128 128zM42.667 341.334v-85.333c117.76 0 213.333-95.573 213.333-213.333h85.333c0 165.12-133.547 298.667-298.667 298.667zM42.667 512v-85.333c212.053 0 384-171.947 384-384h85.333c0 259.413-210.347 469.333-469.333 469.333z" />
-<glyph unicode="&#xe7b9;" d="M853.333 170.667c46.933 0 84.907 38.4 84.907 85.333l0.427 426.667c0 46.933-38.4 85.333-85.333 85.333h-682.667c-46.933 0-85.333-38.4-85.333-85.333v-426.667c0-46.933 38.4-85.333 85.333-85.333h-170.667v-85.333h1024v85.333h-170.667zM170.667 682.667h682.667v-426.667h-682.667v426.667z" />
-<glyph unicode="&#xe7ba;" d="M896 853.334h-768c-46.933 0-85.333-38.4-85.333-85.333v-512c0-46.933 38.4-85.333 85.333-85.333h298.667l-85.333-128v-42.667h341.333v42.667l-85.333 128h298.667c46.933 0 85.333 38.4 85.333 85.333v512c0 46.933-38.4 85.333-85.333 85.333zM896 341.334h-768v426.667h768v-426.667z" />
-<glyph unicode="&#xe7bb;" d="M896 853.334h-768c-46.933 0-85.333-38.4-85.333-85.333v-512c0-46.933 38.4-85.333 85.333-85.333h298.667v-85.333h-85.333v-85.333h341.333v85.333h-85.333v85.333h298.667c46.933 0 85.333 38.4 85.333 85.333v512c0 46.933-38.4 85.333-85.333 85.333zM896 256h-768v512h768v-512z" />
-<glyph unicode="&#xe7bc;" d="M341.333-42.666h341.333v85.333h-341.333v-85.333zM682.667 895.574l-341.333 0.427c-46.933 0-85.333-38.4-85.333-85.333v-597.333c0-46.933 38.4-85.333 85.333-85.333h341.333c46.933 0 85.333 38.4 85.333 85.333v597.333c0 46.933-38.4 84.907-85.333 84.907zM682.667 298.667h-341.333v426.667h341.333v-426.667z" />
-<glyph unicode="&#xe7bd;" d="M640 618.667v234.667h-256v-234.667l128-128 128 128zM320 554.667h-234.667v-256h234.667l128 128-128 128zM384 234.667v-234.667h256v234.667l-128 128-128-128zM704 554.667l-128-128 128-128h234.667v256h-234.667z" />
-<glyph unicode="&#xe7be;" d="M512 896c-212.053 0-384-171.947-384-384v-298.667c0-70.827 57.173-128 128-128h128v341.333h-170.667v85.333c0 165.12 133.547 298.667 298.667 298.667s298.667-133.547 298.667-298.667v-85.333h-170.667v-341.333h170.667v-42.667h-298.667v-85.333h256c70.827 0 128 57.173 128 128v426.667c0 212.053-171.947 384-384 384z" />
-<glyph unicode="&#xe7bf;" d="M512 896c-212.053 0-384-171.947-384-384v-298.667c0-70.827 57.173-128 128-128h128v341.333h-170.667v85.333c0 165.12 133.547 298.667 298.667 298.667s298.667-133.547 298.667-298.667v-85.333h-170.667v-341.333h128c70.827 0 128 57.173 128 128v298.667c0 212.053-171.947 384-384 384z" />
-<glyph unicode="&#xe7c0;" d="M661.333 512c35.413 0 64 28.587 64 64s-28.587 64-64 64-64-28.587-64-64 28.587-64 64-64zM362.667 512c35.413 0 64 28.587 64 64s-28.587 64-64 64-64-28.587-64-64 28.587-64 64-64zM512 213.334c111.36 0 206.080 71.253 241.067 170.667h-482.133c34.987-99.413 129.707-170.667 241.067-170.667zM511.573 896c-235.52 0-426.24-191.147-426.24-426.667s190.72-426.667 426.24-426.667c235.947 0 427.093 191.147 427.093 426.667s-191.147 426.667-427.093 426.667zM512 128c-188.587 0-341.333 152.747-341.333 341.333s152.747 341.333 341.333 341.333 341.333-152.747 341.333-341.333-152.747-341.333-341.333-341.333z" />
-<glyph unicode="&#xe7c1;" d="M316.16 604.16l195.84-195.413 195.84 195.413 60.16-60.16-256-256-256 256z" />
-<glyph unicode="&#xe7c2;" d="M657.493 252.16l-195.413 195.84 195.413 195.84-60.16 60.16-256-256 256-256z" />
-<glyph unicode="&#xe7c3;" d="M366.507 241.494l195.413 195.84-195.413 195.84 60.16 60.16 256-256-256-256z" />
-<glyph unicode="&#xe7c4;" d="M316.16 281.174l195.84 195.413 195.84-195.413 60.16 60.16-256 256-256-256z" />
-<glyph unicode="&#xe7c5;" d="M896 469.334h-604.587l152.747 153.173-60.16 60.16-256-256 256-256 60.16 60.16-152.747 153.173h604.587z" />
-<glyph unicode="&#xe7c6;" d="M512 579.84l195.84-195.84 60.16 60.16-256 256-256-256 60.16-60.16 195.84 195.84zM256 170.667h512v85.333h-512v-85.333z" />
-<glyph unicode="&#xe7c7;" d="M256 512c-46.933 0-85.333-38.4-85.333-85.333s38.4-85.333 85.333-85.333 85.333 38.4 85.333 85.333-38.4 85.333-85.333 85.333zM768 512c-46.933 0-85.333-38.4-85.333-85.333s38.4-85.333 85.333-85.333 85.333 38.4 85.333 85.333-38.4 85.333-85.333 85.333zM512 512c-46.933 0-85.333-38.4-85.333-85.333s38.4-85.333 85.333-85.333 85.333 38.4 85.333 85.333-38.4 85.333-85.333 85.333z" />
-<glyph unicode="&#xe7c8;" d="M853.333 810.667h-682.667c-46.933 0-84.907-38.4-84.907-85.333l-0.427-426.667c0-46.933 38.4-85.333 85.333-85.333h682.667c46.933 0 85.333 38.4 85.333 85.333v426.667c0 46.933-38.4 85.333-85.333 85.333zM469.333 682.667h85.333v-85.333h-85.333v85.333zM469.333 554.667h85.333v-85.333h-85.333v85.333zM341.333 682.667h85.333v-85.333h-85.333v85.333zM341.333 554.667h85.333v-85.333h-85.333v85.333zM298.667 469.334h-85.333v85.333h85.333v-85.333zM298.667 597.334h-85.333v85.333h85.333v-85.333zM682.667 298.667h-341.333v85.333h341.333v-85.333zM682.667 469.334h-85.333v85.333h85.333v-85.333zM682.667 597.334h-85.333v85.333h85.333v-85.333zM810.667 469.334h-85.333v85.333h85.333v-85.333zM810.667 597.334h-85.333v85.333h85.333v-85.333zM512-42.666l170.667 170.667h-341.333l170.667-170.667z" />
-<glyph unicode="&#xe7c9;" d="M810.667 640v-170.667h-561.92l152.747 153.173-60.16 60.16-256-256 256-256 60.16 60.16-152.747 153.173h647.253v256z" />
-<glyph unicode="&#xe7ca;" d="M494.507 622.507l152.747-153.173h-604.587v-85.333h604.587l-153.173-153.173 60.587-60.16 256 256-256 256-60.16-60.16zM853.333 682.667v-512h85.333v512h-85.333z" />
-<glyph unicode="&#xe7cb;" d="M512 298.667c70.827 0 127.573 57.173 127.573 128l0.427 256c0 70.827-57.173 128-128 128s-128-57.173-128-128v-256c0-70.827 57.173-128 128-128zM738.133 426.667c0-128-108.373-217.6-226.133-217.6s-226.133 89.6-226.133 217.6h-72.533c0-145.92 116.053-265.813 256-286.72v-139.947h85.333v139.947c139.947 20.48 256 140.8 256 286.72h-72.533z" />
-<glyph unicode="&#xe7cc;" d="M853.333 725.334h-682.667c-46.933 0-84.907-38.4-84.907-85.333l-0.427-426.667c0-46.933 38.4-85.333 85.333-85.333h682.667c46.933 0 85.333 38.4 85.333 85.333v426.667c0 46.933-38.4 85.333-85.333 85.333zM469.333 597.334h85.333v-85.333h-85.333v85.333zM469.333 469.334h85.333v-85.333h-85.333v85.333zM341.333 597.334h85.333v-85.333h-85.333v85.333zM341.333 469.334h85.333v-85.333h-85.333v85.333zM298.667 384h-85.333v85.333h85.333v-85.333zM298.667 512h-85.333v85.333h85.333v-85.333zM682.667 213.334h-341.333v85.333h341.333v-85.333zM682.667 384h-85.333v85.333h85.333v-85.333zM682.667 512h-85.333v85.333h85.333v-85.333zM810.667 384h-85.333v85.333h85.333v-85.333zM810.667 512h-85.333v85.333h85.333v-85.333z" />
-<glyph unicode="&#xe7cd;" d="M938.667 170.667v640h-853.333v-640h-85.333v-85.333h1024v85.333h-85.333zM597.333 170.667h-170.667v42.667h170.667v-42.667zM853.333 298.667h-682.667v426.667h682.667v-426.667z" />
-<glyph unicode="&#xe7ce;" d="M853.333 170.667c46.933 0 84.907 38.4 84.907 85.333l0.427 469.333c0 46.933-38.4 85.333-85.333 85.333h-682.667c-46.933 0-85.333-38.4-85.333-85.333v-469.333c0-46.933 38.4-85.333 85.333-85.333h-170.667c0-46.933 38.4-85.333 85.333-85.333h853.333c46.933 0 85.333 38.4 85.333 85.333h-170.667zM170.667 725.334h682.667v-469.333h-682.667v469.333zM512 128c-23.467 0-42.667 19.2-42.667 42.667s19.2 42.667 42.667 42.667 42.667-19.2 42.667-42.667-19.2-42.667-42.667-42.667z" />
-<glyph unicode="&#xe7cf;" d="M853.333 170.667v42.667c46.933 0 84.907 38.4 84.907 85.333l0.427 426.667c0 46.933-38.4 85.333-85.333 85.333h-682.667c-46.933 0-85.333-38.4-85.333-85.333v-426.667c0-46.933 38.4-85.333 85.333-85.333v-42.667h-170.667v-85.333h1024v85.333h-170.667zM170.667 725.334h682.667v-426.667h-682.667v426.667z" />
-<glyph unicode="&#xe7d0;" d="M853.333 170.667c46.933 0 85.333 38.4 85.333 85.333v426.667c0 46.933-38.4 85.333-85.333 85.333h-682.667c-46.933 0-85.333-38.4-85.333-85.333v-426.667c0-46.933 38.4-85.333 85.333-85.333h-170.667v-85.333h1024v85.333h-170.667zM170.667 682.667h682.667v-426.667h-682.667v426.667z" />
-<glyph unicode="&#xe7d1;" d="M640 554.667h-256v-256h256v256zM554.667 384h-85.333v85.333h85.333v-85.333zM896 469.334v85.333h-85.333v85.333c0 46.933-38.4 85.333-85.333 85.333h-85.333v85.333h-85.333v-85.333h-85.333v85.333h-85.333v-85.333h-85.333c-46.933 0-85.333-38.4-85.333-85.333v-85.333h-85.333v-85.333h85.333v-85.333h-85.333v-85.333h85.333v-85.333c0-46.933 38.4-85.333 85.333-85.333h85.333v-85.333h85.333v85.333h85.333v-85.333h85.333v85.333h85.333c46.933 0 85.333 38.4 85.333 85.333v85.333h85.333v85.333h-85.333v85.333h85.333zM725.333 213.334h-426.667v426.667h426.667v-426.667z" />
-<glyph unicode="&#xe7d2;" d="M554.667 893.014v-338.347h298.667c0 174.080-130.133 317.44-298.667 338.347zM170.667 298.667c0-188.587 152.747-341.333 341.333-341.333s341.333 152.747 341.333 341.333v170.667h-682.667v-170.667zM469.333 893.014c-168.533-20.907-298.667-164.267-298.667-338.347h298.667v338.347z" />
-<glyph unicode="&#xe7d3;" d="M682.667 896h-341.333c-70.827 0-128-57.173-128-128v-682.667c0-70.827 57.173-128 128-128h341.333c70.827 0 128 57.173 128 128v682.667c0 70.827-57.173 128-128 128zM597.333 42.667h-170.667v42.667h170.667v-42.667zM736 170.667h-448v597.333h448v-597.333z" />
-<glyph unicode="&#xe7d4;" d="M661.333 896h-341.333c-58.88 0-106.667-47.787-106.667-106.667v-725.333c0-58.88 47.787-106.667 106.667-106.667h341.333c58.88 0 106.667 47.787 106.667 106.667v725.333c0 58.88-47.787 106.667-106.667 106.667zM490.667-0c-35.413 0-64 28.587-64 64s28.587 64 64 64 64-28.587 64-64-28.587-64-64-64zM682.667 170.667h-384v597.333h384v-597.333z" />
-<glyph unicode="&#xe7d5;" d="M938.667 682.667v85.333h-647.68l85.333-85.333h562.347zM81.92 868.267l-54.187-54.187 77.653-77.653c-12.373-14.507-20.053-33.28-20.053-53.76v-469.333h-85.333v-128h756.48l100.267-100.267 54.187 54.187-829.013 829.013zM170.667 671.147l457.813-457.813h-457.813v457.813zM981.333 597.334h-256c-23.467 0-42.667-19.2-42.667-42.667v-178.347l85.333-85.333v221.013h170.667v-298.667h-93.013l128-128h7.68c23.467 0 42.667 19.2 42.667 42.667v426.667c0 23.467-19.2 42.667-42.667 42.667z" />
-<glyph unicode="&#xe7d6;" d="M170.667 682.667h768v85.333h-768c-46.933 0-85.333-38.4-85.333-85.333v-469.333h-85.333v-128h597.333v128h-426.667v469.333zM981.333 597.334h-256c-23.467 0-42.667-19.2-42.667-42.667v-426.667c0-23.467 19.2-42.667 42.667-42.667h256c23.467 0 42.667 19.2 42.667 42.667v426.667c0 23.467-19.2 42.667-42.667 42.667zM938.667 213.334h-170.667v298.667h170.667v-298.667z" />
-<glyph unicode="&#xe7d7;" d="M512 896l-384-170.667v-256c0-236.8 163.84-458.24 384-512 220.16 53.76 384 275.2 384 512v256l-384 170.667zM512 427.094h298.667c-22.613-175.787-139.947-332.373-298.667-381.44v381.013h-298.667v243.2l298.667 132.693v-375.467z" />
-<glyph unicode="&#xe7d8;" d="M852.907 768c0 46.933-37.973 85.333-84.907 85.333h-341.333l-256-256v-512c0-46.933 38.4-85.333 85.333-85.333h512.427c46.933 0 84.907 38.4 84.907 85.333l-0.427 682.667zM384 128h-85.333v85.333h85.333v-85.333zM725.333 128h-85.333v85.333h85.333v-85.333zM384 298.667h-85.333v170.667h85.333v-170.667zM554.667 128h-85.333v170.667h85.333v-170.667zM554.667 384h-85.333v85.333h85.333v-85.333zM725.333 298.667h-85.333v170.667h85.333v-170.667z" />
-<glyph unicode="&#xe7d9;" d="M725.333 895.574l-426.667 0.427c-46.933 0-85.333-38.4-85.333-85.333v-768c0-46.933 38.4-85.333 85.333-85.333h426.667c46.933 0 85.333 38.4 85.333 85.333v768c0 46.933-38.4 84.907-85.333 84.907zM725.333 128h-426.667v597.333h426.667v-597.333z" />
-<glyph unicode="&#xe7da;" d="M725.333 853.334h-426.667c-46.933 0-85.333-38.4-85.333-85.333v-682.667c0-46.933 38.4-84.907 85.333-84.907l426.667-0.427c46.933 0 85.333 38.4 85.333 85.333v682.667c0 46.933-38.4 85.333-85.333 85.333zM512 768c46.933 0 85.333-38.4 85.333-85.333s-38.4-85.333-85.333-85.333c-47.36 0-85.333 38.4-85.333 85.333s37.973 85.333 85.333 85.333zM512 85.334c-117.76 0-213.333 95.573-213.333 213.333s95.573 213.333 213.333 213.333 213.333-95.573 213.333-213.333-95.573-213.333-213.333-213.333zM512 426.667c-70.827 0-128-57.173-128-128s57.173-128 128-128 128 57.173 128 128-57.173 128-128 128z" />
-<glyph unicode="&#xe7db;" d="M768 938.667h-512c-70.827 0-128-57.173-128-128v-768c0-70.827 57.173-128 128-128h512c70.827 0 128 57.173 128 128v768c0 70.827-57.173 128-128 128zM597.333-0h-170.667v42.667h170.667v-42.667zM821.333 128h-618.667v682.667h618.667v-682.667z" />
-<glyph unicode="&#xe7dc;" d="M789.333 938.667h-597.333c-58.88 0-106.667-47.787-106.667-106.667v-810.667c0-58.88 47.787-106.667 106.667-106.667h597.333c58.88 0 106.667 47.787 106.667 106.667v810.667c0 58.88-47.787 106.667-106.667 106.667zM490.667-42.666c-35.413 0-64 28.587-64 64s28.587 64 64 64 64-28.587 64-64-28.587-64-64-64zM810.667 128h-640v682.667h640v-682.667z" />
-<glyph unicode="&#xe7dd;" d="M896 768h-768c-46.933 0-85.333-38.4-85.333-85.333v-512c0-46.933 38.4-85.333 85.333-85.333h768c46.933 0 84.907 38.4 84.907 85.333l0.427 512c0 46.933-38.4 85.333-85.333 85.333zM810.667 170.667h-597.333v512h597.333v-512z" />
-<glyph unicode="&#xe7de;" d="M896 810.667h-768c-46.933 0-85.333-38.4-85.333-85.333v-512c0-46.933 38.4-85.333 85.333-85.333h213.333v-85.333h341.333v85.333h213.333c46.933 0 84.907 38.4 84.907 85.333l0.427 512c0 46.933-38.4 85.333-85.333 85.333zM896 213.334h-768v512h768v-512z" />
-<glyph unicode="&#xe7df;" d="M853.333 426.667c0 108.373-50.773 205.227-129.707 267.52l-40.96 244.48h-341.333l-40.533-244.48c-79.36-62.293-130.133-158.72-130.133-267.52s50.773-205.227 130.133-267.52l40.533-244.48h341.333l40.96 244.48c78.933 62.293 129.707 159.147 129.707 267.52zM256 426.667c0 141.227 114.773 256 256 256s256-114.773 256-256-114.773-256-256-256-256 114.773-256 256z" />
-<glyph unicode="&#xe7e0;" d="M170.667 682.667h-85.333v-597.333c0-46.933 38.4-85.333 85.333-85.333h597.333v85.333h-597.333v597.333zM853.333 853.334h-512c-46.933 0-85.333-38.4-85.333-85.333v-512c0-46.933 38.4-85.333 85.333-85.333h512c46.933 0 85.333 38.4 85.333 85.333v512c0 46.933-38.4 85.333-85.333 85.333zM810.667 469.334h-170.667v-170.667h-85.333v170.667h-170.667v85.333h170.667v170.667h85.333v-170.667h170.667v-85.333z" />
-<glyph unicode="&#xe7e1;" d="M512 853.334c-235.093 0-426.667-191.573-426.667-426.667s191.573-426.667 426.667-426.667 426.667 191.573 426.667 426.667-191.573 426.667-426.667 426.667zM512 85.334c-188.16 0-341.333 153.173-341.333 341.333s153.173 341.333 341.333 341.333 341.333-153.173 341.333-341.333-153.173-341.333-341.333-341.333zM640 426.667c0-70.827-57.173-128-128-128s-128 57.173-128 128 57.173 128 128 128 128-57.173 128-128z" />
-<glyph unicode="&#xe7e2;" d="M614.4 682.667l-17.067 85.333h-384v-725.333h85.333v298.667h238.933l17.067-85.333h298.667v426.667z" />
-<glyph unicode="&#xe7e3;" d="M512 810.667v-395.947c-20.053 7.253-41.387 11.947-64 11.947-106.24 0-192-85.76-192-192s85.76-192 192-192c98.56 0 179.2 74.667 189.867 170.667h2.133v469.333h170.667v128h-298.667z" />
-<glyph unicode="&#xe7e4;" d="M426.667 554.667c-23.467 0-42.667-19.2-42.667-42.667s19.2-42.667 42.667-42.667 42.667 19.2 42.667 42.667-19.2 42.667-42.667 42.667zM426.667 384c-23.467 0-42.667-19.2-42.667-42.667s19.2-42.667 42.667-42.667 42.667 19.2 42.667 42.667-19.2 42.667-42.667 42.667zM298.667 533.334c-11.947 0-21.333-9.387-21.333-21.333s9.387-21.333 21.333-21.333 21.333 9.387 21.333 21.333-9.387 21.333-21.333 21.333zM426.667 234.667c-11.947 0-21.333-9.387-21.333-21.333s9.387-21.333 21.333-21.333 21.333 9.387 21.333 21.333-9.387 21.333-21.333 21.333zM298.667 362.667c-11.947 0-21.333-9.387-21.333-21.333s9.387-21.333 21.333-21.333 21.333 9.387 21.333 21.333-9.387 21.333-21.333 21.333zM426.667 618.667c11.947 0 21.333 9.387 21.333 21.333s-9.387 21.333-21.333 21.333-21.333-9.387-21.333-21.333 9.387-21.333 21.333-21.333zM597.333 554.667c-23.467 0-42.667-19.2-42.667-42.667s19.2-42.667 42.667-42.667 42.667 19.2 42.667 42.667-19.2 42.667-42.667 42.667zM597.333 618.667c11.947 0 21.333 9.387 21.333 21.333s-9.387 21.333-21.333 21.333-21.333-9.387-21.333-21.333 9.387-21.333 21.333-21.333zM725.333 362.667c-11.947 0-21.333-9.387-21.333-21.333s9.387-21.333 21.333-21.333 21.333 9.387 21.333 21.333-9.387 21.333-21.333 21.333zM725.333 533.334c-11.947 0-21.333-9.387-21.333-21.333s9.387-21.333 21.333-21.333 21.333 9.387 21.333 21.333-9.387 21.333-21.333 21.333zM512 853.334c-235.52 0-426.667-191.147-426.667-426.667s191.147-426.667 426.667-426.667 426.667 191.147 426.667 426.667-191.147 426.667-426.667 426.667zM512 85.334c-188.587 0-341.333 152.747-341.333 341.333s152.747 341.333 341.333 341.333 341.333-152.747 341.333-341.333-152.747-341.333-341.333-341.333zM597.333 234.667c-11.947 0-21.333-9.387-21.333-21.333s9.387-21.333 21.333-21.333 21.333 9.387 21.333 21.333-9.387 21.333-21.333 21.333zM597.333 384c-23.467 0-42.667-19.2-42.667-42.667s19.2-42.667 42.667-42.667 42.667 19.2 42.667 42.667-19.2 42.667-42.667 42.667z" />
-<glyph unicode="&#xe7e5;" d="M213.333 192c35.413 0 64 28.587 64 64s-28.587 64-64 64-64-28.587-64-64 28.587-64 64-64zM384 384c23.467 0 42.667 19.2 42.667 42.667s-19.2 42.667-42.667 42.667-42.667-19.2-42.667-42.667 19.2-42.667 42.667-42.667zM384 554.667c23.467 0 42.667 19.2 42.667 42.667s-19.2 42.667-42.667 42.667-42.667-19.2-42.667-42.667 19.2-42.667 42.667-42.667zM128 42.667h768v85.333h-768v-85.333zM213.333 533.334c35.413 0 64 28.587 64 64s-28.587 64-64 64-64-28.587-64-64 28.587-64 64-64zM213.333 362.667c35.413 0 64 28.587 64 64s-28.587 64-64 64-64-28.587-64-64 28.587-64 64-64zM384 213.334c23.467 0 42.667 19.2 42.667 42.667s-19.2 42.667-42.667 42.667-42.667-19.2-42.667-42.667 19.2-42.667 42.667-42.667zM725.333 234.667c11.947 0 21.333 9.387 21.333 21.333s-9.387 21.333-21.333 21.333-21.333-9.387-21.333-21.333 9.387-21.333 21.333-21.333zM128 810.667v-85.333h768v85.333h-768zM725.333 576c11.947 0 21.333 9.387 21.333 21.333s-9.387 21.333-21.333 21.333-21.333-9.387-21.333-21.333 9.387-21.333 21.333-21.333zM725.333 405.334c11.947 0 21.333 9.387 21.333 21.333s-9.387 21.333-21.333 21.333-21.333-9.387-21.333-21.333 9.387-21.333 21.333-21.333zM554.667 554.667c23.467 0 42.667 19.2 42.667 42.667s-19.2 42.667-42.667 42.667-42.667-19.2-42.667-42.667 19.2-42.667 42.667-42.667zM554.667 384c23.467 0 42.667 19.2 42.667 42.667s-19.2 42.667-42.667 42.667-42.667-19.2-42.667-42.667 19.2-42.667 42.667-42.667zM554.667 213.334c23.467 0 42.667 19.2 42.667 42.667s-19.2 42.667-42.667 42.667-42.667-19.2-42.667-42.667 19.2-42.667 42.667-42.667z" />
-<glyph unicode="&#xe7e6;" d="M597.333 640c23.467 0 42.667 19.2 42.667 42.667s-19.2 42.667-42.667 42.667-42.667-19.2-42.667-42.667 19.2-42.667 42.667-42.667zM588.8 448.854l8.533-0.853c35.413 0 64 28.587 64 64s-28.587 64-64 64-64-28.587-64-64l0.853-8.533c3.84-28.587 26.027-50.773 54.613-54.613zM597.333 789.334c11.947 0 21.333 9.387 21.333 21.333s-9.387 21.333-21.333 21.333-21.333-9.387-21.333-21.333 9.387-21.333 21.333-21.333zM426.667 789.334c11.947 0 21.333 9.387 21.333 21.333s-9.387 21.333-21.333 21.333-21.333-9.387-21.333-21.333 9.387-21.333 21.333-21.333zM896 490.667c11.947 0 21.333 9.387 21.333 21.333s-9.387 21.333-21.333 21.333-21.333-9.387-21.333-21.333 9.387-21.333 21.333-21.333zM426.667 640c23.467 0 42.667 19.2 42.667 42.667s-19.2 42.667-42.667 42.667-42.667-19.2-42.667-42.667 19.2-42.667 42.667-42.667zM768 298.667c23.467 0 42.667 19.2 42.667 42.667s-19.2 42.667-42.667 42.667-42.667-19.2-42.667-42.667 19.2-42.667 42.667-42.667zM768 469.334c23.467 0 42.667 19.2 42.667 42.667s-19.2 42.667-42.667 42.667-42.667-19.2-42.667-42.667 19.2-42.667 42.667-42.667zM768 640c23.467 0 42.667 19.2 42.667 42.667s-19.2 42.667-42.667 42.667-42.667-19.2-42.667-42.667 19.2-42.667 42.667-42.667zM597.333 64c-11.947 0-21.333-9.387-21.333-21.333s9.387-21.333 21.333-21.333 21.333 9.387 21.333 21.333-9.387 21.333-21.333 21.333zM106.667 713.814l161.28-161.28-11.947 2.133c-23.467 0-42.667-19.2-42.667-42.667s19.2-42.667 42.667-42.667 42.667 19.2 42.667 42.667c0 4.267-1.28 8.107-2.56 11.947l119.893-119.893c-30.293-4.693-53.333-31.147-53.333-62.72 0-35.413 28.587-64 64-64 31.573 0 58.027 23.040 62.72 53.333l119.893-119.893c-3.84 1.28-7.68 2.56-11.947 2.56-23.467 0-42.667-19.2-42.667-42.667s19.2-42.667 42.667-42.667 42.667 19.2 42.667 42.667c0 4.267-1.28 8.107-2.56 11.947l161.28-161.28 54.613 54.187-692.48 692.48-54.187-54.187zM426.667 213.334c-23.467 0-42.667-19.2-42.667-42.667s19.2-42.667 42.667-42.667 42.667 19.2 42.667 42.667-19.2 42.667-42.667 42.667zM896 362.667c-11.947 0-21.333-9.387-21.333-21.333s9.387-21.333 21.333-21.333 21.333 9.387 21.333 21.333-9.387 21.333-21.333 21.333zM256 384c-23.467 0-42.667-19.2-42.667-42.667s19.2-42.667 42.667-42.667 42.667 19.2 42.667 42.667-19.2 42.667-42.667 42.667zM128 533.334c-11.947 0-21.333-9.387-21.333-21.333s9.387-21.333 21.333-21.333 21.333 9.387 21.333 21.333-9.387 21.333-21.333 21.333zM426.667 64c-11.947 0-21.333-9.387-21.333-21.333s9.387-21.333 21.333-21.333 21.333 9.387 21.333 21.333-9.387 21.333-21.333 21.333zM256 213.334c-23.467 0-42.667-19.2-42.667-42.667s19.2-42.667 42.667-42.667 42.667 19.2 42.667 42.667-19.2 42.667-42.667 42.667zM128 362.667c-11.947 0-21.333-9.387-21.333-21.333s9.387-21.333 21.333-21.333 21.333 9.387 21.333 21.333-9.387 21.333-21.333 21.333z" />
-<glyph unicode="&#xe7e7;" d="M256 384c-23.467 0-42.667-19.2-42.667-42.667s19.2-42.667 42.667-42.667 42.667 19.2 42.667 42.667-19.2 42.667-42.667 42.667zM256 213.334c-23.467 0-42.667-19.2-42.667-42.667s19.2-42.667 42.667-42.667 42.667 19.2 42.667 42.667-19.2 42.667-42.667 42.667zM256 554.667c-23.467 0-42.667-19.2-42.667-42.667s19.2-42.667 42.667-42.667 42.667 19.2 42.667 42.667-19.2 42.667-42.667 42.667zM128 533.334c-11.947 0-21.333-9.387-21.333-21.333s9.387-21.333 21.333-21.333 21.333 9.387 21.333 21.333-9.387 21.333-21.333 21.333zM256 725.334c-23.467 0-42.667-19.2-42.667-42.667s19.2-42.667 42.667-42.667 42.667 19.2 42.667 42.667-19.2 42.667-42.667 42.667zM896 490.667c11.947 0 21.333 9.387 21.333 21.333s-9.387 21.333-21.333 21.333-21.333-9.387-21.333-21.333 9.387-21.333 21.333-21.333zM597.333 640c23.467 0 42.667 19.2 42.667 42.667s-19.2 42.667-42.667 42.667-42.667-19.2-42.667-42.667 19.2-42.667 42.667-42.667zM597.333 789.334c11.947 0 21.333 9.387 21.333 21.333s-9.387 21.333-21.333 21.333-21.333-9.387-21.333-21.333 9.387-21.333 21.333-21.333zM128 362.667c-11.947 0-21.333-9.387-21.333-21.333s9.387-21.333 21.333-21.333 21.333 9.387 21.333 21.333-9.387 21.333-21.333 21.333zM426.667 64c-11.947 0-21.333-9.387-21.333-21.333s9.387-21.333 21.333-21.333 21.333 9.387 21.333 21.333-9.387 21.333-21.333 21.333zM426.667 789.334c11.947 0 21.333 9.387 21.333 21.333s-9.387 21.333-21.333 21.333-21.333-9.387-21.333-21.333 9.387-21.333 21.333-21.333zM426.667 640c23.467 0 42.667 19.2 42.667 42.667s-19.2 42.667-42.667 42.667-42.667-19.2-42.667-42.667 19.2-42.667 42.667-42.667zM426.667 405.334c-35.413 0-64-28.587-64-64s28.587-64 64-64 64 28.587 64 64-28.587 64-64 64zM768 384c-23.467 0-42.667-19.2-42.667-42.667s19.2-42.667 42.667-42.667 42.667 19.2 42.667 42.667-19.2 42.667-42.667 42.667zM768 213.334c-23.467 0-42.667-19.2-42.667-42.667s19.2-42.667 42.667-42.667 42.667 19.2 42.667 42.667-19.2 42.667-42.667 42.667zM768 554.667c-23.467 0-42.667-19.2-42.667-42.667s19.2-42.667 42.667-42.667 42.667 19.2 42.667 42.667-19.2 42.667-42.667 42.667zM768 725.334c-23.467 0-42.667-19.2-42.667-42.667s19.2-42.667 42.667-42.667 42.667 19.2 42.667 42.667-19.2 42.667-42.667 42.667zM896 362.667c-11.947 0-21.333-9.387-21.333-21.333s9.387-21.333 21.333-21.333 21.333 9.387 21.333 21.333-9.387 21.333-21.333 21.333zM597.333 213.334c-23.467 0-42.667-19.2-42.667-42.667s19.2-42.667 42.667-42.667 42.667 19.2 42.667 42.667-19.2 42.667-42.667 42.667zM597.333 64c-11.947 0-21.333-9.387-21.333-21.333s9.387-21.333 21.333-21.333 21.333 9.387 21.333 21.333-9.387 21.333-21.333 21.333zM426.667 576c-35.413 0-64-28.587-64-64s28.587-64 64-64 64 28.587 64 64-28.587 64-64 64zM426.667 213.334c-23.467 0-42.667-19.2-42.667-42.667s19.2-42.667 42.667-42.667 42.667 19.2 42.667 42.667-19.2 42.667-42.667 42.667zM597.333 405.334c-35.413 0-64-28.587-64-64s28.587-64 64-64 64 28.587 64 64-28.587 64-64 64zM597.333 576c-35.413 0-64-28.587-64-64s28.587-64 64-64 64 28.587 64 64-28.587 64-64 64z" />
-<glyph unicode="&#xe7e8;" d="M938.667 426.667c0-235.641-191.025-426.667-426.667-426.667s-426.667 191.025-426.667 426.667c0 235.641 191.025 426.667 426.667 426.667s426.667-191.025 426.667-426.667z" />
-<glyph unicode="&#xe7e9;" d="M426.667 853.334c-77.653 0-150.613-21.333-213.333-57.6 127.573-73.813 213.333-211.2 213.333-369.067s-85.76-295.253-213.333-369.067c62.72-36.267 135.68-57.6 213.333-57.6 235.52 0 426.667 191.147 426.667 426.667s-191.147 426.667-426.667 426.667z" />
-<glyph unicode="&#xe7ea;" d="M384 853.334c-44.8 0-87.467-6.827-128-19.627 173.227-54.187 298.667-215.893 298.667-407.040s-125.44-352.853-298.667-407.040c40.533-12.8 83.2-19.627 128-19.627 235.52 0 426.667 191.147 426.667 426.667s-191.147 426.667-426.667 426.667z" />
-<glyph unicode="&#xe7eb;" d="M853.333 567.894v200.107h-200.107l-141.227 141.227-141.227-141.227h-200.107v-200.107l-141.227-141.227 141.227-141.227v-200.107h200.107l141.227-141.227 141.227 141.227h200.107v200.107l141.227 141.227-141.227 141.227zM512 170.667c-37.973 0-74.24 8.533-106.667 23.467 87.893 40.533 149.333 129.28 149.333 232.533s-61.44 192-149.333 232.533c32.427 14.933 68.693 23.467 106.667 23.467 141.227 0 256-114.773 256-256s-114.773-256-256-256z" />
-<glyph unicode="&#xe7ec;" d="M853.333 285.44l141.227 141.227-141.227 141.227v200.107h-200.107l-141.227 141.227-141.227-141.227h-200.107v-200.107l-141.227-141.227 141.227-141.227v-200.107h200.107l141.227-141.227 141.227 141.227h200.107v200.107zM512 170.667c-141.227 0-256 114.773-256 256s114.773 256 256 256 256-114.773 256-256-114.773-256-256-256z" />
-<glyph unicode="&#xe7ed;" d="M853.333 285.44l141.227 141.227-141.227 141.227v200.107h-200.107l-141.227 141.227-141.227-141.227h-200.107v-200.107l-141.227-141.227 141.227-141.227v-200.107h200.107l141.227-141.227 141.227 141.227h200.107v200.107zM512 170.667v512c141.227 0 256-114.773 256-256s-114.773-256-256-256z" />
-<glyph unicode="&#xe7ee;" d="M853.333 567.894v200.107h-200.107l-141.227 141.227-141.227-141.227h-200.107v-200.107l-141.227-141.227 141.227-141.227v-200.107h200.107l141.227-141.227 141.227 141.227h200.107v200.107l141.227 141.227-141.227 141.227zM512 170.667c-141.227 0-256 114.773-256 256s114.773 256 256 256 256-114.773 256-256-114.773-256-256-256zM512 597.334c-94.293 0-170.667-76.373-170.667-170.667s76.373-170.667 170.667-170.667 170.667 76.373 170.667 170.667-76.373 170.667-170.667 170.667z" />
-<glyph unicode="&#xe7ef;" d="M298.667 341.334c-70.827 0-128-57.173-128-128 0-55.893-49.493-85.333-85.333-85.333 39.253-52.053 106.24-85.333 170.667-85.333 94.293 0 170.667 76.373 170.667 170.667 0 70.827-57.173 128-128 128zM883.627 741.12l-57.173 57.173c-16.64 16.64-43.52 16.64-60.16 0l-382.293-382.293 117.333-117.333 382.293 382.293c16.64 16.64 16.64 43.52 0 60.16z" />
-<glyph unicode="&#xe7f0;" d="M648.533 426.667c0-75.405-61.128-136.533-136.533-136.533s-136.533 61.128-136.533 136.533c0 75.405 61.128 136.533 136.533 136.533s136.533-61.128 136.533-136.533zM384 853.334l-78.080-85.333h-135.253c-46.933 0-85.333-38.4-85.333-85.333v-512c0-46.933 38.4-85.333 85.333-85.333h682.667c46.933 0 85.333 38.4 85.333 85.333v512c0 46.933-38.4 85.333-85.333 85.333h-135.253l-78.080 85.333h-256zM512 213.334c-117.76 0-213.333 95.573-213.333 213.333s95.573 213.333 213.333 213.333 213.333-95.573 213.333-213.333-95.573-213.333-213.333-213.333z" />
-<glyph unicode="&#xe7f1;" d="M426.667 85.334h-213.333v-85.333h213.333v-85.333l128 128-128 128v-85.333zM597.333 85.334v-85.333h213.333v85.333h-213.333zM512 597.334c46.933 0 85.333 38.4 85.333 85.333s-38.4 85.333-85.333 85.333-84.907-38.4-84.907-85.333 37.973-85.333 84.907-85.333zM725.333 938.667h-426.667c-46.933 0-85.333-38.4-85.333-85.333v-597.333c0-46.933 38.4-85.333 85.333-85.333h426.667c46.933 0 85.333 38.4 85.333 85.333v597.333c0 46.933-38.4 85.333-85.333 85.333zM298.667 853.334h426.667v-448c0 71.253-142.080 106.667-213.333 106.667s-213.333-35.413-213.333-106.667v448z" />
-<glyph unicode="&#xe7f2;" d="M426.667 85.334h-213.333v-85.333h213.333v-85.333l128 128-128 128v-85.333zM597.333 85.334v-85.333h213.333v85.333h-213.333zM725.333 938.667h-426.667c-46.933 0-85.333-38.4-85.333-85.333v-597.333c0-46.933 38.4-85.333 85.333-85.333h426.667c46.933 0 85.333 38.4 85.333 85.333v597.333c0 46.933-38.4 85.333-85.333 85.333zM512 682.667c-47.36 0-85.333 38.4-85.333 85.333s37.973 85.333 84.907 85.333 85.333-38.4 85.333-85.333c0.427-46.933-37.973-85.333-84.907-85.333z" />
-<glyph unicode="&#xe7f3;" d="M597.333 725.334c0 46.933-38.4 85.333-85.333 85.333h-42.667v42.667c0 23.467-19.2 42.667-42.667 42.667h-170.667c-23.467 0-42.667-19.2-42.667-42.667v-42.667h-42.667c-46.933 0-85.333-38.4-85.333-85.333v-640c0-46.933 38.4-85.333 85.333-85.333h341.333c46.933 0 85.333 38.4 85.333 85.333h341.333v640h-341.333zM512 170.667h-85.333v85.333h85.333v-85.333zM512 554.667h-85.333v85.333h85.333v-85.333zM682.667 170.667h-85.333v85.333h85.333v-85.333zM682.667 554.667h-85.333v85.333h85.333v-85.333zM853.333 170.667h-85.333v85.333h85.333v-85.333zM853.333 554.667h-85.333v85.333h85.333v-85.333z" />
-<glyph unicode="&#xe7f4;" d="M401.067 490.667l203.52 352.427c-29.867 6.4-60.587 10.24-92.587 10.24-102.4 0-196.267-36.267-269.653-96l156.16-270.933 2.56 4.267zM919.040 554.667c-39.253 124.587-134.4 224.427-256 270.507l-156.16-270.507h412.16zM930.133 512h-319.573l12.373-21.333 203.093-352c69.973 75.947 112.64 176.64 112.64 288 0 29.44-2.987 57.6-8.533 85.333zM364.373 426.667l-166.4 288c-69.547-75.947-112.64-176.64-112.64-288 0-29.44 2.987-57.6 8.533-85.333h319.573l-49.067 85.333zM104.96 298.667c39.253-124.587 134.4-224.427 256-270.507l156.16 270.507h-412.16zM585.813 298.667l-166.4-288.427c29.867-6.4 60.587-10.24 92.587-10.24 102.4 0 196.267 36.267 269.653 96l-156.16 270.933-39.68-68.267z" />
-<glyph unicode="&#xe7f5;" d="M512 597.334c-94.293 0-170.667-76.373-170.667-170.667s76.373-170.667 170.667-170.667 170.667 76.373 170.667 170.667-76.373 170.667-170.667 170.667zM213.333 298.667h-85.333v-170.667c0-46.933 38.4-85.333 85.333-85.333h170.667v85.333h-170.667v170.667zM213.333 725.334h170.667v85.333h-170.667c-46.933 0-85.333-38.4-85.333-85.333v-170.667h85.333v170.667zM810.667 810.667h-170.667v-85.333h170.667v-170.667h85.333v170.667c0 46.933-38.4 85.333-85.333 85.333zM810.667 128h-170.667v-85.333h170.667c46.933 0 85.333 38.4 85.333 85.333v170.667h-85.333v-170.667z" />
-<glyph unicode="&#xe7f6;" d="M213.333 298.667h-85.333v-170.667c0-46.933 38.4-85.333 85.333-85.333h170.667v85.333h-170.667v170.667zM213.333 725.334h170.667v85.333h-170.667c-46.933 0-85.333-38.4-85.333-85.333v-170.667h85.333v170.667zM810.667 810.667h-170.667v-85.333h170.667v-170.667h85.333v170.667c0 46.933-38.4 85.333-85.333 85.333zM810.667 128h-170.667v-85.333h170.667c46.933 0 85.333 38.4 85.333 85.333v170.667h-85.333v-170.667zM512 597.334c-94.293 0-170.667-76.373-170.667-170.667s76.373-170.667 170.667-170.667 170.667 76.373 170.667 170.667-76.373 170.667-170.667 170.667zM512 341.334c-46.933 0-85.333 38.4-85.333 85.333s38.4 85.333 85.333 85.333 85.333-38.4 85.333-85.333-38.4-85.333-85.333-85.333z" />
-<glyph unicode="&#xe7f7;" d="M938.667 256v512c0 46.933-38.4 85.333-85.333 85.333h-512c-46.933 0-85.333-38.4-85.333-85.333v-512c0-46.933 38.4-85.333 85.333-85.333h512c46.933 0 85.333 38.4 85.333 85.333zM469.333 426.667l86.613-115.627 126.72 158.293 170.667-213.333h-512l128 170.667zM85.333 682.667v-597.333c0-46.933 38.4-85.333 85.333-85.333h597.333v85.333h-597.333v597.333h-85.333z" />
-<glyph unicode="&#xe7f8;" d="M512 810.667c-212.053 0-384-171.947-384-384s171.947-384 384-384c35.413 0 64 28.587 64 64 0 16.64-6.4 31.573-16.64 43.093-9.813 11.093-16.213 26.027-16.213 42.24 0 35.413 28.587 64 64 64h75.52c117.76 0 213.333 95.573 213.333 213.333 0 188.587-171.947 341.333-384 341.333zM277.333 426.667c-35.413 0-64 28.587-64 64s28.587 64 64 64 64-28.587 64-64-28.587-64-64-64zM405.333 597.334c-35.413 0-64 28.587-64 64s28.587 64 64 64 64-28.587 64-64-28.587-64-64-64zM618.667 597.334c-35.413 0-64 28.587-64 64s28.587 64 64 64 64-28.587 64-64-28.587-64-64-64zM746.667 426.667c-35.413 0-64 28.587-64 64s28.587 64 64 64 64-28.587 64-64-28.587-64-64-64z" />
-<glyph unicode="&#xe7f9;" d="M883.627 698.454l-99.84 99.84c-16.64 16.64-43.52 16.64-60.16 0l-133.12-133.12-82.347 81.493-60.16-60.16 60.587-60.587-380.587-380.587v-202.667h202.667l380.587 380.587 60.587-60.587 60.16 60.16-81.92 81.92 133.12 133.12c17.067 17.067 17.067 43.947 0.427 60.587zM295.253 128l-81.92 81.92 343.893 343.893 81.92-81.92-343.893-343.893z" />
-<glyph unicode="&#xe7fa;" d="M426.667 810.667h-213.333c-46.933 0-85.333-38.4-85.333-85.333v-597.333c0-46.933 38.4-85.333 85.333-85.333h213.333v-85.333h85.333v938.667h-85.333v-85.333zM426.667 170.667h-213.333l213.333 256v-256zM810.667 810.667h-213.333v-85.333h213.333v-554.667l-213.333 256v-384h213.333c46.933 0 85.333 38.4 85.333 85.333v597.333c0 46.933-38.4 85.333-85.333 85.333z" />
-<glyph unicode="&#xe7fb;" d="M682.667 597.334h-85.333v-128h-128v-85.333h128v-128h85.333v128h128v85.333h-128zM85.333 426.667c0 119.040 69.973 221.867 171.093 269.653v92.16c-148.907-52.907-256.427-194.987-256.427-361.813s107.52-308.907 256.427-361.813v92.16c-101.12 47.787-171.093 150.613-171.093 269.653zM640 810.667c-211.627 0-384-172.373-384-384s172.373-384 384-384 384 172.373 384 384-172.373 384-384 384zM640 128c-164.693 0-298.667 133.973-298.667 298.667s133.973 298.667 298.667 298.667 298.667-133.973 298.667-298.667-133.973-298.667-298.667-298.667z" />
-<glyph unicode="&#xe7fc;" d="M554.667 640h-85.333v-170.667h-170.667v-85.333h170.667v-170.667h85.333v170.667h170.667v85.333h-170.667v170.667zM512 853.334c-235.093 0-426.667-191.573-426.667-426.667s191.573-426.667 426.667-426.667 426.667 191.573 426.667 426.667-191.573 426.667-426.667 426.667zM512 85.334c-188.16 0-341.333 153.173-341.333 341.333s153.173 341.333 341.333 341.333 341.333-153.173 341.333-341.333-153.173-341.333-341.333-341.333z" />
-<glyph unicode="&#xe7fd;" d="M810.667 768h-597.333c-46.933 0-85.333-38.4-85.333-85.333v-512c0-46.933 38.4-85.333 85.333-85.333h597.333c46.933 0 85.333 38.4 85.333 85.333v512c0 46.933-38.4 85.333-85.333 85.333zM810.667 170.667h-597.333v512h597.333v-512z" />
-<glyph unicode="&#xe7fe;" d="M810.667 725.334h-597.333c-46.933 0-85.333-38.4-85.333-85.333v-426.667c0-46.933 38.4-85.333 85.333-85.333h597.333c46.933 0 85.333 38.4 85.333 85.333v426.667c0 46.933-38.4 85.333-85.333 85.333zM810.667 213.334h-597.333v426.667h597.333v-426.667z" />
-<glyph unicode="&#xe7ff;" d="M810.667 640h-597.333c-46.933 0-85.333-38.4-85.333-85.333v-256c0-46.933 38.4-85.333 85.333-85.333h597.333c46.933 0 85.333 38.4 85.333 85.333v256c0 46.933-38.4 85.333-85.333 85.333zM810.667 298.667h-597.333v256h597.333v-256z" />
-<glyph unicode="&#xe800;" d="M810.667 682.667h-597.333c-46.933 0-85.333-38.4-85.333-85.333v-341.333c0-46.933 38.4-85.333 85.333-85.333h597.333c46.933 0 85.333 38.4 85.333 85.333v341.333c0 46.933-38.4 85.333-85.333 85.333zM810.667 256h-597.333v341.333h597.333v-341.333z" />
-<glyph unicode="&#xe801;" d="M810.667 810.667h-597.333c-46.933 0-85.333-38.4-85.333-85.333v-597.333c0-46.933 38.4-85.333 85.333-85.333h597.333c46.933 0 85.333 38.4 85.333 85.333v597.333c0 46.933-38.4 85.333-85.333 85.333zM810.667 128h-597.333v597.333h597.333v-597.333z" />
-<glyph unicode="&#xe802;" d="M128 725.334v-170.667h85.333v170.667h170.667v85.333h-170.667c-46.933 0-85.333-38.4-85.333-85.333zM213.333 298.667h-85.333v-170.667c0-46.933 38.4-85.333 85.333-85.333h170.667v85.333h-170.667v170.667zM810.667 128h-170.667v-85.333h170.667c46.933 0 85.333 38.4 85.333 85.333v170.667h-85.333v-170.667zM810.667 810.667h-170.667v-85.333h170.667v-170.667h85.333v170.667c0 46.933-38.4 85.333-85.333 85.333z" />
-<glyph unicode="&#xe803;" d="M810.667 725.334h-597.333c-46.933 0-85.333-38.4-85.333-85.333v-426.667c0-46.933 38.4-85.333 85.333-85.333h597.333c46.933 0 85.333 38.4 85.333 85.333v426.667c0 46.933-38.4 85.333-85.333 85.333zM810.667 213.334h-597.333v426.667h597.333v-426.667z" />
-<glyph unicode="&#xe804;" d="M810.667 810.667h-597.333c-46.933 0-85.333-38.4-85.333-85.333v-597.333c0-46.933 38.4-85.333 85.333-85.333h597.333c46.933 0 85.333 38.4 85.333 85.333v597.333c0 46.933-38.4 85.333-85.333 85.333zM810.667 128h-597.333v597.333h597.333v-597.333zM595.627 414.294l-117.333-151.040-83.627 100.693-117.333-150.613h469.333l-151.040 200.96z" />
-<glyph unicode="&#xe805;" d="M725.333 810.667h-426.667c-46.933 0-85.333-38.4-85.333-85.333v-597.333c0-46.933 38.4-85.333 85.333-85.333h426.667c46.933 0 85.333 38.4 85.333 85.333v597.333c0 46.933-38.4 85.333-85.333 85.333zM725.333 128h-426.667v597.333h426.667v-597.333z" />
-<glyph unicode="&#xe806;" d="M768 768h-512c-46.933 0-85.333-38.4-85.333-85.333v-512c0-46.933 38.4-85.333 85.333-85.333h512c46.933 0 85.333 38.4 85.333 85.333v512c0 46.933-38.4 85.333-85.333 85.333zM768 170.667h-512v512h512v-512z" />
-<glyph unicode="&#xe807;" d="M725.333 298.667h85.333v341.333c0 46.933-38.4 85.333-85.333 85.333h-341.333v-85.333h341.333v-341.333zM298.667 213.334v682.667h-85.333v-170.667h-170.667v-85.333h170.667v-426.667c0-46.933 38.4-85.333 85.333-85.333h426.667v-170.667h85.333v170.667h170.667v85.333h-682.667z" />
-<glyph unicode="&#xe808;" d="M85.333 277.334v-85.333h853.333v85.333h-853.333zM85.333 490.667v-85.333h853.333v85.333h-853.333zM85.333 704v-85.333h853.333v85.333h-853.333z" />
-<glyph unicode="&#xe809;" d="M128 768l384-682.667 384 682.667h-768zM272.213 682.667h480l-240.213-426.667-239.787 426.667z" />
-<glyph unicode="&#xe80a;" d="M128 202.667v-160h160l471.893 471.893-160 160-471.893-471.893zM883.627 638.294c16.64 16.64 16.64 43.52 0 60.16l-99.84 99.84c-16.64 16.64-43.52 16.64-60.16 0l-78.080-78.080 160-160 78.080 78.080z" />
-<glyph unicode="&#xe80b;" d="M170.667 469.334v-85.333h341.333v85.333h-341.333zM810.667 170.667h-85.333v453.12l-128-43.52v72.533l200.533 72.533h12.8v-554.667z" />
-<glyph unicode="&#xe80c;" d="M642.133 243.627l122.027 130.987c16.213 16.64 30.72 33.707 44.373 50.347s25.173 33.28 34.987 49.92c9.813 16.64 17.493 33.28 23.040 49.92s8.107 33.707 8.107 50.347c0 22.613-3.84 43.52-11.52 62.293s-18.773 34.56-33.28 47.36c-14.507 13.227-32.853 23.040-53.76 30.293-21.76 6.827-46.080 10.24-73.387 10.24-29.44 0-55.893-4.693-78.933-13.653s-42.667-21.76-58.027-37.547c-15.787-15.787-27.733-34.133-35.84-55.467-7.68-20.053-11.52-41.387-11.947-64h91.307c0.427 13.227 2.133 25.6 5.547 37.12 3.84 12.373 9.813 23.040 17.067 32 7.68 8.96 17.493 15.787 29.013 20.907s25.6 7.68 40.96 7.68c13.227 0 24.747-2.133 34.56-6.4s18.347-10.667 25.173-18.347c6.827-7.68 11.947-17.067 15.787-27.733 3.413-10.667 5.547-22.187 5.547-34.56 0-9.387-1.28-18.347-3.413-27.733-2.56-9.387-6.4-19.2-12.373-29.867s-13.653-22.613-23.893-35.413c-9.813-12.8-22.187-27.733-37.547-43.947l-177.92-194.133v-63.573h368.213v72.96h-253.867zM85.333 469.334v-85.333h341.333v85.333h-341.333z" />
-<glyph unicode="&#xe80d;" d="M426.667 640h-85.333v-170.667h-170.667v-85.333h170.667v-170.667h85.333v170.667h170.667v85.333h-170.667v170.667zM853.333 170.667h-85.333v453.12l-128-43.52v72.533l200.533 72.533h12.8v-554.667z" />
-<glyph unicode="&#xe80e;" d="M684.8 243.627l122.027 130.987c16.213 16.64 30.72 33.707 44.373 50.347s25.173 33.28 34.987 49.92c9.813 16.64 17.493 33.28 23.040 49.92s8.107 33.707 8.107 50.347c0 22.613-3.84 43.52-11.52 62.293s-18.773 34.56-33.28 47.36c-14.507 13.227-32.853 23.040-53.76 30.293-21.76 6.827-46.080 10.24-73.387 10.24-29.44 0-55.893-4.693-78.933-13.653s-42.667-21.76-58.027-37.547c-15.787-15.787-27.733-34.133-35.84-55.467-7.68-20.053-11.52-41.387-11.947-64h91.307c0.427 13.227 2.133 25.6 5.547 37.12 3.84 12.373 9.813 23.040 17.067 32 7.68 8.96 17.493 15.787 29.013 20.907s25.6 7.68 40.96 7.68c13.227 0 24.747-2.133 34.56-6.4s18.347-10.667 25.173-18.347c6.827-7.68 11.947-17.067 15.787-27.733 3.413-10.667 5.547-22.187 5.547-34.56 0-9.387-1.28-18.347-3.413-27.733-2.56-9.387-6.4-19.2-12.373-29.867s-13.653-22.613-23.893-35.413c-9.813-12.8-22.187-27.733-37.547-43.947l-177.92-194.133v-63.573h368.213v72.96h-253.867zM341.333 640h-85.333v-170.667h-170.667v-85.333h170.667v-170.667h85.333v170.667h170.667v85.333h-170.667v170.667z" />
-<glyph unicode="&#xe80f;" d="M688.64 405.334c0-42.667-4.267-78.933-12.8-108.8s-20.48-54.187-35.413-72.533c-15.36-18.773-33.707-32-55.467-40.533s-45.653-12.8-72.533-12.8c-26.453 0-50.347 4.267-72.107 12.8s-40.533 21.76-55.893 40.533c-15.36 18.773-27.733 43.093-36.267 72.533-8.533 29.867-12.8 66.133-12.8 108.8v87.040c0 42.667 4.267 78.933 12.8 108.8s20.48 53.76 35.84 72.107c15.36 18.347 34.133 31.573 55.893 39.68 21.333 8.107 45.653 12.373 72.107 12.373 26.88 0 50.773-4.267 72.533-12.373s40.533-21.333 55.893-39.68c15.36-18.347 27.307-42.24 35.84-72.107s12.8-65.707 12.8-108.8v-87.040zM598.613 506.027c0 27.307-2.133 50.347-5.547 69.12-3.84 18.773-9.387 33.707-17.067 45.227-7.253 11.52-16.64 19.627-27.307 24.747-10.667 5.547-23.040 8.107-36.693 8.107s-26.027-2.56-36.693-7.68-20.053-13.227-27.307-24.747c-7.253-11.52-13.227-26.453-17.067-45.227s-5.547-41.813-5.547-69.12v-113.92c0-27.307 2.133-50.347 5.973-69.12 3.84-19.2 9.813-34.56 17.067-46.507s16.64-20.48 27.307-26.027 23.040-8.107 37.12-8.107c14.080 0 26.453 2.56 37.12 8.107s19.627 14.080 26.88 26.027c7.253 11.947 12.8 27.307 16.64 46.507s5.547 42.24 5.547 69.12v113.493z" />
-<glyph unicode="&#xe810;" d="M640 213.334v-85.333h85.333v85.333h85.333v85.333h-85.333v85.333h-85.333v-85.333h-85.333v-85.333h85.333zM853.333 853.334h-682.667c-46.933 0-85.333-38.4-85.333-85.333v-682.667c0-46.933 38.4-85.333 85.333-85.333h682.667c46.933 0 85.333 38.4 85.333 85.333v682.667c0 46.933-38.4 85.333-85.333 85.333zM213.333 725.334h256v-85.333h-256v85.333zM853.333 85.334h-682.667l682.667 682.667v-682.667z" />
-<glyph unicode="&#xe811;" d="M128 725.334h-85.333v-682.667c0-46.933 38.4-85.333 85.333-85.333h682.667v85.333h-682.667v682.667zM597.333 298.667h85.333v426.667h-170.667v-85.333h85.333v-341.333zM896 896h-597.333c-46.933 0-85.333-38.4-85.333-85.333v-597.333c0-46.933 38.4-85.333 85.333-85.333h597.333c46.933 0 85.333 38.4 85.333 85.333v597.333c0 46.933-38.4 85.333-85.333 85.333zM896 213.334h-597.333v597.333h597.333v-597.333z" />
-<glyph unicode="&#xe812;" d="M128 725.334h-85.333v-682.667c0-46.933 38.4-85.333 85.333-85.333h682.667v85.333h-682.667v682.667zM896 896h-597.333c-46.933 0-85.333-38.4-85.333-85.333v-597.333c0-46.933 38.4-85.333 85.333-85.333h597.333c46.933 0 85.333 38.4 85.333 85.333v597.333c0 46.933-38.4 85.333-85.333 85.333zM896 213.334h-597.333v597.333h597.333v-597.333zM725.333 384h-170.667v85.333h85.333c46.933 0 85.333 37.973 85.333 85.333v85.333c0 47.36-38.4 85.333-85.333 85.333h-170.667v-85.333h170.667v-85.333h-85.333c-46.933 0-85.333-37.973-85.333-85.333v-170.667h256v85.333z" />
-<glyph unicode="&#xe813;" d="M896 896h-597.333c-46.933 0-85.333-38.4-85.333-85.333v-597.333c0-46.933 38.4-85.333 85.333-85.333h597.333c46.933 0 85.333 38.4 85.333 85.333v597.333c0 46.933-38.4 85.333-85.333 85.333zM896 213.334h-597.333v597.333h597.333v-597.333zM128 725.334h-85.333v-682.667c0-46.933 38.4-85.333 85.333-85.333h682.667v85.333h-682.667v682.667zM725.333 384v64c0 35.413-28.587 64-64 64 35.413 0 64 28.587 64 64v64c0 47.36-38.4 85.333-85.333 85.333h-170.667v-85.333h170.667v-85.333h-85.333v-85.333h85.333v-85.333h-170.667v-85.333h170.667c46.933 0 85.333 37.973 85.333 85.333z" />
-<glyph unicode="&#xe814;" d="M128 725.334h-85.333v-682.667c0-46.933 38.4-85.333 85.333-85.333h682.667v85.333h-682.667v682.667zM640 298.667h85.333v426.667h-85.333v-170.667h-85.333v170.667h-85.333v-256h170.667v-170.667zM896 896h-597.333c-46.933 0-85.333-38.4-85.333-85.333v-597.333c0-46.933 38.4-85.333 85.333-85.333h597.333c46.933 0 85.333 38.4 85.333 85.333v597.333c0 46.933-38.4 85.333-85.333 85.333zM896 213.334h-597.333v597.333h597.333v-597.333z" />
-<glyph unicode="&#xe815;" d="M896 896h-597.333c-46.933 0-85.333-38.4-85.333-85.333v-597.333c0-46.933 38.4-85.333 85.333-85.333h597.333c46.933 0 85.333 38.4 85.333 85.333v597.333c0 46.933-38.4 85.333-85.333 85.333zM896 213.334h-597.333v597.333h597.333v-597.333zM128 725.334h-85.333v-682.667c0-46.933 38.4-85.333 85.333-85.333h682.667v85.333h-682.667v682.667zM725.333 384v85.333c0 47.36-38.4 85.333-85.333 85.333h-85.333v85.333h170.667v85.333h-256v-256h170.667v-85.333h-170.667v-85.333h170.667c46.933 0 85.333 37.973 85.333 85.333z" />
-<glyph unicode="&#xe816;" d="M128 725.334h-85.333v-682.667c0-46.933 38.4-85.333 85.333-85.333h682.667v85.333h-682.667v682.667zM896 896h-597.333c-46.933 0-85.333-38.4-85.333-85.333v-597.333c0-46.933 38.4-85.333 85.333-85.333h597.333c46.933 0 85.333 38.4 85.333 85.333v597.333c0 46.933-38.4 85.333-85.333 85.333zM896 213.334h-597.333v597.333h597.333v-597.333zM554.667 298.667h85.333c46.933 0 85.333 37.973 85.333 85.333v85.333c0 47.36-38.4 85.333-85.333 85.333h-85.333v85.333h170.667v85.333h-170.667c-46.933 0-85.333-37.973-85.333-85.333v-256c0-47.36 38.4-85.333 85.333-85.333zM554.667 469.334h85.333v-85.333h-85.333v85.333z" />
-<glyph unicode="&#xe817;" d="M128 725.334h-85.333v-682.667c0-46.933 38.4-85.333 85.333-85.333h682.667v85.333h-682.667v682.667zM896 896h-597.333c-46.933 0-85.333-38.4-85.333-85.333v-597.333c0-46.933 38.4-85.333 85.333-85.333h597.333c46.933 0 85.333 38.4 85.333 85.333v597.333c0 46.933-38.4 85.333-85.333 85.333zM896 213.334h-597.333v597.333h597.333v-597.333zM554.667 298.667l170.667 341.333v85.333h-256v-85.333h170.667l-170.667-341.333h85.333z" />
-<glyph unicode="&#xe818;" d="M128 725.334h-85.333v-682.667c0-46.933 38.4-85.333 85.333-85.333h682.667v85.333h-682.667v682.667zM896 896h-597.333c-46.933 0-85.333-38.4-85.333-85.333v-597.333c0-46.933 38.4-85.333 85.333-85.333h597.333c46.933 0 85.333 38.4 85.333 85.333v597.333c0 46.933-38.4 85.333-85.333 85.333zM896 213.334h-597.333v597.333h597.333v-597.333zM554.667 298.667h85.333c46.933 0 85.333 37.973 85.333 85.333v64c0 35.413-28.587 64-64 64 35.413 0 64 28.587 64 64v64c0 47.36-38.4 85.333-85.333 85.333h-85.333c-46.933 0-85.333-37.973-85.333-85.333v-64c0-35.413 28.587-64 64-64-35.413 0-64-28.587-64-64v-64c0-47.36 38.4-85.333 85.333-85.333zM554.667 640h85.333v-85.333h-85.333v85.333zM554.667 469.334h85.333v-85.333h-85.333v85.333z" />
-<glyph unicode="&#xe819;" d="M128 725.334h-85.333v-682.667c0-46.933 38.4-85.333 85.333-85.333h682.667v85.333h-682.667v682.667zM597.333 426.667v170.667c0 47.36-38.4 85.333-85.333 85.333h-42.667c-46.933 0-85.333-37.973-85.333-85.333v-42.667c0-47.36 38.4-85.333 85.333-85.333h42.667v-42.667h-128v-85.333h128c46.933 0 85.333 37.973 85.333 85.333zM469.333 554.667v42.667h42.667v-42.667h-42.667zM896 896h-597.333c-46.933 0-85.333-38.4-85.333-85.333v-597.333c0-46.933 38.4-85.333 85.333-85.333h597.333c46.933 0 85.333 38.4 85.333 85.333v597.333c0 46.933-38.4 85.333-85.333 85.333zM896 554.667h-85.333v85.333h-85.333v-85.333h-85.333v-85.333h85.333v-85.333h85.333v85.333h85.333v-256h-597.333v597.333h597.333v-256z" />
-<glyph unicode="&#xe81a;" d="M128 725.334h-85.333v-682.667c0-46.933 38.4-85.333 85.333-85.333h682.667v85.333h-682.667v682.667zM896 896h-597.333c-46.933 0-85.333-38.4-85.333-85.333v-597.333c0-46.933 38.4-85.333 85.333-85.333h597.333c46.933 0 85.333 38.4 85.333 85.333v597.333c0 46.933-38.4 85.333-85.333 85.333zM896 213.334h-597.333v597.333h597.333v-597.333zM640 725.334h-85.333c-46.933 0-85.333-37.973-85.333-85.333v-85.333c0-47.36 38.4-85.333 85.333-85.333h85.333v-85.333h-170.667v-85.333h170.667c46.933 0 85.333 37.973 85.333 85.333v256c0 47.36-38.4 85.333-85.333 85.333zM640 554.667h-85.333v85.333h85.333v-85.333z" />
-<glyph unicode="&#xe81b;" d="M810.667 810.667h-597.333c-46.933 0-85.333-38.4-85.333-85.333v-597.333c0-46.933 38.4-85.333 85.333-85.333h597.333c46.933 0 85.333 38.4 85.333 85.333v597.333c0 46.933-38.4 85.333-85.333 85.333zM810.667 128l-298.667 341.333v-341.333h-298.667l298.667 341.333v256h298.667v-597.333z" />
-<glyph unicode="&#xe81c;" d="M213.333 298.667h-85.333v-170.667c0-46.933 38.4-85.333 85.333-85.333h170.667v85.333h-170.667v170.667zM213.333 725.334h170.667v85.333h-170.667c-46.933 0-85.333-38.4-85.333-85.333v-170.667h85.333v170.667zM810.667 810.667h-170.667v-85.333h170.667v-170.667h85.333v170.667c0 46.933-38.4 85.333-85.333 85.333zM810.667 128h-170.667v-85.333h170.667c46.933 0 85.333 38.4 85.333 85.333v170.667h-85.333v-170.667zM512 554.667c-70.827 0-128-57.173-128-128s57.173-128 128-128 128 57.173 128 128-57.173 128-128 128z" />
-<glyph unicode="&#xe81d;" d="M825.6 510.294c-29.013 147.2-158.293 257.707-313.6 257.707-123.307 0-229.973-69.973-283.307-172.373-128.427-13.653-228.693-122.027-228.693-254.293 0-141.227 114.773-256 256-256h554.667c117.76 0 213.333 95.573 213.333 213.333 0 112.64-87.467 203.947-198.4 211.627zM810.667 170.667h-554.667c-94.293 0-170.667 76.373-170.667 170.667s76.373 170.667 170.667 170.667 170.667-76.373 170.667-170.667h85.333c0 117.76-79.36 216.747-187.733 246.613 43.093 57.173 110.933 94.72 187.733 94.72 129.28 0 234.667-105.387 234.667-234.667v-21.333h64c70.4 0 128-57.6 128-128s-57.6-128-128-128z" />
-<glyph unicode="&#xe81e;" d="M853.333 768h-170.667l-170.667 170.667-170.667-170.667h-170.667c-46.933 0-85.333-38.4-85.333-85.333v-597.333c0-46.933 38.4-85.333 85.333-85.333h682.667c46.933 0 85.333 38.4 85.333 85.333v597.333c0 46.933-38.4 85.333-85.333 85.333zM853.333 85.334h-682.667v597.333h192.853l150.187 149.333 148.48-149.333h191.147v-597.333zM768 597.334h-512v-426.667h512z" />
-<glyph unicode="&#xe81f;" d="M597.333 682.667l-160-213.333 121.6-162.133-68.267-51.2c-72.107 96-192 256-192 256l-256-341.333h938.667l-384 512z" />
-<glyph unicode="&#xe820;" d="M128 725.334h-85.333v-682.667c0-46.933 38.4-85.333 85.333-85.333h682.667v85.333h-682.667v682.667zM896 896h-597.333c-46.933 0-85.333-38.4-85.333-85.333v-597.333c0-46.933 38.4-85.333 85.333-85.333h597.333c46.933 0 85.333 38.4 85.333 85.333v597.333c0 46.933-38.4 85.333-85.333 85.333zM896 213.334h-597.333v597.333h597.333v-597.333z" />
-<glyph unicode="&#xe821;" d="M469.333 765.014v86.187c-85.76-8.533-163.84-42.667-226.987-94.293l60.587-61.013c47.36 36.693 104.107 61.44 166.4 69.12zM781.653 756.907c-63.147 51.627-141.227 85.76-226.987 94.293v-86.187c62.293-7.68 119.040-32.427 166.4-69.12l60.587 61.013zM850.347 469.334h86.187c-8.533 85.76-42.667 163.84-94.293 226.987l-61.013-60.587c36.693-47.36 61.44-104.107 69.12-166.4zM242.773 635.734l-61.013 60.587c-51.627-63.147-85.76-141.227-94.293-226.987h86.187c7.68 62.293 32.427 119.040 69.12 166.4zM173.653 384h-86.187c8.533-85.76 42.667-163.84 94.293-226.987l61.013 61.013c-36.693 46.933-61.44 103.68-69.12 165.973zM640 426.667c0 70.827-57.173 128-128 128s-128-57.173-128-128 57.173-128 128-128 128 57.173 128 128zM781.227 217.6l61.013-61.013c51.627 63.147 85.76 141.653 94.293 226.987h-86.187c-7.68-61.867-32.427-118.613-69.12-165.973zM554.667 88.32v-86.187c85.76 8.533 163.84 42.667 226.987 94.293l-61.013 61.013c-46.933-36.693-103.68-61.44-165.973-69.12zM242.347 96.427c63.147-51.627 141.653-85.76 226.987-94.293v86.187c-62.293 7.68-119.040 32.427-166.4 69.12l-60.587-61.013z" />
-<glyph unicode="&#xe822;" d="M797.867 409.6c-11.947 6.827-24.32 12.373-36.693 17.067 12.373 4.693 24.747 10.24 36.693 17.067 81.92 47.36 127.573 133.12 128 221.44-76.373 43.947-173.653 47.36-256 0-11.947-6.827-23.040-14.933-33.28-23.040 2.133 13.227 3.413 26.88 3.413 40.533 0 94.72-51.627 177.067-128 221.44-76.373-44.373-128-126.72-128-221.44 0-13.653 1.28-27.307 3.413-40.533-10.24 8.533-21.333 16.64-33.28 23.467-81.92 47.36-179.2 43.947-256 0 0-88.32 45.653-174.080 128-221.44 11.947-6.827 24.32-12.373 36.693-17.067-12.373-4.693-24.747-10.24-36.693-17.067-81.92-47.36-127.573-133.12-128-221.44 76.373-43.947 173.653-47.36 256 0 11.947 6.827 23.040 14.933 33.28 23.040-2.133-13.653-3.413-27.307-3.413-40.96 0-94.72 51.627-177.067 128-221.44 76.373 44.373 128 126.72 128 221.44 0 13.653-1.28 27.307-3.413 40.533 10.24-8.533 21.333-16.213 33.28-23.040 81.92-47.36 179.2-43.947 256 0-0.427 88.32-46.080 174.080-128 221.44zM512 256c-94.293 0-170.667 76.373-170.667 170.667s76.373 170.667 170.667 170.667 170.667-76.373 170.667-170.667-76.373-170.667-170.667-170.667z" />
-<glyph unicode="&#xe823;" d="M680.96 499.627l-117.333-151.040-83.627 100.693-117.333-150.613h469.333l-151.040 200.96zM128 725.334h-85.333v-682.667c0-46.933 38.4-85.333 85.333-85.333h682.667v85.333h-682.667v682.667zM896 896h-597.333c-46.933 0-85.333-38.4-85.333-85.333v-597.333c0-46.933 38.4-85.333 85.333-85.333h597.333c46.933 0 85.333 38.4 85.333 85.333v597.333c0 46.933-38.4 85.333-85.333 85.333zM896 213.334h-597.333v597.333h597.333v-597.333z" />
-<glyph unicode="&#xe824;" d="M298.667 469.334h-256v-85.333h256v85.333zM391.253 607.574l-90.453 90.453-60.16-60.16 90.453-90.453 60.16 60.16zM554.667 896h-85.333v-256h85.333v256zM783.36 637.867l-60.16 60.16-90.453-90.453 60.16-60.16 90.453 90.453zM725.333 469.334v-85.333h256v85.333h-256zM512 554.667c-70.827 0-128-57.173-128-128s57.173-128 128-128 128 57.173 128 128-57.173 128-128 128zM632.747 245.76l90.453-90.453 60.16 60.16-90.453 90.453-60.16-60.16zM240.64 215.467l60.16-60.16 90.453 90.453-60.16 60.16-90.453-90.453zM469.333-42.666h85.333v256h-85.333v-256z" />
-<glyph unicode="&#xe825;" d="M128 853.334v-512h128v-384l298.667 512h-170.667l170.667 384h-426.667zM810.667 853.334h-85.333l-136.533-384h81.067l29.867 85.333h136.533l29.867-85.333h81.067l-136.533 384zM718.933 612.267l49.067 155.733 49.067-155.733h-98.133z" />
-<glyph unicode="&#xe826;" d="M139.52 810.667l-54.187-54.187 213.333-213.333v-159.147h128v-384l152.747 261.973 177.067-176.64 54.187 54.187-671.147 671.147zM725.333 512h-170.667l170.667 341.333h-426.667v-93.013l360.96-360.96 65.707 112.64z" />
-<glyph unicode="&#xe827;" d="M298.667 853.334v-469.333h128v-384l298.667 512h-170.667l170.667 341.333z" />
-<glyph unicode="&#xe828;" d="M640 42.667h85.333v85.333h-85.333v-85.333zM810.667 554.667h85.333v85.333h-85.333v-85.333zM128 725.334v-597.333c0-46.933 38.4-85.333 85.333-85.333h170.667v85.333h-170.667v597.333h170.667v85.333h-170.667c-46.933 0-85.333-38.4-85.333-85.333zM810.667 810.667v-85.333h85.333c0 46.933-38.4 85.333-85.333 85.333zM469.333-42.666h85.333v938.667h-85.333v-938.667zM810.667 213.334h85.333v85.333h-85.333v-85.333zM640 725.334h85.333v85.333h-85.333v-85.333zM810.667 384h85.333v85.333h-85.333v-85.333zM810.667 42.667c46.933 0 85.333 38.4 85.333 85.333h-85.333v-85.333z" />
-<glyph unicode="&#xe829;" d="M469.333 554.667h85.333v-85.333h-85.333zM384 469.334h85.333v-85.333h-85.333zM554.667 469.334h85.333v-85.333h-85.333zM640 554.667h85.333v-85.333h-85.333zM298.667 554.667h85.333v-85.333h-85.333zM810.667 810.667h-597.333c-46.933 0-85.333-38.4-85.333-85.333v-597.333c0-46.933 38.4-85.333 85.333-85.333h597.333c46.933 0 85.333 38.4 85.333 85.333v597.333c0 46.933-38.4 85.333-85.333 85.333zM384 170.667h-85.333v85.333h85.333v-85.333zM554.667 170.667h-85.333v85.333h85.333v-85.333zM725.333 170.667h-85.333v85.333h85.333v-85.333zM810.667 469.334h-85.333v-85.333h85.333v-85.333h-85.333v85.333h-85.333v-85.333h-85.333v85.333h-85.333v-85.333h-85.333v85.333h-85.333v-85.333h-85.333v85.333h85.333v85.333h-85.333v256h597.333v-256z" />
-<glyph unicode="&#xe82a;" d="M426.667 426.667c-46.933 0-85.333-38.4-85.333-85.333s38.4-85.333 85.333-85.333 85.333 38.4 85.333 85.333-38.4 85.333-85.333 85.333zM256 597.334c-46.933 0-85.333-38.4-85.333-85.333s38.4-85.333 85.333-85.333 85.333 38.4 85.333 85.333-38.4 85.333-85.333 85.333zM256 256c-46.933 0-85.333-38.4-85.333-85.333s38.4-85.333 85.333-85.333 85.333 38.4 85.333 85.333-38.4 85.333-85.333 85.333zM768 597.334c46.933 0 85.333 38.4 85.333 85.333s-38.4 85.333-85.333 85.333-85.333-38.4-85.333-85.333 38.4-85.333 85.333-85.333zM597.333 256c-46.933 0-85.333-38.4-85.333-85.333s38.4-85.333 85.333-85.333 85.333 38.4 85.333 85.333-38.4 85.333-85.333 85.333zM768 426.667c-46.933 0-85.333-38.4-85.333-85.333s38.4-85.333 85.333-85.333 85.333 38.4 85.333 85.333-38.4 85.333-85.333 85.333zM597.333 597.334c-46.933 0-85.333-38.4-85.333-85.333s38.4-85.333 85.333-85.333 85.333 38.4 85.333 85.333-38.4 85.333-85.333 85.333zM426.667 768c-46.933 0-85.333-38.4-85.333-85.333s38.4-85.333 85.333-85.333 85.333 38.4 85.333 85.333-38.4 85.333-85.333 85.333z" />
-<glyph unicode="&#xe82b;" d="M341.333 768v-61.867l85.333-85.333v147.2h170.667v-170.667h-147.2l85.333-85.333h61.867v-61.867l85.333-85.333v147.2h170.667v-170.667h-147.2l85.333-85.333h61.867v-61.867l85.333-85.333v659.2c0 46.933-38.4 85.333-85.333 85.333h-659.2l85.333-85.333h61.867zM682.667 768h170.667v-170.667h-170.667v170.667zM54.187 884.48l-54.187-54.613 85.333-85.333v-659.2c0-46.933 38.4-85.333 85.333-85.333h659.627l85.333-85.333 54.187 54.187-915.627 915.627zM426.667 403.2l61.867-61.867h-61.867v61.867zM170.667 659.2l61.867-61.867h-61.867v61.867zM341.333 85.334h-170.667v170.667h170.667v-170.667zM341.333 341.334h-170.667v170.667h147.2l23.467-23.467v-147.2zM597.333 85.334h-170.667v170.667h147.2l23.467-23.040v-147.627zM682.667 85.334v62.293l62.293-62.293h-62.293z" />
-<glyph unicode="&#xe82c;" d="M853.333 853.334h-682.667c-46.933 0-85.333-38.4-85.333-85.333v-682.667c0-46.933 38.4-85.333 85.333-85.333h682.667c46.933 0 85.333 38.4 85.333 85.333v682.667c0 46.933-38.4 85.333-85.333 85.333zM341.333 85.334h-170.667v170.667h170.667v-170.667zM341.333 341.334h-170.667v170.667h170.667v-170.667zM341.333 597.334h-170.667v170.667h170.667v-170.667zM597.333 85.334h-170.667v170.667h170.667v-170.667zM597.333 341.334h-170.667v170.667h170.667v-170.667zM597.333 597.334h-170.667v170.667h170.667v-170.667zM853.333 85.334h-170.667v170.667h170.667v-170.667zM853.333 341.334h-170.667v170.667h170.667v-170.667zM853.333 597.334h-170.667v170.667h170.667v-170.667z" />
-<glyph unicode="&#xe82d;" d="M768 213.334l-628.48 628.48-54.187-54.613 170.667-170.667v-147.2h-85.333v170.667h-85.333v-426.667h85.333v170.667h85.333v-170.667h85.333v317.867l42.667-42.667v-275.2h170.667c28.587 0 53.76 14.080 69.12 35.84l270.507-270.507 54.187 54.187-180.48 180.48zM554.667 298.667h-85.333v104.533l85.333-85.333v-19.2zM768 384h42.667l34.987-139.52 31.147-31.147h61.867l-50.773 177.92c29.867 13.227 50.773 43.093 50.773 78.080v85.333c0 46.933-38.4 85.333-85.333 85.333h-170.667v-232.533l85.333-85.333v61.867zM768 554.667h85.333v-85.333h-85.333v85.333zM640 450.134v104.533c0 46.933-38.4 85.333-85.333 85.333h-104.533l189.867-189.867z" />
-<glyph unicode="&#xe82e;" d="M256 469.334h-85.333v170.667h-85.333v-426.667h85.333v170.667h85.333v-170.667h85.333v426.667h-85.333v-170.667zM554.667 640h-170.667v-426.667h170.667c46.933 0 85.333 38.4 85.333 85.333v256c0 46.933-38.4 85.333-85.333 85.333zM554.667 298.667h-85.333v256h85.333v-256zM938.667 469.334v85.333c0 46.933-38.4 85.333-85.333 85.333h-170.667v-426.667h85.333v170.667h42.667l42.667-170.667h85.333l-50.773 177.92c29.867 13.227 50.773 43.093 50.773 78.080zM853.333 469.334h-85.333v85.333h85.333v-85.333z" />
-<glyph unicode="&#xe82f;" d="M725.333 682.667c-141.227 0-256-114.773-256-256s114.773-256 256-256 256 114.773 256 256-114.773 256-256 256zM213.333 597.334c-94.293 0-170.667-76.373-170.667-170.667s76.373-170.667 170.667-170.667 170.667 76.373 170.667 170.667-76.373 170.667-170.667 170.667zM213.333 341.334c-46.933 0-85.333 38.4-85.333 85.333s38.4 85.333 85.333 85.333 85.333-38.4 85.333-85.333-38.4-85.333-85.333-85.333z" />
-<glyph unicode="&#xe830;" d="M213.333 597.334c-94.293 0-170.667-76.373-170.667-170.667s76.373-170.667 170.667-170.667 170.667 76.373 170.667 170.667-76.373 170.667-170.667 170.667zM725.333 682.667c-141.227 0-256-114.773-256-256s114.773-256 256-256 256 114.773 256 256-114.773 256-256 256zM725.333 256c-94.293 0-170.667 76.373-170.667 170.667s76.373 170.667 170.667 170.667 170.667-76.373 170.667-170.667-76.373-170.667-170.667-170.667z" />
-<glyph unicode="&#xe831;" d="M756.48 425.814l169.813 169.813c16.64 16.64 16.64 43.52 0 60.16l-185.173 185.173c-16.64 16.64-43.52 16.64-60.16 0l-169.813-169.813-169.813 169.813c-8.533 8.107-19.2 12.373-30.293 12.373-10.667 0-21.76-4.267-29.867-12.373l-185.173-185.173c-16.64-16.64-16.64-43.52 0-60.16l169.813-169.813-169.813-169.813c-16.64-16.64-16.64-43.52 0-60.16l185.173-185.173c16.64-16.64 43.52-16.64 60.16 0l169.813 169.813 169.813-169.813c8.533-8.533 19.2-12.373 30.293-12.373s21.76 4.267 30.293 12.373l185.173 185.173c16.64 16.64 16.64 43.52 0 60.16l-170.24 169.813zM512 554.667c23.467 0 42.667-19.2 42.667-42.667s-19.2-42.667-42.667-42.667-42.667 19.2-42.667 42.667 19.2 42.667 42.667 42.667zM311.040 471.040l-154.88 154.453 154.88 154.88 154.453-154.453-154.453-154.88zM426.667 384c-23.467 0-42.667 19.2-42.667 42.667s19.2 42.667 42.667 42.667 42.667-19.2 42.667-42.667-19.2-42.667-42.667-42.667zM512 298.667c-23.467 0-42.667 19.2-42.667 42.667s19.2 42.667 42.667 42.667 42.667-19.2 42.667-42.667-19.2-42.667-42.667-42.667zM597.333 469.334c23.467 0 42.667-19.2 42.667-42.667s-19.2-42.667-42.667-42.667-42.667 19.2-42.667 42.667 19.2 42.667 42.667 42.667zM710.827 70.827l-154.88 154.453 154.88 154.88 154.453-154.453-154.453-154.88z" />
-<glyph unicode="&#xe832;" d="M682.667 512h-85.333v-85.333h85.333v85.333zM682.667 341.334h-85.333v-85.333h85.333v85.333zM341.333 512h-85.333v-85.333h85.333v85.333zM512 512h-85.333v-85.333h85.333v85.333zM853.333 768h-682.667c-46.933 0-85.333-38.4-85.333-85.333v-512c0-46.933 38.4-85.333 85.333-85.333h682.667c46.933 0 85.333 38.4 85.333 85.333v512c0 46.933-38.4 85.333-85.333 85.333zM853.333 170.667h-682.667v512h682.667v-512z" />
-<glyph unicode="&#xe833;" d="M896 128v597.333c0 46.933-38.4 85.333-85.333 85.333h-597.333c-46.933 0-85.333-38.4-85.333-85.333v-597.333c0-46.933 38.4-85.333 85.333-85.333h597.333c46.933 0 85.333 38.4 85.333 85.333zM362.667 362.667l106.667-128.427 149.333 192.427 192-256h-597.333l149.333 192z" />
-<glyph unicode="&#xe834;" d="M810.667 810.667h-597.333c-46.933 0-85.333-38.4-85.333-85.333v-597.333c0-46.933 38.4-85.333 85.333-85.333h597.333c46.933 0 85.333 38.4 85.333 85.333v597.333c0 46.933-38.4 85.333-85.333 85.333zM234.667 618.667h85.333v85.333h64v-85.333h85.333v-64h-85.333v-85.333h-64v85.333h-85.333v64zM810.667 128h-597.333l597.333 597.333v-597.333zM725.333 213.334v64h-213.333v-64h213.333z" />
-<glyph unicode="&#xe835;" d="M597.333 682.667l-160-213.333 121.6-162.133-68.267-51.2c-72.107 96-192 256-192 256l-256-341.333h938.667l-384 512z" />
-<glyph unicode="&#xe836;" d="M256 810.667h-128v-128c70.827 0 128 57.173 128 128zM597.333 810.667h-85.333c0-212.053-171.947-384-384-384v-85.333c259.413 0 469.333 210.347 469.333 469.333zM426.667 810.667h-85.333c0-117.76-95.573-213.333-213.333-213.333v-85.333c165.12 0 298.667 133.547 298.667 298.667zM426.667 42.667h85.333c0 212.053 171.947 384 384 384v85.333c-258.987 0-469.333-210.347-469.333-469.333zM768 42.667h128v128c-70.827 0-128-57.173-128-128zM597.333 42.667h85.333c0 117.76 95.573 213.333 213.333 213.333v85.333c-165.12 0-298.667-133.547-298.667-298.667z" />
-<glyph unicode="&#xe837;" d="M426.667 810.667h-85.333c0-15.787-1.707-30.72-5.12-45.227l67.84-67.84c14.507 34.56 22.613 72.96 22.613 113.067zM128 756.48l121.173-121.173c-34.56-23.893-75.947-37.973-121.173-37.973v-85.333c68.693 0 131.84 23.467 182.187 62.293l61.013-61.013c-66.56-54.187-151.040-86.613-243.2-86.613v-85.333c115.627 0 221.44 42.24 303.36 111.787l106.667-106.667c-69.12-82.347-111.36-188.16-111.36-303.787h85.333c0 92.16 32.427 176.64 86.613 242.773l61.013-61.013c-38.827-49.92-62.293-113.067-62.293-181.76h85.333c0 45.227 14.080 86.613 37.973 121.173l121.173-121.173 54.187 54.187-713.813 713.813-54.187-54.187zM597.333 810.667h-85.333c0-64-15.787-124.16-43.52-177.493l62.293-62.293c41.813 69.973 66.56 151.893 66.56 239.787zM850.773 250.88c14.507 3.413 29.44 5.12 45.227 5.12v85.333c-40.107 0-78.507-8.107-113.493-22.187l68.267-68.267zM656.213 445.44l62.293-62.293c53.333 27.733 113.493 43.52 177.493 43.52v85.333c-87.893 0-169.813-24.747-239.787-66.56z" />
-<glyph unicode="&#xe838;" d="M512 853.334c-235.52 0-426.667-191.147-426.667-426.667s191.147-426.667 426.667-426.667 426.667 191.147 426.667 426.667-191.147 426.667-426.667 426.667z" />
-<glyph unicode="&#xe839;" d="M811.093 810.667h-597.333c-46.933 0-85.333-38.4-85.333-85.333v-597.333c0-46.933 38.4-85.333 85.333-85.333h597.333c46.933 0 85.333 38.4 85.333 85.333v597.333c0 46.933-38.4 85.333-85.333 85.333zM640.427 490.667c0-35.413-28.587-64-64-64 35.413 0 64-28.587 64-64v-64c0-47.36-38.4-85.333-85.333-85.333h-170.667v85.333h170.667v85.333h-85.333v85.333h85.333v85.333h-170.667v85.333h170.667c46.933 0 85.333-37.973 85.333-85.333v-64z" />
-<glyph unicode="&#xe83a;" d="M810.667 810.667h-597.333c-46.933 0-85.333-38.4-85.333-85.333v-597.333c0-46.933 38.4-85.333 85.333-85.333h597.333c46.933 0 85.333 38.4 85.333 85.333v597.333c0 46.933-38.4 85.333-85.333 85.333zM640 213.334h-85.333v170.667h-170.667v256h85.333v-170.667h85.333v170.667h85.333v-426.667z" />
-<glyph unicode="&#xe83b;" d="M810.667 810.667h-597.333c-46.933 0-85.333-38.4-85.333-85.333v-597.333c0-46.933 38.4-85.333 85.333-85.333h597.333c46.933 0 85.333 38.4 85.333 85.333v597.333c0 46.933-38.4 85.333-85.333 85.333zM640 554.667h-170.667v-85.333h85.333c46.933 0 85.333-37.973 85.333-85.333v-85.333c0-47.36-38.4-85.333-85.333-85.333h-170.667v85.333h170.667v85.333h-170.667v256h256v-85.333z" />
-<glyph unicode="&#xe83c;" d="M469.333 298.667h85.333v85.333h-85.333v-85.333zM810.667 810.667h-597.333c-46.933 0-85.333-38.4-85.333-85.333v-597.333c0-46.933 38.4-85.333 85.333-85.333h597.333c46.933 0 85.333 38.4 85.333 85.333v597.333c0 46.933-38.4 85.333-85.333 85.333zM640 554.667h-170.667v-85.333h85.333c46.933 0 85.333-37.973 85.333-85.333v-85.333c0-47.36-38.4-85.333-85.333-85.333h-85.333c-46.933 0-85.333 37.973-85.333 85.333v256c0 47.36 38.4 85.333 85.333 85.333h170.667v-85.333z" />
-<glyph unicode="&#xe83d;" d="M810.667 810.667h-597.333c-46.933 0-85.333-38.4-85.333-85.333v-597.333c0-46.933 38.4-85.333 85.333-85.333h597.333c46.933 0 85.333 38.4 85.333 85.333v597.333c0 46.933-38.4 85.333-85.333 85.333zM597.333 213.334h-85.333v341.333h-85.333v85.333h170.667v-426.667z" />
-<glyph unicode="&#xe83e;" d="M810.667 810.667h-597.333c-46.933 0-85.333-38.4-85.333-85.333v-597.333c0-46.933 38.4-85.333 85.333-85.333h597.333c46.933 0 85.333 38.4 85.333 85.333v597.333c0 46.933-38.4 85.333-85.333 85.333zM640 469.334c0-47.36-38.4-85.333-85.333-85.333h-85.333v-85.333h170.667v-85.333h-256v170.667c0 47.36 38.4 85.333 85.333 85.333h85.333v85.333h-170.667v85.333h170.667c46.933 0 85.333-37.973 85.333-85.333v-85.333z" />
-<glyph unicode="&#xe83f;" d="M512 512c-164.693 0-298.667-133.973-298.667-298.667h85.333c0 117.76 95.573 213.333 213.333 213.333s213.333-95.573 213.333-213.333h85.333c0 164.693-133.973 298.667-298.667 298.667zM512 682.667c-258.987 0-469.333-210.347-469.333-469.333h85.333c0 211.627 172.373 384 384 384s384-172.373 384-384h85.333c0 258.987-210.347 469.333-469.333 469.333z" />
-<glyph unicode="&#xe840;" d="M554.667 640h-85.333v-170.667h-170.667v-85.333h170.667v-170.667h85.333v170.667h170.667v85.333h-170.667v170.667zM512 853.334c-235.093 0-426.667-191.573-426.667-426.667s191.573-426.667 426.667-426.667h341.333c46.933 0 85.333 38.4 85.333 85.333v341.333c0 235.093-191.573 426.667-426.667 426.667zM512 85.334c-188.16 0-341.333 153.173-341.333 341.333s153.173 341.333 341.333 341.333 341.333-153.173 341.333-341.333-153.173-341.333-341.333-341.333z" />
-<glyph unicode="&#xe841;" d="M768 768l85.333-170.667h-128l-85.333 170.667h-85.333l85.333-170.667h-128l-85.333 170.667h-85.333l85.333-170.667h-128l-85.333 170.667h-42.667c-46.933 0-84.907-38.4-84.907-85.333l-0.427-512c0-46.933 38.4-85.333 85.333-85.333h682.667c46.933 0 85.333 38.4 85.333 85.333v597.333h-170.667z" />
-<glyph unicode="&#xe842;" d="M945.92 547.414c0 165.12-133.547 298.667-298.667 298.667s-298.667-133.547-298.667-298.667c0-148.053 107.52-270.507 248.747-293.973v-168.107h-341.333v128h42.667v170.667c0 23.467-19.2 42.667-42.667 42.667h-128c-23.467 0-42.667-19.2-42.667-42.667v-170.667h42.667v-213.333h682.667v85.333h-128v165.547c148.053 17.493 263.253 143.36 263.253 296.533zM192 469.334c35.413 0 64 28.587 64 64s-28.587 64-64 64-64-28.587-64-64 28.587-64 64-64z" />
-<glyph unicode="&#xe843;" d="M554.667 250.88c148.053 17.493 263.253 143.36 263.253 296.533 0 165.12-133.547 298.667-298.667 298.667s-298.667-133.547-298.667-298.667c0-148.053 107.52-270.507 248.747-293.973v-168.107h-256v-85.333h597.333v85.333h-256v165.547z" />
-<glyph unicode="&#xe844;" d="M657.493 622.507l-60.16 60.16-256-256 256-256 60.16 60.16-195.413 195.84z" />
-<glyph unicode="&#xe845;" d="M426.667 682.667l-60.16-60.16 195.413-195.84-195.413-195.84 60.16-60.16 256 256z" />
-<glyph unicode="&#xe846;" d="M512 810.667c-212.053 0-384-171.947-384-384s171.947-384 384-384c35.413 0 64 28.587 64 64 0 16.64-6.4 31.573-16.64 43.093-9.813 11.093-16.213 26.027-16.213 42.24 0 35.413 28.587 64 64 64h75.52c117.76 0 213.333 95.573 213.333 213.333 0 188.587-171.947 341.333-384 341.333zM277.333 426.667c-35.413 0-64 28.587-64 64s28.587 64 64 64 64-28.587 64-64-28.587-64-64-64zM405.333 597.334c-35.413 0-64 28.587-64 64s28.587 64 64 64 64-28.587 64-64-28.587-64-64-64zM618.667 597.334c-35.413 0-64 28.587-64 64s28.587 64 64 64 64-28.587 64-64-28.587-64-64-64zM746.667 426.667c-35.413 0-64 28.587-64 64s28.587 64 64 64 64-28.587 64-64-28.587-64-64-64z" />
-<glyph unicode="&#xe847;" d="M512 853.334c-235.947 0-426.667-190.72-426.667-426.667s190.72-426.667 426.667-426.667 426.667 190.72 426.667 426.667-190.72 426.667-426.667 426.667zM512 85.334c-188.16 0-341.333 153.173-341.333 341.333s153.173 341.333 341.333 341.333 341.333-153.173 341.333-341.333-153.173-341.333-341.333-341.333z" />
-<glyph unicode="&#xe848;" d="M853.333 659.627v-465.493c-110.933 32.853-225.28 49.493-341.333 49.493s-230.4-16.64-341.333-49.493v465.493c110.933-32.853 225.28-49.493 341.333-49.493 116.053-0.427 230.4 16.213 341.333 49.493zM914.347 768c-4.267 0-8.533-0.853-13.227-2.56-125.44-46.933-257.28-69.973-389.12-69.973s-263.68 23.467-389.12 69.973c-4.693 1.707-9.387 2.56-13.227 2.56-14.507 0-24.32-9.813-24.32-26.88v-629.333c0-16.64 9.813-26.453 24.32-26.453 4.267 0 8.533 0.853 13.227 2.56 125.44 46.933 257.28 69.973 389.12 69.973s263.68-23.467 389.12-69.973c4.693-1.707 8.96-2.56 13.227-2.56 14.080 0 24.32 9.813 24.32 26.88v628.907c0 17.067-10.24 26.88-24.32 26.88z" />
-<glyph unicode="&#xe849;" d="M850.773 37.547c-46.933 125.44-69.973 257.28-69.973 389.12s23.467 263.68 69.973 389.12c1.707 4.693 2.56 9.387 2.56 13.227 0 14.507-9.813 24.32-26.88 24.32h-628.907c-17.067 0-26.88-9.813-26.88-24.32 0-4.267 0.853-8.533 2.56-13.227 46.933-125.44 70.4-257.28 70.4-389.12s-23.467-263.68-69.973-389.12c-2.133-4.693-2.987-9.387-2.987-13.227 0-14.080 9.813-24.32 26.88-24.32h629.333c16.64 0 26.88 10.24 26.88 24.32-0.427 4.267-1.28 8.533-2.987 13.227zM279.040 85.334c32.853 110.933 49.493 225.28 49.493 341.333s-16.64 230.4-49.493 341.333h465.493c-32.853-110.933-49.493-225.28-49.493-341.333s16.64-230.4 49.493-341.333h-465.493z" />
-<glyph unicode="&#xe84a;" d="M512 682.667c104.533 0 200.96-8.533 311.040-27.307 20.053-75.947 30.293-152.747 30.293-228.693s-10.24-152.747-30.293-228.693c-110.080-18.773-206.507-27.307-311.040-27.307s-200.96 8.533-311.040 27.307c-20.053 75.947-30.293 152.747-30.293 228.693s10.24 152.747 30.293 228.693c110.080 18.773 206.507 27.307 311.040 27.307zM512 768c-116.48 0-222.72-10.24-339.2-30.72l-39.68-6.827-10.667-38.4c-24.747-88.32-37.12-177.067-37.12-265.387s12.373-177.067 37.12-265.387l10.667-37.973 39.68-6.827c116.48-20.907 222.72-31.147 339.2-31.147s222.72 10.24 339.2 30.72l39.68 6.827 10.667 37.973c24.747 88.747 37.12 177.493 37.12 265.813s-12.373 177.067-37.12 265.387l-10.667 37.973-39.68 6.827c-116.48 20.907-222.72 31.147-339.2 31.147z" />
-<glyph unicode="&#xe84b;" d="M981.333 170.667v512c0 46.933-38.4 85.333-85.333 85.333h-768c-46.933 0-85.333-38.4-85.333-85.333v-512c0-46.933 38.4-85.333 85.333-85.333h768c46.933 0 85.333 38.4 85.333 85.333zM362.667 405.334l106.667-128.427 149.333 192.427 192-256h-597.333l149.333 192z" />
-<glyph unicode="&#xe84c;" d="M768 853.334h-512c-46.933 0-85.333-38.4-85.333-85.333v-682.667c0-46.933 38.4-85.333 85.333-85.333h512c46.933 0 85.333 38.4 85.333 85.333v682.667c0 46.933-38.4 85.333-85.333 85.333zM256 768h213.333v-341.333l-106.667 64-106.667-64v341.333zM256 128l128 164.693 91.307-110.080 128 164.693 164.693-219.307h-512z" />
-<glyph unicode="&#xe84d;" d="M648.533 426.667c0-75.405-61.128-136.533-136.533-136.533s-136.533 61.128-136.533 136.533c0 75.405 61.128 136.533 136.533 136.533s136.533-61.128 136.533-136.533zM384 853.334l-78.080-85.333h-135.253c-46.933 0-85.333-38.4-85.333-85.333v-512c0-46.933 38.4-85.333 85.333-85.333h682.667c46.933 0 85.333 38.4 85.333 85.333v512c0 46.933-38.4 85.333-85.333 85.333h-135.253l-78.080 85.333h-256zM512 213.334c-117.76 0-213.333 95.573-213.333 213.333s95.573 213.333 213.333 213.333 213.333-95.573 213.333-213.333-95.573-213.333-213.333-213.333z" />
-<glyph unicode="&#xe84e;" d="M938.667 256v512c0 46.933-38.4 85.333-85.333 85.333h-512c-46.933 0-85.333-38.4-85.333-85.333v-512c0-46.933 38.4-85.333 85.333-85.333h512c46.933 0 85.333 38.4 85.333 85.333zM469.333 426.667l86.613-115.627 126.72 158.293 170.667-213.333h-512l128 170.667zM85.333 682.667v-597.333c0-46.933 38.4-85.333 85.333-85.333h597.333v85.333h-597.333v597.333h-85.333z" />
-<glyph unicode="&#xe84f;" d="M896 128v597.333c0 46.933-38.4 85.333-85.333 85.333h-597.333c-46.933 0-85.333-38.4-85.333-85.333v-597.333c0-46.933 38.4-85.333 85.333-85.333h597.333c46.933 0 85.333 38.4 85.333 85.333zM362.667 362.667l106.667-128.427 149.333 192.427 192-256h-597.333l149.333 192z" />
-<glyph unicode="&#xe850;" d="M512 416c52.907 0 96 43.093 96 96s-43.093 96-96 96-96-43.093-96-96 43.093-96 96-96zM704 245.334c0 64-128 96-192 96s-192-32-192-96v-32h384v32zM810.667 810.667h-597.333c-46.933 0-85.333-38.4-85.333-85.333v-597.333c0-46.933 38.4-85.333 85.333-85.333h597.333c46.933 0 85.333 38.4 85.333 85.333v597.333c0 46.933-38.4 85.333-85.333 85.333zM810.667 128h-597.333v597.333h597.333v-597.333z" />
-<glyph unicode="&#xe851;" d="M512 746.667c-213.333 0-395.52-132.693-469.333-320 73.813-187.307 256-320 469.333-320s395.52 132.693 469.333 320c-73.813 187.307-256 320-469.333 320zM512 213.334c-117.76 0-213.333 95.573-213.333 213.333s95.573 213.333 213.333 213.333 213.333-95.573 213.333-213.333-95.573-213.333-213.333-213.333zM512 554.667c-70.827 0-128-57.173-128-128s57.173-128 128-128 128 57.173 128 128-57.173 128-128 128z" />
-<glyph unicode="&#xe852;" d="M303.36 574.72l-60.16 60.587c-38.4-49.493-62.293-106.667-69.547-165.973h86.187c5.973 37.12 20.907 73.387 43.52 105.387zM259.84 384h-86.187c7.253-59.307 30.72-116.48 69.12-165.973l60.16 60.587c-22.187 32-37.12 67.84-43.093 105.387zM302.933 157.014c49.493-38.4 107.093-61.44 166.4-68.693v86.613c-37.12 6.4-72.96 20.907-104.96 43.947l-61.44-61.867zM554.667 765.014v130.987l-194.133-194.133 194.133-189.867v166.827c121.173-20.48 213.333-125.44 213.333-252.16s-92.16-231.68-213.333-252.16v-86.187c168.533 20.907 298.667 164.267 298.667 338.347s-130.133 317.44-298.667 338.347z" />
-<glyph unicode="&#xe853;" d="M663.467 701.867l-194.133 194.133v-130.987c-168.107-20.907-298.667-164.267-298.667-338.347s130.133-317.44 298.667-338.347v86.187c-121.173 20.48-213.333 125.44-213.333 252.16s92.16 231.68 213.333 252.16v-166.827l194.133 189.867zM850.347 469.334c-7.253 59.307-30.72 116.48-69.12 165.973l-60.587-60.587c23.040-32 37.547-68.267 43.52-105.387h86.187zM554.667 174.934v-86.187c59.307 7.253 116.907 30.293 166.4 68.693l-61.44 61.44c-32-23.040-67.84-37.973-104.96-43.947zM720.64 278.187l60.587-60.16c38.4 49.493 61.867 106.667 69.12 165.973h-86.187c-5.973-37.12-20.48-73.387-43.52-105.813z" />
-<glyph unicode="&#xe854;" d="M426.667 597.334v-341.333l213.333 170.667-213.333 170.667zM810.667 810.667h-597.333c-46.933 0-85.333-38.4-85.333-85.333v-597.333c0-46.933 38.4-85.333 85.333-85.333h597.333c46.933 0 85.333 38.4 85.333 85.333v597.333c0 46.933-38.4 85.333-85.333 85.333zM810.667 128h-597.333v597.333h597.333v-597.333z" />
-<glyph unicode="&#xe855;" d="M896 682.667h-768c-46.933 0-85.333-38.4-85.333-85.333v-341.333c0-46.933 38.4-85.333 85.333-85.333h768c46.933 0 85.333 38.4 85.333 85.333v341.333c0 46.933-38.4 85.333-85.333 85.333zM896 256h-768v341.333h85.333v-170.667h85.333v170.667h85.333v-170.667h85.333v170.667h85.333v-170.667h85.333v170.667h85.333v-170.667h85.333v170.667h85.333v-341.333z" />
-<glyph unicode="&#xe856;" d="M107.947 100.267l57.173-23.893v385.28l-103.68-250.027c-17.493-43.52 3.413-93.44 46.507-111.36zM939.947 258.134l-211.627 510.72c-13.227 32-44.373 51.627-77.227 52.48-11.093 0-22.613-1.707-33.707-6.4l-314.453-130.133c-32-13.227-51.627-43.947-52.48-76.8-0.427-11.52 1.707-23.040 6.4-34.133l211.627-510.72c13.227-32.427 44.8-52.053 78.080-52.48 11.093 0 22.187 2.133 32.853 6.4l314.027 130.133c43.52 17.92 64.427 67.84 46.507 110.933zM336.213 565.334c-23.467 0-42.667 19.2-42.667 42.667s19.2 42.667 42.667 42.667 42.667-19.2 42.667-42.667-19.2-42.667-42.667-42.667zM250.88 96c0-46.933 38.4-85.333 85.333-85.333h61.867l-147.2 355.84v-270.507z" />
-<glyph unicode="&#xe857;" d="M853.333 768h-135.253l-78.080 85.333h-256l-78.080-85.333h-135.253c-46.933 0-85.333-38.4-85.333-85.333v-512c0-46.933 38.4-85.333 85.333-85.333h682.667c46.933 0 85.333 38.4 85.333 85.333v512c0 46.933-38.4 85.333-85.333 85.333zM640 277.334v106.667h-256v-106.667l-149.333 149.333 149.333 149.333v-106.667h256v106.667l149.333-149.333-149.333-149.333z" />
-<glyph unicode="&#xe858;" d="M768 533.334v149.333c0 23.467-19.2 42.667-42.667 42.667h-597.333c-23.467 0-42.667-19.2-42.667-42.667v-512c0-23.467 19.2-42.667 42.667-42.667h597.333c23.467 0 42.667 19.2 42.667 42.667v149.333l170.667-170.667v554.667l-170.667-170.667zM554.667 277.334v106.667h-256v-106.667l-149.333 149.333 149.333 149.333v-106.667h256v106.667l149.333-149.333-149.333-149.333z" />
-<glyph unicode="&#xe859;" d="M511.573 853.334c-235.52 0-426.24-191.147-426.24-426.667s190.72-426.667 426.24-426.667c235.947 0 427.093 191.147 427.093 426.667s-191.147 426.667-427.093 426.667zM512 85.334c-188.587 0-341.333 152.747-341.333 341.333s152.747 341.333 341.333 341.333 341.333-152.747 341.333-341.333-152.747-341.333-341.333-341.333zM661.333 469.334c35.413 0 64 28.587 64 64s-28.587 64-64 64-64-28.587-64-64 28.587-64 64-64zM362.667 469.334c35.413 0 64 28.587 64 64s-28.587 64-64 64-64-28.587-64-64 28.587-64 64-64zM512 192c99.413 0 183.893 62.293 218.027 149.333h-436.053c34.133-87.040 118.613-149.333 218.027-149.333z" />
-<glyph unicode="&#xe85a;" d="M832.427 807.254l-701.013-701.013c3.84-14.507 11.52-27.733 21.76-38.4 10.667-10.24 23.893-17.92 38.4-21.76l701.44 701.013c-8.107 29.44-31.147 52.48-60.587 60.16zM506.88 810.667l-378.88-378.88v-120.747l499.627 499.627h-120.747zM213.333 810.667c-46.933 0-85.333-38.4-85.333-85.333v-85.333l170.667 170.667h-85.333zM810.667 42.667c23.467 0 44.8 9.387 60.16 25.173 15.787 15.36 25.173 36.693 25.173 60.16v85.333l-170.667-170.667h85.333zM396.373 42.667h120.747l378.88 378.88v120.747l-499.627-499.627z" />
-<glyph unicode="&#xe85b;" d="M692.907 607.574c-49.92 49.92-115.2 75.093-180.907 75.093v-256l-180.907-180.907c99.84-99.84 261.973-99.84 362.24 0 99.84 99.84 99.84 261.973-0.427 361.813zM512 853.334c-235.52 0-426.667-191.147-426.667-426.667s191.147-426.667 426.667-426.667 426.667 191.147 426.667 426.667-191.147 426.667-426.667 426.667zM512 85.334c-188.587 0-341.333 152.747-341.333 341.333s152.747 341.333 341.333 341.333 341.333-152.747 341.333-341.333-152.747-341.333-341.333-341.333z" />
-<glyph unicode="&#xe85c;" d="M495.36 385.28c-6.827 10.24-15.36 19.627-26.453 27.733-10.667 8.107-23.893 14.933-39.68 20.48 12.8 5.973 24.32 12.8 34.133 21.333s17.92 17.493 24.32 27.307c6.4 9.813 11.52 19.627 14.507 30.293 3.413 10.24 4.693 20.907 4.693 31.147 0 23.467-3.84 44.373-11.947 62.293-7.68 17.92-18.773 32.853-33.28 45.227-14.080 11.947-31.147 21.333-51.2 27.307-19.2 5.547-41.387 8.533-65.28 8.533-23.467 0-45.227-3.413-64.853-10.24-20.053-7.253-37.12-17.067-51.2-29.44s-25.6-26.88-33.28-43.947c-8.533-16.64-12.373-35.413-12.373-55.040h84.48c0 11.093 2.133 20.907 5.973 29.44s9.387 16.213 16.213 22.187c7.253 5.973 15.36 10.667 24.747 14.080s19.627 5.12 31.147 5.12c26.027 0 45.227-6.827 58.027-20.053s18.773-32 18.773-56.32c0-11.52-1.707-22.187-5.12-31.573s-8.96-17.493-16.213-24.32c-7.253-6.827-16.213-11.947-26.88-15.787s-23.467-5.547-37.973-5.547h-49.92v-66.987h50.347c14.507 0 27.307-1.707 38.827-4.693 11.52-3.413 21.333-8.107 29.44-14.933s14.507-15.36 18.773-26.027c4.267-10.24 6.827-23.040 6.827-37.12 0-26.453-7.68-46.507-22.613-60.587s-35.84-20.907-61.867-20.907c-12.373 0-23.893 1.707-34.133 5.547-10.24 3.413-18.773 8.533-26.027 15.36s-12.8 14.507-16.64 23.893c-3.84 9.387-5.973 19.627-5.973 30.72h-84.907c0-23.467 4.693-43.947 13.653-61.867s21.333-32.853 36.693-44.8 32.853-20.907 52.907-26.88 40.96-8.96 63.147-8.96c24.32 0 46.507 3.413 67.413 9.813s38.827 16.213 53.76 29.013c15.36 12.8 27.307 28.16 35.84 46.933 8.533 18.347 12.8 39.68 12.8 63.147 0 12.373-1.707 24.747-4.693 36.693-3.413 10.667-8.107 21.76-14.933 32.427zM890.453 325.547c-5.973 11.947-14.933 22.613-26.88 31.573s-26.027 16.64-43.093 22.613-36.267 11.52-57.6 16.213c-14.933 2.987-27.307 6.4-37.12 9.813s-17.493 6.827-23.467 10.667c-5.973 3.84-9.813 8.107-11.947 12.8s-3.413 10.24-3.413 16.64 1.28 11.947 3.84 17.493c2.56 5.547 6.4 10.667 11.52 14.507 5.12 4.267 11.52 7.68 19.2 10.24s17.067 3.84 27.307 3.84c10.667 0 20.053-1.707 28.16-4.693s14.933-7.253 20.48-12.373c5.547-5.12 9.387-11.093 12.373-17.92 2.56-6.827 4.267-13.653 4.267-20.907h83.2c0 16.64-3.413 32-10.24 46.507s-16.64 26.88-29.44 37.547c-12.8 10.667-28.16 18.773-46.507 25.173s-39.253 9.387-62.293 9.387c-21.76 0-41.813-2.987-59.307-8.96s-32.853-14.080-45.227-24.32c-12.373-10.24-21.76-22.187-28.587-35.84s-9.813-27.733-9.813-43.093 3.413-29.013 9.813-40.96c6.4-11.947 15.787-22.187 27.307-31.147s25.6-16.213 41.813-22.613c16.213-5.973 34.56-11.093 54.187-15.36 16.64-3.413 30.293-7.253 40.533-11.093s18.347-8.107 24.32-12.373c5.547-4.267 9.387-9.387 11.52-14.507s2.987-10.667 2.987-16.64c0-13.653-5.547-24.32-17.067-32.853s-28.16-12.373-49.92-12.373c-9.387 0-18.347 0.853-27.307 3.413-8.96 2.133-17.067 5.547-23.893 10.24-7.253 4.693-12.8 11.093-17.493 18.773s-7.253 17.493-7.68 28.587h-80.64c0-15.36 3.413-30.293 10.24-44.8s16.64-27.733 29.867-39.68c13.227-11.52 29.44-20.907 49.067-28.16s41.813-10.667 67.413-10.667c22.613 0 43.093 2.56 61.44 8.107s34.133 13.227 47.36 23.040c13.227 9.813 23.040 21.76 30.293 35.413s10.667 28.587 10.667 45.227c-0.853 17.067-3.84 31.573-10.24 43.52z" />
-<glyph unicode="&#xe85d;" d="M0 609.28v-71.68l128 42.667v-409.6h85.333v512h-10.667l-202.667-73.387zM1014.613 325.547c-5.973 11.947-14.933 22.613-26.88 31.573s-26.027 16.64-43.093 22.613-36.267 11.52-57.6 16.213c-14.933 2.987-27.307 6.4-37.12 9.813s-17.493 6.827-23.467 10.667c-5.973 3.84-9.813 8.107-11.947 12.8s-3.413 10.24-3.413 16.64c0 5.973 1.28 11.947 3.84 17.493s6.4 10.667 11.52 14.507c5.12 4.267 11.52 7.68 19.2 10.24s17.067 3.84 27.307 3.84c10.667 0 20.053-1.707 28.16-4.693s14.933-7.253 20.48-12.373c5.547-5.12 9.387-11.093 12.373-17.92 2.56-6.827 4.267-13.653 4.267-20.907h83.2c0 16.64-3.413 32-10.24 46.507s-16.64 26.88-29.44 37.547c-12.8 10.667-28.16 18.773-46.507 25.173s-39.253 9.387-62.293 9.387c-21.76 0-41.813-2.987-59.307-8.96s-32.853-14.080-45.227-24.32c-12.373-10.24-21.76-22.187-28.587-35.84s-9.813-27.733-9.813-43.093 3.413-29.44 9.813-40.96c6.4-11.947 15.36-22.187 27.307-31.147 11.52-8.96 25.6-16.213 41.813-22.613 16.213-5.973 34.56-11.093 54.187-15.36 16.64-3.413 30.293-7.253 40.533-11.093s18.347-8.107 24.32-12.373c5.547-4.267 9.387-9.387 11.52-14.507s2.987-10.667 2.987-16.64c0-13.653-5.547-24.32-17.067-32.853s-28.16-12.373-49.92-12.373c-9.387 0-18.347 0.853-27.307 3.413-8.96 2.133-17.067 5.547-23.893 10.24-7.253 4.693-12.8 11.093-17.493 18.773s-7.253 17.493-7.68 28.587h-80.64c0-15.36 3.413-30.293 10.24-44.8s16.64-27.733 29.867-39.68c13.227-11.52 29.44-20.907 49.067-28.16s41.813-10.667 67.413-10.667c22.613 0 43.093 2.56 61.44 8.107s34.133 13.227 47.36 23.040c13.227 9.813 23.040 21.76 30.293 35.413s10.667 28.587 10.667 45.227c-0.853 17.067-3.84 31.573-10.24 43.52zM589.653 637.867c-14.507 17.067-32 29.867-52.48 37.547-20.053 7.68-43.093 11.52-67.84 11.52s-47.36-3.84-67.84-11.52c-20.48-7.68-37.973-20.053-52.48-37.547s-25.6-39.68-33.707-67.84c-7.68-27.733-11.947-61.867-11.947-101.973v-81.92c0-40.107 3.84-74.24 11.947-101.973 8.107-28.16 19.2-50.773 34.133-68.267 14.507-17.493 32-30.293 52.48-37.973s43.093-11.947 67.84-11.947c25.173 0 47.787 3.84 67.84 11.947 20.48 7.68 37.547 20.48 52.053 37.973s25.6 40.107 33.28 68.267c7.68 27.733 11.947 61.867 11.947 101.973v81.92c0 40.107-3.84 74.24-11.947 101.973-7.68 28.16-18.773 50.773-33.28 67.84zM550.4 374.614c0-25.6-1.707-47.36-5.12-65.28s-8.533-32.427-15.36-43.52c-6.827-11.093-15.36-19.2-25.173-24.32s-21.76-7.68-34.987-7.68c-12.8 0-24.747 2.56-34.987 7.68s-18.773 13.227-25.6 24.32c-6.827 11.093-12.373 25.6-16.213 43.52s-5.547 39.68-5.547 65.28v106.667c0 25.6 1.707 47.36 5.547 64.853s8.96 31.573 16.213 42.667c6.827 10.667 15.36 18.347 25.6 23.467 10.24 4.693 21.76 7.253 34.56 7.253 13.227 0 24.747-2.56 34.56-7.253 10.24-4.693 18.773-12.373 25.6-23.467 6.827-10.667 12.373-24.747 15.787-42.24s5.547-39.253 5.547-64.853v-107.093z" />
-<glyph unicode="&#xe85e;" d="M512 768c-94.293 0-170.667-76.373-170.667-170.667s76.373-170.667 170.667-170.667 170.667 76.373 170.667 170.667-76.373 170.667-170.667 170.667zM512 341.334c-113.92 0-341.333-57.173-341.333-170.667v-85.333h682.667v85.333c0 113.92-227.413 170.667-341.333 170.667z" />
-<glyph unicode="&#xe85f;" d="M812.373 744.534l-60.587-60.587c-66.133 52.48-149.333 84.053-239.787 84.053-78.080 0-150.613-23.467-211.2-63.147l62.293-62.293c43.52 25.173 94.72 40.107 148.907 40.107 165.12 0 298.667-133.547 298.667-298.667 0-54.187-14.933-105.387-40.107-148.907l61.867-61.867c40.107 60.16 63.573 132.693 63.573 210.773 0 90.453-31.573 173.653-84.053 239.36l60.587 60.587-60.16 60.587zM640 896h-256v-85.333h256v85.333zM469.333 535.894l85.333-85.333v146.773h-85.333v-61.44zM128.853 768l-54.187-54.187 117.333-117.76c-40.533-60.587-64-133.547-64-212.053 0-212.053 171.52-384 384-384 78.507 0 151.467 23.467 212.48 64l106.667-106.667 54.187 54.187-756.48 756.48zM512 85.334c-165.12 0-298.667 133.547-298.667 298.667 0 54.613 14.933 105.813 40.533 150.187l407.893-407.893c-43.947-26.027-95.147-40.96-149.76-40.96z" />
-<glyph unicode="&#xe860;" d="M640 896h-256v-85.333h256v85.333zM469.333 341.334h85.333v256h-85.333v-256zM811.947 623.36l60.587 60.587c-18.347 21.76-38.4 42.24-60.16 60.16l-60.587-60.587c-66.133 52.907-149.333 84.48-239.787 84.48-212.053 0-384-171.947-384-384s171.52-384 384-384 384 171.947 384 384c0 90.453-31.573 173.653-84.053 239.36zM512 85.334c-165.12 0-298.667 133.547-298.667 298.667s133.547 298.667 298.667 298.667 298.667-133.547 298.667-298.667-133.547-298.667-298.667-298.667z" />
-<glyph unicode="&#xe861;" d="M512 853.334c-235.52 0-426.667-191.147-426.667-426.667s191.147-426.667 426.667-426.667 426.667 191.147 426.667 426.667-191.147 426.667-426.667 426.667zM469.333 88.32c-168.107 20.907-298.667 164.267-298.667 338.347s130.133 317.44 298.667 338.347v-676.693zM554.667 765.014c43.947-5.547 85.333-19.2 122.453-39.68h-122.453v39.68zM554.667 640h223.573c10.667-13.227 20.48-27.733 29.013-42.667h-252.587v42.667zM554.667 512h287.573c3.413-14.080 6.4-28.16 8.107-42.667h-295.68v42.667zM554.667 88.32v39.68h122.453c-37.12-20.48-78.507-34.133-122.453-39.68zM778.24 213.334h-223.573v42.667h252.587c-8.533-14.933-18.347-29.44-29.013-42.667zM842.24 341.334h-287.573v42.667h295.68c-1.707-14.507-4.693-28.587-8.107-42.667z" />
-<glyph unicode="&#xe862;" d="M938.667 170.667v85.333h-597.333v512h85.333l-128 128-128-128h85.333v-85.333h-170.667v-85.333h170.667v-341.333c0-46.933 38.4-85.333 85.333-85.333h341.333v-85.333h-85.333l128-128 128 128h-85.333v85.333h170.667zM426.667 597.334h256v-256h85.333v256c0 46.933-38.4 85.333-85.333 85.333h-256v-85.333z" />
-<glyph unicode="&#xe863;" d="M128 213.334v-85.333h256v85.333h-256zM128 725.334v-85.333h426.667v85.333h-426.667zM554.667 42.667v85.333h341.333v85.333h-341.333v85.333h-85.333v-256h85.333zM298.667 554.667v-85.333h-170.667v-85.333h170.667v-85.333h85.333v256h-85.333zM896 384v85.333h-426.667v-85.333h426.667zM640 554.667h85.333v85.333h170.667v85.333h-170.667v85.333h-85.333v-256z" />
-<glyph unicode="&#xe864;" d="M292.267 398.934h98.133l-49.067 155.733-49.067-155.733zM938.667 640l-51.2-268.373-64 268.373h-68.267l-63.573-268.373-51.627 268.373h-32.427c-62.72 78.080-158.293 128-266.24 128-188.587 0-341.333-152.747-341.333-341.333s152.747-341.333 341.333-341.333c133.547 0 249.173 77.227 305.067 189.013l4.267-18.347h74.667l64 260.267 64-260.267h74.667l87.467 384h-76.8zM439.467 256l-29.867 85.333h-136.533l-29.867-85.333h-81.067l136.533 384h85.333l136.533-384h-81.067z" />
-<glyph unicode="&#xe865;" d="M826.027 510.294c-29.44 147.2-158.72 257.707-314.027 257.707-123.307 0-230.4-69.973-283.733-172.373-128.427-13.653-228.267-122.453-228.267-254.293 0-141.227 114.773-256 256-256h554.667c117.76 0 213.333 95.573 213.333 213.333 0 112.64-87.467 203.947-197.973 211.627z" />
-<glyph unicode="&#xe866;" d="M151.467 147.627l60.16-60.16 76.373 76.8-60.16 60.16-76.373-76.8zM469.333-19.2h85.333v125.867h-85.333v-125.867zM170.667 490.667h-128v-85.333h128v85.333zM640 669.44v205.227h-256v-205.227c-76.373-44.373-128-126.72-128-221.44 0-141.227 114.773-256 256-256s256 114.773 256 256c0 94.72-51.627 177.067-128 221.44zM853.333 490.667v-85.333h128v85.333h-128zM735.573 163.84l76.373-76.8 60.16 60.16-76.8 76.373-59.733-59.733z" />
-<glyph unicode="&#xe867;" d="M213.333 320h597.333v256h-597.333v-256zM469.333 915.2v-125.867h85.333v125.867h-85.333zM812.373 808.534l-76.373-76.373 60.16-60.16 76.8 76.373-60.587 60.16zM554.667-19.2v125.867h-85.333v-125.867h85.333zM872.533 147.627l-76.8 76.373-60.16-60.16 76.373-76.8 60.587 60.587zM151.467 748.374l76.373-76.373 60.16 60.16-76.373 76.373-60.16-60.16zM211.627 87.467l76.373 76.8-60.16 60.16-76.373-76.373 60.16-60.587z" />
-<glyph unicode="&#xe868;" d="M288.427 732.16l-76.8 76.373-60.16-60.16 76.373-76.373 60.587 60.16zM170.667 490.667h-128v-85.333h128v85.333zM554.667 915.2h-85.333v-125.867h85.333v125.867zM872.533 748.374l-60.16 60.16-76.373-76.373 60.16-60.16 76.373 76.373zM735.573 163.84l76.373-76.8 60.16 60.16-76.8 76.373-59.733-59.733zM853.333 490.667v-85.333h128v85.333h-128zM512 704c-141.227 0-256-114.773-256-256s114.773-256 256-256 256 114.773 256 256-114.773 256-256 256zM469.333-19.2h85.333v125.867h-85.333v-125.867zM151.467 147.627l60.16-60.16 76.373 76.8-60.16 60.16-76.373-76.8z" />
-<glyph unicode="&#xe869;" d="M810.667 896h-597.333c-46.933 0-84.907-38.4-84.907-85.333l-0.427-551.68c0-29.44 14.933-55.467 37.547-70.827l346.453-230.827 346.027 230.827c22.613 15.36 37.547 41.387 37.547 70.827l0.427 551.68c0 46.933-38.4 85.333-85.333 85.333zM426.667 256l-213.333 213.333 60.16 60.16 153.173-152.747 323.84 323.84 60.16-60.587-384-384z" />
-<glyph unicode="&#xe86a;" d="M682.667 733.867c42.24 0 76.8 34.56 76.8 76.8s-34.56 76.8-76.8 76.8c-42.667 0-76.8-34.56-76.8-76.8s34.133-76.8 76.8-76.8zM810.667 426.667c-117.76 0-213.333-95.573-213.333-213.333s95.573-213.333 213.333-213.333 213.333 95.573 213.333 213.333-95.573 213.333-213.333 213.333zM810.667 64c-82.347 0-149.333 66.987-149.333 149.333s66.987 149.333 149.333 149.333 149.333-66.987 149.333-149.333-66.987-149.333-149.333-149.333zM631.467 512h179.2v76.8h-136.533l-82.347 139.52c-12.8 21.333-35.84 35.413-62.293 35.413-20.053 0-37.973-8.107-51.2-21.333l-157.867-157.867c-13.653-12.8-21.76-31.147-21.76-51.2 0-26.88 14.080-49.493 36.267-62.72l142.933-86.613v-213.333h76.8v276.48l-96 71.253 98.987 99.413 73.813-105.813zM213.333 426.667c-117.76 0-213.333-95.573-213.333-213.333s95.573-213.333 213.333-213.333 213.333 95.573 213.333 213.333-95.573 213.333-213.333 213.333zM213.333 64c-82.347 0-149.333 66.987-149.333 149.333s66.987 149.333 149.333 149.333 149.333-66.987 149.333-149.333-66.987-149.333-149.333-149.333z" />
-<glyph unicode="&#xe86b;" d="M170.667 256c0-37.547 16.64-71.253 42.667-94.72v-75.947c0-23.467 19.2-42.667 42.667-42.667h42.667c23.467 0 42.667 19.2 42.667 42.667v42.667h341.333v-42.667c0-23.467 19.2-42.667 42.667-42.667h42.667c23.467 0 42.667 19.2 42.667 42.667v75.947c26.027 23.467 42.667 57.173 42.667 94.72v426.667c0 149.333-152.747 170.667-341.333 170.667s-341.333-21.333-341.333-170.667v-426.667zM320 213.334c-35.413 0-64 28.587-64 64s28.587 64 64 64 64-28.587 64-64-28.587-64-64-64zM704 213.334c-35.413 0-64 28.587-64 64s28.587 64 64 64 64-28.587 64-64-28.587-64-64-64zM768 469.334h-512v213.333h512v-213.333z" />
-<glyph unicode="&#xe86c;" d="M807.253 682.24c-8.533 25.173-32.427 43.093-60.587 43.093h-469.333c-28.16 0-51.627-17.92-60.587-43.093l-88.747-255.573v-341.333c0-23.467 19.2-42.667 42.667-42.667h42.667c23.467 0 42.667 19.2 42.667 42.667v42.667h512v-42.667c0-23.467 19.2-42.667 42.667-42.667h42.667c23.467 0 42.667 19.2 42.667 42.667v341.333l-88.747 255.573zM277.333 256c-35.413 0-64 28.587-64 64s28.587 64 64 64 64-28.587 64-64-28.587-64-64-64zM746.667 256c-35.413 0-64 28.587-64 64s28.587 64 64 64 64-28.587 64-64-28.587-64-64-64zM213.333 469.334l64 192h469.333l64-192h-597.333z" />
-<glyph unicode="&#xe86d;" d="M853.333 42.667c-59.307 0-118.613 20.053-170.667 56.32-104.107-72.96-237.227-72.96-341.333 0-52.053-36.267-111.36-56.32-170.667-56.32h-85.333v-85.333h85.333c58.88 0 116.907 14.933 170.667 42.24 107.52-55.040 233.813-55.040 341.333 0 53.76-27.733 111.787-42.24 170.667-42.24h85.333v85.333h-85.333zM168.533 128h2.133c68.267 0 128.853 37.547 170.667 85.333 41.813-47.787 102.4-85.333 170.667-85.333s128.853 37.547 170.667 85.333c41.813-47.787 102.4-85.333 170.667-85.333h2.133l80.64 285.013c3.413 11.093 2.56 23.040-2.56 33.28s-14.507 17.92-25.6 21.333l-54.613 17.92v197.12c0 46.933-38.4 85.333-85.333 85.333h-128v128h-256v-128h-128c-46.933 0-85.333-38.4-85.333-85.333v-197.12l-55.040-17.92c-11.093-3.413-20.48-11.093-25.6-21.333s-6.4-22.187-2.56-33.28l81.067-285.013zM256 682.667h512v-169.387l-256 84.053-256-84.053v169.387z" />
-<glyph unicode="&#xe86e;" d="M512 853.334c-188.587 0-341.333-21.333-341.333-170.667v-405.333c0-82.347 66.987-149.333 149.333-149.333l-64-64v-21.333h512v21.333l-64 64c82.347 0 149.333 66.987 149.333 149.333v405.333c0 149.333-152.747 170.667-341.333 170.667zM320 213.334c-35.413 0-64 28.587-64 64s28.587 64 64 64 64-28.587 64-64-28.587-64-64-64zM469.333 469.334h-213.333v213.333h213.333v-213.333zM704 213.334c-35.413 0-64 28.587-64 64s28.587 64 64 64 64-28.587 64-64-28.587-64-64-64zM768 469.334h-213.333v213.333h213.333v-213.333z" />
-<glyph unicode="&#xe86f;" d="M170.667 277.334c0-82.347 66.987-149.333 149.333-149.333l-64-64v-21.333h512v21.333l-64 64c82.347 0 149.333 66.987 149.333 149.333v448c0 149.333-152.747 170.667-341.333 170.667s-341.333-21.333-341.333-170.667v-448zM512 213.334c-46.933 0-85.333 38.4-85.333 85.333s38.4 85.333 85.333 85.333 85.333-38.4 85.333-85.333-38.4-85.333-85.333-85.333zM768 512h-512v213.333h512v-213.333z" />
-<glyph unicode="&#xe870;" d="M512 853.334c-188.587 0-341.333-21.333-341.333-170.667v-405.333c0-82.347 66.987-149.333 149.333-149.333l-64-64v-21.333h512v21.333l-64 64c82.347 0 149.333 66.987 149.333 149.333v405.333c0 149.333-152.747 170.667-341.333 170.667zM320 213.334c-35.413 0-64 28.587-64 64s28.587 64 64 64 64-28.587 64-64-28.587-64-64-64zM469.333 469.334h-213.333v213.333h213.333v-213.333zM704 213.334c-35.413 0-64 28.587-64 64s28.587 64 64 64 64-28.587 64-64-28.587-64-64-64zM768 469.334h-213.333v213.333h213.333v-213.333z" />
-<glyph unicode="&#xe871;" d="M597.333 776.534c42.24 0 76.8 34.56 76.8 76.8 0 42.667-34.56 76.8-76.8 76.8-42.667 0-76.8-34.56-76.8-76.8s34.133-76.8 76.8-76.8zM602.453 512h208.213v76.8h-154.453l-85.333 142.080c-12.8 21.333-35.84 35.413-62.293 35.413-7.253 0-14.507-1.28-20.907-2.987l-231.68-72.107v-221.867h76.8v156.587l90.027 28.16-166.827-654.080h76.8l122.453 346.027 99.413-132.693v-213.333h76.8v273.493l-106.24 193.707 31.147 122.453 46.080-77.653z" />
-<glyph unicode="&#xe872;" d="M926.293 456.96l-384 384c-16.64 16.64-43.52 16.64-60.16 0l-384-384c-16.64-16.64-16.64-43.52 0-60.16l384-384c16.64-16.64 43.52-16.64 60.16 0l384 384c16.64 16.213 16.64 43.093 0 60.16zM597.333 320v106.667h-170.667v-128h-85.333v170.667c0 23.467 19.2 42.667 42.667 42.667h213.333v106.667l149.333-149.333-149.333-149.333z" />
-<glyph unicode="&#xe873;" d="M896 256v85.333l-341.333 213.333v234.667c0 35.413-28.587 64-64 64s-64-28.587-64-64v-234.667l-341.333-213.333v-85.333l341.333 106.667v-234.667l-85.333-64v-64l149.333 42.667 149.333-42.667v64l-85.333 64v234.667l341.333-106.667z" />
-<glyph unicode="&#xe874;" d="M298.667 384c70.827 0 128 57.173 128 128s-57.173 128-128 128-128-57.173-128-128 57.173-128 128-128zM810.667 640h-341.333v-298.667h-341.333v384h-85.333v-640h85.333v128h768v-128h85.333v384c0 94.293-76.373 170.667-170.667 170.667z" />
-<glyph unicode="&#xe875;" d="M845.227 299.094l50.773 39.253-61.013 61.013-50.773-39.253 61.013-61.013zM826.027 500.48l69.973 54.187-384 298.667-124.16-96.853 335.787-336.213 102.4 80.213zM139.52 896l-54.187-54.187 180.053-180.053-137.387-107.093 69.547-54.187 314.453-244.48 89.6 69.547 61.013-61.013-150.613-116.907-314.453 244.48-69.547-53.76 384-298.667 211.2 164.267 161.28-161.28 54.187 54.187-799.147 799.147z" />
-<glyph unicode="&#xe876;" d="M511.573 147.627l-314.453 244.48-69.12-53.76 384-298.667 384 298.667-69.547 54.187-314.88-244.907zM512 256l384 298.667-384 298.667-384-298.667 69.547-54.187 314.453-244.48z" />
-<glyph unicode="&#xe877;" d="M896 256v85.333l-341.333 213.333v234.667c0 35.413-28.587 64-64 64s-64-28.587-64-64v-234.667l-341.333-213.333v-85.333l341.333 106.667v-234.667l-85.333-64v-64l149.333 42.667 149.333-42.667v64l-85.333 64v234.667l341.333-106.667z" />
-<glyph unicode="&#xe878;" d="M469.333 213.334h85.333v42.667h42.667c23.467 0 42.667 19.2 42.667 42.667v128c0 23.467-19.2 42.667-42.667 42.667h-128v42.667h170.667v85.333h-85.333v42.667h-85.333v-42.667h-42.667c-23.467 0-42.667-19.2-42.667-42.667v-128c0-23.467 19.2-42.667 42.667-42.667h128v-42.667h-170.667v-85.333h85.333v-42.667zM853.333 768h-682.667c-47.36 0-84.907-37.973-84.907-85.333l-0.427-512c0-47.36 37.973-85.333 85.333-85.333h682.667c47.36 0 85.333 37.973 85.333 85.333v512c0 47.36-37.973 85.333-85.333 85.333zM853.333 170.667h-682.667v512h682.667v-512z" />
-<glyph unicode="&#xe879;" d="M853.333 426.667c0 46.933 38.4 85.333 85.333 85.333v170.667c0 46.933-38.4 85.333-85.333 85.333h-682.667c-46.933 0-84.907-38.4-84.907-85.333v-170.667c46.933 0 84.907-38.4 84.907-85.333s-37.973-85.333-85.333-85.333v-170.667c0-46.933 38.4-85.333 85.333-85.333h682.667c46.933 0 85.333 38.4 85.333 85.333v170.667c-46.933 0-85.333 38.4-85.333 85.333zM664.747 221.867l-152.747 98.133-152.747-98.133 46.080 175.787-140.373 114.773 180.907 10.667 66.133 168.107 65.707-168.533 180.907-10.667-140.373-114.773 46.507-175.36z" />
-<glyph unicode="&#xe87a;" d="M469.333 384v-256h-213.333v-85.333h512v85.333h-213.333v256l341.333 341.333v85.333h-768v-85.333l341.333-341.333zM320 640l-85.333 85.333h554.667l-85.333-85.333h-384z" />
-<glyph unicode="&#xe87b;" d="M853.333 810.667h-682.667v-426.667c0-94.293 76.373-170.667 170.667-170.667h256c94.293 0 170.667 76.373 170.667 170.667v128h85.333c47.36 0 85.333 37.973 85.333 85.333v128c0 47.36-37.973 85.333-85.333 85.333zM853.333 597.334h-85.333v128h85.333v-128zM85.333 42.667h768v85.333h-768v-85.333z" />
-<glyph unicode="&#xe87c;" d="M725.333 725.334c35.413 0 64 28.587 64 64 0 42.667-64 115.2-64 115.2s-64-72.533-64-115.2c0-35.413 28.587-64 64-64zM512 725.334c35.413 0 64 28.587 64 64 0 42.667-64 115.2-64 115.2s-64-72.533-64-115.2c0-35.413 28.587-64 64-64zM298.667 725.334c35.413 0 64 28.587 64 64 0 42.667-64 115.2-64 115.2s-64-72.533-64-115.2c0-35.413 28.587-64 64-64zM807.253 596.907c-8.533 25.173-32.427 43.093-60.587 43.093h-469.333c-28.16 0-51.627-17.92-60.587-43.093l-88.747-255.573v-341.333c0-23.467 19.2-42.667 42.667-42.667h42.667c23.467 0 42.667 19.2 42.667 42.667v42.667h512v-42.667c0-23.467 19.2-42.667 42.667-42.667h42.667c23.467 0 42.667 19.2 42.667 42.667v341.333l-88.747 255.573zM277.333 170.667c-35.413 0-64 28.587-64 64s28.587 64 64 64 64-28.587 64-64-28.587-64-64-64zM746.667 170.667c-35.413 0-64 28.587-64 64s28.587 64 64 64 64-28.587 64-64-28.587-64-64-64zM213.333 384l64 192h469.333l64-192h-597.333z" />
-<glyph unicode="&#xe87d;" d="M810.667 640v128h-597.333v-128h-128v-554.667h341.333v170.667h170.667v-170.667h341.333v554.667h-128zM469.333 512h-85.333v-42.667h85.333v-42.667h-128v128h85.333v42.667h-85.333v42.667h128v-128zM682.667 426.667h-42.667v85.333h-85.333v128h42.667v-85.333h42.667v85.333h42.667v-213.333z" />
-<glyph unicode="&#xe87e;" d="M128 853.334l85.76-777.813c5.12-42.667 40.96-75.52 84.907-75.52h426.667c43.947 0 79.787 32.853 84.907 75.52l85.76 777.813h-768zM512 128c-70.827 0-128 57.173-128 128 0 85.333 128 230.4 128 230.4s128-145.067 128-230.4c0-70.827-57.173-128-128-128zM782.080 597.334h-540.16l-18.773 170.667h577.28l-18.347-170.667z" />
-<glyph unicode="&#xe87f;" d="M512-0c212.053 0 384 171.947 384 384-212.053 0-384-171.947-384-384zM238.933 501.334c0-58.88 47.787-106.667 106.667-106.667 22.613 0 43.093 6.827 60.587 18.773l-0.853-8.107c0-58.88 47.787-106.667 106.667-106.667s106.667 47.787 106.667 106.667l-0.853 8.107c17.067-11.947 37.973-18.773 60.587-18.773 58.88 0 106.667 47.787 106.667 106.667 0 42.667-25.173 78.933-61.013 96 35.84 17.067 61.013 53.333 61.013 96 0 58.88-47.787 106.667-106.667 106.667-22.613 0-43.093-6.827-60.587-18.773l0.853 8.107c0 58.88-47.787 106.667-106.667 106.667s-106.667-47.787-106.667-106.667l0.853-8.107c-17.067 11.947-37.973 18.773-60.587 18.773-58.88 0-106.667-47.787-106.667-106.667 0-42.667 25.173-78.933 61.013-96-35.84-17.067-61.013-53.333-61.013-96zM512 704c58.88 0 106.667-47.787 106.667-106.667s-47.787-106.667-106.667-106.667-106.667 47.787-106.667 106.667 47.787 106.667 106.667 106.667zM128 384c0-212.053 171.947-384 384-384 0 212.053-171.947 384-384 384z" />
-<glyph unicode="&#xe880;" d="M843.52 630.187l0.427 0.427-158.72 158.72-45.227-45.227 90.027-90.027c-40.107-15.36-68.693-53.76-68.693-99.413 0-58.88 47.787-106.667 106.667-106.667 15.36 0 29.44 3.413 42.667 8.96v-307.627c0-23.467-19.2-42.667-42.667-42.667s-42.667 19.2-42.667 42.667v192c0 46.933-38.4 85.333-85.333 85.333h-42.667v298.667c0 46.933-38.4 85.333-85.333 85.333h-256c-46.933 0-85.333-38.4-85.333-85.333v-682.667h426.667v320h64v-213.333c0-58.88 47.787-106.667 106.667-106.667s106.667 47.787 106.667 106.667v405.333c0 29.44-11.947 56.32-31.147 75.52zM512 512h-256v213.333h256v-213.333zM768 512c-23.467 0-42.667 19.2-42.667 42.667s19.2 42.667 42.667 42.667 42.667-19.2 42.667-42.667-19.2-42.667-42.667-42.667z" />
-<glyph unicode="&#xe881;" d="M298.667 170.667c-46.933 0-84.907-38.4-84.907-85.333s37.973-85.333 84.907-85.333 85.333 38.4 85.333 85.333-38.4 85.333-85.333 85.333zM42.667 853.334v-85.333h85.333l153.6-323.84-57.6-104.533c-6.827-11.947-10.667-26.027-10.667-40.96 0-46.933 38.4-85.333 85.333-85.333h512v85.333h-494.080c-5.973 0-10.667 4.693-10.667 10.667l1.28 5.12 38.4 69.547h317.867c32 0 60.16 17.493 74.667 43.947l152.747 276.907c3.413 5.973 5.12 13.227 5.12 20.48 0 23.467-19.2 42.667-42.667 42.667h-631.040l-40.107 85.333h-139.52zM725.333 170.667c-46.933 0-84.907-38.4-84.907-85.333s37.973-85.333 84.907-85.333 85.333 38.4 85.333 85.333-38.4 85.333-85.333 85.333z" />
-<glyph unicode="&#xe882;" d="M810.667 810.667h-597.333c-46.933 0-84.907-38.4-84.907-85.333l-0.427-597.333c0-46.933 38.4-85.333 85.333-85.333h597.333c46.933 0 85.333 38.4 85.333 85.333v597.333c0 46.933-38.4 85.333-85.333 85.333zM768 341.334h-170.667v-170.667h-170.667v170.667h-170.667v170.667h170.667v170.667h170.667v-170.667h170.667v-170.667z" />
-<glyph unicode="&#xe883;" d="M298.667 384c70.827 0 128 57.173 128 128s-57.173 128-128 128-128-57.173-128-128 57.173-128 128-128zM810.667 640h-341.333v-298.667h-341.333v384h-85.333v-640h85.333v128h768v-128h85.333v384c0 94.293-76.373 170.667-170.667 170.667z" />
-<glyph unicode="&#xe884;" d="M391.253 220.587c66.56-66.56 174.933-66.56 241.493 0s66.56 174.933 0 241.493l-241.493-241.493zM768 852.907l-512 0.427c-47.36 0-85.333-37.973-85.333-85.333v-682.667c0-47.36 37.973-85.333 85.333-85.333h512c47.36 0 85.333 37.973 85.333 85.333v682.667c0 47.36-37.973 84.907-85.333 84.907zM426.667 768c23.467 0 42.667-19.2 42.667-42.667s-19.2-42.667-42.667-42.667-42.667 19.2-42.667 42.667 19.2 42.667 42.667 42.667zM298.667 768c23.467 0 42.667-19.2 42.667-42.667s-19.2-42.667-42.667-42.667-42.667 19.2-42.667 42.667 19.2 42.667 42.667 42.667zM512 85.334c-141.227 0-256 114.773-256 256s114.773 256 256 256 256-114.773 256-256-114.773-256-256-256z" />
-<glyph unicode="&#xe885;" d="M512 445.867c-100.693 93.867-235.52 151.467-384 151.467v-469.333c148.48 0 283.307-57.6 384-151.467 100.693 93.44 235.52 151.467 384 151.467v469.333c-148.48 0-283.307-57.6-384-151.467zM512 597.334c70.827 0 128 57.173 128 128s-57.173 128-128 128-128-57.173-128-128 57.173-128 128-128z" />
-<glyph unicode="&#xe886;" d="M810.667 682.667h-85.333c0 117.76-95.573 213.333-213.333 213.333s-213.333-95.573-213.333-213.333h-85.333c-46.933 0-84.907-38.4-84.907-85.333l-0.427-512c0-46.933 38.4-85.333 85.333-85.333h597.333c46.933 0 85.333 38.4 85.333 85.333v512c0 46.933-38.4 85.333-85.333 85.333zM512 810.667c70.827 0 128-57.173 128-128h-256c0 70.827 57.173 128 128 128zM512 384c-117.76 0-213.333 95.573-213.333 213.333h85.333c0-70.827 57.173-128 128-128s128 57.173 128 128h85.333c0-117.76-95.573-213.333-213.333-213.333z" />
-<glyph unicode="&#xe887;" d="M768 810.667v-85.333h-85.333v85.333h-341.333v-85.333h-85.333v85.333h-85.333v-768h85.333v85.333h85.333v-85.333h341.333v85.333h85.333v-85.333h85.333v768h-85.333zM341.333 213.334h-85.333v85.333h85.333v-85.333zM341.333 384h-85.333v85.333h85.333v-85.333zM341.333 554.667h-85.333v85.333h85.333v-85.333zM768 213.334h-85.333v85.333h85.333v-85.333zM768 384h-85.333v85.333h85.333v-85.333zM768 554.667h-85.333v85.333h85.333v-85.333z" />
-<glyph unicode="&#xe888;" d="M913.493 444.587l-384 384c-15.36 15.36-36.693 24.747-60.16 24.747h-298.667c-46.933 0-85.333-38.4-85.333-85.333v-298.667c0-23.467 9.387-44.8 25.173-60.587l384-384c15.36-15.36 36.693-24.747 60.16-24.747s44.8 9.387 60.16 25.173l298.667 298.667c15.787 15.36 25.173 36.693 25.173 60.16s-9.813 45.227-25.173 60.587zM234.667 640c-35.413 0-64 28.587-64 64s28.587 64 64 64 64-28.587 64-64-28.587-64-64-64z" />
-<glyph unicode="&#xe889;" d="M554.667 810.667h-298.667v-768h170.667v256h128c141.227 0 256 114.773 256 256s-114.773 256-256 256zM563.2 469.334h-136.533v170.667h136.533c46.933 0 85.333-38.4 85.333-85.333s-38.4-85.333-85.333-85.333z" />
-<glyph unicode="&#xe88a;" d="M896 725.334h-112.64l48.64 133.973-100.267 36.693-62.293-170.667h-541.44v-85.333l85.333-256-85.333-256v-85.333h768v85.333l-85.333 256 85.333 256v85.333zM682.667 341.334h-128v-128h-85.333v128h-128v85.333h128v128h85.333v-128h128v-85.333z" />
-<glyph unicode="&#xe88b;" d="M282.453 478.294c61.44-120.747 160.427-219.307 281.173-281.173l93.867 93.867c11.52 11.52 28.587 15.36 43.52 10.24 47.787-15.787 99.413-24.32 152.32-24.32 23.467 0 42.667-19.2 42.667-42.667v-148.907c0-23.467-19.2-42.667-42.667-42.667-400.64 0-725.333 324.693-725.333 725.333 0 23.467 19.2 42.667 42.667 42.667h149.333c23.467 0 42.667-19.2 42.667-42.667 0-53.333 8.533-104.533 24.32-152.32 4.693-14.933 1.28-31.573-10.667-43.52l-93.867-93.867z" />
-<glyph unicode="&#xe88c;" d="M512 853.334c-152.32 0-288.853-65.707-383.573-170.667l383.573-682.667 383.573 682.667c-94.293 104.533-231.253 170.667-383.573 170.667zM298.667 640c0 46.933 38.4 85.333 85.333 85.333s85.333-38.4 85.333-85.333-38.4-85.333-85.333-85.333-85.333 38.4-85.333 85.333zM512 298.667c-46.933 0-85.333 38.4-85.333 85.333s38.4 85.333 85.333 85.333 85.333-38.4 85.333-85.333-38.4-85.333-85.333-85.333z" />
-<glyph unicode="&#xe88d;" d="M853.333 426.667c0 46.933 38.4 85.333 85.333 85.333v170.667c0 46.933-38.4 85.333-85.333 85.333h-682.667c-46.933 0-84.907-38.4-84.907-85.333v-170.667c46.933 0 84.907-38.4 84.907-85.333s-37.973-85.333-85.333-85.333v-170.667c0-46.933 38.4-85.333 85.333-85.333h682.667c46.933 0 85.333 38.4 85.333 85.333v170.667c-46.933 0-85.333 38.4-85.333 85.333zM664.747 221.867l-152.747 98.133-152.747-98.133 46.080 175.787-140.373 114.773 180.907 10.667 66.133 168.107 65.707-168.533 180.907-10.667-140.373-114.773 46.507-175.36z" />
-<glyph unicode="&#xe88e;" d="M853.333 768h-682.667c-46.933 0-84.907-38.4-84.907-85.333l-0.427-512c0-46.933 38.4-85.333 85.333-85.333h682.667c46.933 0 85.333 38.4 85.333 85.333v512c0 46.933-38.4 85.333-85.333 85.333zM853.333 597.334l-341.333-213.333-341.333 213.333v85.333l341.333-213.333 341.333 213.333v-85.333z" />
-<glyph unicode="&#xe88f;" d="M810.667 597.334h-597.333c-70.827 0-128-57.173-128-128v-256h170.667v-170.667h512v170.667h170.667v256c0 70.827-57.173 128-128 128zM682.667 128h-341.333v213.333h341.333v-213.333zM810.667 426.667c-23.467 0-42.667 19.2-42.667 42.667s19.2 42.667 42.667 42.667 42.667-19.2 42.667-42.667-19.2-42.667-42.667-42.667zM768 810.667h-512v-170.667h512v170.667z" />
-<glyph unicode="&#xe890;" d="M345.6 369.494l120.747 120.747-299.52 299.093c-66.56-66.56-66.56-174.507 0-241.493l178.773-178.347zM634.88 446.72c65.28-30.293 157.013-8.96 224.853 58.88 81.493 81.493 97.28 198.4 34.56 261.12-62.293 62.293-179.2 46.933-261.12-34.56-67.84-67.84-89.173-159.573-58.88-224.853l-416.427-416.427 60.16-60.16 293.973 293.12 293.547-293.547 60.16 60.16-293.547 293.547 62.72 62.72z" />
-<glyph unicode="&#xe891;" d="M648.533 426.667c0-75.405-61.128-136.533-136.533-136.533s-136.533 61.128-136.533 136.533c0 75.405 61.128 136.533 136.533 136.533s136.533-61.128 136.533-136.533zM384 853.334l-78.080-85.333h-135.253c-46.933 0-85.333-38.4-85.333-85.333v-512c0-46.933 38.4-85.333 85.333-85.333h682.667c46.933 0 85.333 38.4 85.333 85.333v512c0 46.933-38.4 85.333-85.333 85.333h-135.253l-78.080 85.333h-256zM512 213.334c-117.76 0-213.333 95.573-213.333 213.333s95.573 213.333 213.333 213.333 213.333-95.573 213.333-213.333-95.573-213.333-213.333-213.333z" />
-<glyph unicode="&#xe892;" d="M853.333 597.334h-128v170.667h-597.333c-46.933 0-85.333-38.4-85.333-85.333v-469.333h85.333c0-70.827 57.173-128 128-128s128 57.173 128 128h256c0-70.827 57.173-128 128-128s128 57.173 128 128h85.333v213.333l-128 170.667zM256 149.334c-35.413 0-64 28.587-64 64s28.587 64 64 64 64-28.587 64-64-28.587-64-64-64zM832 533.334l83.627-106.667h-190.293v106.667h106.667zM768 149.334c-35.413 0-64 28.587-64 64s28.587 64 64 64 64-28.587 64-64-28.587-64-64-64z" />
-<glyph unicode="&#xe893;" d="M807.253 682.24c-8.533 25.173-32.427 43.093-60.587 43.093h-106.667v85.333h-256v-85.333h-106.667c-28.16 0-51.627-17.92-60.587-43.093l-88.747-255.573v-341.333c0-23.467 19.2-42.667 42.667-42.667h42.667c23.467 0 42.667 19.2 42.667 42.667v42.667h512v-42.667c0-23.467 19.2-42.667 42.667-42.667h42.667c23.467 0 42.667 19.2 42.667 42.667v341.333l-88.747 255.573zM277.333 256c-35.413 0-64 28.587-64 64s28.587 64 64 64 64-28.587 64-64-28.587-64-64-64zM746.667 256c-35.413 0-64 28.587-64 64s28.587 64 64 64 64-28.587 64-64-28.587-64-64-64zM213.333 469.334l64 192h469.333l64-192h-597.333z" />
-<glyph unicode="&#xe894;" d="M810.667 853.334h-597.333c-47.36 0-85.333-38.4-85.333-85.333v-597.333c0-46.933 37.973-85.333 85.333-85.333h170.667l128-128 128 128h170.667c46.933 0 85.333 38.4 85.333 85.333v597.333c0 46.933-38.4 85.333-85.333 85.333zM512 712.534c63.573 0 115.2-51.627 115.2-115.2s-51.627-115.2-115.2-115.2c-63.573 0-115.2 51.627-115.2 115.2s51.627 115.2 115.2 115.2zM768 256h-512v38.4c0 85.333 170.667 132.267 256 132.267s256-46.933 256-132.267v-38.4z" />
-<glyph unicode="&#xe895;" d="M874.667 810.667l-6.827-1.28-227.84-88.32-256 89.6-240.64-81.067c-8.96-2.987-15.36-10.667-15.36-20.48v-645.12c0-11.947 9.387-21.333 21.333-21.333l6.827 1.28 227.84 88.32 256-89.6 240.64 81.067c8.96 2.987 15.36 10.667 15.36 20.48v645.12c0 11.947-9.387 21.333-21.333 21.333zM640 128l-256 90.027v507.307l256-90.027v-507.307z" />
-<glyph unicode="&#xe896;" d="M512 597.334c-94.293 0-170.667-76.373-170.667-170.667s76.373-170.667 170.667-170.667 170.667 76.373 170.667 170.667-76.373 170.667-170.667 170.667zM893.44 469.334c-19.627 177.92-160.853 319.147-338.773 338.773v87.893h-85.333v-87.893c-177.92-19.627-319.147-160.853-338.773-338.773h-87.893v-85.333h87.893c19.627-177.92 160.853-319.147 338.773-338.773v-87.893h85.333v87.893c177.92 19.627 319.147 160.853 338.773 338.773h87.893v85.333h-87.893zM512 128c-165.12 0-298.667 133.547-298.667 298.667s133.547 298.667 298.667 298.667 298.667-133.547 298.667-298.667-133.547-298.667-298.667-298.667z" />
-<glyph unicode="&#xe897;" d="M512 853.334l-320-780.373 30.293-30.293 289.707 128 289.707-128 30.293 30.293z" />
-<glyph unicode="&#xe898;" d="M768 597.334c0 141.227-114.773 256-256 256s-256-114.773-256-256c0-192 256-469.333 256-469.333s256 277.333 256 469.333zM426.667 597.334c0 46.933 38.4 85.333 85.333 85.333s85.333-38.4 85.333-85.333-37.973-85.333-85.333-85.333c-46.933 0-85.333 38.4-85.333 85.333zM213.333 85.334v-85.333h597.333v85.333h-597.333z" />
-<glyph unicode="&#xe899;" d="M512 853.334c-165.12 0-298.667-133.547-298.667-298.667 0-224 298.667-554.667 298.667-554.667s298.667 330.667 298.667 554.667c0 165.12-133.547 298.667-298.667 298.667zM512 448c-58.88 0-106.667 47.787-106.667 106.667s47.787 106.667 106.667 106.667 106.667-47.787 106.667-106.667-47.787-106.667-106.667-106.667z" />
-<glyph unicode="&#xe89a;" d="M853.333 853.334h-682.667c-46.933 0-84.907-38.4-84.907-85.333l-0.427-768 170.667 170.667h597.333c46.933 0 85.333 38.4 85.333 85.333v512c0 46.933-38.4 85.333-85.333 85.333zM256 341.334v105.387l293.547 293.547c8.533 8.533 21.76 8.533 30.293 0l75.52-75.52c8.533-8.533 8.533-21.76 0-30.293l-293.973-293.12h-105.387zM768 341.334h-320l85.333 85.333h234.667v-85.333z" />
-<glyph unicode="&#xe89b;" d="M345.6 369.494l120.747 120.747-299.52 299.093c-66.56-66.56-66.56-174.507 0-241.493l178.773-178.347zM634.88 446.72c65.28-30.293 157.013-8.96 224.853 58.88 81.493 81.493 97.28 198.4 34.56 261.12-62.293 62.293-179.2 46.933-261.12-34.56-67.84-67.84-89.173-159.573-58.88-224.853l-416.427-416.427 60.16-60.16 293.973 293.12 293.547-293.547 60.16 60.16-293.547 293.547 62.72 62.72z" />
-<glyph unicode="&#xe89c;" d="M810.667 810.667h-597.333c-46.933 0-85.333-38.4-85.333-85.333v-597.333c0-46.933 38.4-85.333 85.333-85.333h597.333c46.933 0 85.333 38.4 85.333 85.333v597.333c0 46.933-38.4 85.333-85.333 85.333zM213.333 725.76h128c0-70.827-57.173-128.427-128-128.427v128.427zM213.333 426.667v85.333c117.76 0 213.333 96 213.333 213.76h85.333c0-165.12-133.547-299.093-298.667-299.093zM213.333 170.667l149.333 192 106.667-128.427 149.333 192.427 192-256h-597.333z" />
-<glyph unicode="&#xe89d;" d="M853.333 768h-682.667v-85.333h682.667v85.333zM896 341.334v85.333l-42.667 213.333h-682.667l-42.667-213.333v-85.333h42.667v-256h426.667v256h170.667v-256h85.333v256h42.667zM512 170.667h-256v170.667h256v-170.667z" />
-<glyph unicode="&#xe89e;" d="M597.333 682.667l-160-213.333 121.6-162.133-68.267-51.2c-72.107 96-192 256-192 256l-256-341.333h938.667l-384 512z" />
-<glyph unicode="&#xe89f;" d="M853.333 512h-128v48.64c73.387 19.2 128 85.333 128 164.693h-128v42.667c0 23.467-19.2 42.667-42.667 42.667h-341.333c-23.467 0-42.667-19.2-42.667-42.667v-42.667h-128c0-79.36 54.613-145.493 128-164.693v-48.64h-128c0-79.36 54.613-145.493 128-164.693v-48.64h-128c0-79.36 54.613-145.493 128-164.693v-48.64c0-23.467 19.2-42.667 42.667-42.667h341.333c23.467 0 42.667 19.2 42.667 42.667v48.64c73.387 19.2 128 85.333 128 164.693h-128v48.64c73.387 19.2 128 85.333 128 164.693zM512 128c-47.36 0-85.333 38.4-85.333 85.333s37.973 85.333 85.333 85.333c46.933 0 85.333-38.4 85.333-85.333s-37.973-85.333-85.333-85.333zM512 341.334c-47.36 0-85.333 38.4-85.333 85.333s37.973 85.333 85.333 85.333c46.933 0 85.333-38.4 85.333-85.333s-37.973-85.333-85.333-85.333zM512 554.667c-47.36 0-85.333 38.4-85.333 85.333 0 47.36 37.973 85.333 85.333 85.333 46.933 0 85.333-37.973 85.333-85.333 0-46.933-37.973-85.333-85.333-85.333z" />
-<glyph unicode="&#xe8a0;" d="M170.667 597.334h170.667v170.667h-170.667v-170.667zM426.667 85.334h170.667v170.667h-170.667v-170.667zM170.667 85.334h170.667v170.667h-170.667v-170.667zM170.667 341.334h170.667v170.667h-170.667v-170.667zM426.667 341.334h170.667v170.667h-170.667v-170.667zM682.667 768v-170.667h170.667v170.667h-170.667zM426.667 597.334h170.667v170.667h-170.667v-170.667zM682.667 341.334h170.667v170.667h-170.667v-170.667zM682.667 85.334h170.667v170.667h-170.667v-170.667z" />
-<glyph unicode="&#xe8a1;" d="M853.333 469.334h-519.253l238.507 238.507-60.587 60.16-341.333-341.333 341.333-341.333 60.16 60.16-238.080 238.507h519.253v85.333z" />
-<glyph unicode="&#xe8a2;" d="M512 853.334c-235.52 0-426.667-191.147-426.667-426.667s191.147-426.667 426.667-426.667 426.667 191.147 426.667 426.667-191.147 426.667-426.667 426.667zM512 341.334l-170.667 170.667h341.333l-170.667-170.667z" />
-<glyph unicode="&#xe8a3;" d="M298.667 512l213.333-213.333 213.333 213.333z" />
-<glyph unicode="&#xe8a4;" d="M298.667 341.334l213.333 213.333 213.333-213.333z" />
-<glyph unicode="&#xe8a5;" d="M512 768l-60.16-60.16 238.080-238.507h-519.253v-85.333h519.253l-238.080-238.507 60.16-60.16 341.333 341.333z" />
-<glyph unicode="&#xe8a6;" d="M512 853.334c-235.947 0-426.667-190.72-426.667-426.667s190.72-426.667 426.667-426.667 426.667 190.72 426.667 426.667-190.72 426.667-426.667 426.667zM725.333 273.494l-60.16-60.16-153.173 153.173-153.173-153.173-60.16 60.16 153.173 153.173-153.173 153.173 60.16 60.16 153.173-153.173 153.173 153.173 60.16-60.16-153.173-153.173 153.173-153.173z" />
-<glyph unicode="&#xe8a7;" d="M384 248.747l-177.92 177.92-60.587-60.16 238.507-238.507 512 512-60.16 60.16z" />
-<glyph unicode="&#xe8a8;" d="M657.493 622.507l-60.16 60.16-256-256 256-256 60.16 60.16-195.413 195.84z" />
-<glyph unicode="&#xe8a9;" d="M426.667 682.667l-60.16-60.16 195.413-195.84-195.413-195.84 60.16-60.16 256 256z" />
-<glyph unicode="&#xe8aa;" d="M810.667 665.174l-60.16 60.16-238.507-238.507-238.507 238.507-60.16-60.16 238.507-238.507-238.507-238.507 60.16-60.16 238.507 238.507 238.507-238.507 60.16 60.16-238.507 238.507z" />
-<glyph unicode="&#xe8ab;" d="M512 597.334l-256-256 60.16-60.16 195.84 195.413 195.84-195.413 60.16 60.16z" />
-<glyph unicode="&#xe8ac;" d="M707.84 572.16l-195.84-195.413-195.84 195.413-60.16-60.16 256-256 256 256z" />
-<glyph unicode="&#xe8ad;" d="M213.333 256h128v-128h85.333v213.333h-213.333v-85.333zM341.333 597.334h-128v-85.333h213.333v213.333h-85.333v-128zM597.333 128h85.333v128h128v85.333h-213.333v-213.333zM682.667 597.334v128h-85.333v-213.333h213.333v85.333h-128z" />
-<glyph unicode="&#xe8ae;" d="M298.667 341.334h-85.333v-213.333h213.333v85.333h-128v128zM213.333 512h85.333v128h128v85.333h-213.333v-213.333zM725.333 213.334h-128v-85.333h213.333v213.333h-85.333v-128zM597.333 725.334v-85.333h128v-128h85.333v213.333h-213.333z" />
-<glyph unicode="&#xe8af;" d="M128 170.667h768v85.333h-768v-85.333zM128 384h768v85.333h-768v-85.333zM128 682.667v-85.333h768v85.333h-768z" />
-<glyph unicode="&#xe8b0;" d="M256 512c-46.933 0-85.333-38.4-85.333-85.333s38.4-85.333 85.333-85.333 85.333 38.4 85.333 85.333-38.4 85.333-85.333 85.333zM768 512c-46.933 0-85.333-38.4-85.333-85.333s38.4-85.333 85.333-85.333 85.333 38.4 85.333 85.333-38.4 85.333-85.333 85.333zM512 512c-46.933 0-85.333-38.4-85.333-85.333s38.4-85.333 85.333-85.333 85.333 38.4 85.333 85.333-38.4 85.333-85.333 85.333z" />
-<glyph unicode="&#xe8b1;" d="M512 597.334c46.933 0 85.333 38.4 85.333 85.333s-38.4 85.333-85.333 85.333-85.333-38.4-85.333-85.333 38.4-85.333 85.333-85.333zM512 512c-46.933 0-85.333-38.4-85.333-85.333s38.4-85.333 85.333-85.333 85.333 38.4 85.333 85.333-38.4 85.333-85.333 85.333zM512 256c-46.933 0-85.333-38.4-85.333-85.333s38.4-85.333 85.333-85.333 85.333 38.4 85.333 85.333-38.4 85.333-85.333 85.333z" />
-<glyph unicode="&#xe8b2;" d="M753.067 667.734c-61.867 61.867-146.773 100.267-241.067 100.267-188.587 0-340.907-152.747-340.907-341.333s152.32-341.333 340.907-341.333c159.147 0 291.84 108.8 329.813 256h-88.747c-34.987-99.413-129.707-170.667-241.067-170.667-141.227 0-256 114.773-256 256s114.773 256 256 256c70.827 0 133.973-29.44 180.053-75.947l-137.387-137.387h298.667v298.667l-100.267-100.267z" />
-<glyph unicode="&#xe8b3;" d="M316.16 145.494l60.587-60.16 135.253 135.253 135.253-135.253 60.16 60.16-195.413 195.84-195.84-195.84zM707.84 707.84l-60.587 60.16-135.253-135.253-135.253 135.253-60.587-60.16 195.84-195.84 195.84 195.84z" />
-<glyph unicode="&#xe8b4;" d="M512 689.92l135.253-135.253 60.16 60.16-195.413 195.84-195.84-195.84 60.587-60.16 135.253 135.253zM512 163.414l-135.253 135.253-60.16-60.16 195.413-195.84 195.84 195.84-60.587 60.16-135.253-135.253z" />
-<glyph unicode="&#xe8b5;" d="M213.333 256c0-165.12 133.547-298.667 298.667-298.667s298.667 133.547 298.667 298.667v170.667h-597.333v-170.667zM687.787 752.214l89.6 89.6-34.987 35.413-98.133-98.56c-40.107 20.053-84.48 32-132.267 32s-92.16-11.947-131.84-32l-98.56 98.56-34.987-35.413 89.6-89.6c-74.24-54.187-122.88-141.227-122.88-240.213v-42.667h597.333v42.667c0 98.987-48.64 186.027-122.88 240.213zM384 554.667c-23.467 0-42.667 19.2-42.667 42.667s19.2 42.667 42.667 42.667 42.667-19.2 42.667-42.667-19.2-42.667-42.667-42.667zM640 554.667c-23.467 0-42.667 19.2-42.667 42.667s19.2 42.667 42.667 42.667 42.667-19.2 42.667-42.667-19.2-42.667-42.667-42.667z" />
-<glyph unicode="&#xe8b6;" d="M607.573 426.24l98.987-98.987c11.947 30.72 18.773 64.427 18.773 99.413s-6.827 67.84-18.347 98.56l-99.413-98.987zM833.28 652.374l-53.76-53.76c26.88-51.627 41.813-109.653 41.813-171.52s-15.36-120.32-41.813-171.52l51.2-51.2c41.387 65.707 65.707 143.36 65.707 226.56-0.427 80.64-23.467 156.587-63.147 221.44zM670.293 609.707l-243.627 243.627h-42.667v-323.84l-195.84 195.84-60.16-60.16 238.507-238.507-238.507-238.507 60.16-60.16 195.84 195.84v-323.84h42.667l243.627 243.627-183.467 183.040 183.467 183.040zM469.333 689.92l80.213-80.213-80.213-80.213v160.427zM549.547 243.627l-80.213-80.213v160.427l80.213-80.213z" />
-<glyph unicode="&#xe8b7;" d="M853.333 256h85.333v85.333h-85.333v-85.333zM853.333 640v-213.333h85.333v213.333h-85.333zM426.667 768c-188.587 0-341.333-152.747-341.333-341.333s152.747-341.333 341.333-341.333 341.333 152.747 341.333 341.333-152.747 341.333-341.333 341.333zM426.667 341.334c-46.933 0-85.333 38.4-85.333 85.333s38.4 85.333 85.333 85.333 85.333-38.4 85.333-85.333-38.4-85.333-85.333-85.333z" />
-<glyph unicode="&#xe8b8;" d="M512 853.334c-234.667 0-426.667-192-426.667-426.667s192-426.667 426.667-426.667 426.667 192 426.667 426.667-192 426.667-426.667 426.667zM170.667 426.667c0 187.733 153.6 341.333 341.333 341.333 76.8 0 149.333-25.6 209.067-72.533l-477.867-477.867c-46.933 59.733-72.533 132.267-72.533 209.067zM512 85.334c-76.8 0-149.333 25.6-209.067 72.533l477.867 477.867c46.933-59.733 72.533-132.267 72.533-209.067 0-187.733-153.6-341.333-341.333-341.333z" />
-<glyph unicode="&#xe8b9;" d="M512 853.334c-235.52 0-426.667-191.147-426.667-426.667s191.147-426.667 426.667-426.667 426.667 191.147 426.667 426.667-191.147 426.667-426.667 426.667zM512 85.334c-188.587 0-341.333 152.747-341.333 341.333 0 78.933 26.88 151.467 72.107 209.067l478.293-478.293c-57.6-45.227-130.133-72.107-209.067-72.107zM781.227 217.6l-478.293 478.293c57.6 45.227 130.133 72.107 209.067 72.107 188.587 0 341.333-152.747 341.333-341.333 0-78.933-26.88-151.467-72.107-209.067z" />
-<glyph unicode="&#xe8ba;" d="M807.253 724.907c-8.533 25.173-32.427 43.093-60.587 43.093h-469.333c-28.16 0-51.627-17.92-60.587-43.093l-88.747-255.573v-341.333c0-23.467 19.2-42.667 42.667-42.667h42.667c23.467 0 42.667 19.2 42.667 42.667v42.667h512v-42.667c0-23.467 19.2-42.667 42.667-42.667h42.667c23.467 0 42.667 19.2 42.667 42.667v341.333l-88.747 255.573zM277.333 298.667c-35.413 0-64 28.587-64 64s28.587 64 64 64 64-28.587 64-64-28.587-64-64-64zM746.667 298.667c-35.413 0-64 28.587-64 64s28.587 64 64 64 64-28.587 64-64-28.587-64-64-64zM213.333 512l64 192h469.333l64-192h-597.333z" />
-<glyph unicode="&#xe8bb;" d="M705.28 466.774l-45.227 45.227-208.213-208.213-90.453 90.453-45.227-45.227 135.68-135.68 253.44 253.44zM810.667 810.667h-42.667v85.333h-85.333v-85.333h-341.333v85.333h-85.333v-85.333h-42.667c-47.36 0-84.907-38.4-84.907-85.333l-0.427-597.333c0-46.933 37.973-85.333 85.333-85.333h597.333c46.933 0 85.333 38.4 85.333 85.333v597.333c0 46.933-38.4 85.333-85.333 85.333zM810.667 128h-597.333v469.333h597.333v-469.333z" />
-<glyph unicode="&#xe8bc;" d="M397.227 213.334l104.107 104.107 104.107-104.107 45.227 45.227-104.107 104.107 104.107 104.107-45.227 45.227-104.107-104.107-104.107 104.107-45.227-45.227 104.107-104.107-104.107-104.107 45.227-45.227zM810.667 810.667h-42.667v85.333h-85.333v-85.333h-341.333v85.333h-85.333v-85.333h-42.667c-47.36 0-84.907-38.4-84.907-85.333l-0.427-597.333c0-46.933 37.973-85.333 85.333-85.333h597.333c46.933 0 85.333 38.4 85.333 85.333v597.333c0 46.933-38.4 85.333-85.333 85.333zM810.667 128h-597.333v469.333h597.333v-469.333z" />
-<glyph unicode="&#xe8bd;" d="M725.333 512h-426.667v-85.333h426.667v85.333zM810.667 810.667h-42.667v85.333h-85.333v-85.333h-341.333v85.333h-85.333v-85.333h-42.667c-47.36 0-84.907-38.4-84.907-85.333l-0.427-597.333c0-46.933 37.973-85.333 85.333-85.333h597.333c46.933 0 85.333 38.4 85.333 85.333v597.333c0 46.933-38.4 85.333-85.333 85.333zM810.667 128h-597.333v469.333h597.333v-469.333zM597.333 341.334h-298.667v-85.333h298.667v85.333z" />
-<glyph unicode="&#xe8be;" d="M853.333 682.667h-341.333l-85.333 85.333h-256c-46.933 0-85.333-38.4-85.333-85.333v-512c0-46.933 38.4-85.333 85.333-85.333h682.667c46.933 0 85.333 38.4 85.333 85.333v426.667c0 46.933-38.4 85.333-85.333 85.333zM579.413 170.667l-152.747 89.6-152.747-89.6 40.533 173.653-134.827 116.907 177.493 15.36 69.547 163.413 69.547-163.84 177.493-15.36-134.827-116.907 40.533-173.227z" />
-<glyph unicode="&#xe8bf;" d="M853.333 853.334h-682.667c-46.933 0-84.907-38.4-84.907-85.333l-0.427-768 170.667 170.667h597.333c46.933 0 85.333 38.4 85.333 85.333v512c0 46.933-38.4 85.333-85.333 85.333zM213.333 341.334l149.333 192 106.667-128.427 149.333 192.427 192-256h-597.333z" />
-<glyph unicode="&#xe8c0;" d="M938.667 810.667h-640c-29.44 0-52.48-14.933-67.84-37.547l-230.827-346.453 230.827-346.027c15.36-22.613 41.387-37.973 70.827-37.973h637.013c46.933 0 85.333 38.4 85.333 85.333v597.333c0 46.933-38.4 85.333-85.333 85.333zM384 362.667c-35.413 0-64 28.587-64 64s28.587 64 64 64 64-28.587 64-64-28.587-64-64-64zM597.333 362.667c-35.413 0-64 28.587-64 64s28.587 64 64 64 64-28.587 64-64-28.587-64-64-64zM810.667 362.667c-35.413 0-64 28.587-64 64s28.587 64 64 64 64-28.587 64-64-28.587-64-64-64z" />
-<glyph unicode="&#xe8c1;" d="M832 512c7.253 0 14.080-1.28 21.333-2.133v386.133l-810.667-810.667h554.667v128c0 37.973 16.64 71.68 42.667 95.147v11.52c0 105.813 86.187 192 192 192zM938.667 256v64c0 58.88-47.787 106.667-106.667 106.667s-106.667-47.787-106.667-106.667v-64c-23.467 0-42.667-19.2-42.667-42.667v-170.667c0-23.467 19.2-42.667 42.667-42.667h213.333c23.467 0 42.667 19.2 42.667 42.667v170.667c0 23.467-19.2 42.667-42.667 42.667zM896 256h-128v64c0 35.413 28.587 64 64 64s64-28.587 64-64v-64z" />
-<glyph unicode="&#xe8c2;" d="M627.627 533.334l97.707 97.707v-161.707h21.333l121.6 121.6-91.307 91.733 91.733 91.733-122.027 121.6h-21.333v-161.707l-97.707 97.707-30.293-30.293 119.040-119.040-119.040-119.040 30.293-30.293zM768 814.507l40.107-40.107-40.107-40.107v80.213zM768 631.040l40.107-40.107-40.107-40.107v80.213zM853.333 277.334c-53.333 0-104.533 8.533-152.32 24.32-14.933 4.693-31.573 1.28-43.52-10.24l-93.867-93.867c-120.747 61.44-219.733 160-281.173 281.173l93.867 94.293c11.947 11.093 15.36 27.733 10.667 42.667-15.787 47.787-24.32 98.987-24.32 152.32 0 23.467-19.2 42.667-42.667 42.667h-149.333c-23.467 0-42.667-19.2-42.667-42.667 0-400.64 324.693-725.333 725.333-725.333 23.467 0 42.667 19.2 42.667 42.667v149.333c0 23.467-19.2 42.667-42.667 42.667z" />
-<glyph unicode="&#xe8c3;" d="M768 469.334l213.333 213.333-213.333 213.333v-128h-170.667v-170.667h170.667v-128zM853.333 277.334c-53.333 0-104.533 8.533-152.32 24.32-14.933 4.693-31.573 1.28-43.52-10.24l-93.867-93.867c-120.747 61.44-219.733 160-281.173 281.173l93.867 94.293c11.947 11.093 15.36 27.733 10.667 42.667-15.787 47.787-24.32 98.987-24.32 152.32 0 23.467-19.2 42.667-42.667 42.667h-149.333c-23.467 0-42.667-19.2-42.667-42.667 0-400.64 324.693-725.333 725.333-725.333 23.467 0 42.667 19.2 42.667 42.667v149.333c0 23.467-19.2 42.667-42.667 42.667z" />
-<glyph unicode="&#xe8c4;" d="M853.333 277.334c-53.333 0-104.533 8.533-152.32 24.32-14.933 4.693-31.573 1.28-43.52-10.24l-93.867-93.867c-120.747 61.44-219.733 160-281.173 281.173l93.867 94.293c11.947 11.093 15.36 27.733 10.667 42.667-15.787 47.787-24.32 98.987-24.32 152.32 0 23.467-19.2 42.667-42.667 42.667h-149.333c-23.467 0-42.667-19.2-42.667-42.667 0-400.64 324.693-725.333 725.333-725.333 23.467 0 42.667 19.2 42.667 42.667v149.333c0 23.467-19.2 42.667-42.667 42.667zM810.667 426.667h85.333c0 212.053-171.947 384-384 384v-85.333c165.12 0 298.667-133.547 298.667-298.667zM640 426.667h85.333c0 117.76-95.573 213.333-213.333 213.333v-85.333c70.827 0 128-57.173 128-128z" />
-<glyph unicode="&#xe8c5;" d="M853.333 277.334c-53.333 0-104.533 8.533-152.32 24.32-14.933 4.693-31.573 1.28-43.52-10.24l-93.867-93.867c-120.747 61.44-219.733 160-281.173 281.173l93.867 94.293c11.947 11.093 15.36 27.733 10.667 42.667-15.787 47.787-24.32 98.987-24.32 152.32 0 23.467-19.2 42.667-42.667 42.667h-149.333c-23.467 0-42.667-19.2-42.667-42.667 0-400.64 324.693-725.333 725.333-725.333 23.467 0 42.667 19.2 42.667 42.667v149.333c0 23.467-19.2 42.667-42.667 42.667zM853.333 768v21.333c0 58.88-47.787 106.667-106.667 106.667s-106.667-47.787-106.667-106.667v-21.333c-23.467 0-42.667-19.2-42.667-42.667v-170.667c0-23.467 19.2-42.667 42.667-42.667h213.333c23.467 0 42.667 19.2 42.667 42.667v170.667c0 23.467-19.2 42.667-42.667 42.667zM819.2 768h-145.067v21.333c0 40.107 32.427 72.533 72.533 72.533s72.533-32.427 72.533-72.533v-21.333z" />
-<glyph unicode="&#xe8c6;" d="M277.333 704l234.667-234.667 298.667 298.667-42.667 42.667-256-256-192 192h149.333v64h-256v-256h64v149.333zM1011.627 227.414c-130.133 123.307-305.92 199.253-499.627 199.253s-369.493-75.947-499.627-199.253c-7.68-7.68-12.373-18.347-12.373-30.293s4.693-22.613 12.373-30.293l105.813-105.813c7.68-7.68 18.347-12.373 30.293-12.373 11.52 0 22.187 4.693 29.867 11.947 33.707 31.573 72.107 58.027 113.493 78.933 14.080 6.827 23.893 21.333 23.893 38.4v132.267c61.867 20.48 128 31.147 196.267 31.147s134.4-10.667 196.267-30.72v-132.267c0-16.64 9.813-31.573 23.893-38.4 41.813-20.907 79.787-47.787 113.92-78.933 7.68-7.68 18.347-11.947 29.867-11.947 11.947 0 22.613 4.693 30.293 12.373l105.813 105.813c7.68 7.68 12.373 18.347 12.373 30.293s-5.12 22.187-12.8 29.867z" />
-<glyph unicode="&#xe8c7;" d="M725.333 810.667h-85.333v-298.667h85.333v298.667zM853.333 277.334c-53.333 0-104.533 8.533-152.32 24.32-14.933 4.693-31.573 1.28-43.52-10.24l-93.867-93.867c-120.747 61.44-219.733 160-281.173 281.173l93.867 94.293c11.947 11.093 15.36 27.733 10.667 42.667-15.787 47.787-24.32 98.987-24.32 152.32 0 23.467-19.2 42.667-42.667 42.667h-149.333c-23.467 0-42.667-19.2-42.667-42.667 0-400.64 324.693-725.333 725.333-725.333 23.467 0 42.667 19.2 42.667 42.667v149.333c0 23.467-19.2 42.667-42.667 42.667zM810.667 810.667v-298.667h85.333v298.667h-85.333z" />
-<glyph unicode="&#xe8c8;" d="M853.333 682.667h-170.667v85.333l-85.333 85.333h-170.667l-85.333-85.333v-85.333h-170.667c-47.36 0-84.907-37.973-84.907-85.333l-0.427-469.333c0-47.36 37.973-85.333 85.333-85.333h682.667c47.36 0 85.333 37.973 85.333 85.333v469.333c0 47.36-37.973 85.333-85.333 85.333zM426.667 768h170.667v-85.333h-170.667v85.333zM512 128l-213.333 213.333h128v170.667h170.667v-170.667h128l-213.333-213.333z" />
-<glyph unicode="&#xe8c9;" d="M853.333 682.667h-170.667v85.333l-85.333 85.333h-170.667l-85.333-85.333v-85.333h-170.667c-47.36 0-84.907-37.973-84.907-85.333l-0.427-469.333c0-47.36 37.973-85.333 85.333-85.333h682.667c47.36 0 85.333 37.973 85.333 85.333v469.333c0 47.36-37.973 85.333-85.333 85.333zM426.667 768h170.667v-85.333h-170.667v85.333zM448 192l-149.333 149.333 60.16 60.16 89.173-89.173 221.013 221.013 60.16-60.16-281.173-281.173z" />
-<glyph unicode="&#xe8ca;" d="M768 853.334h-341.333l-255.147-256-0.853-512c0-46.933 38.4-85.333 85.333-85.333h512c46.933 0 85.333 38.4 85.333 85.333v682.667c0 46.933-38.4 85.333-85.333 85.333zM512 597.334h-85.333v170.667h85.333v-170.667zM640 597.334h-85.333v170.667h85.333v-170.667zM768 597.334h-85.333v170.667h85.333v-170.667z" />
-<glyph unicode="&#xe8cb;" d="M768 853.334h-341.333l-255.147-256-0.853-512c0-46.933 38.4-85.333 85.333-85.333h512c46.933 0 85.333 38.4 85.333 85.333v682.667c0 46.933-38.4 85.333-85.333 85.333zM554.667 213.334h-85.333v85.333h85.333v-85.333zM554.667 384h-85.333v213.333h85.333v-213.333z" />
-<glyph unicode="&#xe8cc;" d="M853.333 853.334h-682.667c-46.933 0-84.907-38.4-84.907-85.333l-0.427-768 170.667 170.667h597.333c46.933 0 85.333 38.4 85.333 85.333v512c0 46.933-38.4 85.333-85.333 85.333zM554.667 341.334h-85.333v85.333h85.333v-85.333zM554.667 512h-85.333v170.667h85.333v-170.667z" />
-<glyph unicode="&#xe8cd;" d="M853.333 853.334h-682.667c-46.933 0-84.907-38.4-84.907-85.333l-0.427-768 170.667 170.667h597.333c46.933 0 85.333 38.4 85.333 85.333v512c0 46.933-38.4 85.333-85.333 85.333zM384 469.334h-85.333v85.333h85.333v-85.333zM554.667 469.334h-85.333v85.333h85.333v-85.333zM725.333 469.334h-85.333v85.333h85.333v-85.333z" />
-<glyph unicode="&#xe8ce;" d="M426.667 667.734v89.173c-34.133-8.96-66.133-23.040-95.147-40.96l62.293-62.293c10.667 5.12 21.333 10.24 32.853 14.080zM122.027 707.84l100.693-100.693c-32.853-52.053-52.053-113.92-52.053-180.48 0-94.293 38.827-179.2 100.693-240.64l-100.693-100.693h256v256l-95.573-95.573c-46.080 46.507-75.093 110.080-75.093 180.907 0 42.667 10.667 82.773 29.013 118.187l344.747-344.747c-10.667-5.547-21.333-10.667-32.853-14.507v-89.173c34.133 8.96 66.133 23.040 95.147 40.96l100.693-100.693 54.187 54.187-670.293 671.147-54.613-54.187zM853.333 768h-256v-256l95.573 95.573c46.080-46.507 75.093-110.080 75.093-180.907 0-42.667-10.667-82.773-29.013-118.187l62.293-62.293c32.853 52.053 52.053 113.92 52.053 180.48 0 94.293-38.827 179.2-100.693 240.64l100.693 100.693z" />
-<glyph unicode="&#xe8cf;" d="M128 426.667c0-94.293 38.827-179.2 100.693-240.64l-100.693-100.693h256v256l-95.573-95.573c-46.080 46.507-75.093 110.080-75.093 180.907 0 111.36 71.253 206.080 170.667 241.067v89.173c-147.2-37.973-256-171.093-256-330.24zM469.333 213.334h85.333v85.333h-85.333v-85.333zM896 768h-256v-256l95.573 95.573c46.080-46.507 75.093-110.080 75.093-180.907 0-111.36-71.253-206.080-170.667-241.067v-89.173c147.2 37.973 256 171.093 256 330.24 0 94.293-38.827 179.2-100.693 240.64l100.693 100.693zM469.333 384h85.333v256h-85.333v-256z" />
-<glyph unicode="&#xe8d0;" d="M512 768v128l-170.667-170.667 170.667-170.667v128c141.227 0 256-114.773 256-256 0-43.093-10.667-84.053-29.867-119.467l62.293-62.293c33.28 52.48 52.907 114.773 52.907 181.76 0 188.587-152.747 341.333-341.333 341.333zM512 170.667c-141.227 0-256 114.773-256 256 0 43.093 10.667 84.053 29.867 119.467l-62.293 62.293c-33.28-52.48-52.907-114.773-52.907-181.76 0-188.587 152.747-341.333 341.333-341.333v-128l170.667 170.667-170.667 170.667v-128z" />
-<glyph unicode="&#xe8d1;" d="M725.333 895.574l-426.667 0.427c-46.933 0-85.333-38.4-85.333-85.333v-768c0-46.933 38.4-85.333 85.333-85.333h426.667c46.933 0 85.333 38.4 85.333 85.333v768c0 46.933-38.4 84.907-85.333 84.907zM725.333 128h-426.667v597.333h426.667v-597.333zM682.667 384h-128v213.333h-85.333v-213.333h-128l170.667-170.667 170.667 170.667z" />
-<glyph unicode="&#xe8d2;" d="M85.333 256v-85.333c117.76 0 213.333-95.573 213.333-213.333h85.333c0 165.12-133.547 298.667-298.667 298.667zM85.333 85.334v-128h128c0 70.827-57.173 128-128 128zM85.333 426.667v-85.333c212.053 0 384-171.947 384-384h85.333c0 259.413-209.92 469.333-469.333 469.333zM725.333 895.574l-426.667 0.427c-46.933 0-85.333-38.4-85.333-85.333v-314.453c29.44-6.827 58.027-15.787 85.333-27.307v256.427h426.667v-554.667h-129.28c22.187-53.333 35.84-110.507 40.533-170.667h88.747c46.933 0 85.333 38.4 85.333 85.333v725.333c0 46.933-38.4 84.907-85.333 84.907z" />
-<glyph unicode="&#xe8d3;" d="M807.253 724.907c-8.533 25.173-32.427 43.093-60.587 43.093h-469.333c-28.16 0-51.627-17.92-60.587-43.093l-88.747-255.573v-341.333c0-23.467 19.2-42.667 42.667-42.667h42.667c23.467 0 42.667 19.2 42.667 42.667v42.667h512v-42.667c0-23.467 19.2-42.667 42.667-42.667h42.667c23.467 0 42.667 19.2 42.667 42.667v341.333l-88.747 255.573zM277.333 298.667c-35.413 0-64 28.587-64 64s28.587 64 64 64 64-28.587 64-64-28.587-64-64-64zM746.667 298.667c-35.413 0-64 28.587-64 64s28.587 64 64 64 64-28.587 64-64-28.587-64-64-64zM213.333 512l64 192h469.333l64-192h-597.333z" />
-<glyph unicode="&#xe8d4;" d="M0 298.667h85.333v256h-85.333v-256zM128 213.334h85.333v426.667h-85.333v-426.667zM938.667 554.667v-256h85.333v256h-85.333zM810.667 213.334h85.333v426.667h-85.333v-426.667zM704 810.667h-384c-35.413 0-64-28.587-64-64v-640c0-35.413 28.587-64 64-64h384c35.413 0 64 28.587 64 64v640c0 35.413-28.587 64-64 64zM682.667 128h-341.333v597.333h341.333v-597.333z" />
-<glyph unicode="&#xe8d5;" d="M853.333 853.334h-682.667c-46.933 0-84.907-38.4-84.907-85.333l-0.427-768 170.667 170.667h597.333c46.933 0 85.333 38.4 85.333 85.333v512c0 46.933-38.4 85.333-85.333 85.333zM768 341.334l-170.667 136.533v-136.533h-341.333v341.333h341.333v-136.533l170.667 136.533v-341.333z" />
-<glyph unicode="&#xe8d6;" d="M938.667 768v21.333c0 58.88-47.787 106.667-106.667 106.667s-106.667-47.787-106.667-106.667v-21.333c-23.467 0-42.667-19.2-42.667-42.667v-170.667c0-23.467 19.2-42.667 42.667-42.667h213.333c23.467 0 42.667 19.2 42.667 42.667v170.667c0 23.467-19.2 42.667-42.667 42.667zM904.533 768h-145.067v21.333c0 40.107 32.427 72.533 72.533 72.533s72.533-32.427 72.533-72.533v-21.333zM807.253 426.667c1.707-14.080 3.413-28.16 3.413-42.667 0-88.747-34.133-169.387-89.6-229.973-11.093 34.56-42.667 59.307-81.067 59.307h-42.667v128c0 23.467-19.2 42.667-42.667 42.667h-256v85.333h85.333c23.467 0 42.667 19.2 42.667 42.667v85.333h85.333c46.933 0 85.333 38.4 85.333 85.333v108.373c-40.533 12.8-83.2 19.627-128 19.627-235.52 0-426.667-191.147-426.667-426.667s191.147-426.667 426.667-426.667 426.667 191.147 426.667 426.667c0 14.507-0.853 28.587-2.133 42.667h-86.613zM426.667 45.654c-168.533 20.907-298.667 164.267-298.667 338.347 0 26.453 3.413 51.627 8.96 76.373l204.373-204.373v-42.667c0-46.933 38.4-85.333 85.333-85.333v-82.347z" />
-<glyph unicode="&#xe8d7;" d="M512 682.667c47.36 0 85.333 38.4 85.333 85.333 0 16.213-4.267 31.147-12.373 43.947l-72.96 126.72-72.96-126.72c-8.107-12.8-12.373-27.733-12.373-43.947 0-46.933 38.4-85.333 85.333-85.333zM708.267 256.427l-45.653 45.653-46.080-45.653c-55.467-55.467-152.747-55.893-208.64 0l-45.653 45.653-46.507-45.653c-27.733-27.733-64.853-43.093-104.107-43.093-31.147 0-59.733 9.813-83.627 26.027v-196.693c0-23.467 19.2-42.667 42.667-42.667h682.667c23.467 0 42.667 19.2 42.667 42.667v196.693c-23.893-16.213-52.48-26.027-83.627-26.027-39.253 0-76.373 15.36-104.107 43.093zM768 554.667h-213.333v85.333h-85.333v-85.333h-213.333c-70.827 0-128-57.173-128-128v-65.707c0-46.080 37.547-83.627 83.627-83.627 22.187 0 43.52 8.533 58.88 24.32l91.307 90.88 90.88-90.88c31.573-31.573 86.613-31.573 118.187 0l91.307 90.88 90.88-90.88c15.787-15.787 36.693-24.32 58.88-24.32 46.080 0 83.627 37.547 83.627 83.627v65.707c0.427 70.827-56.747 128-127.573 128z" />
-<glyph unicode="&#xe8d8;" d="M512 640v170.667h-426.667v-768h853.333v597.333h-426.667zM256 128h-85.333v85.333h85.333v-85.333zM256 298.667h-85.333v85.333h85.333v-85.333zM256 469.334h-85.333v85.333h85.333v-85.333zM256 640h-85.333v85.333h85.333v-85.333zM426.667 128h-85.333v85.333h85.333v-85.333zM426.667 298.667h-85.333v85.333h85.333v-85.333zM426.667 469.334h-85.333v85.333h85.333v-85.333zM426.667 640h-85.333v85.333h85.333v-85.333zM853.333 128h-341.333v85.333h85.333v85.333h-85.333v85.333h85.333v85.333h-85.333v85.333h341.333v-426.667zM768 469.334h-85.333v-85.333h85.333v85.333zM768 298.667h-85.333v-85.333h85.333v85.333z" />
-<glyph unicode="&#xe8d9;" d="M341.333 512h-128v128h-85.333v-128h-128v-85.333h128v-128h85.333v128h128v85.333zM768 469.334c70.827 0 127.573 57.173 127.573 128s-56.747 128-127.573 128c-13.653 0-26.88-2.133-38.827-5.973 24.32-34.56 38.4-76.373 38.4-122.027s-14.507-87.040-38.4-122.027c11.947-3.84 25.173-5.973 38.827-5.973zM554.667 469.334c70.827 0 127.573 57.173 127.573 128s-56.747 128-127.573 128c-70.827 0-128-57.173-128-128s57.173-128 128-128zM837.12 377.174c35.413-31.147 58.88-70.827 58.88-121.173v-85.333h128v85.333c0 65.707-101.12 106.24-186.88 121.173zM554.667 384c-85.333 0-256-42.667-256-128v-85.333h512v85.333c0 85.333-170.667 128-256 128z" />
-<glyph unicode="&#xe8da;" d="M682.667 469.334c70.827 0 127.573 57.173 127.573 128s-56.747 128-127.573 128c-70.827 0-128-57.173-128-128s57.173-128 128-128zM341.333 469.334c70.827 0 127.573 57.173 127.573 128s-56.747 128-127.573 128c-70.827 0-128-57.173-128-128s57.173-128 128-128zM341.333 384c-99.413 0-298.667-49.92-298.667-149.333v-106.667h597.333v106.667c0 99.413-199.253 149.333-298.667 149.333zM682.667 384c-12.373 0-26.453-0.853-41.387-2.133 49.493-35.84 84.053-84.053 84.053-147.2v-106.667h256v106.667c0 99.413-199.253 149.333-298.667 149.333z" />
-<glyph unicode="&#xe8db;" d="M640 469.334v256l-128 128-128-128v-85.333h-256v-597.333h768v426.667h-256zM298.667 128h-85.333v85.333h85.333v-85.333zM298.667 298.667h-85.333v85.333h85.333v-85.333zM298.667 469.334h-85.333v85.333h85.333v-85.333zM554.667 128h-85.333v85.333h85.333v-85.333zM554.667 298.667h-85.333v85.333h85.333v-85.333zM554.667 469.334h-85.333v85.333h85.333v-85.333zM554.667 640h-85.333v85.333h85.333v-85.333zM810.667 128h-85.333v85.333h85.333v-85.333zM810.667 298.667h-85.333v85.333h85.333v-85.333z" />
-<glyph unicode="&#xe8dc;" d="M511.573 853.334c-235.52 0-426.24-191.147-426.24-426.667s190.72-426.667 426.24-426.667c235.947 0 427.093 191.147 427.093 426.667s-191.147 426.667-427.093 426.667zM512 85.334c-188.587 0-341.333 152.747-341.333 341.333s152.747 341.333 341.333 341.333 341.333-152.747 341.333-341.333-152.747-341.333-341.333-341.333zM661.333 469.334c35.413 0 64 28.587 64 64s-28.587 64-64 64-64-28.587-64-64 28.587-64 64-64zM362.667 469.334c35.413 0 64 28.587 64 64s-28.587 64-64 64-64-28.587-64-64 28.587-64 64-64zM512 192c99.413 0 183.893 62.293 218.027 149.333h-436.053c34.133-87.040 118.613-149.333 218.027-149.333z" />
-<glyph unicode="&#xe8dd;" d="M490.667-0c46.933 0 85.333 38.4 85.333 85.333h-170.667c0-46.933 38.4-85.333 85.333-85.333zM768 256v234.667c0 130.987-90.88 240.64-213.333 269.653v29.013c0 35.413-28.587 64-64 64s-64-28.587-64-64v-29.013c-122.453-29.013-213.333-138.667-213.333-269.653v-234.667l-85.333-85.333v-42.667h725.333v42.667l-85.333 85.333zM682.667 213.334h-384v277.333c0 106.24 85.76 192 192 192s192-85.76 192-192v-277.333z" />
-<glyph unicode="&#xe8de;" d="M490.667-0c46.933 0 85.333 38.4 85.333 85.333h-170.667c0-46.933 38.4-85.333 85.333-85.333zM768 490.667c0 130.987-90.88 240.64-213.333 269.653v29.013c0 35.413-28.587 64-64 64s-64-28.587-64-64v-29.013c-21.76-5.12-42.24-13.653-61.867-23.893l403.2-402.773v157.013zM756.48 128l85.333-85.333 54.187 54.187-713.813 713.813-54.187-54.187 124.587-124.587c-24.747-41.387-39.253-89.6-39.253-141.227v-234.667l-85.333-85.333v-42.667h628.48z" />
-<glyph unicode="&#xe8df;" d="M280.747 785.92l-61.013 61.013c-101.973-77.653-169.387-198.4-175.787-334.933h85.333c6.4 113.067 64.427 212.053 151.467 273.92zM852.053 512h85.333c-6.4 136.533-73.813 257.28-176.213 334.933l-61.013-61.013c87.467-61.867 145.493-160.853 151.893-273.92zM768 490.667c0 130.987-90.88 240.64-213.333 269.653v29.013c0 35.413-28.587 64-64 64s-64-28.587-64-64v-29.013c-122.453-29.013-213.333-138.667-213.333-269.653v-234.667l-85.333-85.333v-42.667h725.333v42.667l-85.333 85.333v234.667zM490.667-0c5.973 0 11.52 0.427 17.067 1.707 27.733 5.547 50.773 24.747 61.44 50.347 4.267 10.24 6.827 21.333 6.827 33.28h-170.667c0-46.933 38.4-85.333 85.333-85.333z" />
-<glyph unicode="&#xe8e0;" d="M490.667-0c46.933 0 85.333 38.4 85.333 85.333h-170.667c0-46.933 38.4-85.333 85.333-85.333zM768 256v234.667c0 130.987-90.88 240.64-213.333 269.653v29.013c0 35.413-28.587 64-64 64s-64-28.587-64-64v-29.013c-122.453-29.013-213.333-138.667-213.333-269.653v-234.667l-85.333-85.333v-42.667h725.333v42.667l-85.333 85.333zM597.333 520.534l-119.467-145.067h119.467v-76.8h-213.333v76.8l119.467 145.067h-119.467v76.8h213.333v-76.8z" />
-<glyph unicode="&#xe8e1;" d="M490.667-0c46.933 0 85.333 38.4 85.333 85.333h-170.667c0-46.933 38.4-85.333 85.333-85.333zM768 256v234.667c0 130.987-90.88 240.64-213.333 269.653v29.013c0 35.413-28.587 64-64 64s-64-28.587-64-64v-29.013c-122.453-29.013-213.333-138.667-213.333-269.653v-234.667l-85.333-85.333v-42.667h725.333v42.667l-85.333 85.333z" />
-<glyph unicode="&#xe8e2;" d="M128 725.334v-256h213.333l-42.667 170.667 170.667-42.667v213.333h-256c-46.933 0-85.333-38.4-85.333-85.333zM341.333 384h-213.333v-256c0-46.933 38.4-85.333 85.333-85.333h256v213.333l-170.667-42.667 42.667 170.667zM725.333 213.334l-170.667 42.667v-213.333h256c46.933 0 85.333 38.4 85.333 85.333v256h-213.333l42.667-170.667zM810.667 810.667h-256v-213.333l170.667 42.667-42.667-170.667h213.333v256c0 46.933-38.4 85.333-85.333 85.333z" />
-<glyph unicode="&#xe8e3;" d="M853.333 768h-135.253l-78.080 85.333h-256l-78.080-85.333h-135.253c-46.933 0-85.333-38.4-85.333-85.333v-512c0-46.933 38.4-85.333 85.333-85.333h682.667c46.933 0 85.333 38.4 85.333 85.333v512c0 46.933-38.4 85.333-85.333 85.333zM512 640c69.547 0 130.56-33.707 169.813-85.333h-169.813c-70.827 0-128-57.173-128-128 0-14.933 2.987-29.44 7.68-42.667h-88.747c-2.56 13.653-4.267 28.16-4.267 42.667 0 117.76 95.573 213.333 213.333 213.333zM512 213.334c-69.547 0-130.56 33.707-169.813 85.333h169.813c70.827 0 128 57.173 128 128 0 14.933-2.987 29.44-7.68 42.667h88.747c2.987-13.653 4.267-28.16 4.267-42.667 0-117.76-95.573-213.333-213.333-213.333z" />
-<glyph unicode="&#xe8e4;" d="M704 384c-51.2 0-130.987-14.507-192-42.667-61.013 28.587-140.8 42.667-192 42.667-92.587 0-277.333-46.080-277.333-138.667v-117.333h938.667v117.333c0 92.587-184.747 138.667-277.333 138.667zM533.333 192h-426.667v53.333c0 23.040 109.227 74.667 213.333 74.667s213.333-51.627 213.333-74.667v-53.333zM917.333 192h-320v53.333c0 19.627-8.533 36.693-22.187 52.053 37.547 12.8 83.627 22.613 128.853 22.613 104.107 0 213.333-51.627 213.333-74.667v-53.333zM320 426.667c82.347 0 149.333 66.987 149.333 149.333s-66.987 149.333-149.333 149.333-149.333-66.987-149.333-149.333 66.987-149.333 149.333-149.333zM320 661.334c46.933 0 85.333-38.4 85.333-85.333s-38.4-85.333-85.333-85.333-85.333 38.4-85.333 85.333 38.4 85.333 85.333 85.333zM704 426.667c82.347 0 149.333 66.987 149.333 149.333s-66.987 149.333-149.333 149.333-149.333-66.987-149.333-149.333 66.987-149.333 149.333-149.333zM704 661.334c46.933 0 85.333-38.4 85.333-85.333s-38.4-85.333-85.333-85.333-85.333 38.4-85.333 85.333 38.4 85.333 85.333 85.333z" />
-<glyph unicode="&#xe8e5;" d="M682.667 469.334c70.827 0 127.573 57.173 127.573 128s-56.747 128-127.573 128c-70.827 0-128-57.173-128-128s57.173-128 128-128zM341.333 469.334c70.827 0 127.573 57.173 127.573 128s-56.747 128-127.573 128c-70.827 0-128-57.173-128-128s57.173-128 128-128zM341.333 384c-99.413 0-298.667-49.92-298.667-149.333v-106.667h597.333v106.667c0 99.413-199.253 149.333-298.667 149.333zM682.667 384c-12.373 0-26.453-0.853-41.387-2.133 49.493-35.84 84.053-84.053 84.053-147.2v-106.667h256v106.667c0 99.413-199.253 149.333-298.667 149.333z" />
-<glyph unicode="&#xe8e6;" d="M640 426.667c94.293 0 170.667 76.373 170.667 170.667s-76.373 170.667-170.667 170.667-170.667-76.373-170.667-170.667 76.373-170.667 170.667-170.667zM256 512v128h-85.333v-128h-128v-85.333h128v-128h85.333v128h128v85.333h-128zM640 341.334c-113.92 0-341.333-57.173-341.333-170.667v-85.333h682.667v85.333c0 113.493-227.413 170.667-341.333 170.667z" />
-<glyph unicode="&#xe8e7;" d="M512 686.934c49.493 0 89.6-40.107 89.6-89.6s-40.107-89.6-89.6-89.6-89.6 40.107-89.6 89.6 40.107 89.6 89.6 89.6zM512 302.934c126.72 0 260.267-62.293 260.267-89.6v-46.933h-520.533v46.933c0 27.307 133.547 89.6 260.267 89.6zM512 768c-94.293 0-170.667-76.373-170.667-170.667s76.373-170.667 170.667-170.667 170.667 76.373 170.667 170.667-76.373 170.667-170.667 170.667zM512 384c-113.92 0-341.333-57.173-341.333-170.667v-128h682.667v128c0 113.493-227.413 170.667-341.333 170.667z" />
-<glyph unicode="&#xe8e8;" d="M512 426.667c94.293 0 170.667 76.373 170.667 170.667s-76.373 170.667-170.667 170.667-170.667-76.373-170.667-170.667 76.373-170.667 170.667-170.667zM512 341.334c-113.92 0-341.333-57.173-341.333-170.667v-85.333h682.667v85.333c0 113.493-227.413 170.667-341.333 170.667z" />
-<glyph unicode="&#xe8e9;" d="M426.667 597.334h-85.333v-170.667h-170.667v-85.333h170.667v-170.667h85.333v170.667h170.667v85.333h-170.667zM618.667 679.254v-77.653l106.667 21.333v-452.267h85.333v554.667z" />
-<glyph unicode="&#xe8ea;" d="M810.667 810.667h-597.333c-46.933 0-85.333-38.4-85.333-85.333v-597.333c0-46.933 38.4-85.333 85.333-85.333h597.333c46.933 0 85.333 38.4 85.333 85.333v597.333c0 46.933-38.4 85.333-85.333 85.333zM384 213.334h-85.333v298.667h85.333v-298.667zM554.667 213.334h-85.333v426.667h85.333v-426.667zM725.333 213.334h-85.333v170.667h85.333v-170.667z" />
-<glyph unicode="&#xe8eb;" d="M512 853.334c-235.52 0-426.667-191.147-426.667-426.667s191.147-426.667 426.667-426.667 426.667 191.147 426.667 426.667-191.147 426.667-426.667 426.667zM469.333 88.32c-168.533 20.907-298.667 164.267-298.667 338.347 0 26.453 3.413 51.627 8.96 76.373l204.373-204.373v-42.667c0-46.933 38.4-85.333 85.333-85.333v-82.347zM763.733 196.694c-11.093 34.56-42.667 59.307-81.067 59.307h-42.667v128c0 23.467-19.2 42.667-42.667 42.667h-256v85.333h85.333c23.467 0 42.667 19.2 42.667 42.667v85.333h85.333c46.933 0 85.333 38.4 85.333 85.333v17.493c125.013-50.773 213.333-173.227 213.333-316.16 0-88.747-34.133-169.387-89.6-229.973z" />
-<glyph unicode="&#xe8ec;" d="M213.333 376.32v-170.667l298.667-162.987 298.667 162.987v170.667l-298.667-162.987-298.667 162.987zM512 810.667l-469.333-256 469.333-256 384 209.493v-294.827h85.333v341.333l-469.333 256z" />
-<glyph unicode="&#xe8ed;" d="M768 252.587c-32.427 0-61.44-12.8-83.627-32.853l-304.213 177.067c2.133 9.813 3.84 19.627 3.84 29.867s-1.707 20.053-3.84 29.867l300.8 175.36c23.040-21.333 53.333-34.56 87.040-34.56 70.827 0 128 57.173 128 128s-57.173 128-128 128-128-57.173-128-128c0-10.24 1.707-20.053 3.84-29.867l-300.8-175.36c-23.040 21.333-53.333 34.56-87.040 34.56-70.827 0-128-57.173-128-128s57.173-128 128-128c33.707 0 64 13.227 87.040 34.56l303.787-177.493c-2.133-8.96-3.413-18.347-3.413-27.733 0-68.693 55.893-124.587 124.587-124.587s124.587 55.893 124.587 124.587-55.893 124.587-124.587 124.587z" />
-<glyph unicode="&#xe8ee;" d="M576 910.080s31.573-113.067 31.573-204.8c0-87.893-57.6-159.147-145.493-159.147-88.32 0-154.88 71.253-154.88 159.147l1.28 15.36c-86.187-102.4-137.813-235.093-137.813-379.307 0-188.587 152.747-341.333 341.333-341.333s341.333 152.747 341.333 341.333c0 229.973-110.507 435.2-277.333 568.747zM499.627 128c-75.947 0-137.387 59.733-137.387 133.973 0 69.12 44.8 117.76 119.893 133.12 75.52 15.36 153.6 51.627 197.12 110.080 16.64-55.040 25.173-113.067 25.173-172.373 0-113.067-91.733-204.8-204.8-204.8z" />
-<glyph unicode="&#xe8ef;" d="M810.667 725.334v-597.333h-597.333v597.333h597.333zM810.667 810.667h-597.333c-46.933 0-85.333-38.4-85.333-85.333v-597.333c0-46.933 38.4-85.333 85.333-85.333h597.333c46.933 0 85.333 38.4 85.333 85.333v597.333c0 46.933-38.4 85.333-85.333 85.333z" />
-<glyph unicode="&#xe8f0;" d="M810.667 810.667h-597.333c-47.36 0-85.333-38.4-85.333-85.333v-597.333c0-46.933 37.973-85.333 85.333-85.333h597.333c47.36 0 85.333 38.4 85.333 85.333v597.333c0 46.933-37.973 85.333-85.333 85.333zM426.667 213.334l-213.333 213.333 60.16 60.16 153.173-152.747 323.84 323.84 60.16-60.587-384-384z" />
-<glyph unicode="&#xe8f1;" d="M512 853.334c-235.52 0-426.667-191.147-426.667-426.667s191.147-426.667 426.667-426.667 426.667 191.147 426.667 426.667-191.147 426.667-426.667 426.667zM512 85.334c-188.587 0-341.333 152.747-341.333 341.333s152.747 341.333 341.333 341.333 341.333-152.747 341.333-341.333-152.747-341.333-341.333-341.333z" />
-<glyph unicode="&#xe8f2;" d="M512 640c-117.76 0-213.333-95.573-213.333-213.333s95.573-213.333 213.333-213.333 213.333 95.573 213.333 213.333-95.573 213.333-213.333 213.333zM512 853.334c-235.52 0-426.667-191.147-426.667-426.667s191.147-426.667 426.667-426.667 426.667 191.147 426.667 426.667-191.147 426.667-426.667 426.667zM512 85.334c-188.587 0-341.333 152.747-341.333 341.333s152.747 341.333 341.333 341.333 341.333-152.747 341.333-341.333-152.747-341.333-341.333-341.333z" />
-<glyph unicode="&#xe8f3;" d="M938.667 523.094l-306.773 26.453-119.893 282.453-119.893-282.88-306.773-26.027 232.96-201.813-69.973-299.947 263.68 159.147 263.68-159.147-69.547 299.947 232.533 201.813zM512 260.267v396.8l72.96-172.373 186.88-16.213-141.653-122.88 42.667-182.613-160.853 97.28z" />
-<glyph unicode="&#xe8f4;" d="M938.667 544.427l-306.773 26.453-119.893 282.453-119.893-282.88-306.773-26.027 232.96-201.813-69.973-299.947 263.68 159.147 263.68-159.147-69.547 299.947 232.533 201.813zM512 281.6l-160.427-96.853 42.667 182.613-141.653 122.88 186.88 16.213 72.533 171.947 72.96-172.373 186.88-16.213-141.653-122.88 42.667-182.613-160.853 97.28z" />
-<glyph unicode="&#xe8f5;" d="M512 201.814l263.68-159.147-69.973 299.947 232.96 201.813-306.773 26.027-119.893 282.88-119.893-282.88-306.773-26.027 232.96-201.813-69.973-299.947z" />
-<glyph unicode="&#xe8f6;" d="M1032.533 597.334l59.733 72.533c-21.333 12.8-226.133 183.467-537.6 183.467s-516.267-170.667-537.6-183.467l537.6-669.867 298.667 371.2v226.133c0 0 179.2 0 179.2 0z" horiz-adv-x="1109" />
-<glyph unicode="&#xe8f7;" d="M900.267 576c34.133 0 68.267-8.533 98.133-25.6l93.867 119.467c-17.067 12.8-221.867 183.467-533.333 183.467s-516.267-170.667-537.6-183.467l537.6-669.867 179.2 221.867c-34.133 38.4-51.2 85.333-51.2 136.533 0 123.733 98.133 217.6 213.333 217.6z" horiz-adv-x="1109" />
-<glyph unicode="&#xe8f8;" d="M938.667 597.334v256l-853.333-853.333h682.667v597.333h170.667z" />
-</font></defs></svg> \ No newline at end of file
diff --git a/doc/_extensions/odoo_ext/static/fonts/Material-Design-Icons.ttf b/doc/_extensions/odoo_ext/static/fonts/Material-Design-Icons.ttf
deleted file mode 100644
index e12f0cc41bf..00000000000
--- a/doc/_extensions/odoo_ext/static/fonts/Material-Design-Icons.ttf
+++ /dev/null
Binary files differ
diff --git a/doc/_extensions/odoo_ext/static/fonts/Material-Design-Icons.woff b/doc/_extensions/odoo_ext/static/fonts/Material-Design-Icons.woff
deleted file mode 100644
index 201581f2582..00000000000
--- a/doc/_extensions/odoo_ext/static/fonts/Material-Design-Icons.woff
+++ /dev/null
Binary files differ
diff --git a/doc/_extensions/odoo_ext/static/footer.less b/doc/_extensions/odoo_ext/static/footer.less
deleted file mode 100644
index d5019e29ce5..00000000000
--- a/doc/_extensions/odoo_ext/static/footer.less
+++ /dev/null
@@ -1,95 +0,0 @@
-// Based on http://www.odoo.com/openerp_website/static/src/less/footer.less
-// ========================================================================
-
-body > footer {
- font-size: 14px;
- position: relative;
- width: 100%;
- height: auto;
- min-height: @footer-heigth;
- background-color: @footer-bg-color;
- color: @gray;
-
- z-index: 1;
- @media screen and (min-width: @screen-md-min) {
- &.o_footer_effect {
- .o-position-absolute(auto, 0, 0, 0);
- position: fixed;
- z-index: 0;
- }
- }
-
- .o_footer_logo {
- margin-bottom: 3em;
- margin-top: 3em;
- }
-
- a {
- color: @footer-text;
- &:hover, &:active, &:focus {
- color: white;
- }
- }
- .dropdown-menu a {
- color: @dropdown-link-color;
- &:hover, &:focus {
- color: @dropdown-link-hover-color;
- }
- &:active {
- color: @dropdown-link-active-color;
- }
- }
-
- .divider {
- margin: 10px 0;
- }
- ul, ol {
- list-style: none;
- padding-left: 0;
- }
- span.menu_title {
- font-weight: @fw_semibold;
- color: white;
- + ul {
- margin-top: 10px;
- }
- }
- .o_language_selector, .o_country_selector {
- display: inline-block;
- .opacity(0.8);
- a {
- font-size: 0.9em;
- font-weight: bold;
- }
- img {
- max-height: 20px;
- margin-right: 10px;
- vertical-align: bottom;
- }
- &:hover {
- .opacity(1);
- }
- }
- .o_country_selector {
- float: right;
- }
-
- hr {
- border-top-color: lighten(@footer-bg-color, 10%);
- }
- .o_footer_bottom {
- background-color: @footer-bottom-bg-color;
- color: @footer-text;
- padding: 1em 0;
- margin-top: 3em;
- a {
- .opacity(0.6);
- &:hover {
- .opacity(1);
- }
- }
- .social-links .fa {
- margin-left: 20px;
- }
- }
-}
diff --git a/doc/_extensions/odoo_ext/static/header.less b/doc/_extensions/odoo_ext/static/header.less
deleted file mode 100644
index ab5afd13b00..00000000000
--- a/doc/_extensions/odoo_ext/static/header.less
+++ /dev/null
@@ -1,834 +0,0 @@
-// Based on http://www.odoo.com/openerp_website/static/src/less/header.less
-// ========================================================================
-
-// ============= MIXINS
-.o-top-menu-links() {
- &:not(.btn) {
- display: inline-block;
- padding: 0 20px;
- font-weight: @fw_semibold;
- text-transform: uppercase;
-
- @media screen and (min-width: @screen-sm-min) and (max-width: @screen-sm-max) {
- font-size: 11px;
-
- &:not(.dropdown-toggle) {
- padding: 0 10px;
- }
- }
- }
-}
-
-.o-white-header() {
- background-color: @w-header-white;
- color: @header-link-normal;
- .deep-1();
-
- .o_logo {
- background-position: 0 0;
- }
-
- > .o_main_header_main > .o_primary_nav > li.dropdown > a {
- &::before, &::after {
- background-color: @header-link-normal;
- box-shadow: 0 1px 1px fade(@header-link-normal,10%);
- }
- }
-}
-
-// ============= MAIN HEADER
-#oe_main_menu_navbar ~ #wrapwrap .o_main_header {
- &.o_has_sub_nav.o_scrolled {
- top: 34px - (@w-header-height + 1);
- }
-}
-
-.o_main_header {
- @secondary-menu-animation-duration-opening: 500ms;
- @secondary-menu-animation-duration-closing: @secondary-menu-animation-duration-opening * 2/3;
-
- position: fixed;
- width: 100%;
- height: @w-header-height;
- z-index: 2;
- background-color: fade(white, 60%);
- color: @header-link-normal;
- font-family: "Work Sans", sans-serif;
- font-size: 12px;
- .transition(all .2s ease);
- .transition-property(~'background, box-shadow' );
- .translate3d(auto, auto, 0);
-
- a:focus, a:active, a:focus:active {
- outline: none;
- }
-
- .btn-primary {
- color: white!important;
- font-size: inherit!important;
- font-weight: @fw_bold;
- text-transform: uppercase;
- }
-
- > .o_main_header_main {
- .container(); // FIXME Remove this once the web_editor "container container" rule is fixed.
- height: 100%;
-
- a {
- color: inherit;
- &:hover, &:focus {
- color: saturate(@header-link-normal, 10%);
- }
- }
-
- .o_logo {
- margin: 15px 0;
- .size(63px, 20px);
- background-size: cover;
- }
-
- > .o_primary_nav {
- @w-header-arrow-length: 10px;
-
- @media (min-width: @screen-sm-min) {
- height: 100%;
- &:before {
- content: "";
- background: transparent;
- z-index: -1;
- visibility: hidden;
- box-shadow: 0 1px 0 transparent;
- .size( 100%, @w-header-height);
- .o-position-absolute(0,0);
- .transition(~'background @{secondary-menu-animation-duration-opening} @{o-ease} 0ms, visibility 0ms linear @{secondary-menu-animation-duration-opening}, box-shadow @{secondary-menu-animation-duration-opening} linear 0ms' );
- }
-
- &.o_sub_opened:before {
- visibility: visible;
- background: @w-header-white;
- box-shadow: 0 1px 0 @gray-lighter;
- .transition(~'background @{secondary-menu-animation-duration-opening} @{o-ease} 0ms, visibility 0ms linear 0s, box-shadow @{secondary-menu-animation-duration-opening} linear 0ms');
-
- }
- }
-
- margin: 0 auto;
- padding: 0;
- text-align: center;
- white-space: nowrap;
-
- .dropdown {
- position: static;
-
- > a {
- position: relative;
- .backface-visibility(hidden);
-
- &::before, &::after {
- content: "";
- display: block;
- .o-position-absolute(50%, 0);
- .o-transform-origin(50%, 50%);
- .o-transition(all, 300ms);
- width: @w-header-arrow-length;
- height: 1px;
- background-color: @headings-color;
- box-shadow: 0 1px 1px fade(@headings-color, 10%);
- }
- &::before {
- .rotate(45deg);
- right: @w-header-arrow-length / sqrt(2) - 1;
- }
- &::after {
- .rotate(-45deg);
- }
- }
- &.open > a {
- color: @odoo-brand-primary!important;
- font-weight: @fw_semibold;
-
- &::before, &::after {
- background-color: @odoo-brand-primary!important;
- box-shadow: 0 1px 1px fade(@odoo-brand-primary, 10%);
- right: @w-header-arrow-length / sqrt(2) / 2;
- }
- &::before {
- .rotate(-45deg);
- }
- &::after {
- .rotate(45deg);
- }
- }
- > .dropdown-menu {
- border: none;
- border-radius: 0;
- margin: 0;
- }
- }
-
- > li {
- display: inline-block;
-
- > a {
- height: 100%;
- line-height: @w-header-height;
- .o-top-menu-links();
- }
- &.dropdown > a {
- margin-right: @w-header-arrow-length * 2;
- }
-
- // Secondary nav animation
- @media (min-width: @screen-sm-min) {
- &.open > .o_secondary_nav {
- visibility: visible;
- background-color: white;
- .translate(0, 0);
- .transition(~'transform @{secondary-menu-animation-duration-opening} @{o-ease} 0ms, visibility 0ms linear 0ms, background-color 0ms linear @{secondary-menu-animation-duration-opening}');
-
- .container > .row > div {
- opacity: 1;
- .translate(0, 0);
-
- &:nth-child(1) {
- .transition-delay(@secondary-menu-animation-duration-opening * 1/5);
- }
- &:nth-child(2) {
- .transition-delay(@secondary-menu-animation-duration-opening * 2/5);
- }
- &:nth-child(3) {
- .transition-delay(@secondary-menu-animation-duration-opening * 3/5);
- }
- &:nth-child(4) {
- .transition-delay(@secondary-menu-animation-duration-opening * 4/5);
- }
- }
- .o_store_link {
- max-height: @w-header-height;
- .o-transition(max-height, @secondary-menu-animation-duration-opening, @o-ease, @secondary-menu-animation-duration-opening * 3/5);
- }
-
- &::before {
- opacity: 0.5;
- }
- }
- }
- }
-
- .o_secondary_nav {
- @w-li-link-height: 30px;
- @w-li-link-animation-time: 300ms;
- @w-menu-gutter-increase: 60px;
-
- width: 100%;
- padding: 15px 0 (@w-header-height + 15);
- box-shadow: 0 3px 6px fade(black, 5%);
-
- @media (min-width: @screen-md-min) { // Change gutter width for that case
- > .container > .row {
- margin-left: (@grid-gutter-width + @w-menu-gutter-increase) / -2;
- margin-right: (@grid-gutter-width + @w-menu-gutter-increase) / -2;
-
- > div {
- padding-left: (@grid-gutter-width + @w-menu-gutter-increase) / 2;
- padding-right: (@grid-gutter-width + @w-menu-gutter-increase) / 2;
- }
- }
- }
-
- > .container > .row > div {
- font-size: 16px;
- overflow: hidden;
-
- @media (min-width: @screen-sm-min) {
- height: 340px;
- padding-top: 10px;
-
- + div {
- border-left: 1px solid @gray-lighter;
- }
- }
-
- ul {
- position: relative;
- list-style: none;
- padding: 0;
-
- > li {
- height: @w-li-link-height;
- .o-transition(all, @w-li-link-animation-time, @o-ease, @w-li-link-animation-time/3);
- .transition-property(~'height, opacity');
-
- > a {
- display: block;
- height: 100%;
- line-height: @w-li-link-height;
- font-weight: @fw_medium;
- font-size: 1.4rem;
- }
-
- &.dropdown {
- &:not(.open) > a {
- &::before, &::after {
- .o-transform-origin((@w-header-arrow-length * 0.8), 50%);
- width: @w-header-arrow-length * 0.8;
- right: 0;
- }
- }
-
- > ul {
- .o-position-absolute(@w-li-link-height, 0, 0, 0);
- .translate(100%, 0);
- .opacity(0);
- .o-transition(all, @w-li-link-animation-time, @o-ease, 0);
- }
- &.open > ul {
- .translate(0, 0);
- .opacity(1);
- .o-transition(all, @w-li-link-animation-time, @o-ease, @w-li-link-animation-time/3);
- }
- }
- }
- &.o_sub_opened > li:not(.open) {
- opacity: 0;
- height: 0 !important;
- overflow: hidden;
- .o-transition(all, @w-li-link-animation-time, @o-ease, 0);
- }
- }
-
- .o_nav_app_family {
- text-align: center;
- font-weight: @fw_medium;
- line-height: 2;
- .o-no-select();
-
- > span {
- .o-retina-bg("apps_families_s.png", 0px, 50%);
- display: none;
- }
-
- @media (min-width: @screen-sm-min) {
- > span {
- display: block;
- margin: 0 auto;
- background-size: auto 100%;
- width: 51px;
- height: 50px;
- }
- > div {
- font-size: 0.7em;
- font-weight: @fw_medium;
- line-height: 1.5;
- color: @text-color;
- margin-bottom: 1.3em;
- }
- }
- }
-
- @media (min-width: @screen-sm-min) {
- &.o_website_apps {
- a:hover, a:focus, .o_nav_app_family {
- color: @color-beta;
- }
- }
- &.o_sale_apps {
- a:hover, a:focus, .o_nav_app_family {
- color: @color-gamma;
- }
- .o_nav_app_family > span {
- background-position: -60px 50%;
- }
- }
- &.o_operation_apps {
- a:hover, a:focus, .o_nav_app_family {
- color: @color-delta;
- }
- .o_nav_app_family > span {
- background-position: -120px 50%;
- }
- }
- &.o_productivity_apps {
- a:hover, a:focus, .o_nav_app_family {
- color: @color-epsilon;
- }
- .o_nav_app_family > span {
- background-position: -181px 50%;
- }
- }
- }
- }
-
- > .o_store_link {
- .o-position-absolute(auto, 0, 0, 0);
- overflow: hidden;
- display: block;
- height: @w-header-height;
- line-height: @w-header-height;
- border-top: 1px solid @gray-lighter;
- text-align: center;
- font-size: 12px;
- font-weight: @fw_semibold;
- }
-
- @media (min-width: @screen-sm-min) {
- // Animation
- display: block;
- background-color: @w-header-white;
- visibility: hidden;
- z-index: -2;
- .translate(0, -115%);
- .transition(~'transform @{secondary-menu-animation-duration-closing} @{o-ease} 0ms, visibility 0ms linear @{secondary-menu-animation-duration-closing}, background-color 0ms linear 0ms');
-
- .container > .row > div {
- opacity: 0;
- .translate(0, -30%);
- .o-transition(all, @secondary-menu-animation-duration-opening, @o-ease, 0ms);
- }
- .o_store_link {
- max-height: 0;
- .o-transition(max-height, @secondary-menu-animation-duration-opening/2, @o-ease, 0s);
- }
-
- // Overlay
- &::before {
- content: "";
- .o-position-absolute(100%, 0, -1000px, 0);
- display: block;
- background-color: #000;
- opacity: 0;
- .o-transition(opacity, @secondary-menu-animation-duration-opening, @o-ease);
- }
- }
- }
- }
-
- .o_header_buttons {
- height: 100%;
- line-height: @w-header-height;
- float: right;
-
- > * {
- display: inline-block;
- float: left;
- }
-
- a {
- .o-top-menu-links();
-
- &.dropdown-toggle {
- padding: 0 10px;
- }
-
- &.o_my_cart {
- padding: 0;
-
- .my_cart_quantity {
- font-family: sans-serif;
- border-radius: 100%;
- font-weight: bold;
- font-size: 90%;
- padding: 4px 0;
- min-width: 19px;
- text-align: center;
- display: inline-block;
- }
- }
- }
-
- .btn-primary {
- margin-top: 9px;
- }
-
- > .dropdown {
- margin: 0 5px;
-
- @media screen and (min-width: @screen-md-min) {
- margin: 0 15px;
- }
-
- &, .dropdown-toggle {
- height: 100%;
- }
-
- > .dropdown-menu {
- left: auto;
- right: 0;
- li a {
- padding-top: 5px;
- padding-bottom: 5px;
- color: @text-color;
- }
- }
- }
- }
- }
-
- > .o_sub_nav {
- min-height: @w-sub-nav-height;
- border: 1px solid fade(black, 5%);
- border-width: 1px 0;
- background-color: fade(white, 80%);
-
- > .container {
-
- .navbar-header {
- height: @w-sub-nav-height - 2;
- line-height: @w-sub-nav-height - 2;
- font-weight: @fw_semibold;
- color: @text-color;
- overflow: hidden;
-
- .o_app_name_logo,
- .o_app_name_title {
- .translate(-61px, 0);
- .o-transition(transform, 400ms);
- }
-
- &:hover {
- color: @headings-color;
- }
-
- .o_app_name_logo {
- .o_logo();
- .o_logo_15();
- vertical-align: middle;
- margin: auto 5px 3px 0;
- }
- .o_app_name_title {
- color: inherit;
- vertical-align: middle;
- display: inline-block;
-
- span{
- margin-right: 5px;
- }
- }
- }
-
- .nav {
- margin-right: -15px; // gutter's right compensation
- }
-
- .nav > li {
- margin-left: 20px;
- height: @w-sub-nav-height - 2;
- line-height: @w-sub-nav-height - 2;
-
- > a {
- height: 100%;
- line-height: @w-sub-nav-height - 2;
- padding: 0;
- font-size: 12px;
- font-weight: @fw_medium;
- color: @text-color;
-
- &:hover, &:focus {
- color: @headings-color;
- background-color: transparent;
- }
- }
- &.active > a {
- color: @headings-color;
- font-weight: @fw_semibold;
- }
- }
-
- .call-to-action {
- line-height: @w-sub-nav-height - 4;
- overflow: hidden;
- width: 100%;
- max-width: 0px;
- transform-origin: 0 0;
- .transition(max-width 0.3s ease 0ms);
-
-
- > a {
- margin-left: 35px;
- font-weight: @fw_semibold;
- padding: (@padding-base-vertical - 2px) @padding-base-horizontal;
- line-height: 1.4em;
- font-size: 12px!important;
- }
- }
- }
- }
- &.o_inverted:not(.o_scrolled) > .o_sub_nav {
- .transition( 0.3s background-color);
- background-color: fade(white, 5%);
- border-color: fade(white, 10%);
-
- .nav > li > a,
- .o_app_name_title {
- color: fade(white, 90%);
-
- &:hover, &:focus {
- color: white;
- }
- }
- }
-
- @media (min-width: @screen-sm-min) {
- // Top menu styles
- // --------------------------------
- &.o_has_sub_nav {
- position: absolute;
- &.o_scrolled {
- position: fixed;
- top: -(@w-header-height + 1);
- }
- }
-
- &.o_inverted {
- background-color: transparent;
- color: white;
- a:hover, a:focus {
- color: inherit;
- }
-
- .o_logo {
- .o_logo_inverse;
- }
-
- .o_main_header_main > .o_primary_nav > li.dropdown > a {
- &::before, &::after {
- background-color: white;
- box-shadow: 0 1px 1px fade(white, 10%);
- }
- }
- }
- > .o_main_header_main > .o_header_buttons {
- .dropdown.open {
- background-color: @w-header-white;
- color: @header-link-normal;
-
- .dropdown-menu {
- background-color: @w-header-white;
- margin-top: 0;
- border: none;
- border-radius: 0;
- .deep-1();
- text-align: left;
- min-width: 100%;
- padding-bottom: @w-header-height/4;
-
- > li > a {
- display: block;
- color: @header-link-normal;
- float: none;
- text-transform: none;
- font-weight: normal;
- }
- }
- }
- }
- }
-
- &.o_scrolled:not(.o_transparent_blocked), &.o_sub_opened {
- .o-white-header();
- }
-
- &.o_scrolled .o_sub_nav {
- background: @w-header-white;
-
- > .container {
- .navbar-header > span{
- .translate(0, 0);
- }
- .call-to-action {
- max-width: 133px;
- }
- }
- }
-
- &.o_sub_opened .o_sub_nav {
- display: none;
- }
-}
-
-@media (max-width: @screen-xs-max) {
- .o_main_header {
- @mobile-dark: #25252D;
- @mobile-light: #33343D;
-
- position: relative;
- height: auto;
- min-height: @w-header-height;
- .o-white-header();
-
- > .o_main_header_main {
- position: relative;
-
- > .o_primary_nav, .o_header_buttons {
- display: none;
- }
-
- > .o_mobile_menu_toggle {
- .o-position-absolute(0, 0);
- width: @w-header-height;
- line-height: @w-header-height;
- font-size: @w-header-height/3;
- text-align: center;
- }
- }
-
- > .o_sub_nav {
- display: none;
- }
-
- &.o_mobile_menu_opened {
- > .o_main_header_main {
- margin: 0;
-
- > .o_header_buttons {
- float: none;
- background-color: @mobile-dark;
- padding: 0 (@grid-gutter-width/2);
- box-sizing: content-box;
- margin: @w-header-height (-@grid-gutter-width/2) 0;
- display: block;
- text-align: center;
- .size(100%, auto);
-
- > * {
- overflow: visible!important;
- color: @w-header-white;
- float: none;
- display: inline;
-
- > a:not(.btn) {
- display: initial!important;
- }
-
- .dropdown-toggle {
- color: @w-header-white!important;
- }
-
- .dropdown-menu {
- position: relative;
- line-height: 2;
- background: fade(white, 5%);
- width: 100%;
- margin: 0 (-@grid-gutter-width/2) 0;
- box-sizing: content-box;
- padding: 5px (@grid-gutter-width/2);
-
- > li > a {
- float: none;
- display: block;
- margin-bottom: 5px;
- padding: 10px;
- color: @w-header-white!important;
- font-size: 0.8em;
-
- &:hover {
- background: fade(white, 5%);
- }
- }
- }
- }
- }
-
-
- > .o_primary_nav {
- display: block;
- background-color: @mobile-dark;
- color: white;
- margin: 0 (-@grid-gutter-width/2) 0;
- padding: 0;
- float: none;
- white-space: normal;
-
- a:hover, a:focus, a:active {
- color: white;
- }
-
- li {
- border: 0 solid @mobile-light;
- border-width: 1px 5px 0;
- }
-
- > li {
- width: 100%;
- padding: 0 @grid-gutter-width/2;
-
- &.dropdown {
- padding: 0;
-
- > a {
- display: none;
- }
- > .dropdown-menu {
- position: static;
- display: block;
- background-color: transparent;
- box-shadow: none;
- }
-
- > .o_secondary_nav {
- padding: 0;
-
- > .container > .row > div {
- padding: 0;
-
- ul {
- list-style-type: none;
-
- > li {
- height: @w-header-height;
- padding: 0 @grid-gutter-width/2;
- border-width: 1px 0 0;
-
- > a {
- line-height: @w-header-height;
- }
-
- &.dropdown.open {
- height: auto;
- border: none;
- > ul {
- position: static;
- }
- }
- }
- }
- > .o_nav_app_family {
- height: @w-header-height;
- line-height: @w-header-height;
- background-color: @mobile-light;
-
- > * {
- display: none;
- }
-
- &::after {
- content: "(Apps)";
- }
- }
- }
-
- > .o_store_link {
- position: relative;
- border: 0 solid @mobile-light;
- border-width: 14px 0 0;
- padding-top: 14px;
- line-height: 1.5;
- height: 60px;
- }
- }
-
- &::after {
- content: "";
- display: inline-block;
- width: 100%;
- height: 20px;
- margin-bottom: -5px; // FIXME don't know why
- background-color: @mobile-light;
- }
- }
- }
- }
- }
- }
- }
-}
diff --git a/doc/_extensions/odoo_ext/static/img/2x_apps_families_s.png b/doc/_extensions/odoo_ext/static/img/2x_apps_families_s.png
deleted file mode 100644
index f364d40139e..00000000000
--- a/doc/_extensions/odoo_ext/static/img/2x_apps_families_s.png
+++ /dev/null
Binary files differ
diff --git a/doc/_extensions/odoo_ext/static/img/apps_families_s.png b/doc/_extensions/odoo_ext/static/img/apps_families_s.png
deleted file mode 100644
index 344232c936b..00000000000
--- a/doc/_extensions/odoo_ext/static/img/apps_families_s.png
+++ /dev/null
Binary files differ
diff --git a/doc/_extensions/odoo_ext/static/img/banner_bg.png b/doc/_extensions/odoo_ext/static/img/banner_bg.png
deleted file mode 100644
index 468c0d14d92..00000000000
--- a/doc/_extensions/odoo_ext/static/img/banner_bg.png
+++ /dev/null
Binary files differ
diff --git a/doc/_extensions/odoo_ext/static/img/geometric_gradient.png b/doc/_extensions/odoo_ext/static/img/geometric_gradient.png
deleted file mode 100644
index 50fec3a5362..00000000000
--- a/doc/_extensions/odoo_ext/static/img/geometric_gradient.png
+++ /dev/null
Binary files differ
diff --git a/doc/_extensions/odoo_ext/static/img/github-square_32.png b/doc/_extensions/odoo_ext/static/img/github-square_32.png
deleted file mode 100644
index 17466644f0e..00000000000
--- a/doc/_extensions/odoo_ext/static/img/github-square_32.png
+++ /dev/null
Binary files differ
diff --git a/doc/_extensions/odoo_ext/static/img/logos/odoo_logo.png b/doc/_extensions/odoo_ext/static/img/logos/odoo_logo.png
deleted file mode 100644
index 55b03ae38c8..00000000000
--- a/doc/_extensions/odoo_ext/static/img/logos/odoo_logo.png
+++ /dev/null
Binary files differ
diff --git a/doc/_extensions/odoo_ext/static/img/logos/odoo_logo.svg b/doc/_extensions/odoo_ext/static/img/logos/odoo_logo.svg
deleted file mode 100644
index 0d404edf64a..00000000000
--- a/doc/_extensions/odoo_ext/static/img/logos/odoo_logo.svg
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<svg width="1254px" height="200px" viewBox="0 0 1254 200" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
- <!-- Generator: Sketch 3.3.3 (12081) - http://www.bohemiancoding.com/sketch -->
- <title>odoo_logo</title>
- <desc>Created with Sketch.</desc>
- <defs></defs>
- <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
- <g id="odoo_logo" sketch:type="MSArtboardGroup">
- <g id="odoo_logo_rgb" sketch:type="MSLayerGroup" transform="translate(0.000000, 1.000000)">
- <path d="M550.5,198.865327 C592.197499,198.865327 626,165.062825 626,123.365327 C626,81.667828 592.197499,47.8653266 550.5,47.8653266 C508.802501,47.8653266 475,81.667828 475,123.365327 C475,165.062825 508.802501,198.865327 550.5,198.865327 Z M550.5,167.865327 C575.076671,167.865327 595,147.941998 595,123.365327 C595,98.7886553 575.076671,78.8653266 550.5,78.8653266 C525.923329,78.8653266 506,98.7886553 506,123.365327 C506,147.941998 525.923329,167.865327 550.5,167.865327 Z" id="Oval-3" fill="#888888" sketch:type="MSShapeGroup"></path>
- <path d="M390.5,198.865327 C432.197499,198.865327 466,165.062825 466,123.365327 C466,81.667828 432.197499,47.8653266 390.5,47.8653266 C348.802501,47.8653266 315,81.667828 315,123.365327 C315,165.062825 348.802501,198.865327 390.5,198.865327 Z M390.5,167.865327 C415.076671,167.865327 435,147.941998 435,123.365327 C435,98.7886553 415.076671,78.8653266 390.5,78.8653266 C365.923329,78.8653266 346,98.7886553 346,123.365327 C346,147.941998 365.923329,167.865327 390.5,167.865327 Z" id="Oval-2" fill="#888888" sketch:type="MSShapeGroup"></path>
- <g id="D" transform="translate(157.000000, 0.000000)" fill="#888888" sketch:type="MSShapeGroup">
- <g id="d-+-Rectangle-1">
- <path d="M151.130367,122.770274 C151.131897,122.968444 151.132663,123.166796 151.132663,123.365327 C151.132663,165.062825 117.330162,198.865327 75.6326633,198.865327 C33.9351647,198.865327 0.132663317,165.062825 0.132663317,123.365327 C0.132663317,81.667828 33.9351647,47.8653266 75.6326633,47.8653266 C92.7270283,47.8653266 108.494494,53.5464573 121.149994,63.1236518 L121.149994,15.0040777 C121.149994,6.71755439 127.863901,0 136.149994,0 C144.434265,0 151.149994,6.72381102 151.149994,15.0040777 L151.149994,121.995922 C151.149994,122.255634 151.143399,122.513804 151.130367,122.770274 L151.130367,122.770274 Z M75.6326633,167.865327 C100.209335,167.865327 120.132663,147.941998 120.132663,123.365327 C120.132663,98.7886553 100.209335,78.8653266 75.6326633,78.8653266 C51.055992,78.8653266 31.1326633,98.7886553 31.1326633,123.365327 C31.1326633,147.941998 51.055992,167.865327 75.6326633,167.865327 Z" id="d"></path>
- </g>
- </g>
- <path d="M76.1924623,198.697487 C117.889961,198.697487 151.692462,164.894986 151.692462,123.197487 C151.692462,81.4999888 117.889961,47.6974874 76.1924623,47.6974874 C34.4949637,47.6974874 0.692462312,81.4999888 0.692462312,123.197487 C0.692462312,164.894986 34.4949637,198.697487 76.1924623,198.697487 Z M75.5,168 C100.076671,168 120,148.076671 120,123.5 C120,98.9233286 100.076671,79 75.5,79 C50.9233286,79 31,98.9233286 31,123.5 C31,148.076671 50.9233286,168 75.5,168 Z" id="Oval-1" fill="#9C5789" sketch:type="MSShapeGroup"></path>
- </g>
- <g id="odoo_logo_white" sketch:type="MSLayerGroup" transform="translate(627.000000, 1.000000)" fill="#FFFFFF">
- <path d="M550.5,198.865327 C592.197499,198.865327 626,165.062825 626,123.365327 C626,81.667828 592.197499,47.8653266 550.5,47.8653266 C508.802501,47.8653266 475,81.667828 475,123.365327 C475,165.062825 508.802501,198.865327 550.5,198.865327 Z M550.5,167.865327 C575.076671,167.865327 595,147.941998 595,123.365327 C595,98.7886553 575.076671,78.8653266 550.5,78.8653266 C525.923329,78.8653266 506,98.7886553 506,123.365327 C506,147.941998 525.923329,167.865327 550.5,167.865327 Z" id="Oval-3" sketch:type="MSShapeGroup"></path>
- <path d="M390.5,198.865327 C432.197499,198.865327 466,165.062825 466,123.365327 C466,81.667828 432.197499,47.8653266 390.5,47.8653266 C348.802501,47.8653266 315,81.667828 315,123.365327 C315,165.062825 348.802501,198.865327 390.5,198.865327 Z M390.5,167.865327 C415.076671,167.865327 435,147.941998 435,123.365327 C435,98.7886553 415.076671,78.8653266 390.5,78.8653266 C365.923329,78.8653266 346,98.7886553 346,123.365327 C346,147.941998 365.923329,167.865327 390.5,167.865327 Z" id="Oval-2" sketch:type="MSShapeGroup"></path>
- <g id="D" transform="translate(157.000000, 0.000000)" sketch:type="MSShapeGroup">
- <g id="d-+-Rectangle-1">
- <path d="M151.130367,122.770274 C151.131897,122.968444 151.132663,123.166796 151.132663,123.365327 C151.132663,165.062825 117.330162,198.865327 75.6326633,198.865327 C33.9351647,198.865327 0.132663317,165.062825 0.132663317,123.365327 C0.132663317,81.667828 33.9351647,47.8653266 75.6326633,47.8653266 C92.7270283,47.8653266 108.494494,53.5464573 121.149994,63.1236518 L121.149994,15.0040777 C121.149994,6.71755439 127.863901,0 136.149994,0 C144.434265,0 151.149994,6.72381102 151.149994,15.0040777 L151.149994,121.995922 C151.149994,122.255634 151.143399,122.513804 151.130367,122.770274 L151.130367,122.770274 Z M75.6326633,167.865327 C100.209335,167.865327 120.132663,147.941998 120.132663,123.365327 C120.132663,98.7886553 100.209335,78.8653266 75.6326633,78.8653266 C51.055992,78.8653266 31.1326633,98.7886553 31.1326633,123.365327 C31.1326633,147.941998 51.055992,167.865327 75.6326633,167.865327 Z" id="d"></path>
- </g>
- </g>
- <path d="M76.1924623,198.697487 C117.889961,198.697487 151.692462,164.894986 151.692462,123.197487 C151.692462,81.4999888 117.889961,47.6974874 76.1924623,47.6974874 C34.4949637,47.6974874 0.692462312,81.4999888 0.692462312,123.197487 C0.692462312,164.894986 34.4949637,198.697487 76.1924623,198.697487 Z M75.5,168 C100.076671,168 120,148.076671 120,123.5 C120,98.9233286 100.076671,79 75.5,79 C50.9233286,79 31,98.9233286 31,123.5 C31,148.076671 50.9233286,168 75.5,168 Z" id="Oval-1" sketch:type="MSShapeGroup"></path>
- </g>
- </g>
- </g>
-</svg> \ No newline at end of file
diff --git a/doc/_extensions/odoo_ext/static/img/logos/odoo_logo_small.png b/doc/_extensions/odoo_ext/static/img/logos/odoo_logo_small.png
deleted file mode 100644
index 49ff16ac50d..00000000000
--- a/doc/_extensions/odoo_ext/static/img/logos/odoo_logo_small.png
+++ /dev/null
Binary files differ
diff --git a/doc/_extensions/odoo_ext/static/img/odoo_logo_rgb.png b/doc/_extensions/odoo_ext/static/img/odoo_logo_rgb.png
deleted file mode 100644
index 1776dbd0e99..00000000000
--- a/doc/_extensions/odoo_ext/static/img/odoo_logo_rgb.png
+++ /dev/null
Binary files differ
diff --git a/doc/_extensions/odoo_ext/static/img/odoo_logo_white.png b/doc/_extensions/odoo_ext/static/img/odoo_logo_white.png
deleted file mode 100644
index 528d485f2fa..00000000000
--- a/doc/_extensions/odoo_ext/static/img/odoo_logo_white.png
+++ /dev/null
Binary files differ
diff --git a/doc/_extensions/odoo_ext/static/index.less b/doc/_extensions/odoo_ext/static/index.less
deleted file mode 100644
index 9d13250ccf8..00000000000
--- a/doc/_extensions/odoo_ext/static/index.less
+++ /dev/null
@@ -1,114 +0,0 @@
-// ================================================
-// ======= Index pages (covers and toctree) =======
-// ================================================
-
-#wrap.index {
- @media screen and (min-width: @screen-md-min) {
- > .card.top {
- padding: 10% 0 2%;
- }
- }
-
- > main.index {
- margin: 10px auto;
-
- .o_content {
- box-shadow: none;
- background: none;
- }
- }
-}
-
-main.index {
- .toc-section h2 {
- // section title
- padding: 0 0 4px;
- border-bottom: 1px solid @gray-lighter;
- margin: 1.4em 0 0.8em;
- font-size: 16px;
- font-family: @font-family-base;
- letter-spacing: 0;
- font-weight: bold;
- color: @text-muted;
- }
-
- .card {
- border-radius: 4px;
- position: relative;
- overflow: hidden;
- margin-bottom: @card_margin-bottom;
- padding-top: 56%;
- background-color: @doc_paper;
- .deep-1;
-
- .card-img {
- span {
- display: block;
- background-size: cover;
- background-position: 50%;
- .square(100%);
- }
- }
-
- figcaption {
- color: @text-color;
- box-shadow: inset 0 1px 0 @gray-lighter;
- font-weight: bold;
- line-height: 1.2;
- font-size: 14px;
- background-color: white;
- padding: 8px 12px 6px;
- .o-position-absolute(0, -1px, auto, -1px);
- }
- }
-
- .toc-single-entry .card figcaption {
- @media screen and(min-width: @screen-md) {
- font-size: 1.5em;
- padding: 20px 15px;
- }
- }
-}
-
-.toctree-wrapper > ul {
- list-style: none;
- padding: 0;
-
- li {
- line-height: 1.4;
-
- &.toctree-l1, &.toctree-l3 {
- padding-left: 0;
-
- &:before {
- content: none;
- }
-
- &:first-child {
- margin-top: 0;
- }
- }
-
- &.toctree-l1 {
- margin: 0 0 15px;
-
- > span {
- font-size: 21px;
- }
- }
-
- &.toctree-l2 {
- > span {
- font-weight: @fw_medium;
- }
-
- > ul {
- margin: 0 0 15px;
-
- &:empty {
- display: none;
- }
- }
- }
- }
-} \ No newline at end of file
diff --git a/doc/_extensions/odoo_ext/static/jquery.min.js b/doc/_extensions/odoo_ext/static/jquery.min.js
deleted file mode 100644
index 25714ed29ab..00000000000
--- a/doc/_extensions/odoo_ext/static/jquery.min.js
+++ /dev/null
@@ -1,4 +0,0 @@
-/*! jQuery v2.1.3 | (c) 2005, 2014 jQuery Foundation, Inc. | jquery.org/license */
-!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=c.slice,e=c.concat,f=c.push,g=c.indexOf,h={},i=h.toString,j=h.hasOwnProperty,k={},l=a.document,m="2.1.3",n=function(a,b){return new n.fn.init(a,b)},o=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,p=/^-ms-/,q=/-([\da-z])/gi,r=function(a,b){return b.toUpperCase()};n.fn=n.prototype={jquery:m,constructor:n,selector:"",length:0,toArray:function(){return d.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:d.call(this)},pushStack:function(a){var b=n.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return n.each(this,a,b)},map:function(a){return this.pushStack(n.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:c.sort,splice:c.splice},n.extend=n.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||n.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(a=arguments[h]))for(b in a)c=g[b],d=a[b],g!==d&&(j&&d&&(n.isPlainObject(d)||(e=n.isArray(d)))?(e?(e=!1,f=c&&n.isArray(c)?c:[]):f=c&&n.isPlainObject(c)?c:{},g[b]=n.extend(j,f,d)):void 0!==d&&(g[b]=d));return g},n.extend({expando:"jQuery"+(m+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===n.type(a)},isArray:Array.isArray,isWindow:function(a){return null!=a&&a===a.window},isNumeric:function(a){return!n.isArray(a)&&a-parseFloat(a)+1>=0},isPlainObject:function(a){return"object"!==n.type(a)||a.nodeType||n.isWindow(a)?!1:a.constructor&&!j.call(a.constructor.prototype,"isPrototypeOf")?!1:!0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?h[i.call(a)]||"object":typeof a},globalEval:function(a){var b,c=eval;a=n.trim(a),a&&(1===a.indexOf("use strict")?(b=l.createElement("script"),b.text=a,l.head.appendChild(b).parentNode.removeChild(b)):c(a))},camelCase:function(a){return a.replace(p,"ms-").replace(q,r)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,c){var d,e=0,f=a.length,g=s(a);if(c){if(g){for(;f>e;e++)if(d=b.apply(a[e],c),d===!1)break}else for(e in a)if(d=b.apply(a[e],c),d===!1)break}else if(g){for(;f>e;e++)if(d=b.call(a[e],e,a[e]),d===!1)break}else for(e in a)if(d=b.call(a[e],e,a[e]),d===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(o,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(s(Object(a))?n.merge(c,"string"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){return null==b?-1:g.call(b,a,c)},merge:function(a,b){for(var c=+b.length,d=0,e=a.length;c>d;d++)a[e++]=b[d];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,f=0,g=a.length,h=s(a),i=[];if(h)for(;g>f;f++)d=b(a[f],f,c),null!=d&&i.push(d);else for(f in a)d=b(a[f],f,c),null!=d&&i.push(d);return e.apply([],i)},guid:1,proxy:function(a,b){var c,e,f;return"string"==typeof b&&(c=a[b],b=a,a=c),n.isFunction(a)?(e=d.call(arguments,2),f=function(){return a.apply(b||this,e.concat(d.call(arguments)))},f.guid=a.guid=a.guid||n.guid++,f):void 0},now:Date.now,support:k}),n.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(a,b){h["[object "+b+"]"]=b.toLowerCase()});function s(a){var b=a.length,c=n.type(a);return"function"===c||n.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var t=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=hb(),z=hb(),A=hb(),B=function(a,b){return a===b&&(l=!0),0},C=1<<31,D={}.hasOwnProperty,E=[],F=E.pop,G=E.push,H=E.push,I=E.slice,J=function(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return c;return-1},K="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",L="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",N=M.replace("w","w#"),O="\\["+L+"*("+M+")(?:"+L+"*([*^$|!~]?=)"+L+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+N+"))|)"+L+"*\\]",P=":("+M+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+O+")*)|.*)\\)|)",Q=new RegExp(L+"+","g"),R=new RegExp("^"+L+"+|((?:^|[^\\\\])(?:\\\\.)*)"+L+"+$","g"),S=new RegExp("^"+L+"*,"+L+"*"),T=new RegExp("^"+L+"*([>+~]|"+L+")"+L+"*"),U=new RegExp("="+L+"*([^\\]'\"]*?)"+L+"*\\]","g"),V=new RegExp(P),W=new RegExp("^"+N+"$"),X={ID:new RegExp("^#("+M+")"),CLASS:new RegExp("^\\.("+M+")"),TAG:new RegExp("^("+M.replace("w","w*")+")"),ATTR:new RegExp("^"+O),PSEUDO:new RegExp("^"+P),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+L+"*(even|odd|(([+-]|)(\\d*)n|)"+L+"*(?:([+-]|)"+L+"*(\\d+)|))"+L+"*\\)|)","i"),bool:new RegExp("^(?:"+K+")$","i"),needsContext:new RegExp("^"+L+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+L+"*((?:-\\d)?\\d*)"+L+"*\\)|)(?=[^-]|$)","i")},Y=/^(?:input|select|textarea|button)$/i,Z=/^h\d$/i,$=/^[^{]+\{\s*\[native \w/,_=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ab=/[+~]/,bb=/'|\\/g,cb=new RegExp("\\\\([\\da-f]{1,6}"+L+"?|("+L+")|.)","ig"),db=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},eb=function(){m()};try{H.apply(E=I.call(v.childNodes),v.childNodes),E[v.childNodes.length].nodeType}catch(fb){H={apply:E.length?function(a,b){G.apply(a,I.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function gb(a,b,d,e){var f,h,j,k,l,o,r,s,w,x;if((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,d=d||[],k=b.nodeType,"string"!=typeof a||!a||1!==k&&9!==k&&11!==k)return d;if(!e&&p){if(11!==k&&(f=_.exec(a)))if(j=f[1]){if(9===k){if(h=b.getElementById(j),!h||!h.parentNode)return d;if(h.id===j)return d.push(h),d}else if(b.ownerDocument&&(h=b.ownerDocument.getElementById(j))&&t(b,h)&&h.id===j)return d.push(h),d}else{if(f[2])return H.apply(d,b.getElementsByTagName(a)),d;if((j=f[3])&&c.getElementsByClassName)return H.apply(d,b.getElementsByClassName(j)),d}if(c.qsa&&(!q||!q.test(a))){if(s=r=u,w=b,x=1!==k&&a,1===k&&"object"!==b.nodeName.toLowerCase()){o=g(a),(r=b.getAttribute("id"))?s=r.replace(bb,"\\$&"):b.setAttribute("id",s),s="[id='"+s+"'] ",l=o.length;while(l--)o[l]=s+rb(o[l]);w=ab.test(a)&&pb(b.parentNode)||b,x=o.join(",")}if(x)try{return H.apply(d,w.querySelectorAll(x)),d}catch(y){}finally{r||b.removeAttribute("id")}}}return i(a.replace(R,"$1"),b,d,e)}function hb(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ib(a){return a[u]=!0,a}function jb(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function kb(a,b){var c=a.split("|"),e=a.length;while(e--)d.attrHandle[c[e]]=b}function lb(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||C)-(~a.sourceIndex||C);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function mb(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function nb(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function ob(a){return ib(function(b){return b=+b,ib(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function pb(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=gb.support={},f=gb.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=gb.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=g.documentElement,e=g.defaultView,e&&e!==e.top&&(e.addEventListener?e.addEventListener("unload",eb,!1):e.attachEvent&&e.attachEvent("onunload",eb)),p=!f(g),c.attributes=jb(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=jb(function(a){return a.appendChild(g.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=$.test(g.getElementsByClassName),c.getById=jb(function(a){return o.appendChild(a).id=u,!g.getElementsByName||!g.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c&&c.parentNode?[c]:[]}},d.filter.ID=function(a){var b=a.replace(cb,db);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(cb,db);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=$.test(g.querySelectorAll))&&(jb(function(a){o.appendChild(a).innerHTML="<a id='"+u+"'></a><select id='"+u+"-\f]' msallowcapture=''><option selected=''></option></select>",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+L+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+L+"*(?:value|"+K+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),jb(function(a){var b=g.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+L+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=$.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&jb(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",P)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=$.test(o.compareDocumentPosition),t=b||$.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===g||a.ownerDocument===v&&t(v,a)?-1:b===g||b.ownerDocument===v&&t(v,b)?1:k?J(k,a)-J(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,h=[a],i=[b];if(!e||!f)return a===g?-1:b===g?1:e?-1:f?1:k?J(k,a)-J(k,b):0;if(e===f)return lb(a,b);c=a;while(c=c.parentNode)h.unshift(c);c=b;while(c=c.parentNode)i.unshift(c);while(h[d]===i[d])d++;return d?lb(h[d],i[d]):h[d]===v?-1:i[d]===v?1:0},g):n},gb.matches=function(a,b){return gb(a,null,null,b)},gb.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(U,"='$1']"),!(!c.matchesSelector||!p||r&&r.test(b)||q&&q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return gb(b,n,null,[a]).length>0},gb.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},gb.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&D.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},gb.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},gb.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=gb.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=gb.selectors={cacheLength:50,createPseudo:ib,match:X,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(cb,db),a[3]=(a[3]||a[4]||a[5]||"").replace(cb,db),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||gb.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&gb.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return X.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&V.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(cb,db).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+L+")"+a+"("+L+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=gb.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(Q," ")+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h;if(q){if(f){while(p){l=b;while(l=l[p])if(h?l.nodeName.toLowerCase()===r:1===l.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){k=q[u]||(q[u]={}),j=k[a]||[],n=j[0]===w&&j[1],m=j[0]===w&&j[2],l=n&&q.childNodes[n];while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if(1===l.nodeType&&++m&&l===b){k[a]=[w,n,m];break}}else if(s&&(j=(b[u]||(b[u]={}))[a])&&j[0]===w)m=j[1];else while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if((h?l.nodeName.toLowerCase()===r:1===l.nodeType)&&++m&&(s&&((l[u]||(l[u]={}))[a]=[w,m]),l===b))break;return m-=e,m===d||m%d===0&&m/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||gb.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ib(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=J(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ib(function(a){var b=[],c=[],d=h(a.replace(R,"$1"));return d[u]?ib(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ib(function(a){return function(b){return gb(a,b).length>0}}),contains:ib(function(a){return a=a.replace(cb,db),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ib(function(a){return W.test(a||"")||gb.error("unsupported lang: "+a),a=a.replace(cb,db).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Z.test(a.nodeName)},input:function(a){return Y.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:ob(function(){return[0]}),last:ob(function(a,b){return[b-1]}),eq:ob(function(a,b,c){return[0>c?c+b:c]}),even:ob(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:ob(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:ob(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:ob(function(a,b,c){for(var d=0>c?c+b:c;++d<b;)a.push(d);return a})}},d.pseudos.nth=d.pseudos.eq;for(b in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})d.pseudos[b]=mb(b);for(b in{submit:!0,reset:!0})d.pseudos[b]=nb(b);function qb(){}qb.prototype=d.filters=d.pseudos,d.setFilters=new qb,g=gb.tokenize=function(a,b){var c,e,f,g,h,i,j,k=z[a+" "];if(k)return b?0:k.slice(0);h=a,i=[],j=d.preFilter;while(h){(!c||(e=S.exec(h)))&&(e&&(h=h.slice(e[0].length)||h),i.push(f=[])),c=!1,(e=T.exec(h))&&(c=e.shift(),f.push({value:c,type:e[0].replace(R," ")}),h=h.slice(c.length));for(g in d.filter)!(e=X[g].exec(h))||j[g]&&!(e=j[g](e))||(c=e.shift(),f.push({value:c,type:g,matches:e}),h=h.slice(c.length));if(!c)break}return b?h.length:h?gb.error(a):z(a,i).slice(0)};function rb(a){for(var b=0,c=a.length,d="";c>b;b++)d+=a[b].value;return d}function sb(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(i=b[u]||(b[u]={}),(h=i[d])&&h[0]===w&&h[1]===f)return j[2]=h[2];if(i[d]=j,j[2]=a(b,c,g))return!0}}}function tb(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function ub(a,b,c){for(var d=0,e=b.length;e>d;d++)gb(a,b[d],c);return c}function vb(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(!c||c(f,d,e))&&(g.push(f),j&&b.push(h));return g}function wb(a,b,c,d,e,f){return d&&!d[u]&&(d=wb(d)),e&&!e[u]&&(e=wb(e,f)),ib(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||ub(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:vb(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=vb(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?J(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=vb(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):H.apply(g,r)})}function xb(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=sb(function(a){return a===b},h,!0),l=sb(function(a){return J(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];f>i;i++)if(c=d.relative[a[i].type])m=[sb(tb(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return wb(i>1&&tb(m),i>1&&rb(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(R,"$1"),c,e>i&&xb(a.slice(i,e)),f>e&&xb(a=a.slice(e)),f>e&&rb(a))}m.push(c)}return tb(m)}function yb(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,m,o,p=0,q="0",r=f&&[],s=[],t=j,u=f||e&&d.find.TAG("*",k),v=w+=null==t?1:Math.random()||.1,x=u.length;for(k&&(j=g!==n&&g);q!==x&&null!=(l=u[q]);q++){if(e&&l){m=0;while(o=a[m++])if(o(l,g,h)){i.push(l);break}k&&(w=v)}c&&((l=!o&&l)&&p--,f&&r.push(l))}if(p+=q,c&&q!==p){m=0;while(o=b[m++])o(r,s,g,h);if(f){if(p>0)while(q--)r[q]||s[q]||(s[q]=F.call(i));s=vb(s)}H.apply(i,s),k&&!f&&s.length>0&&p+b.length>1&&gb.uniqueSort(i)}return k&&(w=v,j=t),r};return c?ib(f):f}return h=gb.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=xb(b[c]),f[u]?d.push(f):e.push(f);f=A(a,yb(e,d)),f.selector=a}return f},i=gb.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(cb,db),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=X.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(cb,db),ab.test(j[0].type)&&pb(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&rb(j),!a)return H.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,ab.test(a)&&pb(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=jb(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),jb(function(a){return a.innerHTML="<a href='#'></a>","#"===a.firstChild.getAttribute("href")})||kb("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&jb(function(a){return a.innerHTML="<input/>",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||kb("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),jb(function(a){return null==a.getAttribute("disabled")})||kb(K,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),gb}(a);n.find=t,n.expr=t.selectors,n.expr[":"]=n.expr.pseudos,n.unique=t.uniqueSort,n.text=t.getText,n.isXMLDoc=t.isXML,n.contains=t.contains;var u=n.expr.match.needsContext,v=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,w=/^.[^:#\[\.,]*$/;function x(a,b,c){if(n.isFunction(b))return n.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return n.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(w.test(b))return n.filter(b,a,c);b=n.filter(b,a)}return n.grep(a,function(a){return g.call(b,a)>=0!==c})}n.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?n.find.matchesSelector(d,a)?[d]:[]:n.find.matches(a,n.grep(b,function(a){return 1===a.nodeType}))},n.fn.extend({find:function(a){var b,c=this.length,d=[],e=this;if("string"!=typeof a)return this.pushStack(n(a).filter(function(){for(b=0;c>b;b++)if(n.contains(e[b],this))return!0}));for(b=0;c>b;b++)n.find(a,e[b],d);return d=this.pushStack(c>1?n.unique(d):d),d.selector=this.selector?this.selector+" "+a:a,d},filter:function(a){return this.pushStack(x(this,a||[],!1))},not:function(a){return this.pushStack(x(this,a||[],!0))},is:function(a){return!!x(this,"string"==typeof a&&u.test(a)?n(a):a||[],!1).length}});var y,z=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,A=n.fn.init=function(a,b){var c,d;if(!a)return this;if("string"==typeof a){if(c="<"===a[0]&&">"===a[a.length-1]&&a.length>=3?[null,a,null]:z.exec(a),!c||!c[1]&&b)return!b||b.jquery?(b||y).find(a):this.constructor(b).find(a);if(c[1]){if(b=b instanceof n?b[0]:b,n.merge(this,n.parseHTML(c[1],b&&b.nodeType?b.ownerDocument||b:l,!0)),v.test(c[1])&&n.isPlainObject(b))for(c in b)n.isFunction(this[c])?this[c](b[c]):this.attr(c,b[c]);return this}return d=l.getElementById(c[2]),d&&d.parentNode&&(this.length=1,this[0]=d),this.context=l,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):n.isFunction(a)?"undefined"!=typeof y.ready?y.ready(a):a(n):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),n.makeArray(a,this))};A.prototype=n.fn,y=n(l);var B=/^(?:parents|prev(?:Until|All))/,C={children:!0,contents:!0,next:!0,prev:!0};n.extend({dir:function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&n(a).is(c))break;d.push(a)}return d},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}}),n.fn.extend({has:function(a){var b=n(a,this),c=b.length;return this.filter(function(){for(var a=0;c>a;a++)if(n.contains(this,b[a]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=u.test(a)||"string"!=typeof a?n(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&n.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?n.unique(f):f)},index:function(a){return a?"string"==typeof a?g.call(n(a),this[0]):g.call(this,a.jquery?a[0]:a):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(n.unique(n.merge(this.get(),n(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function D(a,b){while((a=a[b])&&1!==a.nodeType);return a}n.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return n.dir(a,"parentNode")},parentsUntil:function(a,b,c){return n.dir(a,"parentNode",c)},next:function(a){return D(a,"nextSibling")},prev:function(a){return D(a,"previousSibling")},nextAll:function(a){return n.dir(a,"nextSibling")},prevAll:function(a){return n.dir(a,"previousSibling")},nextUntil:function(a,b,c){return n.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return n.dir(a,"previousSibling",c)},siblings:function(a){return n.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return n.sibling(a.firstChild)},contents:function(a){return a.contentDocument||n.merge([],a.childNodes)}},function(a,b){n.fn[a]=function(c,d){var e=n.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=n.filter(d,e)),this.length>1&&(C[a]||n.unique(e),B.test(a)&&e.reverse()),this.pushStack(e)}});var E=/\S+/g,F={};function G(a){var b=F[a]={};return n.each(a.match(E)||[],function(a,c){b[c]=!0}),b}n.Callbacks=function(a){a="string"==typeof a?F[a]||G(a):n.extend({},a);var b,c,d,e,f,g,h=[],i=!a.once&&[],j=function(l){for(b=a.memory&&l,c=!0,g=e||0,e=0,f=h.length,d=!0;h&&f>g;g++)if(h[g].apply(l[0],l[1])===!1&&a.stopOnFalse){b=!1;break}d=!1,h&&(i?i.length&&j(i.shift()):b?h=[]:k.disable())},k={add:function(){if(h){var c=h.length;!function g(b){n.each(b,function(b,c){var d=n.type(c);"function"===d?a.unique&&k.has(c)||h.push(c):c&&c.length&&"string"!==d&&g(c)})}(arguments),d?f=h.length:b&&(e=c,j(b))}return this},remove:function(){return h&&n.each(arguments,function(a,b){var c;while((c=n.inArray(b,h,c))>-1)h.splice(c,1),d&&(f>=c&&f--,g>=c&&g--)}),this},has:function(a){return a?n.inArray(a,h)>-1:!(!h||!h.length)},empty:function(){return h=[],f=0,this},disable:function(){return h=i=b=void 0,this},disabled:function(){return!h},lock:function(){return i=void 0,b||k.disable(),this},locked:function(){return!i},fireWith:function(a,b){return!h||c&&!i||(b=b||[],b=[a,b.slice?b.slice():b],d?i.push(b):j(b)),this},fire:function(){return k.fireWith(this,arguments),this},fired:function(){return!!c}};return k},n.extend({Deferred:function(a){var b=[["resolve","done",n.Callbacks("once memory"),"resolved"],["reject","fail",n.Callbacks("once memory"),"rejected"],["notify","progress",n.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return n.Deferred(function(c){n.each(b,function(b,f){var g=n.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&n.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?n.extend(a,d):d}},e={};return d.pipe=d.then,n.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=d.call(arguments),e=c.length,f=1!==e||a&&n.isFunction(a.promise)?e:0,g=1===f?a:n.Deferred(),h=function(a,b,c){return function(e){b[a]=this,c[a]=arguments.length>1?d.call(arguments):e,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(e>1)for(i=new Array(e),j=new Array(e),k=new Array(e);e>b;b++)c[b]&&n.isFunction(c[b].promise)?c[b].promise().done(h(b,k,c)).fail(g.reject).progress(h(b,j,i)):--f;return f||g.resolveWith(k,c),g.promise()}});var H;n.fn.ready=function(a){return n.ready.promise().done(a),this},n.extend({isReady:!1,readyWait:1,holdReady:function(a){a?n.readyWait++:n.ready(!0)},ready:function(a){(a===!0?--n.readyWait:n.isReady)||(n.isReady=!0,a!==!0&&--n.readyWait>0||(H.resolveWith(l,[n]),n.fn.triggerHandler&&(n(l).triggerHandler("ready"),n(l).off("ready"))))}});function I(){l.removeEventListener("DOMContentLoaded",I,!1),a.removeEventListener("load",I,!1),n.ready()}n.ready.promise=function(b){return H||(H=n.Deferred(),"complete"===l.readyState?setTimeout(n.ready):(l.addEventListener("DOMContentLoaded",I,!1),a.addEventListener("load",I,!1))),H.promise(b)},n.ready.promise();var J=n.access=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===n.type(c)){e=!0;for(h in c)n.access(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,n.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(n(a),c)})),b))for(;i>h;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f};n.acceptData=function(a){return 1===a.nodeType||9===a.nodeType||!+a.nodeType};function K(){Object.defineProperty(this.cache={},0,{get:function(){return{}}}),this.expando=n.expando+K.uid++}K.uid=1,K.accepts=n.acceptData,K.prototype={key:function(a){if(!K.accepts(a))return 0;var b={},c=a[this.expando];if(!c){c=K.uid++;try{b[this.expando]={value:c},Object.defineProperties(a,b)}catch(d){b[this.expando]=c,n.extend(a,b)}}return this.cache[c]||(this.cache[c]={}),c},set:function(a,b,c){var d,e=this.key(a),f=this.cache[e];if("string"==typeof b)f[b]=c;else if(n.isEmptyObject(f))n.extend(this.cache[e],b);else for(d in b)f[d]=b[d];return f},get:function(a,b){var c=this.cache[this.key(a)];return void 0===b?c:c[b]},access:function(a,b,c){var d;return void 0===b||b&&"string"==typeof b&&void 0===c?(d=this.get(a,b),void 0!==d?d:this.get(a,n.camelCase(b))):(this.set(a,b,c),void 0!==c?c:b)},remove:function(a,b){var c,d,e,f=this.key(a),g=this.cache[f];if(void 0===b)this.cache[f]={};else{n.isArray(b)?d=b.concat(b.map(n.camelCase)):(e=n.camelCase(b),b in g?d=[b,e]:(d=e,d=d in g?[d]:d.match(E)||[])),c=d.length;while(c--)delete g[d[c]]}},hasData:function(a){return!n.isEmptyObject(this.cache[a[this.expando]]||{})},discard:function(a){a[this.expando]&&delete this.cache[a[this.expando]]}};var L=new K,M=new K,N=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,O=/([A-Z])/g;function P(a,b,c){var d;if(void 0===c&&1===a.nodeType)if(d="data-"+b.replace(O,"-$1").toLowerCase(),c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:N.test(c)?n.parseJSON(c):c}catch(e){}M.set(a,b,c)}else c=void 0;return c}n.extend({hasData:function(a){return M.hasData(a)||L.hasData(a)},data:function(a,b,c){return M.access(a,b,c)
-},removeData:function(a,b){M.remove(a,b)},_data:function(a,b,c){return L.access(a,b,c)},_removeData:function(a,b){L.remove(a,b)}}),n.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=M.get(f),1===f.nodeType&&!L.get(f,"hasDataAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=n.camelCase(d.slice(5)),P(f,d,e[d])));L.set(f,"hasDataAttrs",!0)}return e}return"object"==typeof a?this.each(function(){M.set(this,a)}):J(this,function(b){var c,d=n.camelCase(a);if(f&&void 0===b){if(c=M.get(f,a),void 0!==c)return c;if(c=M.get(f,d),void 0!==c)return c;if(c=P(f,d,void 0),void 0!==c)return c}else this.each(function(){var c=M.get(this,d);M.set(this,d,b),-1!==a.indexOf("-")&&void 0!==c&&M.set(this,a,b)})},null,b,arguments.length>1,null,!0)},removeData:function(a){return this.each(function(){M.remove(this,a)})}}),n.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=L.get(a,b),c&&(!d||n.isArray(c)?d=L.access(a,b,n.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=n.queue(a,b),d=c.length,e=c.shift(),f=n._queueHooks(a,b),g=function(){n.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return L.get(a,c)||L.access(a,c,{empty:n.Callbacks("once memory").add(function(){L.remove(a,[b+"queue",c])})})}}),n.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.length<c?n.queue(this[0],a):void 0===b?this:this.each(function(){var c=n.queue(this,a,b);n._queueHooks(this,a),"fx"===a&&"inprogress"!==c[0]&&n.dequeue(this,a)})},dequeue:function(a){return this.each(function(){n.dequeue(this,a)})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,b){var c,d=1,e=n.Deferred(),f=this,g=this.length,h=function(){--d||e.resolveWith(f,[f])};"string"!=typeof a&&(b=a,a=void 0),a=a||"fx";while(g--)c=L.get(f[g],a+"queueHooks"),c&&c.empty&&(d++,c.empty.add(h));return h(),e.promise(b)}});var Q=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,R=["Top","Right","Bottom","Left"],S=function(a,b){return a=b||a,"none"===n.css(a,"display")||!n.contains(a.ownerDocument,a)},T=/^(?:checkbox|radio)$/i;!function(){var a=l.createDocumentFragment(),b=a.appendChild(l.createElement("div")),c=l.createElement("input");c.setAttribute("type","radio"),c.setAttribute("checked","checked"),c.setAttribute("name","t"),b.appendChild(c),k.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,b.innerHTML="<textarea>x</textarea>",k.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue}();var U="undefined";k.focusinBubbles="onfocusin"in a;var V=/^key/,W=/^(?:mouse|pointer|contextmenu)|click/,X=/^(?:focusinfocus|focusoutblur)$/,Y=/^([^.]*)(?:\.(.+)|)$/;function Z(){return!0}function $(){return!1}function _(){try{return l.activeElement}catch(a){}}n.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=L.get(a);if(r){c.handler&&(f=c,c=f.handler,e=f.selector),c.guid||(c.guid=n.guid++),(i=r.events)||(i=r.events={}),(g=r.handle)||(g=r.handle=function(b){return typeof n!==U&&n.event.triggered!==b.type?n.event.dispatch.apply(a,arguments):void 0}),b=(b||"").match(E)||[""],j=b.length;while(j--)h=Y.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o&&(l=n.event.special[o]||{},o=(e?l.delegateType:l.bindType)||o,l=n.event.special[o]||{},k=n.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&n.expr.match.needsContext.test(e),namespace:p.join(".")},f),(m=i[o])||(m=i[o]=[],m.delegateCount=0,l.setup&&l.setup.call(a,d,p,g)!==!1||a.addEventListener&&a.addEventListener(o,g,!1)),l.add&&(l.add.call(a,k),k.handler.guid||(k.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,k):m.push(k),n.event.global[o]=!0)}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=L.hasData(a)&&L.get(a);if(r&&(i=r.events)){b=(b||"").match(E)||[""],j=b.length;while(j--)if(h=Y.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=n.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,m=i[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),g=f=m.length;while(f--)k=m[f],!e&&q!==k.origType||c&&c.guid!==k.guid||h&&!h.test(k.namespace)||d&&d!==k.selector&&("**"!==d||!k.selector)||(m.splice(f,1),k.selector&&m.delegateCount--,l.remove&&l.remove.call(a,k));g&&!m.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||n.removeEvent(a,o,r.handle),delete i[o])}else for(o in i)n.event.remove(a,o+b[j],c,d,!0);n.isEmptyObject(i)&&(delete r.handle,L.remove(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,m,o,p=[d||l],q=j.call(b,"type")?b.type:b,r=j.call(b,"namespace")?b.namespace.split("."):[];if(g=h=d=d||l,3!==d.nodeType&&8!==d.nodeType&&!X.test(q+n.event.triggered)&&(q.indexOf(".")>=0&&(r=q.split("."),q=r.shift(),r.sort()),k=q.indexOf(":")<0&&"on"+q,b=b[n.expando]?b:new n.Event(q,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=r.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+r.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:n.makeArray(c,[b]),o=n.event.special[q]||{},e||!o.trigger||o.trigger.apply(d,c)!==!1)){if(!e&&!o.noBubble&&!n.isWindow(d)){for(i=o.delegateType||q,X.test(i+q)||(g=g.parentNode);g;g=g.parentNode)p.push(g),h=g;h===(d.ownerDocument||l)&&p.push(h.defaultView||h.parentWindow||a)}f=0;while((g=p[f++])&&!b.isPropagationStopped())b.type=f>1?i:o.bindType||q,m=(L.get(g,"events")||{})[b.type]&&L.get(g,"handle"),m&&m.apply(g,c),m=k&&g[k],m&&m.apply&&n.acceptData(g)&&(b.result=m.apply(g,c),b.result===!1&&b.preventDefault());return b.type=q,e||b.isDefaultPrevented()||o._default&&o._default.apply(p.pop(),c)!==!1||!n.acceptData(d)||k&&n.isFunction(d[q])&&!n.isWindow(d)&&(h=d[k],h&&(d[k]=null),n.event.triggered=q,d[q](),n.event.triggered=void 0,h&&(d[k]=h)),b.result}},dispatch:function(a){a=n.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(L.get(this,"events")||{})[a.type]||[],k=n.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=n.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,c=0;while((g=f.handlers[c++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(g.namespace))&&(a.handleObj=g,a.data=g.data,e=((n.event.special[g.origType]||{}).handle||g.handler).apply(f.elem,i),void 0!==e&&(a.result=e)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(!a.button||"click"!==a.type))for(;i!==this;i=i.parentNode||this)if(i.disabled!==!0||"click"!==a.type){for(d=[],c=0;h>c;c++)f=b[c],e=f.selector+" ",void 0===d[e]&&(d[e]=f.needsContext?n(e,this).index(i)>=0:n.find(e,this,null,[i]).length),d[e]&&d.push(f);d.length&&g.push({elem:i,handlers:d})}return h<b.length&&g.push({elem:this,handlers:b.slice(h)}),g},props:"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){return null==a.which&&(a.which=null!=b.charCode?b.charCode:b.keyCode),a}},mouseHooks:{props:"button buttons clientX clientY offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,b){var c,d,e,f=b.button;return null==a.pageX&&null!=b.clientX&&(c=a.target.ownerDocument||l,d=c.documentElement,e=c.body,a.pageX=b.clientX+(d&&d.scrollLeft||e&&e.scrollLeft||0)-(d&&d.clientLeft||e&&e.clientLeft||0),a.pageY=b.clientY+(d&&d.scrollTop||e&&e.scrollTop||0)-(d&&d.clientTop||e&&e.clientTop||0)),a.which||void 0===f||(a.which=1&f?1:2&f?3:4&f?2:0),a}},fix:function(a){if(a[n.expando])return a;var b,c,d,e=a.type,f=a,g=this.fixHooks[e];g||(this.fixHooks[e]=g=W.test(e)?this.mouseHooks:V.test(e)?this.keyHooks:{}),d=g.props?this.props.concat(g.props):this.props,a=new n.Event(f),b=d.length;while(b--)c=d[b],a[c]=f[c];return a.target||(a.target=l),3===a.target.nodeType&&(a.target=a.target.parentNode),g.filter?g.filter(a,f):a},special:{load:{noBubble:!0},focus:{trigger:function(){return this!==_()&&this.focus?(this.focus(),!1):void 0},delegateType:"focusin"},blur:{trigger:function(){return this===_()&&this.blur?(this.blur(),!1):void 0},delegateType:"focusout"},click:{trigger:function(){return"checkbox"===this.type&&this.click&&n.nodeName(this,"input")?(this.click(),!1):void 0},_default:function(a){return n.nodeName(a.target,"a")}},beforeunload:{postDispatch:function(a){void 0!==a.result&&a.originalEvent&&(a.originalEvent.returnValue=a.result)}}},simulate:function(a,b,c,d){var e=n.extend(new n.Event,c,{type:a,isSimulated:!0,originalEvent:{}});d?n.event.trigger(e,null,b):n.event.dispatch.call(b,e),e.isDefaultPrevented()&&c.preventDefault()}},n.removeEvent=function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)},n.Event=function(a,b){return this instanceof n.Event?(a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||void 0===a.defaultPrevented&&a.returnValue===!1?Z:$):this.type=a,b&&n.extend(this,b),this.timeStamp=a&&a.timeStamp||n.now(),void(this[n.expando]=!0)):new n.Event(a,b)},n.Event.prototype={isDefaultPrevented:$,isPropagationStopped:$,isImmediatePropagationStopped:$,preventDefault:function(){var a=this.originalEvent;this.isDefaultPrevented=Z,a&&a.preventDefault&&a.preventDefault()},stopPropagation:function(){var a=this.originalEvent;this.isPropagationStopped=Z,a&&a.stopPropagation&&a.stopPropagation()},stopImmediatePropagation:function(){var a=this.originalEvent;this.isImmediatePropagationStopped=Z,a&&a.stopImmediatePropagation&&a.stopImmediatePropagation(),this.stopPropagation()}},n.each({mouseenter:"mouseover",mouseleave:"mouseout",pointerenter:"pointerover",pointerleave:"pointerout"},function(a,b){n.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c,d=this,e=a.relatedTarget,f=a.handleObj;return(!e||e!==d&&!n.contains(d,e))&&(a.type=f.origType,c=f.handler.apply(this,arguments),a.type=b),c}}}),k.focusinBubbles||n.each({focus:"focusin",blur:"focusout"},function(a,b){var c=function(a){n.event.simulate(b,a.target,n.event.fix(a),!0)};n.event.special[b]={setup:function(){var d=this.ownerDocument||this,e=L.access(d,b);e||d.addEventListener(a,c,!0),L.access(d,b,(e||0)+1)},teardown:function(){var d=this.ownerDocument||this,e=L.access(d,b)-1;e?L.access(d,b,e):(d.removeEventListener(a,c,!0),L.remove(d,b))}}}),n.fn.extend({on:function(a,b,c,d,e){var f,g;if("object"==typeof a){"string"!=typeof b&&(c=c||b,b=void 0);for(g in a)this.on(g,b,c,a[g],e);return this}if(null==c&&null==d?(d=b,c=b=void 0):null==d&&("string"==typeof b?(d=c,c=void 0):(d=c,c=b,b=void 0)),d===!1)d=$;else if(!d)return this;return 1===e&&(f=d,d=function(a){return n().off(a),f.apply(this,arguments)},d.guid=f.guid||(f.guid=n.guid++)),this.each(function(){n.event.add(this,a,d,c,b)})},one:function(a,b,c,d){return this.on(a,b,c,d,1)},off:function(a,b,c){var d,e;if(a&&a.preventDefault&&a.handleObj)return d=a.handleObj,n(a.delegateTarget).off(d.namespace?d.origType+"."+d.namespace:d.origType,d.selector,d.handler),this;if("object"==typeof a){for(e in a)this.off(e,b,a[e]);return this}return(b===!1||"function"==typeof b)&&(c=b,b=void 0),c===!1&&(c=$),this.each(function(){n.event.remove(this,a,c,b)})},trigger:function(a,b){return this.each(function(){n.event.trigger(a,b,this)})},triggerHandler:function(a,b){var c=this[0];return c?n.event.trigger(a,b,c,!0):void 0}});var ab=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,bb=/<([\w:]+)/,cb=/<|&#?\w+;/,db=/<(?:script|style|link)/i,eb=/checked\s*(?:[^=]|=\s*.checked.)/i,fb=/^$|\/(?:java|ecma)script/i,gb=/^true\/(.*)/,hb=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,ib={option:[1,"<select multiple='multiple'>","</select>"],thead:[1,"<table>","</table>"],col:[2,"<table><colgroup>","</colgroup></table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:[0,"",""]};ib.optgroup=ib.option,ib.tbody=ib.tfoot=ib.colgroup=ib.caption=ib.thead,ib.th=ib.td;function jb(a,b){return n.nodeName(a,"table")&&n.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function kb(a){return a.type=(null!==a.getAttribute("type"))+"/"+a.type,a}function lb(a){var b=gb.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function mb(a,b){for(var c=0,d=a.length;d>c;c++)L.set(a[c],"globalEval",!b||L.get(b[c],"globalEval"))}function nb(a,b){var c,d,e,f,g,h,i,j;if(1===b.nodeType){if(L.hasData(a)&&(f=L.access(a),g=L.set(b,f),j=f.events)){delete g.handle,g.events={};for(e in j)for(c=0,d=j[e].length;d>c;c++)n.event.add(b,e,j[e][c])}M.hasData(a)&&(h=M.access(a),i=n.extend({},h),M.set(b,i))}}function ob(a,b){var c=a.getElementsByTagName?a.getElementsByTagName(b||"*"):a.querySelectorAll?a.querySelectorAll(b||"*"):[];return void 0===b||b&&n.nodeName(a,b)?n.merge([a],c):c}function pb(a,b){var c=b.nodeName.toLowerCase();"input"===c&&T.test(a.type)?b.checked=a.checked:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}n.extend({clone:function(a,b,c){var d,e,f,g,h=a.cloneNode(!0),i=n.contains(a.ownerDocument,a);if(!(k.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||n.isXMLDoc(a)))for(g=ob(h),f=ob(a),d=0,e=f.length;e>d;d++)pb(f[d],g[d]);if(b)if(c)for(f=f||ob(a),g=g||ob(h),d=0,e=f.length;e>d;d++)nb(f[d],g[d]);else nb(a,h);return g=ob(h,"script"),g.length>0&&mb(g,!i&&ob(a,"script")),h},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,k=b.createDocumentFragment(),l=[],m=0,o=a.length;o>m;m++)if(e=a[m],e||0===e)if("object"===n.type(e))n.merge(l,e.nodeType?[e]:e);else if(cb.test(e)){f=f||k.appendChild(b.createElement("div")),g=(bb.exec(e)||["",""])[1].toLowerCase(),h=ib[g]||ib._default,f.innerHTML=h[1]+e.replace(ab,"<$1></$2>")+h[2],j=h[0];while(j--)f=f.lastChild;n.merge(l,f.childNodes),f=k.firstChild,f.textContent=""}else l.push(b.createTextNode(e));k.textContent="",m=0;while(e=l[m++])if((!d||-1===n.inArray(e,d))&&(i=n.contains(e.ownerDocument,e),f=ob(k.appendChild(e),"script"),i&&mb(f),c)){j=0;while(e=f[j++])fb.test(e.type||"")&&c.push(e)}return k},cleanData:function(a){for(var b,c,d,e,f=n.event.special,g=0;void 0!==(c=a[g]);g++){if(n.acceptData(c)&&(e=c[L.expando],e&&(b=L.cache[e]))){if(b.events)for(d in b.events)f[d]?n.event.remove(c,d):n.removeEvent(c,d,b.handle);L.cache[e]&&delete L.cache[e]}delete M.cache[c[M.expando]]}}}),n.fn.extend({text:function(a){return J(this,function(a){return void 0===a?n.text(this):this.empty().each(function(){(1===this.nodeType||11===this.nodeType||9===this.nodeType)&&(this.textContent=a)})},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=jb(this,a);b.appendChild(a)}})},prepend:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=jb(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var c,d=a?n.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||n.cleanData(ob(c)),c.parentNode&&(b&&n.contains(c.ownerDocument,c)&&mb(ob(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++)1===a.nodeType&&(n.cleanData(ob(a,!1)),a.textContent="");return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return n.clone(this,a,b)})},html:function(a){return J(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a&&1===b.nodeType)return b.innerHTML;if("string"==typeof a&&!db.test(a)&&!ib[(bb.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(ab,"<$1></$2>");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(n.cleanData(ob(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=arguments[0];return this.domManip(arguments,function(b){a=this.parentNode,n.cleanData(ob(this)),a&&a.replaceChild(b,this)}),a&&(a.length||a.nodeType)?this:this.remove()},detach:function(a){return this.remove(a,!0)},domManip:function(a,b){a=e.apply([],a);var c,d,f,g,h,i,j=0,l=this.length,m=this,o=l-1,p=a[0],q=n.isFunction(p);if(q||l>1&&"string"==typeof p&&!k.checkClone&&eb.test(p))return this.each(function(c){var d=m.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(l&&(c=n.buildFragment(a,this[0].ownerDocument,!1,this),d=c.firstChild,1===c.childNodes.length&&(c=d),d)){for(f=n.map(ob(c,"script"),kb),g=f.length;l>j;j++)h=c,j!==o&&(h=n.clone(h,!0,!0),g&&n.merge(f,ob(h,"script"))),b.call(this[j],h,j);if(g)for(i=f[f.length-1].ownerDocument,n.map(f,lb),j=0;g>j;j++)h=f[j],fb.test(h.type||"")&&!L.access(h,"globalEval")&&n.contains(i,h)&&(h.src?n._evalUrl&&n._evalUrl(h.src):n.globalEval(h.textContent.replace(hb,"")))}return this}}),n.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){n.fn[a]=function(a){for(var c,d=[],e=n(a),g=e.length-1,h=0;g>=h;h++)c=h===g?this:this.clone(!0),n(e[h])[b](c),f.apply(d,c.get());return this.pushStack(d)}});var qb,rb={};function sb(b,c){var d,e=n(c.createElement(b)).appendTo(c.body),f=a.getDefaultComputedStyle&&(d=a.getDefaultComputedStyle(e[0]))?d.display:n.css(e[0],"display");return e.detach(),f}function tb(a){var b=l,c=rb[a];return c||(c=sb(a,b),"none"!==c&&c||(qb=(qb||n("<iframe frameborder='0' width='0' height='0'/>")).appendTo(b.documentElement),b=qb[0].contentDocument,b.write(),b.close(),c=sb(a,b),qb.detach()),rb[a]=c),c}var ub=/^margin/,vb=new RegExp("^("+Q+")(?!px)[a-z%]+$","i"),wb=function(b){return b.ownerDocument.defaultView.opener?b.ownerDocument.defaultView.getComputedStyle(b,null):a.getComputedStyle(b,null)};function xb(a,b,c){var d,e,f,g,h=a.style;return c=c||wb(a),c&&(g=c.getPropertyValue(b)||c[b]),c&&(""!==g||n.contains(a.ownerDocument,a)||(g=n.style(a,b)),vb.test(g)&&ub.test(b)&&(d=h.width,e=h.minWidth,f=h.maxWidth,h.minWidth=h.maxWidth=h.width=g,g=c.width,h.width=d,h.minWidth=e,h.maxWidth=f)),void 0!==g?g+"":g}function yb(a,b){return{get:function(){return a()?void delete this.get:(this.get=b).apply(this,arguments)}}}!function(){var b,c,d=l.documentElement,e=l.createElement("div"),f=l.createElement("div");if(f.style){f.style.backgroundClip="content-box",f.cloneNode(!0).style.backgroundClip="",k.clearCloneStyle="content-box"===f.style.backgroundClip,e.style.cssText="border:0;width:0;height:0;top:0;left:-9999px;margin-top:1px;position:absolute",e.appendChild(f);function g(){f.style.cssText="-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;display:block;margin-top:1%;top:1%;border:1px;padding:1px;width:4px;position:absolute",f.innerHTML="",d.appendChild(e);var g=a.getComputedStyle(f,null);b="1%"!==g.top,c="4px"===g.width,d.removeChild(e)}a.getComputedStyle&&n.extend(k,{pixelPosition:function(){return g(),b},boxSizingReliable:function(){return null==c&&g(),c},reliableMarginRight:function(){var b,c=f.appendChild(l.createElement("div"));return c.style.cssText=f.style.cssText="-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:0",c.style.marginRight=c.style.width="0",f.style.width="1px",d.appendChild(e),b=!parseFloat(a.getComputedStyle(c,null).marginRight),d.removeChild(e),f.removeChild(c),b}})}}(),n.swap=function(a,b,c,d){var e,f,g={};for(f in b)g[f]=a.style[f],a.style[f]=b[f];e=c.apply(a,d||[]);for(f in b)a.style[f]=g[f];return e};var zb=/^(none|table(?!-c[ea]).+)/,Ab=new RegExp("^("+Q+")(.*)$","i"),Bb=new RegExp("^([+-])=("+Q+")","i"),Cb={position:"absolute",visibility:"hidden",display:"block"},Db={letterSpacing:"0",fontWeight:"400"},Eb=["Webkit","O","Moz","ms"];function Fb(a,b){if(b in a)return b;var c=b[0].toUpperCase()+b.slice(1),d=b,e=Eb.length;while(e--)if(b=Eb[e]+c,b in a)return b;return d}function Gb(a,b,c){var d=Ab.exec(b);return d?Math.max(0,d[1]-(c||0))+(d[2]||"px"):b}function Hb(a,b,c,d,e){for(var f=c===(d?"border":"content")?4:"width"===b?1:0,g=0;4>f;f+=2)"margin"===c&&(g+=n.css(a,c+R[f],!0,e)),d?("content"===c&&(g-=n.css(a,"padding"+R[f],!0,e)),"margin"!==c&&(g-=n.css(a,"border"+R[f]+"Width",!0,e))):(g+=n.css(a,"padding"+R[f],!0,e),"padding"!==c&&(g+=n.css(a,"border"+R[f]+"Width",!0,e)));return g}function Ib(a,b,c){var d=!0,e="width"===b?a.offsetWidth:a.offsetHeight,f=wb(a),g="border-box"===n.css(a,"boxSizing",!1,f);if(0>=e||null==e){if(e=xb(a,b,f),(0>e||null==e)&&(e=a.style[b]),vb.test(e))return e;d=g&&(k.boxSizingReliable()||e===a.style[b]),e=parseFloat(e)||0}return e+Hb(a,b,c||(g?"border":"content"),d,f)+"px"}function Jb(a,b){for(var c,d,e,f=[],g=0,h=a.length;h>g;g++)d=a[g],d.style&&(f[g]=L.get(d,"olddisplay"),c=d.style.display,b?(f[g]||"none"!==c||(d.style.display=""),""===d.style.display&&S(d)&&(f[g]=L.access(d,"olddisplay",tb(d.nodeName)))):(e=S(d),"none"===c&&e||L.set(d,"olddisplay",e?c:n.css(d,"display"))));for(g=0;h>g;g++)d=a[g],d.style&&(b&&"none"!==d.style.display&&""!==d.style.display||(d.style.display=b?f[g]||"":"none"));return a}n.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=xb(a,"opacity");return""===c?"1":c}}}},cssNumber:{columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":"cssFloat"},style:function(a,b,c,d){if(a&&3!==a.nodeType&&8!==a.nodeType&&a.style){var e,f,g,h=n.camelCase(b),i=a.style;return b=n.cssProps[h]||(n.cssProps[h]=Fb(i,h)),g=n.cssHooks[b]||n.cssHooks[h],void 0===c?g&&"get"in g&&void 0!==(e=g.get(a,!1,d))?e:i[b]:(f=typeof c,"string"===f&&(e=Bb.exec(c))&&(c=(e[1]+1)*e[2]+parseFloat(n.css(a,b)),f="number"),null!=c&&c===c&&("number"!==f||n.cssNumber[h]||(c+="px"),k.clearCloneStyle||""!==c||0!==b.indexOf("background")||(i[b]="inherit"),g&&"set"in g&&void 0===(c=g.set(a,c,d))||(i[b]=c)),void 0)}},css:function(a,b,c,d){var e,f,g,h=n.camelCase(b);return b=n.cssProps[h]||(n.cssProps[h]=Fb(a.style,h)),g=n.cssHooks[b]||n.cssHooks[h],g&&"get"in g&&(e=g.get(a,!0,c)),void 0===e&&(e=xb(a,b,d)),"normal"===e&&b in Db&&(e=Db[b]),""===c||c?(f=parseFloat(e),c===!0||n.isNumeric(f)?f||0:e):e}}),n.each(["height","width"],function(a,b){n.cssHooks[b]={get:function(a,c,d){return c?zb.test(n.css(a,"display"))&&0===a.offsetWidth?n.swap(a,Cb,function(){return Ib(a,b,d)}):Ib(a,b,d):void 0},set:function(a,c,d){var e=d&&wb(a);return Gb(a,c,d?Hb(a,b,d,"border-box"===n.css(a,"boxSizing",!1,e),e):0)}}}),n.cssHooks.marginRight=yb(k.reliableMarginRight,function(a,b){return b?n.swap(a,{display:"inline-block"},xb,[a,"marginRight"]):void 0}),n.each({margin:"",padding:"",border:"Width"},function(a,b){n.cssHooks[a+b]={expand:function(c){for(var d=0,e={},f="string"==typeof c?c.split(" "):[c];4>d;d++)e[a+R[d]+b]=f[d]||f[d-2]||f[0];return e}},ub.test(a)||(n.cssHooks[a+b].set=Gb)}),n.fn.extend({css:function(a,b){return J(this,function(a,b,c){var d,e,f={},g=0;if(n.isArray(b)){for(d=wb(a),e=b.length;e>g;g++)f[b[g]]=n.css(a,b[g],!1,d);return f}return void 0!==c?n.style(a,b,c):n.css(a,b)},a,b,arguments.length>1)},show:function(){return Jb(this,!0)},hide:function(){return Jb(this)},toggle:function(a){return"boolean"==typeof a?a?this.show():this.hide():this.each(function(){S(this)?n(this).show():n(this).hide()})}});function Kb(a,b,c,d,e){return new Kb.prototype.init(a,b,c,d,e)}n.Tween=Kb,Kb.prototype={constructor:Kb,init:function(a,b,c,d,e,f){this.elem=a,this.prop=c,this.easing=e||"swing",this.options=b,this.start=this.now=this.cur(),this.end=d,this.unit=f||(n.cssNumber[c]?"":"px")},cur:function(){var a=Kb.propHooks[this.prop];return a&&a.get?a.get(this):Kb.propHooks._default.get(this)},run:function(a){var b,c=Kb.propHooks[this.prop];return this.pos=b=this.options.duration?n.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):a,this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):Kb.propHooks._default.set(this),this}},Kb.prototype.init.prototype=Kb.prototype,Kb.propHooks={_default:{get:function(a){var b;return null==a.elem[a.prop]||a.elem.style&&null!=a.elem.style[a.prop]?(b=n.css(a.elem,a.prop,""),b&&"auto"!==b?b:0):a.elem[a.prop]},set:function(a){n.fx.step[a.prop]?n.fx.step[a.prop](a):a.elem.style&&(null!=a.elem.style[n.cssProps[a.prop]]||n.cssHooks[a.prop])?n.style(a.elem,a.prop,a.now+a.unit):a.elem[a.prop]=a.now}}},Kb.propHooks.scrollTop=Kb.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},n.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2}},n.fx=Kb.prototype.init,n.fx.step={};var Lb,Mb,Nb=/^(?:toggle|show|hide)$/,Ob=new RegExp("^(?:([+-])=|)("+Q+")([a-z%]*)$","i"),Pb=/queueHooks$/,Qb=[Vb],Rb={"*":[function(a,b){var c=this.createTween(a,b),d=c.cur(),e=Ob.exec(b),f=e&&e[3]||(n.cssNumber[a]?"":"px"),g=(n.cssNumber[a]||"px"!==f&&+d)&&Ob.exec(n.css(c.elem,a)),h=1,i=20;if(g&&g[3]!==f){f=f||g[3],e=e||[],g=+d||1;do h=h||".5",g/=h,n.style(c.elem,a,g+f);while(h!==(h=c.cur()/d)&&1!==h&&--i)}return e&&(g=c.start=+g||+d||0,c.unit=f,c.end=e[1]?g+(e[1]+1)*e[2]:+e[2]),c}]};function Sb(){return setTimeout(function(){Lb=void 0}),Lb=n.now()}function Tb(a,b){var c,d=0,e={height:a};for(b=b?1:0;4>d;d+=2-b)c=R[d],e["margin"+c]=e["padding"+c]=a;return b&&(e.opacity=e.width=a),e}function Ub(a,b,c){for(var d,e=(Rb[b]||[]).concat(Rb["*"]),f=0,g=e.length;g>f;f++)if(d=e[f].call(c,b,a))return d}function Vb(a,b,c){var d,e,f,g,h,i,j,k,l=this,m={},o=a.style,p=a.nodeType&&S(a),q=L.get(a,"fxshow");c.queue||(h=n._queueHooks(a,"fx"),null==h.unqueued&&(h.unqueued=0,i=h.empty.fire,h.empty.fire=function(){h.unqueued||i()}),h.unqueued++,l.always(function(){l.always(function(){h.unqueued--,n.queue(a,"fx").length||h.empty.fire()})})),1===a.nodeType&&("height"in b||"width"in b)&&(c.overflow=[o.overflow,o.overflowX,o.overflowY],j=n.css(a,"display"),k="none"===j?L.get(a,"olddisplay")||tb(a.nodeName):j,"inline"===k&&"none"===n.css(a,"float")&&(o.display="inline-block")),c.overflow&&(o.overflow="hidden",l.always(function(){o.overflow=c.overflow[0],o.overflowX=c.overflow[1],o.overflowY=c.overflow[2]}));for(d in b)if(e=b[d],Nb.exec(e)){if(delete b[d],f=f||"toggle"===e,e===(p?"hide":"show")){if("show"!==e||!q||void 0===q[d])continue;p=!0}m[d]=q&&q[d]||n.style(a,d)}else j=void 0;if(n.isEmptyObject(m))"inline"===("none"===j?tb(a.nodeName):j)&&(o.display=j);else{q?"hidden"in q&&(p=q.hidden):q=L.access(a,"fxshow",{}),f&&(q.hidden=!p),p?n(a).show():l.done(function(){n(a).hide()}),l.done(function(){var b;L.remove(a,"fxshow");for(b in m)n.style(a,b,m[b])});for(d in m)g=Ub(p?q[d]:0,d,l),d in q||(q[d]=g.start,p&&(g.end=g.start,g.start="width"===d||"height"===d?1:0))}}function Wb(a,b){var c,d,e,f,g;for(c in a)if(d=n.camelCase(c),e=b[d],f=a[c],n.isArray(f)&&(e=f[1],f=a[c]=f[0]),c!==d&&(a[d]=f,delete a[c]),g=n.cssHooks[d],g&&"expand"in g){f=g.expand(f),delete a[d];for(c in f)c in a||(a[c]=f[c],b[c]=e)}else b[d]=e}function Xb(a,b,c){var d,e,f=0,g=Qb.length,h=n.Deferred().always(function(){delete i.elem}),i=function(){if(e)return!1;for(var b=Lb||Sb(),c=Math.max(0,j.startTime+j.duration-b),d=c/j.duration||0,f=1-d,g=0,i=j.tweens.length;i>g;g++)j.tweens[g].run(f);return h.notifyWith(a,[j,f,c]),1>f&&i?c:(h.resolveWith(a,[j]),!1)},j=h.promise({elem:a,props:n.extend({},b),opts:n.extend(!0,{specialEasing:{}},c),originalProperties:b,originalOptions:c,startTime:Lb||Sb(),duration:c.duration,tweens:[],createTween:function(b,c){var d=n.Tween(a,j.opts,b,c,j.opts.specialEasing[b]||j.opts.easing);return j.tweens.push(d),d},stop:function(b){var c=0,d=b?j.tweens.length:0;if(e)return this;for(e=!0;d>c;c++)j.tweens[c].run(1);return b?h.resolveWith(a,[j,b]):h.rejectWith(a,[j,b]),this}}),k=j.props;for(Wb(k,j.opts.specialEasing);g>f;f++)if(d=Qb[f].call(j,a,k,j.opts))return d;return n.map(k,Ub,j),n.isFunction(j.opts.start)&&j.opts.start.call(a,j),n.fx.timer(n.extend(i,{elem:a,anim:j,queue:j.opts.queue})),j.progress(j.opts.progress).done(j.opts.done,j.opts.complete).fail(j.opts.fail).always(j.opts.always)}n.Animation=n.extend(Xb,{tweener:function(a,b){n.isFunction(a)?(b=a,a=["*"]):a=a.split(" ");for(var c,d=0,e=a.length;e>d;d++)c=a[d],Rb[c]=Rb[c]||[],Rb[c].unshift(b)},prefilter:function(a,b){b?Qb.unshift(a):Qb.push(a)}}),n.speed=function(a,b,c){var d=a&&"object"==typeof a?n.extend({},a):{complete:c||!c&&b||n.isFunction(a)&&a,duration:a,easing:c&&b||b&&!n.isFunction(b)&&b};return d.duration=n.fx.off?0:"number"==typeof d.duration?d.duration:d.duration in n.fx.speeds?n.fx.speeds[d.duration]:n.fx.speeds._default,(null==d.queue||d.queue===!0)&&(d.queue="fx"),d.old=d.complete,d.complete=function(){n.isFunction(d.old)&&d.old.call(this),d.queue&&n.dequeue(this,d.queue)},d},n.fn.extend({fadeTo:function(a,b,c,d){return this.filter(S).css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=n.isEmptyObject(a),f=n.speed(b,c,d),g=function(){var b=Xb(this,n.extend({},a),f);(e||L.get(this,"finish"))&&b.stop(!0)};return g.finish=g,e||f.queue===!1?this.each(g):this.queue(f.queue,g)},stop:function(a,b,c){var d=function(a){var b=a.stop;delete a.stop,b(c)};return"string"!=typeof a&&(c=b,b=a,a=void 0),b&&a!==!1&&this.queue(a||"fx",[]),this.each(function(){var b=!0,e=null!=a&&a+"queueHooks",f=n.timers,g=L.get(this);if(e)g[e]&&g[e].stop&&d(g[e]);else for(e in g)g[e]&&g[e].stop&&Pb.test(e)&&d(g[e]);for(e=f.length;e--;)f[e].elem!==this||null!=a&&f[e].queue!==a||(f[e].anim.stop(c),b=!1,f.splice(e,1));(b||!c)&&n.dequeue(this,a)})},finish:function(a){return a!==!1&&(a=a||"fx"),this.each(function(){var b,c=L.get(this),d=c[a+"queue"],e=c[a+"queueHooks"],f=n.timers,g=d?d.length:0;for(c.finish=!0,n.queue(this,a,[]),e&&e.stop&&e.stop.call(this,!0),b=f.length;b--;)f[b].elem===this&&f[b].queue===a&&(f[b].anim.stop(!0),f.splice(b,1));for(b=0;g>b;b++)d[b]&&d[b].finish&&d[b].finish.call(this);delete c.finish})}}),n.each(["toggle","show","hide"],function(a,b){var c=n.fn[b];n.fn[b]=function(a,d,e){return null==a||"boolean"==typeof a?c.apply(this,arguments):this.animate(Tb(b,!0),a,d,e)}}),n.each({slideDown:Tb("show"),slideUp:Tb("hide"),slideToggle:Tb("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){n.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),n.timers=[],n.fx.tick=function(){var a,b=0,c=n.timers;for(Lb=n.now();b<c.length;b++)a=c[b],a()||c[b]!==a||c.splice(b--,1);c.length||n.fx.stop(),Lb=void 0},n.fx.timer=function(a){n.timers.push(a),a()?n.fx.start():n.timers.pop()},n.fx.interval=13,n.fx.start=function(){Mb||(Mb=setInterval(n.fx.tick,n.fx.interval))},n.fx.stop=function(){clearInterval(Mb),Mb=null},n.fx.speeds={slow:600,fast:200,_default:400},n.fn.delay=function(a,b){return a=n.fx?n.fx.speeds[a]||a:a,b=b||"fx",this.queue(b,function(b,c){var d=setTimeout(b,a);c.stop=function(){clearTimeout(d)}})},function(){var a=l.createElement("input"),b=l.createElement("select"),c=b.appendChild(l.createElement("option"));a.type="checkbox",k.checkOn=""!==a.value,k.optSelected=c.selected,b.disabled=!0,k.optDisabled=!c.disabled,a=l.createElement("input"),a.value="t",a.type="radio",k.radioValue="t"===a.value}();var Yb,Zb,$b=n.expr.attrHandle;n.fn.extend({attr:function(a,b){return J(this,n.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){n.removeAttr(this,a)})}}),n.extend({attr:function(a,b,c){var d,e,f=a.nodeType;if(a&&3!==f&&8!==f&&2!==f)return typeof a.getAttribute===U?n.prop(a,b,c):(1===f&&n.isXMLDoc(a)||(b=b.toLowerCase(),d=n.attrHooks[b]||(n.expr.match.bool.test(b)?Zb:Yb)),void 0===c?d&&"get"in d&&null!==(e=d.get(a,b))?e:(e=n.find.attr(a,b),null==e?void 0:e):null!==c?d&&"set"in d&&void 0!==(e=d.set(a,c,b))?e:(a.setAttribute(b,c+""),c):void n.removeAttr(a,b))
-},removeAttr:function(a,b){var c,d,e=0,f=b&&b.match(E);if(f&&1===a.nodeType)while(c=f[e++])d=n.propFix[c]||c,n.expr.match.bool.test(c)&&(a[d]=!1),a.removeAttribute(c)},attrHooks:{type:{set:function(a,b){if(!k.radioValue&&"radio"===b&&n.nodeName(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}}}}),Zb={set:function(a,b,c){return b===!1?n.removeAttr(a,c):a.setAttribute(c,c),c}},n.each(n.expr.match.bool.source.match(/\w+/g),function(a,b){var c=$b[b]||n.find.attr;$b[b]=function(a,b,d){var e,f;return d||(f=$b[b],$b[b]=e,e=null!=c(a,b,d)?b.toLowerCase():null,$b[b]=f),e}});var _b=/^(?:input|select|textarea|button)$/i;n.fn.extend({prop:function(a,b){return J(this,n.prop,a,b,arguments.length>1)},removeProp:function(a){return this.each(function(){delete this[n.propFix[a]||a]})}}),n.extend({propFix:{"for":"htmlFor","class":"className"},prop:function(a,b,c){var d,e,f,g=a.nodeType;if(a&&3!==g&&8!==g&&2!==g)return f=1!==g||!n.isXMLDoc(a),f&&(b=n.propFix[b]||b,e=n.propHooks[b]),void 0!==c?e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:a[b]=c:e&&"get"in e&&null!==(d=e.get(a,b))?d:a[b]},propHooks:{tabIndex:{get:function(a){return a.hasAttribute("tabindex")||_b.test(a.nodeName)||a.href?a.tabIndex:-1}}}}),k.optSelected||(n.propHooks.selected={get:function(a){var b=a.parentNode;return b&&b.parentNode&&b.parentNode.selectedIndex,null}}),n.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){n.propFix[this.toLowerCase()]=this});var ac=/[\t\r\n\f]/g;n.fn.extend({addClass:function(a){var b,c,d,e,f,g,h="string"==typeof a&&a,i=0,j=this.length;if(n.isFunction(a))return this.each(function(b){n(this).addClass(a.call(this,b,this.className))});if(h)for(b=(a||"").match(E)||[];j>i;i++)if(c=this[i],d=1===c.nodeType&&(c.className?(" "+c.className+" ").replace(ac," "):" ")){f=0;while(e=b[f++])d.indexOf(" "+e+" ")<0&&(d+=e+" ");g=n.trim(d),c.className!==g&&(c.className=g)}return this},removeClass:function(a){var b,c,d,e,f,g,h=0===arguments.length||"string"==typeof a&&a,i=0,j=this.length;if(n.isFunction(a))return this.each(function(b){n(this).removeClass(a.call(this,b,this.className))});if(h)for(b=(a||"").match(E)||[];j>i;i++)if(c=this[i],d=1===c.nodeType&&(c.className?(" "+c.className+" ").replace(ac," "):"")){f=0;while(e=b[f++])while(d.indexOf(" "+e+" ")>=0)d=d.replace(" "+e+" "," ");g=a?n.trim(d):"",c.className!==g&&(c.className=g)}return this},toggleClass:function(a,b){var c=typeof a;return"boolean"==typeof b&&"string"===c?b?this.addClass(a):this.removeClass(a):this.each(n.isFunction(a)?function(c){n(this).toggleClass(a.call(this,c,this.className,b),b)}:function(){if("string"===c){var b,d=0,e=n(this),f=a.match(E)||[];while(b=f[d++])e.hasClass(b)?e.removeClass(b):e.addClass(b)}else(c===U||"boolean"===c)&&(this.className&&L.set(this,"__className__",this.className),this.className=this.className||a===!1?"":L.get(this,"__className__")||"")})},hasClass:function(a){for(var b=" "+a+" ",c=0,d=this.length;d>c;c++)if(1===this[c].nodeType&&(" "+this[c].className+" ").replace(ac," ").indexOf(b)>=0)return!0;return!1}});var bc=/\r/g;n.fn.extend({val:function(a){var b,c,d,e=this[0];{if(arguments.length)return d=n.isFunction(a),this.each(function(c){var e;1===this.nodeType&&(e=d?a.call(this,c,n(this).val()):a,null==e?e="":"number"==typeof e?e+="":n.isArray(e)&&(e=n.map(e,function(a){return null==a?"":a+""})),b=n.valHooks[this.type]||n.valHooks[this.nodeName.toLowerCase()],b&&"set"in b&&void 0!==b.set(this,e,"value")||(this.value=e))});if(e)return b=n.valHooks[e.type]||n.valHooks[e.nodeName.toLowerCase()],b&&"get"in b&&void 0!==(c=b.get(e,"value"))?c:(c=e.value,"string"==typeof c?c.replace(bc,""):null==c?"":c)}}}),n.extend({valHooks:{option:{get:function(a){var b=n.find.attr(a,"value");return null!=b?b:n.trim(n.text(a))}},select:{get:function(a){for(var b,c,d=a.options,e=a.selectedIndex,f="select-one"===a.type||0>e,g=f?null:[],h=f?e+1:d.length,i=0>e?h:f?e:0;h>i;i++)if(c=d[i],!(!c.selected&&i!==e||(k.optDisabled?c.disabled:null!==c.getAttribute("disabled"))||c.parentNode.disabled&&n.nodeName(c.parentNode,"optgroup"))){if(b=n(c).val(),f)return b;g.push(b)}return g},set:function(a,b){var c,d,e=a.options,f=n.makeArray(b),g=e.length;while(g--)d=e[g],(d.selected=n.inArray(d.value,f)>=0)&&(c=!0);return c||(a.selectedIndex=-1),f}}}}),n.each(["radio","checkbox"],function(){n.valHooks[this]={set:function(a,b){return n.isArray(b)?a.checked=n.inArray(n(a).val(),b)>=0:void 0}},k.checkOn||(n.valHooks[this].get=function(a){return null===a.getAttribute("value")?"on":a.value})}),n.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){n.fn[b]=function(a,c){return arguments.length>0?this.on(b,null,a,c):this.trigger(b)}}),n.fn.extend({hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return 1===arguments.length?this.off(a,"**"):this.off(b,a||"**",c)}});var cc=n.now(),dc=/\?/;n.parseJSON=function(a){return JSON.parse(a+"")},n.parseXML=function(a){var b,c;if(!a||"string"!=typeof a)return null;try{c=new DOMParser,b=c.parseFromString(a,"text/xml")}catch(d){b=void 0}return(!b||b.getElementsByTagName("parsererror").length)&&n.error("Invalid XML: "+a),b};var ec=/#.*$/,fc=/([?&])_=[^&]*/,gc=/^(.*?):[ \t]*([^\r\n]*)$/gm,hc=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,ic=/^(?:GET|HEAD)$/,jc=/^\/\//,kc=/^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/,lc={},mc={},nc="*/".concat("*"),oc=a.location.href,pc=kc.exec(oc.toLowerCase())||[];function qc(a){return function(b,c){"string"!=typeof b&&(c=b,b="*");var d,e=0,f=b.toLowerCase().match(E)||[];if(n.isFunction(c))while(d=f[e++])"+"===d[0]?(d=d.slice(1)||"*",(a[d]=a[d]||[]).unshift(c)):(a[d]=a[d]||[]).push(c)}}function rc(a,b,c,d){var e={},f=a===mc;function g(h){var i;return e[h]=!0,n.each(a[h]||[],function(a,h){var j=h(b,c,d);return"string"!=typeof j||f||e[j]?f?!(i=j):void 0:(b.dataTypes.unshift(j),g(j),!1)}),i}return g(b.dataTypes[0])||!e["*"]&&g("*")}function sc(a,b){var c,d,e=n.ajaxSettings.flatOptions||{};for(c in b)void 0!==b[c]&&((e[c]?a:d||(d={}))[c]=b[c]);return d&&n.extend(!0,a,d),a}function tc(a,b,c){var d,e,f,g,h=a.contents,i=a.dataTypes;while("*"===i[0])i.shift(),void 0===d&&(d=a.mimeType||b.getResponseHeader("Content-Type"));if(d)for(e in h)if(h[e]&&h[e].test(d)){i.unshift(e);break}if(i[0]in c)f=i[0];else{for(e in c){if(!i[0]||a.converters[e+" "+i[0]]){f=e;break}g||(g=e)}f=f||g}return f?(f!==i[0]&&i.unshift(f),c[f]):void 0}function uc(a,b,c,d){var e,f,g,h,i,j={},k=a.dataTypes.slice();if(k[1])for(g in a.converters)j[g.toLowerCase()]=a.converters[g];f=k.shift();while(f)if(a.responseFields[f]&&(c[a.responseFields[f]]=b),!i&&d&&a.dataFilter&&(b=a.dataFilter(b,a.dataType)),i=f,f=k.shift())if("*"===f)f=i;else if("*"!==i&&i!==f){if(g=j[i+" "+f]||j["* "+f],!g)for(e in j)if(h=e.split(" "),h[1]===f&&(g=j[i+" "+h[0]]||j["* "+h[0]])){g===!0?g=j[e]:j[e]!==!0&&(f=h[0],k.unshift(h[1]));break}if(g!==!0)if(g&&a["throws"])b=g(b);else try{b=g(b)}catch(l){return{state:"parsererror",error:g?l:"No conversion from "+i+" to "+f}}}return{state:"success",data:b}}n.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:oc,type:"GET",isLocal:hc.test(pc[1]),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":nc,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":n.parseJSON,"text xml":n.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(a,b){return b?sc(sc(a,n.ajaxSettings),b):sc(n.ajaxSettings,a)},ajaxPrefilter:qc(lc),ajaxTransport:qc(mc),ajax:function(a,b){"object"==typeof a&&(b=a,a=void 0),b=b||{};var c,d,e,f,g,h,i,j,k=n.ajaxSetup({},b),l=k.context||k,m=k.context&&(l.nodeType||l.jquery)?n(l):n.event,o=n.Deferred(),p=n.Callbacks("once memory"),q=k.statusCode||{},r={},s={},t=0,u="canceled",v={readyState:0,getResponseHeader:function(a){var b;if(2===t){if(!f){f={};while(b=gc.exec(e))f[b[1].toLowerCase()]=b[2]}b=f[a.toLowerCase()]}return null==b?null:b},getAllResponseHeaders:function(){return 2===t?e:null},setRequestHeader:function(a,b){var c=a.toLowerCase();return t||(a=s[c]=s[c]||a,r[a]=b),this},overrideMimeType:function(a){return t||(k.mimeType=a),this},statusCode:function(a){var b;if(a)if(2>t)for(b in a)q[b]=[q[b],a[b]];else v.always(a[v.status]);return this},abort:function(a){var b=a||u;return c&&c.abort(b),x(0,b),this}};if(o.promise(v).complete=p.add,v.success=v.done,v.error=v.fail,k.url=((a||k.url||oc)+"").replace(ec,"").replace(jc,pc[1]+"//"),k.type=b.method||b.type||k.method||k.type,k.dataTypes=n.trim(k.dataType||"*").toLowerCase().match(E)||[""],null==k.crossDomain&&(h=kc.exec(k.url.toLowerCase()),k.crossDomain=!(!h||h[1]===pc[1]&&h[2]===pc[2]&&(h[3]||("http:"===h[1]?"80":"443"))===(pc[3]||("http:"===pc[1]?"80":"443")))),k.data&&k.processData&&"string"!=typeof k.data&&(k.data=n.param(k.data,k.traditional)),rc(lc,k,b,v),2===t)return v;i=n.event&&k.global,i&&0===n.active++&&n.event.trigger("ajaxStart"),k.type=k.type.toUpperCase(),k.hasContent=!ic.test(k.type),d=k.url,k.hasContent||(k.data&&(d=k.url+=(dc.test(d)?"&":"?")+k.data,delete k.data),k.cache===!1&&(k.url=fc.test(d)?d.replace(fc,"$1_="+cc++):d+(dc.test(d)?"&":"?")+"_="+cc++)),k.ifModified&&(n.lastModified[d]&&v.setRequestHeader("If-Modified-Since",n.lastModified[d]),n.etag[d]&&v.setRequestHeader("If-None-Match",n.etag[d])),(k.data&&k.hasContent&&k.contentType!==!1||b.contentType)&&v.setRequestHeader("Content-Type",k.contentType),v.setRequestHeader("Accept",k.dataTypes[0]&&k.accepts[k.dataTypes[0]]?k.accepts[k.dataTypes[0]]+("*"!==k.dataTypes[0]?", "+nc+"; q=0.01":""):k.accepts["*"]);for(j in k.headers)v.setRequestHeader(j,k.headers[j]);if(k.beforeSend&&(k.beforeSend.call(l,v,k)===!1||2===t))return v.abort();u="abort";for(j in{success:1,error:1,complete:1})v[j](k[j]);if(c=rc(mc,k,b,v)){v.readyState=1,i&&m.trigger("ajaxSend",[v,k]),k.async&&k.timeout>0&&(g=setTimeout(function(){v.abort("timeout")},k.timeout));try{t=1,c.send(r,x)}catch(w){if(!(2>t))throw w;x(-1,w)}}else x(-1,"No Transport");function x(a,b,f,h){var j,r,s,u,w,x=b;2!==t&&(t=2,g&&clearTimeout(g),c=void 0,e=h||"",v.readyState=a>0?4:0,j=a>=200&&300>a||304===a,f&&(u=tc(k,v,f)),u=uc(k,u,v,j),j?(k.ifModified&&(w=v.getResponseHeader("Last-Modified"),w&&(n.lastModified[d]=w),w=v.getResponseHeader("etag"),w&&(n.etag[d]=w)),204===a||"HEAD"===k.type?x="nocontent":304===a?x="notmodified":(x=u.state,r=u.data,s=u.error,j=!s)):(s=x,(a||!x)&&(x="error",0>a&&(a=0))),v.status=a,v.statusText=(b||x)+"",j?o.resolveWith(l,[r,x,v]):o.rejectWith(l,[v,x,s]),v.statusCode(q),q=void 0,i&&m.trigger(j?"ajaxSuccess":"ajaxError",[v,k,j?r:s]),p.fireWith(l,[v,x]),i&&(m.trigger("ajaxComplete",[v,k]),--n.active||n.event.trigger("ajaxStop")))}return v},getJSON:function(a,b,c){return n.get(a,b,c,"json")},getScript:function(a,b){return n.get(a,void 0,b,"script")}}),n.each(["get","post"],function(a,b){n[b]=function(a,c,d,e){return n.isFunction(c)&&(e=e||d,d=c,c=void 0),n.ajax({url:a,type:b,dataType:e,data:c,success:d})}}),n._evalUrl=function(a){return n.ajax({url:a,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0})},n.fn.extend({wrapAll:function(a){var b;return n.isFunction(a)?this.each(function(b){n(this).wrapAll(a.call(this,b))}):(this[0]&&(b=n(a,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstElementChild)a=a.firstElementChild;return a}).append(this)),this)},wrapInner:function(a){return this.each(n.isFunction(a)?function(b){n(this).wrapInner(a.call(this,b))}:function(){var b=n(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=n.isFunction(a);return this.each(function(c){n(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){n.nodeName(this,"body")||n(this).replaceWith(this.childNodes)}).end()}}),n.expr.filters.hidden=function(a){return a.offsetWidth<=0&&a.offsetHeight<=0},n.expr.filters.visible=function(a){return!n.expr.filters.hidden(a)};var vc=/%20/g,wc=/\[\]$/,xc=/\r?\n/g,yc=/^(?:submit|button|image|reset|file)$/i,zc=/^(?:input|select|textarea|keygen)/i;function Ac(a,b,c,d){var e;if(n.isArray(b))n.each(b,function(b,e){c||wc.test(a)?d(a,e):Ac(a+"["+("object"==typeof e?b:"")+"]",e,c,d)});else if(c||"object"!==n.type(b))d(a,b);else for(e in b)Ac(a+"["+e+"]",b[e],c,d)}n.param=function(a,b){var c,d=[],e=function(a,b){b=n.isFunction(b)?b():null==b?"":b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};if(void 0===b&&(b=n.ajaxSettings&&n.ajaxSettings.traditional),n.isArray(a)||a.jquery&&!n.isPlainObject(a))n.each(a,function(){e(this.name,this.value)});else for(c in a)Ac(c,a[c],b,e);return d.join("&").replace(vc,"+")},n.fn.extend({serialize:function(){return n.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var a=n.prop(this,"elements");return a?n.makeArray(a):this}).filter(function(){var a=this.type;return this.name&&!n(this).is(":disabled")&&zc.test(this.nodeName)&&!yc.test(a)&&(this.checked||!T.test(a))}).map(function(a,b){var c=n(this).val();return null==c?null:n.isArray(c)?n.map(c,function(a){return{name:b.name,value:a.replace(xc,"\r\n")}}):{name:b.name,value:c.replace(xc,"\r\n")}}).get()}}),n.ajaxSettings.xhr=function(){try{return new XMLHttpRequest}catch(a){}};var Bc=0,Cc={},Dc={0:200,1223:204},Ec=n.ajaxSettings.xhr();a.attachEvent&&a.attachEvent("onunload",function(){for(var a in Cc)Cc[a]()}),k.cors=!!Ec&&"withCredentials"in Ec,k.ajax=Ec=!!Ec,n.ajaxTransport(function(a){var b;return k.cors||Ec&&!a.crossDomain?{send:function(c,d){var e,f=a.xhr(),g=++Bc;if(f.open(a.type,a.url,a.async,a.username,a.password),a.xhrFields)for(e in a.xhrFields)f[e]=a.xhrFields[e];a.mimeType&&f.overrideMimeType&&f.overrideMimeType(a.mimeType),a.crossDomain||c["X-Requested-With"]||(c["X-Requested-With"]="XMLHttpRequest");for(e in c)f.setRequestHeader(e,c[e]);b=function(a){return function(){b&&(delete Cc[g],b=f.onload=f.onerror=null,"abort"===a?f.abort():"error"===a?d(f.status,f.statusText):d(Dc[f.status]||f.status,f.statusText,"string"==typeof f.responseText?{text:f.responseText}:void 0,f.getAllResponseHeaders()))}},f.onload=b(),f.onerror=b("error"),b=Cc[g]=b("abort");try{f.send(a.hasContent&&a.data||null)}catch(h){if(b)throw h}},abort:function(){b&&b()}}:void 0}),n.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/(?:java|ecma)script/},converters:{"text script":function(a){return n.globalEval(a),a}}}),n.ajaxPrefilter("script",function(a){void 0===a.cache&&(a.cache=!1),a.crossDomain&&(a.type="GET")}),n.ajaxTransport("script",function(a){if(a.crossDomain){var b,c;return{send:function(d,e){b=n("<script>").prop({async:!0,charset:a.scriptCharset,src:a.url}).on("load error",c=function(a){b.remove(),c=null,a&&e("error"===a.type?404:200,a.type)}),l.head.appendChild(b[0])},abort:function(){c&&c()}}}});var Fc=[],Gc=/(=)\?(?=&|$)|\?\?/;n.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=Fc.pop()||n.expando+"_"+cc++;return this[a]=!0,a}}),n.ajaxPrefilter("json jsonp",function(b,c,d){var e,f,g,h=b.jsonp!==!1&&(Gc.test(b.url)?"url":"string"==typeof b.data&&!(b.contentType||"").indexOf("application/x-www-form-urlencoded")&&Gc.test(b.data)&&"data");return h||"jsonp"===b.dataTypes[0]?(e=b.jsonpCallback=n.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,h?b[h]=b[h].replace(Gc,"$1"+e):b.jsonp!==!1&&(b.url+=(dc.test(b.url)?"&":"?")+b.jsonp+"="+e),b.converters["script json"]=function(){return g||n.error(e+" was not called"),g[0]},b.dataTypes[0]="json",f=a[e],a[e]=function(){g=arguments},d.always(function(){a[e]=f,b[e]&&(b.jsonpCallback=c.jsonpCallback,Fc.push(e)),g&&n.isFunction(f)&&f(g[0]),g=f=void 0}),"script"):void 0}),n.parseHTML=function(a,b,c){if(!a||"string"!=typeof a)return null;"boolean"==typeof b&&(c=b,b=!1),b=b||l;var d=v.exec(a),e=!c&&[];return d?[b.createElement(d[1])]:(d=n.buildFragment([a],b,e),e&&e.length&&n(e).remove(),n.merge([],d.childNodes))};var Hc=n.fn.load;n.fn.load=function(a,b,c){if("string"!=typeof a&&Hc)return Hc.apply(this,arguments);var d,e,f,g=this,h=a.indexOf(" ");return h>=0&&(d=n.trim(a.slice(h)),a=a.slice(0,h)),n.isFunction(b)?(c=b,b=void 0):b&&"object"==typeof b&&(e="POST"),g.length>0&&n.ajax({url:a,type:e,dataType:"html",data:b}).done(function(a){f=arguments,g.html(d?n("<div>").append(n.parseHTML(a)).find(d):a)}).complete(c&&function(a,b){g.each(c,f||[a.responseText,b,a])}),this},n.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(a,b){n.fn[b]=function(a){return this.on(b,a)}}),n.expr.filters.animated=function(a){return n.grep(n.timers,function(b){return a===b.elem}).length};var Ic=a.document.documentElement;function Jc(a){return n.isWindow(a)?a:9===a.nodeType&&a.defaultView}n.offset={setOffset:function(a,b,c){var d,e,f,g,h,i,j,k=n.css(a,"position"),l=n(a),m={};"static"===k&&(a.style.position="relative"),h=l.offset(),f=n.css(a,"top"),i=n.css(a,"left"),j=("absolute"===k||"fixed"===k)&&(f+i).indexOf("auto")>-1,j?(d=l.position(),g=d.top,e=d.left):(g=parseFloat(f)||0,e=parseFloat(i)||0),n.isFunction(b)&&(b=b.call(a,c,h)),null!=b.top&&(m.top=b.top-h.top+g),null!=b.left&&(m.left=b.left-h.left+e),"using"in b?b.using.call(a,m):l.css(m)}},n.fn.extend({offset:function(a){if(arguments.length)return void 0===a?this:this.each(function(b){n.offset.setOffset(this,a,b)});var b,c,d=this[0],e={top:0,left:0},f=d&&d.ownerDocument;if(f)return b=f.documentElement,n.contains(b,d)?(typeof d.getBoundingClientRect!==U&&(e=d.getBoundingClientRect()),c=Jc(f),{top:e.top+c.pageYOffset-b.clientTop,left:e.left+c.pageXOffset-b.clientLeft}):e},position:function(){if(this[0]){var a,b,c=this[0],d={top:0,left:0};return"fixed"===n.css(c,"position")?b=c.getBoundingClientRect():(a=this.offsetParent(),b=this.offset(),n.nodeName(a[0],"html")||(d=a.offset()),d.top+=n.css(a[0],"borderTopWidth",!0),d.left+=n.css(a[0],"borderLeftWidth",!0)),{top:b.top-d.top-n.css(c,"marginTop",!0),left:b.left-d.left-n.css(c,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||Ic;while(a&&!n.nodeName(a,"html")&&"static"===n.css(a,"position"))a=a.offsetParent;return a||Ic})}}),n.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(b,c){var d="pageYOffset"===c;n.fn[b]=function(e){return J(this,function(b,e,f){var g=Jc(b);return void 0===f?g?g[c]:b[e]:void(g?g.scrollTo(d?a.pageXOffset:f,d?f:a.pageYOffset):b[e]=f)},b,e,arguments.length,null)}}),n.each(["top","left"],function(a,b){n.cssHooks[b]=yb(k.pixelPosition,function(a,c){return c?(c=xb(a,b),vb.test(c)?n(a).position()[b]+"px":c):void 0})}),n.each({Height:"height",Width:"width"},function(a,b){n.each({padding:"inner"+a,content:b,"":"outer"+a},function(c,d){n.fn[d]=function(d,e){var f=arguments.length&&(c||"boolean"!=typeof d),g=c||(d===!0||e===!0?"margin":"border");return J(this,function(b,c,d){var e;return n.isWindow(b)?b.document.documentElement["client"+a]:9===b.nodeType?(e=b.documentElement,Math.max(b.body["scroll"+a],e["scroll"+a],b.body["offset"+a],e["offset"+a],e["client"+a])):void 0===d?n.css(b,c,g):n.style(b,c,d,g)},b,f?d:void 0,f,null)}})}),n.fn.size=function(){return this.length},n.fn.andSelf=n.fn.addBack,"function"==typeof define&&define.amd&&define("jquery",[],function(){return n});var Kc=a.jQuery,Lc=a.$;return n.noConflict=function(b){return a.$===n&&(a.$=Lc),b&&a.jQuery===n&&(a.jQuery=Kc),n},typeof b===U&&(a.jQuery=a.$=n),n});
diff --git a/doc/_extensions/odoo_ext/static/jquery.noconflict.js b/doc/_extensions/odoo_ext/static/jquery.noconflict.js
deleted file mode 100644
index 204fb2a9f28..00000000000
--- a/doc/_extensions/odoo_ext/static/jquery.noconflict.js
+++ /dev/null
@@ -1 +0,0 @@
-$.noConflict(true);
diff --git a/doc/_extensions/odoo_ext/static/layout.less b/doc/_extensions/odoo_ext/static/layout.less
deleted file mode 100644
index c826e769544..00000000000
--- a/doc/_extensions/odoo_ext/static/layout.less
+++ /dev/null
@@ -1,164 +0,0 @@
-// ================================================
-// ================ Layout =======================
-// ================================================
-
-
-// Bootrstrap adaptations
-// ------------------------------------------------------------------
-body, header {
- position: relative;
-}
-
-.container .container {
- max-width: 100%;
- padding: 0;
- margin: 0;
-}
-
-.img-responsive {
- display: inline-block;
-}
-
-.img-responsive.center-block {
- display: block;
-}
-
-article.doc-content *[class*="col-"] {
- padding: 0;
-}
-
-
-// Main Components
-// ------------------------------------------------------------------
-#wrap {
- z-index: 1;
- position: relative;
- background: @gray-lightest;
- padding-bottom: 40px;
-}
-
-main {
- position: relative;
- display: block;
-
- .o_content {
- background-color: @doc_paper;
- .deep-1;
-
- @media (min-width: @screen-sm-min) {
- margin: -40px auto 0;
- border-radius: 2px;
- }
- }
-
- article.doc-body {
- .pseudo-col();
- padding: 15px;
-
- @media (min-width: @screen-sm-min) {
- padding: 15px 30px;
- }
-
- @media (min-width: @screen-md-min) {
- max-width: 700px;
- }
-
- @media (min-width: @screen-lg-min) {
- margin-left: 7%;
- margin-top: 20px;
- }
-
- > * {
- max-width: 100%;
- }
- }
-}
-
-main.o_aside_removed, main.o_slim_page {
- max-width: 700px;
-
- @media (min-width: @screen-lg-min) {
- max-width: 760px;
- }
-
- article.doc-body {
- @media (min-width: @screen-md-min) {
- padding-left: 30px;
- }
- }
-}
-
-main.has_code_col {
- max-width: 700px;
-
- @media (min-width: @screen-lg-min) {
- max-width: @container-lg;
- }
-
- .doc-aside, .doc-content {
- .pseudo-col();
-
- @media (max-width: @screen-md-max) {
- padding: 0;
- }
- }
-
- aside {
- display: none;
- }
-
- article.doc-body {
- > section {
- max-width: 100%;
- }
-
- @media (min-width: @screen-lg-min) {
- width: 100%;
- max-width: none;
- margin:0;
-
- &:before {
- .code-col();
- }
-
- > section {
- position: relative;
- display: block;
- float: left;
- width: 100%;
-
- > * {
- width: 48%;
- float: left;
- clear: left;
- }
-
- > h2, > h3, > h4, > h5, > h6, > h1 {
- width: 48%;
- float: none;
- clear: none;
- }
-
- .doc-aside {
- width: 49%;
- float: none;
- clear: none;
- margin-left: 51%;
- color: @gray-light;
- font-size: 14px;
- line-height: 1.45;
-
- pre {
- font-size: 12px;
- }
- }
- }
-
- }
- }
-}
-
-article.doc-toc .toctree-wrapper > ul > li > span {
- display: block;
- font-size: 28px;
-}
diff --git a/doc/_extensions/odoo_ext/static/mdi.less b/doc/_extensions/odoo_ext/static/mdi.less
deleted file mode 100644
index c2e646ec227..00000000000
--- a/doc/_extensions/odoo_ext/static/mdi.less
+++ /dev/null
@@ -1,2381 +0,0 @@
-// Material Design Icons
-// https://github.com/google/material-design-icons
-// preview at http://fezvrasta.github.io/bootstrap-material-design/bootstrap-elements.html#icon
-
-
-
-@font-face {
- font-family: 'Material-Design-Icons';
- src: url('fonts/Material-Design-Icons.eot?3ocs8m');
- src: url('fonts/Material-Design-Icons.eot?#iefix3ocs8m') format('embedded-opentype'), url('fonts/Material-Design-Icons.woff?3ocs8m') format('woff'), url('fonts/Material-Design-Icons.ttf?3ocs8m') format('truetype'), url('fonts/Material-Design-Icons.svg?3ocs8m#Material-Design-Icons') format('svg');
- font-weight: normal;
- font-style: normal;
-}
-
-
-[class^="mdi-"],
-[class*="mdi-"] {
- speak: none;
- display: inline-block;
- font: normal normal normal 24px/1 'Material-Design-Icons';
- text-rendering: geometricPrecision;
- /* Better Font Rendering =========== */
- -webkit-font-smoothing: antialiased;
- -moz-osx-font-smoothing: grayscale;
- -webkit-transform: translate(0, 0);
- -ms-transform: translate(0, 0);
- transform: translate(0, 0);
-}
-[class^="mdi-"]:before,
-[class*="mdi-"]:before {
- display: inline-block;
- speak: none;
- text-decoration: inherit;
-}
-[class^="mdi-"].pull-left,
-[class*="mdi-"].pull-left {
- margin-right: .3em;
-}
-[class^="mdi-"].pull-right,
-[class*="mdi-"].pull-right {
- margin-left: .3em;
-}
-[class^="mdi-"].mdi-lg:before,
-[class*="mdi-"].mdi-lg:before,
-[class^="mdi-"].mdi-lg:after,
-[class*="mdi-"].mdi-lg:after {
- font-size: 1.33333333em;
- line-height: 0.75em;
- vertical-align: -15%;
-}
-[class^="mdi-"].mdi-2x:before,
-[class*="mdi-"].mdi-2x:before,
-[class^="mdi-"].mdi-2x:after,
-[class*="mdi-"].mdi-2x:after {
- font-size: 2em;
-}
-[class^="mdi-"].mdi-3x:before,
-[class*="mdi-"].mdi-3x:before,
-[class^="mdi-"].mdi-3x:after,
-[class*="mdi-"].mdi-3x:after {
- font-size: 3em;
-}
-[class^="mdi-"].mdi-4x:before,
-[class*="mdi-"].mdi-4x:before,
-[class^="mdi-"].mdi-4x:after,
-[class*="mdi-"].mdi-4x:after {
- font-size: 4em;
-}
-[class^="mdi-"].mdi-5x:before,
-[class*="mdi-"].mdi-5x:before,
-[class^="mdi-"].mdi-5x:after,
-[class*="mdi-"].mdi-5x:after {
- font-size: 5em;
-}
-
-.mdi-stack {
- position: relative;
- display: inline-block;
- width: 2em;
- height: 2em;
- line-height: 2em;
- vertical-align: middle;
-}
-.mdi-stack-1x,
-.mdi-stack-2x {
- position: absolute;
- left: 0;
- width: 100%;
- text-align: center;
-}
-.mdi-stack-1x {
- line-height: inherit;
-}
-.mdi-stack-2x {
- font-size: 2em;
-}
-.mdi-inverse {
- color: #ffffff;
-}
-
-/* Start Icons */
-.mdi-action-3d-rotation:before {
- content: "\e600";
-}
-.mdi-action-accessibility:before {
- content: "\e601";
-}
-.mdi-action-account-balance-wallet:before {
- content: "\e602";
-}
-.mdi-action-account-balance:before {
- content: "\e603";
-}
-.mdi-action-account-box:before {
- content: "\e604";
-}
-.mdi-action-account-child:before {
- content: "\e605";
-}
-.mdi-action-account-circle:before {
- content: "\e606";
-}
-.mdi-action-add-shopping-cart:before {
- content: "\e607";
-}
-.mdi-action-alarm-add:before {
- content: "\e608";
-}
-.mdi-action-alarm-off:before {
- content: "\e609";
-}
-.mdi-action-alarm-on:before {
- content: "\e60a";
-}
-.mdi-action-alarm:before {
- content: "\e60b";
-}
-.mdi-action-android:before {
- content: "\e60c";
-}
-.mdi-action-announcement:before {
- content: "\e60d";
-}
-.mdi-action-aspect-ratio:before {
- content: "\e60e";
-}
-.mdi-action-assessment:before {
- content: "\e60f";
-}
-.mdi-action-assignment-ind:before {
- content: "\e610";
-}
-.mdi-action-assignment-late:before {
- content: "\e611";
-}
-.mdi-action-assignment-return:before {
- content: "\e612";
-}
-.mdi-action-assignment-returned:before {
- content: "\e613";
-}
-.mdi-action-assignment-turned-in:before {
- content: "\e614";
-}
-.mdi-action-assignment:before {
- content: "\e615";
-}
-.mdi-action-autorenew:before {
- content: "\e616";
-}
-.mdi-action-backup:before {
- content: "\e617";
-}
-.mdi-action-book:before {
- content: "\e618";
-}
-.mdi-action-bookmark-outline:before {
- content: "\e619";
-}
-.mdi-action-bookmark:before {
- content: "\e61a";
-}
-.mdi-action-bug-report:before {
- content: "\e61b";
-}
-.mdi-action-cached:before {
- content: "\e61c";
-}
-.mdi-action-check-circle:before {
- content: "\e61d";
-}
-.mdi-action-class:before {
- content: "\e61e";
-}
-.mdi-action-credit-card:before {
- content: "\e61f";
-}
-.mdi-action-dashboard:before {
- content: "\e620";
-}
-.mdi-action-delete:before {
- content: "\e621";
-}
-.mdi-action-description:before {
- content: "\e622";
-}
-.mdi-action-dns:before {
- content: "\e623";
-}
-.mdi-action-done-all:before {
- content: "\e624";
-}
-.mdi-action-done:before {
- content: "\e625";
-}
-.mdi-action-event:before {
- content: "\e626";
-}
-.mdi-action-exit-to-app:before {
- content: "\e627";
-}
-.mdi-action-explore:before {
- content: "\e628";
-}
-.mdi-action-extension:before {
- content: "\e629";
-}
-.mdi-action-face-unlock:before {
- content: "\e62a";
-}
-.mdi-action-favorite-outline:before {
- content: "\e62b";
-}
-.mdi-action-favorite:before {
- content: "\e62c";
-}
-.mdi-action-find-in-page:before {
- content: "\e62d";
-}
-.mdi-action-find-replace:before {
- content: "\e62e";
-}
-.mdi-action-flip-to-back:before {
- content: "\e62f";
-}
-.mdi-action-flip-to-front:before {
- content: "\e630";
-}
-.mdi-action-get-app:before {
- content: "\e631";
-}
-.mdi-action-grade:before {
- content: "\e632";
-}
-.mdi-action-group-work:before {
- content: "\e633";
-}
-.mdi-action-help:before {
- content: "\e634";
-}
-.mdi-action-highlight-remove:before {
- content: "\e635";
-}
-.mdi-action-history:before {
- content: "\e636";
-}
-.mdi-action-home:before {
- content: "\e637";
-}
-.mdi-action-https:before {
- content: "\e638";
-}
-.mdi-action-info-outline:before {
- content: "\e639";
-}
-.mdi-action-info:before {
- content: "\e63a";
-}
-.mdi-action-input:before {
- content: "\e63b";
-}
-.mdi-action-invert-colors:before {
- content: "\e63c";
-}
-.mdi-action-label-outline:before {
- content: "\e63d";
-}
-.mdi-action-label:before {
- content: "\e63e";
-}
-.mdi-action-language:before {
- content: "\e63f";
-}
-.mdi-action-launch:before {
- content: "\e640";
-}
-.mdi-action-list:before {
- content: "\e641";
-}
-.mdi-action-lock-open:before {
- content: "\e642";
-}
-.mdi-action-lock-outline:before {
- content: "\e643";
-}
-.mdi-action-lock:before {
- content: "\e644";
-}
-.mdi-action-loyalty:before {
- content: "\e645";
-}
-.mdi-action-markunread-mailbox:before {
- content: "\e646";
-}
-.mdi-action-note-add:before {
- content: "\e647";
-}
-.mdi-action-open-in-browser:before {
- content: "\e648";
-}
-.mdi-action-open-in-new:before {
- content: "\e649";
-}
-.mdi-action-open-with:before {
- content: "\e64a";
-}
-.mdi-action-pageview:before {
- content: "\e64b";
-}
-.mdi-action-payment:before {
- content: "\e64c";
-}
-.mdi-action-perm-camera-mic:before {
- content: "\e64d";
-}
-.mdi-action-perm-contact-cal:before {
- content: "\e64e";
-}
-.mdi-action-perm-data-setting:before {
- content: "\e64f";
-}
-.mdi-action-perm-device-info:before {
- content: "\e650";
-}
-.mdi-action-perm-identity:before {
- content: "\e651";
-}
-.mdi-action-perm-media:before {
- content: "\e652";
-}
-.mdi-action-perm-phone-msg:before {
- content: "\e653";
-}
-.mdi-action-perm-scan-wifi:before {
- content: "\e654";
-}
-.mdi-action-picture-in-picture:before {
- content: "\e655";
-}
-.mdi-action-polymer:before {
- content: "\e656";
-}
-.mdi-action-print:before {
- content: "\e657";
-}
-.mdi-action-query-builder:before {
- content: "\e658";
-}
-.mdi-action-question-answer:before {
- content: "\e659";
-}
-.mdi-action-receipt:before {
- content: "\e65a";
-}
-.mdi-action-redeem:before {
- content: "\e65b";
-}
-.mdi-action-reorder:before {
- content: "\e65c";
-}
-.mdi-action-report-problem:before {
- content: "\e65d";
-}
-.mdi-action-restore:before {
- content: "\e65e";
-}
-.mdi-action-room:before {
- content: "\e65f";
-}
-.mdi-action-schedule:before {
- content: "\e660";
-}
-.mdi-action-search:before {
- content: "\e661";
-}
-.mdi-action-settings-applications:before {
- content: "\e662";
-}
-.mdi-action-settings-backup-restore:before {
- content: "\e663";
-}
-.mdi-action-settings-bluetooth:before {
- content: "\e664";
-}
-.mdi-action-settings-cell:before {
- content: "\e665";
-}
-.mdi-action-settings-display:before {
- content: "\e666";
-}
-.mdi-action-settings-ethernet:before {
- content: "\e667";
-}
-.mdi-action-settings-input-antenna:before {
- content: "\e668";
-}
-.mdi-action-settings-input-component:before {
- content: "\e669";
-}
-.mdi-action-settings-input-composite:before {
- content: "\e66a";
-}
-.mdi-action-settings-input-hdmi:before {
- content: "\e66b";
-}
-.mdi-action-settings-input-svideo:before {
- content: "\e66c";
-}
-.mdi-action-settings-overscan:before {
- content: "\e66d";
-}
-.mdi-action-settings-phone:before {
- content: "\e66e";
-}
-.mdi-action-settings-power:before {
- content: "\e66f";
-}
-.mdi-action-settings-remote:before {
- content: "\e670";
-}
-.mdi-action-settings-voice:before {
- content: "\e671";
-}
-.mdi-action-settings:before {
- content: "\e672";
-}
-.mdi-action-shop-two:before {
- content: "\e673";
-}
-.mdi-action-shop:before {
- content: "\e674";
-}
-.mdi-action-shopping-basket:before {
- content: "\e675";
-}
-.mdi-action-shopping-cart:before {
- content: "\e676";
-}
-.mdi-action-speaker-notes:before {
- content: "\e677";
-}
-.mdi-action-spellcheck:before {
- content: "\e678";
-}
-.mdi-action-star-rate:before {
- content: "\e679";
-}
-.mdi-action-stars:before {
- content: "\e67a";
-}
-.mdi-action-store:before {
- content: "\e67b";
-}
-.mdi-action-subject:before {
- content: "\e67c";
-}
-.mdi-action-supervisor-account:before {
- content: "\e67d";
-}
-.mdi-action-swap-horiz:before {
- content: "\e67e";
-}
-.mdi-action-swap-vert-circle:before {
- content: "\e67f";
-}
-.mdi-action-swap-vert:before {
- content: "\e680";
-}
-.mdi-action-system-update-tv:before {
- content: "\e681";
-}
-.mdi-action-tab-unselected:before {
- content: "\e682";
-}
-.mdi-action-tab:before {
- content: "\e683";
-}
-.mdi-action-theaters:before {
- content: "\e684";
-}
-.mdi-action-thumb-down:before {
- content: "\e685";
-}
-.mdi-action-thumb-up:before {
- content: "\e686";
-}
-.mdi-action-thumbs-up-down:before {
- content: "\e687";
-}
-.mdi-action-toc:before {
- content: "\e688";
-}
-.mdi-action-today:before {
- content: "\e689";
-}
-.mdi-action-track-changes:before {
- content: "\e68a";
-}
-.mdi-action-translate:before {
- content: "\e68b";
-}
-.mdi-action-trending-down:before {
- content: "\e68c";
-}
-.mdi-action-trending-neutral:before {
- content: "\e68d";
-}
-.mdi-action-trending-up:before {
- content: "\e68e";
-}
-.mdi-action-turned-in-not:before {
- content: "\e68f";
-}
-.mdi-action-turned-in:before {
- content: "\e690";
-}
-.mdi-action-verified-user:before {
- content: "\e691";
-}
-.mdi-action-view-agenda:before {
- content: "\e692";
-}
-.mdi-action-view-array:before {
- content: "\e693";
-}
-.mdi-action-view-carousel:before {
- content: "\e694";
-}
-.mdi-action-view-column:before {
- content: "\e695";
-}
-.mdi-action-view-day:before {
- content: "\e696";
-}
-.mdi-action-view-headline:before {
- content: "\e697";
-}
-.mdi-action-view-list:before {
- content: "\e698";
-}
-.mdi-action-view-module:before {
- content: "\e699";
-}
-.mdi-action-view-quilt:before {
- content: "\e69a";
-}
-.mdi-action-view-stream:before {
- content: "\e69b";
-}
-.mdi-action-view-week:before {
- content: "\e69c";
-}
-.mdi-action-visibility-off:before {
- content: "\e69d";
-}
-.mdi-action-visibility:before {
- content: "\e69e";
-}
-.mdi-action-wallet-giftcard:before {
- content: "\e69f";
-}
-.mdi-action-wallet-membership:before {
- content: "\e6a0";
-}
-.mdi-action-wallet-travel:before {
- content: "\e6a1";
-}
-.mdi-action-work:before {
- content: "\e6a2";
-}
-.mdi-alert-error:before {
- content: "\e6a3";
-}
-.mdi-alert-warning:before {
- content: "\e6a4";
-}
-.mdi-av-album:before {
- content: "\e6a5";
-}
-.mdi-av-closed-caption:before {
- content: "\e6a6";
-}
-.mdi-av-equalizer:before {
- content: "\e6a7";
-}
-.mdi-av-explicit:before {
- content: "\e6a8";
-}
-.mdi-av-fast-forward:before {
- content: "\e6a9";
-}
-.mdi-av-fast-rewind:before {
- content: "\e6aa";
-}
-.mdi-av-games:before {
- content: "\e6ab";
-}
-.mdi-av-hearing:before {
- content: "\e6ac";
-}
-.mdi-av-high-quality:before {
- content: "\e6ad";
-}
-.mdi-av-loop:before {
- content: "\e6ae";
-}
-.mdi-av-mic-none:before {
- content: "\e6af";
-}
-.mdi-av-mic-off:before {
- content: "\e6b0";
-}
-.mdi-av-mic:before {
- content: "\e6b1";
-}
-.mdi-av-movie:before {
- content: "\e6b2";
-}
-.mdi-av-my-library-add:before {
- content: "\e6b3";
-}
-.mdi-av-my-library-books:before {
- content: "\e6b4";
-}
-.mdi-av-my-library-music:before {
- content: "\e6b5";
-}
-.mdi-av-new-releases:before {
- content: "\e6b6";
-}
-.mdi-av-not-interested:before {
- content: "\e6b7";
-}
-.mdi-av-pause-circle-fill:before {
- content: "\e6b8";
-}
-.mdi-av-pause-circle-outline:before {
- content: "\e6b9";
-}
-.mdi-av-pause:before {
- content: "\e6ba";
-}
-.mdi-av-play-arrow:before {
- content: "\e6bb";
-}
-.mdi-av-play-circle-fill:before {
- content: "\e6bc";
-}
-.mdi-av-play-circle-outline:before {
- content: "\e6bd";
-}
-.mdi-av-play-shopping-bag:before {
- content: "\e6be";
-}
-.mdi-av-playlist-add:before {
- content: "\e6bf";
-}
-.mdi-av-queue-mus:before {
- content: "\e6c0";
-}
-.mdi-av-queue:before {
- content: "\e6c1";
-}
-.mdi-av-radio:before {
- content: "\e6c2";
-}
-.mdi-av-recent-actors:before {
- content: "\e6c3";
-}
-.mdi-av-repeat-one:before {
- content: "\e6c4";
-}
-.mdi-av-repeat:before {
- content: "\e6c5";
-}
-.mdi-av-replay:before {
- content: "\e6c6";
-}
-.mdi-av-shuffle:before {
- content: "\e6c7";
-}
-.mdi-av-skip-next:before {
- content: "\e6c8";
-}
-.mdi-av-skip-previous:before {
- content: "\e6c9";
-}
-.mdi-av-snooze:before {
- content: "\e6ca";
-}
-.mdi-av-stop:before {
- content: "\e6cb";
-}
-.mdi-av-subtitles:before {
- content: "\e6cc";
-}
-.mdi-av-surround-sound:before {
- content: "\e6cd";
-}
-.mdi-av-timer:before {
- content: "\e6ce";
-}
-.mdi-av-video-collection:before {
- content: "\e6cf";
-}
-.mdi-av-videocam-off:before {
- content: "\e6d0";
-}
-.mdi-av-videocam:before {
- content: "\e6d1";
-}
-.mdi-av-volume-down:before {
- content: "\e6d2";
-}
-.mdi-av-volume-mute:before {
- content: "\e6d3";
-}
-.mdi-av-volume-off:before {
- content: "\e6d4";
-}
-.mdi-av-volume-up:before {
- content: "\e6d5";
-}
-.mdi-av-web:before {
- content: "\e6d6";
-}
-.mdi-communication-business:before {
- content: "\e6d7";
-}
-.mdi-communication-call-end:before {
- content: "\e6d8";
-}
-.mdi-communication-call-made:before {
- content: "\e6d9";
-}
-.mdi-communication-call-merge:before {
- content: "\e6da";
-}
-.mdi-communication-call-missed:before {
- content: "\e6db";
-}
-.mdi-communication-call-received:before {
- content: "\e6dc";
-}
-.mdi-communication-call-split:before {
- content: "\e6dd";
-}
-.mdi-communication-call:before {
- content: "\e6de";
-}
-.mdi-communication-chat:before {
- content: "\e6df";
-}
-.mdi-communication-clear-all:before {
- content: "\e6e0";
-}
-.mdi-communication-comment:before {
- content: "\e6e1";
-}
-.mdi-communication-contacts:before {
- content: "\e6e2";
-}
-.mdi-communication-dialer-sip:before {
- content: "\e6e3";
-}
-.mdi-communication-dialpad:before {
- content: "\e6e4";
-}
-.mdi-communication-dnd-on:before {
- content: "\e6e5";
-}
-.mdi-communication-email:before {
- content: "\e6e6";
-}
-.mdi-communication-forum:before {
- content: "\e6e7";
-}
-.mdi-communication-import-export:before {
- content: "\e6e8";
-}
-.mdi-communication-invert-colors-off:before {
- content: "\e6e9";
-}
-.mdi-communication-invert-colors-on:before {
- content: "\e6ea";
-}
-.mdi-communication-live-help:before {
- content: "\e6eb";
-}
-.mdi-communication-location-off:before {
- content: "\e6ec";
-}
-.mdi-communication-location-on:before {
- content: "\e6ed";
-}
-.mdi-communication-message:before {
- content: "\e6ee";
-}
-.mdi-communication-messenger:before {
- content: "\e6ef";
-}
-.mdi-communication-no-sim:before {
- content: "\e6f0";
-}
-.mdi-communication-phone:before {
- content: "\e6f1";
-}
-.mdi-communication-portable-wifi-off:before {
- content: "\e6f2";
-}
-.mdi-communication-quick-contacts-dialer:before {
- content: "\e6f3";
-}
-.mdi-communication-quick-contacts-mail:before {
- content: "\e6f4";
-}
-.mdi-communication-ring-volume:before {
- content: "\e6f5";
-}
-.mdi-communication-stay-current-landscape:before {
- content: "\e6f6";
-}
-.mdi-communication-stay-current-portrait:before {
- content: "\e6f7";
-}
-.mdi-communication-stay-primary-landscape:before {
- content: "\e6f8";
-}
-.mdi-communication-stay-primary-portrait:before {
- content: "\e6f9";
-}
-.mdi-communication-swap-calls:before {
- content: "\e6fa";
-}
-.mdi-communication-textsms:before {
- content: "\e6fb";
-}
-.mdi-communication-voicemail:before {
- content: "\e6fc";
-}
-.mdi-communication-vpn-key:before {
- content: "\e6fd";
-}
-.mdi-content-add-box:before {
- content: "\e6fe";
-}
-.mdi-content-add-circle-outline:before {
- content: "\e6ff";
-}
-.mdi-content-add-circle:before {
- content: "\e700";
-}
-.mdi-content-add:before {
- content: "\e701";
-}
-.mdi-content-archive:before {
- content: "\e702";
-}
-.mdi-content-backspace:before {
- content: "\e703";
-}
-.mdi-content-block:before {
- content: "\e704";
-}
-.mdi-content-clear:before {
- content: "\e705";
-}
-.mdi-content-content-copy:before {
- content: "\e706";
-}
-.mdi-content-content-cut:before {
- content: "\e707";
-}
-.mdi-content-content-paste:before {
- content: "\e708";
-}
-.mdi-content-create:before {
- content: "\e709";
-}
-.mdi-content-drafts:before {
- content: "\e70a";
-}
-.mdi-content-filter-list:before {
- content: "\e70b";
-}
-.mdi-content-flag:before {
- content: "\e70c";
-}
-.mdi-content-forward:before {
- content: "\e70d";
-}
-.mdi-content-gesture:before {
- content: "\e70e";
-}
-.mdi-content-inbox:before {
- content: "\e70f";
-}
-.mdi-content-link:before {
- content: "\e710";
-}
-.mdi-content-mail:before {
- content: "\e711";
-}
-.mdi-content-markunread:before {
- content: "\e712";
-}
-.mdi-content-redo:before {
- content: "\e713";
-}
-.mdi-content-remove-circle-outline:before {
- content: "\e714";
-}
-.mdi-content-remove-circle:before {
- content: "\e715";
-}
-.mdi-content-remove:before {
- content: "\e716";
-}
-.mdi-content-reply-all:before {
- content: "\e717";
-}
-.mdi-content-reply:before {
- content: "\e718";
-}
-.mdi-content-report:before {
- content: "\e719";
-}
-.mdi-content-save:before {
- content: "\e71a";
-}
-.mdi-content-select-all:before {
- content: "\e71b";
-}
-.mdi-content-send:before {
- content: "\e71c";
-}
-.mdi-content-sort:before {
- content: "\e71d";
-}
-.mdi-content-text-format:before {
- content: "\e71e";
-}
-.mdi-content-undo:before {
- content: "\e71f";
-}
-.mdi-editor-attach-file:before {
- content: "\e776";
-}
-.mdi-editor-attach-money:before {
- content: "\e777";
-}
-.mdi-editor-border-all:before {
- content: "\e778";
-}
-.mdi-editor-border-bottom:before {
- content: "\e779";
-}
-.mdi-editor-border-clear:before {
- content: "\e77a";
-}
-.mdi-editor-border-color:before {
- content: "\e77b";
-}
-.mdi-editor-border-horizontal:before {
- content: "\e77c";
-}
-.mdi-editor-border-inner:before {
- content: "\e77d";
-}
-.mdi-editor-border-left:before {
- content: "\e77e";
-}
-.mdi-editor-border-outer:before {
- content: "\e77f";
-}
-.mdi-editor-border-right:before {
- content: "\e780";
-}
-.mdi-editor-border-style:before {
- content: "\e781";
-}
-.mdi-editor-border-top:before {
- content: "\e782";
-}
-.mdi-editor-border-vertical:before {
- content: "\e783";
-}
-.mdi-editor-format-align-center:before {
- content: "\e784";
-}
-.mdi-editor-format-align-justify:before {
- content: "\e785";
-}
-.mdi-editor-format-align-left:before {
- content: "\e786";
-}
-.mdi-editor-format-align-right:before {
- content: "\e787";
-}
-.mdi-editor-format-bold:before {
- content: "\e788";
-}
-.mdi-editor-format-clear:before {
- content: "\e789";
-}
-.mdi-editor-format-color-fill:before {
- content: "\e78a";
-}
-.mdi-editor-format-color-reset:before {
- content: "\e78b";
-}
-.mdi-editor-format-color-text:before {
- content: "\e78c";
-}
-.mdi-editor-format-indent-decrease:before {
- content: "\e78d";
-}
-.mdi-editor-format-indent-increase:before {
- content: "\e78e";
-}
-.mdi-editor-format-italic:before {
- content: "\e78f";
-}
-.mdi-editor-format-line-spacing:before {
- content: "\e790";
-}
-.mdi-editor-format-list-bulleted:before {
- content: "\e791";
-}
-.mdi-editor-format-list-numbered:before {
- content: "\e792";
-}
-.mdi-editor-format-paint:before {
- content: "\e793";
-}
-.mdi-editor-format-quote:before {
- content: "\e794";
-}
-.mdi-editor-format-size:before {
- content: "\e795";
-}
-.mdi-editor-format-strikethrough:before {
- content: "\e796";
-}
-.mdi-editor-format-textdirection-l-to-r:before {
- content: "\e797";
-}
-.mdi-editor-format-textdirection-r-to-l:before {
- content: "\e798";
-}
-.mdi-editor-format-underline:before {
- content: "\e799";
-}
-.mdi-editor-functions:before {
- content: "\e79a";
-}
-.mdi-editor-insert-chart:before {
- content: "\e79b";
-}
-.mdi-editor-insert-comment:before {
- content: "\e79c";
-}
-.mdi-editor-insert-drive-file:before {
- content: "\e79d";
-}
-.mdi-editor-insert-emoticon:before {
- content: "\e79e";
-}
-.mdi-editor-insert-invitation:before {
- content: "\e79f";
-}
-.mdi-editor-insert-link:before {
- content: "\e7a0";
-}
-.mdi-editor-insert-photo:before {
- content: "\e7a1";
-}
-.mdi-editor-merge-type:before {
- content: "\e7a2";
-}
-.mdi-editor-mode-comment:before {
- content: "\e7a3";
-}
-.mdi-editor-mode-edit:before {
- content: "\e7a4";
-}
-.mdi-editor-publish:before {
- content: "\e7a5";
-}
-.mdi-editor-vertical-align-bottom:before {
- content: "\e7a6";
-}
-.mdi-editor-vertical-align-center:before {
- content: "\e7a7";
-}
-.mdi-editor-vertical-align-top:before {
- content: "\e7a8";
-}
-.mdi-editor-wrap-text:before {
- content: "\e7a9";
-}
-.mdi-file-attachment:before {
- content: "\e7aa";
-}
-.mdi-file-cloud-circle:before {
- content: "\e7ab";
-}
-.mdi-file-cloud-done:before {
- content: "\e7ac";
-}
-.mdi-file-cloud-download:before {
- content: "\e7ad";
-}
-.mdi-file-cloud-off:before {
- content: "\e7ae";
-}
-.mdi-file-cloud-queue:before {
- content: "\e7af";
-}
-.mdi-file-cloud-upload:before {
- content: "\e7b0";
-}
-.mdi-file-cloud:before {
- content: "\e7b1";
-}
-.mdi-file-file-download:before {
- content: "\e7b2";
-}
-.mdi-file-file-upload:before {
- content: "\e7b3";
-}
-.mdi-file-folder-open:before {
- content: "\e7b4";
-}
-.mdi-file-folder-shared:before {
- content: "\e7b5";
-}
-.mdi-file-folder:before {
- content: "\e7b6";
-}
-.mdi-device-access-alarm:before {
- content: "\e720";
-}
-.mdi-device-access-alarms:before {
- content: "\e721";
-}
-.mdi-device-access-time:before {
- content: "\e722";
-}
-.mdi-device-add-alarm:before {
- content: "\e723";
-}
-.mdi-device-airplanemode-off:before {
- content: "\e724";
-}
-.mdi-device-airplanemode-on:before {
- content: "\e725";
-}
-.mdi-device-battery-20:before {
- content: "\e726";
-}
-.mdi-device-battery-30:before {
- content: "\e727";
-}
-.mdi-device-battery-50:before {
- content: "\e728";
-}
-.mdi-device-battery-60:before {
- content: "\e729";
-}
-.mdi-device-battery-80:before {
- content: "\e72a";
-}
-.mdi-device-battery-90:before {
- content: "\e72b";
-}
-.mdi-device-battery-alert:before {
- content: "\e72c";
-}
-.mdi-device-battery-charging-20:before {
- content: "\e72d";
-}
-.mdi-device-battery-charging-30:before {
- content: "\e72e";
-}
-.mdi-device-battery-charging-50:before {
- content: "\e72f";
-}
-.mdi-device-battery-charging-60:before {
- content: "\e730";
-}
-.mdi-device-battery-charging-80:before {
- content: "\e731";
-}
-.mdi-device-battery-charging-90:before {
- content: "\e732";
-}
-.mdi-device-battery-charging-full:before {
- content: "\e733";
-}
-.mdi-device-battery-full:before {
- content: "\e734";
-}
-.mdi-device-battery-std:before {
- content: "\e735";
-}
-.mdi-device-battery-unknown:before {
- content: "\e736";
-}
-.mdi-device-bluetooth-connected:before {
- content: "\e737";
-}
-.mdi-device-bluetooth-disabled:before {
- content: "\e738";
-}
-.mdi-device-bluetooth-searching:before {
- content: "\e739";
-}
-.mdi-device-bluetooth:before {
- content: "\e73a";
-}
-.mdi-device-brightness-auto:before {
- content: "\e73b";
-}
-.mdi-device-brightness-high:before {
- content: "\e73c";
-}
-.mdi-device-brightness-low:before {
- content: "\e73d";
-}
-.mdi-device-brightness-medium:before {
- content: "\e73e";
-}
-.mdi-device-data-usage:before {
- content: "\e73f";
-}
-.mdi-device-developer-mode:before {
- content: "\e740";
-}
-.mdi-device-devices:before {
- content: "\e741";
-}
-.mdi-device-dvr:before {
- content: "\e742";
-}
-.mdi-device-gps-fixed:before {
- content: "\e743";
-}
-.mdi-device-gps-not-fixed:before {
- content: "\e744";
-}
-.mdi-device-gps-off:before {
- content: "\e745";
-}
-.mdi-device-location-disabled:before {
- content: "\e746";
-}
-.mdi-device-location-searching:before {
- content: "\e747";
-}
-.mdi-device-multitrack-audio:before {
- content: "\e748";
-}
-.mdi-device-network-cell:before {
- content: "\e749";
-}
-.mdi-device-network-wifi:before {
- content: "\e74a";
-}
-.mdi-device-nfc:before {
- content: "\e74b";
-}
-.mdi-device-now-wallpaper:before {
- content: "\e74c";
-}
-.mdi-device-now-widgets:before {
- content: "\e74d";
-}
-.mdi-device-screen-lock-landscape:before {
- content: "\e74e";
-}
-.mdi-device-screen-lock-portrait:before {
- content: "\e74f";
-}
-.mdi-device-screen-lock-rotation:before {
- content: "\e750";
-}
-.mdi-device-screen-rotation:before {
- content: "\e751";
-}
-.mdi-device-sd-storage:before {
- content: "\e752";
-}
-.mdi-device-settings-system-daydream:before {
- content: "\e753";
-}
-.mdi-device-signal-cellular-0-bar:before {
- content: "\e754";
-}
-.mdi-device-signal-cellular-1-bar:before {
- content: "\e755";
-}
-.mdi-device-signal-cellular-2-bar:before {
- content: "\e756";
-}
-.mdi-device-signal-cellular-3-bar:before {
- content: "\e757";
-}
-.mdi-device-signal-cellular-4-bar:before {
- content: "\e758";
-}
-.mdi-signal-wifi-statusbar-connected-no-internet-after:before {
- content: "\e8f6";
-}
-.mdi-device-signal-cellular-connected-no-internet-0-bar:before {
- content: "\e759";
-}
-.mdi-device-signal-cellular-connected-no-internet-1-bar:before {
- content: "\e75a";
-}
-.mdi-device-signal-cellular-connected-no-internet-2-bar:before {
- content: "\e75b";
-}
-.mdi-device-signal-cellular-connected-no-internet-3-bar:before {
- content: "\e75c";
-}
-.mdi-device-signal-cellular-connected-no-internet-4-bar:before {
- content: "\e75d";
-}
-.mdi-device-signal-cellular-no-sim:before {
- content: "\e75e";
-}
-.mdi-device-signal-cellular-null:before {
- content: "\e75f";
-}
-.mdi-device-signal-cellular-off:before {
- content: "\e760";
-}
-.mdi-device-signal-wifi-0-bar:before {
- content: "\e761";
-}
-.mdi-device-signal-wifi-1-bar:before {
- content: "\e762";
-}
-.mdi-device-signal-wifi-2-bar:before {
- content: "\e763";
-}
-.mdi-device-signal-wifi-3-bar:before {
- content: "\e764";
-}
-.mdi-device-signal-wifi-4-bar:before {
- content: "\e765";
-}
-.mdi-device-signal-wifi-off:before {
- content: "\e766";
-}
-.mdi-device-signal-wifi-statusbar-1-bar:before {
- content: "\e767";
-}
-.mdi-device-signal-wifi-statusbar-2-bar:before {
- content: "\e768";
-}
-.mdi-device-signal-wifi-statusbar-3-bar:before {
- content: "\e769";
-}
-.mdi-device-signal-wifi-statusbar-4-bar:before {
- content: "\e76a";
-}
-.mdi-device-signal-wifi-statusbar-connected-no-internet-:before {
- content: "\e76b";
-}
-.mdi-device-signal-wifi-statusbar-connected-no-internet:before {
- content: "\e76f";
-}
-.mdi-device-signal-wifi-statusbar-connected-no-internet-2:before {
- content: "\e76c";
-}
-.mdi-device-signal-wifi-statusbar-connected-no-internet-3:before {
- content: "\e76d";
-}
-.mdi-device-signal-wifi-statusbar-connected-no-internet-4:before {
- content: "\e76e";
-}
-.mdi-signal-wifi-statusbar-not-connected-after:before {
- content: "\e8f7";
-}
-.mdi-device-signal-wifi-statusbar-not-connected:before {
- content: "\e770";
-}
-.mdi-device-signal-wifi-statusbar-null:before {
- content: "\e771";
-}
-.mdi-device-storage:before {
- content: "\e772";
-}
-.mdi-device-usb:before {
- content: "\e773";
-}
-.mdi-device-wifi-lock:before {
- content: "\e774";
-}
-.mdi-device-wifi-tethering:before {
- content: "\e775";
-}
-.mdi-hardware-cast-connected:before {
- content: "\e7b7";
-}
-.mdi-hardware-cast:before {
- content: "\e7b8";
-}
-.mdi-hardware-computer:before {
- content: "\e7b9";
-}
-.mdi-hardware-desktop-mac:before {
- content: "\e7ba";
-}
-.mdi-hardware-desktop-windows:before {
- content: "\e7bb";
-}
-.mdi-hardware-dock:before {
- content: "\e7bc";
-}
-.mdi-hardware-gamepad:before {
- content: "\e7bd";
-}
-.mdi-hardware-headset-mic:before {
- content: "\e7be";
-}
-.mdi-hardware-headset:before {
- content: "\e7bf";
-}
-.mdi-hardware-keyboard-alt:before {
- content: "\e7c0";
-}
-.mdi-hardware-keyboard-arrow-down:before {
- content: "\e7c1";
-}
-.mdi-hardware-keyboard-arrow-left:before {
- content: "\e7c2";
-}
-.mdi-hardware-keyboard-arrow-right:before {
- content: "\e7c3";
-}
-.mdi-hardware-keyboard-arrow-up:before {
- content: "\e7c4";
-}
-.mdi-hardware-keyboard-backspace:before {
- content: "\e7c5";
-}
-.mdi-hardware-keyboard-capslock:before {
- content: "\e7c6";
-}
-.mdi-hardware-keyboard-control:before {
- content: "\e7c7";
-}
-.mdi-hardware-keyboard-hide:before {
- content: "\e7c8";
-}
-.mdi-hardware-keyboard-return:before {
- content: "\e7c9";
-}
-.mdi-hardware-keyboard-tab:before {
- content: "\e7ca";
-}
-.mdi-hardware-keyboard-voice:before {
- content: "\e7cb";
-}
-.mdi-hardware-keyboard:before {
- content: "\e7cc";
-}
-.mdi-hardware-laptop-chromebook:before {
- content: "\e7cd";
-}
-.mdi-hardware-laptop-mac:before {
- content: "\e7ce";
-}
-.mdi-hardware-laptop-windows:before {
- content: "\e7cf";
-}
-.mdi-hardware-laptop:before {
- content: "\e7d0";
-}
-.mdi-hardware-memory:before {
- content: "\e7d1";
-}
-.mdi-hardware-mouse:before {
- content: "\e7d2";
-}
-.mdi-hardware-phone-android:before {
- content: "\e7d3";
-}
-.mdi-hardware-phone-iphone:before {
- content: "\e7d4";
-}
-.mdi-hardware-phonelink-off:before {
- content: "\e7d5";
-}
-.mdi-hardware-phonelink:before {
- content: "\e7d6";
-}
-.mdi-hardware-security:before {
- content: "\e7d7";
-}
-.mdi-hardware-sim-card:before {
- content: "\e7d8";
-}
-.mdi-hardware-smartphone:before {
- content: "\e7d9";
-}
-.mdi-hardware-speaker:before {
- content: "\e7da";
-}
-.mdi-hardware-tablet-android:before {
- content: "\e7db";
-}
-.mdi-hardware-tablet-mac:before {
- content: "\e7dc";
-}
-.mdi-hardware-tablet:before {
- content: "\e7dd";
-}
-.mdi-hardware-tv:before {
- content: "\e7de";
-}
-.mdi-hardware-watch:before {
- content: "\e7df";
-}
-.mdi-image-add-to-photos:before {
- content: "\e7e0";
-}
-.mdi-image-adjust:before {
- content: "\e7e1";
-}
-.mdi-image-assistant-photo:before {
- content: "\e7e2";
-}
-.mdi-image-audiotrack:before {
- content: "\e7e3";
-}
-.mdi-image-blur-circular:before {
- content: "\e7e4";
-}
-.mdi-image-blur-linear:before {
- content: "\e7e5";
-}
-.mdi-image-blur-off:before {
- content: "\e7e6";
-}
-.mdi-image-blur-on:before {
- content: "\e7e7";
-}
-.mdi-image-brightness-1:before {
- content: "\e7e8";
-}
-.mdi-image-brightness-2:before {
- content: "\e7e9";
-}
-.mdi-image-brightness-3:before {
- content: "\e7ea";
-}
-.mdi-image-brightness-4:before {
- content: "\e7eb";
-}
-.mdi-image-brightness-5:before {
- content: "\e7ec";
-}
-.mdi-image-brightness-6:before {
- content: "\e7ed";
-}
-.mdi-image-brightness-7:before {
- content: "\e7ee";
-}
-.mdi-image-brush:before {
- content: "\e7ef";
-}
-.mdi-image-camera-alt:before {
- content: "\e7f0";
-}
-.mdi-image-camera-front:before {
- content: "\e7f1";
-}
-.mdi-image-camera-rear:before {
- content: "\e7f2";
-}
-.mdi-image-camera-roll:before {
- content: "\e7f3";
-}
-.mdi-image-camera:before {
- content: "\e7f4";
-}
-.mdi-image-center-focus-strong:before {
- content: "\e7f5";
-}
-.mdi-image-center-focus-weak:before {
- content: "\e7f6";
-}
-.mdi-image-collections:before {
- content: "\e7f7";
-}
-.mdi-image-color-lens:before {
- content: "\e7f8";
-}
-.mdi-image-colorize:before {
- content: "\e7f9";
-}
-.mdi-image-compare:before {
- content: "\e7fa";
-}
-.mdi-image-control-point-duplicate:before {
- content: "\e7fb";
-}
-.mdi-image-control-point:before {
- content: "\e7fc";
-}
-.mdi-image-crop-3-2:before {
- content: "\e7fd";
-}
-.mdi-image-crop-5-4:before {
- content: "\e7fe";
-}
-.mdi-image-crop-7-5:before {
- content: "\e7ff";
-}
-.mdi-image-crop-16-9:before {
- content: "\e800";
-}
-.mdi-image-crop-din:before {
- content: "\e801";
-}
-.mdi-image-crop-free:before {
- content: "\e802";
-}
-.mdi-image-crop-landscape:before {
- content: "\e803";
-}
-.mdi-image-crop-original:before {
- content: "\e804";
-}
-.mdi-image-crop-portrait:before {
- content: "\e805";
-}
-.mdi-image-crop-square:before {
- content: "\e806";
-}
-.mdi-image-crop:before {
- content: "\e807";
-}
-.mdi-image-dehaze:before {
- content: "\e808";
-}
-.mdi-image-details:before {
- content: "\e809";
-}
-.mdi-image-edit:before {
- content: "\e80a";
-}
-.mdi-image-exposure-minus-1:before {
- content: "\e80b";
-}
-.mdi-image-exposure-minus-2:before {
- content: "\e80c";
-}
-.mdi-image-exposure-plus-1:before {
- content: "\e80d";
-}
-.mdi-image-exposure-plus-2:before {
- content: "\e80e";
-}
-.mdi-image-exposure-zero:before {
- content: "\e80f";
-}
-.mdi-image-exposure:before {
- content: "\e810";
-}
-.mdi-image-filter-1:before {
- content: "\e811";
-}
-.mdi-image-filter-2:before {
- content: "\e812";
-}
-.mdi-image-filter-3:before {
- content: "\e813";
-}
-.mdi-image-filter-4:before {
- content: "\e814";
-}
-.mdi-image-filter-5:before {
- content: "\e815";
-}
-.mdi-image-filter-6:before {
- content: "\e816";
-}
-.mdi-image-filter-7:before {
- content: "\e817";
-}
-.mdi-image-filter-8:before {
- content: "\e818";
-}
-.mdi-image-filter-9-plus:before {
- content: "\e819";
-}
-.mdi-image-filter-9:before {
- content: "\e81a";
-}
-.mdi-image-filter-b-and-w:before {
- content: "\e81b";
-}
-.mdi-image-filter-center-focus:before {
- content: "\e81c";
-}
-.mdi-image-filter-drama:before {
- content: "\e81d";
-}
-.mdi-image-filter-frames:before {
- content: "\e81e";
-}
-.mdi-image-filter-hdr:before {
- content: "\e81f";
-}
-.mdi-image-filter-none:before {
- content: "\e820";
-}
-.mdi-image-filter-tilt-shift:before {
- content: "\e821";
-}
-.mdi-image-filter-vintage:before {
- content: "\e822";
-}
-.mdi-image-filter:before {
- content: "\e823";
-}
-.mdi-image-flare:before {
- content: "\e824";
-}
-.mdi-image-flash-auto:before {
- content: "\e825";
-}
-.mdi-image-flash-off:before {
- content: "\e826";
-}
-.mdi-image-flash-on:before {
- content: "\e827";
-}
-.mdi-image-flip:before {
- content: "\e828";
-}
-.mdi-image-gradient:before {
- content: "\e829";
-}
-.mdi-image-grain:before {
- content: "\e82a";
-}
-.mdi-image-grid-off:before {
- content: "\e82b";
-}
-.mdi-image-grid-on:before {
- content: "\e82c";
-}
-.mdi-image-hdr-off:before {
- content: "\e82d";
-}
-.mdi-image-hdr-on:before {
- content: "\e82e";
-}
-.mdi-image-hdr-strong:before {
- content: "\e82f";
-}
-.mdi-image-hdr-weak:before {
- content: "\e830";
-}
-.mdi-image-healing:before {
- content: "\e831";
-}
-.mdi-image-image-aspect-ratio:before {
- content: "\e832";
-}
-.mdi-image-image:before {
- content: "\e833";
-}
-.mdi-image-iso:before {
- content: "\e834";
-}
-.mdi-image-landscape:before {
- content: "\e835";
-}
-.mdi-image-leak-add:before {
- content: "\e836";
-}
-.mdi-image-leak-remove:before {
- content: "\e837";
-}
-.mdi-image-lens:before {
- content: "\e838";
-}
-.mdi-image-looks-3:before {
- content: "\e839";
-}
-.mdi-image-looks-4:before {
- content: "\e83a";
-}
-.mdi-image-looks-5:before {
- content: "\e83b";
-}
-.mdi-image-looks-6:before {
- content: "\e83c";
-}
-.mdi-image-looks-one:before {
- content: "\e83d";
-}
-.mdi-image-looks-two:before {
- content: "\e83e";
-}
-.mdi-image-looks:before {
- content: "\e83f";
-}
-.mdi-image-loupe:before {
- content: "\e840";
-}
-.mdi-image-movie-creation:before {
- content: "\e841";
-}
-.mdi-image-nature-people:before {
- content: "\e842";
-}
-.mdi-image-nature:before {
- content: "\e843";
-}
-.mdi-image-navigate-before:before {
- content: "\e844";
-}
-.mdi-image-navigate-next:before {
- content: "\e845";
-}
-.mdi-image-palette:before {
- content: "\e846";
-}
-.mdi-image-panorama-fisheye:before {
- content: "\e847";
-}
-.mdi-image-panorama-horizontal:before {
- content: "\e848";
-}
-.mdi-image-panorama-vertical:before {
- content: "\e849";
-}
-.mdi-image-panorama-wide-angle:before {
- content: "\e84a";
-}
-.mdi-image-panorama:before {
- content: "\e84b";
-}
-.mdi-image-photo-album:before {
- content: "\e84c";
-}
-.mdi-image-photo-camera:before {
- content: "\e84d";
-}
-.mdi-image-photo-library:before {
- content: "\e84e";
-}
-.mdi-image-photo:before {
- content: "\e84f";
-}
-.mdi-image-portrait:before {
- content: "\e850";
-}
-.mdi-image-remove-red-eye:before {
- content: "\e851";
-}
-.mdi-image-rotate-left:before {
- content: "\e852";
-}
-.mdi-image-rotate-right:before {
- content: "\e853";
-}
-.mdi-image-slideshow:before {
- content: "\e854";
-}
-.mdi-image-straighten:before {
- content: "\e855";
-}
-.mdi-image-style:before {
- content: "\e856";
-}
-.mdi-image-switch-camera:before {
- content: "\e857";
-}
-.mdi-image-switch-video:before {
- content: "\e858";
-}
-.mdi-image-tag-faces:before {
- content: "\e859";
-}
-.mdi-image-texture:before {
- content: "\e85a";
-}
-.mdi-image-timelapse:before {
- content: "\e85b";
-}
-.mdi-image-timer-3:before {
- content: "\e85c";
-}
-.mdi-image-timer-10:before {
- content: "\e85d";
-}
-.mdi-image-timer-auto:before {
- content: "\e85e";
-}
-.mdi-image-timer-off:before {
- content: "\e85f";
-}
-.mdi-image-timer:before {
- content: "\e860";
-}
-.mdi-image-tonality:before {
- content: "\e861";
-}
-.mdi-image-transform:before {
- content: "\e862";
-}
-.mdi-image-tune:before {
- content: "\e863";
-}
-.mdi-image-wb-auto:before {
- content: "\e864";
-}
-.mdi-image-wb-cloudy:before {
- content: "\e865";
-}
-.mdi-image-wb-incandescent:before {
- content: "\e866";
-}
-.mdi-image-wb-irradescent:before {
- content: "\e867";
-}
-.mdi-image-wb-sunny:before {
- content: "\e868";
-}
-.mdi-maps-beenhere:before {
- content: "\e869";
-}
-.mdi-maps-directions-bike:before {
- content: "\e86a";
-}
-.mdi-maps-directions-bus:before {
- content: "\e86b";
-}
-.mdi-maps-directions-car:before {
- content: "\e86c";
-}
-.mdi-maps-directions-ferry:before {
- content: "\e86d";
-}
-.mdi-maps-directions-subway:before {
- content: "\e86e";
-}
-.mdi-maps-directions-train:before {
- content: "\e86f";
-}
-.mdi-maps-directions-transit:before {
- content: "\e870";
-}
-.mdi-maps-directions-walk:before {
- content: "\e871";
-}
-.mdi-maps-directions:before {
- content: "\e872";
-}
-.mdi-maps-flight:before {
- content: "\e873";
-}
-.mdi-maps-hotel:before {
- content: "\e874";
-}
-.mdi-maps-layers-clear:before {
- content: "\e875";
-}
-.mdi-maps-layers:before {
- content: "\e876";
-}
-.mdi-maps-local-airport:before {
- content: "\e877";
-}
-.mdi-maps-local-atm:before {
- content: "\e878";
-}
-.mdi-maps-local-attraction:before {
- content: "\e879";
-}
-.mdi-maps-local-bar:before {
- content: "\e87a";
-}
-.mdi-maps-local-cafe:before {
- content: "\e87b";
-}
-.mdi-maps-local-car-wash:before {
- content: "\e87c";
-}
-.mdi-maps-local-convenience-store:before {
- content: "\e87d";
-}
-.mdi-maps-local-drink:before {
- content: "\e87e";
-}
-.mdi-maps-local-florist:before {
- content: "\e87f";
-}
-.mdi-maps-local-gas-station:before {
- content: "\e880";
-}
-.mdi-maps-local-grocery-store:before {
- content: "\e881";
-}
-.mdi-maps-local-hospital:before {
- content: "\e882";
-}
-.mdi-maps-local-hotel:before {
- content: "\e883";
-}
-.mdi-maps-local-laundry-service:before {
- content: "\e884";
-}
-.mdi-maps-local-library:before {
- content: "\e885";
-}
-.mdi-maps-local-mall:before {
- content: "\e886";
-}
-.mdi-maps-local-movies:before {
- content: "\e887";
-}
-.mdi-maps-local-offer:before {
- content: "\e888";
-}
-.mdi-maps-local-parking:before {
- content: "\e889";
-}
-.mdi-maps-local-pharmacy:before {
- content: "\e88a";
-}
-.mdi-maps-local-phone:before {
- content: "\e88b";
-}
-.mdi-maps-local-pizza:before {
- content: "\e88c";
-}
-.mdi-maps-local-play:before {
- content: "\e88d";
-}
-.mdi-maps-local-post-office:before {
- content: "\e88e";
-}
-.mdi-maps-local-print-shop:before {
- content: "\e88f";
-}
-.mdi-maps-local-restaurant:before {
- content: "\e890";
-}
-.mdi-maps-local-see:before {
- content: "\e891";
-}
-.mdi-maps-local-shipping:before {
- content: "\e892";
-}
-.mdi-maps-local-taxi:before {
- content: "\e893";
-}
-.mdi-maps-location-history:before {
- content: "\e894";
-}
-.mdi-maps-map:before {
- content: "\e895";
-}
-.mdi-maps-my-location:before {
- content: "\e896";
-}
-.mdi-maps-navigation:before {
- content: "\e897";
-}
-.mdi-maps-pin-drop:before {
- content: "\e898";
-}
-.mdi-maps-place:before {
- content: "\e899";
-}
-.mdi-maps-rate-review:before {
- content: "\e89a";
-}
-.mdi-maps-restaurant-menu:before {
- content: "\e89b";
-}
-.mdi-maps-satellite:before {
- content: "\e89c";
-}
-.mdi-maps-store-mall-directory:before {
- content: "\e89d";
-}
-.mdi-maps-terrain:before {
- content: "\e89e";
-}
-.mdi-maps-traffic:before {
- content: "\e89f";
-}
-.mdi-navigation-apps:before {
- content: "\e8a0";
-}
-.mdi-navigation-arrow-back:before {
- content: "\e8a1";
-}
-.mdi-navigation-arrow-drop-down-circle:before {
- content: "\e8a2";
-}
-.mdi-navigation-arrow-drop-down:before {
- content: "\e8a3";
-}
-.mdi-navigation-arrow-drop-up:before {
- content: "\e8a4";
-}
-.mdi-navigation-arrow-forward:before {
- content: "\e8a5";
-}
-.mdi-navigation-cancel:before {
- content: "\e8a6";
-}
-.mdi-navigation-check:before {
- content: "\e8a7";
-}
-.mdi-navigation-chevron-left:before {
- content: "\e8a8";
-}
-.mdi-navigation-chevron-right:before {
- content: "\e8a9";
-}
-.mdi-navigation-close:before {
- content: "\e8aa";
-}
-.mdi-navigation-expand-less:before {
- content: "\e8ab";
-}
-.mdi-navigation-expand-more:before {
- content: "\e8ac";
-}
-.mdi-navigation-fullscreen-exit:before {
- content: "\e8ad";
-}
-.mdi-navigation-fullscreen:before {
- content: "\e8ae";
-}
-.mdi-navigation-menu:before {
- content: "\e8af";
-}
-.mdi-navigation-more-horiz:before {
- content: "\e8b0";
-}
-.mdi-navigation-more-vert:before {
- content: "\e8b1";
-}
-.mdi-navigation-refresh:before {
- content: "\e8b2";
-}
-.mdi-navigation-unfold-less:before {
- content: "\e8b3";
-}
-.mdi-navigation-unfold-more:before {
- content: "\e8b4";
-}
-.mdi-notification-adb:before {
- content: "\e8b5";
-}
-.mdi-notification-bluetooth-audio:before {
- content: "\e8b6";
-}
-.mdi-notification-disc-full:before {
- content: "\e8b7";
-}
-.mdi-notification-dnd-forwardslash:before {
- content: "\e8b8";
-}
-.mdi-notification-do-not-disturb:before {
- content: "\e8b9";
-}
-.mdi-notification-drive-eta:before {
- content: "\e8ba";
-}
-.mdi-notification-event-available:before {
- content: "\e8bb";
-}
-.mdi-notification-event-busy:before {
- content: "\e8bc";
-}
-.mdi-notification-event-note:before {
- content: "\e8bd";
-}
-.mdi-notification-folder-special:before {
- content: "\e8be";
-}
-.mdi-notification-mms:before {
- content: "\e8bf";
-}
-.mdi-notification-more:before {
- content: "\e8c0";
-}
-.mdi-notification-network-locked:before {
- content: "\e8c1";
-}
-.mdi-notification-phone-bluetooth-speaker:before {
- content: "\e8c2";
-}
-.mdi-notification-phone-forwarded:before {
- content: "\e8c3";
-}
-.mdi-notification-phone-in-talk:before {
- content: "\e8c4";
-}
-.mdi-notification-phone-locked:before {
- content: "\e8c5";
-}
-.mdi-notification-phone-missed:before {
- content: "\e8c6";
-}
-.mdi-notification-phone-paused:before {
- content: "\e8c7";
-}
-.mdi-notification-play-download:before {
- content: "\e8c8";
-}
-.mdi-notification-play-install:before {
- content: "\e8c9";
-}
-.mdi-notification-sd-card:before {
- content: "\e8ca";
-}
-.mdi-notification-sim-card-alert:before {
- content: "\e8cb";
-}
-.mdi-notification-sms-failed:before {
- content: "\e8cc";
-}
-.mdi-notification-sms:before {
- content: "\e8cd";
-}
-.mdi-notification-sync-disabled:before {
- content: "\e8ce";
-}
-.mdi-notification-sync-problem:before {
- content: "\e8cf";
-}
-.mdi-notification-sync:before {
- content: "\e8d0";
-}
-.mdi-notification-system-update:before {
- content: "\e8d1";
-}
-.mdi-notification-tap-and-play:before {
- content: "\e8d2";
-}
-.mdi-notification-time-to-leave:before {
- content: "\e8d3";
-}
-.mdi-notification-vibration:before {
- content: "\e8d4";
-}
-.mdi-notification-voice-chat:before {
- content: "\e8d5";
-}
-.mdi-notification-vpn-lock:before {
- content: "\e8d6";
-}
-.mdi-social-cake:before {
- content: "\e8d7";
-}
-.mdi-social-domain:before {
- content: "\e8d8";
-}
-.mdi-social-group-add:before {
- content: "\e8d9";
-}
-.mdi-social-group:before {
- content: "\e8da";
-}
-.mdi-social-location-city:before {
- content: "\e8db";
-}
-.mdi-social-mood:before {
- content: "\e8dc";
-}
-.mdi-social-notifications-none:before {
- content: "\e8dd";
-}
-.mdi-social-notifications-off:before {
- content: "\e8de";
-}
-.mdi-social-notifications-on:before {
- content: "\e8df";
-}
-.mdi-social-notifications-paused:before {
- content: "\e8e0";
-}
-.mdi-social-notifications:before {
- content: "\e8e1";
-}
-.mdi-social-pages:before {
- content: "\e8e2";
-}
-.mdi-social-party-mode:before {
- content: "\e8e3";
-}
-.mdi-social-people-outline:before {
- content: "\e8e4";
-}
-.mdi-social-people:before {
- content: "\e8e5";
-}
-.mdi-social-person-add:before {
- content: "\e8e6";
-}
-.mdi-social-person-outline:before {
- content: "\e8e7";
-}
-.mdi-social-person:before {
- content: "\e8e8";
-}
-.mdi-social-plus-one:before {
- content: "\e8e9";
-}
-.mdi-social-poll:before {
- content: "\e8ea";
-}
-.mdi-social-publ24px:before {
- content: "\e8eb";
-}
-.mdi-social-school:before {
- content: "\e8ec";
-}
-.mdi-social-share:before {
- content: "\e8ed";
-}
-.mdi-social-whatshot:before {
- content: "\e8ee";
-}
-.mdi-toggle-check-box-outline-blank:before {
- content: "\e8ef";
-}
-.mdi-toggle-check-box:before {
- content: "\e8f0";
-}
-.mdi-toggle-radio-button-off:before {
- content: "\e8f1";
-}
-.mdi-toggle-radio-button-on:before {
- content: "\e8f2";
-}
-.mdi-toggle-star-half:before {
- content: "\e8f3";
-}
-.mdi-toggle-star-outline:before {
- content: "\e8f4";
-}
-.mdi-toggle-star:before {
- content: "\e8f5";
-} \ No newline at end of file
diff --git a/doc/_extensions/odoo_ext/static/mixins.less b/doc/_extensions/odoo_ext/static/mixins.less
deleted file mode 100644
index 151791eb0d2..00000000000
--- a/doc/_extensions/odoo_ext/static/mixins.less
+++ /dev/null
@@ -1,277 +0,0 @@
-// ================================================
-// ================ Mixins =======================
-// ================================================
-
-// Code column layout mixins
-// ------------------------------------------------------------------
-.pseudo-col() {
- position: relative;
- min-height: 1px;
- padding-right: 15px;
- padding-left: 15px;
- float: left;
- width: 100%;
-}
-
-.code-col() {
- content: "";
- background: @doc_code-bg;
- .box-shadow(inset 40px 0 40px -18px rgba(22, 24, 29, 0.3));
- .o-position-absolute(0,0);
- .size(50%, 100%);
-}
-
-// Utilities
-// ------------------------------------------------------------------
-.o-no-select {
- pointer-events: none;
- cursor: default;
- &, & * {
- &::selection {
- background: transparent;
- }
- &::-moz-selection {
- background: transparent;
- }
- }
-}
-
-.o-position-absolute(@top: auto, @right: auto, @bottom: auto, @left: auto) {
- position: absolute;
- top: @top;
- left: @left;
- bottom: @bottom;
- right: @right;
-}
-
-.o-transform-origin(@x: 50%, @y: 50%, @z: 0) {
- -ms-transform-origin: @x @y @z;
- -webkit-transform-origin: @x @y @z;
- -moz-transform-origin: @x @y @z;
- transform-origin: @x @y @z;
-}
-
-.o-transition(@property: all, @duration: 0s, @timing-function: ease, @transition-delay: 0s) {
- -webkit-transition: @property @duration @timing-function @transition-delay;
- -moz-transition: @property @duration @timing-function @transition-delay;
- -o-transition: @property @duration @timing-function @transition-delay;
- transition: @property @duration @timing-function @transition-delay;
-}
-
-// Backgrounds
-// ------------------------------------------------------------------
-.o-svg-bg(@file_name,@file_ext,@x:50%, @y:50%, @repeat: no-repeat, @folder: '') {
- @std-url: url("img/@{folder}@{file_name}.@{file_ext}");
- @svg-url: url("img/@{folder}@{file_name}.svg");
- background-image: @std-url;
- background-image: @svg-url;
- background-position: @x @y;
- background-repeat: @repeat;
-}
-
-.o-retina-bg(@img,@x:50%, @y:50%, @repeat: no-repeat, @folder: '') {
- @std-url: url("img/@{folder}@{img}");
- background-image: @std-url;
- background-position: @x @y;
- background-repeat: @repeat;
-
- @media
- only screen and (-webkit-min-device-pixel-ratio: 2),
- only screen and ( min--moz-device-pixel-ratio: 2),
- only screen and ( -o-min-device-pixel-ratio: 2/1),
- only screen and ( min-device-pixel-ratio: 2),
- only screen and ( min-resolution: 192dpi),
- only screen and ( min-resolution: 2dppx) {
- @2x-url: url("img/@{folder}@{website-2x-prefix}@{img}");
- background-image: @2x-url;
- }
-}
-
-.o-gradient(@deg: 99deg , @startColor: @o-violet-dark, @endColor: @o-violet-darker, @startOffset: 10%, @endOffset: 90%) {
- background: mix(@startColor, @endColor);
- background: -webkit-linear-gradient(@deg, @startColor @startOffset, @endColor @endOffset);
- background: -moz-linear-gradient(@deg, @startColor @startOffset, @endColor @endOffset);
- background: -ms-linear-gradient(@deg, @startColor @startOffset, @endColor @endOffset);
- background: -o-linear-gradient(@deg, @startColor @startOffset, @endColor @endOffset);
- background: linear-gradient(@deg, @startColor @startOffset, @endColor @endOffset);
-}
-
-// Logos
-// ------------------------------------------------------------------
-.o-logo-size(@height) {
- @ratio: 3.135;
- .size((@height * @ratio), @height);
- background-size: auto @height;
-}
-.generate-logo-classes(@n, @i: 15) when (@i =< @n) {
- .o_logo_@{i} {
- .o-logo-size(@i*1px)
- }
- .generate-logo-classes(@n, (@i * 2));
-}
-
-.o_logo {
- .o-svg-bg("odoo_logo","png", 0, 0, no-repeat, "logos/" );
- display: inline-block;
- .o-logo-size(30px); // 30px height is default size
-
- &.center-block,
- &.o_logo_responsive_half {
- position: relative;
- margin-left: auto;
- margin-right: auto;
- display: block;
- }
-
- &.o_logo_responsive {
- background-size: cover;
- width: 100%;
- height: 0;
- padding-bottom: 31.9%;
- }
-
- &.o_logo_responsive_half {
- background-size: cover;
- width: 50%;
- height: 0;
- padding-bottom: 15.94%;
- }
-}
-
-// Generate Logo's sizes classes
-// heights: 15 - 30 - 60 - 120 - 240
-// ------------------------------------------------------------------
-.generate-logo-classes(240);
-
-&.o_logo_inverse {
- background-position: 100% 0;
- &.o_logo_15.center-block {
- background-position: 102% 0;
- }
-}
-
-// Shadows
-// --------------------------------------------------
-.deep-1() {
- box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.17);
-}
-
-.transform(@args) {
- -webkit-transform : @args;
- -moz-transform : @args;
- -ms-transform : @args;
- -o-transform : @args;
- transform : @args;
-}
-
-// Material Design Icons
-// --------------------------------------------------
-.mdi-icon(@content) {
- font-family: 'Material-Design-Icons';
- content: @content;
- display: inline-block;
- text-rendering: geometricPrecision;
- font-size: 1em;
- -webkit-font-smoothing: antialiased;
- -moz-osx-font-smoothing: grayscale;
-}
-
-// Documentation Dropdown style
-// --------------------------------------------------
-.o-doc-dropdown {
- > a.dropdown-toggle {
- padding: 0 5px 0 10px;
- &:after {
- .mdi-icon( "\e7c1");
-
- @media screen and (max-width: @screen-xs-max) {
- font-size: 1.5em
- }
- }
- }
-
- &.open {
- z-index: 1;
- position: relative;
- background-color: @gray-light;
- color: @header-link-normal;
-
- @media screen and (min-width: @screen-sm-min){
- background-color: @w-header-white;
- }
-
- .dropdown-toggle {
- color: @header-link-normal;
-
- &:hover {
- color: @headings-color;
- }
- }
-
- .dropdown-menu {
- margin-top: 0;
- border: none;
- border-radius: 0;
- text-align: left;
- min-width: 100%;
- background-color: @w-header-white;
- padding-bottom: @w-header-height/4;
- .deep-1();
-
- > li > a {
- font-size: 12px;
- display: block;
- color: @header-link-normal;
- float: none;
- text-transform: none;
- font-weight: @fw_medium;
-
- @media screen and (max-width: @screen-xs-max) {
- padding-left: 10px;
- }
- }
- > li.active > a {
- color: white;
- background-color: desaturate(@brand-primary, 40%);
- }
-
- @media screen and (max-width: @screen-xs-max) {
- position: static;
- }
- @media screen and (min-width: @screen-sm-min) {
- background-color: @w-header-white;
- }
- }
- }
-
- &.o_dropdown_mobile_nav {
- margin-left: 0;
-
- > .dropdown-toggle {
- &:after {
- .o-position-absolute(0, 0);
- }
- }
-
- .o_breadcrumb_dropdown_menu > li{
- > a {
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
- }
- > a:before {
- content: "|";
- margin-right: 0.5em;
- }
- &:nth-child(1) > a:before {
- display: none;
- }
- &:nth-child(2) > a:before {
- padding-left: 0.5em;
- }
- &:nth-child(3) > a:before {
- padding-left: 1em;
- }
- }
- }
-}
diff --git a/doc/_extensions/odoo_ext/static/print.less b/doc/_extensions/odoo_ext/static/print.less
deleted file mode 100644
index 997ba7139d5..00000000000
--- a/doc/_extensions/odoo_ext/static/print.less
+++ /dev/null
@@ -1,54 +0,0 @@
-
-@media print {
- body {
-
- header, footer{
- display: none;
- }
-
- #main_navbar{
- position: relative;
- display: block;
- height: 100px!important;
- #main-back {
- display: none;
- }
- #main_title{
- position: relative;
- transform: none;
- }
- .navbar-main{
- display: none!important;
- }
- }
-
- main{
- .opacity(1);
- .animation(none);
- aside{
- display:none;
- }
- article{
- h1, .h1 {
- font-size: 2em;
- }
- h2, .h2{
- font-size: 1.642857143em;
- }
- h3, .h3{
- font-size: 1.25em;
- }
- p, ul, ol, table, blockquote, .alert, .doc-code, .admonition{
- margin-top: inherit;
- margin-bottom: inherit;
- font-size: inherit;
- }
- }
- }
-
- .floating_action_container{
- display: none;
- }
-
- } // /body
-} \ No newline at end of file
diff --git a/doc/_extensions/odoo_ext/static/style.css b/doc/_extensions/odoo_ext/static/style.css
deleted file mode 100644
index 436871ca738..00000000000
--- a/doc/_extensions/odoo_ext/static/style.css
+++ /dev/null
@@ -1,12181 +0,0 @@
-/*!
- * Bootstrap v3.3.6 (http://getbootstrap.com)
- * Copyright 2011-2015 Twitter, Inc.
- * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
- */
-/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */
-html {
- font-family: sans-serif;
- -ms-text-size-adjust: 100%;
- -webkit-text-size-adjust: 100%;
-}
-body {
- margin: 0;
-}
-article,
-aside,
-details,
-figcaption,
-figure,
-footer,
-header,
-hgroup,
-main,
-menu,
-nav,
-section,
-summary {
- display: block;
-}
-audio,
-canvas,
-progress,
-video {
- display: inline-block;
- vertical-align: baseline;
-}
-audio:not([controls]) {
- display: none;
- height: 0;
-}
-[hidden],
-template {
- display: none;
-}
-a {
- background-color: transparent;
-}
-a:active,
-a:hover {
- outline: 0;
-}
-abbr[title] {
- border-bottom: 1px dotted;
-}
-b,
-strong {
- font-weight: bold;
-}
-dfn {
- font-style: italic;
-}
-h1 {
- font-size: 2em;
- margin: 0.67em 0;
-}
-mark {
- background: #ff0;
- color: #000;
-}
-small {
- font-size: 80%;
-}
-sub,
-sup {
- font-size: 75%;
- line-height: 0;
- position: relative;
- vertical-align: baseline;
-}
-sup {
- top: -0.5em;
-}
-sub {
- bottom: -0.25em;
-}
-img {
- border: 0;
-}
-svg:not(:root) {
- overflow: hidden;
-}
-figure {
- margin: 1em 40px;
-}
-hr {
- box-sizing: content-box;
- height: 0;
-}
-pre {
- overflow: auto;
-}
-code,
-kbd,
-pre,
-samp {
- font-family: monospace, monospace;
- font-size: 1em;
-}
-button,
-input,
-optgroup,
-select,
-textarea {
- color: inherit;
- font: inherit;
- margin: 0;
-}
-button {
- overflow: visible;
-}
-button,
-select {
- text-transform: none;
-}
-button,
-html input[type="button"],
-input[type="reset"],
-input[type="submit"] {
- -webkit-appearance: button;
- cursor: pointer;
-}
-button[disabled],
-html input[disabled] {
- cursor: default;
-}
-button::-moz-focus-inner,
-input::-moz-focus-inner {
- border: 0;
- padding: 0;
-}
-input {
- line-height: normal;
-}
-input[type="checkbox"],
-input[type="radio"] {
- box-sizing: border-box;
- padding: 0;
-}
-input[type="number"]::-webkit-inner-spin-button,
-input[type="number"]::-webkit-outer-spin-button {
- height: auto;
-}
-input[type="search"] {
- -webkit-appearance: textfield;
- box-sizing: content-box;
-}
-input[type="search"]::-webkit-search-cancel-button,
-input[type="search"]::-webkit-search-decoration {
- -webkit-appearance: none;
-}
-fieldset {
- border: 1px solid #c0c0c0;
- margin: 0 2px;
- padding: 0.35em 0.625em 0.75em;
-}
-legend {
- border: 0;
- padding: 0;
-}
-textarea {
- overflow: auto;
-}
-optgroup {
- font-weight: bold;
-}
-table {
- border-collapse: collapse;
- border-spacing: 0;
-}
-td,
-th {
- padding: 0;
-}
-/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */
-@media print {
- *,
- *:before,
- *:after {
- background: transparent !important;
- color: #000 !important;
- box-shadow: none !important;
- text-shadow: none !important;
- }
- a,
- a:visited {
- text-decoration: underline;
- }
- a[href]:after {
- content: " (" attr(href) ")";
- }
- abbr[title]:after {
- content: " (" attr(title) ")";
- }
- a[href^="#"]:after,
- a[href^="javascript:"]:after {
- content: "";
- }
- pre,
- blockquote {
- border: 1px solid #999;
- page-break-inside: avoid;
- }
- thead {
- display: table-header-group;
- }
- tr,
- img {
- page-break-inside: avoid;
- }
- img {
- max-width: 100% !important;
- }
- p,
- h2,
- h3 {
- orphans: 3;
- widows: 3;
- }
- h2,
- h3 {
- page-break-after: avoid;
- }
- .navbar {
- display: none;
- }
- .btn > .caret,
- .dropup > .btn > .caret {
- border-top-color: #000 !important;
- }
- .label {
- border: 1px solid #000;
- }
- .table {
- border-collapse: collapse !important;
- }
- .table td,
- .table th {
- background-color: #fff !important;
- }
- .table-bordered th,
- .table-bordered td {
- border: 1px solid #ddd !important;
- }
-}
-@font-face {
- font-family: 'Glyphicons Halflings';
- src: url('../fonts/glyphicons-halflings-regular.eot');
- src: url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('../fonts/glyphicons-halflings-regular.woff2') format('woff2'), url('../fonts/glyphicons-halflings-regular.woff') format('woff'), url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg');
-}
-.glyphicon {
- position: relative;
- top: 1px;
- display: inline-block;
- font-family: 'Glyphicons Halflings';
- font-style: normal;
- font-weight: normal;
- line-height: 1;
- -webkit-font-smoothing: antialiased;
- -moz-osx-font-smoothing: grayscale;
-}
-.glyphicon-asterisk:before {
- content: "\002a";
-}
-.glyphicon-plus:before {
- content: "\002b";
-}
-.glyphicon-euro:before,
-.glyphicon-eur:before {
- content: "\20ac";
-}
-.glyphicon-minus:before {
- content: "\2212";
-}
-.glyphicon-cloud:before {
- content: "\2601";
-}
-.glyphicon-envelope:before {
- content: "\2709";
-}
-.glyphicon-pencil:before {
- content: "\270f";
-}
-.glyphicon-glass:before {
- content: "\e001";
-}
-.glyphicon-music:before {
- content: "\e002";
-}
-.glyphicon-search:before {
- content: "\e003";
-}
-.glyphicon-heart:before {
- content: "\e005";
-}
-.glyphicon-star:before {
- content: "\e006";
-}
-.glyphicon-star-empty:before {
- content: "\e007";
-}
-.glyphicon-user:before {
- content: "\e008";
-}
-.glyphicon-film:before {
- content: "\e009";
-}
-.glyphicon-th-large:before {
- content: "\e010";
-}
-.glyphicon-th:before {
- content: "\e011";
-}
-.glyphicon-th-list:before {
- content: "\e012";
-}
-.glyphicon-ok:before {
- content: "\e013";
-}
-.glyphicon-remove:before {
- content: "\e014";
-}
-.glyphicon-zoom-in:before {
- content: "\e015";
-}
-.glyphicon-zoom-out:before {
- content: "\e016";
-}
-.glyphicon-off:before {
- content: "\e017";
-}
-.glyphicon-signal:before {
- content: "\e018";
-}
-.glyphicon-cog:before {
- content: "\e019";
-}
-.glyphicon-trash:before {
- content: "\e020";
-}
-.glyphicon-home:before {
- content: "\e021";
-}
-.glyphicon-file:before {
- content: "\e022";
-}
-.glyphicon-time:before {
- content: "\e023";
-}
-.glyphicon-road:before {
- content: "\e024";
-}
-.glyphicon-download-alt:before {
- content: "\e025";
-}
-.glyphicon-download:before {
- content: "\e026";
-}
-.glyphicon-upload:before {
- content: "\e027";
-}
-.glyphicon-inbox:before {
- content: "\e028";
-}
-.glyphicon-play-circle:before {
- content: "\e029";
-}
-.glyphicon-repeat:before {
- content: "\e030";
-}
-.glyphicon-refresh:before {
- content: "\e031";
-}
-.glyphicon-list-alt:before {
- content: "\e032";
-}
-.glyphicon-lock:before {
- content: "\e033";
-}
-.glyphicon-flag:before {
- content: "\e034";
-}
-.glyphicon-headphones:before {
- content: "\e035";
-}
-.glyphicon-volume-off:before {
- content: "\e036";
-}
-.glyphicon-volume-down:before {
- content: "\e037";
-}
-.glyphicon-volume-up:before {
- content: "\e038";
-}
-.glyphicon-qrcode:before {
- content: "\e039";
-}
-.glyphicon-barcode:before {
- content: "\e040";
-}
-.glyphicon-tag:before {
- content: "\e041";
-}
-.glyphicon-tags:before {
- content: "\e042";
-}
-.glyphicon-book:before {
- content: "\e043";
-}
-.glyphicon-bookmark:before {
- content: "\e044";
-}
-.glyphicon-print:before {
- content: "\e045";
-}
-.glyphicon-camera:before {
- content: "\e046";
-}
-.glyphicon-font:before {
- content: "\e047";
-}
-.glyphicon-bold:before {
- content: "\e048";
-}
-.glyphicon-italic:before {
- content: "\e049";
-}
-.glyphicon-text-height:before {
- content: "\e050";
-}
-.glyphicon-text-width:before {
- content: "\e051";
-}
-.glyphicon-align-left:before {
- content: "\e052";
-}
-.glyphicon-align-center:before {
- content: "\e053";
-}
-.glyphicon-align-right:before {
- content: "\e054";
-}
-.glyphicon-align-justify:before {
- content: "\e055";
-}
-.glyphicon-list:before {
- content: "\e056";
-}
-.glyphicon-indent-left:before {
- content: "\e057";
-}
-.glyphicon-indent-right:before {
- content: "\e058";
-}
-.glyphicon-facetime-video:before {
- content: "\e059";
-}
-.glyphicon-picture:before {
- content: "\e060";
-}
-.glyphicon-map-marker:before {
- content: "\e062";
-}
-.glyphicon-adjust:before {
- content: "\e063";
-}
-.glyphicon-tint:before {
- content: "\e064";
-}
-.glyphicon-edit:before {
- content: "\e065";
-}
-.glyphicon-share:before {
- content: "\e066";
-}
-.glyphicon-check:before {
- content: "\e067";
-}
-.glyphicon-move:before {
- content: "\e068";
-}
-.glyphicon-step-backward:before {
- content: "\e069";
-}
-.glyphicon-fast-backward:before {
- content: "\e070";
-}
-.glyphicon-backward:before {
- content: "\e071";
-}
-.glyphicon-play:before {
- content: "\e072";
-}
-.glyphicon-pause:before {
- content: "\e073";
-}
-.glyphicon-stop:before {
- content: "\e074";
-}
-.glyphicon-forward:before {
- content: "\e075";
-}
-.glyphicon-fast-forward:before {
- content: "\e076";
-}
-.glyphicon-step-forward:before {
- content: "\e077";
-}
-.glyphicon-eject:before {
- content: "\e078";
-}
-.glyphicon-chevron-left:before {
- content: "\e079";
-}
-.glyphicon-chevron-right:before {
- content: "\e080";
-}
-.glyphicon-plus-sign:before {
- content: "\e081";
-}
-.glyphicon-minus-sign:before {
- content: "\e082";
-}
-.glyphicon-remove-sign:before {
- content: "\e083";
-}
-.glyphicon-ok-sign:before {
- content: "\e084";
-}
-.glyphicon-question-sign:before {
- content: "\e085";
-}
-.glyphicon-info-sign:before {
- content: "\e086";
-}
-.glyphicon-screenshot:before {
- content: "\e087";
-}
-.glyphicon-remove-circle:before {
- content: "\e088";
-}
-.glyphicon-ok-circle:before {
- content: "\e089";
-}
-.glyphicon-ban-circle:before {
- content: "\e090";
-}
-.glyphicon-arrow-left:before {
- content: "\e091";
-}
-.glyphicon-arrow-right:before {
- content: "\e092";
-}
-.glyphicon-arrow-up:before {
- content: "\e093";
-}
-.glyphicon-arrow-down:before {
- content: "\e094";
-}
-.glyphicon-share-alt:before {
- content: "\e095";
-}
-.glyphicon-resize-full:before {
- content: "\e096";
-}
-.glyphicon-resize-small:before {
- content: "\e097";
-}
-.glyphicon-exclamation-sign:before {
- content: "\e101";
-}
-.glyphicon-gift:before {
- content: "\e102";
-}
-.glyphicon-leaf:before {
- content: "\e103";
-}
-.glyphicon-fire:before {
- content: "\e104";
-}
-.glyphicon-eye-open:before {
- content: "\e105";
-}
-.glyphicon-eye-close:before {
- content: "\e106";
-}
-.glyphicon-warning-sign:before {
- content: "\e107";
-}
-.glyphicon-plane:before {
- content: "\e108";
-}
-.glyphicon-calendar:before {
- content: "\e109";
-}
-.glyphicon-random:before {
- content: "\e110";
-}
-.glyphicon-comment:before {
- content: "\e111";
-}
-.glyphicon-magnet:before {
- content: "\e112";
-}
-.glyphicon-chevron-up:before {
- content: "\e113";
-}
-.glyphicon-chevron-down:before {
- content: "\e114";
-}
-.glyphicon-retweet:before {
- content: "\e115";
-}
-.glyphicon-shopping-cart:before {
- content: "\e116";
-}
-.glyphicon-folder-close:before {
- content: "\e117";
-}
-.glyphicon-folder-open:before {
- content: "\e118";
-}
-.glyphicon-resize-vertical:before {
- content: "\e119";
-}
-.glyphicon-resize-horizontal:before {
- content: "\e120";
-}
-.glyphicon-hdd:before {
- content: "\e121";
-}
-.glyphicon-bullhorn:before {
- content: "\e122";
-}
-.glyphicon-bell:before {
- content: "\e123";
-}
-.glyphicon-certificate:before {
- content: "\e124";
-}
-.glyphicon-thumbs-up:before {
- content: "\e125";
-}
-.glyphicon-thumbs-down:before {
- content: "\e126";
-}
-.glyphicon-hand-right:before {
- content: "\e127";
-}
-.glyphicon-hand-left:before {
- content: "\e128";
-}
-.glyphicon-hand-up:before {
- content: "\e129";
-}
-.glyphicon-hand-down:before {
- content: "\e130";
-}
-.glyphicon-circle-arrow-right:before {
- content: "\e131";
-}
-.glyphicon-circle-arrow-left:before {
- content: "\e132";
-}
-.glyphicon-circle-arrow-up:before {
- content: "\e133";
-}
-.glyphicon-circle-arrow-down:before {
- content: "\e134";
-}
-.glyphicon-globe:before {
- content: "\e135";
-}
-.glyphicon-wrench:before {
- content: "\e136";
-}
-.glyphicon-tasks:before {
- content: "\e137";
-}
-.glyphicon-filter:before {
- content: "\e138";
-}
-.glyphicon-briefcase:before {
- content: "\e139";
-}
-.glyphicon-fullscreen:before {
- content: "\e140";
-}
-.glyphicon-dashboard:before {
- content: "\e141";
-}
-.glyphicon-paperclip:before {
- content: "\e142";
-}
-.glyphicon-heart-empty:before {
- content: "\e143";
-}
-.glyphicon-link:before {
- content: "\e144";
-}
-.glyphicon-phone:before {
- content: "\e145";
-}
-.glyphicon-pushpin:before {
- content: "\e146";
-}
-.glyphicon-usd:before {
- content: "\e148";
-}
-.glyphicon-gbp:before {
- content: "\e149";
-}
-.glyphicon-sort:before {
- content: "\e150";
-}
-.glyphicon-sort-by-alphabet:before {
- content: "\e151";
-}
-.glyphicon-sort-by-alphabet-alt:before {
- content: "\e152";
-}
-.glyphicon-sort-by-order:before {
- content: "\e153";
-}
-.glyphicon-sort-by-order-alt:before {
- content: "\e154";
-}
-.glyphicon-sort-by-attributes:before {
- content: "\e155";
-}
-.glyphicon-sort-by-attributes-alt:before {
- content: "\e156";
-}
-.glyphicon-unchecked:before {
- content: "\e157";
-}
-.glyphicon-expand:before {
- content: "\e158";
-}
-.glyphicon-collapse-down:before {
- content: "\e159";
-}
-.glyphicon-collapse-up:before {
- content: "\e160";
-}
-.glyphicon-log-in:before {
- content: "\e161";
-}
-.glyphicon-flash:before {
- content: "\e162";
-}
-.glyphicon-log-out:before {
- content: "\e163";
-}
-.glyphicon-new-window:before {
- content: "\e164";
-}
-.glyphicon-record:before {
- content: "\e165";
-}
-.glyphicon-save:before {
- content: "\e166";
-}
-.glyphicon-open:before {
- content: "\e167";
-}
-.glyphicon-saved:before {
- content: "\e168";
-}
-.glyphicon-import:before {
- content: "\e169";
-}
-.glyphicon-export:before {
- content: "\e170";
-}
-.glyphicon-send:before {
- content: "\e171";
-}
-.glyphicon-floppy-disk:before {
- content: "\e172";
-}
-.glyphicon-floppy-saved:before {
- content: "\e173";
-}
-.glyphicon-floppy-remove:before {
- content: "\e174";
-}
-.glyphicon-floppy-save:before {
- content: "\e175";
-}
-.glyphicon-floppy-open:before {
- content: "\e176";
-}
-.glyphicon-credit-card:before {
- content: "\e177";
-}
-.glyphicon-transfer:before {
- content: "\e178";
-}
-.glyphicon-cutlery:before {
- content: "\e179";
-}
-.glyphicon-header:before {
- content: "\e180";
-}
-.glyphicon-compressed:before {
- content: "\e181";
-}
-.glyphicon-earphone:before {
- content: "\e182";
-}
-.glyphicon-phone-alt:before {
- content: "\e183";
-}
-.glyphicon-tower:before {
- content: "\e184";
-}
-.glyphicon-stats:before {
- content: "\e185";
-}
-.glyphicon-sd-video:before {
- content: "\e186";
-}
-.glyphicon-hd-video:before {
- content: "\e187";
-}
-.glyphicon-subtitles:before {
- content: "\e188";
-}
-.glyphicon-sound-stereo:before {
- content: "\e189";
-}
-.glyphicon-sound-dolby:before {
- content: "\e190";
-}
-.glyphicon-sound-5-1:before {
- content: "\e191";
-}
-.glyphicon-sound-6-1:before {
- content: "\e192";
-}
-.glyphicon-sound-7-1:before {
- content: "\e193";
-}
-.glyphicon-copyright-mark:before {
- content: "\e194";
-}
-.glyphicon-registration-mark:before {
- content: "\e195";
-}
-.glyphicon-cloud-download:before {
- content: "\e197";
-}
-.glyphicon-cloud-upload:before {
- content: "\e198";
-}
-.glyphicon-tree-conifer:before {
- content: "\e199";
-}
-.glyphicon-tree-deciduous:before {
- content: "\e200";
-}
-.glyphicon-cd:before {
- content: "\e201";
-}
-.glyphicon-save-file:before {
- content: "\e202";
-}
-.glyphicon-open-file:before {
- content: "\e203";
-}
-.glyphicon-level-up:before {
- content: "\e204";
-}
-.glyphicon-copy:before {
- content: "\e205";
-}
-.glyphicon-paste:before {
- content: "\e206";
-}
-.glyphicon-alert:before {
- content: "\e209";
-}
-.glyphicon-equalizer:before {
- content: "\e210";
-}
-.glyphicon-king:before {
- content: "\e211";
-}
-.glyphicon-queen:before {
- content: "\e212";
-}
-.glyphicon-pawn:before {
- content: "\e213";
-}
-.glyphicon-bishop:before {
- content: "\e214";
-}
-.glyphicon-knight:before {
- content: "\e215";
-}
-.glyphicon-baby-formula:before {
- content: "\e216";
-}
-.glyphicon-tent:before {
- content: "\26fa";
-}
-.glyphicon-blackboard:before {
- content: "\e218";
-}
-.glyphicon-bed:before {
- content: "\e219";
-}
-.glyphicon-apple:before {
- content: "\f8ff";
-}
-.glyphicon-erase:before {
- content: "\e221";
-}
-.glyphicon-hourglass:before {
- content: "\231b";
-}
-.glyphicon-lamp:before {
- content: "\e223";
-}
-.glyphicon-duplicate:before {
- content: "\e224";
-}
-.glyphicon-piggy-bank:before {
- content: "\e225";
-}
-.glyphicon-scissors:before {
- content: "\e226";
-}
-.glyphicon-bitcoin:before {
- content: "\e227";
-}
-.glyphicon-btc:before {
- content: "\e227";
-}
-.glyphicon-xbt:before {
- content: "\e227";
-}
-.glyphicon-yen:before {
- content: "\00a5";
-}
-.glyphicon-jpy:before {
- content: "\00a5";
-}
-.glyphicon-ruble:before {
- content: "\20bd";
-}
-.glyphicon-rub:before {
- content: "\20bd";
-}
-.glyphicon-scale:before {
- content: "\e230";
-}
-.glyphicon-ice-lolly:before {
- content: "\e231";
-}
-.glyphicon-ice-lolly-tasted:before {
- content: "\e232";
-}
-.glyphicon-education:before {
- content: "\e233";
-}
-.glyphicon-option-horizontal:before {
- content: "\e234";
-}
-.glyphicon-option-vertical:before {
- content: "\e235";
-}
-.glyphicon-menu-hamburger:before {
- content: "\e236";
-}
-.glyphicon-modal-window:before {
- content: "\e237";
-}
-.glyphicon-oil:before {
- content: "\e238";
-}
-.glyphicon-grain:before {
- content: "\e239";
-}
-.glyphicon-sunglasses:before {
- content: "\e240";
-}
-.glyphicon-text-size:before {
- content: "\e241";
-}
-.glyphicon-text-color:before {
- content: "\e242";
-}
-.glyphicon-text-background:before {
- content: "\e243";
-}
-.glyphicon-object-align-top:before {
- content: "\e244";
-}
-.glyphicon-object-align-bottom:before {
- content: "\e245";
-}
-.glyphicon-object-align-horizontal:before {
- content: "\e246";
-}
-.glyphicon-object-align-left:before {
- content: "\e247";
-}
-.glyphicon-object-align-vertical:before {
- content: "\e248";
-}
-.glyphicon-object-align-right:before {
- content: "\e249";
-}
-.glyphicon-triangle-right:before {
- content: "\e250";
-}
-.glyphicon-triangle-left:before {
- content: "\e251";
-}
-.glyphicon-triangle-bottom:before {
- content: "\e252";
-}
-.glyphicon-triangle-top:before {
- content: "\e253";
-}
-.glyphicon-console:before {
- content: "\e254";
-}
-.glyphicon-superscript:before {
- content: "\e255";
-}
-.glyphicon-subscript:before {
- content: "\e256";
-}
-.glyphicon-menu-left:before {
- content: "\e257";
-}
-.glyphicon-menu-right:before {
- content: "\e258";
-}
-.glyphicon-menu-down:before {
- content: "\e259";
-}
-.glyphicon-menu-up:before {
- content: "\e260";
-}
-* {
- -webkit-box-sizing: border-box;
- -moz-box-sizing: border-box;
- box-sizing: border-box;
-}
-*:before,
-*:after {
- -webkit-box-sizing: border-box;
- -moz-box-sizing: border-box;
- box-sizing: border-box;
-}
-html {
- font-size: 10px;
- -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
-}
-body {
- font-family: -apple-system, system-ui, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
- font-size: 16px;
- line-height: 1.42857143;
- color: #373e42;
- background-color: #F9F9F9;
-}
-input,
-button,
-select,
-textarea {
- font-family: inherit;
- font-size: inherit;
- line-height: inherit;
-}
-a {
- color: #875A7B;
- text-decoration: none;
-}
-a:hover,
-a:focus {
- color: #926485;
- text-decoration: none;
-}
-a:focus {
- outline: thin dotted;
- outline: 5px auto -webkit-focus-ring-color;
- outline-offset: -2px;
-}
-figure {
- margin: 0;
-}
-img {
- vertical-align: middle;
-}
-.img-responsive,
-.thumbnail > img,
-.thumbnail a > img,
-.carousel-inner > .item > img,
-.carousel-inner > .item > a > img {
- display: block;
- max-width: 100%;
- height: auto;
- display: inline-block;
-}
-.img-rounded {
- border-radius: 6px;
-}
-.img-thumbnail {
- padding: 4px;
- line-height: 1.42857143;
- background-color: #F9F9F9;
- border: 1px solid #ddd;
- border-radius: 4px;
- -webkit-transition: all 0.2s ease-in-out;
- -o-transition: all 0.2s ease-in-out;
- transition: all 0.2s ease-in-out;
- display: inline-block;
- max-width: 100%;
- height: auto;
-}
-.img-circle {
- border-radius: 50%;
-}
-hr {
- margin-top: 22px;
- margin-bottom: 22px;
- border: 0;
- border-top: 1px solid #F2F2F2;
-}
-.sr-only {
- position: absolute;
- width: 1px;
- height: 1px;
- margin: -1px;
- padding: 0;
- overflow: hidden;
- clip: rect(0, 0, 0, 0);
- border: 0;
-}
-.sr-only-focusable:active,
-.sr-only-focusable:focus {
- position: static;
- width: auto;
- height: auto;
- margin: 0;
- overflow: visible;
- clip: auto;
-}
-[role="button"] {
- cursor: pointer;
-}
-h1,
-h2,
-h3,
-h4,
-h5,
-h6,
-.h1,
-.h2,
-.h3,
-.h4,
-.h5,
-.h6 {
- font-family: -apple-system, system-ui, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
- font-weight: 400;
- line-height: 1.1;
- color: #21313a;
-}
-h1 small,
-h2 small,
-h3 small,
-h4 small,
-h5 small,
-h6 small,
-.h1 small,
-.h2 small,
-.h3 small,
-.h4 small,
-.h5 small,
-.h6 small,
-h1 .small,
-h2 .small,
-h3 .small,
-h4 .small,
-h5 .small,
-h6 .small,
-.h1 .small,
-.h2 .small,
-.h3 .small,
-.h4 .small,
-.h5 .small,
-.h6 .small {
- font-weight: normal;
- line-height: 1;
- color: #21313a;
-}
-h1,
-.h1,
-h2,
-.h2,
-h3,
-.h3 {
- margin-top: 22px;
- margin-bottom: 11px;
-}
-h1 small,
-.h1 small,
-h2 small,
-.h2 small,
-h3 small,
-.h3 small,
-h1 .small,
-.h1 .small,
-h2 .small,
-.h2 .small,
-h3 .small,
-.h3 .small {
- font-size: 65%;
-}
-h4,
-.h4,
-h5,
-.h5,
-h6,
-.h6 {
- margin-top: 11px;
- margin-bottom: 11px;
-}
-h4 small,
-.h4 small,
-h5 small,
-.h5 small,
-h6 small,
-.h6 small,
-h4 .small,
-.h4 .small,
-h5 .small,
-.h5 .small,
-h6 .small,
-.h6 .small {
- font-size: 75%;
-}
-h1,
-.h1 {
- font-size: 41px;
-}
-h2,
-.h2 {
- font-size: 30px;
-}
-h3,
-.h3 {
- font-size: 24px;
-}
-h4,
-.h4 {
- font-size: 19px;
-}
-h5,
-.h5 {
- font-size: 17px;
-}
-h6,
-.h6 {
- font-size: 17px;
-}
-p {
- margin: 0 0 11px;
-}
-.lead {
- margin-bottom: 22px;
- font-size: 18px;
- font-weight: 300;
- line-height: 1.4;
-}
-@media (min-width: 768px) {
- .lead {
- font-size: 24px;
- }
-}
-small,
-.small {
- font-size: 87%;
-}
-mark,
-.mark {
- background-color: #fcf8e3;
- padding: 0.2em;
-}
-.text-left {
- text-align: left;
-}
-.text-right {
- text-align: right;
-}
-.text-center {
- text-align: center;
-}
-.text-justify {
- text-align: justify;
-}
-.text-nowrap {
- white-space: nowrap;
-}
-.text-lowercase {
- text-transform: lowercase;
-}
-.text-uppercase {
- text-transform: uppercase;
-}
-.text-capitalize {
- text-transform: capitalize;
-}
-.text-muted {
- color: #888888;
-}
-.text-primary {
- color: #21b799;
-}
-a.text-primary:hover,
-a.text-primary:focus {
- color: #198c75;
-}
-.text-success {
- color: #3c763d;
-}
-a.text-success:hover,
-a.text-success:focus {
- color: #2b542c;
-}
-.text-info {
- color: #31708f;
-}
-a.text-info:hover,
-a.text-info:focus {
- color: #245269;
-}
-.text-warning {
- color: #8a6d3b;
-}
-a.text-warning:hover,
-a.text-warning:focus {
- color: #66512c;
-}
-.text-danger {
- color: #a94442;
-}
-a.text-danger:hover,
-a.text-danger:focus {
- color: #843534;
-}
-.bg-primary {
- color: #fff;
- background-color: #21b799;
-}
-a.bg-primary:hover,
-a.bg-primary:focus {
- background-color: #198c75;
-}
-.bg-success {
- background-color: #dff0d8;
-}
-a.bg-success:hover,
-a.bg-success:focus {
- background-color: #c1e2b3;
-}
-.bg-info {
- background-color: #d9edf7;
-}
-a.bg-info:hover,
-a.bg-info:focus {
- background-color: #afd9ee;
-}
-.bg-warning {
- background-color: #fcf8e3;
-}
-a.bg-warning:hover,
-a.bg-warning:focus {
- background-color: #f7ecb5;
-}
-.bg-danger {
- background-color: #f2dede;
-}
-a.bg-danger:hover,
-a.bg-danger:focus {
- background-color: #e4b9b9;
-}
-.page-header {
- padding-bottom: 10px;
- margin: 44px 0 22px;
- border-bottom: 1px solid #F2F2F2;
-}
-ul,
-ol {
- margin-top: 0;
- margin-bottom: 11px;
-}
-ul ul,
-ol ul,
-ul ol,
-ol ol {
- margin-bottom: 0;
-}
-.list-unstyled {
- padding-left: 0;
- list-style: none;
-}
-.list-inline {
- padding-left: 0;
- list-style: none;
- margin-left: -5px;
-}
-.list-inline > li {
- display: inline-block;
- padding-left: 5px;
- padding-right: 5px;
-}
-dl {
- margin-top: 0;
- margin-bottom: 22px;
-}
-dt,
-dd {
- line-height: 1.42857143;
-}
-dt {
- font-weight: bold;
-}
-dd {
- margin-left: 0;
-}
-@media (min-width: 768px) {
- .dl-horizontal dt {
- float: left;
- width: 160px;
- clear: left;
- text-align: right;
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
- }
- .dl-horizontal dd {
- margin-left: 180px;
- }
-}
-abbr[title],
-abbr[data-original-title] {
- cursor: help;
- border-bottom: 1px dotted #dcddde;
-}
-.initialism {
- font-size: 90%;
- text-transform: uppercase;
-}
-blockquote {
- padding: 11px 22px;
- margin: 0 0 22px;
- font-size: 20px;
- border-left: 5px solid #F2F2F2;
-}
-blockquote p:last-child,
-blockquote ul:last-child,
-blockquote ol:last-child {
- margin-bottom: 0;
-}
-blockquote footer,
-blockquote small,
-blockquote .small {
- display: block;
- font-size: 80%;
- line-height: 1.42857143;
- color: #dcddde;
-}
-blockquote footer:before,
-blockquote small:before,
-blockquote .small:before {
- content: '\2014 \00A0';
-}
-.blockquote-reverse,
-blockquote.pull-right {
- padding-right: 15px;
- padding-left: 0;
- border-right: 5px solid #F2F2F2;
- border-left: 0;
- text-align: right;
-}
-.blockquote-reverse footer:before,
-blockquote.pull-right footer:before,
-.blockquote-reverse small:before,
-blockquote.pull-right small:before,
-.blockquote-reverse .small:before,
-blockquote.pull-right .small:before {
- content: '';
-}
-.blockquote-reverse footer:after,
-blockquote.pull-right footer:after,
-.blockquote-reverse small:after,
-blockquote.pull-right small:after,
-.blockquote-reverse .small:after,
-blockquote.pull-right .small:after {
- content: '\00A0 \2014';
-}
-address {
- margin-bottom: 22px;
- font-style: normal;
- line-height: 1.42857143;
-}
-code,
-kbd,
-pre,
-samp {
- font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
-}
-code {
- padding: 2px 4px;
- font-size: 90%;
- color: #c7254e;
- background-color: #f9f2f4;
- border-radius: 4px;
-}
-kbd {
- padding: 2px 4px;
- font-size: 90%;
- color: #fff;
- background-color: #333;
- border-radius: 3px;
- box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.25);
-}
-kbd kbd {
- padding: 0;
- font-size: 100%;
- font-weight: bold;
- box-shadow: none;
-}
-pre {
- display: block;
- padding: 10.5px;
- margin: 0 0 11px;
- font-size: 15px;
- line-height: 1.42857143;
- word-break: break-all;
- word-wrap: break-word;
- color: #6B6D70;
- background-color: #f5f5f5;
- border: 1px solid #ccc;
- border-radius: 4px;
-}
-pre code {
- padding: 0;
- font-size: inherit;
- color: inherit;
- white-space: pre-wrap;
- background-color: transparent;
- border-radius: 0;
-}
-.pre-scrollable {
- max-height: 340px;
- overflow-y: scroll;
-}
-.container {
- margin-right: auto;
- margin-left: auto;
- padding-left: 15px;
- padding-right: 15px;
-}
-@media (min-width: 768px) {
- .container {
- width: 750px;
- }
-}
-@media (min-width: 992px) {
- .container {
- width: 970px;
- }
-}
-@media (min-width: 1200px) {
- .container {
- width: 1170px;
- }
-}
-.container-fluid {
- margin-right: auto;
- margin-left: auto;
- padding-left: 15px;
- padding-right: 15px;
-}
-.row {
- margin-left: -15px;
- margin-right: -15px;
-}
-.col-xs-1,
-.col-sm-1,
-.col-md-1,
-.col-lg-1,
-.col-xs-2,
-.col-sm-2,
-.col-md-2,
-.col-lg-2,
-.col-xs-3,
-.col-sm-3,
-.col-md-3,
-.col-lg-3,
-.col-xs-4,
-.col-sm-4,
-.col-md-4,
-.col-lg-4,
-.col-xs-5,
-.col-sm-5,
-.col-md-5,
-.col-lg-5,
-.col-xs-6,
-.col-sm-6,
-.col-md-6,
-.col-lg-6,
-.col-xs-7,
-.col-sm-7,
-.col-md-7,
-.col-lg-7,
-.col-xs-8,
-.col-sm-8,
-.col-md-8,
-.col-lg-8,
-.col-xs-9,
-.col-sm-9,
-.col-md-9,
-.col-lg-9,
-.col-xs-10,
-.col-sm-10,
-.col-md-10,
-.col-lg-10,
-.col-xs-11,
-.col-sm-11,
-.col-md-11,
-.col-lg-11,
-.col-xs-12,
-.col-sm-12,
-.col-md-12,
-.col-lg-12 {
- position: relative;
- min-height: 1px;
- padding-left: 15px;
- padding-right: 15px;
-}
-.col-xs-1,
-.col-xs-2,
-.col-xs-3,
-.col-xs-4,
-.col-xs-5,
-.col-xs-6,
-.col-xs-7,
-.col-xs-8,
-.col-xs-9,
-.col-xs-10,
-.col-xs-11,
-.col-xs-12 {
- float: left;
-}
-.col-xs-12 {
- width: 100%;
-}
-.col-xs-11 {
- width: 91.66666667%;
-}
-.col-xs-10 {
- width: 83.33333333%;
-}
-.col-xs-9 {
- width: 75%;
-}
-.col-xs-8 {
- width: 66.66666667%;
-}
-.col-xs-7 {
- width: 58.33333333%;
-}
-.col-xs-6 {
- width: 50%;
-}
-.col-xs-5 {
- width: 41.66666667%;
-}
-.col-xs-4 {
- width: 33.33333333%;
-}
-.col-xs-3 {
- width: 25%;
-}
-.col-xs-2 {
- width: 16.66666667%;
-}
-.col-xs-1 {
- width: 8.33333333%;
-}
-.col-xs-pull-12 {
- right: 100%;
-}
-.col-xs-pull-11 {
- right: 91.66666667%;
-}
-.col-xs-pull-10 {
- right: 83.33333333%;
-}
-.col-xs-pull-9 {
- right: 75%;
-}
-.col-xs-pull-8 {
- right: 66.66666667%;
-}
-.col-xs-pull-7 {
- right: 58.33333333%;
-}
-.col-xs-pull-6 {
- right: 50%;
-}
-.col-xs-pull-5 {
- right: 41.66666667%;
-}
-.col-xs-pull-4 {
- right: 33.33333333%;
-}
-.col-xs-pull-3 {
- right: 25%;
-}
-.col-xs-pull-2 {
- right: 16.66666667%;
-}
-.col-xs-pull-1 {
- right: 8.33333333%;
-}
-.col-xs-pull-0 {
- right: auto;
-}
-.col-xs-push-12 {
- left: 100%;
-}
-.col-xs-push-11 {
- left: 91.66666667%;
-}
-.col-xs-push-10 {
- left: 83.33333333%;
-}
-.col-xs-push-9 {
- left: 75%;
-}
-.col-xs-push-8 {
- left: 66.66666667%;
-}
-.col-xs-push-7 {
- left: 58.33333333%;
-}
-.col-xs-push-6 {
- left: 50%;
-}
-.col-xs-push-5 {
- left: 41.66666667%;
-}
-.col-xs-push-4 {
- left: 33.33333333%;
-}
-.col-xs-push-3 {
- left: 25%;
-}
-.col-xs-push-2 {
- left: 16.66666667%;
-}
-.col-xs-push-1 {
- left: 8.33333333%;
-}
-.col-xs-push-0 {
- left: auto;
-}
-.col-xs-offset-12 {
- margin-left: 100%;
-}
-.col-xs-offset-11 {
- margin-left: 91.66666667%;
-}
-.col-xs-offset-10 {
- margin-left: 83.33333333%;
-}
-.col-xs-offset-9 {
- margin-left: 75%;
-}
-.col-xs-offset-8 {
- margin-left: 66.66666667%;
-}
-.col-xs-offset-7 {
- margin-left: 58.33333333%;
-}
-.col-xs-offset-6 {
- margin-left: 50%;
-}
-.col-xs-offset-5 {
- margin-left: 41.66666667%;
-}
-.col-xs-offset-4 {
- margin-left: 33.33333333%;
-}
-.col-xs-offset-3 {
- margin-left: 25%;
-}
-.col-xs-offset-2 {
- margin-left: 16.66666667%;
-}
-.col-xs-offset-1 {
- margin-left: 8.33333333%;
-}
-.col-xs-offset-0 {
- margin-left: 0%;
-}
-@media (min-width: 768px) {
- .col-sm-1,
- .col-sm-2,
- .col-sm-3,
- .col-sm-4,
- .col-sm-5,
- .col-sm-6,
- .col-sm-7,
- .col-sm-8,
- .col-sm-9,
- .col-sm-10,
- .col-sm-11,
- .col-sm-12 {
- float: left;
- }
- .col-sm-12 {
- width: 100%;
- }
- .col-sm-11 {
- width: 91.66666667%;
- }
- .col-sm-10 {
- width: 83.33333333%;
- }
- .col-sm-9 {
- width: 75%;
- }
- .col-sm-8 {
- width: 66.66666667%;
- }
- .col-sm-7 {
- width: 58.33333333%;
- }
- .col-sm-6 {
- width: 50%;
- }
- .col-sm-5 {
- width: 41.66666667%;
- }
- .col-sm-4 {
- width: 33.33333333%;
- }
- .col-sm-3 {
- width: 25%;
- }
- .col-sm-2 {
- width: 16.66666667%;
- }
- .col-sm-1 {
- width: 8.33333333%;
- }
- .col-sm-pull-12 {
- right: 100%;
- }
- .col-sm-pull-11 {
- right: 91.66666667%;
- }
- .col-sm-pull-10 {
- right: 83.33333333%;
- }
- .col-sm-pull-9 {
- right: 75%;
- }
- .col-sm-pull-8 {
- right: 66.66666667%;
- }
- .col-sm-pull-7 {
- right: 58.33333333%;
- }
- .col-sm-pull-6 {
- right: 50%;
- }
- .col-sm-pull-5 {
- right: 41.66666667%;
- }
- .col-sm-pull-4 {
- right: 33.33333333%;
- }
- .col-sm-pull-3 {
- right: 25%;
- }
- .col-sm-pull-2 {
- right: 16.66666667%;
- }
- .col-sm-pull-1 {
- right: 8.33333333%;
- }
- .col-sm-pull-0 {
- right: auto;
- }
- .col-sm-push-12 {
- left: 100%;
- }
- .col-sm-push-11 {
- left: 91.66666667%;
- }
- .col-sm-push-10 {
- left: 83.33333333%;
- }
- .col-sm-push-9 {
- left: 75%;
- }
- .col-sm-push-8 {
- left: 66.66666667%;
- }
- .col-sm-push-7 {
- left: 58.33333333%;
- }
- .col-sm-push-6 {
- left: 50%;
- }
- .col-sm-push-5 {
- left: 41.66666667%;
- }
- .col-sm-push-4 {
- left: 33.33333333%;
- }
- .col-sm-push-3 {
- left: 25%;
- }
- .col-sm-push-2 {
- left: 16.66666667%;
- }
- .col-sm-push-1 {
- left: 8.33333333%;
- }
- .col-sm-push-0 {
- left: auto;
- }
- .col-sm-offset-12 {
- margin-left: 100%;
- }
- .col-sm-offset-11 {
- margin-left: 91.66666667%;
- }
- .col-sm-offset-10 {
- margin-left: 83.33333333%;
- }
- .col-sm-offset-9 {
- margin-left: 75%;
- }
- .col-sm-offset-8 {
- margin-left: 66.66666667%;
- }
- .col-sm-offset-7 {
- margin-left: 58.33333333%;
- }
- .col-sm-offset-6 {
- margin-left: 50%;
- }
- .col-sm-offset-5 {
- margin-left: 41.66666667%;
- }
- .col-sm-offset-4 {
- margin-left: 33.33333333%;
- }
- .col-sm-offset-3 {
- margin-left: 25%;
- }
- .col-sm-offset-2 {
- margin-left: 16.66666667%;
- }
- .col-sm-offset-1 {
- margin-left: 8.33333333%;
- }
- .col-sm-offset-0 {
- margin-left: 0%;
- }
-}
-@media (min-width: 992px) {
- .col-md-1,
- .col-md-2,
- .col-md-3,
- .col-md-4,
- .col-md-5,
- .col-md-6,
- .col-md-7,
- .col-md-8,
- .col-md-9,
- .col-md-10,
- .col-md-11,
- .col-md-12 {
- float: left;
- }
- .col-md-12 {
- width: 100%;
- }
- .col-md-11 {
- width: 91.66666667%;
- }
- .col-md-10 {
- width: 83.33333333%;
- }
- .col-md-9 {
- width: 75%;
- }
- .col-md-8 {
- width: 66.66666667%;
- }
- .col-md-7 {
- width: 58.33333333%;
- }
- .col-md-6 {
- width: 50%;
- }
- .col-md-5 {
- width: 41.66666667%;
- }
- .col-md-4 {
- width: 33.33333333%;
- }
- .col-md-3 {
- width: 25%;
- }
- .col-md-2 {
- width: 16.66666667%;
- }
- .col-md-1 {
- width: 8.33333333%;
- }
- .col-md-pull-12 {
- right: 100%;
- }
- .col-md-pull-11 {
- right: 91.66666667%;
- }
- .col-md-pull-10 {
- right: 83.33333333%;
- }
- .col-md-pull-9 {
- right: 75%;
- }
- .col-md-pull-8 {
- right: 66.66666667%;
- }
- .col-md-pull-7 {
- right: 58.33333333%;
- }
- .col-md-pull-6 {
- right: 50%;
- }
- .col-md-pull-5 {
- right: 41.66666667%;
- }
- .col-md-pull-4 {
- right: 33.33333333%;
- }
- .col-md-pull-3 {
- right: 25%;
- }
- .col-md-pull-2 {
- right: 16.66666667%;
- }
- .col-md-pull-1 {
- right: 8.33333333%;
- }
- .col-md-pull-0 {
- right: auto;
- }
- .col-md-push-12 {
- left: 100%;
- }
- .col-md-push-11 {
- left: 91.66666667%;
- }
- .col-md-push-10 {
- left: 83.33333333%;
- }
- .col-md-push-9 {
- left: 75%;
- }
- .col-md-push-8 {
- left: 66.66666667%;
- }
- .col-md-push-7 {
- left: 58.33333333%;
- }
- .col-md-push-6 {
- left: 50%;
- }
- .col-md-push-5 {
- left: 41.66666667%;
- }
- .col-md-push-4 {
- left: 33.33333333%;
- }
- .col-md-push-3 {
- left: 25%;
- }
- .col-md-push-2 {
- left: 16.66666667%;
- }
- .col-md-push-1 {
- left: 8.33333333%;
- }
- .col-md-push-0 {
- left: auto;
- }
- .col-md-offset-12 {
- margin-left: 100%;
- }
- .col-md-offset-11 {
- margin-left: 91.66666667%;
- }
- .col-md-offset-10 {
- margin-left: 83.33333333%;
- }
- .col-md-offset-9 {
- margin-left: 75%;
- }
- .col-md-offset-8 {
- margin-left: 66.66666667%;
- }
- .col-md-offset-7 {
- margin-left: 58.33333333%;
- }
- .col-md-offset-6 {
- margin-left: 50%;
- }
- .col-md-offset-5 {
- margin-left: 41.66666667%;
- }
- .col-md-offset-4 {
- margin-left: 33.33333333%;
- }
- .col-md-offset-3 {
- margin-left: 25%;
- }
- .col-md-offset-2 {
- margin-left: 16.66666667%;
- }
- .col-md-offset-1 {
- margin-left: 8.33333333%;
- }
- .col-md-offset-0 {
- margin-left: 0%;
- }
-}
-@media (min-width: 1200px) {
- .col-lg-1,
- .col-lg-2,
- .col-lg-3,
- .col-lg-4,
- .col-lg-5,
- .col-lg-6,
- .col-lg-7,
- .col-lg-8,
- .col-lg-9,
- .col-lg-10,
- .col-lg-11,
- .col-lg-12 {
- float: left;
- }
- .col-lg-12 {
- width: 100%;
- }
- .col-lg-11 {
- width: 91.66666667%;
- }
- .col-lg-10 {
- width: 83.33333333%;
- }
- .col-lg-9 {
- width: 75%;
- }
- .col-lg-8 {
- width: 66.66666667%;
- }
- .col-lg-7 {
- width: 58.33333333%;
- }
- .col-lg-6 {
- width: 50%;
- }
- .col-lg-5 {
- width: 41.66666667%;
- }
- .col-lg-4 {
- width: 33.33333333%;
- }
- .col-lg-3 {
- width: 25%;
- }
- .col-lg-2 {
- width: 16.66666667%;
- }
- .col-lg-1 {
- width: 8.33333333%;
- }
- .col-lg-pull-12 {
- right: 100%;
- }
- .col-lg-pull-11 {
- right: 91.66666667%;
- }
- .col-lg-pull-10 {
- right: 83.33333333%;
- }
- .col-lg-pull-9 {
- right: 75%;
- }
- .col-lg-pull-8 {
- right: 66.66666667%;
- }
- .col-lg-pull-7 {
- right: 58.33333333%;
- }
- .col-lg-pull-6 {
- right: 50%;
- }
- .col-lg-pull-5 {
- right: 41.66666667%;
- }
- .col-lg-pull-4 {
- right: 33.33333333%;
- }
- .col-lg-pull-3 {
- right: 25%;
- }
- .col-lg-pull-2 {
- right: 16.66666667%;
- }
- .col-lg-pull-1 {
- right: 8.33333333%;
- }
- .col-lg-pull-0 {
- right: auto;
- }
- .col-lg-push-12 {
- left: 100%;
- }
- .col-lg-push-11 {
- left: 91.66666667%;
- }
- .col-lg-push-10 {
- left: 83.33333333%;
- }
- .col-lg-push-9 {
- left: 75%;
- }
- .col-lg-push-8 {
- left: 66.66666667%;
- }
- .col-lg-push-7 {
- left: 58.33333333%;
- }
- .col-lg-push-6 {
- left: 50%;
- }
- .col-lg-push-5 {
- left: 41.66666667%;
- }
- .col-lg-push-4 {
- left: 33.33333333%;
- }
- .col-lg-push-3 {
- left: 25%;
- }
- .col-lg-push-2 {
- left: 16.66666667%;
- }
- .col-lg-push-1 {
- left: 8.33333333%;
- }
- .col-lg-push-0 {
- left: auto;
- }
- .col-lg-offset-12 {
- margin-left: 100%;
- }
- .col-lg-offset-11 {
- margin-left: 91.66666667%;
- }
- .col-lg-offset-10 {
- margin-left: 83.33333333%;
- }
- .col-lg-offset-9 {
- margin-left: 75%;
- }
- .col-lg-offset-8 {
- margin-left: 66.66666667%;
- }
- .col-lg-offset-7 {
- margin-left: 58.33333333%;
- }
- .col-lg-offset-6 {
- margin-left: 50%;
- }
- .col-lg-offset-5 {
- margin-left: 41.66666667%;
- }
- .col-lg-offset-4 {
- margin-left: 33.33333333%;
- }
- .col-lg-offset-3 {
- margin-left: 25%;
- }
- .col-lg-offset-2 {
- margin-left: 16.66666667%;
- }
- .col-lg-offset-1 {
- margin-left: 8.33333333%;
- }
- .col-lg-offset-0 {
- margin-left: 0%;
- }
-}
-table {
- background-color: transparent;
-}
-caption {
- padding-top: 8px;
- padding-bottom: 8px;
- color: #888888;
- text-align: left;
-}
-th {
- text-align: left;
-}
-.table {
- width: 100%;
- max-width: 100%;
- margin-bottom: 22px;
-}
-.table > thead > tr > th,
-.table > tbody > tr > th,
-.table > tfoot > tr > th,
-.table > thead > tr > td,
-.table > tbody > tr > td,
-.table > tfoot > tr > td {
- padding: 8px;
- line-height: 1.42857143;
- vertical-align: top;
- border-top: 1px solid #ddd;
-}
-.table > thead > tr > th {
- vertical-align: bottom;
- border-bottom: 2px solid #ddd;
-}
-.table > caption + thead > tr:first-child > th,
-.table > colgroup + thead > tr:first-child > th,
-.table > thead:first-child > tr:first-child > th,
-.table > caption + thead > tr:first-child > td,
-.table > colgroup + thead > tr:first-child > td,
-.table > thead:first-child > tr:first-child > td {
- border-top: 0;
-}
-.table > tbody + tbody {
- border-top: 2px solid #ddd;
-}
-.table .table {
- background-color: #F9F9F9;
-}
-.table-condensed > thead > tr > th,
-.table-condensed > tbody > tr > th,
-.table-condensed > tfoot > tr > th,
-.table-condensed > thead > tr > td,
-.table-condensed > tbody > tr > td,
-.table-condensed > tfoot > tr > td {
- padding: 5px;
-}
-.table-bordered {
- border: 1px solid #ddd;
-}
-.table-bordered > thead > tr > th,
-.table-bordered > tbody > tr > th,
-.table-bordered > tfoot > tr > th,
-.table-bordered > thead > tr > td,
-.table-bordered > tbody > tr > td,
-.table-bordered > tfoot > tr > td {
- border: 1px solid #ddd;
-}
-.table-bordered > thead > tr > th,
-.table-bordered > thead > tr > td {
- border-bottom-width: 2px;
-}
-.table-striped > tbody > tr:nth-of-type(odd) {
- background-color: #f9f9f9;
-}
-.table-hover > tbody > tr:hover {
- background-color: #f5f5f5;
-}
-table col[class*="col-"] {
- position: static;
- float: none;
- display: table-column;
-}
-table td[class*="col-"],
-table th[class*="col-"] {
- position: static;
- float: none;
- display: table-cell;
-}
-.table > thead > tr > td.active,
-.table > tbody > tr > td.active,
-.table > tfoot > tr > td.active,
-.table > thead > tr > th.active,
-.table > tbody > tr > th.active,
-.table > tfoot > tr > th.active,
-.table > thead > tr.active > td,
-.table > tbody > tr.active > td,
-.table > tfoot > tr.active > td,
-.table > thead > tr.active > th,
-.table > tbody > tr.active > th,
-.table > tfoot > tr.active > th {
- background-color: #f5f5f5;
-}
-.table-hover > tbody > tr > td.active:hover,
-.table-hover > tbody > tr > th.active:hover,
-.table-hover > tbody > tr.active:hover > td,
-.table-hover > tbody > tr:hover > .active,
-.table-hover > tbody > tr.active:hover > th {
- background-color: #e8e8e8;
-}
-.table > thead > tr > td.success,
-.table > tbody > tr > td.success,
-.table > tfoot > tr > td.success,
-.table > thead > tr > th.success,
-.table > tbody > tr > th.success,
-.table > tfoot > tr > th.success,
-.table > thead > tr.success > td,
-.table > tbody > tr.success > td,
-.table > tfoot > tr.success > td,
-.table > thead > tr.success > th,
-.table > tbody > tr.success > th,
-.table > tfoot > tr.success > th {
- background-color: #dff0d8;
-}
-.table-hover > tbody > tr > td.success:hover,
-.table-hover > tbody > tr > th.success:hover,
-.table-hover > tbody > tr.success:hover > td,
-.table-hover > tbody > tr:hover > .success,
-.table-hover > tbody > tr.success:hover > th {
- background-color: #d0e9c6;
-}
-.table > thead > tr > td.info,
-.table > tbody > tr > td.info,
-.table > tfoot > tr > td.info,
-.table > thead > tr > th.info,
-.table > tbody > tr > th.info,
-.table > tfoot > tr > th.info,
-.table > thead > tr.info > td,
-.table > tbody > tr.info > td,
-.table > tfoot > tr.info > td,
-.table > thead > tr.info > th,
-.table > tbody > tr.info > th,
-.table > tfoot > tr.info > th {
- background-color: #d9edf7;
-}
-.table-hover > tbody > tr > td.info:hover,
-.table-hover > tbody > tr > th.info:hover,
-.table-hover > tbody > tr.info:hover > td,
-.table-hover > tbody > tr:hover > .info,
-.table-hover > tbody > tr.info:hover > th {
- background-color: #c4e3f3;
-}
-.table > thead > tr > td.warning,
-.table > tbody > tr > td.warning,
-.table > tfoot > tr > td.warning,
-.table > thead > tr > th.warning,
-.table > tbody > tr > th.warning,
-.table > tfoot > tr > th.warning,
-.table > thead > tr.warning > td,
-.table > tbody > tr.warning > td,
-.table > tfoot > tr.warning > td,
-.table > thead > tr.warning > th,
-.table > tbody > tr.warning > th,
-.table > tfoot > tr.warning > th {
- background-color: #fcf8e3;
-}
-.table-hover > tbody > tr > td.warning:hover,
-.table-hover > tbody > tr > th.warning:hover,
-.table-hover > tbody > tr.warning:hover > td,
-.table-hover > tbody > tr:hover > .warning,
-.table-hover > tbody > tr.warning:hover > th {
- background-color: #faf2cc;
-}
-.table > thead > tr > td.danger,
-.table > tbody > tr > td.danger,
-.table > tfoot > tr > td.danger,
-.table > thead > tr > th.danger,
-.table > tbody > tr > th.danger,
-.table > tfoot > tr > th.danger,
-.table > thead > tr.danger > td,
-.table > tbody > tr.danger > td,
-.table > tfoot > tr.danger > td,
-.table > thead > tr.danger > th,
-.table > tbody > tr.danger > th,
-.table > tfoot > tr.danger > th {
- background-color: #f2dede;
-}
-.table-hover > tbody > tr > td.danger:hover,
-.table-hover > tbody > tr > th.danger:hover,
-.table-hover > tbody > tr.danger:hover > td,
-.table-hover > tbody > tr:hover > .danger,
-.table-hover > tbody > tr.danger:hover > th {
- background-color: #ebcccc;
-}
-.table-responsive {
- overflow-x: auto;
- min-height: 0.01%;
-}
-@media screen and (max-width: 767px) {
- .table-responsive {
- width: 100%;
- margin-bottom: 16.5px;
- overflow-y: hidden;
- -ms-overflow-style: -ms-autohiding-scrollbar;
- border: 1px solid #ddd;
- }
- .table-responsive > .table {
- margin-bottom: 0;
- }
- .table-responsive > .table > thead > tr > th,
- .table-responsive > .table > tbody > tr > th,
- .table-responsive > .table > tfoot > tr > th,
- .table-responsive > .table > thead > tr > td,
- .table-responsive > .table > tbody > tr > td,
- .table-responsive > .table > tfoot > tr > td {
- white-space: nowrap;
- }
- .table-responsive > .table-bordered {
- border: 0;
- }
- .table-responsive > .table-bordered > thead > tr > th:first-child,
- .table-responsive > .table-bordered > tbody > tr > th:first-child,
- .table-responsive > .table-bordered > tfoot > tr > th:first-child,
- .table-responsive > .table-bordered > thead > tr > td:first-child,
- .table-responsive > .table-bordered > tbody > tr > td:first-child,
- .table-responsive > .table-bordered > tfoot > tr > td:first-child {
- border-left: 0;
- }
- .table-responsive > .table-bordered > thead > tr > th:last-child,
- .table-responsive > .table-bordered > tbody > tr > th:last-child,
- .table-responsive > .table-bordered > tfoot > tr > th:last-child,
- .table-responsive > .table-bordered > thead > tr > td:last-child,
- .table-responsive > .table-bordered > tbody > tr > td:last-child,
- .table-responsive > .table-bordered > tfoot > tr > td:last-child {
- border-right: 0;
- }
- .table-responsive > .table-bordered > tbody > tr:last-child > th,
- .table-responsive > .table-bordered > tfoot > tr:last-child > th,
- .table-responsive > .table-bordered > tbody > tr:last-child > td,
- .table-responsive > .table-bordered > tfoot > tr:last-child > td {
- border-bottom: 0;
- }
-}
-fieldset {
- padding: 0;
- margin: 0;
- border: 0;
- min-width: 0;
-}
-legend {
- display: block;
- width: 100%;
- padding: 0;
- margin-bottom: 22px;
- font-size: 24px;
- line-height: inherit;
- color: #6B6D70;
- border: 0;
- border-bottom: 1px solid #e5e5e5;
-}
-label {
- display: inline-block;
- max-width: 100%;
- margin-bottom: 5px;
- font-weight: bold;
-}
-input[type="search"] {
- -webkit-box-sizing: border-box;
- -moz-box-sizing: border-box;
- box-sizing: border-box;
-}
-input[type="radio"],
-input[type="checkbox"] {
- margin: 4px 0 0;
- margin-top: 1px \9;
- line-height: normal;
-}
-input[type="file"] {
- display: block;
-}
-input[type="range"] {
- display: block;
- width: 100%;
-}
-select[multiple],
-select[size] {
- height: auto;
-}
-input[type="file"]:focus,
-input[type="radio"]:focus,
-input[type="checkbox"]:focus {
- outline: thin dotted;
- outline: 5px auto -webkit-focus-ring-color;
- outline-offset: -2px;
-}
-output {
- display: block;
- padding-top: 7px;
- font-size: 16px;
- line-height: 1.42857143;
- color: #888888;
-}
-.form-control {
- display: block;
- width: 100%;
- height: 36px;
- padding: 6px 12px;
- font-size: 16px;
- line-height: 1.42857143;
- color: #888888;
- background-color: #fff;
- background-image: none;
- border: 1px solid #ccc;
- border-radius: 4px;
- -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
- box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
- -webkit-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
- -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
- transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
-}
-.form-control:focus {
- border-color: #66afe9;
- outline: 0;
- -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);
- box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);
-}
-.form-control::-moz-placeholder {
- color: #999;
- opacity: 1;
-}
-.form-control:-ms-input-placeholder {
- color: #999;
-}
-.form-control::-webkit-input-placeholder {
- color: #999;
-}
-.form-control::-ms-expand {
- border: 0;
- background-color: transparent;
-}
-.form-control[disabled],
-.form-control[readonly],
-fieldset[disabled] .form-control {
- background-color: #F2F2F2;
- opacity: 1;
-}
-.form-control[disabled],
-fieldset[disabled] .form-control {
- cursor: not-allowed;
-}
-textarea.form-control {
- height: auto;
-}
-input[type="search"] {
- -webkit-appearance: none;
-}
-@media screen and (-webkit-min-device-pixel-ratio: 0) {
- input[type="date"].form-control,
- input[type="time"].form-control,
- input[type="datetime-local"].form-control,
- input[type="month"].form-control {
- line-height: 36px;
- }
- input[type="date"].input-sm,
- input[type="time"].input-sm,
- input[type="datetime-local"].input-sm,
- input[type="month"].input-sm,
- .input-group-sm input[type="date"],
- .input-group-sm input[type="time"],
- .input-group-sm input[type="datetime-local"],
- .input-group-sm input[type="month"] {
- line-height: 33px;
- }
- input[type="date"].input-lg,
- input[type="time"].input-lg,
- input[type="datetime-local"].input-lg,
- input[type="month"].input-lg,
- .input-group-lg input[type="date"],
- .input-group-lg input[type="time"],
- .input-group-lg input[type="datetime-local"],
- .input-group-lg input[type="month"] {
- line-height: 49px;
- }
-}
-.form-group {
- margin-bottom: 15px;
-}
-.radio,
-.checkbox {
- position: relative;
- display: block;
- margin-top: 10px;
- margin-bottom: 10px;
-}
-.radio label,
-.checkbox label {
- min-height: 22px;
- padding-left: 20px;
- margin-bottom: 0;
- font-weight: normal;
- cursor: pointer;
-}
-.radio input[type="radio"],
-.radio-inline input[type="radio"],
-.checkbox input[type="checkbox"],
-.checkbox-inline input[type="checkbox"] {
- position: absolute;
- margin-left: -20px;
- margin-top: 4px \9;
-}
-.radio + .radio,
-.checkbox + .checkbox {
- margin-top: -5px;
-}
-.radio-inline,
-.checkbox-inline {
- position: relative;
- display: inline-block;
- padding-left: 20px;
- margin-bottom: 0;
- vertical-align: middle;
- font-weight: normal;
- cursor: pointer;
-}
-.radio-inline + .radio-inline,
-.checkbox-inline + .checkbox-inline {
- margin-top: 0;
- margin-left: 10px;
-}
-input[type="radio"][disabled],
-input[type="checkbox"][disabled],
-input[type="radio"].disabled,
-input[type="checkbox"].disabled,
-fieldset[disabled] input[type="radio"],
-fieldset[disabled] input[type="checkbox"] {
- cursor: not-allowed;
-}
-.radio-inline.disabled,
-.checkbox-inline.disabled,
-fieldset[disabled] .radio-inline,
-fieldset[disabled] .checkbox-inline {
- cursor: not-allowed;
-}
-.radio.disabled label,
-.checkbox.disabled label,
-fieldset[disabled] .radio label,
-fieldset[disabled] .checkbox label {
- cursor: not-allowed;
-}
-.form-control-static {
- padding-top: 7px;
- padding-bottom: 7px;
- margin-bottom: 0;
- min-height: 38px;
-}
-.form-control-static.input-lg,
-.form-control-static.input-sm {
- padding-left: 0;
- padding-right: 0;
-}
-.input-sm {
- height: 33px;
- padding: 5px 10px;
- font-size: 14px;
- line-height: 1.5;
- border-radius: 3px;
-}
-select.input-sm {
- height: 33px;
- line-height: 33px;
-}
-textarea.input-sm,
-select[multiple].input-sm {
- height: auto;
-}
-.form-group-sm .form-control {
- height: 33px;
- padding: 5px 10px;
- font-size: 14px;
- line-height: 1.5;
- border-radius: 3px;
-}
-.form-group-sm select.form-control {
- height: 33px;
- line-height: 33px;
-}
-.form-group-sm textarea.form-control,
-.form-group-sm select[multiple].form-control {
- height: auto;
-}
-.form-group-sm .form-control-static {
- height: 33px;
- min-height: 36px;
- padding: 6px 10px;
- font-size: 14px;
- line-height: 1.5;
-}
-.input-lg {
- height: 49px;
- padding: 10px 16px;
- font-size: 20px;
- line-height: 1.3333333;
- border-radius: 6px;
-}
-select.input-lg {
- height: 49px;
- line-height: 49px;
-}
-textarea.input-lg,
-select[multiple].input-lg {
- height: auto;
-}
-.form-group-lg .form-control {
- height: 49px;
- padding: 10px 16px;
- font-size: 20px;
- line-height: 1.3333333;
- border-radius: 6px;
-}
-.form-group-lg select.form-control {
- height: 49px;
- line-height: 49px;
-}
-.form-group-lg textarea.form-control,
-.form-group-lg select[multiple].form-control {
- height: auto;
-}
-.form-group-lg .form-control-static {
- height: 49px;
- min-height: 42px;
- padding: 11px 16px;
- font-size: 20px;
- line-height: 1.3333333;
-}
-.has-feedback {
- position: relative;
-}
-.has-feedback .form-control {
- padding-right: 45px;
-}
-.form-control-feedback {
- position: absolute;
- top: 0;
- right: 0;
- z-index: 2;
- display: block;
- width: 36px;
- height: 36px;
- line-height: 36px;
- text-align: center;
- pointer-events: none;
-}
-.input-lg + .form-control-feedback,
-.input-group-lg + .form-control-feedback,
-.form-group-lg .form-control + .form-control-feedback {
- width: 49px;
- height: 49px;
- line-height: 49px;
-}
-.input-sm + .form-control-feedback,
-.input-group-sm + .form-control-feedback,
-.form-group-sm .form-control + .form-control-feedback {
- width: 33px;
- height: 33px;
- line-height: 33px;
-}
-.has-success .help-block,
-.has-success .control-label,
-.has-success .radio,
-.has-success .checkbox,
-.has-success .radio-inline,
-.has-success .checkbox-inline,
-.has-success.radio label,
-.has-success.checkbox label,
-.has-success.radio-inline label,
-.has-success.checkbox-inline label {
- color: #3c763d;
-}
-.has-success .form-control {
- border-color: #3c763d;
- -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
- box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
-}
-.has-success .form-control:focus {
- border-color: #2b542c;
- -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168;
- box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168;
-}
-.has-success .input-group-addon {
- color: #3c763d;
- border-color: #3c763d;
- background-color: #dff0d8;
-}
-.has-success .form-control-feedback {
- color: #3c763d;
-}
-.has-warning .help-block,
-.has-warning .control-label,
-.has-warning .radio,
-.has-warning .checkbox,
-.has-warning .radio-inline,
-.has-warning .checkbox-inline,
-.has-warning.radio label,
-.has-warning.checkbox label,
-.has-warning.radio-inline label,
-.has-warning.checkbox-inline label {
- color: #8a6d3b;
-}
-.has-warning .form-control {
- border-color: #8a6d3b;
- -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
- box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
-}
-.has-warning .form-control:focus {
- border-color: #66512c;
- -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b;
- box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b;
-}
-.has-warning .input-group-addon {
- color: #8a6d3b;
- border-color: #8a6d3b;
- background-color: #fcf8e3;
-}
-.has-warning .form-control-feedback {
- color: #8a6d3b;
-}
-.has-error .help-block,
-.has-error .control-label,
-.has-error .radio,
-.has-error .checkbox,
-.has-error .radio-inline,
-.has-error .checkbox-inline,
-.has-error.radio label,
-.has-error.checkbox label,
-.has-error.radio-inline label,
-.has-error.checkbox-inline label {
- color: #a94442;
-}
-.has-error .form-control {
- border-color: #a94442;
- -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
- box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
-}
-.has-error .form-control:focus {
- border-color: #843534;
- -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483;
- box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483;
-}
-.has-error .input-group-addon {
- color: #a94442;
- border-color: #a94442;
- background-color: #f2dede;
-}
-.has-error .form-control-feedback {
- color: #a94442;
-}
-.has-feedback label ~ .form-control-feedback {
- top: 27px;
-}
-.has-feedback label.sr-only ~ .form-control-feedback {
- top: 0;
-}
-.help-block {
- display: block;
- margin-top: 5px;
- margin-bottom: 10px;
- color: #717f88;
-}
-@media (min-width: 768px) {
- .form-inline .form-group {
- display: inline-block;
- margin-bottom: 0;
- vertical-align: middle;
- }
- .form-inline .form-control {
- display: inline-block;
- width: auto;
- vertical-align: middle;
- }
- .form-inline .form-control-static {
- display: inline-block;
- }
- .form-inline .input-group {
- display: inline-table;
- vertical-align: middle;
- }
- .form-inline .input-group .input-group-addon,
- .form-inline .input-group .input-group-btn,
- .form-inline .input-group .form-control {
- width: auto;
- }
- .form-inline .input-group > .form-control {
- width: 100%;
- }
- .form-inline .control-label {
- margin-bottom: 0;
- vertical-align: middle;
- }
- .form-inline .radio,
- .form-inline .checkbox {
- display: inline-block;
- margin-top: 0;
- margin-bottom: 0;
- vertical-align: middle;
- }
- .form-inline .radio label,
- .form-inline .checkbox label {
- padding-left: 0;
- }
- .form-inline .radio input[type="radio"],
- .form-inline .checkbox input[type="checkbox"] {
- position: relative;
- margin-left: 0;
- }
- .form-inline .has-feedback .form-control-feedback {
- top: 0;
- }
-}
-.form-horizontal .radio,
-.form-horizontal .checkbox,
-.form-horizontal .radio-inline,
-.form-horizontal .checkbox-inline {
- margin-top: 0;
- margin-bottom: 0;
- padding-top: 7px;
-}
-.form-horizontal .radio,
-.form-horizontal .checkbox {
- min-height: 29px;
-}
-.form-horizontal .form-group {
- margin-left: -15px;
- margin-right: -15px;
-}
-@media (min-width: 768px) {
- .form-horizontal .control-label {
- text-align: right;
- margin-bottom: 0;
- padding-top: 7px;
- }
-}
-.form-horizontal .has-feedback .form-control-feedback {
- right: 15px;
-}
-@media (min-width: 768px) {
- .form-horizontal .form-group-lg .control-label {
- padding-top: 11px;
- font-size: 20px;
- }
-}
-@media (min-width: 768px) {
- .form-horizontal .form-group-sm .control-label {
- padding-top: 6px;
- font-size: 14px;
- }
-}
-.btn {
- display: inline-block;
- margin-bottom: 0;
- font-weight: normal;
- text-align: center;
- vertical-align: middle;
- touch-action: manipulation;
- cursor: pointer;
- background-image: none;
- border: 1px solid transparent;
- white-space: nowrap;
- padding: 6px 12px;
- font-size: 16px;
- line-height: 1.42857143;
- border-radius: 4px;
- -webkit-user-select: none;
- -moz-user-select: none;
- -ms-user-select: none;
- user-select: none;
-}
-.btn:focus,
-.btn:active:focus,
-.btn.active:focus,
-.btn.focus,
-.btn:active.focus,
-.btn.active.focus {
- outline: thin dotted;
- outline: 5px auto -webkit-focus-ring-color;
- outline-offset: -2px;
-}
-.btn:hover,
-.btn:focus,
-.btn.focus {
- color: #333;
- text-decoration: none;
-}
-.btn:active,
-.btn.active {
- outline: 0;
- background-image: none;
- -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
- box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
-}
-.btn.disabled,
-.btn[disabled],
-fieldset[disabled] .btn {
- cursor: not-allowed;
- opacity: 0.65;
- filter: alpha(opacity=65);
- -webkit-box-shadow: none;
- box-shadow: none;
-}
-a.btn.disabled,
-fieldset[disabled] a.btn {
- pointer-events: none;
-}
-.btn-default {
- color: #333;
- background-color: #fff;
- border-color: #ccc;
-}
-.btn-default:focus,
-.btn-default.focus {
- color: #333;
- background-color: #e6e6e6;
- border-color: #8c8c8c;
-}
-.btn-default:hover {
- color: #333;
- background-color: #e6e6e6;
- border-color: #adadad;
-}
-.btn-default:active,
-.btn-default.active,
-.open > .dropdown-toggle.btn-default {
- color: #333;
- background-color: #e6e6e6;
- border-color: #adadad;
-}
-.btn-default:active:hover,
-.btn-default.active:hover,
-.open > .dropdown-toggle.btn-default:hover,
-.btn-default:active:focus,
-.btn-default.active:focus,
-.open > .dropdown-toggle.btn-default:focus,
-.btn-default:active.focus,
-.btn-default.active.focus,
-.open > .dropdown-toggle.btn-default.focus {
- color: #333;
- background-color: #d4d4d4;
- border-color: #8c8c8c;
-}
-.btn-default:active,
-.btn-default.active,
-.open > .dropdown-toggle.btn-default {
- background-image: none;
-}
-.btn-default.disabled:hover,
-.btn-default[disabled]:hover,
-fieldset[disabled] .btn-default:hover,
-.btn-default.disabled:focus,
-.btn-default[disabled]:focus,
-fieldset[disabled] .btn-default:focus,
-.btn-default.disabled.focus,
-.btn-default[disabled].focus,
-fieldset[disabled] .btn-default.focus {
- background-color: #fff;
- border-color: #ccc;
-}
-.btn-default .badge {
- color: #fff;
- background-color: #333;
-}
-.btn-primary {
- color: #fff;
- background-color: #21b799;
- border-color: #1da187;
-}
-.btn-primary:focus,
-.btn-primary.focus {
- color: #fff;
- background-color: #198c75;
- border-color: #0a352d;
-}
-.btn-primary:hover {
- color: #fff;
- background-color: #198c75;
- border-color: #146e5c;
-}
-.btn-primary:active,
-.btn-primary.active,
-.open > .dropdown-toggle.btn-primary {
- color: #fff;
- background-color: #198c75;
- border-color: #146e5c;
-}
-.btn-primary:active:hover,
-.btn-primary.active:hover,
-.open > .dropdown-toggle.btn-primary:hover,
-.btn-primary:active:focus,
-.btn-primary.active:focus,
-.open > .dropdown-toggle.btn-primary:focus,
-.btn-primary:active.focus,
-.btn-primary.active.focus,
-.open > .dropdown-toggle.btn-primary.focus {
- color: #fff;
- background-color: #146e5c;
- border-color: #0a352d;
-}
-.btn-primary:active,
-.btn-primary.active,
-.open > .dropdown-toggle.btn-primary {
- background-image: none;
-}
-.btn-primary.disabled:hover,
-.btn-primary[disabled]:hover,
-fieldset[disabled] .btn-primary:hover,
-.btn-primary.disabled:focus,
-.btn-primary[disabled]:focus,
-fieldset[disabled] .btn-primary:focus,
-.btn-primary.disabled.focus,
-.btn-primary[disabled].focus,
-fieldset[disabled] .btn-primary.focus {
- background-color: #21b799;
- border-color: #1da187;
-}
-.btn-primary .badge {
- color: #21b799;
- background-color: #fff;
-}
-.btn-success {
- color: #fff;
- background-color: #50AF51;
- border-color: #489e49;
-}
-.btn-success:focus,
-.btn-success.focus {
- color: #fff;
- background-color: #408c41;
- border-color: #204620;
-}
-.btn-success:hover {
- color: #fff;
- background-color: #408c41;
- border-color: #357435;
-}
-.btn-success:active,
-.btn-success.active,
-.open > .dropdown-toggle.btn-success {
- color: #fff;
- background-color: #408c41;
- border-color: #357435;
-}
-.btn-success:active:hover,
-.btn-success.active:hover,
-.open > .dropdown-toggle.btn-success:hover,
-.btn-success:active:focus,
-.btn-success.active:focus,
-.open > .dropdown-toggle.btn-success:focus,
-.btn-success:active.focus,
-.btn-success.active.focus,
-.open > .dropdown-toggle.btn-success.focus {
- color: #fff;
- background-color: #357335;
- border-color: #204620;
-}
-.btn-success:active,
-.btn-success.active,
-.open > .dropdown-toggle.btn-success {
- background-image: none;
-}
-.btn-success.disabled:hover,
-.btn-success[disabled]:hover,
-fieldset[disabled] .btn-success:hover,
-.btn-success.disabled:focus,
-.btn-success[disabled]:focus,
-fieldset[disabled] .btn-success:focus,
-.btn-success.disabled.focus,
-.btn-success[disabled].focus,
-fieldset[disabled] .btn-success.focus {
- background-color: #50AF51;
- border-color: #489e49;
-}
-.btn-success .badge {
- color: #50AF51;
- background-color: #fff;
-}
-.btn-info {
- color: #fff;
- background-color: #4B9EB6;
- border-color: #438fa5;
-}
-.btn-info:focus,
-.btn-info.focus {
- color: #fff;
- background-color: #3b7f93;
- border-color: #1e404a;
-}
-.btn-info:hover {
- color: #fff;
- background-color: #3b7f93;
- border-color: #316979;
-}
-.btn-info:active,
-.btn-info.active,
-.open > .dropdown-toggle.btn-info {
- color: #fff;
- background-color: #3b7f93;
- border-color: #316979;
-}
-.btn-info:active:hover,
-.btn-info.active:hover,
-.open > .dropdown-toggle.btn-info:hover,
-.btn-info:active:focus,
-.btn-info.active:focus,
-.open > .dropdown-toggle.btn-info:focus,
-.btn-info:active.focus,
-.btn-info.active.focus,
-.open > .dropdown-toggle.btn-info.focus {
- color: #fff;
- background-color: #316979;
- border-color: #1e404a;
-}
-.btn-info:active,
-.btn-info.active,
-.open > .dropdown-toggle.btn-info {
- background-image: none;
-}
-.btn-info.disabled:hover,
-.btn-info[disabled]:hover,
-fieldset[disabled] .btn-info:hover,
-.btn-info.disabled:focus,
-.btn-info[disabled]:focus,
-fieldset[disabled] .btn-info:focus,
-.btn-info.disabled.focus,
-.btn-info[disabled].focus,
-fieldset[disabled] .btn-info.focus {
- background-color: #4B9EB6;
- border-color: #438fa5;
-}
-.btn-info .badge {
- color: #4B9EB6;
- background-color: #fff;
-}
-.btn-warning {
- color: #fff;
- background-color: #F0AD4E;
- border-color: #eea236;
-}
-.btn-warning:focus,
-.btn-warning.focus {
- color: #fff;
- background-color: #ec971f;
- border-color: #985f0d;
-}
-.btn-warning:hover {
- color: #fff;
- background-color: #ec971f;
- border-color: #d58512;
-}
-.btn-warning:active,
-.btn-warning.active,
-.open > .dropdown-toggle.btn-warning {
- color: #fff;
- background-color: #ec971f;
- border-color: #d58512;
-}
-.btn-warning:active:hover,
-.btn-warning.active:hover,
-.open > .dropdown-toggle.btn-warning:hover,
-.btn-warning:active:focus,
-.btn-warning.active:focus,
-.open > .dropdown-toggle.btn-warning:focus,
-.btn-warning:active.focus,
-.btn-warning.active.focus,
-.open > .dropdown-toggle.btn-warning.focus {
- color: #fff;
- background-color: #d58512;
- border-color: #985f0d;
-}
-.btn-warning:active,
-.btn-warning.active,
-.open > .dropdown-toggle.btn-warning {
- background-image: none;
-}
-.btn-warning.disabled:hover,
-.btn-warning[disabled]:hover,
-fieldset[disabled] .btn-warning:hover,
-.btn-warning.disabled:focus,
-.btn-warning[disabled]:focus,
-fieldset[disabled] .btn-warning:focus,
-.btn-warning.disabled.focus,
-.btn-warning[disabled].focus,
-fieldset[disabled] .btn-warning.focus {
- background-color: #F0AD4E;
- border-color: #eea236;
-}
-.btn-warning .badge {
- color: #F0AD4E;
- background-color: #fff;
-}
-.btn-danger {
- color: #fff;
- background-color: #D9534F;
- border-color: #d43f3a;
-}
-.btn-danger:focus,
-.btn-danger.focus {
- color: #fff;
- background-color: #c9302c;
- border-color: #761c19;
-}
-.btn-danger:hover {
- color: #fff;
- background-color: #c9302c;
- border-color: #ac2925;
-}
-.btn-danger:active,
-.btn-danger.active,
-.open > .dropdown-toggle.btn-danger {
- color: #fff;
- background-color: #c9302c;
- border-color: #ac2925;
-}
-.btn-danger:active:hover,
-.btn-danger.active:hover,
-.open > .dropdown-toggle.btn-danger:hover,
-.btn-danger:active:focus,
-.btn-danger.active:focus,
-.open > .dropdown-toggle.btn-danger:focus,
-.btn-danger:active.focus,
-.btn-danger.active.focus,
-.open > .dropdown-toggle.btn-danger.focus {
- color: #fff;
- background-color: #ac2925;
- border-color: #761c19;
-}
-.btn-danger:active,
-.btn-danger.active,
-.open > .dropdown-toggle.btn-danger {
- background-image: none;
-}
-.btn-danger.disabled:hover,
-.btn-danger[disabled]:hover,
-fieldset[disabled] .btn-danger:hover,
-.btn-danger.disabled:focus,
-.btn-danger[disabled]:focus,
-fieldset[disabled] .btn-danger:focus,
-.btn-danger.disabled.focus,
-.btn-danger[disabled].focus,
-fieldset[disabled] .btn-danger.focus {
- background-color: #D9534F;
- border-color: #d43f3a;
-}
-.btn-danger .badge {
- color: #D9534F;
- background-color: #fff;
-}
-.btn-link {
- color: #875A7B;
- font-weight: normal;
- border-radius: 0;
-}
-.btn-link,
-.btn-link:active,
-.btn-link.active,
-.btn-link[disabled],
-fieldset[disabled] .btn-link {
- background-color: transparent;
- -webkit-box-shadow: none;
- box-shadow: none;
-}
-.btn-link,
-.btn-link:hover,
-.btn-link:focus,
-.btn-link:active {
- border-color: transparent;
-}
-.btn-link:hover,
-.btn-link:focus {
- color: #926485;
- text-decoration: none;
- background-color: transparent;
-}
-.btn-link[disabled]:hover,
-fieldset[disabled] .btn-link:hover,
-.btn-link[disabled]:focus,
-fieldset[disabled] .btn-link:focus {
- color: #dcddde;
- text-decoration: none;
-}
-.btn-lg,
-.btn-group-lg > .btn {
- padding: 10px 16px;
- font-size: 20px;
- line-height: 1.3333333;
- border-radius: 6px;
-}
-.btn-sm,
-.btn-group-sm > .btn {
- padding: 5px 10px;
- font-size: 14px;
- line-height: 1.5;
- border-radius: 3px;
-}
-.btn-xs,
-.btn-group-xs > .btn {
- padding: 1px 5px;
- font-size: 14px;
- line-height: 1.5;
- border-radius: 3px;
-}
-.btn-block {
- display: block;
- width: 100%;
-}
-.btn-block + .btn-block {
- margin-top: 5px;
-}
-input[type="submit"].btn-block,
-input[type="reset"].btn-block,
-input[type="button"].btn-block {
- width: 100%;
-}
-.fade {
- opacity: 0;
- -webkit-transition: opacity 0.15s linear;
- -o-transition: opacity 0.15s linear;
- transition: opacity 0.15s linear;
-}
-.fade.in {
- opacity: 1;
-}
-.collapse {
- display: none;
-}
-.collapse.in {
- display: block;
-}
-tr.collapse.in {
- display: table-row;
-}
-tbody.collapse.in {
- display: table-row-group;
-}
-.collapsing {
- position: relative;
- height: 0;
- overflow: hidden;
- -webkit-transition-property: height, visibility;
- transition-property: height, visibility;
- -webkit-transition-duration: 0.35s;
- transition-duration: 0.35s;
- -webkit-transition-timing-function: ease;
- transition-timing-function: ease;
-}
-.caret {
- display: inline-block;
- width: 0;
- height: 0;
- margin-left: 2px;
- vertical-align: middle;
- border-top: 4px dashed;
- border-top: 4px solid \9;
- border-right: 4px solid transparent;
- border-left: 4px solid transparent;
-}
-.dropup,
-.dropdown {
- position: relative;
-}
-.dropdown-toggle:focus {
- outline: 0;
-}
-.dropdown-menu {
- position: absolute;
- top: 100%;
- left: 0;
- z-index: 1000;
- display: none;
- float: left;
- min-width: 160px;
- padding: 5px 0;
- margin: 2px 0 0;
- list-style: none;
- font-size: 16px;
- text-align: left;
- background-color: #fff;
- border: 1px solid #ccc;
- border: 1px solid rgba(0, 0, 0, 0.15);
- border-radius: 4px;
- -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);
- box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);
- background-clip: padding-box;
-}
-.dropdown-menu.pull-right {
- right: 0;
- left: auto;
-}
-.dropdown-menu .divider {
- height: 1px;
- margin: 10px 0;
- overflow: hidden;
- background-color: #e5e5e5;
-}
-.dropdown-menu > li > a {
- display: block;
- padding: 3px 20px;
- clear: both;
- font-weight: normal;
- line-height: 1.42857143;
- color: #6B6D70;
- white-space: nowrap;
-}
-.dropdown-menu > li > a:hover,
-.dropdown-menu > li > a:focus {
- text-decoration: none;
- color: #5f6063;
- background-color: #f5f5f5;
-}
-.dropdown-menu > .active > a,
-.dropdown-menu > .active > a:hover,
-.dropdown-menu > .active > a:focus {
- color: #fff;
- text-decoration: none;
- outline: 0;
- background-color: #21b799;
-}
-.dropdown-menu > .disabled > a,
-.dropdown-menu > .disabled > a:hover,
-.dropdown-menu > .disabled > a:focus {
- color: #dcddde;
-}
-.dropdown-menu > .disabled > a:hover,
-.dropdown-menu > .disabled > a:focus {
- text-decoration: none;
- background-color: transparent;
- background-image: none;
- filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
- cursor: not-allowed;
-}
-.open > .dropdown-menu {
- display: block;
-}
-.open > a {
- outline: 0;
-}
-.dropdown-menu-right {
- left: auto;
- right: 0;
-}
-.dropdown-menu-left {
- left: 0;
- right: auto;
-}
-.dropdown-header {
- display: block;
- padding: 3px 20px;
- font-size: 14px;
- line-height: 1.42857143;
- color: #dcddde;
- white-space: nowrap;
-}
-.dropdown-backdrop {
- position: fixed;
- left: 0;
- right: 0;
- bottom: 0;
- top: 0;
- z-index: 990;
-}
-.pull-right > .dropdown-menu {
- right: 0;
- left: auto;
-}
-.dropup .caret,
-.navbar-fixed-bottom .dropdown .caret {
- border-top: 0;
- border-bottom: 4px dashed;
- border-bottom: 4px solid \9;
- content: "";
-}
-.dropup .dropdown-menu,
-.navbar-fixed-bottom .dropdown .dropdown-menu {
- top: auto;
- bottom: 100%;
- margin-bottom: 2px;
-}
-@media (min-width: 768px) {
- .navbar-right .dropdown-menu {
- left: auto;
- right: 0;
- }
- .navbar-right .dropdown-menu-left {
- left: 0;
- right: auto;
- }
-}
-.btn-group,
-.btn-group-vertical {
- position: relative;
- display: inline-block;
- vertical-align: middle;
-}
-.btn-group > .btn,
-.btn-group-vertical > .btn {
- position: relative;
- float: left;
-}
-.btn-group > .btn:hover,
-.btn-group-vertical > .btn:hover,
-.btn-group > .btn:focus,
-.btn-group-vertical > .btn:focus,
-.btn-group > .btn:active,
-.btn-group-vertical > .btn:active,
-.btn-group > .btn.active,
-.btn-group-vertical > .btn.active {
- z-index: 2;
-}
-.btn-group .btn + .btn,
-.btn-group .btn + .btn-group,
-.btn-group .btn-group + .btn,
-.btn-group .btn-group + .btn-group {
- margin-left: -1px;
-}
-.btn-toolbar {
- margin-left: -5px;
-}
-.btn-toolbar .btn,
-.btn-toolbar .btn-group,
-.btn-toolbar .input-group {
- float: left;
-}
-.btn-toolbar > .btn,
-.btn-toolbar > .btn-group,
-.btn-toolbar > .input-group {
- margin-left: 5px;
-}
-.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) {
- border-radius: 0;
-}
-.btn-group > .btn:first-child {
- margin-left: 0;
-}
-.btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) {
- border-bottom-right-radius: 0;
- border-top-right-radius: 0;
-}
-.btn-group > .btn:last-child:not(:first-child),
-.btn-group > .dropdown-toggle:not(:first-child) {
- border-bottom-left-radius: 0;
- border-top-left-radius: 0;
-}
-.btn-group > .btn-group {
- float: left;
-}
-.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn {
- border-radius: 0;
-}
-.btn-group > .btn-group:first-child:not(:last-child) > .btn:last-child,
-.btn-group > .btn-group:first-child:not(:last-child) > .dropdown-toggle {
- border-bottom-right-radius: 0;
- border-top-right-radius: 0;
-}
-.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child {
- border-bottom-left-radius: 0;
- border-top-left-radius: 0;
-}
-.btn-group .dropdown-toggle:active,
-.btn-group.open .dropdown-toggle {
- outline: 0;
-}
-.btn-group > .btn + .dropdown-toggle {
- padding-left: 8px;
- padding-right: 8px;
-}
-.btn-group > .btn-lg + .dropdown-toggle {
- padding-left: 12px;
- padding-right: 12px;
-}
-.btn-group.open .dropdown-toggle {
- -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
- box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
-}
-.btn-group.open .dropdown-toggle.btn-link {
- -webkit-box-shadow: none;
- box-shadow: none;
-}
-.btn .caret {
- margin-left: 0;
-}
-.btn-lg .caret {
- border-width: 5px 5px 0;
- border-bottom-width: 0;
-}
-.dropup .btn-lg .caret {
- border-width: 0 5px 5px;
-}
-.btn-group-vertical > .btn,
-.btn-group-vertical > .btn-group,
-.btn-group-vertical > .btn-group > .btn {
- display: block;
- float: none;
- width: 100%;
- max-width: 100%;
-}
-.btn-group-vertical > .btn-group > .btn {
- float: none;
-}
-.btn-group-vertical > .btn + .btn,
-.btn-group-vertical > .btn + .btn-group,
-.btn-group-vertical > .btn-group + .btn,
-.btn-group-vertical > .btn-group + .btn-group {
- margin-top: -1px;
- margin-left: 0;
-}
-.btn-group-vertical > .btn:not(:first-child):not(:last-child) {
- border-radius: 0;
-}
-.btn-group-vertical > .btn:first-child:not(:last-child) {
- border-top-right-radius: 4px;
- border-top-left-radius: 4px;
- border-bottom-right-radius: 0;
- border-bottom-left-radius: 0;
-}
-.btn-group-vertical > .btn:last-child:not(:first-child) {
- border-top-right-radius: 0;
- border-top-left-radius: 0;
- border-bottom-right-radius: 4px;
- border-bottom-left-radius: 4px;
-}
-.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn {
- border-radius: 0;
-}
-.btn-group-vertical > .btn-group:first-child:not(:last-child) > .btn:last-child,
-.btn-group-vertical > .btn-group:first-child:not(:last-child) > .dropdown-toggle {
- border-bottom-right-radius: 0;
- border-bottom-left-radius: 0;
-}
-.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child {
- border-top-right-radius: 0;
- border-top-left-radius: 0;
-}
-.btn-group-justified {
- display: table;
- width: 100%;
- table-layout: fixed;
- border-collapse: separate;
-}
-.btn-group-justified > .btn,
-.btn-group-justified > .btn-group {
- float: none;
- display: table-cell;
- width: 1%;
-}
-.btn-group-justified > .btn-group .btn {
- width: 100%;
-}
-.btn-group-justified > .btn-group .dropdown-menu {
- left: auto;
-}
-[data-toggle="buttons"] > .btn input[type="radio"],
-[data-toggle="buttons"] > .btn-group > .btn input[type="radio"],
-[data-toggle="buttons"] > .btn input[type="checkbox"],
-[data-toggle="buttons"] > .btn-group > .btn input[type="checkbox"] {
- position: absolute;
- clip: rect(0, 0, 0, 0);
- pointer-events: none;
-}
-.input-group {
- position: relative;
- display: table;
- border-collapse: separate;
-}
-.input-group[class*="col-"] {
- float: none;
- padding-left: 0;
- padding-right: 0;
-}
-.input-group .form-control {
- position: relative;
- z-index: 2;
- float: left;
- width: 100%;
- margin-bottom: 0;
-}
-.input-group .form-control:focus {
- z-index: 3;
-}
-.input-group-lg > .form-control,
-.input-group-lg > .input-group-addon,
-.input-group-lg > .input-group-btn > .btn {
- height: 49px;
- padding: 10px 16px;
- font-size: 20px;
- line-height: 1.3333333;
- border-radius: 6px;
-}
-select.input-group-lg > .form-control,
-select.input-group-lg > .input-group-addon,
-select.input-group-lg > .input-group-btn > .btn {
- height: 49px;
- line-height: 49px;
-}
-textarea.input-group-lg > .form-control,
-textarea.input-group-lg > .input-group-addon,
-textarea.input-group-lg > .input-group-btn > .btn,
-select[multiple].input-group-lg > .form-control,
-select[multiple].input-group-lg > .input-group-addon,
-select[multiple].input-group-lg > .input-group-btn > .btn {
- height: auto;
-}
-.input-group-sm > .form-control,
-.input-group-sm > .input-group-addon,
-.input-group-sm > .input-group-btn > .btn {
- height: 33px;
- padding: 5px 10px;
- font-size: 14px;
- line-height: 1.5;
- border-radius: 3px;
-}
-select.input-group-sm > .form-control,
-select.input-group-sm > .input-group-addon,
-select.input-group-sm > .input-group-btn > .btn {
- height: 33px;
- line-height: 33px;
-}
-textarea.input-group-sm > .form-control,
-textarea.input-group-sm > .input-group-addon,
-textarea.input-group-sm > .input-group-btn > .btn,
-select[multiple].input-group-sm > .form-control,
-select[multiple].input-group-sm > .input-group-addon,
-select[multiple].input-group-sm > .input-group-btn > .btn {
- height: auto;
-}
-.input-group-addon,
-.input-group-btn,
-.input-group .form-control {
- display: table-cell;
-}
-.input-group-addon:not(:first-child):not(:last-child),
-.input-group-btn:not(:first-child):not(:last-child),
-.input-group .form-control:not(:first-child):not(:last-child) {
- border-radius: 0;
-}
-.input-group-addon,
-.input-group-btn {
- width: 1%;
- white-space: nowrap;
- vertical-align: middle;
-}
-.input-group-addon {
- padding: 6px 12px;
- font-size: 16px;
- font-weight: normal;
- line-height: 1;
- color: #888888;
- text-align: center;
- background-color: #F2F2F2;
- border: 1px solid #ccc;
- border-radius: 4px;
-}
-.input-group-addon.input-sm {
- padding: 5px 10px;
- font-size: 14px;
- border-radius: 3px;
-}
-.input-group-addon.input-lg {
- padding: 10px 16px;
- font-size: 20px;
- border-radius: 6px;
-}
-.input-group-addon input[type="radio"],
-.input-group-addon input[type="checkbox"] {
- margin-top: 0;
-}
-.input-group .form-control:first-child,
-.input-group-addon:first-child,
-.input-group-btn:first-child > .btn,
-.input-group-btn:first-child > .btn-group > .btn,
-.input-group-btn:first-child > .dropdown-toggle,
-.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle),
-.input-group-btn:last-child > .btn-group:not(:last-child) > .btn {
- border-bottom-right-radius: 0;
- border-top-right-radius: 0;
-}
-.input-group-addon:first-child {
- border-right: 0;
-}
-.input-group .form-control:last-child,
-.input-group-addon:last-child,
-.input-group-btn:last-child > .btn,
-.input-group-btn:last-child > .btn-group > .btn,
-.input-group-btn:last-child > .dropdown-toggle,
-.input-group-btn:first-child > .btn:not(:first-child),
-.input-group-btn:first-child > .btn-group:not(:first-child) > .btn {
- border-bottom-left-radius: 0;
- border-top-left-radius: 0;
-}
-.input-group-addon:last-child {
- border-left: 0;
-}
-.input-group-btn {
- position: relative;
- font-size: 0;
- white-space: nowrap;
-}
-.input-group-btn > .btn {
- position: relative;
-}
-.input-group-btn > .btn + .btn {
- margin-left: -1px;
-}
-.input-group-btn > .btn:hover,
-.input-group-btn > .btn:focus,
-.input-group-btn > .btn:active {
- z-index: 2;
-}
-.input-group-btn:first-child > .btn,
-.input-group-btn:first-child > .btn-group {
- margin-right: -1px;
-}
-.input-group-btn:last-child > .btn,
-.input-group-btn:last-child > .btn-group {
- z-index: 2;
- margin-left: -1px;
-}
-.nav {
- margin-bottom: 0;
- padding-left: 0;
- list-style: none;
-}
-.nav > li {
- position: relative;
- display: block;
-}
-.nav > li > a {
- position: relative;
- display: block;
- padding: 10px 15px;
-}
-.nav > li > a:hover,
-.nav > li > a:focus {
- text-decoration: none;
- background-color: #F2F2F2;
-}
-.nav > li.disabled > a {
- color: #dcddde;
-}
-.nav > li.disabled > a:hover,
-.nav > li.disabled > a:focus {
- color: #dcddde;
- text-decoration: none;
- background-color: transparent;
- cursor: not-allowed;
-}
-.nav .open > a,
-.nav .open > a:hover,
-.nav .open > a:focus {
- background-color: #F2F2F2;
- border-color: #875A7B;
-}
-.nav .nav-divider {
- height: 1px;
- margin: 10px 0;
- overflow: hidden;
- background-color: #e5e5e5;
-}
-.nav > li > a > img {
- max-width: none;
-}
-.nav-tabs {
- border-bottom: 1px solid #ddd;
-}
-.nav-tabs > li {
- float: left;
- margin-bottom: -1px;
-}
-.nav-tabs > li > a {
- margin-right: 2px;
- line-height: 1.42857143;
- border: 1px solid transparent;
- border-radius: 4px 4px 0 0;
-}
-.nav-tabs > li > a:hover {
- border-color: #F2F2F2 #F2F2F2 #ddd;
-}
-.nav-tabs > li.active > a,
-.nav-tabs > li.active > a:hover,
-.nav-tabs > li.active > a:focus {
- color: #888888;
- background-color: #F9F9F9;
- border: 1px solid #ddd;
- border-bottom-color: transparent;
- cursor: default;
-}
-.nav-tabs.nav-justified {
- width: 100%;
- border-bottom: 0;
-}
-.nav-tabs.nav-justified > li {
- float: none;
-}
-.nav-tabs.nav-justified > li > a {
- text-align: center;
- margin-bottom: 5px;
-}
-.nav-tabs.nav-justified > .dropdown .dropdown-menu {
- top: auto;
- left: auto;
-}
-@media (min-width: 768px) {
- .nav-tabs.nav-justified > li {
- display: table-cell;
- width: 1%;
- }
- .nav-tabs.nav-justified > li > a {
- margin-bottom: 0;
- }
-}
-.nav-tabs.nav-justified > li > a {
- margin-right: 0;
- border-radius: 4px;
-}
-.nav-tabs.nav-justified > .active > a,
-.nav-tabs.nav-justified > .active > a:hover,
-.nav-tabs.nav-justified > .active > a:focus {
- border: 1px solid #ddd;
-}
-@media (min-width: 768px) {
- .nav-tabs.nav-justified > li > a {
- border-bottom: 1px solid #ddd;
- border-radius: 4px 4px 0 0;
- }
- .nav-tabs.nav-justified > .active > a,
- .nav-tabs.nav-justified > .active > a:hover,
- .nav-tabs.nav-justified > .active > a:focus {
- border-bottom-color: #F9F9F9;
- }
-}
-.nav-pills > li {
- float: left;
-}
-.nav-pills > li > a {
- border-radius: 4px;
-}
-.nav-pills > li + li {
- margin-left: 2px;
-}
-.nav-pills > li.active > a,
-.nav-pills > li.active > a:hover,
-.nav-pills > li.active > a:focus {
- color: #fff;
- background-color: #21b799;
-}
-.nav-stacked > li {
- float: none;
-}
-.nav-stacked > li + li {
- margin-top: 2px;
- margin-left: 0;
-}
-.nav-justified {
- width: 100%;
-}
-.nav-justified > li {
- float: none;
-}
-.nav-justified > li > a {
- text-align: center;
- margin-bottom: 5px;
-}
-.nav-justified > .dropdown .dropdown-menu {
- top: auto;
- left: auto;
-}
-@media (min-width: 768px) {
- .nav-justified > li {
- display: table-cell;
- width: 1%;
- }
- .nav-justified > li > a {
- margin-bottom: 0;
- }
-}
-.nav-tabs-justified {
- border-bottom: 0;
-}
-.nav-tabs-justified > li > a {
- margin-right: 0;
- border-radius: 4px;
-}
-.nav-tabs-justified > .active > a,
-.nav-tabs-justified > .active > a:hover,
-.nav-tabs-justified > .active > a:focus {
- border: 1px solid #ddd;
-}
-@media (min-width: 768px) {
- .nav-tabs-justified > li > a {
- border-bottom: 1px solid #ddd;
- border-radius: 4px 4px 0 0;
- }
- .nav-tabs-justified > .active > a,
- .nav-tabs-justified > .active > a:hover,
- .nav-tabs-justified > .active > a:focus {
- border-bottom-color: #F9F9F9;
- }
-}
-.tab-content > .tab-pane {
- display: none;
-}
-.tab-content > .active {
- display: block;
-}
-.nav-tabs .dropdown-menu {
- margin-top: -1px;
- border-top-right-radius: 0;
- border-top-left-radius: 0;
-}
-.navbar {
- position: relative;
- min-height: 50px;
- margin-bottom: 22px;
- border: 1px solid transparent;
-}
-@media (min-width: 768px) {
- .navbar {
- border-radius: 4px;
- }
-}
-@media (min-width: 768px) {
- .navbar-header {
- float: left;
- }
-}
-.navbar-collapse {
- overflow-x: visible;
- padding-right: 15px;
- padding-left: 15px;
- border-top: 1px solid transparent;
- box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1);
- -webkit-overflow-scrolling: touch;
-}
-.navbar-collapse.in {
- overflow-y: auto;
-}
-@media (min-width: 768px) {
- .navbar-collapse {
- width: auto;
- border-top: 0;
- box-shadow: none;
- }
- .navbar-collapse.collapse {
- display: block !important;
- height: auto !important;
- padding-bottom: 0;
- overflow: visible !important;
- }
- .navbar-collapse.in {
- overflow-y: visible;
- }
- .navbar-fixed-top .navbar-collapse,
- .navbar-static-top .navbar-collapse,
- .navbar-fixed-bottom .navbar-collapse {
- padding-left: 0;
- padding-right: 0;
- }
-}
-.navbar-fixed-top .navbar-collapse,
-.navbar-fixed-bottom .navbar-collapse {
- max-height: 340px;
-}
-@media (max-device-width: 480px) and (orientation: landscape) {
- .navbar-fixed-top .navbar-collapse,
- .navbar-fixed-bottom .navbar-collapse {
- max-height: 200px;
- }
-}
-.container > .navbar-header,
-.container-fluid > .navbar-header,
-.container > .navbar-collapse,
-.container-fluid > .navbar-collapse {
- margin-right: -15px;
- margin-left: -15px;
-}
-@media (min-width: 768px) {
- .container > .navbar-header,
- .container-fluid > .navbar-header,
- .container > .navbar-collapse,
- .container-fluid > .navbar-collapse {
- margin-right: 0;
- margin-left: 0;
- }
-}
-.navbar-static-top {
- z-index: 1000;
- border-width: 0 0 1px;
-}
-@media (min-width: 768px) {
- .navbar-static-top {
- border-radius: 0;
- }
-}
-.navbar-fixed-top,
-.navbar-fixed-bottom {
- position: fixed;
- right: 0;
- left: 0;
- z-index: 1030;
-}
-@media (min-width: 768px) {
- .navbar-fixed-top,
- .navbar-fixed-bottom {
- border-radius: 0;
- }
-}
-.navbar-fixed-top {
- top: 0;
- border-width: 0 0 1px;
-}
-.navbar-fixed-bottom {
- bottom: 0;
- margin-bottom: 0;
- border-width: 1px 0 0;
-}
-.navbar-brand {
- float: left;
- padding: 14px 15px;
- font-size: 20px;
- line-height: 22px;
- height: 50px;
-}
-.navbar-brand:hover,
-.navbar-brand:focus {
- text-decoration: none;
-}
-.navbar-brand > img {
- display: block;
-}
-@media (min-width: 768px) {
- .navbar > .container .navbar-brand,
- .navbar > .container-fluid .navbar-brand {
- margin-left: -15px;
- }
-}
-.navbar-toggle {
- position: relative;
- float: right;
- margin-right: 15px;
- padding: 9px 10px;
- margin-top: 8px;
- margin-bottom: 8px;
- background-color: transparent;
- background-image: none;
- border: 1px solid transparent;
- border-radius: 4px;
-}
-.navbar-toggle:focus {
- outline: 0;
-}
-.navbar-toggle .icon-bar {
- display: block;
- width: 22px;
- height: 2px;
- border-radius: 1px;
-}
-.navbar-toggle .icon-bar + .icon-bar {
- margin-top: 4px;
-}
-@media (min-width: 768px) {
- .navbar-toggle {
- display: none;
- }
-}
-.navbar-nav {
- margin: 7px -15px;
-}
-.navbar-nav > li > a {
- padding-top: 10px;
- padding-bottom: 10px;
- line-height: 22px;
-}
-@media (max-width: 767px) {
- .navbar-nav .open .dropdown-menu {
- position: static;
- float: none;
- width: auto;
- margin-top: 0;
- background-color: transparent;
- border: 0;
- box-shadow: none;
- }
- .navbar-nav .open .dropdown-menu > li > a,
- .navbar-nav .open .dropdown-menu .dropdown-header {
- padding: 5px 15px 5px 25px;
- }
- .navbar-nav .open .dropdown-menu > li > a {
- line-height: 22px;
- }
- .navbar-nav .open .dropdown-menu > li > a:hover,
- .navbar-nav .open .dropdown-menu > li > a:focus {
- background-image: none;
- }
-}
-@media (min-width: 768px) {
- .navbar-nav {
- float: left;
- margin: 0;
- }
- .navbar-nav > li {
- float: left;
- }
- .navbar-nav > li > a {
- padding-top: 14px;
- padding-bottom: 14px;
- }
-}
-.navbar-form {
- margin-left: -15px;
- margin-right: -15px;
- padding: 10px 15px;
- border-top: 1px solid transparent;
- border-bottom: 1px solid transparent;
- -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);
- box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);
- margin-top: 7px;
- margin-bottom: 7px;
-}
-@media (min-width: 768px) {
- .navbar-form .form-group {
- display: inline-block;
- margin-bottom: 0;
- vertical-align: middle;
- }
- .navbar-form .form-control {
- display: inline-block;
- width: auto;
- vertical-align: middle;
- }
- .navbar-form .form-control-static {
- display: inline-block;
- }
- .navbar-form .input-group {
- display: inline-table;
- vertical-align: middle;
- }
- .navbar-form .input-group .input-group-addon,
- .navbar-form .input-group .input-group-btn,
- .navbar-form .input-group .form-control {
- width: auto;
- }
- .navbar-form .input-group > .form-control {
- width: 100%;
- }
- .navbar-form .control-label {
- margin-bottom: 0;
- vertical-align: middle;
- }
- .navbar-form .radio,
- .navbar-form .checkbox {
- display: inline-block;
- margin-top: 0;
- margin-bottom: 0;
- vertical-align: middle;
- }
- .navbar-form .radio label,
- .navbar-form .checkbox label {
- padding-left: 0;
- }
- .navbar-form .radio input[type="radio"],
- .navbar-form .checkbox input[type="checkbox"] {
- position: relative;
- margin-left: 0;
- }
- .navbar-form .has-feedback .form-control-feedback {
- top: 0;
- }
-}
-@media (max-width: 767px) {
- .navbar-form .form-group {
- margin-bottom: 5px;
- }
- .navbar-form .form-group:last-child {
- margin-bottom: 0;
- }
-}
-@media (min-width: 768px) {
- .navbar-form {
- width: auto;
- border: 0;
- margin-left: 0;
- margin-right: 0;
- padding-top: 0;
- padding-bottom: 0;
- -webkit-box-shadow: none;
- box-shadow: none;
- }
-}
-.navbar-nav > li > .dropdown-menu {
- margin-top: 0;
- border-top-right-radius: 0;
- border-top-left-radius: 0;
-}
-.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu {
- margin-bottom: 0;
- border-top-right-radius: 4px;
- border-top-left-radius: 4px;
- border-bottom-right-radius: 0;
- border-bottom-left-radius: 0;
-}
-.navbar-btn {
- margin-top: 7px;
- margin-bottom: 7px;
-}
-.navbar-btn.btn-sm {
- margin-top: 8.5px;
- margin-bottom: 8.5px;
-}
-.navbar-btn.btn-xs {
- margin-top: 14px;
- margin-bottom: 14px;
-}
-.navbar-text {
- margin-top: 14px;
- margin-bottom: 14px;
-}
-@media (min-width: 768px) {
- .navbar-text {
- float: left;
- margin-left: 15px;
- margin-right: 15px;
- }
-}
-@media (min-width: 768px) {
- .navbar-left {
- float: left !important;
- }
- .navbar-right {
- float: right !important;
- margin-right: -15px;
- }
- .navbar-right ~ .navbar-right {
- margin-right: 0;
- }
-}
-.navbar-default {
- background-color: #f8f8f8;
- border-color: #e7e7e7;
-}
-.navbar-default .navbar-brand {
- color: #777;
-}
-.navbar-default .navbar-brand:hover,
-.navbar-default .navbar-brand:focus {
- color: #5e5e5e;
- background-color: transparent;
-}
-.navbar-default .navbar-text {
- color: #777;
-}
-.navbar-default .navbar-nav > li > a {
- color: #777;
-}
-.navbar-default .navbar-nav > li > a:hover,
-.navbar-default .navbar-nav > li > a:focus {
- color: #333;
- background-color: transparent;
-}
-.navbar-default .navbar-nav > .active > a,
-.navbar-default .navbar-nav > .active > a:hover,
-.navbar-default .navbar-nav > .active > a:focus {
- color: #555;
- background-color: #e7e7e7;
-}
-.navbar-default .navbar-nav > .disabled > a,
-.navbar-default .navbar-nav > .disabled > a:hover,
-.navbar-default .navbar-nav > .disabled > a:focus {
- color: #ccc;
- background-color: transparent;
-}
-.navbar-default .navbar-toggle {
- border-color: #ddd;
-}
-.navbar-default .navbar-toggle:hover,
-.navbar-default .navbar-toggle:focus {
- background-color: #ddd;
-}
-.navbar-default .navbar-toggle .icon-bar {
- background-color: #888;
-}
-.navbar-default .navbar-collapse,
-.navbar-default .navbar-form {
- border-color: #e7e7e7;
-}
-.navbar-default .navbar-nav > .open > a,
-.navbar-default .navbar-nav > .open > a:hover,
-.navbar-default .navbar-nav > .open > a:focus {
- background-color: #e7e7e7;
- color: #555;
-}
-@media (max-width: 767px) {
- .navbar-default .navbar-nav .open .dropdown-menu > li > a {
- color: #777;
- }
- .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover,
- .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus {
- color: #333;
- background-color: transparent;
- }
- .navbar-default .navbar-nav .open .dropdown-menu > .active > a,
- .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover,
- .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus {
- color: #555;
- background-color: #e7e7e7;
- }
- .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a,
- .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover,
- .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:focus {
- color: #ccc;
- background-color: transparent;
- }
-}
-.navbar-default .navbar-link {
- color: #777;
-}
-.navbar-default .navbar-link:hover {
- color: #333;
-}
-.navbar-default .btn-link {
- color: #777;
-}
-.navbar-default .btn-link:hover,
-.navbar-default .btn-link:focus {
- color: #333;
-}
-.navbar-default .btn-link[disabled]:hover,
-fieldset[disabled] .navbar-default .btn-link:hover,
-.navbar-default .btn-link[disabled]:focus,
-fieldset[disabled] .navbar-default .btn-link:focus {
- color: #ccc;
-}
-.navbar-inverse {
- background-color: #222;
- border-color: #080808;
-}
-.navbar-inverse .navbar-brand {
- color: #ffffff;
-}
-.navbar-inverse .navbar-brand:hover,
-.navbar-inverse .navbar-brand:focus {
- color: #fff;
- background-color: transparent;
-}
-.navbar-inverse .navbar-text {
- color: #ffffff;
-}
-.navbar-inverse .navbar-nav > li > a {
- color: #ffffff;
-}
-.navbar-inverse .navbar-nav > li > a:hover,
-.navbar-inverse .navbar-nav > li > a:focus {
- color: #fff;
- background-color: transparent;
-}
-.navbar-inverse .navbar-nav > .active > a,
-.navbar-inverse .navbar-nav > .active > a:hover,
-.navbar-inverse .navbar-nav > .active > a:focus {
- color: #fff;
- background-color: #080808;
-}
-.navbar-inverse .navbar-nav > .disabled > a,
-.navbar-inverse .navbar-nav > .disabled > a:hover,
-.navbar-inverse .navbar-nav > .disabled > a:focus {
- color: #444;
- background-color: transparent;
-}
-.navbar-inverse .navbar-toggle {
- border-color: #333;
-}
-.navbar-inverse .navbar-toggle:hover,
-.navbar-inverse .navbar-toggle:focus {
- background-color: #333;
-}
-.navbar-inverse .navbar-toggle .icon-bar {
- background-color: #fff;
-}
-.navbar-inverse .navbar-collapse,
-.navbar-inverse .navbar-form {
- border-color: #101010;
-}
-.navbar-inverse .navbar-nav > .open > a,
-.navbar-inverse .navbar-nav > .open > a:hover,
-.navbar-inverse .navbar-nav > .open > a:focus {
- background-color: #080808;
- color: #fff;
-}
-@media (max-width: 767px) {
- .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header {
- border-color: #080808;
- }
- .navbar-inverse .navbar-nav .open .dropdown-menu .divider {
- background-color: #080808;
- }
- .navbar-inverse .navbar-nav .open .dropdown-menu > li > a {
- color: #ffffff;
- }
- .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover,
- .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus {
- color: #fff;
- background-color: transparent;
- }
- .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a,
- .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover,
- .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus {
- color: #fff;
- background-color: #080808;
- }
- .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a,
- .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:hover,
- .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:focus {
- color: #444;
- background-color: transparent;
- }
-}
-.navbar-inverse .navbar-link {
- color: #ffffff;
-}
-.navbar-inverse .navbar-link:hover {
- color: #fff;
-}
-.navbar-inverse .btn-link {
- color: #ffffff;
-}
-.navbar-inverse .btn-link:hover,
-.navbar-inverse .btn-link:focus {
- color: #fff;
-}
-.navbar-inverse .btn-link[disabled]:hover,
-fieldset[disabled] .navbar-inverse .btn-link:hover,
-.navbar-inverse .btn-link[disabled]:focus,
-fieldset[disabled] .navbar-inverse .btn-link:focus {
- color: #444;
-}
-.breadcrumb {
- padding: 8px 15px;
- margin-bottom: 22px;
- list-style: none;
- background-color: #f5f5f5;
- border-radius: 4px;
-}
-.breadcrumb > li {
- display: inline-block;
-}
-.breadcrumb > li + li:before {
- content: "/\00a0";
- padding: 0 5px;
- color: #ccc;
-}
-.breadcrumb > .active {
- color: #dcddde;
-}
-.pagination {
- display: inline-block;
- padding-left: 0;
- margin: 22px 0;
- border-radius: 4px;
-}
-.pagination > li {
- display: inline;
-}
-.pagination > li > a,
-.pagination > li > span {
- position: relative;
- float: left;
- padding: 6px 12px;
- line-height: 1.42857143;
- text-decoration: none;
- color: #875A7B;
- background-color: #fff;
- border: 1px solid #ddd;
- margin-left: -1px;
-}
-.pagination > li:first-child > a,
-.pagination > li:first-child > span {
- margin-left: 0;
- border-bottom-left-radius: 4px;
- border-top-left-radius: 4px;
-}
-.pagination > li:last-child > a,
-.pagination > li:last-child > span {
- border-bottom-right-radius: 4px;
- border-top-right-radius: 4px;
-}
-.pagination > li > a:hover,
-.pagination > li > span:hover,
-.pagination > li > a:focus,
-.pagination > li > span:focus {
- z-index: 2;
- color: #926485;
- background-color: #F2F2F2;
- border-color: #ddd;
-}
-.pagination > .active > a,
-.pagination > .active > span,
-.pagination > .active > a:hover,
-.pagination > .active > span:hover,
-.pagination > .active > a:focus,
-.pagination > .active > span:focus {
- z-index: 3;
- color: #fff;
- background-color: #21b799;
- border-color: #21b799;
- cursor: default;
-}
-.pagination > .disabled > span,
-.pagination > .disabled > span:hover,
-.pagination > .disabled > span:focus,
-.pagination > .disabled > a,
-.pagination > .disabled > a:hover,
-.pagination > .disabled > a:focus {
- color: #dcddde;
- background-color: #fff;
- border-color: #ddd;
- cursor: not-allowed;
-}
-.pagination-lg > li > a,
-.pagination-lg > li > span {
- padding: 10px 16px;
- font-size: 20px;
- line-height: 1.3333333;
-}
-.pagination-lg > li:first-child > a,
-.pagination-lg > li:first-child > span {
- border-bottom-left-radius: 6px;
- border-top-left-radius: 6px;
-}
-.pagination-lg > li:last-child > a,
-.pagination-lg > li:last-child > span {
- border-bottom-right-radius: 6px;
- border-top-right-radius: 6px;
-}
-.pagination-sm > li > a,
-.pagination-sm > li > span {
- padding: 5px 10px;
- font-size: 14px;
- line-height: 1.5;
-}
-.pagination-sm > li:first-child > a,
-.pagination-sm > li:first-child > span {
- border-bottom-left-radius: 3px;
- border-top-left-radius: 3px;
-}
-.pagination-sm > li:last-child > a,
-.pagination-sm > li:last-child > span {
- border-bottom-right-radius: 3px;
- border-top-right-radius: 3px;
-}
-.pager {
- padding-left: 0;
- margin: 22px 0;
- list-style: none;
- text-align: center;
-}
-.pager li {
- display: inline;
-}
-.pager li > a,
-.pager li > span {
- display: inline-block;
- padding: 5px 14px;
- background-color: #fff;
- border: 1px solid #ddd;
- border-radius: 15px;
-}
-.pager li > a:hover,
-.pager li > a:focus {
- text-decoration: none;
- background-color: #F2F2F2;
-}
-.pager .next > a,
-.pager .next > span {
- float: right;
-}
-.pager .previous > a,
-.pager .previous > span {
- float: left;
-}
-.pager .disabled > a,
-.pager .disabled > a:hover,
-.pager .disabled > a:focus,
-.pager .disabled > span {
- color: #dcddde;
- background-color: #fff;
- cursor: not-allowed;
-}
-.label {
- display: inline;
- padding: 0.2em 0.6em 0.3em;
- font-size: 75%;
- font-weight: bold;
- line-height: 1;
- color: #fff;
- text-align: center;
- white-space: nowrap;
- vertical-align: baseline;
- border-radius: 0.25em;
-}
-a.label:hover,
-a.label:focus {
- color: #fff;
- text-decoration: none;
- cursor: pointer;
-}
-.label:empty {
- display: none;
-}
-.btn .label {
- position: relative;
- top: -1px;
-}
-.label-default {
- background-color: #dcddde;
-}
-.label-default[href]:hover,
-.label-default[href]:focus {
- background-color: #c2c4c5;
-}
-.label-primary {
- background-color: #21b799;
-}
-.label-primary[href]:hover,
-.label-primary[href]:focus {
- background-color: #198c75;
-}
-.label-success {
- background-color: #50AF51;
-}
-.label-success[href]:hover,
-.label-success[href]:focus {
- background-color: #408c41;
-}
-.label-info {
- background-color: #4B9EB6;
-}
-.label-info[href]:hover,
-.label-info[href]:focus {
- background-color: #3b7f93;
-}
-.label-warning {
- background-color: #F0AD4E;
-}
-.label-warning[href]:hover,
-.label-warning[href]:focus {
- background-color: #ec971f;
-}
-.label-danger {
- background-color: #D9534F;
-}
-.label-danger[href]:hover,
-.label-danger[href]:focus {
- background-color: #c9302c;
-}
-.badge {
- display: inline-block;
- min-width: 10px;
- padding: 3px 7px;
- font-size: 14px;
- font-weight: bold;
- color: #fff;
- line-height: 1;
- vertical-align: middle;
- white-space: nowrap;
- text-align: center;
- background-color: #dcddde;
- border-radius: 10px;
-}
-.badge:empty {
- display: none;
-}
-.btn .badge {
- position: relative;
- top: -1px;
-}
-.btn-xs .badge,
-.btn-group-xs > .btn .badge {
- top: 0;
- padding: 1px 5px;
-}
-a.badge:hover,
-a.badge:focus {
- color: #fff;
- text-decoration: none;
- cursor: pointer;
-}
-.list-group-item.active > .badge,
-.nav-pills > .active > a > .badge {
- color: #875A7B;
- background-color: #fff;
-}
-.list-group-item > .badge {
- float: right;
-}
-.list-group-item > .badge + .badge {
- margin-right: 5px;
-}
-.nav-pills > li > a > .badge {
- margin-left: 3px;
-}
-.jumbotron {
- padding-top: 30px;
- padding-bottom: 30px;
- margin-bottom: 30px;
- color: inherit;
- background-color: #F2F2F2;
-}
-.jumbotron h1,
-.jumbotron .h1 {
- color: inherit;
-}
-.jumbotron p {
- margin-bottom: 15px;
- font-size: 24px;
- font-weight: 200;
-}
-.jumbotron > hr {
- border-top-color: #d9d9d9;
-}
-.container .jumbotron,
-.container-fluid .jumbotron {
- border-radius: 6px;
- padding-left: 15px;
- padding-right: 15px;
-}
-.jumbotron .container {
- max-width: 100%;
-}
-@media screen and (min-width: 768px) {
- .jumbotron {
- padding-top: 48px;
- padding-bottom: 48px;
- }
- .container .jumbotron,
- .container-fluid .jumbotron {
- padding-left: 60px;
- padding-right: 60px;
- }
- .jumbotron h1,
- .jumbotron .h1 {
- font-size: 72px;
- }
-}
-.thumbnail {
- display: block;
- padding: 4px;
- margin-bottom: 22px;
- line-height: 1.42857143;
- background-color: #F9F9F9;
- border: 1px solid #ddd;
- border-radius: 4px;
- -webkit-transition: border 0.2s ease-in-out;
- -o-transition: border 0.2s ease-in-out;
- transition: border 0.2s ease-in-out;
-}
-.thumbnail > img,
-.thumbnail a > img {
- margin-left: auto;
- margin-right: auto;
-}
-a.thumbnail:hover,
-a.thumbnail:focus,
-a.thumbnail.active {
- border-color: #875A7B;
-}
-.thumbnail .caption {
- padding: 9px;
- color: #373e42;
-}
-.alert {
- padding: 15px;
- margin-bottom: 22px;
- border: 1px solid transparent;
- border-radius: 4px;
-}
-.alert h4 {
- margin-top: 0;
- color: inherit;
-}
-.alert .alert-link {
- font-weight: bold;
-}
-.alert > p,
-.alert > ul {
- margin-bottom: 0;
-}
-.alert > p + p {
- margin-top: 5px;
-}
-.alert-dismissable,
-.alert-dismissible {
- padding-right: 35px;
-}
-.alert-dismissable .close,
-.alert-dismissible .close {
- position: relative;
- top: -2px;
- right: -21px;
- color: inherit;
-}
-.alert-success {
- background-color: #dff0d8;
- border-color: #d6e9c6;
- color: #3c763d;
-}
-.alert-success hr {
- border-top-color: #c9e2b3;
-}
-.alert-success .alert-link {
- color: #2b542c;
-}
-.alert-info {
- background-color: #d9edf7;
- border-color: #bce8f1;
- color: #31708f;
-}
-.alert-info hr {
- border-top-color: #a6e1ec;
-}
-.alert-info .alert-link {
- color: #245269;
-}
-.alert-warning {
- background-color: #fcf8e3;
- border-color: #faebcc;
- color: #8a6d3b;
-}
-.alert-warning hr {
- border-top-color: #f7e1b5;
-}
-.alert-warning .alert-link {
- color: #66512c;
-}
-.alert-danger {
- background-color: #f2dede;
- border-color: #ebccd1;
- color: #a94442;
-}
-.alert-danger hr {
- border-top-color: #e4b9c0;
-}
-.alert-danger .alert-link {
- color: #843534;
-}
-@-webkit-keyframes progress-bar-stripes {
- from {
- background-position: 40px 0;
- }
- to {
- background-position: 0 0;
- }
-}
-@keyframes progress-bar-stripes {
- from {
- background-position: 40px 0;
- }
- to {
- background-position: 0 0;
- }
-}
-.progress {
- overflow: hidden;
- height: 22px;
- margin-bottom: 22px;
- background-color: #f5f5f5;
- border-radius: 4px;
- -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
- box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
-}
-.progress-bar {
- float: left;
- width: 0%;
- height: 100%;
- font-size: 14px;
- line-height: 22px;
- color: #fff;
- text-align: center;
- background-color: #21b799;
- -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);
- box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);
- -webkit-transition: width 0.6s ease;
- -o-transition: width 0.6s ease;
- transition: width 0.6s ease;
-}
-.progress-striped .progress-bar,
-.progress-bar-striped {
- background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
- background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
- background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
- background-size: 40px 40px;
-}
-.progress.active .progress-bar,
-.progress-bar.active {
- -webkit-animation: progress-bar-stripes 2s linear infinite;
- -o-animation: progress-bar-stripes 2s linear infinite;
- animation: progress-bar-stripes 2s linear infinite;
-}
-.progress-bar-success {
- background-color: #50AF51;
-}
-.progress-striped .progress-bar-success {
- background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
- background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
- background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
-}
-.progress-bar-info {
- background-color: #4B9EB6;
-}
-.progress-striped .progress-bar-info {
- background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
- background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
- background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
-}
-.progress-bar-warning {
- background-color: #F0AD4E;
-}
-.progress-striped .progress-bar-warning {
- background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
- background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
- background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
-}
-.progress-bar-danger {
- background-color: #D9534F;
-}
-.progress-striped .progress-bar-danger {
- background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
- background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
- background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
-}
-.media {
- margin-top: 15px;
-}
-.media:first-child {
- margin-top: 0;
-}
-.media,
-.media-body {
- zoom: 1;
- overflow: hidden;
-}
-.media-body {
- width: 10000px;
-}
-.media-object {
- display: block;
-}
-.media-object.img-thumbnail {
- max-width: none;
-}
-.media-right,
-.media > .pull-right {
- padding-left: 10px;
-}
-.media-left,
-.media > .pull-left {
- padding-right: 10px;
-}
-.media-left,
-.media-right,
-.media-body {
- display: table-cell;
- vertical-align: top;
-}
-.media-middle {
- vertical-align: middle;
-}
-.media-bottom {
- vertical-align: bottom;
-}
-.media-heading {
- margin-top: 0;
- margin-bottom: 5px;
-}
-.media-list {
- padding-left: 0;
- list-style: none;
-}
-.list-group {
- margin-bottom: 20px;
- padding-left: 0;
-}
-.list-group-item {
- position: relative;
- display: block;
- padding: 10px 15px;
- margin-bottom: -1px;
- background-color: #fff;
- border: 1px solid #ddd;
-}
-.list-group-item:first-child {
- border-top-right-radius: 4px;
- border-top-left-radius: 4px;
-}
-.list-group-item:last-child {
- margin-bottom: 0;
- border-bottom-right-radius: 4px;
- border-bottom-left-radius: 4px;
-}
-a.list-group-item,
-button.list-group-item {
- color: #555;
-}
-a.list-group-item .list-group-item-heading,
-button.list-group-item .list-group-item-heading {
- color: #333;
-}
-a.list-group-item:hover,
-button.list-group-item:hover,
-a.list-group-item:focus,
-button.list-group-item:focus {
- text-decoration: none;
- color: #555;
- background-color: #f5f5f5;
-}
-button.list-group-item {
- width: 100%;
- text-align: left;
-}
-.list-group-item.disabled,
-.list-group-item.disabled:hover,
-.list-group-item.disabled:focus {
- background-color: #F2F2F2;
- color: #dcddde;
- cursor: not-allowed;
-}
-.list-group-item.disabled .list-group-item-heading,
-.list-group-item.disabled:hover .list-group-item-heading,
-.list-group-item.disabled:focus .list-group-item-heading {
- color: inherit;
-}
-.list-group-item.disabled .list-group-item-text,
-.list-group-item.disabled:hover .list-group-item-text,
-.list-group-item.disabled:focus .list-group-item-text {
- color: #dcddde;
-}
-.list-group-item.active,
-.list-group-item.active:hover,
-.list-group-item.active:focus {
- z-index: 2;
- color: #fff;
- background-color: #21b799;
- border-color: #21b799;
-}
-.list-group-item.active .list-group-item-heading,
-.list-group-item.active:hover .list-group-item-heading,
-.list-group-item.active:focus .list-group-item-heading,
-.list-group-item.active .list-group-item-heading > small,
-.list-group-item.active:hover .list-group-item-heading > small,
-.list-group-item.active:focus .list-group-item-heading > small,
-.list-group-item.active .list-group-item-heading > .small,
-.list-group-item.active:hover .list-group-item-heading > .small,
-.list-group-item.active:focus .list-group-item-heading > .small {
- color: inherit;
-}
-.list-group-item.active .list-group-item-text,
-.list-group-item.active:hover .list-group-item-text,
-.list-group-item.active:focus .list-group-item-text {
- color: #b3f1e5;
-}
-.list-group-item-success {
- color: #3c763d;
- background-color: #dff0d8;
-}
-a.list-group-item-success,
-button.list-group-item-success {
- color: #3c763d;
-}
-a.list-group-item-success .list-group-item-heading,
-button.list-group-item-success .list-group-item-heading {
- color: inherit;
-}
-a.list-group-item-success:hover,
-button.list-group-item-success:hover,
-a.list-group-item-success:focus,
-button.list-group-item-success:focus {
- color: #3c763d;
- background-color: #d0e9c6;
-}
-a.list-group-item-success.active,
-button.list-group-item-success.active,
-a.list-group-item-success.active:hover,
-button.list-group-item-success.active:hover,
-a.list-group-item-success.active:focus,
-button.list-group-item-success.active:focus {
- color: #fff;
- background-color: #3c763d;
- border-color: #3c763d;
-}
-.list-group-item-info {
- color: #31708f;
- background-color: #d9edf7;
-}
-a.list-group-item-info,
-button.list-group-item-info {
- color: #31708f;
-}
-a.list-group-item-info .list-group-item-heading,
-button.list-group-item-info .list-group-item-heading {
- color: inherit;
-}
-a.list-group-item-info:hover,
-button.list-group-item-info:hover,
-a.list-group-item-info:focus,
-button.list-group-item-info:focus {
- color: #31708f;
- background-color: #c4e3f3;
-}
-a.list-group-item-info.active,
-button.list-group-item-info.active,
-a.list-group-item-info.active:hover,
-button.list-group-item-info.active:hover,
-a.list-group-item-info.active:focus,
-button.list-group-item-info.active:focus {
- color: #fff;
- background-color: #31708f;
- border-color: #31708f;
-}
-.list-group-item-warning {
- color: #8a6d3b;
- background-color: #fcf8e3;
-}
-a.list-group-item-warning,
-button.list-group-item-warning {
- color: #8a6d3b;
-}
-a.list-group-item-warning .list-group-item-heading,
-button.list-group-item-warning .list-group-item-heading {
- color: inherit;
-}
-a.list-group-item-warning:hover,
-button.list-group-item-warning:hover,
-a.list-group-item-warning:focus,
-button.list-group-item-warning:focus {
- color: #8a6d3b;
- background-color: #faf2cc;
-}
-a.list-group-item-warning.active,
-button.list-group-item-warning.active,
-a.list-group-item-warning.active:hover,
-button.list-group-item-warning.active:hover,
-a.list-group-item-warning.active:focus,
-button.list-group-item-warning.active:focus {
- color: #fff;
- background-color: #8a6d3b;
- border-color: #8a6d3b;
-}
-.list-group-item-danger {
- color: #a94442;
- background-color: #f2dede;
-}
-a.list-group-item-danger,
-button.list-group-item-danger {
- color: #a94442;
-}
-a.list-group-item-danger .list-group-item-heading,
-button.list-group-item-danger .list-group-item-heading {
- color: inherit;
-}
-a.list-group-item-danger:hover,
-button.list-group-item-danger:hover,
-a.list-group-item-danger:focus,
-button.list-group-item-danger:focus {
- color: #a94442;
- background-color: #ebcccc;
-}
-a.list-group-item-danger.active,
-button.list-group-item-danger.active,
-a.list-group-item-danger.active:hover,
-button.list-group-item-danger.active:hover,
-a.list-group-item-danger.active:focus,
-button.list-group-item-danger.active:focus {
- color: #fff;
- background-color: #a94442;
- border-color: #a94442;
-}
-.list-group-item-heading {
- margin-top: 0;
- margin-bottom: 5px;
-}
-.list-group-item-text {
- margin-bottom: 0;
- line-height: 1.3;
-}
-.panel {
- margin-bottom: 22px;
- background-color: #fff;
- border: 1px solid transparent;
- border-radius: 4px;
- -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);
- box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);
-}
-.panel-body {
- padding: 15px;
-}
-.panel-heading {
- padding: 10px 15px;
- border-bottom: 1px solid transparent;
- border-top-right-radius: 3px;
- border-top-left-radius: 3px;
-}
-.panel-heading > .dropdown .dropdown-toggle {
- color: inherit;
-}
-.panel-title {
- margin-top: 0;
- margin-bottom: 0;
- font-size: 18px;
- color: inherit;
-}
-.panel-title > a,
-.panel-title > small,
-.panel-title > .small,
-.panel-title > small > a,
-.panel-title > .small > a {
- color: inherit;
-}
-.panel-footer {
- padding: 10px 15px;
- background-color: #f5f5f5;
- border-top: 1px solid #ddd;
- border-bottom-right-radius: 3px;
- border-bottom-left-radius: 3px;
-}
-.panel > .list-group,
-.panel > .panel-collapse > .list-group {
- margin-bottom: 0;
-}
-.panel > .list-group .list-group-item,
-.panel > .panel-collapse > .list-group .list-group-item {
- border-width: 1px 0;
- border-radius: 0;
-}
-.panel > .list-group:first-child .list-group-item:first-child,
-.panel > .panel-collapse > .list-group:first-child .list-group-item:first-child {
- border-top: 0;
- border-top-right-radius: 3px;
- border-top-left-radius: 3px;
-}
-.panel > .list-group:last-child .list-group-item:last-child,
-.panel > .panel-collapse > .list-group:last-child .list-group-item:last-child {
- border-bottom: 0;
- border-bottom-right-radius: 3px;
- border-bottom-left-radius: 3px;
-}
-.panel > .panel-heading + .panel-collapse > .list-group .list-group-item:first-child {
- border-top-right-radius: 0;
- border-top-left-radius: 0;
-}
-.panel-heading + .list-group .list-group-item:first-child {
- border-top-width: 0;
-}
-.list-group + .panel-footer {
- border-top-width: 0;
-}
-.panel > .table,
-.panel > .table-responsive > .table,
-.panel > .panel-collapse > .table {
- margin-bottom: 0;
-}
-.panel > .table caption,
-.panel > .table-responsive > .table caption,
-.panel > .panel-collapse > .table caption {
- padding-left: 15px;
- padding-right: 15px;
-}
-.panel > .table:first-child,
-.panel > .table-responsive:first-child > .table:first-child {
- border-top-right-radius: 3px;
- border-top-left-radius: 3px;
-}
-.panel > .table:first-child > thead:first-child > tr:first-child,
-.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child,
-.panel > .table:first-child > tbody:first-child > tr:first-child,
-.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child {
- border-top-left-radius: 3px;
- border-top-right-radius: 3px;
-}
-.panel > .table:first-child > thead:first-child > tr:first-child td:first-child,
-.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:first-child,
-.panel > .table:first-child > tbody:first-child > tr:first-child td:first-child,
-.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:first-child,
-.panel > .table:first-child > thead:first-child > tr:first-child th:first-child,
-.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:first-child,
-.panel > .table:first-child > tbody:first-child > tr:first-child th:first-child,
-.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:first-child {
- border-top-left-radius: 3px;
-}
-.panel > .table:first-child > thead:first-child > tr:first-child td:last-child,
-.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:last-child,
-.panel > .table:first-child > tbody:first-child > tr:first-child td:last-child,
-.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:last-child,
-.panel > .table:first-child > thead:first-child > tr:first-child th:last-child,
-.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:last-child,
-.panel > .table:first-child > tbody:first-child > tr:first-child th:last-child,
-.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:last-child {
- border-top-right-radius: 3px;
-}
-.panel > .table:last-child,
-.panel > .table-responsive:last-child > .table:last-child {
- border-bottom-right-radius: 3px;
- border-bottom-left-radius: 3px;
-}
-.panel > .table:last-child > tbody:last-child > tr:last-child,
-.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child,
-.panel > .table:last-child > tfoot:last-child > tr:last-child,
-.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child {
- border-bottom-left-radius: 3px;
- border-bottom-right-radius: 3px;
-}
-.panel > .table:last-child > tbody:last-child > tr:last-child td:first-child,
-.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:first-child,
-.panel > .table:last-child > tfoot:last-child > tr:last-child td:first-child,
-.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:first-child,
-.panel > .table:last-child > tbody:last-child > tr:last-child th:first-child,
-.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:first-child,
-.panel > .table:last-child > tfoot:last-child > tr:last-child th:first-child,
-.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:first-child {
- border-bottom-left-radius: 3px;
-}
-.panel > .table:last-child > tbody:last-child > tr:last-child td:last-child,
-.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:last-child,
-.panel > .table:last-child > tfoot:last-child > tr:last-child td:last-child,
-.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:last-child,
-.panel > .table:last-child > tbody:last-child > tr:last-child th:last-child,
-.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:last-child,
-.panel > .table:last-child > tfoot:last-child > tr:last-child th:last-child,
-.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:last-child {
- border-bottom-right-radius: 3px;
-}
-.panel > .panel-body + .table,
-.panel > .panel-body + .table-responsive,
-.panel > .table + .panel-body,
-.panel > .table-responsive + .panel-body {
- border-top: 1px solid #ddd;
-}
-.panel > .table > tbody:first-child > tr:first-child th,
-.panel > .table > tbody:first-child > tr:first-child td {
- border-top: 0;
-}
-.panel > .table-bordered,
-.panel > .table-responsive > .table-bordered {
- border: 0;
-}
-.panel > .table-bordered > thead > tr > th:first-child,
-.panel > .table-responsive > .table-bordered > thead > tr > th:first-child,
-.panel > .table-bordered > tbody > tr > th:first-child,
-.panel > .table-responsive > .table-bordered > tbody > tr > th:first-child,
-.panel > .table-bordered > tfoot > tr > th:first-child,
-.panel > .table-responsive > .table-bordered > tfoot > tr > th:first-child,
-.panel > .table-bordered > thead > tr > td:first-child,
-.panel > .table-responsive > .table-bordered > thead > tr > td:first-child,
-.panel > .table-bordered > tbody > tr > td:first-child,
-.panel > .table-responsive > .table-bordered > tbody > tr > td:first-child,
-.panel > .table-bordered > tfoot > tr > td:first-child,
-.panel > .table-responsive > .table-bordered > tfoot > tr > td:first-child {
- border-left: 0;
-}
-.panel > .table-bordered > thead > tr > th:last-child,
-.panel > .table-responsive > .table-bordered > thead > tr > th:last-child,
-.panel > .table-bordered > tbody > tr > th:last-child,
-.panel > .table-responsive > .table-bordered > tbody > tr > th:last-child,
-.panel > .table-bordered > tfoot > tr > th:last-child,
-.panel > .table-responsive > .table-bordered > tfoot > tr > th:last-child,
-.panel > .table-bordered > thead > tr > td:last-child,
-.panel > .table-responsive > .table-bordered > thead > tr > td:last-child,
-.panel > .table-bordered > tbody > tr > td:last-child,
-.panel > .table-responsive > .table-bordered > tbody > tr > td:last-child,
-.panel > .table-bordered > tfoot > tr > td:last-child,
-.panel > .table-responsive > .table-bordered > tfoot > tr > td:last-child {
- border-right: 0;
-}
-.panel > .table-bordered > thead > tr:first-child > td,
-.panel > .table-responsive > .table-bordered > thead > tr:first-child > td,
-.panel > .table-bordered > tbody > tr:first-child > td,
-.panel > .table-responsive > .table-bordered > tbody > tr:first-child > td,
-.panel > .table-bordered > thead > tr:first-child > th,
-.panel > .table-responsive > .table-bordered > thead > tr:first-child > th,
-.panel > .table-bordered > tbody > tr:first-child > th,
-.panel > .table-responsive > .table-bordered > tbody > tr:first-child > th {
- border-bottom: 0;
-}
-.panel > .table-bordered > tbody > tr:last-child > td,
-.panel > .table-responsive > .table-bordered > tbody > tr:last-child > td,
-.panel > .table-bordered > tfoot > tr:last-child > td,
-.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > td,
-.panel > .table-bordered > tbody > tr:last-child > th,
-.panel > .table-responsive > .table-bordered > tbody > tr:last-child > th,
-.panel > .table-bordered > tfoot > tr:last-child > th,
-.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > th {
- border-bottom: 0;
-}
-.panel > .table-responsive {
- border: 0;
- margin-bottom: 0;
-}
-.panel-group {
- margin-bottom: 22px;
-}
-.panel-group .panel {
- margin-bottom: 0;
- border-radius: 4px;
-}
-.panel-group .panel + .panel {
- margin-top: 5px;
-}
-.panel-group .panel-heading {
- border-bottom: 0;
-}
-.panel-group .panel-heading + .panel-collapse > .panel-body,
-.panel-group .panel-heading + .panel-collapse > .list-group {
- border-top: 1px solid #ddd;
-}
-.panel-group .panel-footer {
- border-top: 0;
-}
-.panel-group .panel-footer + .panel-collapse .panel-body {
- border-bottom: 1px solid #ddd;
-}
-.panel-default {
- border-color: #ddd;
-}
-.panel-default > .panel-heading {
- color: #6B6D70;
- background-color: #f5f5f5;
- border-color: #ddd;
-}
-.panel-default > .panel-heading + .panel-collapse > .panel-body {
- border-top-color: #ddd;
-}
-.panel-default > .panel-heading .badge {
- color: #f5f5f5;
- background-color: #6B6D70;
-}
-.panel-default > .panel-footer + .panel-collapse > .panel-body {
- border-bottom-color: #ddd;
-}
-.panel-primary {
- border-color: #21b799;
-}
-.panel-primary > .panel-heading {
- color: #fff;
- background-color: #21b799;
- border-color: #21b799;
-}
-.panel-primary > .panel-heading + .panel-collapse > .panel-body {
- border-top-color: #21b799;
-}
-.panel-primary > .panel-heading .badge {
- color: #21b799;
- background-color: #fff;
-}
-.panel-primary > .panel-footer + .panel-collapse > .panel-body {
- border-bottom-color: #21b799;
-}
-.panel-success {
- border-color: #d6e9c6;
-}
-.panel-success > .panel-heading {
- color: #3c763d;
- background-color: #dff0d8;
- border-color: #d6e9c6;
-}
-.panel-success > .panel-heading + .panel-collapse > .panel-body {
- border-top-color: #d6e9c6;
-}
-.panel-success > .panel-heading .badge {
- color: #dff0d8;
- background-color: #3c763d;
-}
-.panel-success > .panel-footer + .panel-collapse > .panel-body {
- border-bottom-color: #d6e9c6;
-}
-.panel-info {
- border-color: #bce8f1;
-}
-.panel-info > .panel-heading {
- color: #31708f;
- background-color: #d9edf7;
- border-color: #bce8f1;
-}
-.panel-info > .panel-heading + .panel-collapse > .panel-body {
- border-top-color: #bce8f1;
-}
-.panel-info > .panel-heading .badge {
- color: #d9edf7;
- background-color: #31708f;
-}
-.panel-info > .panel-footer + .panel-collapse > .panel-body {
- border-bottom-color: #bce8f1;
-}
-.panel-warning {
- border-color: #faebcc;
-}
-.panel-warning > .panel-heading {
- color: #8a6d3b;
- background-color: #fcf8e3;
- border-color: #faebcc;
-}
-.panel-warning > .panel-heading + .panel-collapse > .panel-body {
- border-top-color: #faebcc;
-}
-.panel-warning > .panel-heading .badge {
- color: #fcf8e3;
- background-color: #8a6d3b;
-}
-.panel-warning > .panel-footer + .panel-collapse > .panel-body {
- border-bottom-color: #faebcc;
-}
-.panel-danger {
- border-color: #ebccd1;
-}
-.panel-danger > .panel-heading {
- color: #a94442;
- background-color: #f2dede;
- border-color: #ebccd1;
-}
-.panel-danger > .panel-heading + .panel-collapse > .panel-body {
- border-top-color: #ebccd1;
-}
-.panel-danger > .panel-heading .badge {
- color: #f2dede;
- background-color: #a94442;
-}
-.panel-danger > .panel-footer + .panel-collapse > .panel-body {
- border-bottom-color: #ebccd1;
-}
-.embed-responsive {
- position: relative;
- display: block;
- height: 0;
- padding: 0;
- overflow: hidden;
-}
-.embed-responsive .embed-responsive-item,
-.embed-responsive iframe,
-.embed-responsive embed,
-.embed-responsive object,
-.embed-responsive video {
- position: absolute;
- top: 0;
- left: 0;
- bottom: 0;
- height: 100%;
- width: 100%;
- border: 0;
-}
-.embed-responsive-16by9 {
- padding-bottom: 56.25%;
-}
-.embed-responsive-4by3 {
- padding-bottom: 75%;
-}
-.well {
- min-height: 20px;
- padding: 19px;
- margin-bottom: 20px;
- background-color: #f5f5f5;
- border: 1px solid #e3e3e3;
- border-radius: 4px;
- -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);
- box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);
-}
-.well blockquote {
- border-color: #ddd;
- border-color: rgba(0, 0, 0, 0.15);
-}
-.well-lg {
- padding: 24px;
- border-radius: 6px;
-}
-.well-sm {
- padding: 9px;
- border-radius: 3px;
-}
-.close {
- float: right;
- font-size: 24px;
- font-weight: bold;
- line-height: 1;
- color: #000;
- text-shadow: 0 1px 0 #fff;
- opacity: 0.2;
- filter: alpha(opacity=20);
-}
-.close:hover,
-.close:focus {
- color: #000;
- text-decoration: none;
- cursor: pointer;
- opacity: 0.5;
- filter: alpha(opacity=50);
-}
-button.close {
- padding: 0;
- cursor: pointer;
- background: transparent;
- border: 0;
- -webkit-appearance: none;
-}
-.modal-open {
- overflow: hidden;
-}
-.modal {
- display: none;
- overflow: hidden;
- position: fixed;
- top: 0;
- right: 0;
- bottom: 0;
- left: 0;
- z-index: 1050;
- -webkit-overflow-scrolling: touch;
- outline: 0;
-}
-.modal.fade .modal-dialog {
- -webkit-transform: translate(0, -25%);
- -ms-transform: translate(0, -25%);
- -o-transform: translate(0, -25%);
- transform: translate(0, -25%);
- -webkit-transition: -webkit-transform 0.3s ease-out;
- -moz-transition: -moz-transform 0.3s ease-out;
- -o-transition: -o-transform 0.3s ease-out;
- transition: transform 0.3s ease-out;
-}
-.modal.in .modal-dialog {
- -webkit-transform: translate(0, 0);
- -ms-transform: translate(0, 0);
- -o-transform: translate(0, 0);
- transform: translate(0, 0);
-}
-.modal-open .modal {
- overflow-x: hidden;
- overflow-y: auto;
-}
-.modal-dialog {
- position: relative;
- width: auto;
- margin: 10px;
-}
-.modal-content {
- position: relative;
- background-color: #fff;
- border: 1px solid #999;
- border: 1px solid rgba(0, 0, 0, 0.2);
- border-radius: 6px;
- -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5);
- box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5);
- background-clip: padding-box;
- outline: 0;
-}
-.modal-backdrop {
- position: fixed;
- top: 0;
- right: 0;
- bottom: 0;
- left: 0;
- z-index: 1040;
- background-color: #000;
-}
-.modal-backdrop.fade {
- opacity: 0;
- filter: alpha(opacity=0);
-}
-.modal-backdrop.in {
- opacity: 0.5;
- filter: alpha(opacity=50);
-}
-.modal-header {
- padding: 15px;
- border-bottom: 1px solid #e5e5e5;
-}
-.modal-header .close {
- margin-top: -2px;
-}
-.modal-title {
- margin: 0;
- line-height: 1.42857143;
-}
-.modal-body {
- position: relative;
- padding: 15px;
-}
-.modal-footer {
- padding: 15px;
- text-align: right;
- border-top: 1px solid #e5e5e5;
-}
-.modal-footer .btn + .btn {
- margin-left: 5px;
- margin-bottom: 0;
-}
-.modal-footer .btn-group .btn + .btn {
- margin-left: -1px;
-}
-.modal-footer .btn-block + .btn-block {
- margin-left: 0;
-}
-.modal-scrollbar-measure {
- position: absolute;
- top: -9999px;
- width: 50px;
- height: 50px;
- overflow: scroll;
-}
-@media (min-width: 768px) {
- .modal-dialog {
- width: 600px;
- margin: 30px auto;
- }
- .modal-content {
- -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);
- box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);
- }
- .modal-sm {
- width: 300px;
- }
-}
-@media (min-width: 992px) {
- .modal-lg {
- width: 900px;
- }
-}
-.tooltip {
- position: absolute;
- z-index: 1070;
- display: block;
- font-family: -apple-system, system-ui, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
- font-style: normal;
- font-weight: normal;
- letter-spacing: normal;
- line-break: auto;
- line-height: 1.42857143;
- text-align: left;
- text-align: start;
- text-decoration: none;
- text-shadow: none;
- text-transform: none;
- white-space: normal;
- word-break: normal;
- word-spacing: normal;
- word-wrap: normal;
- font-size: 14px;
- opacity: 0;
- filter: alpha(opacity=0);
-}
-.tooltip.in {
- opacity: 0.9;
- filter: alpha(opacity=90);
-}
-.tooltip.top {
- margin-top: -3px;
- padding: 5px 0;
-}
-.tooltip.right {
- margin-left: 3px;
- padding: 0 5px;
-}
-.tooltip.bottom {
- margin-top: 3px;
- padding: 5px 0;
-}
-.tooltip.left {
- margin-left: -3px;
- padding: 0 5px;
-}
-.tooltip-inner {
- max-width: 200px;
- padding: 3px 8px;
- color: #fff;
- text-align: center;
- background-color: #000;
- border-radius: 4px;
-}
-.tooltip-arrow {
- position: absolute;
- width: 0;
- height: 0;
- border-color: transparent;
- border-style: solid;
-}
-.tooltip.top .tooltip-arrow {
- bottom: 0;
- left: 50%;
- margin-left: -5px;
- border-width: 5px 5px 0;
- border-top-color: #000;
-}
-.tooltip.top-left .tooltip-arrow {
- bottom: 0;
- right: 5px;
- margin-bottom: -5px;
- border-width: 5px 5px 0;
- border-top-color: #000;
-}
-.tooltip.top-right .tooltip-arrow {
- bottom: 0;
- left: 5px;
- margin-bottom: -5px;
- border-width: 5px 5px 0;
- border-top-color: #000;
-}
-.tooltip.right .tooltip-arrow {
- top: 50%;
- left: 0;
- margin-top: -5px;
- border-width: 5px 5px 5px 0;
- border-right-color: #000;
-}
-.tooltip.left .tooltip-arrow {
- top: 50%;
- right: 0;
- margin-top: -5px;
- border-width: 5px 0 5px 5px;
- border-left-color: #000;
-}
-.tooltip.bottom .tooltip-arrow {
- top: 0;
- left: 50%;
- margin-left: -5px;
- border-width: 0 5px 5px;
- border-bottom-color: #000;
-}
-.tooltip.bottom-left .tooltip-arrow {
- top: 0;
- right: 5px;
- margin-top: -5px;
- border-width: 0 5px 5px;
- border-bottom-color: #000;
-}
-.tooltip.bottom-right .tooltip-arrow {
- top: 0;
- left: 5px;
- margin-top: -5px;
- border-width: 0 5px 5px;
- border-bottom-color: #000;
-}
-.popover {
- position: absolute;
- top: 0;
- left: 0;
- z-index: 1060;
- display: none;
- max-width: 276px;
- padding: 1px;
- font-family: -apple-system, system-ui, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
- font-style: normal;
- font-weight: normal;
- letter-spacing: normal;
- line-break: auto;
- line-height: 1.42857143;
- text-align: left;
- text-align: start;
- text-decoration: none;
- text-shadow: none;
- text-transform: none;
- white-space: normal;
- word-break: normal;
- word-spacing: normal;
- word-wrap: normal;
- font-size: 16px;
- background-color: #fff;
- background-clip: padding-box;
- border: 1px solid #ccc;
- border: 1px solid rgba(0, 0, 0, 0.2);
- border-radius: 6px;
- -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
- box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
-}
-.popover.top {
- margin-top: -10px;
-}
-.popover.right {
- margin-left: 10px;
-}
-.popover.bottom {
- margin-top: 10px;
-}
-.popover.left {
- margin-left: -10px;
-}
-.popover-title {
- margin: 0;
- padding: 8px 14px;
- font-size: 16px;
- background-color: #f7f7f7;
- border-bottom: 1px solid #ebebeb;
- border-radius: 5px 5px 0 0;
-}
-.popover-content {
- padding: 9px 14px;
-}
-.popover > .arrow,
-.popover > .arrow:after {
- position: absolute;
- display: block;
- width: 0;
- height: 0;
- border-color: transparent;
- border-style: solid;
-}
-.popover > .arrow {
- border-width: 11px;
-}
-.popover > .arrow:after {
- border-width: 10px;
- content: "";
-}
-.popover.top > .arrow {
- left: 50%;
- margin-left: -11px;
- border-bottom-width: 0;
- border-top-color: #999999;
- border-top-color: rgba(0, 0, 0, 0.25);
- bottom: -11px;
-}
-.popover.top > .arrow:after {
- content: " ";
- bottom: 1px;
- margin-left: -10px;
- border-bottom-width: 0;
- border-top-color: #fff;
-}
-.popover.right > .arrow {
- top: 50%;
- left: -11px;
- margin-top: -11px;
- border-left-width: 0;
- border-right-color: #999999;
- border-right-color: rgba(0, 0, 0, 0.25);
-}
-.popover.right > .arrow:after {
- content: " ";
- left: 1px;
- bottom: -10px;
- border-left-width: 0;
- border-right-color: #fff;
-}
-.popover.bottom > .arrow {
- left: 50%;
- margin-left: -11px;
- border-top-width: 0;
- border-bottom-color: #999999;
- border-bottom-color: rgba(0, 0, 0, 0.25);
- top: -11px;
-}
-.popover.bottom > .arrow:after {
- content: " ";
- top: 1px;
- margin-left: -10px;
- border-top-width: 0;
- border-bottom-color: #fff;
-}
-.popover.left > .arrow {
- top: 50%;
- right: -11px;
- margin-top: -11px;
- border-right-width: 0;
- border-left-color: #999999;
- border-left-color: rgba(0, 0, 0, 0.25);
-}
-.popover.left > .arrow:after {
- content: " ";
- right: 1px;
- border-right-width: 0;
- border-left-color: #fff;
- bottom: -10px;
-}
-.carousel {
- position: relative;
-}
-.carousel-inner {
- position: relative;
- overflow: hidden;
- width: 100%;
-}
-.carousel-inner > .item {
- display: none;
- position: relative;
- -webkit-transition: 0.6s ease-in-out left;
- -o-transition: 0.6s ease-in-out left;
- transition: 0.6s ease-in-out left;
-}
-.carousel-inner > .item > img,
-.carousel-inner > .item > a > img {
- line-height: 1;
-}
-@media all and (transform-3d), (-webkit-transform-3d) {
- .carousel-inner > .item {
- -webkit-transition: -webkit-transform 0.6s ease-in-out;
- -moz-transition: -moz-transform 0.6s ease-in-out;
- -o-transition: -o-transform 0.6s ease-in-out;
- transition: transform 0.6s ease-in-out;
- -webkit-backface-visibility: hidden;
- -moz-backface-visibility: hidden;
- backface-visibility: hidden;
- -webkit-perspective: 1000px;
- -moz-perspective: 1000px;
- perspective: 1000px;
- }
- .carousel-inner > .item.next,
- .carousel-inner > .item.active.right {
- -webkit-transform: translate3d(100%, 0, 0);
- transform: translate3d(100%, 0, 0);
- left: 0;
- }
- .carousel-inner > .item.prev,
- .carousel-inner > .item.active.left {
- -webkit-transform: translate3d(-100%, 0, 0);
- transform: translate3d(-100%, 0, 0);
- left: 0;
- }
- .carousel-inner > .item.next.left,
- .carousel-inner > .item.prev.right,
- .carousel-inner > .item.active {
- -webkit-transform: translate3d(0, 0, 0);
- transform: translate3d(0, 0, 0);
- left: 0;
- }
-}
-.carousel-inner > .active,
-.carousel-inner > .next,
-.carousel-inner > .prev {
- display: block;
-}
-.carousel-inner > .active {
- left: 0;
-}
-.carousel-inner > .next,
-.carousel-inner > .prev {
- position: absolute;
- top: 0;
- width: 100%;
-}
-.carousel-inner > .next {
- left: 100%;
-}
-.carousel-inner > .prev {
- left: -100%;
-}
-.carousel-inner > .next.left,
-.carousel-inner > .prev.right {
- left: 0;
-}
-.carousel-inner > .active.left {
- left: -100%;
-}
-.carousel-inner > .active.right {
- left: 100%;
-}
-.carousel-control {
- position: absolute;
- top: 0;
- left: 0;
- bottom: 0;
- width: 15%;
- opacity: 0.5;
- filter: alpha(opacity=50);
- font-size: 20px;
- color: #fff;
- text-align: center;
- text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
- background-color: rgba(0, 0, 0, 0);
-}
-.carousel-control.left {
- background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);
- background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);
- background-image: linear-gradient(to right, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);
- background-repeat: repeat-x;
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);
-}
-.carousel-control.right {
- left: auto;
- right: 0;
- background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);
- background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);
- background-image: linear-gradient(to right, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);
- background-repeat: repeat-x;
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);
-}
-.carousel-control:hover,
-.carousel-control:focus {
- outline: 0;
- color: #fff;
- text-decoration: none;
- opacity: 0.9;
- filter: alpha(opacity=90);
-}
-.carousel-control .icon-prev,
-.carousel-control .icon-next,
-.carousel-control .glyphicon-chevron-left,
-.carousel-control .glyphicon-chevron-right {
- position: absolute;
- top: 50%;
- margin-top: -10px;
- z-index: 5;
- display: inline-block;
-}
-.carousel-control .icon-prev,
-.carousel-control .glyphicon-chevron-left {
- left: 50%;
- margin-left: -10px;
-}
-.carousel-control .icon-next,
-.carousel-control .glyphicon-chevron-right {
- right: 50%;
- margin-right: -10px;
-}
-.carousel-control .icon-prev,
-.carousel-control .icon-next {
- width: 20px;
- height: 20px;
- line-height: 1;
- font-family: serif;
-}
-.carousel-control .icon-prev:before {
- content: '\2039';
-}
-.carousel-control .icon-next:before {
- content: '\203a';
-}
-.carousel-indicators {
- position: absolute;
- bottom: 10px;
- left: 50%;
- z-index: 15;
- width: 60%;
- margin-left: -30%;
- padding-left: 0;
- list-style: none;
- text-align: center;
-}
-.carousel-indicators li {
- display: inline-block;
- width: 10px;
- height: 10px;
- margin: 1px;
- text-indent: -999px;
- border: 1px solid #fff;
- border-radius: 10px;
- cursor: pointer;
- background-color: #000 \9;
- background-color: rgba(0, 0, 0, 0);
-}
-.carousel-indicators .active {
- margin: 0;
- width: 12px;
- height: 12px;
- background-color: #fff;
-}
-.carousel-caption {
- position: absolute;
- left: 15%;
- right: 15%;
- bottom: 20px;
- z-index: 10;
- padding-top: 20px;
- padding-bottom: 20px;
- color: #fff;
- text-align: center;
- text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
-}
-.carousel-caption .btn {
- text-shadow: none;
-}
-@media screen and (min-width: 768px) {
- .carousel-control .glyphicon-chevron-left,
- .carousel-control .glyphicon-chevron-right,
- .carousel-control .icon-prev,
- .carousel-control .icon-next {
- width: 30px;
- height: 30px;
- margin-top: -10px;
- font-size: 30px;
- }
- .carousel-control .glyphicon-chevron-left,
- .carousel-control .icon-prev {
- margin-left: -10px;
- }
- .carousel-control .glyphicon-chevron-right,
- .carousel-control .icon-next {
- margin-right: -10px;
- }
- .carousel-caption {
- left: 20%;
- right: 20%;
- padding-bottom: 30px;
- }
- .carousel-indicators {
- bottom: 20px;
- }
-}
-.clearfix:before,
-.clearfix:after,
-.dl-horizontal dd:before,
-.dl-horizontal dd:after,
-.container:before,
-.container:after,
-.container-fluid:before,
-.container-fluid:after,
-.row:before,
-.row:after,
-.form-horizontal .form-group:before,
-.form-horizontal .form-group:after,
-.btn-toolbar:before,
-.btn-toolbar:after,
-.btn-group-vertical > .btn-group:before,
-.btn-group-vertical > .btn-group:after,
-.nav:before,
-.nav:after,
-.navbar:before,
-.navbar:after,
-.navbar-header:before,
-.navbar-header:after,
-.navbar-collapse:before,
-.navbar-collapse:after,
-.pager:before,
-.pager:after,
-.panel-body:before,
-.panel-body:after,
-.modal-header:before,
-.modal-header:after,
-.modal-footer:before,
-.modal-footer:after,
-.o_main_header > .o_main_header_main:before,
-.o_main_header > .o_main_header_main:after {
- content: " ";
- display: table;
-}
-.clearfix:after,
-.dl-horizontal dd:after,
-.container:after,
-.container-fluid:after,
-.row:after,
-.form-horizontal .form-group:after,
-.btn-toolbar:after,
-.btn-group-vertical > .btn-group:after,
-.nav:after,
-.navbar:after,
-.navbar-header:after,
-.navbar-collapse:after,
-.pager:after,
-.panel-body:after,
-.modal-header:after,
-.modal-footer:after,
-.o_main_header > .o_main_header_main:after {
- clear: both;
-}
-.center-block {
- display: block;
- margin-left: auto;
- margin-right: auto;
-}
-.pull-right {
- float: right !important;
-}
-.pull-left {
- float: left !important;
-}
-.hide {
- display: none !important;
-}
-.show {
- display: block !important;
-}
-.invisible {
- visibility: hidden;
-}
-.text-hide {
- font: 0/0 a;
- color: transparent;
- text-shadow: none;
- background-color: transparent;
- border: 0;
-}
-.hidden {
- display: none !important;
-}
-.affix {
- position: fixed;
-}
-@-ms-viewport {
- width: device-width;
-}
-.visible-xs,
-.visible-sm,
-.visible-md,
-.visible-lg {
- display: none !important;
-}
-.visible-xs-block,
-.visible-xs-inline,
-.visible-xs-inline-block,
-.visible-sm-block,
-.visible-sm-inline,
-.visible-sm-inline-block,
-.visible-md-block,
-.visible-md-inline,
-.visible-md-inline-block,
-.visible-lg-block,
-.visible-lg-inline,
-.visible-lg-inline-block {
- display: none !important;
-}
-@media (max-width: 767px) {
- .visible-xs {
- display: block !important;
- }
- table.visible-xs {
- display: table !important;
- }
- tr.visible-xs {
- display: table-row !important;
- }
- th.visible-xs,
- td.visible-xs {
- display: table-cell !important;
- }
-}
-@media (max-width: 767px) {
- .visible-xs-block {
- display: block !important;
- }
-}
-@media (max-width: 767px) {
- .visible-xs-inline {
- display: inline !important;
- }
-}
-@media (max-width: 767px) {
- .visible-xs-inline-block {
- display: inline-block !important;
- }
-}
-@media (min-width: 768px) and (max-width: 991px) {
- .visible-sm {
- display: block !important;
- }
- table.visible-sm {
- display: table !important;
- }
- tr.visible-sm {
- display: table-row !important;
- }
- th.visible-sm,
- td.visible-sm {
- display: table-cell !important;
- }
-}
-@media (min-width: 768px) and (max-width: 991px) {
- .visible-sm-block {
- display: block !important;
- }
-}
-@media (min-width: 768px) and (max-width: 991px) {
- .visible-sm-inline {
- display: inline !important;
- }
-}
-@media (min-width: 768px) and (max-width: 991px) {
- .visible-sm-inline-block {
- display: inline-block !important;
- }
-}
-@media (min-width: 992px) and (max-width: 1199px) {
- .visible-md {
- display: block !important;
- }
- table.visible-md {
- display: table !important;
- }
- tr.visible-md {
- display: table-row !important;
- }
- th.visible-md,
- td.visible-md {
- display: table-cell !important;
- }
-}
-@media (min-width: 992px) and (max-width: 1199px) {
- .visible-md-block {
- display: block !important;
- }
-}
-@media (min-width: 992px) and (max-width: 1199px) {
- .visible-md-inline {
- display: inline !important;
- }
-}
-@media (min-width: 992px) and (max-width: 1199px) {
- .visible-md-inline-block {
- display: inline-block !important;
- }
-}
-@media (min-width: 1200px) {
- .visible-lg {
- display: block !important;
- }
- table.visible-lg {
- display: table !important;
- }
- tr.visible-lg {
- display: table-row !important;
- }
- th.visible-lg,
- td.visible-lg {
- display: table-cell !important;
- }
-}
-@media (min-width: 1200px) {
- .visible-lg-block {
- display: block !important;
- }
-}
-@media (min-width: 1200px) {
- .visible-lg-inline {
- display: inline !important;
- }
-}
-@media (min-width: 1200px) {
- .visible-lg-inline-block {
- display: inline-block !important;
- }
-}
-@media (max-width: 767px) {
- .hidden-xs {
- display: none !important;
- }
-}
-@media (min-width: 768px) and (max-width: 991px) {
- .hidden-sm {
- display: none !important;
- }
-}
-@media (min-width: 992px) and (max-width: 1199px) {
- .hidden-md {
- display: none !important;
- }
-}
-@media (min-width: 1200px) {
- .hidden-lg {
- display: none !important;
- }
-}
-.visible-print {
- display: none !important;
-}
-@media print {
- .visible-print {
- display: block !important;
- }
- table.visible-print {
- display: table !important;
- }
- tr.visible-print {
- display: table-row !important;
- }
- th.visible-print,
- td.visible-print {
- display: table-cell !important;
- }
-}
-.visible-print-block {
- display: none !important;
-}
-@media print {
- .visible-print-block {
- display: block !important;
- }
-}
-.visible-print-inline {
- display: none !important;
-}
-@media print {
- .visible-print-inline {
- display: inline !important;
- }
-}
-.visible-print-inline-block {
- display: none !important;
-}
-@media print {
- .visible-print-inline-block {
- display: inline-block !important;
- }
-}
-@media print {
- .hidden-print {
- display: none !important;
- }
-}
-@font-face {
- font-family: 'Material-Design-Icons';
- src: url('fonts/Material-Design-Icons.eot?3ocs8m');
- src: url('fonts/Material-Design-Icons.eot?#iefix3ocs8m') format('embedded-opentype'), url('fonts/Material-Design-Icons.woff?3ocs8m') format('woff'), url('fonts/Material-Design-Icons.ttf?3ocs8m') format('truetype'), url('fonts/Material-Design-Icons.svg?3ocs8m#Material-Design-Icons') format('svg');
- font-weight: normal;
- font-style: normal;
-}
-[class^="mdi-"],
-[class*="mdi-"] {
- speak: none;
- display: inline-block;
- font: normal normal normal 24px/1 'Material-Design-Icons';
- text-rendering: geometricPrecision;
- /* Better Font Rendering =========== */
- -webkit-font-smoothing: antialiased;
- -moz-osx-font-smoothing: grayscale;
- -webkit-transform: translate(0, 0);
- -ms-transform: translate(0, 0);
- transform: translate(0, 0);
-}
-[class^="mdi-"]:before,
-[class*="mdi-"]:before {
- display: inline-block;
- speak: none;
- text-decoration: inherit;
-}
-[class^="mdi-"].pull-left,
-[class*="mdi-"].pull-left {
- margin-right: 0.3em;
-}
-[class^="mdi-"].pull-right,
-[class*="mdi-"].pull-right {
- margin-left: 0.3em;
-}
-[class^="mdi-"].mdi-lg:before,
-[class*="mdi-"].mdi-lg:before,
-[class^="mdi-"].mdi-lg:after,
-[class*="mdi-"].mdi-lg:after {
- font-size: 1.33333333em;
- line-height: 0.75em;
- vertical-align: -15%;
-}
-[class^="mdi-"].mdi-2x:before,
-[class*="mdi-"].mdi-2x:before,
-[class^="mdi-"].mdi-2x:after,
-[class*="mdi-"].mdi-2x:after {
- font-size: 2em;
-}
-[class^="mdi-"].mdi-3x:before,
-[class*="mdi-"].mdi-3x:before,
-[class^="mdi-"].mdi-3x:after,
-[class*="mdi-"].mdi-3x:after {
- font-size: 3em;
-}
-[class^="mdi-"].mdi-4x:before,
-[class*="mdi-"].mdi-4x:before,
-[class^="mdi-"].mdi-4x:after,
-[class*="mdi-"].mdi-4x:after {
- font-size: 4em;
-}
-[class^="mdi-"].mdi-5x:before,
-[class*="mdi-"].mdi-5x:before,
-[class^="mdi-"].mdi-5x:after,
-[class*="mdi-"].mdi-5x:after {
- font-size: 5em;
-}
-.mdi-stack {
- position: relative;
- display: inline-block;
- width: 2em;
- height: 2em;
- line-height: 2em;
- vertical-align: middle;
-}
-.mdi-stack-1x,
-.mdi-stack-2x {
- position: absolute;
- left: 0;
- width: 100%;
- text-align: center;
-}
-.mdi-stack-1x {
- line-height: inherit;
-}
-.mdi-stack-2x {
- font-size: 2em;
-}
-.mdi-inverse {
- color: #ffffff;
-}
-/* Start Icons */
-.mdi-action-3d-rotation:before {
- content: "\e600";
-}
-.mdi-action-accessibility:before {
- content: "\e601";
-}
-.mdi-action-account-balance-wallet:before {
- content: "\e602";
-}
-.mdi-action-account-balance:before {
- content: "\e603";
-}
-.mdi-action-account-box:before {
- content: "\e604";
-}
-.mdi-action-account-child:before {
- content: "\e605";
-}
-.mdi-action-account-circle:before {
- content: "\e606";
-}
-.mdi-action-add-shopping-cart:before {
- content: "\e607";
-}
-.mdi-action-alarm-add:before {
- content: "\e608";
-}
-.mdi-action-alarm-off:before {
- content: "\e609";
-}
-.mdi-action-alarm-on:before {
- content: "\e60a";
-}
-.mdi-action-alarm:before {
- content: "\e60b";
-}
-.mdi-action-android:before {
- content: "\e60c";
-}
-.mdi-action-announcement:before {
- content: "\e60d";
-}
-.mdi-action-aspect-ratio:before {
- content: "\e60e";
-}
-.mdi-action-assessment:before {
- content: "\e60f";
-}
-.mdi-action-assignment-ind:before {
- content: "\e610";
-}
-.mdi-action-assignment-late:before {
- content: "\e611";
-}
-.mdi-action-assignment-return:before {
- content: "\e612";
-}
-.mdi-action-assignment-returned:before {
- content: "\e613";
-}
-.mdi-action-assignment-turned-in:before {
- content: "\e614";
-}
-.mdi-action-assignment:before {
- content: "\e615";
-}
-.mdi-action-autorenew:before {
- content: "\e616";
-}
-.mdi-action-backup:before {
- content: "\e617";
-}
-.mdi-action-book:before {
- content: "\e618";
-}
-.mdi-action-bookmark-outline:before {
- content: "\e619";
-}
-.mdi-action-bookmark:before {
- content: "\e61a";
-}
-.mdi-action-bug-report:before {
- content: "\e61b";
-}
-.mdi-action-cached:before {
- content: "\e61c";
-}
-.mdi-action-check-circle:before {
- content: "\e61d";
-}
-.mdi-action-class:before {
- content: "\e61e";
-}
-.mdi-action-credit-card:before {
- content: "\e61f";
-}
-.mdi-action-dashboard:before {
- content: "\e620";
-}
-.mdi-action-delete:before {
- content: "\e621";
-}
-.mdi-action-description:before {
- content: "\e622";
-}
-.mdi-action-dns:before {
- content: "\e623";
-}
-.mdi-action-done-all:before {
- content: "\e624";
-}
-.mdi-action-done:before {
- content: "\e625";
-}
-.mdi-action-event:before {
- content: "\e626";
-}
-.mdi-action-exit-to-app:before {
- content: "\e627";
-}
-.mdi-action-explore:before {
- content: "\e628";
-}
-.mdi-action-extension:before {
- content: "\e629";
-}
-.mdi-action-face-unlock:before {
- content: "\e62a";
-}
-.mdi-action-favorite-outline:before {
- content: "\e62b";
-}
-.mdi-action-favorite:before {
- content: "\e62c";
-}
-.mdi-action-find-in-page:before {
- content: "\e62d";
-}
-.mdi-action-find-replace:before {
- content: "\e62e";
-}
-.mdi-action-flip-to-back:before {
- content: "\e62f";
-}
-.mdi-action-flip-to-front:before {
- content: "\e630";
-}
-.mdi-action-get-app:before {
- content: "\e631";
-}
-.mdi-action-grade:before {
- content: "\e632";
-}
-.mdi-action-group-work:before {
- content: "\e633";
-}
-.mdi-action-help:before {
- content: "\e634";
-}
-.mdi-action-highlight-remove:before {
- content: "\e635";
-}
-.mdi-action-history:before {
- content: "\e636";
-}
-.mdi-action-home:before {
- content: "\e637";
-}
-.mdi-action-https:before {
- content: "\e638";
-}
-.mdi-action-info-outline:before {
- content: "\e639";
-}
-.mdi-action-info:before {
- content: "\e63a";
-}
-.mdi-action-input:before {
- content: "\e63b";
-}
-.mdi-action-invert-colors:before {
- content: "\e63c";
-}
-.mdi-action-label-outline:before {
- content: "\e63d";
-}
-.mdi-action-label:before {
- content: "\e63e";
-}
-.mdi-action-language:before {
- content: "\e63f";
-}
-.mdi-action-launch:before {
- content: "\e640";
-}
-.mdi-action-list:before {
- content: "\e641";
-}
-.mdi-action-lock-open:before {
- content: "\e642";
-}
-.mdi-action-lock-outline:before {
- content: "\e643";
-}
-.mdi-action-lock:before {
- content: "\e644";
-}
-.mdi-action-loyalty:before {
- content: "\e645";
-}
-.mdi-action-markunread-mailbox:before {
- content: "\e646";
-}
-.mdi-action-note-add:before {
- content: "\e647";
-}
-.mdi-action-open-in-browser:before {
- content: "\e648";
-}
-.mdi-action-open-in-new:before {
- content: "\e649";
-}
-.mdi-action-open-with:before {
- content: "\e64a";
-}
-.mdi-action-pageview:before {
- content: "\e64b";
-}
-.mdi-action-payment:before {
- content: "\e64c";
-}
-.mdi-action-perm-camera-mic:before {
- content: "\e64d";
-}
-.mdi-action-perm-contact-cal:before {
- content: "\e64e";
-}
-.mdi-action-perm-data-setting:before {
- content: "\e64f";
-}
-.mdi-action-perm-device-info:before {
- content: "\e650";
-}
-.mdi-action-perm-identity:before {
- content: "\e651";
-}
-.mdi-action-perm-media:before {
- content: "\e652";
-}
-.mdi-action-perm-phone-msg:before {
- content: "\e653";
-}
-.mdi-action-perm-scan-wifi:before {
- content: "\e654";
-}
-.mdi-action-picture-in-picture:before {
- content: "\e655";
-}
-.mdi-action-polymer:before {
- content: "\e656";
-}
-.mdi-action-print:before {
- content: "\e657";
-}
-.mdi-action-query-builder:before {
- content: "\e658";
-}
-.mdi-action-question-answer:before {
- content: "\e659";
-}
-.mdi-action-receipt:before {
- content: "\e65a";
-}
-.mdi-action-redeem:before {
- content: "\e65b";
-}
-.mdi-action-reorder:before {
- content: "\e65c";
-}
-.mdi-action-report-problem:before {
- content: "\e65d";
-}
-.mdi-action-restore:before {
- content: "\e65e";
-}
-.mdi-action-room:before {
- content: "\e65f";
-}
-.mdi-action-schedule:before {
- content: "\e660";
-}
-.mdi-action-search:before {
- content: "\e661";
-}
-.mdi-action-settings-applications:before {
- content: "\e662";
-}
-.mdi-action-settings-backup-restore:before {
- content: "\e663";
-}
-.mdi-action-settings-bluetooth:before {
- content: "\e664";
-}
-.mdi-action-settings-cell:before {
- content: "\e665";
-}
-.mdi-action-settings-display:before {
- content: "\e666";
-}
-.mdi-action-settings-ethernet:before {
- content: "\e667";
-}
-.mdi-action-settings-input-antenna:before {
- content: "\e668";
-}
-.mdi-action-settings-input-component:before {
- content: "\e669";
-}
-.mdi-action-settings-input-composite:before {
- content: "\e66a";
-}
-.mdi-action-settings-input-hdmi:before {
- content: "\e66b";
-}
-.mdi-action-settings-input-svideo:before {
- content: "\e66c";
-}
-.mdi-action-settings-overscan:before {
- content: "\e66d";
-}
-.mdi-action-settings-phone:before {
- content: "\e66e";
-}
-.mdi-action-settings-power:before {
- content: "\e66f";
-}
-.mdi-action-settings-remote:before {
- content: "\e670";
-}
-.mdi-action-settings-voice:before {
- content: "\e671";
-}
-.mdi-action-settings:before {
- content: "\e672";
-}
-.mdi-action-shop-two:before {
- content: "\e673";
-}
-.mdi-action-shop:before {
- content: "\e674";
-}
-.mdi-action-shopping-basket:before {
- content: "\e675";
-}
-.mdi-action-shopping-cart:before {
- content: "\e676";
-}
-.mdi-action-speaker-notes:before {
- content: "\e677";
-}
-.mdi-action-spellcheck:before {
- content: "\e678";
-}
-.mdi-action-star-rate:before {
- content: "\e679";
-}
-.mdi-action-stars:before {
- content: "\e67a";
-}
-.mdi-action-store:before {
- content: "\e67b";
-}
-.mdi-action-subject:before {
- content: "\e67c";
-}
-.mdi-action-supervisor-account:before {
- content: "\e67d";
-}
-.mdi-action-swap-horiz:before {
- content: "\e67e";
-}
-.mdi-action-swap-vert-circle:before {
- content: "\e67f";
-}
-.mdi-action-swap-vert:before {
- content: "\e680";
-}
-.mdi-action-system-update-tv:before {
- content: "\e681";
-}
-.mdi-action-tab-unselected:before {
- content: "\e682";
-}
-.mdi-action-tab:before {
- content: "\e683";
-}
-.mdi-action-theaters:before {
- content: "\e684";
-}
-.mdi-action-thumb-down:before {
- content: "\e685";
-}
-.mdi-action-thumb-up:before {
- content: "\e686";
-}
-.mdi-action-thumbs-up-down:before {
- content: "\e687";
-}
-.mdi-action-toc:before {
- content: "\e688";
-}
-.mdi-action-today:before {
- content: "\e689";
-}
-.mdi-action-track-changes:before {
- content: "\e68a";
-}
-.mdi-action-translate:before {
- content: "\e68b";
-}
-.mdi-action-trending-down:before {
- content: "\e68c";
-}
-.mdi-action-trending-neutral:before {
- content: "\e68d";
-}
-.mdi-action-trending-up:before {
- content: "\e68e";
-}
-.mdi-action-turned-in-not:before {
- content: "\e68f";
-}
-.mdi-action-turned-in:before {
- content: "\e690";
-}
-.mdi-action-verified-user:before {
- content: "\e691";
-}
-.mdi-action-view-agenda:before {
- content: "\e692";
-}
-.mdi-action-view-array:before {
- content: "\e693";
-}
-.mdi-action-view-carousel:before {
- content: "\e694";
-}
-.mdi-action-view-column:before {
- content: "\e695";
-}
-.mdi-action-view-day:before {
- content: "\e696";
-}
-.mdi-action-view-headline:before {
- content: "\e697";
-}
-.mdi-action-view-list:before {
- content: "\e698";
-}
-.mdi-action-view-module:before {
- content: "\e699";
-}
-.mdi-action-view-quilt:before {
- content: "\e69a";
-}
-.mdi-action-view-stream:before {
- content: "\e69b";
-}
-.mdi-action-view-week:before {
- content: "\e69c";
-}
-.mdi-action-visibility-off:before {
- content: "\e69d";
-}
-.mdi-action-visibility:before {
- content: "\e69e";
-}
-.mdi-action-wallet-giftcard:before {
- content: "\e69f";
-}
-.mdi-action-wallet-membership:before {
- content: "\e6a0";
-}
-.mdi-action-wallet-travel:before {
- content: "\e6a1";
-}
-.mdi-action-work:before {
- content: "\e6a2";
-}
-.mdi-alert-error:before {
- content: "\e6a3";
-}
-.mdi-alert-warning:before {
- content: "\e6a4";
-}
-.mdi-av-album:before {
- content: "\e6a5";
-}
-.mdi-av-closed-caption:before {
- content: "\e6a6";
-}
-.mdi-av-equalizer:before {
- content: "\e6a7";
-}
-.mdi-av-explicit:before {
- content: "\e6a8";
-}
-.mdi-av-fast-forward:before {
- content: "\e6a9";
-}
-.mdi-av-fast-rewind:before {
- content: "\e6aa";
-}
-.mdi-av-games:before {
- content: "\e6ab";
-}
-.mdi-av-hearing:before {
- content: "\e6ac";
-}
-.mdi-av-high-quality:before {
- content: "\e6ad";
-}
-.mdi-av-loop:before {
- content: "\e6ae";
-}
-.mdi-av-mic-none:before {
- content: "\e6af";
-}
-.mdi-av-mic-off:before {
- content: "\e6b0";
-}
-.mdi-av-mic:before {
- content: "\e6b1";
-}
-.mdi-av-movie:before {
- content: "\e6b2";
-}
-.mdi-av-my-library-add:before {
- content: "\e6b3";
-}
-.mdi-av-my-library-books:before {
- content: "\e6b4";
-}
-.mdi-av-my-library-music:before {
- content: "\e6b5";
-}
-.mdi-av-new-releases:before {
- content: "\e6b6";
-}
-.mdi-av-not-interested:before {
- content: "\e6b7";
-}
-.mdi-av-pause-circle-fill:before {
- content: "\e6b8";
-}
-.mdi-av-pause-circle-outline:before {
- content: "\e6b9";
-}
-.mdi-av-pause:before {
- content: "\e6ba";
-}
-.mdi-av-play-arrow:before {
- content: "\e6bb";
-}
-.mdi-av-play-circle-fill:before {
- content: "\e6bc";
-}
-.mdi-av-play-circle-outline:before {
- content: "\e6bd";
-}
-.mdi-av-play-shopping-bag:before {
- content: "\e6be";
-}
-.mdi-av-playlist-add:before {
- content: "\e6bf";
-}
-.mdi-av-queue-mus:before {
- content: "\e6c0";
-}
-.mdi-av-queue:before {
- content: "\e6c1";
-}
-.mdi-av-radio:before {
- content: "\e6c2";
-}
-.mdi-av-recent-actors:before {
- content: "\e6c3";
-}
-.mdi-av-repeat-one:before {
- content: "\e6c4";
-}
-.mdi-av-repeat:before {
- content: "\e6c5";
-}
-.mdi-av-replay:before {
- content: "\e6c6";
-}
-.mdi-av-shuffle:before {
- content: "\e6c7";
-}
-.mdi-av-skip-next:before {
- content: "\e6c8";
-}
-.mdi-av-skip-previous:before {
- content: "\e6c9";
-}
-.mdi-av-snooze:before {
- content: "\e6ca";
-}
-.mdi-av-stop:before {
- content: "\e6cb";
-}
-.mdi-av-subtitles:before {
- content: "\e6cc";
-}
-.mdi-av-surround-sound:before {
- content: "\e6cd";
-}
-.mdi-av-timer:before {
- content: "\e6ce";
-}
-.mdi-av-video-collection:before {
- content: "\e6cf";
-}
-.mdi-av-videocam-off:before {
- content: "\e6d0";
-}
-.mdi-av-videocam:before {
- content: "\e6d1";
-}
-.mdi-av-volume-down:before {
- content: "\e6d2";
-}
-.mdi-av-volume-mute:before {
- content: "\e6d3";
-}
-.mdi-av-volume-off:before {
- content: "\e6d4";
-}
-.mdi-av-volume-up:before {
- content: "\e6d5";
-}
-.mdi-av-web:before {
- content: "\e6d6";
-}
-.mdi-communication-business:before {
- content: "\e6d7";
-}
-.mdi-communication-call-end:before {
- content: "\e6d8";
-}
-.mdi-communication-call-made:before {
- content: "\e6d9";
-}
-.mdi-communication-call-merge:before {
- content: "\e6da";
-}
-.mdi-communication-call-missed:before {
- content: "\e6db";
-}
-.mdi-communication-call-received:before {
- content: "\e6dc";
-}
-.mdi-communication-call-split:before {
- content: "\e6dd";
-}
-.mdi-communication-call:before {
- content: "\e6de";
-}
-.mdi-communication-chat:before {
- content: "\e6df";
-}
-.mdi-communication-clear-all:before {
- content: "\e6e0";
-}
-.mdi-communication-comment:before {
- content: "\e6e1";
-}
-.mdi-communication-contacts:before {
- content: "\e6e2";
-}
-.mdi-communication-dialer-sip:before {
- content: "\e6e3";
-}
-.mdi-communication-dialpad:before {
- content: "\e6e4";
-}
-.mdi-communication-dnd-on:before {
- content: "\e6e5";
-}
-.mdi-communication-email:before {
- content: "\e6e6";
-}
-.mdi-communication-forum:before {
- content: "\e6e7";
-}
-.mdi-communication-import-export:before {
- content: "\e6e8";
-}
-.mdi-communication-invert-colors-off:before {
- content: "\e6e9";
-}
-.mdi-communication-invert-colors-on:before {
- content: "\e6ea";
-}
-.mdi-communication-live-help:before {
- content: "\e6eb";
-}
-.mdi-communication-location-off:before {
- content: "\e6ec";
-}
-.mdi-communication-location-on:before {
- content: "\e6ed";
-}
-.mdi-communication-message:before {
- content: "\e6ee";
-}
-.mdi-communication-messenger:before {
- content: "\e6ef";
-}
-.mdi-communication-no-sim:before {
- content: "\e6f0";
-}
-.mdi-communication-phone:before {
- content: "\e6f1";
-}
-.mdi-communication-portable-wifi-off:before {
- content: "\e6f2";
-}
-.mdi-communication-quick-contacts-dialer:before {
- content: "\e6f3";
-}
-.mdi-communication-quick-contacts-mail:before {
- content: "\e6f4";
-}
-.mdi-communication-ring-volume:before {
- content: "\e6f5";
-}
-.mdi-communication-stay-current-landscape:before {
- content: "\e6f6";
-}
-.mdi-communication-stay-current-portrait:before {
- content: "\e6f7";
-}
-.mdi-communication-stay-primary-landscape:before {
- content: "\e6f8";
-}
-.mdi-communication-stay-primary-portrait:before {
- content: "\e6f9";
-}
-.mdi-communication-swap-calls:before {
- content: "\e6fa";
-}
-.mdi-communication-textsms:before {
- content: "\e6fb";
-}
-.mdi-communication-voicemail:before {
- content: "\e6fc";
-}
-.mdi-communication-vpn-key:before {
- content: "\e6fd";
-}
-.mdi-content-add-box:before {
- content: "\e6fe";
-}
-.mdi-content-add-circle-outline:before {
- content: "\e6ff";
-}
-.mdi-content-add-circle:before {
- content: "\e700";
-}
-.mdi-content-add:before {
- content: "\e701";
-}
-.mdi-content-archive:before {
- content: "\e702";
-}
-.mdi-content-backspace:before {
- content: "\e703";
-}
-.mdi-content-block:before {
- content: "\e704";
-}
-.mdi-content-clear:before {
- content: "\e705";
-}
-.mdi-content-content-copy:before {
- content: "\e706";
-}
-.mdi-content-content-cut:before {
- content: "\e707";
-}
-.mdi-content-content-paste:before {
- content: "\e708";
-}
-.mdi-content-create:before {
- content: "\e709";
-}
-.mdi-content-drafts:before {
- content: "\e70a";
-}
-.mdi-content-filter-list:before {
- content: "\e70b";
-}
-.mdi-content-flag:before {
- content: "\e70c";
-}
-.mdi-content-forward:before {
- content: "\e70d";
-}
-.mdi-content-gesture:before {
- content: "\e70e";
-}
-.mdi-content-inbox:before {
- content: "\e70f";
-}
-.mdi-content-link:before {
- content: "\e710";
-}
-.mdi-content-mail:before {
- content: "\e711";
-}
-.mdi-content-markunread:before {
- content: "\e712";
-}
-.mdi-content-redo:before {
- content: "\e713";
-}
-.mdi-content-remove-circle-outline:before {
- content: "\e714";
-}
-.mdi-content-remove-circle:before {
- content: "\e715";
-}
-.mdi-content-remove:before {
- content: "\e716";
-}
-.mdi-content-reply-all:before {
- content: "\e717";
-}
-.mdi-content-reply:before {
- content: "\e718";
-}
-.mdi-content-report:before {
- content: "\e719";
-}
-.mdi-content-save:before {
- content: "\e71a";
-}
-.mdi-content-select-all:before {
- content: "\e71b";
-}
-.mdi-content-send:before {
- content: "\e71c";
-}
-.mdi-content-sort:before {
- content: "\e71d";
-}
-.mdi-content-text-format:before {
- content: "\e71e";
-}
-.mdi-content-undo:before {
- content: "\e71f";
-}
-.mdi-editor-attach-file:before {
- content: "\e776";
-}
-.mdi-editor-attach-money:before {
- content: "\e777";
-}
-.mdi-editor-border-all:before {
- content: "\e778";
-}
-.mdi-editor-border-bottom:before {
- content: "\e779";
-}
-.mdi-editor-border-clear:before {
- content: "\e77a";
-}
-.mdi-editor-border-color:before {
- content: "\e77b";
-}
-.mdi-editor-border-horizontal:before {
- content: "\e77c";
-}
-.mdi-editor-border-inner:before {
- content: "\e77d";
-}
-.mdi-editor-border-left:before {
- content: "\e77e";
-}
-.mdi-editor-border-outer:before {
- content: "\e77f";
-}
-.mdi-editor-border-right:before {
- content: "\e780";
-}
-.mdi-editor-border-style:before {
- content: "\e781";
-}
-.mdi-editor-border-top:before {
- content: "\e782";
-}
-.mdi-editor-border-vertical:before {
- content: "\e783";
-}
-.mdi-editor-format-align-center:before {
- content: "\e784";
-}
-.mdi-editor-format-align-justify:before {
- content: "\e785";
-}
-.mdi-editor-format-align-left:before {
- content: "\e786";
-}
-.mdi-editor-format-align-right:before {
- content: "\e787";
-}
-.mdi-editor-format-bold:before {
- content: "\e788";
-}
-.mdi-editor-format-clear:before {
- content: "\e789";
-}
-.mdi-editor-format-color-fill:before {
- content: "\e78a";
-}
-.mdi-editor-format-color-reset:before {
- content: "\e78b";
-}
-.mdi-editor-format-color-text:before {
- content: "\e78c";
-}
-.mdi-editor-format-indent-decrease:before {
- content: "\e78d";
-}
-.mdi-editor-format-indent-increase:before {
- content: "\e78e";
-}
-.mdi-editor-format-italic:before {
- content: "\e78f";
-}
-.mdi-editor-format-line-spacing:before {
- content: "\e790";
-}
-.mdi-editor-format-list-bulleted:before {
- content: "\e791";
-}
-.mdi-editor-format-list-numbered:before {
- content: "\e792";
-}
-.mdi-editor-format-paint:before {
- content: "\e793";
-}
-.mdi-editor-format-quote:before {
- content: "\e794";
-}
-.mdi-editor-format-size:before {
- content: "\e795";
-}
-.mdi-editor-format-strikethrough:before {
- content: "\e796";
-}
-.mdi-editor-format-textdirection-l-to-r:before {
- content: "\e797";
-}
-.mdi-editor-format-textdirection-r-to-l:before {
- content: "\e798";
-}
-.mdi-editor-format-underline:before {
- content: "\e799";
-}
-.mdi-editor-functions:before {
- content: "\e79a";
-}
-.mdi-editor-insert-chart:before {
- content: "\e79b";
-}
-.mdi-editor-insert-comment:before {
- content: "\e79c";
-}
-.mdi-editor-insert-drive-file:before {
- content: "\e79d";
-}
-.mdi-editor-insert-emoticon:before {
- content: "\e79e";
-}
-.mdi-editor-insert-invitation:before {
- content: "\e79f";
-}
-.mdi-editor-insert-link:before {
- content: "\e7a0";
-}
-.mdi-editor-insert-photo:before {
- content: "\e7a1";
-}
-.mdi-editor-merge-type:before {
- content: "\e7a2";
-}
-.mdi-editor-mode-comment:before {
- content: "\e7a3";
-}
-.mdi-editor-mode-edit:before {
- content: "\e7a4";
-}
-.mdi-editor-publish:before {
- content: "\e7a5";
-}
-.mdi-editor-vertical-align-bottom:before {
- content: "\e7a6";
-}
-.mdi-editor-vertical-align-center:before {
- content: "\e7a7";
-}
-.mdi-editor-vertical-align-top:before {
- content: "\e7a8";
-}
-.mdi-editor-wrap-text:before {
- content: "\e7a9";
-}
-.mdi-file-attachment:before {
- content: "\e7aa";
-}
-.mdi-file-cloud-circle:before {
- content: "\e7ab";
-}
-.mdi-file-cloud-done:before {
- content: "\e7ac";
-}
-.mdi-file-cloud-download:before {
- content: "\e7ad";
-}
-.mdi-file-cloud-off:before {
- content: "\e7ae";
-}
-.mdi-file-cloud-queue:before {
- content: "\e7af";
-}
-.mdi-file-cloud-upload:before {
- content: "\e7b0";
-}
-.mdi-file-cloud:before {
- content: "\e7b1";
-}
-.mdi-file-file-download:before {
- content: "\e7b2";
-}
-.mdi-file-file-upload:before {
- content: "\e7b3";
-}
-.mdi-file-folder-open:before {
- content: "\e7b4";
-}
-.mdi-file-folder-shared:before {
- content: "\e7b5";
-}
-.mdi-file-folder:before {
- content: "\e7b6";
-}
-.mdi-device-access-alarm:before {
- content: "\e720";
-}
-.mdi-device-access-alarms:before {
- content: "\e721";
-}
-.mdi-device-access-time:before {
- content: "\e722";
-}
-.mdi-device-add-alarm:before {
- content: "\e723";
-}
-.mdi-device-airplanemode-off:before {
- content: "\e724";
-}
-.mdi-device-airplanemode-on:before {
- content: "\e725";
-}
-.mdi-device-battery-20:before {
- content: "\e726";
-}
-.mdi-device-battery-30:before {
- content: "\e727";
-}
-.mdi-device-battery-50:before {
- content: "\e728";
-}
-.mdi-device-battery-60:before {
- content: "\e729";
-}
-.mdi-device-battery-80:before {
- content: "\e72a";
-}
-.mdi-device-battery-90:before {
- content: "\e72b";
-}
-.mdi-device-battery-alert:before {
- content: "\e72c";
-}
-.mdi-device-battery-charging-20:before {
- content: "\e72d";
-}
-.mdi-device-battery-charging-30:before {
- content: "\e72e";
-}
-.mdi-device-battery-charging-50:before {
- content: "\e72f";
-}
-.mdi-device-battery-charging-60:before {
- content: "\e730";
-}
-.mdi-device-battery-charging-80:before {
- content: "\e731";
-}
-.mdi-device-battery-charging-90:before {
- content: "\e732";
-}
-.mdi-device-battery-charging-full:before {
- content: "\e733";
-}
-.mdi-device-battery-full:before {
- content: "\e734";
-}
-.mdi-device-battery-std:before {
- content: "\e735";
-}
-.mdi-device-battery-unknown:before {
- content: "\e736";
-}
-.mdi-device-bluetooth-connected:before {
- content: "\e737";
-}
-.mdi-device-bluetooth-disabled:before {
- content: "\e738";
-}
-.mdi-device-bluetooth-searching:before {
- content: "\e739";
-}
-.mdi-device-bluetooth:before {
- content: "\e73a";
-}
-.mdi-device-brightness-auto:before {
- content: "\e73b";
-}
-.mdi-device-brightness-high:before {
- content: "\e73c";
-}
-.mdi-device-brightness-low:before {
- content: "\e73d";
-}
-.mdi-device-brightness-medium:before {
- content: "\e73e";
-}
-.mdi-device-data-usage:before {
- content: "\e73f";
-}
-.mdi-device-developer-mode:before {
- content: "\e740";
-}
-.mdi-device-devices:before {
- content: "\e741";
-}
-.mdi-device-dvr:before {
- content: "\e742";
-}
-.mdi-device-gps-fixed:before {
- content: "\e743";
-}
-.mdi-device-gps-not-fixed:before {
- content: "\e744";
-}
-.mdi-device-gps-off:before {
- content: "\e745";
-}
-.mdi-device-location-disabled:before {
- content: "\e746";
-}
-.mdi-device-location-searching:before {
- content: "\e747";
-}
-.mdi-device-multitrack-audio:before {
- content: "\e748";
-}
-.mdi-device-network-cell:before {
- content: "\e749";
-}
-.mdi-device-network-wifi:before {
- content: "\e74a";
-}
-.mdi-device-nfc:before {
- content: "\e74b";
-}
-.mdi-device-now-wallpaper:before {
- content: "\e74c";
-}
-.mdi-device-now-widgets:before {
- content: "\e74d";
-}
-.mdi-device-screen-lock-landscape:before {
- content: "\e74e";
-}
-.mdi-device-screen-lock-portrait:before {
- content: "\e74f";
-}
-.mdi-device-screen-lock-rotation:before {
- content: "\e750";
-}
-.mdi-device-screen-rotation:before {
- content: "\e751";
-}
-.mdi-device-sd-storage:before {
- content: "\e752";
-}
-.mdi-device-settings-system-daydream:before {
- content: "\e753";
-}
-.mdi-device-signal-cellular-0-bar:before {
- content: "\e754";
-}
-.mdi-device-signal-cellular-1-bar:before {
- content: "\e755";
-}
-.mdi-device-signal-cellular-2-bar:before {
- content: "\e756";
-}
-.mdi-device-signal-cellular-3-bar:before {
- content: "\e757";
-}
-.mdi-device-signal-cellular-4-bar:before {
- content: "\e758";
-}
-.mdi-signal-wifi-statusbar-connected-no-internet-after:before {
- content: "\e8f6";
-}
-.mdi-device-signal-cellular-connected-no-internet-0-bar:before {
- content: "\e759";
-}
-.mdi-device-signal-cellular-connected-no-internet-1-bar:before {
- content: "\e75a";
-}
-.mdi-device-signal-cellular-connected-no-internet-2-bar:before {
- content: "\e75b";
-}
-.mdi-device-signal-cellular-connected-no-internet-3-bar:before {
- content: "\e75c";
-}
-.mdi-device-signal-cellular-connected-no-internet-4-bar:before {
- content: "\e75d";
-}
-.mdi-device-signal-cellular-no-sim:before {
- content: "\e75e";
-}
-.mdi-device-signal-cellular-null:before {
- content: "\e75f";
-}
-.mdi-device-signal-cellular-off:before {
- content: "\e760";
-}
-.mdi-device-signal-wifi-0-bar:before {
- content: "\e761";
-}
-.mdi-device-signal-wifi-1-bar:before {
- content: "\e762";
-}
-.mdi-device-signal-wifi-2-bar:before {
- content: "\e763";
-}
-.mdi-device-signal-wifi-3-bar:before {
- content: "\e764";
-}
-.mdi-device-signal-wifi-4-bar:before {
- content: "\e765";
-}
-.mdi-device-signal-wifi-off:before {
- content: "\e766";
-}
-.mdi-device-signal-wifi-statusbar-1-bar:before {
- content: "\e767";
-}
-.mdi-device-signal-wifi-statusbar-2-bar:before {
- content: "\e768";
-}
-.mdi-device-signal-wifi-statusbar-3-bar:before {
- content: "\e769";
-}
-.mdi-device-signal-wifi-statusbar-4-bar:before {
- content: "\e76a";
-}
-.mdi-device-signal-wifi-statusbar-connected-no-internet-:before {
- content: "\e76b";
-}
-.mdi-device-signal-wifi-statusbar-connected-no-internet:before {
- content: "\e76f";
-}
-.mdi-device-signal-wifi-statusbar-connected-no-internet-2:before {
- content: "\e76c";
-}
-.mdi-device-signal-wifi-statusbar-connected-no-internet-3:before {
- content: "\e76d";
-}
-.mdi-device-signal-wifi-statusbar-connected-no-internet-4:before {
- content: "\e76e";
-}
-.mdi-signal-wifi-statusbar-not-connected-after:before {
- content: "\e8f7";
-}
-.mdi-device-signal-wifi-statusbar-not-connected:before {
- content: "\e770";
-}
-.mdi-device-signal-wifi-statusbar-null:before {
- content: "\e771";
-}
-.mdi-device-storage:before {
- content: "\e772";
-}
-.mdi-device-usb:before {
- content: "\e773";
-}
-.mdi-device-wifi-lock:before {
- content: "\e774";
-}
-.mdi-device-wifi-tethering:before {
- content: "\e775";
-}
-.mdi-hardware-cast-connected:before {
- content: "\e7b7";
-}
-.mdi-hardware-cast:before {
- content: "\e7b8";
-}
-.mdi-hardware-computer:before {
- content: "\e7b9";
-}
-.mdi-hardware-desktop-mac:before {
- content: "\e7ba";
-}
-.mdi-hardware-desktop-windows:before {
- content: "\e7bb";
-}
-.mdi-hardware-dock:before {
- content: "\e7bc";
-}
-.mdi-hardware-gamepad:before {
- content: "\e7bd";
-}
-.mdi-hardware-headset-mic:before {
- content: "\e7be";
-}
-.mdi-hardware-headset:before {
- content: "\e7bf";
-}
-.mdi-hardware-keyboard-alt:before {
- content: "\e7c0";
-}
-.mdi-hardware-keyboard-arrow-down:before {
- content: "\e7c1";
-}
-.mdi-hardware-keyboard-arrow-left:before {
- content: "\e7c2";
-}
-.mdi-hardware-keyboard-arrow-right:before {
- content: "\e7c3";
-}
-.mdi-hardware-keyboard-arrow-up:before {
- content: "\e7c4";
-}
-.mdi-hardware-keyboard-backspace:before {
- content: "\e7c5";
-}
-.mdi-hardware-keyboard-capslock:before {
- content: "\e7c6";
-}
-.mdi-hardware-keyboard-control:before {
- content: "\e7c7";
-}
-.mdi-hardware-keyboard-hide:before {
- content: "\e7c8";
-}
-.mdi-hardware-keyboard-return:before {
- content: "\e7c9";
-}
-.mdi-hardware-keyboard-tab:before {
- content: "\e7ca";
-}
-.mdi-hardware-keyboard-voice:before {
- content: "\e7cb";
-}
-.mdi-hardware-keyboard:before {
- content: "\e7cc";
-}
-.mdi-hardware-laptop-chromebook:before {
- content: "\e7cd";
-}
-.mdi-hardware-laptop-mac:before {
- content: "\e7ce";
-}
-.mdi-hardware-laptop-windows:before {
- content: "\e7cf";
-}
-.mdi-hardware-laptop:before {
- content: "\e7d0";
-}
-.mdi-hardware-memory:before {
- content: "\e7d1";
-}
-.mdi-hardware-mouse:before {
- content: "\e7d2";
-}
-.mdi-hardware-phone-android:before {
- content: "\e7d3";
-}
-.mdi-hardware-phone-iphone:before {
- content: "\e7d4";
-}
-.mdi-hardware-phonelink-off:before {
- content: "\e7d5";
-}
-.mdi-hardware-phonelink:before {
- content: "\e7d6";
-}
-.mdi-hardware-security:before {
- content: "\e7d7";
-}
-.mdi-hardware-sim-card:before {
- content: "\e7d8";
-}
-.mdi-hardware-smartphone:before {
- content: "\e7d9";
-}
-.mdi-hardware-speaker:before {
- content: "\e7da";
-}
-.mdi-hardware-tablet-android:before {
- content: "\e7db";
-}
-.mdi-hardware-tablet-mac:before {
- content: "\e7dc";
-}
-.mdi-hardware-tablet:before {
- content: "\e7dd";
-}
-.mdi-hardware-tv:before {
- content: "\e7de";
-}
-.mdi-hardware-watch:before {
- content: "\e7df";
-}
-.mdi-image-add-to-photos:before {
- content: "\e7e0";
-}
-.mdi-image-adjust:before {
- content: "\e7e1";
-}
-.mdi-image-assistant-photo:before {
- content: "\e7e2";
-}
-.mdi-image-audiotrack:before {
- content: "\e7e3";
-}
-.mdi-image-blur-circular:before {
- content: "\e7e4";
-}
-.mdi-image-blur-linear:before {
- content: "\e7e5";
-}
-.mdi-image-blur-off:before {
- content: "\e7e6";
-}
-.mdi-image-blur-on:before {
- content: "\e7e7";
-}
-.mdi-image-brightness-1:before {
- content: "\e7e8";
-}
-.mdi-image-brightness-2:before {
- content: "\e7e9";
-}
-.mdi-image-brightness-3:before {
- content: "\e7ea";
-}
-.mdi-image-brightness-4:before {
- content: "\e7eb";
-}
-.mdi-image-brightness-5:before {
- content: "\e7ec";
-}
-.mdi-image-brightness-6:before {
- content: "\e7ed";
-}
-.mdi-image-brightness-7:before {
- content: "\e7ee";
-}
-.mdi-image-brush:before {
- content: "\e7ef";
-}
-.mdi-image-camera-alt:before {
- content: "\e7f0";
-}
-.mdi-image-camera-front:before {
- content: "\e7f1";
-}
-.mdi-image-camera-rear:before {
- content: "\e7f2";
-}
-.mdi-image-camera-roll:before {
- content: "\e7f3";
-}
-.mdi-image-camera:before {
- content: "\e7f4";
-}
-.mdi-image-center-focus-strong:before {
- content: "\e7f5";
-}
-.mdi-image-center-focus-weak:before {
- content: "\e7f6";
-}
-.mdi-image-collections:before {
- content: "\e7f7";
-}
-.mdi-image-color-lens:before {
- content: "\e7f8";
-}
-.mdi-image-colorize:before {
- content: "\e7f9";
-}
-.mdi-image-compare:before {
- content: "\e7fa";
-}
-.mdi-image-control-point-duplicate:before {
- content: "\e7fb";
-}
-.mdi-image-control-point:before {
- content: "\e7fc";
-}
-.mdi-image-crop-3-2:before {
- content: "\e7fd";
-}
-.mdi-image-crop-5-4:before {
- content: "\e7fe";
-}
-.mdi-image-crop-7-5:before {
- content: "\e7ff";
-}
-.mdi-image-crop-16-9:before {
- content: "\e800";
-}
-.mdi-image-crop-din:before {
- content: "\e801";
-}
-.mdi-image-crop-free:before {
- content: "\e802";
-}
-.mdi-image-crop-landscape:before {
- content: "\e803";
-}
-.mdi-image-crop-original:before {
- content: "\e804";
-}
-.mdi-image-crop-portrait:before {
- content: "\e805";
-}
-.mdi-image-crop-square:before {
- content: "\e806";
-}
-.mdi-image-crop:before {
- content: "\e807";
-}
-.mdi-image-dehaze:before {
- content: "\e808";
-}
-.mdi-image-details:before {
- content: "\e809";
-}
-.mdi-image-edit:before {
- content: "\e80a";
-}
-.mdi-image-exposure-minus-1:before {
- content: "\e80b";
-}
-.mdi-image-exposure-minus-2:before {
- content: "\e80c";
-}
-.mdi-image-exposure-plus-1:before {
- content: "\e80d";
-}
-.mdi-image-exposure-plus-2:before {
- content: "\e80e";
-}
-.mdi-image-exposure-zero:before {
- content: "\e80f";
-}
-.mdi-image-exposure:before {
- content: "\e810";
-}
-.mdi-image-filter-1:before {
- content: "\e811";
-}
-.mdi-image-filter-2:before {
- content: "\e812";
-}
-.mdi-image-filter-3:before {
- content: "\e813";
-}
-.mdi-image-filter-4:before {
- content: "\e814";
-}
-.mdi-image-filter-5:before {
- content: "\e815";
-}
-.mdi-image-filter-6:before {
- content: "\e816";
-}
-.mdi-image-filter-7:before {
- content: "\e817";
-}
-.mdi-image-filter-8:before {
- content: "\e818";
-}
-.mdi-image-filter-9-plus:before {
- content: "\e819";
-}
-.mdi-image-filter-9:before {
- content: "\e81a";
-}
-.mdi-image-filter-b-and-w:before {
- content: "\e81b";
-}
-.mdi-image-filter-center-focus:before {
- content: "\e81c";
-}
-.mdi-image-filter-drama:before {
- content: "\e81d";
-}
-.mdi-image-filter-frames:before {
- content: "\e81e";
-}
-.mdi-image-filter-hdr:before {
- content: "\e81f";
-}
-.mdi-image-filter-none:before {
- content: "\e820";
-}
-.mdi-image-filter-tilt-shift:before {
- content: "\e821";
-}
-.mdi-image-filter-vintage:before {
- content: "\e822";
-}
-.mdi-image-filter:before {
- content: "\e823";
-}
-.mdi-image-flare:before {
- content: "\e824";
-}
-.mdi-image-flash-auto:before {
- content: "\e825";
-}
-.mdi-image-flash-off:before {
- content: "\e826";
-}
-.mdi-image-flash-on:before {
- content: "\e827";
-}
-.mdi-image-flip:before {
- content: "\e828";
-}
-.mdi-image-gradient:before {
- content: "\e829";
-}
-.mdi-image-grain:before {
- content: "\e82a";
-}
-.mdi-image-grid-off:before {
- content: "\e82b";
-}
-.mdi-image-grid-on:before {
- content: "\e82c";
-}
-.mdi-image-hdr-off:before {
- content: "\e82d";
-}
-.mdi-image-hdr-on:before {
- content: "\e82e";
-}
-.mdi-image-hdr-strong:before {
- content: "\e82f";
-}
-.mdi-image-hdr-weak:before {
- content: "\e830";
-}
-.mdi-image-healing:before {
- content: "\e831";
-}
-.mdi-image-image-aspect-ratio:before {
- content: "\e832";
-}
-.mdi-image-image:before {
- content: "\e833";
-}
-.mdi-image-iso:before {
- content: "\e834";
-}
-.mdi-image-landscape:before {
- content: "\e835";
-}
-.mdi-image-leak-add:before {
- content: "\e836";
-}
-.mdi-image-leak-remove:before {
- content: "\e837";
-}
-.mdi-image-lens:before {
- content: "\e838";
-}
-.mdi-image-looks-3:before {
- content: "\e839";
-}
-.mdi-image-looks-4:before {
- content: "\e83a";
-}
-.mdi-image-looks-5:before {
- content: "\e83b";
-}
-.mdi-image-looks-6:before {
- content: "\e83c";
-}
-.mdi-image-looks-one:before {
- content: "\e83d";
-}
-.mdi-image-looks-two:before {
- content: "\e83e";
-}
-.mdi-image-looks:before {
- content: "\e83f";
-}
-.mdi-image-loupe:before {
- content: "\e840";
-}
-.mdi-image-movie-creation:before {
- content: "\e841";
-}
-.mdi-image-nature-people:before {
- content: "\e842";
-}
-.mdi-image-nature:before {
- content: "\e843";
-}
-.mdi-image-navigate-before:before {
- content: "\e844";
-}
-.mdi-image-navigate-next:before {
- content: "\e845";
-}
-.mdi-image-palette:before {
- content: "\e846";
-}
-.mdi-image-panorama-fisheye:before {
- content: "\e847";
-}
-.mdi-image-panorama-horizontal:before {
- content: "\e848";
-}
-.mdi-image-panorama-vertical:before {
- content: "\e849";
-}
-.mdi-image-panorama-wide-angle:before {
- content: "\e84a";
-}
-.mdi-image-panorama:before {
- content: "\e84b";
-}
-.mdi-image-photo-album:before {
- content: "\e84c";
-}
-.mdi-image-photo-camera:before {
- content: "\e84d";
-}
-.mdi-image-photo-library:before {
- content: "\e84e";
-}
-.mdi-image-photo:before {
- content: "\e84f";
-}
-.mdi-image-portrait:before {
- content: "\e850";
-}
-.mdi-image-remove-red-eye:before {
- content: "\e851";
-}
-.mdi-image-rotate-left:before {
- content: "\e852";
-}
-.mdi-image-rotate-right:before {
- content: "\e853";
-}
-.mdi-image-slideshow:before {
- content: "\e854";
-}
-.mdi-image-straighten:before {
- content: "\e855";
-}
-.mdi-image-style:before {
- content: "\e856";
-}
-.mdi-image-switch-camera:before {
- content: "\e857";
-}
-.mdi-image-switch-video:before {
- content: "\e858";
-}
-.mdi-image-tag-faces:before {
- content: "\e859";
-}
-.mdi-image-texture:before {
- content: "\e85a";
-}
-.mdi-image-timelapse:before {
- content: "\e85b";
-}
-.mdi-image-timer-3:before {
- content: "\e85c";
-}
-.mdi-image-timer-10:before {
- content: "\e85d";
-}
-.mdi-image-timer-auto:before {
- content: "\e85e";
-}
-.mdi-image-timer-off:before {
- content: "\e85f";
-}
-.mdi-image-timer:before {
- content: "\e860";
-}
-.mdi-image-tonality:before {
- content: "\e861";
-}
-.mdi-image-transform:before {
- content: "\e862";
-}
-.mdi-image-tune:before {
- content: "\e863";
-}
-.mdi-image-wb-auto:before {
- content: "\e864";
-}
-.mdi-image-wb-cloudy:before {
- content: "\e865";
-}
-.mdi-image-wb-incandescent:before {
- content: "\e866";
-}
-.mdi-image-wb-irradescent:before {
- content: "\e867";
-}
-.mdi-image-wb-sunny:before {
- content: "\e868";
-}
-.mdi-maps-beenhere:before {
- content: "\e869";
-}
-.mdi-maps-directions-bike:before {
- content: "\e86a";
-}
-.mdi-maps-directions-bus:before {
- content: "\e86b";
-}
-.mdi-maps-directions-car:before {
- content: "\e86c";
-}
-.mdi-maps-directions-ferry:before {
- content: "\e86d";
-}
-.mdi-maps-directions-subway:before {
- content: "\e86e";
-}
-.mdi-maps-directions-train:before {
- content: "\e86f";
-}
-.mdi-maps-directions-transit:before {
- content: "\e870";
-}
-.mdi-maps-directions-walk:before {
- content: "\e871";
-}
-.mdi-maps-directions:before {
- content: "\e872";
-}
-.mdi-maps-flight:before {
- content: "\e873";
-}
-.mdi-maps-hotel:before {
- content: "\e874";
-}
-.mdi-maps-layers-clear:before {
- content: "\e875";
-}
-.mdi-maps-layers:before {
- content: "\e876";
-}
-.mdi-maps-local-airport:before {
- content: "\e877";
-}
-.mdi-maps-local-atm:before {
- content: "\e878";
-}
-.mdi-maps-local-attraction:before {
- content: "\e879";
-}
-.mdi-maps-local-bar:before {
- content: "\e87a";
-}
-.mdi-maps-local-cafe:before {
- content: "\e87b";
-}
-.mdi-maps-local-car-wash:before {
- content: "\e87c";
-}
-.mdi-maps-local-convenience-store:before {
- content: "\e87d";
-}
-.mdi-maps-local-drink:before {
- content: "\e87e";
-}
-.mdi-maps-local-florist:before {
- content: "\e87f";
-}
-.mdi-maps-local-gas-station:before {
- content: "\e880";
-}
-.mdi-maps-local-grocery-store:before {
- content: "\e881";
-}
-.mdi-maps-local-hospital:before {
- content: "\e882";
-}
-.mdi-maps-local-hotel:before {
- content: "\e883";
-}
-.mdi-maps-local-laundry-service:before {
- content: "\e884";
-}
-.mdi-maps-local-library:before {
- content: "\e885";
-}
-.mdi-maps-local-mall:before {
- content: "\e886";
-}
-.mdi-maps-local-movies:before {
- content: "\e887";
-}
-.mdi-maps-local-offer:before {
- content: "\e888";
-}
-.mdi-maps-local-parking:before {
- content: "\e889";
-}
-.mdi-maps-local-pharmacy:before {
- content: "\e88a";
-}
-.mdi-maps-local-phone:before {
- content: "\e88b";
-}
-.mdi-maps-local-pizza:before {
- content: "\e88c";
-}
-.mdi-maps-local-play:before {
- content: "\e88d";
-}
-.mdi-maps-local-post-office:before {
- content: "\e88e";
-}
-.mdi-maps-local-print-shop:before {
- content: "\e88f";
-}
-.mdi-maps-local-restaurant:before {
- content: "\e890";
-}
-.mdi-maps-local-see:before {
- content: "\e891";
-}
-.mdi-maps-local-shipping:before {
- content: "\e892";
-}
-.mdi-maps-local-taxi:before {
- content: "\e893";
-}
-.mdi-maps-location-history:before {
- content: "\e894";
-}
-.mdi-maps-map:before {
- content: "\e895";
-}
-.mdi-maps-my-location:before {
- content: "\e896";
-}
-.mdi-maps-navigation:before {
- content: "\e897";
-}
-.mdi-maps-pin-drop:before {
- content: "\e898";
-}
-.mdi-maps-place:before {
- content: "\e899";
-}
-.mdi-maps-rate-review:before {
- content: "\e89a";
-}
-.mdi-maps-restaurant-menu:before {
- content: "\e89b";
-}
-.mdi-maps-satellite:before {
- content: "\e89c";
-}
-.mdi-maps-store-mall-directory:before {
- content: "\e89d";
-}
-.mdi-maps-terrain:before {
- content: "\e89e";
-}
-.mdi-maps-traffic:before {
- content: "\e89f";
-}
-.mdi-navigation-apps:before {
- content: "\e8a0";
-}
-.mdi-navigation-arrow-back:before {
- content: "\e8a1";
-}
-.mdi-navigation-arrow-drop-down-circle:before {
- content: "\e8a2";
-}
-.mdi-navigation-arrow-drop-down:before {
- content: "\e8a3";
-}
-.mdi-navigation-arrow-drop-up:before {
- content: "\e8a4";
-}
-.mdi-navigation-arrow-forward:before {
- content: "\e8a5";
-}
-.mdi-navigation-cancel:before {
- content: "\e8a6";
-}
-.mdi-navigation-check:before {
- content: "\e8a7";
-}
-.mdi-navigation-chevron-left:before {
- content: "\e8a8";
-}
-.mdi-navigation-chevron-right:before {
- content: "\e8a9";
-}
-.mdi-navigation-close:before {
- content: "\e8aa";
-}
-.mdi-navigation-expand-less:before {
- content: "\e8ab";
-}
-.mdi-navigation-expand-more:before {
- content: "\e8ac";
-}
-.mdi-navigation-fullscreen-exit:before {
- content: "\e8ad";
-}
-.mdi-navigation-fullscreen:before {
- content: "\e8ae";
-}
-.mdi-navigation-menu:before {
- content: "\e8af";
-}
-.mdi-navigation-more-horiz:before {
- content: "\e8b0";
-}
-.mdi-navigation-more-vert:before {
- content: "\e8b1";
-}
-.mdi-navigation-refresh:before {
- content: "\e8b2";
-}
-.mdi-navigation-unfold-less:before {
- content: "\e8b3";
-}
-.mdi-navigation-unfold-more:before {
- content: "\e8b4";
-}
-.mdi-notification-adb:before {
- content: "\e8b5";
-}
-.mdi-notification-bluetooth-audio:before {
- content: "\e8b6";
-}
-.mdi-notification-disc-full:before {
- content: "\e8b7";
-}
-.mdi-notification-dnd-forwardslash:before {
- content: "\e8b8";
-}
-.mdi-notification-do-not-disturb:before {
- content: "\e8b9";
-}
-.mdi-notification-drive-eta:before {
- content: "\e8ba";
-}
-.mdi-notification-event-available:before {
- content: "\e8bb";
-}
-.mdi-notification-event-busy:before {
- content: "\e8bc";
-}
-.mdi-notification-event-note:before {
- content: "\e8bd";
-}
-.mdi-notification-folder-special:before {
- content: "\e8be";
-}
-.mdi-notification-mms:before {
- content: "\e8bf";
-}
-.mdi-notification-more:before {
- content: "\e8c0";
-}
-.mdi-notification-network-locked:before {
- content: "\e8c1";
-}
-.mdi-notification-phone-bluetooth-speaker:before {
- content: "\e8c2";
-}
-.mdi-notification-phone-forwarded:before {
- content: "\e8c3";
-}
-.mdi-notification-phone-in-talk:before {
- content: "\e8c4";
-}
-.mdi-notification-phone-locked:before {
- content: "\e8c5";
-}
-.mdi-notification-phone-missed:before {
- content: "\e8c6";
-}
-.mdi-notification-phone-paused:before {
- content: "\e8c7";
-}
-.mdi-notification-play-download:before {
- content: "\e8c8";
-}
-.mdi-notification-play-install:before {
- content: "\e8c9";
-}
-.mdi-notification-sd-card:before {
- content: "\e8ca";
-}
-.mdi-notification-sim-card-alert:before {
- content: "\e8cb";
-}
-.mdi-notification-sms-failed:before {
- content: "\e8cc";
-}
-.mdi-notification-sms:before {
- content: "\e8cd";
-}
-.mdi-notification-sync-disabled:before {
- content: "\e8ce";
-}
-.mdi-notification-sync-problem:before {
- content: "\e8cf";
-}
-.mdi-notification-sync:before {
- content: "\e8d0";
-}
-.mdi-notification-system-update:before {
- content: "\e8d1";
-}
-.mdi-notification-tap-and-play:before {
- content: "\e8d2";
-}
-.mdi-notification-time-to-leave:before {
- content: "\e8d3";
-}
-.mdi-notification-vibration:before {
- content: "\e8d4";
-}
-.mdi-notification-voice-chat:before {
- content: "\e8d5";
-}
-.mdi-notification-vpn-lock:before {
- content: "\e8d6";
-}
-.mdi-social-cake:before {
- content: "\e8d7";
-}
-.mdi-social-domain:before {
- content: "\e8d8";
-}
-.mdi-social-group-add:before {
- content: "\e8d9";
-}
-.mdi-social-group:before {
- content: "\e8da";
-}
-.mdi-social-location-city:before {
- content: "\e8db";
-}
-.mdi-social-mood:before {
- content: "\e8dc";
-}
-.mdi-social-notifications-none:before {
- content: "\e8dd";
-}
-.mdi-social-notifications-off:before {
- content: "\e8de";
-}
-.mdi-social-notifications-on:before {
- content: "\e8df";
-}
-.mdi-social-notifications-paused:before {
- content: "\e8e0";
-}
-.mdi-social-notifications:before {
- content: "\e8e1";
-}
-.mdi-social-pages:before {
- content: "\e8e2";
-}
-.mdi-social-party-mode:before {
- content: "\e8e3";
-}
-.mdi-social-people-outline:before {
- content: "\e8e4";
-}
-.mdi-social-people:before {
- content: "\e8e5";
-}
-.mdi-social-person-add:before {
- content: "\e8e6";
-}
-.mdi-social-person-outline:before {
- content: "\e8e7";
-}
-.mdi-social-person:before {
- content: "\e8e8";
-}
-.mdi-social-plus-one:before {
- content: "\e8e9";
-}
-.mdi-social-poll:before {
- content: "\e8ea";
-}
-.mdi-social-publ24px:before {
- content: "\e8eb";
-}
-.mdi-social-school:before {
- content: "\e8ec";
-}
-.mdi-social-share:before {
- content: "\e8ed";
-}
-.mdi-social-whatshot:before {
- content: "\e8ee";
-}
-.mdi-toggle-check-box-outline-blank:before {
- content: "\e8ef";
-}
-.mdi-toggle-check-box:before {
- content: "\e8f0";
-}
-.mdi-toggle-radio-button-off:before {
- content: "\e8f1";
-}
-.mdi-toggle-radio-button-on:before {
- content: "\e8f2";
-}
-.mdi-toggle-star-half:before {
- content: "\e8f3";
-}
-.mdi-toggle-star-outline:before {
- content: "\e8f4";
-}
-.mdi-toggle-star:before {
- content: "\e8f5";
-}
-.o-no-select {
- pointer-events: none;
- cursor: default;
-}
-.o-no-select::selection,
-.o-no-select *::selection {
- background: transparent;
-}
-.o-no-select::-moz-selection,
-.o-no-select *::-moz-selection {
- background: transparent;
-}
-.o_logo {
- background-image: url("img/logos/odoo_logo.png");
- background-image: url("img/logos/odoo_logo.svg");
- background-position: 0 0;
- background-repeat: no-repeat;
- display: inline-block;
- width: 94.05px;
- height: 30px;
- background-size: auto 30px;
-}
-.o_logo.center-block,
-.o_logo.o_logo_responsive_half {
- position: relative;
- margin-left: auto;
- margin-right: auto;
- display: block;
-}
-.o_logo.o_logo_responsive {
- background-size: cover;
- width: 100%;
- height: 0;
- padding-bottom: 31.9%;
-}
-.o_logo.o_logo_responsive_half {
- background-size: cover;
- width: 50%;
- height: 0;
- padding-bottom: 15.94%;
-}
-.o_logo_15 {
- width: 47.025px;
- height: 15px;
- background-size: auto 15px;
-}
-.o_logo_30 {
- width: 94.05px;
- height: 30px;
- background-size: auto 30px;
-}
-.o_logo_60 {
- width: 188.1px;
- height: 60px;
- background-size: auto 60px;
-}
-.o_logo_120 {
- width: 376.2px;
- height: 120px;
- background-size: auto 120px;
-}
-.o_logo_240 {
- width: 752.4px;
- height: 240px;
- background-size: auto 240px;
-}
-.o_logo_inverse {
- background-position: 100% 0;
-}
-.o_logo_inverse.o_logo_15.center-block {
- background-position: 102% 0;
-}
-.o-doc-dropdown > a.dropdown-toggle {
- padding: 0 5px 0 10px;
-}
-.o-doc-dropdown > a.dropdown-toggle:after {
- font-family: 'Material-Design-Icons';
- content: "\e7c1";
- display: inline-block;
- text-rendering: geometricPrecision;
- font-size: 1em;
- -webkit-font-smoothing: antialiased;
- -moz-osx-font-smoothing: grayscale;
-}
-@media screen and (max-width: 767px) {
- .o-doc-dropdown > a.dropdown-toggle:after {
- font-size: 1.5em;
- }
-}
-.o-doc-dropdown.open {
- z-index: 1;
- position: relative;
- background-color: #dcddde;
- color: #2b3134;
-}
-@media screen and (min-width: 768px) {
- .o-doc-dropdown.open {
- background-color: #FCFCFC;
- }
-}
-.o-doc-dropdown.open .dropdown-toggle {
- color: #2b3134;
-}
-.o-doc-dropdown.open .dropdown-toggle:hover {
- color: #21313a;
-}
-.o-doc-dropdown.open .dropdown-menu {
- margin-top: 0;
- border: none;
- border-radius: 0;
- text-align: left;
- min-width: 100%;
- background-color: #FCFCFC;
- padding-bottom: 12.5px;
- box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.17);
-}
-.o-doc-dropdown.open .dropdown-menu > li > a {
- font-size: 12px;
- display: block;
- color: #2b3134;
- float: none;
- text-transform: none;
- font-weight: 500;
-}
-@media screen and (max-width: 767px) {
- .o-doc-dropdown.open .dropdown-menu > li > a {
- padding-left: 10px;
- }
-}
-.o-doc-dropdown.open .dropdown-menu > li.active > a {
- color: white;
- background-color: #4c8c7f;
-}
-@media screen and (max-width: 767px) {
- .o-doc-dropdown.open .dropdown-menu {
- position: static;
- }
-}
-@media screen and (min-width: 768px) {
- .o-doc-dropdown.open .dropdown-menu {
- background-color: #FCFCFC;
- }
-}
-.o-doc-dropdown.o_dropdown_mobile_nav {
- margin-left: 0;
-}
-.o-doc-dropdown.o_dropdown_mobile_nav > .dropdown-toggle:after {
- position: absolute;
- top: 0;
- left: auto;
- bottom: auto;
- right: 0;
-}
-.o-doc-dropdown.o_dropdown_mobile_nav .o_breadcrumb_dropdown_menu > li > a {
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
-}
-.o-doc-dropdown.o_dropdown_mobile_nav .o_breadcrumb_dropdown_menu > li > a:before {
- content: "|";
- margin-right: 0.5em;
-}
-.o-doc-dropdown.o_dropdown_mobile_nav .o_breadcrumb_dropdown_menu > li:nth-child(1) > a:before {
- display: none;
-}
-.o-doc-dropdown.o_dropdown_mobile_nav .o_breadcrumb_dropdown_menu > li:nth-child(2) > a:before {
- padding-left: 0.5em;
-}
-.o-doc-dropdown.o_dropdown_mobile_nav .o_breadcrumb_dropdown_menu > li:nth-child(3) > a:before {
- padding-left: 1em;
-}
-body {
- -webkit-font-smoothing: antialiased;
- -moz-osx-font-smoothing: grayscale;
- text-rendering: optimizeLegibility;
-}
-h1,
-h2,
-h3,
-h4,
-h5,
-h6 {
- text-rendering: geometricPrecision;
-}
-@media (min-width: 1200px) {
- .has_code_col .doc-aside h1,
- .has_code_col .doc-aside h2,
- .has_code_col .doc-aside h3,
- .has_code_col .doc-aside h4,
- .has_code_col .doc-aside h5,
- .has_code_col .doc-aside h6 {
- color: white;
- }
-}
-.footnote-ref {
- vertical-align: super;
- font-size: 1ex;
-}
-.footnote-ref:before {
- content: '[';
-}
-.footnote-ref:after {
- content: ']';
-}
-article.doc-body > section {
- padding-bottom: 10px;
-}
-article.doc-body > section > :last-child {
- margin-bottom: 0;
-}
-article.doc-body > section > h2,
-article.doc-body > section > h3,
-article.doc-body > section > h4,
-article.doc-body > section > h5,
-article.doc-body > section > h6 {
- margin-bottom: 5px;
- margin-top: 40px;
-}
-article.doc-body > section > h2:last-child,
-article.doc-body > section > h3:last-child,
-article.doc-body > section > h4:last-child,
-article.doc-body > section > h5:last-child,
-article.doc-body > section > h6:last-child {
- margin-bottom: -30px;
- padding-bottom: 5px;
- border-bottom: 2px solid #f4f6f7;
-}
-article.doc-body > section > h2 {
- padding-bottom: 5px;
- border-bottom: 2px solid #f4f6f7;
-}
-article.doc-body > section > h5,
-article.doc-body > section > h6 {
- font-weight: 500;
-}
-article.doc-body > section:first-of-type > h2,
-article.doc-body > section:first-of-type > h3,
-article.doc-body > section:first-of-type > h4,
-article.doc-body > section:first-of-type > h5,
-article.doc-body > section:first-of-type > h6 {
- margin-top: 10px;
-}
-article.doc-body > section:first-of-type:empty,
-article.doc-body > section:first-of-type.hidden {
- display: none;
-}
-article.doc-body > section:first-of-type:empty + section > h2,
-article.doc-body > section:first-of-type.hidden + section > h2,
-article.doc-body > section:first-of-type:empty + section > h3,
-article.doc-body > section:first-of-type.hidden + section > h3,
-article.doc-body > section:first-of-type:empty + section > h4,
-article.doc-body > section:first-of-type.hidden + section > h4,
-article.doc-body > section:first-of-type:empty + section > h5,
-article.doc-body > section:first-of-type.hidden + section > h5,
-article.doc-body > section:first-of-type:empty + section > h6,
-article.doc-body > section:first-of-type.hidden + section > h6 {
- margin-top: 10px;
-}
-article.doc-body > section {
- line-height: 26px;
-}
-article.doc-body a,
-article.doc-body a:hover {
- text-decoration: underline;
-}
-article.doc-body blockquote {
- font-size: 15px;
- line-height: 26px;
-}
-article.doc-body blockquote:not(:first-child) {
- margin-top: 17px;
-}
-article.doc-body dl dt code {
- font-size: 0.9em;
-}
-article.doc-body dl dd {
- margin: 2px 0 15px 15px;
-}
-article.doc-body ol,
-article.doc-body ul {
- line-height: 26px;
- padding: 0;
- list-style: none;
- counter-reset: a;
-}
-article.doc-body ol li,
-article.doc-body ul li {
- margin: 5px 0;
- position: relative;
- padding-left: 30px;
-}
-article.doc-body ol li:before,
-article.doc-body ul li:before {
- content: "";
- display: block;
- position: absolute;
- top: 9px;
- left: 10px;
- bottom: auto;
- right: auto;
- width: 6px;
- height: 6px;
- border-radius: 50%;
- background: #939da3;
-}
-article.doc-body ol li p,
-article.doc-body ul li p {
- margin: 0;
-}
-article.doc-body ol li h2,
-article.doc-body ul li h2,
-article.doc-body ol li h3,
-article.doc-body ul li h3,
-article.doc-body ol li h4,
-article.doc-body ul li h4,
-article.doc-body ol li h5,
-article.doc-body ul li h5,
-article.doc-body ol li h6,
-article.doc-body ul li h6 {
- margin-top: 0;
- padding-top: 0;
-}
-article.doc-body ol > li:before {
- counter-increment: a;
- content: counter(a);
- color: #fff;
- font-size: 13px;
- font-weight: bold;
- line-height: 1;
- text-align: center;
- padding: 4px 0;
- width: 20px;
- height: 20px;
- border-radius: 10px;
- position: absolute;
- top: 3px;
- left: 0;
- bottom: auto;
- right: auto;
-}
-article.doc-body .o_has_permalink_marker {
- transition: all, 0.3s;
- padding-left: 0;
-}
-article.doc-body .o_has_permalink_marker i {
- cursor: pointer;
- visibility: hidden;
- margin-left: 0.1em;
- font-size: 0.8em;
- padding: 0.2em;
- -webkit-transform: rotate(-45deg);
- -ms-transform: rotate(-45deg);
- -o-transform: rotate(-45deg);
- transform: rotate(-45deg);
-}
-article.doc-body .o_has_permalink_marker:hover i {
- visibility: visible;
-}
-article.doc-body .o_has_permalink_marker.o_marked {
- padding-left: 10px;
- background-color: #fff7d1;
-}
-@-webkit-keyframes ripple {
- to {
- opacity: 0;
- -webkit-transform: scale(2.5);
- }
-}
-@keyframes ripple {
- to {
- opacity: 0;
- -webkit-transform: scale(2.5);
- -ms-transform: scale(2.5);
- -o-transform: scale(2.5);
- transform: scale(2.5);
- }
-}
-.ripple {
- z-index: 2;
-}
-.ripple .inner-ripple {
- display: block;
- position: absolute;
- border-radius: 100%;
- opacity: 1;
- z-index: -1;
- background: rgba(0, 0, 0, 0.05);
- pointer-events: none;
- -webkit-transform: scale(0);
- -ms-transform: scale(0);
- -o-transform: scale(0);
- transform: scale(0);
-}
-.ripple .inner-ripple.inner-ripple-animated {
- -webkit-animation: ripple 0.35s ease-in;
- -o-animation: ripple 0.35s ease-in;
- animation: ripple 0.35s ease-in;
-}
-article.doc-body .code-fields {
- display: table;
- width: 100%;
- padding: 5px;
- font-size: 0.8em;
- border: 2px solid #F2F2F2;
-}
-article.doc-body .code-fields .code-field {
- display: table-row;
-}
-article.doc-body .code-fields .code-field-body {
- display: block;
- padding-left: 15px;
-}
-@media screen and (min-width: 992px) {
- article.doc-body .code-fields .code-field-body {
- display: table-cell;
- padding-left: 0;
- }
-}
-article.doc-body .code-fields .code-field-name {
- width: auto;
- display: block;
- font-weight: 600;
- color: #21313a;
-}
-article.doc-body .code-fields .code-field-name:after {
- content: ":";
-}
-@media screen and (min-width: 992px) {
- article.doc-body .code-fields .code-field-name {
- text-align: right;
- width: 20%;
- padding-right: 10px;
- display: table-cell;
- }
-}
-article.doc-body .code-fields ul {
- list-style: none;
- margin: 0.2em 0;
-}
-article.doc-body .code-fields ul > li {
- margin: 0 0 8px;
- padding-left: 0px;
- line-height: 1.5;
-}
-article.doc-body .code-fields ul > li:before {
- display: none;
-}
-article.doc-body .code-fields ul strong {
- color: #21313a;
- font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
-}
-article.doc-body .code-fields ul em {
- color: #21313a;
- font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
- font-weight: 600;
-}
-.card-img {
- background: #75526b;
- background: -webkit-linear-gradient(99deg, #875A7B 10%, #62495B 90%);
- background: -moz-linear-gradient(99deg, #875A7B 10%, #62495B 90%);
- background: -ms-linear-gradient(99deg, #875A7B 10%, #62495B 90%);
- background: -o-linear-gradient(99deg, #875A7B 10%, #62495B 90%);
- background: linear-gradient(99deg, #875A7B 10%, #62495B 90%);
- position: absolute;
- top: 0;
- left: auto;
- bottom: auto;
- right: 0;
- -webkit-transform: translate3d(0, 0, 0);
- transform: translate3d(0, 0, 0);
- width: 100%;
- height: 100%;
- display: block;
- background-size: cover;
- background-position: 50%;
-}
-.card.top {
- position: relative;
- overflow: hidden;
- margin: 0;
- padding: 0 0 2%;
- -webkit-transform-origin: 50% 0px 0px;
- -moz-transform-origin: 50% 0px 0px;
- -ms-transform-origin: 50% 0px 0px;
- transform-origin: 50% 0px 0px;
-}
-@media screen and (min-width: 768px) {
- .card.top {
- padding: 12% 0 5%;
- }
-}
-@media screen and (min-width: 992px) {
- .card.top {
- padding: 10% 0 5%;
- }
-}
-@media screen and (min-width: 1200px) {
- .card.top {
- padding: 8% 0 4%;
- }
-}
-.card.top.stacked {
- background: transparent;
- -webkit-transition: background 1s;
- -o-transition: background 1s;
- transition: background 1s;
-}
-.card.top:before {
- content: "";
- display: block;
- background-image: url("img/banner_bg.png");
- background-size: cover;
- background-position: 50%;
- position: absolute;
- top: 0;
- left: auto;
- bottom: auto;
- right: 0;
- width: 100%;
- height: 100%;
-}
-.card.top .card-img {
- background-image: url("img/banner_bg.png");
-}
-.card.top .container {
- position: relative;
- font-size: 32px;
-}
-@media screen and (min-width: 768px) {
- .card.top .container:not(.o_long_title) {
- font-size: 40px;
- }
- .card.top .container.o_short_title {
- font-size: 50px;
- }
-}
-.card.top .container h1 {
- font-weight: 300;
- font-size: 1em;
- color: white;
- line-height: 0.9;
-}
-.card.top.has_banner {
- background: #282F33;
-}
-.card.top.has_banner:before {
- display: none;
-}
-.card.top.has_banner .card-img {
- opacity: 0.35;
-}
-main .alert {
- padding: 8px 15px;
- border-radius: 0;
- margin: 5px auto 15px;
- border-width: 0 0 0 3px;
- border-color: #4B9EB6;
- background-color: #eef6f8;
-}
-main .alert,
-main .alert p {
- line-height: 1.3;
- font-size: 14px;
-}
-main .alert p {
- margin-bottom: 5px;
-}
-main .alert p:last-child {
- margin-bottom: 0;
-}
-main .alert > ul {
- margin: 0.5em 0;
-}
-main .alert > ul > li {
- margin: 0;
-}
-main .alert h3.alert-title {
- font-size: 1em;
- line-height: 1em;
- margin: 0 0 5px;
- font-weight: bold;
- font-family: -apple-system, system-ui, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
- color: #438fa5;
-}
-main .alert h3.alert-title:before {
- font-family: 'Material-Design-Icons';
- content: "\e639";
- display: inline-block;
- text-rendering: geometricPrecision;
- font-size: 1em;
- -webkit-font-smoothing: antialiased;
- -moz-osx-font-smoothing: grayscale;
- -webkit-transform: translate(0, 0.1em);
- -ms-transform: translate(0, 0.1em);
- -o-transform: translate(0, 0.1em);
- transform: translate(0, 0.1em);
- margin-right: 0.2em;
-}
-main .alert.alert-info > h3.alert-title {
- display: none;
-}
-main .alert.alert-go_to {
- border-color: #875A7B;
- background-color: #f7f3f6;
- color: #78506d;
-}
-main .alert.alert-go_to > h3.alert-title {
- color: #593b51;
-}
-main .alert.alert-go_to > h3.alert-title:before {
- content: "\e70d";
-}
-main .alert.alert-success {
- border-color: #b9dfb9;
- background-color: #eef7ee;
-}
-main .alert.alert-success > h3.alert-title {
- color: #408c41;
-}
-main .alert.alert-success > h3.alert-title:before {
- content: "\e625";
-}
-main .alert.alert-warning,
-main .alert.warning {
- border-color: #fceedb;
- background-color: #fef9f3;
-}
-main .alert.alert-warning > h3.alert-title,
-main .alert.warning > h3.alert-title {
- color: #F0AD4E;
-}
-main .alert.alert-warning > h3.alert-title:before,
-main .alert.warning > h3.alert-title:before {
- content: "\e6a4";
-}
-main .alert.alert-danger {
- border-color: #f4cecd;
- background-color: #fdf7f7;
-}
-main .alert.alert-danger > h3.alert-title {
- color: #c9302c;
-}
-main .alert.alert-danger > h3.alert-title:before {
- content: "\e6a4";
-}
-main .alert.alert-exercise {
- border-color: #deddde;
- background-color: #f7f7f7;
- color: #393639;
-}
-main .alert.alert-exercise > h3.alert-title {
- color: #938E94;
-}
-main .alert.alert-exercise > h3.alert-title:before {
- -webkit-transform: translate(0, 0);
- -ms-transform: translate(0, 0);
- -o-transform: translate(0, 0);
- transform: translate(0, 0);
- top: 28px;
- content: "\e709";
-}
-@media (min-width: 1200px) {
- main .alert.doc-content {
- max-width: 55%;
- }
-}
-hr.divider {
- border-color: rgba(249, 249, 249, 0.4);
- position: absolute;
- width: 900%;
- margin-left: -13px;
-}
-img.img-responsive {
- box-shadow: 0 3px 15px #F2F2F2;
- border: 1px solid #F2F2F2;
- margin-bottom: 25px;
-}
-img.img-responsive:not(:first-child) {
- margin-top: 25px;
-}
-.figure h4 {
- margin: 0.5em 0 1.5em;
- padding-left: 1em;
- font-size: 1em;
- font-style: italic;
-}
-.pq-patch em {
- display: block;
- border-radius: 4px 4px 0 0;
- background: #F2F2F2;
- padding-left: 10px;
- font-size: 0.9em;
- font-weight: 600;
-}
-.pq-patch em + .pq-section .highlight {
- border-radius: 0 0 4px 4px;
-}
-span.menuselection {
- font-weight: 500;
-}
-.list-group-item {
- border: none;
- background: transparent;
-}
-blockquote {
- font-family: Georgia, "Times New Roman", Times, serif;
- font-weight: 600;
- font-style: italic;
-}
-blockquote footer {
- font-family: -apple-system, system-ui, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
- background: transparent;
- text-align: left;
- color: #373e42;
- font-weight: normal;
- font-style: normal;
-}
-blockquote footer cite {
- font-style: italic;
-}
-@media (min-width: 992px) {
- blockquote {
- border-left: 3px solid rgba(33, 183, 153, 0.5);
- }
-}
-.code,
-code {
- font-size: 0.8em;
- font-weight: 600;
- color: #0a352d;
- background-color: #def9f4;
-}
-.btn {
- border-radius: 0;
-}
-.table,
-table {
- font-size: 0.9em;
-}
-.code-attribute,
-.code-class,
-.code-classmethod,
-.code-data,
-.code-function,
-.code-method,
-.code-staticmethod {
- padding-left: 20px;
- margin-bottom: 2em;
-}
-.code-attribute > h6,
-.code-class > h6,
-.code-classmethod > h6,
-.code-data > h6,
-.code-function > h6,
-.code-method > h6,
-.code-staticmethod > h6 {
- margin-left: -20px;
- margin-bottom: 0.3em;
-}
-.code-attribute > h6 .viewcode-link,
-.code-class > h6 .viewcode-link,
-.code-classmethod > h6 .viewcode-link,
-.code-data > h6 .viewcode-link,
-.code-function > h6 .viewcode-link,
-.code-method > h6 .viewcode-link,
-.code-staticmethod > h6 .viewcode-link {
- display: none;
- float: right;
-}
-.code-attribute > h6:hover .viewcode-link,
-.code-class > h6:hover .viewcode-link,
-.code-classmethod > h6:hover .viewcode-link,
-.code-data > h6:hover .viewcode-link,
-.code-function > h6:hover .viewcode-link,
-.code-method > h6:hover .viewcode-link,
-.code-staticmethod > h6:hover .viewcode-link {
- display: inline;
-}
-.code-attribute p,
-.code-class p,
-.code-classmethod p,
-.code-data p,
-.code-function p,
-.code-method p,
-.code-staticmethod p {
- margin-bottom: 0.5em;
-}
-article.doc-body.index-category {
- min-height: 300px;
- min-height: 30vh;
-}
-article.doc-body.index-category li.toctree-l1 {
- padding: 5px 0;
-}
-article.doc-body .content-switcher {
- margin-top: 0;
-}
-article.doc-body .content-switcher > ul {
- font-size: 10px;
- padding: 0;
- margin: 0;
- -webkit-transition: all 0.2s ease;
- -o-transition: all 0.2s ease;
- transition: all 0.2s ease;
-}
-article.doc-body .content-switcher > ul > li {
- font-weight: 600;
- color: #dcddde;
- border-bottom: 1px solid transparent;
- margin: 0 20px 0 0;
- padding-left: 0;
- font-size: 1.3em;
- cursor: pointer;
- display: inline-block;
- list-style: none;
- -webkit-transition: all 0.2s;
- -o-transition: all 0.2s;
- transition: all 0.2s;
- opacity: 0.6;
-}
-article.doc-body .content-switcher > ul > li:before {
- content: none;
-}
-article.doc-body .content-switcher > ul > li.active {
- border-bottom: 1px solid #21b799;
- opacity: 1;
-}
-article.doc-body .content-switcher:hover > ul > li {
- opacity: 1;
- filter: alpha(opacity=100);
-}
-article.doc-body .content-switcher > .tabs > * {
- display: none;
- max-width: 100%;
- overflow-x: auto;
-}
-article.doc-body .content-switcher > .tabs > .active {
- display: block;
-}
-.highlight {
- background: #21272b;
- color: #dcddde;
- border-radius: 4px;
- margin-bottom: 11px;
-}
-.highlight pre {
- margin-bottom: 0;
-}
-pre {
- font-size: 0.8em;
- color: #dcddde;
- background: #21272b;
- font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
- font-weight: 600;
- position: relative;
- border: none;
- max-width: 100%;
- overflow: auto;
- margin: 0 0 11px;
-}
-body,
-header {
- position: relative;
-}
-.container .container {
- max-width: 100%;
- padding: 0;
- margin: 0;
-}
-.img-responsive,
-.thumbnail > img,
-.thumbnail a > img,
-.carousel-inner > .item > img,
-.carousel-inner > .item > a > img {
- display: inline-block;
-}
-.img-responsive.center-block {
- display: block;
-}
-article.doc-content *[class*="col-"] {
- padding: 0;
-}
-#wrap {
- z-index: 1;
- position: relative;
- background: #F9F9F9;
- padding-bottom: 40px;
-}
-main {
- position: relative;
- display: block;
-}
-main .o_content {
- background-color: #fff;
- box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.17);
-}
-@media (min-width: 768px) {
- main .o_content {
- margin: -40px auto 0;
- border-radius: 2px;
- }
-}
-main article.doc-body {
- position: relative;
- min-height: 1px;
- padding-right: 15px;
- padding-left: 15px;
- float: left;
- width: 100%;
- padding: 15px;
-}
-@media (min-width: 768px) {
- main article.doc-body {
- padding: 15px 30px;
- }
-}
-@media (min-width: 992px) {
- main article.doc-body {
- max-width: 700px;
- }
-}
-@media (min-width: 1200px) {
- main article.doc-body {
- margin-left: 7%;
- margin-top: 20px;
- }
-}
-main article.doc-body > * {
- max-width: 100%;
-}
-main.o_aside_removed,
-main.o_slim_page {
- max-width: 700px;
-}
-@media (min-width: 1200px) {
- main.o_aside_removed,
- main.o_slim_page {
- max-width: 760px;
- }
-}
-@media (min-width: 992px) {
- main.o_aside_removed article.doc-body,
- main.o_slim_page article.doc-body {
- padding-left: 30px;
- }
-}
-main.has_code_col {
- max-width: 700px;
-}
-@media (min-width: 1200px) {
- main.has_code_col {
- max-width: 1170px;
- }
-}
-main.has_code_col .doc-aside,
-main.has_code_col .doc-content {
- position: relative;
- min-height: 1px;
- padding-right: 15px;
- padding-left: 15px;
- float: left;
- width: 100%;
-}
-@media (max-width: 1199px) {
- main.has_code_col .doc-aside,
- main.has_code_col .doc-content {
- padding: 0;
- }
-}
-main.has_code_col aside {
- display: none;
-}
-main.has_code_col article.doc-body > section {
- max-width: 100%;
-}
-@media (min-width: 1200px) {
- main.has_code_col article.doc-body {
- width: 100%;
- max-width: none;
- margin: 0;
- }
- main.has_code_col article.doc-body:before {
- content: "";
- background: #21272b;
- -webkit-box-shadow: inset 40px 0 40px -18px rgba(22, 24, 29, 0.3);
- box-shadow: inset 40px 0 40px -18px rgba(22, 24, 29, 0.3);
- position: absolute;
- top: 0;
- left: auto;
- bottom: auto;
- right: 0;
- width: 50%;
- height: 100%;
- }
- main.has_code_col article.doc-body > section {
- position: relative;
- display: block;
- float: left;
- width: 100%;
- }
- main.has_code_col article.doc-body > section > * {
- width: 48%;
- float: left;
- clear: left;
- }
- main.has_code_col article.doc-body > section > h2,
- main.has_code_col article.doc-body > section > h3,
- main.has_code_col article.doc-body > section > h4,
- main.has_code_col article.doc-body > section > h5,
- main.has_code_col article.doc-body > section > h6,
- main.has_code_col article.doc-body > section > h1 {
- width: 48%;
- float: none;
- clear: none;
- }
- main.has_code_col article.doc-body > section .doc-aside {
- width: 49%;
- float: none;
- clear: none;
- margin-left: 51%;
- color: #dcddde;
- font-size: 14px;
- line-height: 1.45;
- }
- main.has_code_col article.doc-body > section .doc-aside pre {
- font-size: 12px;
- }
-}
-article.doc-toc .toctree-wrapper > ul > li > span {
- display: block;
- font-size: 28px;
-}
-@media screen and (min-width: 992px) {
- #wrap.index > .card.top {
- padding: 10% 0 2%;
- }
-}
-#wrap.index > main.index {
- margin: 10px auto;
-}
-#wrap.index > main.index .o_content {
- box-shadow: none;
- background: none;
-}
-main.index .toc-section h2 {
- padding: 0 0 4px;
- border-bottom: 1px solid #F2F2F2;
- margin: 1.4em 0 0.8em;
- font-size: 16px;
- font-family: -apple-system, system-ui, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
- letter-spacing: 0;
- font-weight: bold;
- color: #888888;
-}
-main.index .card {
- border-radius: 4px;
- position: relative;
- overflow: hidden;
- margin-bottom: 25px;
- padding-top: 56%;
- background-color: #fff;
- box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.17);
-}
-main.index .card .card-img span {
- display: block;
- background-size: cover;
- background-position: 50%;
- width: 100%;
- height: 100%;
-}
-main.index .card figcaption {
- color: #373e42;
- box-shadow: inset 0 1px 0 #F2F2F2;
- font-weight: bold;
- line-height: 1.2;
- font-size: 14px;
- background-color: white;
- padding: 8px 12px 6px;
- position: absolute;
- top: 0;
- left: -1px;
- bottom: auto;
- right: -1px;
-}
-@media screen and (min-width: 992px) {
- main.index .toc-single-entry .card figcaption {
- font-size: 1.5em;
- padding: 20px 15px;
- }
-}
-.toctree-wrapper > ul {
- list-style: none;
- padding: 0;
-}
-.toctree-wrapper > ul li {
- line-height: 1.4;
-}
-.toctree-wrapper > ul li.toctree-l1,
-.toctree-wrapper > ul li.toctree-l3 {
- padding-left: 0;
-}
-.toctree-wrapper > ul li.toctree-l1:before,
-.toctree-wrapper > ul li.toctree-l3:before {
- content: none;
-}
-.toctree-wrapper > ul li.toctree-l1:first-child,
-.toctree-wrapper > ul li.toctree-l3:first-child {
- margin-top: 0;
-}
-.toctree-wrapper > ul li.toctree-l1 {
- margin: 0 0 15px;
-}
-.toctree-wrapper > ul li.toctree-l1 > span {
- font-size: 21px;
-}
-.toctree-wrapper > ul li.toctree-l2 > span {
- font-weight: 500;
-}
-.toctree-wrapper > ul li.toctree-l2 > ul {
- margin: 0 0 15px;
-}
-.toctree-wrapper > ul li.toctree-l2 > ul:empty {
- display: none;
-}
-#oe_main_menu_navbar ~ #wrapwrap .o_main_header.o_has_sub_nav.o_scrolled {
- top: -17px;
-}
-.o_main_header {
- position: fixed;
- width: 100%;
- height: 50px;
- z-index: 2;
- background-color: rgba(255, 255, 255, 0.6);
- color: #2b3134;
- font-family: "Work Sans", sans-serif;
- font-size: 12px;
- -webkit-transition: all 0.2s ease;
- -o-transition: all 0.2s ease;
- transition: all 0.2s ease;
- -webkit-transition-property: background, box-shadow;
- transition-property: background, box-shadow;
- -webkit-transform: translate3d(auto, auto, 0);
- transform: translate3d(auto, auto, 0);
-}
-.o_main_header a:focus,
-.o_main_header a:active,
-.o_main_header a:focus:active {
- outline: none;
-}
-.o_main_header .btn-primary {
- color: white!important;
- font-size: inherit!important;
- font-weight: 700;
- text-transform: uppercase;
-}
-.o_main_header > .o_main_header_main {
- margin-right: auto;
- margin-left: auto;
- padding-left: 15px;
- padding-right: 15px;
- height: 100%;
-}
-@media (min-width: 768px) {
- .o_main_header > .o_main_header_main {
- width: 750px;
- }
-}
-@media (min-width: 992px) {
- .o_main_header > .o_main_header_main {
- width: 970px;
- }
-}
-@media (min-width: 1200px) {
- .o_main_header > .o_main_header_main {
- width: 1170px;
- }
-}
-.o_main_header > .o_main_header_main > .navbar-header,
-.o_main_header > .o_main_header_main > .navbar-collapse {
- margin-right: -15px;
- margin-left: -15px;
-}
-@media (min-width: 768px) {
- .o_main_header > .o_main_header_main > .navbar-header,
- .o_main_header > .o_main_header_main > .navbar-collapse {
- margin-right: 0;
- margin-left: 0;
- }
-}
-.o_main_header > .o_main_header_main a {
- color: inherit;
-}
-.o_main_header > .o_main_header_main a:hover,
-.o_main_header > .o_main_header_main a:focus {
- color: #273239;
-}
-.o_main_header > .o_main_header_main .o_logo {
- margin: 15px 0;
- width: 63px;
- height: 20px;
- background-size: cover;
-}
-.o_main_header > .o_main_header_main > .o_primary_nav {
- margin: 0 auto;
- padding: 0;
- text-align: center;
- white-space: nowrap;
-}
-@media (min-width: 768px) {
- .o_main_header > .o_main_header_main > .o_primary_nav {
- height: 100%;
- }
- .o_main_header > .o_main_header_main > .o_primary_nav:before {
- content: "";
- background: transparent;
- z-index: -1;
- visibility: hidden;
- box-shadow: 0 1px 0 transparent;
- width: 100%;
- height: 50px;
- position: absolute;
- top: 0;
- left: auto;
- bottom: auto;
- right: 0;
- -webkit-transition: background 500ms cubic-bezier(0.55, 0, 0.1, 1) 0ms, visibility 0ms linear 500ms, box-shadow 500ms linear 0ms;
- -o-transition: background 500ms cubic-bezier(0.55, 0, 0.1, 1) 0ms, visibility 0ms linear 500ms, box-shadow 500ms linear 0ms;
- transition: background 500ms cubic-bezier(0.55, 0, 0.1, 1) 0ms, visibility 0ms linear 500ms, box-shadow 500ms linear 0ms;
- }
- .o_main_header > .o_main_header_main > .o_primary_nav.o_sub_opened:before {
- visibility: visible;
- background: #FCFCFC;
- box-shadow: 0 1px 0 #F2F2F2;
- -webkit-transition: background 500ms cubic-bezier(0.55, 0, 0.1, 1) 0ms, visibility 0ms linear 0s, box-shadow 500ms linear 0ms;
- -o-transition: background 500ms cubic-bezier(0.55, 0, 0.1, 1) 0ms, visibility 0ms linear 0s, box-shadow 500ms linear 0ms;
- transition: background 500ms cubic-bezier(0.55, 0, 0.1, 1) 0ms, visibility 0ms linear 0s, box-shadow 500ms linear 0ms;
- }
-}
-.o_main_header > .o_main_header_main > .o_primary_nav .dropdown {
- position: static;
-}
-.o_main_header > .o_main_header_main > .o_primary_nav .dropdown > a {
- position: relative;
- -webkit-backface-visibility: hidden;
- -moz-backface-visibility: hidden;
- backface-visibility: hidden;
-}
-.o_main_header > .o_main_header_main > .o_primary_nav .dropdown > a::before,
-.o_main_header > .o_main_header_main > .o_primary_nav .dropdown > a::after {
- content: "";
- display: block;
- position: absolute;
- top: 50%;
- left: auto;
- bottom: auto;
- right: 0;
- -ms-transform-origin: 50% 50% 0;
- -webkit-transform-origin: 50% 50% 0;
- -moz-transform-origin: 50% 50% 0;
- transform-origin: 50% 50% 0;
- -webkit-transition: all 300ms ease 0s;
- -moz-transition: all 300ms ease 0s;
- -o-transition: all 300ms ease 0s;
- transition: all 300ms ease 0s;
- width: 10px;
- height: 1px;
- background-color: #21313a;
- box-shadow: 0 1px 1px rgba(33, 49, 58, 0.1);
-}
-.o_main_header > .o_main_header_main > .o_primary_nav .dropdown > a::before {
- -webkit-transform: rotate(45deg);
- -ms-transform: rotate(45deg);
- -o-transform: rotate(45deg);
- transform: rotate(45deg);
- right: 6.07106781px;
-}
-.o_main_header > .o_main_header_main > .o_primary_nav .dropdown > a::after {
- -webkit-transform: rotate(-45deg);
- -ms-transform: rotate(-45deg);
- -o-transform: rotate(-45deg);
- transform: rotate(-45deg);
-}
-.o_main_header > .o_main_header_main > .o_primary_nav .dropdown.open > a {
- color: #9E588B !important;
- font-weight: 600;
-}
-.o_main_header > .o_main_header_main > .o_primary_nav .dropdown.open > a::before,
-.o_main_header > .o_main_header_main > .o_primary_nav .dropdown.open > a::after {
- background-color: #9E588B !important;
- box-shadow: 0 1px 1px rgba(158, 88, 139, 0.1);
- right: 3.53553391px;
-}
-.o_main_header > .o_main_header_main > .o_primary_nav .dropdown.open > a::before {
- -webkit-transform: rotate(-45deg);
- -ms-transform: rotate(-45deg);
- -o-transform: rotate(-45deg);
- transform: rotate(-45deg);
-}
-.o_main_header > .o_main_header_main > .o_primary_nav .dropdown.open > a::after {
- -webkit-transform: rotate(45deg);
- -ms-transform: rotate(45deg);
- -o-transform: rotate(45deg);
- transform: rotate(45deg);
-}
-.o_main_header > .o_main_header_main > .o_primary_nav .dropdown > .dropdown-menu {
- border: none;
- border-radius: 0;
- margin: 0;
-}
-.o_main_header > .o_main_header_main > .o_primary_nav > li {
- display: inline-block;
-}
-.o_main_header > .o_main_header_main > .o_primary_nav > li > a {
- height: 100%;
- line-height: 50px;
-}
-.o_main_header > .o_main_header_main > .o_primary_nav > li > a:not(.btn) {
- display: inline-block;
- padding: 0 20px;
- font-weight: 600;
- text-transform: uppercase;
-}
-@media screen and (min-width: 768px) and (max-width: 991px) {
- .o_main_header > .o_main_header_main > .o_primary_nav > li > a:not(.btn) {
- font-size: 11px;
- }
- .o_main_header > .o_main_header_main > .o_primary_nav > li > a:not(.btn):not(.dropdown-toggle) {
- padding: 0 10px;
- }
-}
-.o_main_header > .o_main_header_main > .o_primary_nav > li.dropdown > a {
- margin-right: 20px;
-}
-@media (min-width: 768px) {
- .o_main_header > .o_main_header_main > .o_primary_nav > li.open > .o_secondary_nav {
- visibility: visible;
- background-color: white;
- -webkit-transform: translate(0, 0);
- -ms-transform: translate(0, 0);
- -o-transform: translate(0, 0);
- transform: translate(0, 0);
- -webkit-transition: transform 500ms cubic-bezier(0.55, 0, 0.1, 1) 0ms, visibility 0ms linear 0ms, background-color 0ms linear 500ms;
- -o-transition: transform 500ms cubic-bezier(0.55, 0, 0.1, 1) 0ms, visibility 0ms linear 0ms, background-color 0ms linear 500ms;
- transition: transform 500ms cubic-bezier(0.55, 0, 0.1, 1) 0ms, visibility 0ms linear 0ms, background-color 0ms linear 500ms;
- }
- .o_main_header > .o_main_header_main > .o_primary_nav > li.open > .o_secondary_nav .container > .row > div {
- opacity: 1;
- -webkit-transform: translate(0, 0);
- -ms-transform: translate(0, 0);
- -o-transform: translate(0, 0);
- transform: translate(0, 0);
- }
- .o_main_header > .o_main_header_main > .o_primary_nav > li.open > .o_secondary_nav .container > .row > div:nth-child(1) {
- -webkit-transition-delay: 100ms;
- transition-delay: 100ms;
- }
- .o_main_header > .o_main_header_main > .o_primary_nav > li.open > .o_secondary_nav .container > .row > div:nth-child(2) {
- -webkit-transition-delay: 200ms;
- transition-delay: 200ms;
- }
- .o_main_header > .o_main_header_main > .o_primary_nav > li.open > .o_secondary_nav .container > .row > div:nth-child(3) {
- -webkit-transition-delay: 300ms;
- transition-delay: 300ms;
- }
- .o_main_header > .o_main_header_main > .o_primary_nav > li.open > .o_secondary_nav .container > .row > div:nth-child(4) {
- -webkit-transition-delay: 400ms;
- transition-delay: 400ms;
- }
- .o_main_header > .o_main_header_main > .o_primary_nav > li.open > .o_secondary_nav .o_store_link {
- max-height: 50px;
- -webkit-transition: max-height 500ms cubic-bezier(0.55, 0, 0.1, 1) 300ms;
- -moz-transition: max-height 500ms cubic-bezier(0.55, 0, 0.1, 1) 300ms;
- -o-transition: max-height 500ms cubic-bezier(0.55, 0, 0.1, 1) 300ms;
- transition: max-height 500ms cubic-bezier(0.55, 0, 0.1, 1) 300ms;
- }
- .o_main_header > .o_main_header_main > .o_primary_nav > li.open > .o_secondary_nav::before {
- opacity: 0.5;
- }
-}
-.o_main_header > .o_main_header_main > .o_primary_nav .o_secondary_nav {
- width: 100%;
- padding: 15px 0 65px;
- box-shadow: 0 3px 6px rgba(0, 0, 0, 0.05);
-}
-@media (min-width: 992px) {
- .o_main_header > .o_main_header_main > .o_primary_nav .o_secondary_nav > .container > .row {
- margin-left: -45px;
- margin-right: -45px;
- }
- .o_main_header > .o_main_header_main > .o_primary_nav .o_secondary_nav > .container > .row > div {
- padding-left: 45px;
- padding-right: 45px;
- }
-}
-.o_main_header > .o_main_header_main > .o_primary_nav .o_secondary_nav > .container > .row > div {
- font-size: 16px;
- overflow: hidden;
-}
-@media (min-width: 768px) {
- .o_main_header > .o_main_header_main > .o_primary_nav .o_secondary_nav > .container > .row > div {
- height: 340px;
- padding-top: 10px;
- }
- .o_main_header > .o_main_header_main > .o_primary_nav .o_secondary_nav > .container > .row > div + div {
- border-left: 1px solid #F2F2F2;
- }
-}
-.o_main_header > .o_main_header_main > .o_primary_nav .o_secondary_nav > .container > .row > div ul {
- position: relative;
- list-style: none;
- padding: 0;
-}
-.o_main_header > .o_main_header_main > .o_primary_nav .o_secondary_nav > .container > .row > div ul > li {
- height: 30px;
- -webkit-transition: all 300ms cubic-bezier(0.55, 0, 0.1, 1) 100ms;
- -moz-transition: all 300ms cubic-bezier(0.55, 0, 0.1, 1) 100ms;
- -o-transition: all 300ms cubic-bezier(0.55, 0, 0.1, 1) 100ms;
- transition: all 300ms cubic-bezier(0.55, 0, 0.1, 1) 100ms;
- -webkit-transition-property: height, opacity;
- transition-property: height, opacity;
-}
-.o_main_header > .o_main_header_main > .o_primary_nav .o_secondary_nav > .container > .row > div ul > li > a {
- display: block;
- height: 100%;
- line-height: 30px;
- font-weight: 500;
- font-size: 1.4rem;
-}
-.o_main_header > .o_main_header_main > .o_primary_nav .o_secondary_nav > .container > .row > div ul > li.dropdown:not(.open) > a::before,
-.o_main_header > .o_main_header_main > .o_primary_nav .o_secondary_nav > .container > .row > div ul > li.dropdown:not(.open) > a::after {
- -ms-transform-origin: 8px 50% 0;
- -webkit-transform-origin: 8px 50% 0;
- -moz-transform-origin: 8px 50% 0;
- transform-origin: 8px 50% 0;
- width: 8px;
- right: 0;
-}
-.o_main_header > .o_main_header_main > .o_primary_nav .o_secondary_nav > .container > .row > div ul > li.dropdown > ul {
- position: absolute;
- top: 30px;
- left: 0;
- bottom: 0;
- right: 0;
- -webkit-transform: translate(100%, 0);
- -ms-transform: translate(100%, 0);
- -o-transform: translate(100%, 0);
- transform: translate(100%, 0);
- opacity: 0;
- filter: alpha(opacity=0);
- -webkit-transition: all 300ms cubic-bezier(0.55, 0, 0.1, 1) 0;
- -moz-transition: all 300ms cubic-bezier(0.55, 0, 0.1, 1) 0;
- -o-transition: all 300ms cubic-bezier(0.55, 0, 0.1, 1) 0;
- transition: all 300ms cubic-bezier(0.55, 0, 0.1, 1) 0;
-}
-.o_main_header > .o_main_header_main > .o_primary_nav .o_secondary_nav > .container > .row > div ul > li.dropdown.open > ul {
- -webkit-transform: translate(0, 0);
- -ms-transform: translate(0, 0);
- -o-transform: translate(0, 0);
- transform: translate(0, 0);
- opacity: 1;
- filter: alpha(opacity=100);
- -webkit-transition: all 300ms cubic-bezier(0.55, 0, 0.1, 1) 100ms;
- -moz-transition: all 300ms cubic-bezier(0.55, 0, 0.1, 1) 100ms;
- -o-transition: all 300ms cubic-bezier(0.55, 0, 0.1, 1) 100ms;
- transition: all 300ms cubic-bezier(0.55, 0, 0.1, 1) 100ms;
-}
-.o_main_header > .o_main_header_main > .o_primary_nav .o_secondary_nav > .container > .row > div ul.o_sub_opened > li:not(.open) {
- opacity: 0;
- height: 0 !important;
- overflow: hidden;
- -webkit-transition: all 300ms cubic-bezier(0.55, 0, 0.1, 1) 0;
- -moz-transition: all 300ms cubic-bezier(0.55, 0, 0.1, 1) 0;
- -o-transition: all 300ms cubic-bezier(0.55, 0, 0.1, 1) 0;
- transition: all 300ms cubic-bezier(0.55, 0, 0.1, 1) 0;
-}
-.o_main_header > .o_main_header_main > .o_primary_nav .o_secondary_nav > .container > .row > div .o_nav_app_family {
- text-align: center;
- font-weight: 500;
- line-height: 2;
- pointer-events: none;
- cursor: default;
-}
-.o_main_header > .o_main_header_main > .o_primary_nav .o_secondary_nav > .container > .row > div .o_nav_app_family::selection,
-.o_main_header > .o_main_header_main > .o_primary_nav .o_secondary_nav > .container > .row > div .o_nav_app_family *::selection {
- background: transparent;
-}
-.o_main_header > .o_main_header_main > .o_primary_nav .o_secondary_nav > .container > .row > div .o_nav_app_family::-moz-selection,
-.o_main_header > .o_main_header_main > .o_primary_nav .o_secondary_nav > .container > .row > div .o_nav_app_family *::-moz-selection {
- background: transparent;
-}
-.o_main_header > .o_main_header_main > .o_primary_nav .o_secondary_nav > .container > .row > div .o_nav_app_family > span {
- background-image: url("img/apps_families_s.png");
- background-position: 0px 50%;
- background-repeat: no-repeat;
- display: none;
-}
-@media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min--moz-device-pixel-ratio: 2), only screen and (-o-min-device-pixel-ratio: 2), only screen and (min-device-pixel-ratio: 2), only screen and (min-resolution: 192dpi), only screen and (min-resolution: 2dppx) {
- .o_main_header > .o_main_header_main > .o_primary_nav .o_secondary_nav > .container > .row > div .o_nav_app_family > span {
- background-image: url("img/2x_apps_families_s.png");
- }
-}
-@media (min-width: 768px) {
- .o_main_header > .o_main_header_main > .o_primary_nav .o_secondary_nav > .container > .row > div .o_nav_app_family > span {
- display: block;
- margin: 0 auto;
- background-size: auto 100%;
- width: 51px;
- height: 50px;
- }
- .o_main_header > .o_main_header_main > .o_primary_nav .o_secondary_nav > .container > .row > div .o_nav_app_family > div {
- font-size: 0.7em;
- font-weight: 500;
- line-height: 1.5;
- color: #373e42;
- margin-bottom: 1.3em;
- }
-}
-@media (min-width: 768px) {
- .o_main_header > .o_main_header_main > .o_primary_nav .o_secondary_nav > .container > .row > div.o_website_apps a:hover,
- .o_main_header > .o_main_header_main > .o_primary_nav .o_secondary_nav > .container > .row > div.o_website_apps a:focus,
- .o_main_header > .o_main_header_main > .o_primary_nav .o_secondary_nav > .container > .row > div.o_website_apps .o_nav_app_family {
- color: #5B899E;
- }
- .o_main_header > .o_main_header_main > .o_primary_nav .o_secondary_nav > .container > .row > div.o_sale_apps a:hover,
- .o_main_header > .o_main_header_main > .o_primary_nav .o_secondary_nav > .container > .row > div.o_sale_apps a:focus,
- .o_main_header > .o_main_header_main > .o_primary_nav .o_secondary_nav > .container > .row > div.o_sale_apps .o_nav_app_family {
- color: #E46F78;
- }
- .o_main_header > .o_main_header_main > .o_primary_nav .o_secondary_nav > .container > .row > div.o_sale_apps .o_nav_app_family > span {
- background-position: -60px 50%;
- }
- .o_main_header > .o_main_header_main > .o_primary_nav .o_secondary_nav > .container > .row > div.o_operation_apps a:hover,
- .o_main_header > .o_main_header_main > .o_primary_nav .o_secondary_nav > .container > .row > div.o_operation_apps a:focus,
- .o_main_header > .o_main_header_main > .o_primary_nav .o_secondary_nav > .container > .row > div.o_operation_apps .o_nav_app_family {
- color: #5C5B80;
- }
- .o_main_header > .o_main_header_main > .o_primary_nav .o_secondary_nav > .container > .row > div.o_operation_apps .o_nav_app_family > span {
- background-position: -120px 50%;
- }
- .o_main_header > .o_main_header_main > .o_primary_nav .o_secondary_nav > .container > .row > div.o_productivity_apps a:hover,
- .o_main_header > .o_main_header_main > .o_primary_nav .o_secondary_nav > .container > .row > div.o_productivity_apps a:focus,
- .o_main_header > .o_main_header_main > .o_primary_nav .o_secondary_nav > .container > .row > div.o_productivity_apps .o_nav_app_family {
- color: #D5653E;
- }
- .o_main_header > .o_main_header_main > .o_primary_nav .o_secondary_nav > .container > .row > div.o_productivity_apps .o_nav_app_family > span {
- background-position: -181px 50%;
- }
-}
-.o_main_header > .o_main_header_main > .o_primary_nav .o_secondary_nav > .o_store_link {
- position: absolute;
- top: auto;
- left: 0;
- bottom: 0;
- right: 0;
- overflow: hidden;
- display: block;
- height: 50px;
- line-height: 50px;
- border-top: 1px solid #F2F2F2;
- text-align: center;
- font-size: 12px;
- font-weight: 600;
-}
-@media (min-width: 768px) {
- .o_main_header > .o_main_header_main > .o_primary_nav .o_secondary_nav {
- display: block;
- background-color: #FCFCFC;
- visibility: hidden;
- z-index: -2;
- -webkit-transform: translate(0, -115%);
- -ms-transform: translate(0, -115%);
- -o-transform: translate(0, -115%);
- transform: translate(0, -115%);
- -webkit-transition: transform 333.3333333333333ms cubic-bezier(0.55, 0, 0.1, 1) 0ms, visibility 0ms linear 333.3333333333333ms, background-color 0ms linear 0ms;
- -o-transition: transform 333.3333333333333ms cubic-bezier(0.55, 0, 0.1, 1) 0ms, visibility 0ms linear 333.3333333333333ms, background-color 0ms linear 0ms;
- transition: transform 333.3333333333333ms cubic-bezier(0.55, 0, 0.1, 1) 0ms, visibility 0ms linear 333.3333333333333ms, background-color 0ms linear 0ms;
- }
- .o_main_header > .o_main_header_main > .o_primary_nav .o_secondary_nav .container > .row > div {
- opacity: 0;
- -webkit-transform: translate(0, -30%);
- -ms-transform: translate(0, -30%);
- -o-transform: translate(0, -30%);
- transform: translate(0, -30%);
- -webkit-transition: all 500ms cubic-bezier(0.55, 0, 0.1, 1) 0ms;
- -moz-transition: all 500ms cubic-bezier(0.55, 0, 0.1, 1) 0ms;
- -o-transition: all 500ms cubic-bezier(0.55, 0, 0.1, 1) 0ms;
- transition: all 500ms cubic-bezier(0.55, 0, 0.1, 1) 0ms;
- }
- .o_main_header > .o_main_header_main > .o_primary_nav .o_secondary_nav .o_store_link {
- max-height: 0;
- -webkit-transition: max-height 250ms cubic-bezier(0.55, 0, 0.1, 1) 0s;
- -moz-transition: max-height 250ms cubic-bezier(0.55, 0, 0.1, 1) 0s;
- -o-transition: max-height 250ms cubic-bezier(0.55, 0, 0.1, 1) 0s;
- transition: max-height 250ms cubic-bezier(0.55, 0, 0.1, 1) 0s;
- }
- .o_main_header > .o_main_header_main > .o_primary_nav .o_secondary_nav::before {
- content: "";
- position: absolute;
- top: 100%;
- left: 0;
- bottom: -1000px;
- right: 0;
- display: block;
- background-color: #000;
- opacity: 0;
- -webkit-transition: opacity 500ms cubic-bezier(0.55, 0, 0.1, 1) 0s;
- -moz-transition: opacity 500ms cubic-bezier(0.55, 0, 0.1, 1) 0s;
- -o-transition: opacity 500ms cubic-bezier(0.55, 0, 0.1, 1) 0s;
- transition: opacity 500ms cubic-bezier(0.55, 0, 0.1, 1) 0s;
- }
-}
-.o_main_header > .o_main_header_main .o_header_buttons {
- height: 100%;
- line-height: 50px;
- float: right;
-}
-.o_main_header > .o_main_header_main .o_header_buttons > * {
- display: inline-block;
- float: left;
-}
-.o_main_header > .o_main_header_main .o_header_buttons a:not(.btn) {
- display: inline-block;
- padding: 0 20px;
- font-weight: 600;
- text-transform: uppercase;
-}
-@media screen and (min-width: 768px) and (max-width: 991px) {
- .o_main_header > .o_main_header_main .o_header_buttons a:not(.btn) {
- font-size: 11px;
- }
- .o_main_header > .o_main_header_main .o_header_buttons a:not(.btn):not(.dropdown-toggle) {
- padding: 0 10px;
- }
-}
-.o_main_header > .o_main_header_main .o_header_buttons a.dropdown-toggle {
- padding: 0 10px;
-}
-.o_main_header > .o_main_header_main .o_header_buttons a.o_my_cart {
- padding: 0;
-}
-.o_main_header > .o_main_header_main .o_header_buttons a.o_my_cart .my_cart_quantity {
- font-family: sans-serif;
- border-radius: 100%;
- font-weight: bold;
- font-size: 90%;
- padding: 4px 0;
- min-width: 19px;
- text-align: center;
- display: inline-block;
-}
-.o_main_header > .o_main_header_main .o_header_buttons .btn-primary {
- margin-top: 9px;
-}
-.o_main_header > .o_main_header_main .o_header_buttons > .dropdown {
- margin: 0 5px;
-}
-@media screen and (min-width: 992px) {
- .o_main_header > .o_main_header_main .o_header_buttons > .dropdown {
- margin: 0 15px;
- }
-}
-.o_main_header > .o_main_header_main .o_header_buttons > .dropdown,
-.o_main_header > .o_main_header_main .o_header_buttons > .dropdown .dropdown-toggle {
- height: 100%;
-}
-.o_main_header > .o_main_header_main .o_header_buttons > .dropdown > .dropdown-menu {
- left: auto;
- right: 0;
-}
-.o_main_header > .o_main_header_main .o_header_buttons > .dropdown > .dropdown-menu li a {
- padding-top: 5px;
- padding-bottom: 5px;
- color: #373e42;
-}
-.o_main_header > .o_sub_nav {
- min-height: 40px;
- border: 1px solid rgba(0, 0, 0, 0.05);
- border-width: 1px 0;
- background-color: rgba(255, 255, 255, 0.8);
-}
-.o_main_header > .o_sub_nav > .container .navbar-header {
- height: 38px;
- line-height: 38px;
- font-weight: 600;
- color: #373e42;
- overflow: hidden;
-}
-.o_main_header > .o_sub_nav > .container .navbar-header .o_app_name_logo,
-.o_main_header > .o_sub_nav > .container .navbar-header .o_app_name_title {
- -webkit-transform: translate(-61px, 0);
- -ms-transform: translate(-61px, 0);
- -o-transform: translate(-61px, 0);
- transform: translate(-61px, 0);
- -webkit-transition: transform 400ms ease 0s;
- -moz-transition: transform 400ms ease 0s;
- -o-transition: transform 400ms ease 0s;
- transition: transform 400ms ease 0s;
-}
-.o_main_header > .o_sub_nav > .container .navbar-header:hover {
- color: #21313a;
-}
-.o_main_header > .o_sub_nav > .container .navbar-header .o_app_name_logo {
- background-image: url("img/logos/odoo_logo.png");
- background-image: url("img/logos/odoo_logo.svg");
- background-position: 0 0;
- background-repeat: no-repeat;
- display: inline-block;
- width: 94.05px;
- height: 30px;
- background-size: auto 30px;
- width: 47.025px;
- height: 15px;
- background-size: auto 15px;
- vertical-align: middle;
- margin: auto 5px 3px 0;
-}
-.o_main_header > .o_sub_nav > .container .navbar-header .o_app_name_logo.center-block,
-.o_main_header > .o_sub_nav > .container .navbar-header .o_app_name_logo.o_logo_responsive_half {
- position: relative;
- margin-left: auto;
- margin-right: auto;
- display: block;
-}
-.o_main_header > .o_sub_nav > .container .navbar-header .o_app_name_logo.o_logo_responsive {
- background-size: cover;
- width: 100%;
- height: 0;
- padding-bottom: 31.9%;
-}
-.o_main_header > .o_sub_nav > .container .navbar-header .o_app_name_logo.o_logo_responsive_half {
- background-size: cover;
- width: 50%;
- height: 0;
- padding-bottom: 15.94%;
-}
-.o_main_header > .o_sub_nav > .container .navbar-header .o_app_name_title {
- color: inherit;
- vertical-align: middle;
- display: inline-block;
-}
-.o_main_header > .o_sub_nav > .container .navbar-header .o_app_name_title span {
- margin-right: 5px;
-}
-.o_main_header > .o_sub_nav > .container .nav {
- margin-right: -15px;
-}
-.o_main_header > .o_sub_nav > .container .nav > li {
- margin-left: 20px;
- height: 38px;
- line-height: 38px;
-}
-.o_main_header > .o_sub_nav > .container .nav > li > a {
- height: 100%;
- line-height: 38px;
- padding: 0;
- font-size: 12px;
- font-weight: 500;
- color: #373e42;
-}
-.o_main_header > .o_sub_nav > .container .nav > li > a:hover,
-.o_main_header > .o_sub_nav > .container .nav > li > a:focus {
- color: #21313a;
- background-color: transparent;
-}
-.o_main_header > .o_sub_nav > .container .nav > li.active > a {
- color: #21313a;
- font-weight: 600;
-}
-.o_main_header > .o_sub_nav > .container .call-to-action {
- line-height: 36px;
- overflow: hidden;
- width: 100%;
- max-width: 0px;
- transform-origin: 0 0;
- -webkit-transition: max-width 0.3s ease 0ms;
- -o-transition: max-width 0.3s ease 0ms;
- transition: max-width 0.3s ease 0ms;
-}
-.o_main_header > .o_sub_nav > .container .call-to-action > a {
- margin-left: 35px;
- font-weight: 600;
- padding: 4px 12px;
- line-height: 1.4em;
- font-size: 12px!important;
-}
-.o_main_header.o_inverted:not(.o_scrolled) > .o_sub_nav {
- -webkit-transition: 0.3s background-color;
- -o-transition: 0.3s background-color;
- transition: 0.3s background-color;
- background-color: rgba(255, 255, 255, 0.05);
- border-color: rgba(255, 255, 255, 0.1);
-}
-.o_main_header.o_inverted:not(.o_scrolled) > .o_sub_nav .nav > li > a,
-.o_main_header.o_inverted:not(.o_scrolled) > .o_sub_nav .o_app_name_title {
- color: rgba(255, 255, 255, 0.9);
-}
-.o_main_header.o_inverted:not(.o_scrolled) > .o_sub_nav .nav > li > a:hover,
-.o_main_header.o_inverted:not(.o_scrolled) > .o_sub_nav .o_app_name_title:hover,
-.o_main_header.o_inverted:not(.o_scrolled) > .o_sub_nav .nav > li > a:focus,
-.o_main_header.o_inverted:not(.o_scrolled) > .o_sub_nav .o_app_name_title:focus {
- color: white;
-}
-@media (min-width: 768px) {
- .o_main_header.o_has_sub_nav {
- position: absolute;
- }
- .o_main_header.o_has_sub_nav.o_scrolled {
- position: fixed;
- top: -51px;
- }
- .o_main_header.o_inverted {
- background-color: transparent;
- color: white;
- }
- .o_main_header.o_inverted a:hover,
- .o_main_header.o_inverted a:focus {
- color: inherit;
- }
- .o_main_header.o_inverted .o_logo {
- background-position: 100% 0;
- }
- .o_main_header.o_inverted .o_logo.o_logo_15.center-block {
- background-position: 102% 0;
- }
- .o_main_header.o_inverted .o_main_header_main > .o_primary_nav > li.dropdown > a::before,
- .o_main_header.o_inverted .o_main_header_main > .o_primary_nav > li.dropdown > a::after {
- background-color: white;
- box-shadow: 0 1px 1px rgba(255, 255, 255, 0.1);
- }
- .o_main_header > .o_main_header_main > .o_header_buttons .dropdown.open {
- background-color: #FCFCFC;
- color: #2b3134;
- }
- .o_main_header > .o_main_header_main > .o_header_buttons .dropdown.open .dropdown-menu {
- background-color: #FCFCFC;
- margin-top: 0;
- border: none;
- border-radius: 0;
- box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.17);
- text-align: left;
- min-width: 100%;
- padding-bottom: 12.5px;
- }
- .o_main_header > .o_main_header_main > .o_header_buttons .dropdown.open .dropdown-menu > li > a {
- display: block;
- color: #2b3134;
- float: none;
- text-transform: none;
- font-weight: normal;
- }
-}
-.o_main_header.o_scrolled:not(.o_transparent_blocked),
-.o_main_header.o_sub_opened {
- background-color: #FCFCFC;
- color: #2b3134;
- box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.17);
-}
-.o_main_header.o_scrolled:not(.o_transparent_blocked) .o_logo,
-.o_main_header.o_sub_opened .o_logo {
- background-position: 0 0;
-}
-.o_main_header.o_scrolled:not(.o_transparent_blocked) > .o_main_header_main > .o_primary_nav > li.dropdown > a::before,
-.o_main_header.o_sub_opened > .o_main_header_main > .o_primary_nav > li.dropdown > a::before,
-.o_main_header.o_scrolled:not(.o_transparent_blocked) > .o_main_header_main > .o_primary_nav > li.dropdown > a::after,
-.o_main_header.o_sub_opened > .o_main_header_main > .o_primary_nav > li.dropdown > a::after {
- background-color: #2b3134;
- box-shadow: 0 1px 1px rgba(43, 49, 52, 0.1);
-}
-.o_main_header.o_scrolled .o_sub_nav {
- background: #FCFCFC;
-}
-.o_main_header.o_scrolled .o_sub_nav > .container .navbar-header > span {
- -webkit-transform: translate(0, 0);
- -ms-transform: translate(0, 0);
- -o-transform: translate(0, 0);
- transform: translate(0, 0);
-}
-.o_main_header.o_scrolled .o_sub_nav > .container .call-to-action {
- max-width: 133px;
-}
-.o_main_header.o_sub_opened .o_sub_nav {
- display: none;
-}
-@media (max-width: 767px) {
- .o_main_header {
- position: relative;
- height: auto;
- min-height: 50px;
- background-color: #FCFCFC;
- color: #2b3134;
- box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.17);
- }
- .o_main_header .o_logo {
- background-position: 0 0;
- }
- .o_main_header > .o_main_header_main > .o_primary_nav > li.dropdown > a::before,
- .o_main_header > .o_main_header_main > .o_primary_nav > li.dropdown > a::after {
- background-color: #2b3134;
- box-shadow: 0 1px 1px rgba(43, 49, 52, 0.1);
- }
- .o_main_header > .o_main_header_main {
- position: relative;
- }
- .o_main_header > .o_main_header_main > .o_primary_nav,
- .o_main_header > .o_main_header_main .o_header_buttons {
- display: none;
- }
- .o_main_header > .o_main_header_main > .o_mobile_menu_toggle {
- position: absolute;
- top: 0;
- left: auto;
- bottom: auto;
- right: 0;
- width: 50px;
- line-height: 50px;
- font-size: 16.66666667px;
- text-align: center;
- }
- .o_main_header > .o_sub_nav {
- display: none;
- }
- .o_main_header.o_mobile_menu_opened > .o_main_header_main {
- margin: 0;
- }
- .o_main_header.o_mobile_menu_opened > .o_main_header_main > .o_header_buttons {
- float: none;
- background-color: #25252D;
- padding: 0 15px;
- box-sizing: content-box;
- margin: 50px -15px 0;
- display: block;
- text-align: center;
- width: 100%;
- height: auto;
- }
- .o_main_header.o_mobile_menu_opened > .o_main_header_main > .o_header_buttons > * {
- overflow: visible!important;
- color: #FCFCFC;
- float: none;
- display: inline;
- }
- .o_main_header.o_mobile_menu_opened > .o_main_header_main > .o_header_buttons > * > a:not(.btn) {
- display: initial!important;
- }
- .o_main_header.o_mobile_menu_opened > .o_main_header_main > .o_header_buttons > * .dropdown-toggle {
- color: #FCFCFC !important;
- }
- .o_main_header.o_mobile_menu_opened > .o_main_header_main > .o_header_buttons > * .dropdown-menu {
- position: relative;
- line-height: 2;
- background: rgba(255, 255, 255, 0.05);
- width: 100%;
- margin: 0 -15px 0;
- box-sizing: content-box;
- padding: 5px 15px;
- }
- .o_main_header.o_mobile_menu_opened > .o_main_header_main > .o_header_buttons > * .dropdown-menu > li > a {
- float: none;
- display: block;
- margin-bottom: 5px;
- padding: 10px;
- color: #FCFCFC !important;
- font-size: 0.8em;
- }
- .o_main_header.o_mobile_menu_opened > .o_main_header_main > .o_header_buttons > * .dropdown-menu > li > a:hover {
- background: rgba(255, 255, 255, 0.05);
- }
- .o_main_header.o_mobile_menu_opened > .o_main_header_main > .o_primary_nav {
- display: block;
- background-color: #25252D;
- color: white;
- margin: 0 -15px 0;
- padding: 0;
- float: none;
- white-space: normal;
- }
- .o_main_header.o_mobile_menu_opened > .o_main_header_main > .o_primary_nav a:hover,
- .o_main_header.o_mobile_menu_opened > .o_main_header_main > .o_primary_nav a:focus,
- .o_main_header.o_mobile_menu_opened > .o_main_header_main > .o_primary_nav a:active {
- color: white;
- }
- .o_main_header.o_mobile_menu_opened > .o_main_header_main > .o_primary_nav li {
- border: 0 solid #33343D;
- border-width: 1px 5px 0;
- }
- .o_main_header.o_mobile_menu_opened > .o_main_header_main > .o_primary_nav > li {
- width: 100%;
- padding: 0 15px;
- }
- .o_main_header.o_mobile_menu_opened > .o_main_header_main > .o_primary_nav > li.dropdown {
- padding: 0;
- }
- .o_main_header.o_mobile_menu_opened > .o_main_header_main > .o_primary_nav > li.dropdown > a {
- display: none;
- }
- .o_main_header.o_mobile_menu_opened > .o_main_header_main > .o_primary_nav > li.dropdown > .dropdown-menu {
- position: static;
- display: block;
- background-color: transparent;
- box-shadow: none;
- }
- .o_main_header.o_mobile_menu_opened > .o_main_header_main > .o_primary_nav > li.dropdown > .o_secondary_nav {
- padding: 0;
- }
- .o_main_header.o_mobile_menu_opened > .o_main_header_main > .o_primary_nav > li.dropdown > .o_secondary_nav > .container > .row > div {
- padding: 0;
- }
- .o_main_header.o_mobile_menu_opened > .o_main_header_main > .o_primary_nav > li.dropdown > .o_secondary_nav > .container > .row > div ul {
- list-style-type: none;
- }
- .o_main_header.o_mobile_menu_opened > .o_main_header_main > .o_primary_nav > li.dropdown > .o_secondary_nav > .container > .row > div ul > li {
- height: 50px;
- padding: 0 15px;
- border-width: 1px 0 0;
- }
- .o_main_header.o_mobile_menu_opened > .o_main_header_main > .o_primary_nav > li.dropdown > .o_secondary_nav > .container > .row > div ul > li > a {
- line-height: 50px;
- }
- .o_main_header.o_mobile_menu_opened > .o_main_header_main > .o_primary_nav > li.dropdown > .o_secondary_nav > .container > .row > div ul > li.dropdown.open {
- height: auto;
- border: none;
- }
- .o_main_header.o_mobile_menu_opened > .o_main_header_main > .o_primary_nav > li.dropdown > .o_secondary_nav > .container > .row > div ul > li.dropdown.open > ul {
- position: static;
- }
- .o_main_header.o_mobile_menu_opened > .o_main_header_main > .o_primary_nav > li.dropdown > .o_secondary_nav > .container > .row > div > .o_nav_app_family {
- height: 50px;
- line-height: 50px;
- background-color: #33343D;
- }
- .o_main_header.o_mobile_menu_opened > .o_main_header_main > .o_primary_nav > li.dropdown > .o_secondary_nav > .container > .row > div > .o_nav_app_family > * {
- display: none;
- }
- .o_main_header.o_mobile_menu_opened > .o_main_header_main > .o_primary_nav > li.dropdown > .o_secondary_nav > .container > .row > div > .o_nav_app_family::after {
- content: "(Apps)";
- }
- .o_main_header.o_mobile_menu_opened > .o_main_header_main > .o_primary_nav > li.dropdown > .o_secondary_nav > .o_store_link {
- position: relative;
- border: 0 solid #33343D;
- border-width: 14px 0 0;
- padding-top: 14px;
- line-height: 1.5;
- height: 60px;
- }
- .o_main_header.o_mobile_menu_opened > .o_main_header_main > .o_primary_nav > li.dropdown::after {
- content: "";
- display: inline-block;
- width: 100%;
- height: 20px;
- margin-bottom: -5px;
- background-color: #33343D;
- }
-}
-body > footer {
- font-size: 14px;
- position: relative;
- width: 100%;
- height: auto;
- min-height: 300px;
- background-color: #282F33;
- color: #888888;
- z-index: 1;
-}
-@media screen and (min-width: 992px) {
- body > footer.o_footer_effect {
- position: absolute;
- top: auto;
- left: 0;
- bottom: 0;
- right: 0;
- position: fixed;
- z-index: 0;
- }
-}
-body > footer .o_footer_logo {
- margin-bottom: 3em;
- margin-top: 3em;
-}
-body > footer a {
- color: #dcddde;
-}
-body > footer a:hover,
-body > footer a:active,
-body > footer a:focus {
- color: white;
-}
-body > footer .dropdown-menu a {
- color: #6B6D70;
-}
-body > footer .dropdown-menu a:hover,
-body > footer .dropdown-menu a:focus {
- color: #5f6063;
-}
-body > footer .dropdown-menu a:active {
- color: #fff;
-}
-body > footer .divider {
- margin: 10px 0;
-}
-body > footer ul,
-body > footer ol {
- list-style: none;
- padding-left: 0;
-}
-body > footer span.menu_title {
- font-weight: 600;
- color: white;
-}
-body > footer span.menu_title + ul {
- margin-top: 10px;
-}
-body > footer .o_language_selector,
-body > footer .o_country_selector {
- display: inline-block;
- opacity: 0.8;
- filter: alpha(opacity=80);
-}
-body > footer .o_language_selector a,
-body > footer .o_country_selector a {
- font-size: 0.9em;
- font-weight: bold;
-}
-body > footer .o_language_selector img,
-body > footer .o_country_selector img {
- max-height: 20px;
- margin-right: 10px;
- vertical-align: bottom;
-}
-body > footer .o_language_selector:hover,
-body > footer .o_country_selector:hover {
- opacity: 1;
- filter: alpha(opacity=100);
-}
-body > footer .o_country_selector {
- float: right;
-}
-body > footer hr {
- border-top-color: #3e4950;
-}
-body > footer .o_footer_bottom {
- background-color: #21272b;
- color: #dcddde;
- padding: 1em 0;
- margin-top: 3em;
-}
-body > footer .o_footer_bottom a {
- opacity: 0.6;
- filter: alpha(opacity=60);
-}
-body > footer .o_footer_bottom a:hover {
- opacity: 1;
- filter: alpha(opacity=100);
-}
-body > footer .o_footer_bottom .social-links .fa {
- margin-left: 20px;
-}
-aside {
- position: relative;
- min-height: 1px;
- padding-right: 15px;
- padding-left: 15px;
- float: left;
- width: 100%;
- max-width: 240px;
- position: static;
- padding: 0;
- display: block;
- border-right: 1px solid #F2F2F2;
-}
-@media (max-width: 992px) {
- aside {
- display: none;
- }
-}
-.navbar-aside {
- position: relative;
- overflow: hidden;
- font-family: -apple-system, system-ui, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
- font-size: 0.85em;
- line-height: 1.5;
- overflow-y: auto;
-}
-.navbar-aside.affix {
- z-index: 2;
- top: 39px;
- position: fixed;
- backface-visibility: hidden;
-}
-@media (max-width: 992px) {
- .navbar-aside.affix {
- display: none;
- }
-}
-.navbar-aside > ul.list-group {
- margin: 0;
- z-index: 0;
-}
-.navbar-aside > h3 {
- margin: 0;
- padding: 15px 0 10px;
- text-transform: uppercase;
- font-weight: 600;
- font-size: 16px;
- color: #373e42;
- overflow-x: hidden;
- position: relative;
- z-index: 1;
- -webkit-box-shadow: 0 10px 9px -10px #d2d2d2;
- box-shadow: 0 10px 9px -10px #d2d2d2;
-}
-.navbar-aside .gith-container {
- margin: 0;
- z-index: 1;
- position: relative;
- overflow-x: hidden;
-}
-.navbar-aside .gith-container .gith-link {
- color: #373e42;
- text-decoration: none;
- display: inline-block;
- position: relative;
- margin: 10px 0;
- font-family: -apple-system, system-ui, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
-}
-.navbar-aside .gith-container .gith-link:hover {
- color: #21313a;
- text-decoration: none;
-}
-.navbar-aside .gith-container .gith-link:before {
- width: 1em;
- height: 1em;
- content: '';
- position: relative;
- background-image: url('img/github-square_32.png');
- background-size: 100%;
- display: inline-block;
- vertical-align: middle;
- -webkit-transform: translate(0, -1px);
- -ms-transform: translate(0, -1px);
- -o-transform: translate(0, -1px);
- transform: translate(0, -1px);
-}
-.navbar-aside ul {
- padding: 0;
- position: relative;
- margin-bottom: 0 !important;
-}
-.navbar-aside ul li {
- padding: 0;
- margin-bottom: 0;
-}
-.navbar-aside ul li:first-child,
-.navbar-aside ul li:last-child {
- border-radius: 0;
-}
-.navbar-aside ul li:first-child {
- overflow: hidden;
- border-radius: 2px 0 0 0;
-}
-.navbar-aside ul li > a {
- display: block;
- padding: 5px 15px;
- color: #373e42;
- line-height: 1.2;
-}
-.navbar-aside ul li > a:focus,
-.navbar-aside ul li > a:hover {
- color: #21313a;
-}
-.navbar-aside ul li.parent > a:after {
- content: '\e7c1';
- font-family: 'Material-Design-Icons';
- opacity: 0.8;
- margin-top: -6px;
- position: absolute;
- top: 50%;
- left: auto;
- bottom: auto;
- right: 10px;
- -webkit-transform: rotate(90deg);
- -ms-transform: rotate(90deg);
- -o-transform: rotate(90deg);
- transform: rotate(90deg);
- -webkit-transition: transform 0.2s;
- -o-transition: transform 0.2s;
- transition: transform 0.2s;
-}
-.navbar-aside ul li.parent.active > a:after {
- -webkit-transform: rotate(0);
- -ms-transform: rotate(0);
- -o-transform: rotate(0);
- transform: rotate(0);
-}
-.navbar-aside ul ul {
- max-height: 0;
- background-color: rgba(220, 221, 222, 0.2);
- padding: 0px;
- overflow: hidden;
- margin-left: 0;
- box-shadow: inset 0 3px 5px -2px #dcddde;
- -webkit-transition: max-height 0.3s cubic-bezier(0.55, 0, 0.1, 1);
- -o-transition: max-height 0.3s cubic-bezier(0.55, 0, 0.1, 1);
- transition: max-height 0.3s cubic-bezier(0.55, 0, 0.1, 1);
-}
-.navbar-aside ul ul > li:not(:last-child) {
- box-shadow: 0 1px 0 rgba(0, 0, 0, 0.04);
-}
-.navbar-aside ul ul > li:not(:last-child).active > ul > li:not(:first-child) {
- border-top: 1px solid #F2F2F2;
-}
-.navbar-aside li.active,
-.navbar-aside li.active:focus,
-.navbar-aside li.active:hover {
- border-color: #F2F2F2;
- background: transparent;
-}
-.navbar-aside li.active > a,
-.navbar-aside li.active:focus > a,
-.navbar-aside li.active:hover > a {
- font-weight: bold;
- color: #21313a;
-}
-.navbar-aside li.active > ul {
- max-height: 1000px;
-}
-.navbar-aside > ul > li {
- background: white;
- border-bottom: 1px solid rgba(0, 0, 0, 0.08);
-}
-.navbar-aside > ul > li > a {
- padding: 10px 15px;
- border-left: 3px solid transparent;
-}
-.navbar-aside > ul > li:focus > a,
-.navbar-aside > ul > li:hover > a {
- border-left: 3px solid #dcddde;
- background-color: transparent;
-}
-.navbar-aside > ul > li.active > a,
-.navbar-aside > ul > li.active:focus > a,
-.navbar-aside > ul > li.active:hover > a {
- border-left: 3px solid #21b799;
-}
-.navbar-aside > ul > li.active.parent + li {
- box-shadow: 0 -3px 5px -4px rgba(40, 47, 51, 0.4);
-}
-.navbar-aside > ul > li > ul > li > a {
- padding-left: 20px;
-}
-.navbar-aside > ul > li > ul > li > ul > li > a {
- padding-left: 30px;
-}
-.navbar-aside > ul > li > ul > li > ul > li > ul > li > a {
- padding-left: 40px;
-}
-.floating_action_container {
- position: fixed;
- right: 8px;
- bottom: 8px;
- width: auto;
- z-index: 800;
-}
-@media (min-width: 992px) {
- .floating_action_container {
- display: none;
- }
-}
-#floating_action {
- width: 56px;
- height: 56px;
- display: inline-block;
- z-index: 0;
- background-color: transparent;
- border-radius: 50%;
- padding: 16px;
- box-shadow: 0 8px 17px 0 rgba(0, 0, 0, 0.1), 0 6px 20px 0 rgba(0, 0, 0, 0.05);
- background-color: #21b799;
- -webkit-transition: transform 500ms cubic-bezier(0.55, 0, 0.1, 1);
- -o-transition: transform 500ms cubic-bezier(0.55, 0, 0.1, 1);
- transition: transform 500ms cubic-bezier(0.55, 0, 0.1, 1);
-}
-#floating_action i {
- color: white;
-}
-#floating_action.active {
- -webkit-transform: translateZ(0px) rotateZ(-180deg);
- -moz-transform: translateZ(0px) rotateZ(-180deg);
- -ms-transform: translateZ(0px) rotateZ(-180deg);
- -o-transform: translateZ(0px) rotateZ(-180deg);
- transform: translateZ(0px) rotateZ(-180deg);
-}
-#floating_action_menu {
- position: absolute;
- top: auto;
- left: auto;
- bottom: 0;
- right: 0;
- z-index: 1;
- overflow: hidden;
- width: 380px;
- padding: 0;
- display: block;
- border-radius: 2px;
- visibility: hidden;
- -webkit-transition: all 0.5s;
- -o-transition: all 0.5s;
- transition: all 0.5s;
- -webkit-box-shadow: 0 0 0 transparent;
- box-shadow: 0 0 0 transparent;
-}
-#floating_action_menu .content {
- margin: 0;
- opacity: 0;
-}
-#floating_action_menu .content li {
- border: none;
- border-top: 1px solid #DDD;
-}
-#floating_action_menu .content li:first-child {
- border-top: none;
-}
-#floating_action_menu .content a {
- display: inline-block;
- cursor: pointer;
- color: #21313a;
- text-decoration: none;
- float: left;
- width: 100%;
- padding: 5px 10px;
-}
-#floating_action_menu .bubble {
- position: absolute;
- top: auto;
- left: auto;
- bottom: 28px;
- right: 28px;
- width: 1px;
- height: 1px;
- background: #21b799;
- content: '';
- color: #fff;
- border-radius: 50%;
- -webkit-transition: all 300ms cubic-bezier(0.55, 0, 0.1, 1);
- -o-transition: all 300ms cubic-bezier(0.55, 0, 0.1, 1);
- transition: all 300ms cubic-bezier(0.55, 0, 0.1, 1);
-}
-#floating_action_menu:before {
- position: absolute;
- top: auto;
- left: auto;
- bottom: 28px;
- right: 28px;
- width: 1px;
- height: 1px;
- background: #21b799;
- content: '';
- color: #fff;
- border-radius: 50%;
- -webkit-transition: all 300ms cubic-bezier(0.55, 0, 0.1, 1);
- -o-transition: all 300ms cubic-bezier(0.55, 0, 0.1, 1);
- transition: all 300ms cubic-bezier(0.55, 0, 0.1, 1);
- background: white;
-}
-#floating_action_menu.active {
- display: block;
- visibility: visible;
- -webkit-transition: all 500ms cubic-bezier(0.55, 0, 0.1, 1);
- -o-transition: all 500ms cubic-bezier(0.55, 0, 0.1, 1);
- transition: all 500ms cubic-bezier(0.55, 0, 0.1, 1);
-}
-#floating_action_menu.active:before,
-#floating_action_menu.active .bubble {
- width: 1000px;
- height: 2000px;
- border-radius: 50%;
- opacity: 0;
- margin-right: -500px;
- margin-bottom: -500px;
- display: block;
- -webkit-transition: all 0.4s cubic-bezier(0.55, 0, 0.1, 1);
- -o-transition: all 0.4s cubic-bezier(0.55, 0, 0.1, 1);
- transition: all 0.4s cubic-bezier(0.55, 0, 0.1, 1);
-}
-#floating_action_menu.active:before {
- opacity: 1;
- filter: alpha(opacity=100);
-}
-#floating_action_menu.active .content {
- position: relative;
- z-index: 1;
- opacity: 1;
- filter: alpha(opacity=100);
- -webkit-transition: all 500ms cubic-bezier(0.4, 0, 0.2, 1);
- -o-transition: all 500ms cubic-bezier(0.4, 0, 0.2, 1);
- transition: all 500ms cubic-bezier(0.4, 0, 0.2, 1);
-}
-#mask {
- opacity: 0;
- filter: alpha(opacity=0);
- position: fixed;
- z-index: 700;
- top: 0;
- left: 0;
- width: 100%;
- height: 0;
- background-color: rgba(0, 0, 0, 0.2);
- -webkit-transition: opacity 0.3s;
- -o-transition: opacity 0.3s;
- transition: opacity 0.3s;
-}
-#mask.active {
- opacity: 1;
- filter: alpha(opacity=100);
- display: block;
- width: 100%;
- height: 100%;
- -webkit-transition: opacity 0.3s;
- -o-transition: opacity 0.3s;
- transition: opacity 0.3s;
-}
-@media print {
- body header,
- body footer {
- display: none;
- }
- body #main_navbar {
- position: relative;
- display: block;
- height: 100px!important;
- }
- body #main_navbar #main-back {
- display: none;
- }
- body #main_navbar #main_title {
- position: relative;
- transform: none;
- }
- body #main_navbar .navbar-main {
- display: none!important;
- }
- body main {
- opacity: 1;
- filter: alpha(opacity=100);
- -webkit-animation: none;
- -o-animation: none;
- animation: none;
- }
- body main aside {
- display: none;
- }
- body main article h1,
- body main article .h1 {
- font-size: 2em;
- }
- body main article h2,
- body main article .h2 {
- font-size: 1.64285714em;
- }
- body main article h3,
- body main article .h3 {
- font-size: 1.25em;
- }
- body main article p,
- body main article ul,
- body main article ol,
- body main article table,
- body main article blockquote,
- body main article .alert,
- body main article .doc-code,
- body main article .admonition {
- margin-top: inherit;
- margin-bottom: inherit;
- font-size: inherit;
- }
- body .floating_action_container {
- display: none;
- }
-}
-.o_main_header.o_mobile_menu_opened .mdi-navigation-menu {
- background-color: #282F33;
- color: #F2F2F2;
-}
-.o_main_header > .o_sub_nav #o_sub-menu #searchbox {
- display: flex;
- align-items: center;
- justify-content: center;
-}
-.o_main_header > .o_sub_nav #o_sub-menu #searchbox > form {
- display: flex;
- flex-grow: 1;
-}
-.o_main_header > .o_sub_nav #o_sub-menu #searchbox > form > .form-control {
- border-radius: 0;
-}
-@media screen and (min-width: 768px) {
- .o_main_header > .o_sub_nav #o_sub-menu .o_breadcrumb {
- background-color: transparent;
- padding: 0;
- margin: 0 0 0 -15px;
- height: 38px;
- line-height: 38px;
- }
-}
-.o_main_header > .o_sub_nav #o_sub-menu .o_breadcrumb > li {
- display: block;
-}
-.o_main_header > .o_sub_nav #o_sub-menu .o_breadcrumb > li,
-.o_main_header > .o_sub_nav #o_sub-menu .o_breadcrumb > li > a {
- height: 30px;
- line-height: 2;
-}
-.o_main_header > .o_sub_nav #o_sub-menu .o_breadcrumb > li:before {
- font-weight: 700;
- float: left;
- padding: 0;
- margin-right: -1px;
- display: none;
-}
-@media screen and (min-width: 768px) {
- .o_main_header > .o_sub_nav #o_sub-menu .o_breadcrumb > li {
- margin-left: 0;
- margin-right: -1px;
- height: 38px;
- line-height: 38px;
- display: inline-block;
- }
- .o_main_header > .o_sub_nav #o_sub-menu .o_breadcrumb > li:before {
- display: block;
- }
- .o_main_header > .o_sub_nav #o_sub-menu .o_breadcrumb > li > a {
- padding: 0;
- height: 38px;
- line-height: 40px;
- letter-spacing: -0.1px;
- word-spacing: -1px;
- display: inline-block;
- height: 100%;
- max-width: 80px;
- overflow: hidden;
- white-space: nowrap;
- text-overflow: ellipsis;
- }
- .o_main_header > .o_sub_nav #o_sub-menu .o_breadcrumb > li:last-child > a {
- max-width: 170px;
- }
-}
-@media screen and (min-width: 1980px) {
- .o_main_header > .o_sub_nav #o_sub-menu .o_breadcrumb > li > a {
- max-width: 120px;
- }
-}
-@media screen and (min-width: 1200px) {
- .o_main_header > .o_sub_nav #o_sub-menu .o_breadcrumb > li:last-child > a {
- max-width: none;
- }
-}
-@media screen and (max-width: 767px) {
- .o_main_header > .o_sub_nav #o_sub-menu .o_breadcrumb > li > a {
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
- }
- .o_main_header > .o_sub_nav #o_sub-menu .o_breadcrumb > li > a:before {
- content: "|";
- margin-right: 0.5em;
- }
- .o_main_header > .o_sub_nav #o_sub-menu .o_breadcrumb > li:nth-child(1) > a:before {
- display: none;
- }
- .o_main_header > .o_sub_nav #o_sub-menu .o_breadcrumb > li:nth-child(2) > a:before {
- padding-left: 0.5em;
- }
- .o_main_header > .o_sub_nav #o_sub-menu .o_breadcrumb > li:nth-child(3) > a:before {
- padding-left: 1em;
- }
-}
-@media screen and (max-width: 767px) {
- .o_main_header.index > .o_sub_nav #o_sub-menu .o_breadcrumb {
- display: none;
- }
-}
-.o_main_header > .o_sub_nav {
- border-radius: 0;
-}
-.o_main_header > .o_sub_nav .navbar-toggle {
- padding: 0 15px;
- margin: 0;
- height: 38px;
- background-color: #F2F2F2;
-}
-.o_main_header > .o_sub_nav .navbar-toggle span {
- line-height: 38px;
-}
-.o_main_header > .o_sub_nav .navbar-toggle.collapsed {
- background-color: #FCFCFC;
-}
-.o_main_header > .o_sub_nav .collapse .nav {
- margin-right: 0;
- margin-bottom: 0;
-}
-.o_main_header > .o_sub_nav .collapse .nav:first-of-type {
- margin-right: -15px;
-}
-.o_main_header > .o_sub_nav .collapse .nav > li {
- margin: 0;
-}
-.o_main_header > .o_sub_nav .collapse .nav > li > a {
- padding: 0 0 0 10px;
-}
-.o_main_header > .o_sub_nav .collapse .nav > li.divider {
- height: auto;
- line-height: 1;
- border-bottom: 1px solid #dcddde;
- padding: 4px 0px 5px;
-}
-.o_main_header > .o_sub_nav .collapse .nav > li.dropdown > a.dropdown-toggle {
- padding: 0 5px 0 10px;
-}
-.o_main_header > .o_sub_nav .collapse .nav > li.dropdown > a.dropdown-toggle:after {
- font-family: 'Material-Design-Icons';
- content: "\e7c1";
- display: inline-block;
- text-rendering: geometricPrecision;
- font-size: 1em;
- -webkit-font-smoothing: antialiased;
- -moz-osx-font-smoothing: grayscale;
-}
-@media screen and (max-width: 767px) {
- .o_main_header > .o_sub_nav .collapse .nav > li.dropdown > a.dropdown-toggle:after {
- font-size: 1.5em;
- }
-}
-.o_main_header > .o_sub_nav .collapse .nav > li.dropdown.open {
- z-index: 1;
- position: relative;
- background-color: #dcddde;
- color: #2b3134;
-}
-@media screen and (min-width: 768px) {
- .o_main_header > .o_sub_nav .collapse .nav > li.dropdown.open {
- background-color: #FCFCFC;
- }
-}
-.o_main_header > .o_sub_nav .collapse .nav > li.dropdown.open .dropdown-toggle {
- color: #2b3134;
-}
-.o_main_header > .o_sub_nav .collapse .nav > li.dropdown.open .dropdown-toggle:hover {
- color: #21313a;
-}
-.o_main_header > .o_sub_nav .collapse .nav > li.dropdown.open .dropdown-menu {
- margin-top: 0;
- border: none;
- border-radius: 0;
- text-align: left;
- min-width: 100%;
- background-color: #FCFCFC;
- padding-bottom: 12.5px;
- box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.17);
-}
-.o_main_header > .o_sub_nav .collapse .nav > li.dropdown.open .dropdown-menu > li > a {
- font-size: 12px;
- display: block;
- color: #2b3134;
- float: none;
- text-transform: none;
- font-weight: 500;
-}
-@media screen and (max-width: 767px) {
- .o_main_header > .o_sub_nav .collapse .nav > li.dropdown.open .dropdown-menu > li > a {
- padding-left: 10px;
- }
-}
-.o_main_header > .o_sub_nav .collapse .nav > li.dropdown.open .dropdown-menu > li.active > a {
- color: white;
- background-color: #4c8c7f;
-}
-@media screen and (max-width: 767px) {
- .o_main_header > .o_sub_nav .collapse .nav > li.dropdown.open .dropdown-menu {
- position: static;
- }
-}
-@media screen and (min-width: 768px) {
- .o_main_header > .o_sub_nav .collapse .nav > li.dropdown.open .dropdown-menu {
- background-color: #FCFCFC;
- }
-}
-.o_main_header > .o_sub_nav .collapse .nav > li.dropdown.o_dropdown_mobile_nav {
- margin-left: 0;
-}
-.o_main_header > .o_sub_nav .collapse .nav > li.dropdown.o_dropdown_mobile_nav > .dropdown-toggle:after {
- position: absolute;
- top: 0;
- left: auto;
- bottom: auto;
- right: 0;
-}
-.o_main_header > .o_sub_nav .collapse .nav > li.dropdown.o_dropdown_mobile_nav .o_breadcrumb_dropdown_menu > li > a {
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
-}
-.o_main_header > .o_sub_nav .collapse .nav > li.dropdown.o_dropdown_mobile_nav .o_breadcrumb_dropdown_menu > li > a:before {
- content: "|";
- margin-right: 0.5em;
-}
-.o_main_header > .o_sub_nav .collapse .nav > li.dropdown.o_dropdown_mobile_nav .o_breadcrumb_dropdown_menu > li:nth-child(1) > a:before {
- display: none;
-}
-.o_main_header > .o_sub_nav .collapse .nav > li.dropdown.o_dropdown_mobile_nav .o_breadcrumb_dropdown_menu > li:nth-child(2) > a:before {
- padding-left: 0.5em;
-}
-.o_main_header > .o_sub_nav .collapse .nav > li.dropdown.o_dropdown_mobile_nav .o_breadcrumb_dropdown_menu > li:nth-child(3) > a:before {
- padding-left: 1em;
-}
-@media screen and (min-width: 768px) and (max-width: 991px) {
- .o_main_header > .o_sub_nav > .container > .collapse > .nav > li > a,
- .o_main_header > .o_sub_nav > .container .o_breadcrumb > li > a {
- font-size: 10px;
- font-weight: 600;
- }
-}
-.o_main_header > .o_sub_nav li.dropdown > a.dropdown-toggle {
- padding: 0 5px 0 10px;
-}
-.o_main_header > .o_sub_nav li.dropdown > a.dropdown-toggle:after {
- font-family: 'Material-Design-Icons';
- content: "\e7c1";
- display: inline-block;
- text-rendering: geometricPrecision;
- font-size: 1em;
- -webkit-font-smoothing: antialiased;
- -moz-osx-font-smoothing: grayscale;
-}
-@media screen and (max-width: 767px) {
- .o_main_header > .o_sub_nav li.dropdown > a.dropdown-toggle:after {
- font-size: 1.5em;
- }
-}
-.o_main_header > .o_sub_nav li.dropdown.open {
- z-index: 1;
- position: relative;
- background-color: #dcddde;
- color: #2b3134;
-}
-@media screen and (min-width: 768px) {
- .o_main_header > .o_sub_nav li.dropdown.open {
- background-color: #FCFCFC;
- }
-}
-.o_main_header > .o_sub_nav li.dropdown.open .dropdown-toggle {
- color: #2b3134;
-}
-.o_main_header > .o_sub_nav li.dropdown.open .dropdown-toggle:hover {
- color: #21313a;
-}
-.o_main_header > .o_sub_nav li.dropdown.open .dropdown-menu {
- margin-top: 0;
- border: none;
- border-radius: 0;
- text-align: left;
- min-width: 100%;
- background-color: #FCFCFC;
- padding-bottom: 12.5px;
- box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.17);
-}
-.o_main_header > .o_sub_nav li.dropdown.open .dropdown-menu > li > a {
- font-size: 12px;
- display: block;
- color: #2b3134;
- float: none;
- text-transform: none;
- font-weight: 500;
-}
-@media screen and (max-width: 767px) {
- .o_main_header > .o_sub_nav li.dropdown.open .dropdown-menu > li > a {
- padding-left: 10px;
- }
-}
-.o_main_header > .o_sub_nav li.dropdown.open .dropdown-menu > li.active > a {
- color: white;
- background-color: #4c8c7f;
-}
-@media screen and (max-width: 767px) {
- .o_main_header > .o_sub_nav li.dropdown.open .dropdown-menu {
- position: static;
- }
-}
-@media screen and (min-width: 768px) {
- .o_main_header > .o_sub_nav li.dropdown.open .dropdown-menu {
- background-color: #FCFCFC;
- }
-}
-.o_main_header > .o_sub_nav li.dropdown.o_dropdown_mobile_nav {
- margin-left: 0;
-}
-.o_main_header > .o_sub_nav li.dropdown.o_dropdown_mobile_nav > .dropdown-toggle:after {
- position: absolute;
- top: 0;
- left: auto;
- bottom: auto;
- right: 0;
-}
-.o_main_header > .o_sub_nav li.dropdown.o_dropdown_mobile_nav .o_breadcrumb_dropdown_menu > li > a {
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
-}
-.o_main_header > .o_sub_nav li.dropdown.o_dropdown_mobile_nav .o_breadcrumb_dropdown_menu > li > a:before {
- content: "|";
- margin-right: 0.5em;
-}
-.o_main_header > .o_sub_nav li.dropdown.o_dropdown_mobile_nav .o_breadcrumb_dropdown_menu > li:nth-child(1) > a:before {
- display: none;
-}
-.o_main_header > .o_sub_nav li.dropdown.o_dropdown_mobile_nav .o_breadcrumb_dropdown_menu > li:nth-child(2) > a:before {
- padding-left: 0.5em;
-}
-.o_main_header > .o_sub_nav li.dropdown.o_dropdown_mobile_nav .o_breadcrumb_dropdown_menu > li:nth-child(3) > a:before {
- padding-left: 1em;
-}
-@media (max-width: 767px) {
- .o_main_header.o_inverted:not(.o_scrolled) .o_sub_nav {
- display: block;
- margin-bottom: 0;
- }
- .o_main_header.o_inverted:not(.o_scrolled) .o_sub_nav .nav {
- margin: 0 0 0 -8px;
- }
- .o_main_header.o_inverted:not(.o_scrolled) .o_sub_nav .nav > li > a {
- color: #373e42;
- }
- .o_main_header.o_inverted:not(.o_scrolled) .o_sub_nav .nav > li > a:hover,
- .o_main_header.o_inverted:not(.o_scrolled) .o_sub_nav .nav > li > a:focus {
- color: #2b3134;
- }
-}
-.o_main_header.o_inverted:not(.o_scrolled) .o_sub_nav_actions {
- margin-left: 10px;
-}
-.o_main_header.o_inverted:not(.o_scrolled) .o_sub_nav_actions > li {
- background: rgba(249, 249, 249, 0.1);
- margin-right: 1px;
-}
-.o_main_header.o_inverted:not(.o_scrolled) .o_sub_nav_actions > li:last-child {
- margin-right: 0;
-}
-.o_main_header.o_scrolled .o_sub_nav #o_doc_title {
- opacity: 1;
- filter: alpha(opacity=100);
- -webkit-transform: translate(0, 0);
- -ms-transform: translate(0, 0);
- -o-transform: translate(0, 0);
- transform: translate(0, 0);
- -webkit-transition: opacity 1s, transform 0.3s;
- -o-transition: opacity 1s, transform 0.3s;
- transition: opacity 1s, transform 0.3s;
-}
-.o_main_header.o_scrolled .o_sub_nav .o_sub_nav_actions {
- margin-left: 10px;
-}
-.o_main_header.o_scrolled .o_sub_nav .o_sub_nav_actions:first-of-type {
- margin-right: -25px;
-}
-.o_main_header.o_scrolled .o_sub_nav .o_sub_nav_actions > li {
- background: rgba(136, 136, 136, 0.1);
- margin-right: 1px;
-}
-.o_main_header.o_scrolled .o_sub_nav .o_sub_nav_actions > li:last-child {
- margin-right: 0;
-}
-#thinking-modular > .clearfix.themes,
-#thinking-modular > .dl-horizontal dd.themes,
-#thinking-modular > .container.themes,
-#thinking-modular > .container-fluid.themes,
-#thinking-modular > .row.themes,
-#thinking-modular > .form-horizontal .form-group.themes,
-#thinking-modular > .btn-toolbar.themes,
-#thinking-modular > .btn-group-vertical > .btn-group.themes,
-#thinking-modular > .nav.themes,
-#thinking-modular > .navbar.themes,
-#thinking-modular > .navbar-header.themes,
-#thinking-modular > .navbar-collapse.themes,
-#thinking-modular > .pager.themes,
-#thinking-modular > .panel-body.themes,
-#thinking-modular > .modal-header.themes,
-#thinking-modular > .modal-footer.themes,
-#thinking-modular > .o_main_header > .o_main_header_main.themes {
- margin-bottom: 3em;
-}
diff --git a/doc/_extensions/odoo_ext/static/style.less b/doc/_extensions/odoo_ext/static/style.less
deleted file mode 100644
index 0efd8542dcd..00000000000
--- a/doc/_extensions/odoo_ext/static/style.less
+++ /dev/null
@@ -1,276 +0,0 @@
-// Assets
-@import "bootstrap-3.3.6/less/bootstrap";
-@import "mdi";
-
-// Define custom variables for style and layout.
-@import "variables";
-
-@import "mixins";
-@import "typography";
-@import "components";
-@import "layout";
-@import "index";
-@import "header";
-@import "footer";
-@import "aside";
-@import "print";
-
-
-
-// Documentation header's customizations
-// --------------------------------------
-// Header style is based on odoo.com and can be find in the header.less file.
-// The following rules are specific for the documentation website.
-
-.o_main_header {
- @o-sub-inner-h: @w-sub-nav-height - 2;
-
- &.o_mobile_menu_opened .mdi-navigation-menu {
- background-color: @footer-bg-color;
- color: @gray-lighter;
- }
-
- > .o_sub_nav #o_sub-menu #searchbox {
- display: flex;
- align-items: center;
- justify-content: center;
-
- > form {
- display: flex;
- flex-grow: 1;
- > .form-control {
- border-radius: 0;
- }
- }
- }
-
- > .o_sub_nav #o_sub-menu .o_breadcrumb {
-
- @media screen and (min-width: @screen-sm-min) {
- background-color: transparent;
- padding: 0;
- margin: 0 0 0 -15px;
- height: @o-sub-inner-h;
- line-height: @o-sub-inner-h;
- }
-
- > li {
- display: block;
- &, > a {
- height: 30px;
- line-height: 2;
- }
-
- &:before {
- font-weight: @fw_bold;
- float: left;
- padding: 0;
- margin-right: -1px;
- display: none;
- }
-
- @media screen and (min-width: @screen-sm-min) {
- margin-left: 0;
- margin-right: -1px;
- height: @o-sub-inner-h;
- line-height: @o-sub-inner-h;
- display: inline-block;
-
- &:before {
- display: block;
- }
-
- > a {
- padding: 0;
- height: @o-sub-inner-h;
- line-height: @w-sub-nav-height;
- letter-spacing: -0.1px;
- word-spacing: -1px;
- display: inline-block;
- height: 100%;
- max-width: 80px;
- overflow: hidden;
- white-space: nowrap;
- text-overflow: ellipsis;
- }
-
- &:last-child > a {
- max-width: 170px;
- }
- }
-
- @media screen and (min-width: 1980px) {
- > a {
- max-width: 120px;
- }
- }
-
- @media screen and (min-width: @screen-lg-min) {
- &:last-child > a {
- max-width: none;
- }
- }
-
- @media screen and (max-width: @screen-xs-max) {
- > a {
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
- }
- > a:before {
- content: "|";
- margin-right: 0.5em;
- }
- &:nth-child(1) > a:before {
- display: none;
- }
- &:nth-child(2) > a:before {
- padding-left: 0.5em;
- }
- &:nth-child(3) > a:before {
- padding-left: 1em;
- }
- }
- }
- }
-
- &.index {
- @media screen and (max-width: @screen-xs-max ){
- > .o_sub_nav #o_sub-menu .o_breadcrumb {
- display: none;
- }
- }
- }
-
- > .o_sub_nav {
- border-radius: 0;
-
- .navbar-toggle {
- padding: 0 15px;
- margin: 0;
- height: @o-sub-inner-h;
- background-color: @gray-lighter;
-
- span {
- line-height: @o-sub-inner-h;
- }
-
- &.collapsed {
- background-color: @w-header-white;
- }
- }
-
- .collapse .nav {
- margin-right: 0;
- margin-bottom: 0;
-
- &:first-of-type {
- margin-right: -15px;
- }
-
- > li {
- margin: 0;
-
- > a {
- padding:0 0 0 10px;
- }
-
- &.divider {
- height: auto;
- line-height: 1;
- border-bottom: 1px solid @gray-light;
- padding: 4px 0px 5px;
- }
-
- &.dropdown {
- .o-doc-dropdown();
- }
- }
- }
-
- > .container > .collapse > .nav,
- > .container .o_breadcrumb {
- > li > a {
- @media screen and (min-width: @screen-sm-min) and ( max-width: @screen-sm-max ) {
- font-size: 10px;
- font-weight: @fw_semibold;
- }
- }
- }
-
- li.dropdown {
- .o-doc-dropdown();
- }
- }
-
-
- &.o_inverted:not(.o_scrolled) {
- @media (max-width: @screen-xs-max) {
- .o_sub_nav {
- display: block;
- margin-bottom: 0;
-
- .nav {
- margin: 0 0 0 -8px;
-
- > li > a{
- color: @text-color;
-
- &:hover, &:focus {
- color: @header-link-normal;
- }
- }
- }
- }
- }
-
- .o_sub_nav_actions {
- margin-left: 10px;
-
- > li {
- background: fade(@gray-lightest, 10%);
- margin-right: 1px;
-
- &:last-child {
- margin-right: 0
- }
- }
- }
- }
-
- &.o_scrolled {
- .o_sub_nav {
- #o_doc_title {
- .opacity(1);
- .translate(0, 0);
- .transition(~'opacity 1s, transform 0.3s');
- }
-
- .o_sub_nav_actions {
- margin-left: 10px;
-
- &:first-of-type {
- margin-right: -25px;
- }
-
- > li {
- background: fade(@gray, 10%);
- margin-right: 1px;
-
- &:last-child {
- margin-right: 0
- }
- }
- }
- }
- }
-}
-
-
-
-// Special Pages
-
-// Theme tutorial
-#thinking-modular > .clearfix.themes {
- margin-bottom: 3em;
-} \ No newline at end of file
diff --git a/doc/_extensions/odoo_ext/static/typography.less b/doc/_extensions/odoo_ext/static/typography.less
deleted file mode 100644
index c22541843c4..00000000000
--- a/doc/_extensions/odoo_ext/static/typography.less
+++ /dev/null
@@ -1,181 +0,0 @@
-// =============================================================================
-// Typography
-// =============================================================================
-@margin-base: 5px;
-
-// Font rendering
-// ----------------------------------------
-body {
- -webkit-font-smoothing: antialiased;
- -moz-osx-font-smoothing: grayscale;
- text-rendering: optimizeLegibility;
-}
-
-// Headings
-// ----------------------------------------
-h1, h2, h3, h4, h5, h6 {
- text-rendering: geometricPrecision;
-
- @media (min-width: @screen-lg-min) {
- .has_code_col .doc-aside &{
- color: white;
- }
- }
-}
-
-.headings-margin-small () {
- > h2, > h3, > h4, > h5, > h6 {
- margin-top: @margin-base*2;
- }
-}
-.headings-bordered () {
- padding-bottom: @margin-base;
- border-bottom: 2px solid #f4f6f7;
-}
-
-.footnote-ref {
- &:before {content: '[';}
- &:after {content: ']';}
- vertical-align: super;
- font-size: 1ex;
-}
-
-article.doc-body {
-
- // Vertical rhythm
- > section {
- padding-bottom: @margin-base*2;
-
- > :last-child {
- margin-bottom: 0;
- }
-
- > h2, > h3, > h4, > h5, > h6 {
- margin-bottom: @margin-base;
- margin-top: @margin-base*8;
-
- &:last-child {
- margin-bottom: -@margin-base*6;
- .headings-bordered();
- }
- }
-
- > h2 {
- .headings-bordered();
- }
-
- > h5, > h6 {
- font-weight: 500;
- }
-
- &:first-of-type {
- .headings-margin-small();
-
- &:empty, &.hidden {
- display: none;
-
- + section {
- .headings-margin-small();
- }
- }
- }
- }
-
- // Typography components
- > section {
- line-height: 26px;
- }
-
- a, a:hover {
- text-decoration: underline;
- }
-
- blockquote {
- font-size: 15px;
- line-height: 26px;
- &:not(:first-child) {
- margin-top: 17px;
- }
- }
-
- dl {
- dt code {
- font-size: 0.9em;
- }
-
- dd {
- margin: 2px 0 @grid-gutter-width/2 @grid-gutter-width/2;
- }
- }
-
- ol, ul {
- line-height: 26px;
- padding: 0;
- list-style: none;
- counter-reset: a;
-
- li {
- margin: 5px 0;
- position: relative;
- padding-left: 30px;
-
- &:before {
- content: "";
- display: block;
- .o-position-absolute(9px, @left: 10px);
- .square(6px);
- border-radius: 50%;
- background: #939da3;
- }
-
- p {
- margin: 0;
- }
-
- h2, h3, h4, h5, h6 {
- margin-top: 0;
- padding-top: 0;
- }
- }
- }
-
- ol > li:before {
- counter-increment: a;
- content: counter(a);
- color: #fff;
- font-size: 13px;
- font-weight: bold;
- line-height: 1;
- text-align: center;
- padding: 4px 0;
- .square(20px);
- border-radius: 10px;
- .o-position-absolute(3px, @left: 0);
- }
-
-
- .o_has_permalink_marker {
- transition: all, 0.3s;
- padding-left: 0;
-
- i {
- cursor: pointer;
- visibility: hidden;
- margin-left: 0.1em;
- font-size: 0.8em;
- padding: 0.2em;
- .rotate(-45deg);
- }
-
- &:hover {
- i {
- visibility: visible;
- }
- }
-
- &.o_marked {
- padding-left: 10px;
- background-color: #fff7d1;
- }
- }
-}
diff --git a/doc/_extensions/odoo_ext/static/variables.less b/doc/_extensions/odoo_ext/static/variables.less
deleted file mode 100644
index d337f796865..00000000000
--- a/doc/_extensions/odoo_ext/static/variables.less
+++ /dev/null
@@ -1,169 +0,0 @@
-// Based on http://www.odoo.com/openerp_website/static/src/less/variables.less
-// ============================================================================
-
-// Prefixes
-// ==============================================
-@website-2x-prefix : "2x_";
-
-
-// Odoo Colours
-// ==============================================
-
-@odoo-brand-optional : #21b799;
-@odoo-brand-primary : #9E588B;
-
-//== Odoo Colours
-@o-violet-dark : #875A7B;
-@o-violet-darker : #62495B;
-
-@o-inverse : #47738F;
-@o-inverse-dark : #5B7687;
-@o-inverse-darker : #485761;
-
-
-//== Grayscale
-@gray-lightest : #F9F9F9;
-@gray-lighter : #F2F2F2;
-@gray-light : #dcddde;
-@gray : #888888;
-@gray-dark : #6B6D70;
-@gray-darker : #282F33;
-@gray-darkest : darken(saturate(@gray-darker, 1%), 3%);
-
-//== UI Colors
-@brand-primary : @odoo-brand-optional;
-@brand-success : #50AF51;
-@brand-info : #4B9EB6;
-@brand-warning : #F0AD4E;
-@brand-danger : #D9534F;
-
-//== Apps' Families Colours
-@color-alpha : @brand-primary;
-@color-alpha-dark : #18856F;
-@color-alpha-light : #26D1AF;
-@color-alpha-lightest : #2AEBC4;
-
-@color-beta : #5B899E;
-@color-beta-dark : #3D5D6B;
-@color-beta-light : #699FB8;
-@color-beta-lightest : #77B5D1;
-
-@color-gamma : #E46F78;
-@color-gamma-dark : #B0565C;
-@color-gamma-light : #FC7C84;
-@color-gamma-lightest : #FC959C;
-
-@color-delta : #5C5B80;
-@color-delta-dark : #37364D;
-@color-delta-light : #6E6D99;
-@color-delta-lightest : #807FB3;
-
-@color-epsilon : #D5653E;
-@color-epsilon-dark : #A34E2F;
-@color-epsilon-light : #F07346;
-@color-epsilon-lightest : #FF8D63;
-
-
-
-@doc_paper_dark : @gray-lighter;
-@doc_paper : #fff;
-
-@doc_exercise : #938E94;
-@doc_code-bg : @gray-darkest;
-@doc_lime : #CDDC39;
-@doc_orange : #FF5722;
-@doc_cyan : #0097A7;
-
-
-// Typography
-// ===============================================
-
-//== Font sizes/weigths
-@font-size-base : 16px;
-
-@fw_light : 300;
-@fw_regular : 400;
-@fw_medium : 500;
-@fw_semibold : 600;
-@fw_bold : 700;
-
-//== Paragraphs
-@font-family-base : -apple-system, system-ui, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
-@text-color : #373e42;
-
-//== Headings
-@headings-color : saturate(@gray-darker, 15%);
-@headings-font-family : @font-family-base;
-@headings-font-weight : @fw_regular;
-@headings-small-color : @headings-color;
-
-@font-size-h2: 30px;
-@font-size-h3: 24px;
-@font-size-h4: 19px;
-@font-size-h5: 17px;
-@font-size-h6: 17px;
-
-//== Global textual link color.
-@link-color : @o-violet-dark;
-@link-hover-color : desaturate(@odoo-brand-primary, 10%);
-@link-hover-decoration : none;
-
-//== Mute color.
-@text-muted : @gray;
-
-
-// Layouting
-// ===============================================
-@body-bg: @gray-lightest;
-
-//== Header
-@w-header-height : 50px;
-@w-sub-nav-height : 40px;
-@w-header-white : #FCFCFC;
-@header-link-normal : darken(@text-color,5%);
-
-//== Footer
-@footer-heigth : 300px;
-@footer-bg-color : @gray-darker;
-@footer-bottom-bg-color : @gray-darkest;
-@footer-text : @gray-light;
-@footer-text-mute : @gray;
-
-
-// ==========================
-// == Docs Variables ========
-// ==========================
-
-// Z-Index Scale (private vars)
-// --------------------------------------------------
-@zIndex-1:100;
-@zIndex-2:200;
-@zIndex-3:300;
-@zIndex-4:400;
-@zIndex-5:500;
-@zIndex-6:600;
-@zIndex-7:700;
-@zIndex-8:800;
-@zIndex-9:900;
-@zIndex-10:1000;
-
-// Z-Index Elements
-// --------------------------------------------------
-
-@zIndex--main: 0;
-@zIndex--mask: @zIndex-7;
-@zIndex--float_action: @zIndex-8;
-@zIndex--toggle_side_menu: @zIndex-8;
-
-
-// Cards
-// --------------------------------------------------
-@card_margin-bottom: 25px;
-
-
-
-// Easing Curves
-// --------------------------------------------------
-@o-ease : cubic-bezier(.55,0,.1,1);
-@ease-material-2 : cubic-bezier(0.215, 0.61, 0.355, 1);
-@ease-material-3 : cubic-bezier(0.4, 0, 0.2, 1);
diff --git a/doc/_extensions/odoo_ext/sub-menu_list.html b/doc/_extensions/odoo_ext/sub-menu_list.html
deleted file mode 100644
index f667cdc407b..00000000000
--- a/doc/_extensions/odoo_ext/sub-menu_list.html
+++ /dev/null
@@ -1,20 +0,0 @@
-{# note: if odoo.com/page/docs sub-menu's structure change, these links have to change as well #}
-
-<li><a href="https://www.odoo.com/documentation/user/14.0/index.html">User</a></li>
-<li><a href="https://www.odoo.com/documentation/14.0/index.html">Developer</a></li>
-<li><a href="https://www.odoo.com/documentation/14.0/setup/install.html">Installation</a></li>
-<li><a href="https://odoo.com/slides">eLearning</a></li>
-<li><a href="https://www.odoo.com/page/odoo-white-paper">White Papers</a></li>
-<li><a href="https://www.odoo.com/page/legal">Legal</a></li>
-
-{%- if pagename != "search" and builder != "singlehtml" %}
-<li id="searchbox" style="display: none; margin: 0 0 0 10px;" role="search">
- <form class="search form-inline input-group-sm" action="{{ pathto('search') }}" method="get">
- <input type="text" class="form-control" name="q" id="q" placeholder="Search..." />
- <input type="hidden" name="area" value="default" />
- <input type="hidden" name="check_keywords" value="yes" />
- <button type="submit" value="Go" class="btn btn-default btn-sm">Go</button>
- </form>
-</li>
-<script type="text/javascript">$('#searchbox').show(0);</script>
-{%- endif %} \ No newline at end of file
diff --git a/doc/_extensions/odoo_ext/switcher.py b/doc/_extensions/odoo_ext/switcher.py
deleted file mode 100644
index 8571d124259..00000000000
--- a/doc/_extensions/odoo_ext/switcher.py
+++ /dev/null
@@ -1,45 +0,0 @@
-from docutils import nodes, utils
-from docutils.parsers.rst import Directive
-
-from pygments.lexers import get_lexer_by_name, PythonLexer
-PythonLexer.name = 'Python 2'
-
-def setup(app):
- app.add_directive('switcher', SwitcherDirective)
- app.add_directive('case', CaseDirective)
-
-class SwitcherDirective(Directive):
- has_content = True
-
- def run(self):
- self.assert_has_content()
-
- body = nodes.compound('\n'.join(self.content), classes=['tabs'])
- self.state.nested_parse(self.content, self.content_offset, body)
-
- titles = []
- for child in body.children:
- if isinstance(child, nodes.literal_block):
- titles.append(get_lexer_by_name(child['language']).name)
- else:
- assert child['names'], ("A switcher case must be either a "\
- "code block or a compound with a name")
- titles.append(' '.join(child['names']))
- tabs = nodes.bullet_list('', *[
- nodes.list_item('', nodes.Text(title))
- for title in titles
- ])
- node = nodes.compound('', tabs, body, classes=['content-switcher'])
- return [node]
-
-class CaseDirective(Directive):
- required_arguments = 1
- final_argument_whitespace = True
- has_content = True
-
- def run(self):
- self.assert_has_content()
-
- node = nodes.compound('\n'.join(self.content), names=[self.arguments[0]])
- self.state.nested_parse(self.content, self.content_offset, node)
- return [node]
diff --git a/doc/_extensions/odoo_ext/switchers_list.html b/doc/_extensions/odoo_ext/switchers_list.html
deleted file mode 100644
index 1e90a61ae17..00000000000
--- a/doc/_extensions/odoo_ext/switchers_list.html
+++ /dev/null
@@ -1,25 +0,0 @@
-{% if languages %}
-<li class="languages dropdown">
- <a class="dropdown-toggle" href="#" data-toggle="dropdown">
- {{ language }}
- </a>
- <ul class="dropdown-menu" role="menu">
- {% for name, url in languages %}
- <li><a href="{{ url }}">{{ name }}</a></li>
- {% endfor %}
- </ul>
-</li>
-{% endif %}
-
-{% if versions %}
-<li class="versions dropdown">
- <a class="dropdown-toggle" href="#" data-toggle="dropdown">
- {{ version }}
- </a>
- <ul class="dropdown-menu" role="menu">
- {% for name, url in versions %}
- <li><a href="{{ url }}">{{ name }}</a></li>
- {% endfor %}
- </ul>
-</li>
-{% endif %}
diff --git a/doc/_extensions/odoo_ext/theme.conf b/doc/_extensions/odoo_ext/theme.conf
deleted file mode 100644
index cdac6eeafb9..00000000000
--- a/doc/_extensions/odoo_ext/theme.conf
+++ /dev/null
@@ -1,4 +0,0 @@
-[theme]
-inherit = basic
-stylesheet = style.css
-pygments_style = odoo
diff --git a/doc/_extensions/odoo_ext/translator.py b/doc/_extensions/odoo_ext/translator.py
deleted file mode 100644
index 914d0a81313..00000000000
--- a/doc/_extensions/odoo_ext/translator.py
+++ /dev/null
@@ -1,748 +0,0 @@
-# -*- coding: utf-8 -*-
-from __future__ import print_function
-
-import os.path
-import posixpath
-import re
-
-from docutils import nodes
-from sphinx import addnodes, util, builders
-from sphinx.locale import admonitionlabels
-from urllib.request import url2pathname
-
-
-def _parents(node):
- while node.parent:
- node = node.parent
- yield node
-
-class BootstrapTranslator(nodes.NodeVisitor, object):
- head_prefix = 'head_prefix'
- head = 'head'
- stylesheet = 'stylesheet'
- body_prefix = 'body_prefix'
- body_pre_docinfo = 'body_pre_docinfo'
- docinfo = 'docinfo'
- body_suffix = 'body_suffix'
- subtitle = 'subtitle'
- header = 'header'
- footer = 'footer'
- html_prolog = 'html_prolog'
- html_head = 'html_head'
- html_title = 'html_title'
- html_subtitle = 'html_subtitle'
-
-
- def __init__(self, document, builder):
- # order of parameter swapped between Sphinx 1.x and 2.x, check if
- # we're running 1.x and swap back
- if not isinstance(builder, builders.Builder):
- builder, document = document, builder
-
- super(BootstrapTranslator, self).__init__(document)
- self.builder = builder
- self.meta = [
- # HTMLWriter strips out the first two items from Translator.meta
- # with no explanation
- '', '',
- ]
- self.add_meta('<meta http-equiv="X-UA-Compatible" content="IE=edge">')
- self.add_meta('<meta name="viewport" content="width=device-width, initial-scale=1">')
- self.body = []
- self.fragment = self.body
- self.html_body = self.body
- # document title
- self.title = []
- self.start_document_title = 0
- self.first_title = False
-
- self.context = []
- self.section_level = 0
-
- self.config = self.builder.config
- self.highlightlang = self.highlightlang_base = self.builder.config.highlight_language
- self.highlightopts = getattr(builder.config, 'highlight_options', {})
-
- self.first_param = 1
- self.optional_param_level = 0
- self.required_params_left = 0
- self.param_separator = ','
-
- def encode(self, text):
- return str(text).translate({
- ord('&'): u'&amp;',
- ord('<'): u'&lt;',
- ord('"'): u'&quot;',
- ord('>'): u'&gt;',
- 0xa0: u'&nbsp;'
- })
-
- def add_meta(self, meta):
- self.meta.append('\n ' + meta)
-
- def starttag(self, node, tagname, **attributes):
- tagname = str(tagname).lower()
-
- # extract generic attributes
- attrs = {name.lower(): value for name, value in attributes.items()}
- attrs.update(
- (name, value) for name, value in node.attributes.items()
- if name.startswith('data-')
- )
-
- prefix = []
- postfix = []
-
- # handle possibly multiple ids
- assert 'id' not in attrs, "starttag can't be passed a single id attribute, use a list of ids"
- ids = node.get('ids', []) + attrs.pop('ids', [])
- if ids:
- _ids = iter(ids)
- attrs['id'] = next(_ids)
- postfix.extend(u'<i id="{}"></i>'.format(_id) for _id in _ids)
-
- # set CSS class
- classes = set(node.get('classes', []) + attrs.pop('class', '').split())
- if classes:
- attrs['class'] = u' '.join(classes)
-
- return u'{prefix}<{tag} {attrs}>{postfix}'.format(
- prefix=u''.join(prefix),
- tag=tagname,
- attrs=u' '.join(u'{}="{}"'.format(name, self.attval(value))
- for name, value in attrs.items()),
- postfix=u''.join(postfix),
- )
- # only "space characters" SPACE, CHARACTER TABULATION, LINE FEED,
- # FORM FEED and CARRIAGE RETURN should be collapsed, not al White_Space
- def attval(self, value, whitespace=re.compile(u'[ \t\n\f\r]+')):
- return self.encode(whitespace.sub(' ', str(value)))
-
- def astext(self):
- return u''.join(self.body)
-
- def unknown_visit(self, node):
- print("unknown node", node.__class__.__name__)
- self.body.append(u'[UNKNOWN NODE {}]'.format(node.__class__.__name__))
- raise nodes.SkipNode
-
- def visit_highlightlang(self, node):
- self.highlightlang = node['lang']
- def depart_highlightlang(self, node):
- pass
-
- def visit_document(self, node):
- self.first_title = True
- def depart_document(self, node):
- pass
-
- def visit_meta(self, node):
- if node.hasattr('lang'):
- node['xml:lang'] = node['lang']
- # del(node['lang'])
- meta = self.starttag(node, 'meta', **node.non_default_attributes())
- self.add_meta(meta)
- def depart_meta(self, node):
- pass
-
- def visit_section(self, node):
- # close "parent" or preceding section, unless this is the opening of
- # the first section
- if self.section_level:
- self.body.append(u'</section>')
- self.section_level += 1
-
- self.body.append(self.starttag(node, 'section'))
- def depart_section(self, node):
- self.section_level -= 1
- # close last section of document
- if not self.section_level:
- self.body.append(u'</section>')
-
- def visit_topic(self, node):
- self.body.append(self.starttag(node, 'nav'))
- def depart_topic(self, node):
- self.body.append(u'</nav>')
-
- def is_compact_paragraph(self, node):
- parent = node.parent
- if isinstance(parent, (nodes.document, nodes.compound,
- addnodes.desc_content,
- addnodes.versionmodified)):
- # Never compact paragraphs in document or compound.
- return False
-
- for key, value in node.attlist():
- # we can ignore a few specific classes, all other non-default
- # attributes require that a <p> node remains
- if key != 'classes' or value not in ([], ['first'], ['last'], ['first', 'last']):
- return False
-
- first = isinstance(node.parent[0], nodes.label)
- for child in parent.children[first:]:
- # only first paragraph can be compact
- if isinstance(child, nodes.Invisible):
- continue
- if child is node:
- break
- return False
- parent_length = len([
- 1 for n in parent
- if not isinstance(n, (nodes.Invisible, nodes.label))
- ])
- return parent_length == 1
-
- def visit_paragraph(self, node):
- if self.is_compact_paragraph(node):
- self.context.append(u'')
- return
- self.body.append(self.starttag(node, 'p'))
- self.context.append(u'</p>')
- def depart_paragraph(self, node):
- self.body.append(self.context.pop())
- def visit_compact_paragraph(self, node):
- pass
- def depart_compact_paragraph(self, node):
- pass
-
- def visit_problematic(self, node):
- if node.hasattr('refid'):
- self.body.append('<a href="#%s">' % node['refid'])
- self.context.append('</a>')
- else:
- self.context.append('')
- self.body.append(self.starttag(node, 'span', CLASS='problematic'))
-
- def depart_problematic(self, node):
- self.body.append('</span>')
- self.body.append(self.context.pop())
-
- def visit_literal_block(self, node):
- if node.rawsource != node.astext():
- # most probably a parsed-literal block -- don't highlight
- self.body.append(self.starttag(node, 'pre'))
- return
- lang = self.highlightlang
- highlight_args = node.get('highlight_args', {})
- if 'language' in node:
- # code-block directives
- lang = node['language']
- highlight_args['force'] = True
- linenos = node.get('linenos', False)
- if lang is self.highlightlang_base:
- # only pass highlighter options for original language
- opts = self.highlightopts
- else:
- opts = {}
-
- def warner(msg, **kw):
- self.builder.warn(msg, (self.builder.current_docname, node.line))
- highlighted = self.builder.highlighter.highlight_block(
- node.rawsource, lang, opts=opts, warn=warner, linenos=linenos,
- **highlight_args)
- self.body.append(self.starttag(node, 'div', CLASS='highlight-%s' % lang))
- self.body.append(highlighted)
- self.body.append(u'</div>\n')
- raise nodes.SkipNode
- def depart_literal_block(self, node):
- self.body.append(u'</pre>')
-
- def visit_bullet_list(self, node):
- self.body.append(self.starttag(node, 'ul'))
- def depart_bullet_list(self, node):
- self.body.append(u'</ul>')
- def visit_enumerated_list(self, node):
- self.body.append(self.starttag(node, 'ol'))
- def depart_enumerated_list(self, node):
- self.body.append(u'</ol>')
- def visit_list_item(self, node):
- self.body.append(self.starttag(node, 'li'))
- def depart_list_item(self, node):
- self.body.append(u'</li>')
- def visit_definition_list(self, node):
- self.body.append(self.starttag(node, 'dl'))
- def depart_definition_list(self, node):
- self.body.append(u'</dl>')
- def visit_definition_list_item(self, node):
- pass
- def depart_definition_list_item(self, node):
- pass
- def visit_term(self, node):
- self.body.append(self.starttag(node, 'dt'))
- def depart_term(self, node):
- self.body.append(u'</dt>')
- def visit_termsep(self, node):
- self.body.append(self.starttag(node, 'br'))
- raise nodes.SkipNode
- def visit_definition(self, node):
- self.body.append(self.starttag(node, 'dd'))
- def depart_definition(self, node):
- self.body.append(u'</dd>')
-
- def visit_admonition(self, node, type=None):
- clss = {
- # ???: 'alert-success',
-
- 'note': 'alert-info',
- 'hint': 'alert-info',
- 'tip': 'alert-info',
- 'seealso': 'alert-go_to',
-
- 'warning': 'alert-warning',
- 'attention': 'alert-warning',
- 'caution': 'alert-warning',
- 'important': 'alert-warning',
-
- 'danger': 'alert-danger',
- 'error': 'alert-danger',
-
- 'exercise': 'alert-exercise',
- }
- self.body.append(self.starttag(node, 'div', role='alert', CLASS='alert {}'.format(
- clss.get(type, '')
- )))
- if 'alert-dismissible' in node.get('classes', []):
- self.body.append(
- u'<button type="button" class="close" data-dismiss="alert" aria-label="Close">'
- u'<span aria-hidden="true">&times;</span>'
- u'</button>')
- if type:
- node.insert(0, nodes.title(type, admonitionlabels[type]))
- def depart_admonition(self, node):
- self.body.append(u'</div>')
- visit_note = lambda self, node: self.visit_admonition(node, 'note')
- visit_warning = lambda self, node: self.visit_admonition(node, 'warning')
- visit_attention = lambda self, node: self.visit_admonition(node, 'attention')
- visit_caution = lambda self, node: self.visit_admonition(node, 'caution')
- visit_danger = lambda self, node: self.visit_admonition(node, 'danger')
- visit_error = lambda self, node: self.visit_admonition(node, 'error')
- visit_hint = lambda self, node: self.visit_admonition(node, 'hint')
- visit_important = lambda self, node: self.visit_admonition(node, 'important')
- visit_tip = lambda self, node: self.visit_admonition(node, 'tip')
- visit_exercise = lambda self, node: self.visit_admonition(node, 'exercise')
- visit_seealso = lambda self, node: self.visit_admonition(node, 'seealso')
- depart_note = depart_admonition
- depart_warning = depart_admonition
- depart_attention = depart_admonition
- depart_caution = depart_admonition
- depart_danger = depart_admonition
- depart_error = depart_admonition
- depart_hint = depart_admonition
- depart_important = depart_admonition
- depart_tip = depart_admonition
- depart_exercise = depart_admonition
- depart_seealso = depart_admonition
- def visit_versionmodified(self, node):
- self.body.append(self.starttag(node, 'div', CLASS=node['type']))
- def depart_versionmodified(self, node):
- self.body.append(u'</div>')
-
- def visit_title(self, node):
- parent = node.parent
- closing = u'</h3>'
- if isinstance(parent, nodes.Admonition):
- self.body.append(self.starttag(node, 'h3', CLASS='alert-title'))
- elif isinstance(node.parent, nodes.document):
- self.body.append(self.starttag(node, 'h1'))
- closing = u'</h1>'
- self.start_document_title = len(self.body)
- else:
- assert isinstance(parent, nodes.section), "expected a section node as parent to the title, found {}".format(parent)
- if self.first_title:
- self.first_title = False
- raise nodes.SkipNode()
- nodename = 'h{}'.format(self.section_level)
- self.body.append(self.starttag(node, nodename))
- closing = u'</{}>'.format(nodename)
- self.context.append(closing)
- def depart_title(self, node):
- self.body.append(self.context.pop())
- if self.start_document_title:
- self.title = self.body[self.start_document_title:-1]
- self.start_document_title = 0
- del self.body[:]
-
- # the rubric should be a smaller heading than the current section, up to
- # h6... maybe "h7" should be a ``p`` instead?
- def visit_rubric(self, node):
- self.body.append(self.starttag(node, 'h{}'.format(min(self.section_level + 1, 6))))
- def depart_rubric(self, node):
- self.body.append(u'</h{}>'.format(min(self.section_level + 1, 6)))
-
- def visit_block_quote(self, node):
- self.body.append(self.starttag(node, 'blockquote'))
- def depart_block_quote(self, node):
- self.body.append(u'</blockquote>')
- def visit_attribution(self, node):
- self.body.append(self.starttag(node, 'footer'))
- def depart_attribution(self, node):
- self.body.append(u'</footer>')
-
- def visit_container(self, node):
- self.body.append(self.starttag(node, 'div'))
- def depart_container(self, node):
- self.body.append(u'</div>')
- def visit_compound(self, node):
- self.body.append(self.starttag(node, 'div'))
- def depart_compound(self, node):
- self.body.append(u'</div>')
-
- def visit_image(self, node):
- uri = node['uri']
- if uri in self.builder.images:
- uri = posixpath.join(self.builder.imgpath,
- self.builder.images[uri])
- attrs = {'src': uri, 'class': 'img-responsive'}
- if 'alt' in node:
- attrs['alt'] = node['alt']
- if 'align' in node:
- if node['align'] == 'center':
- attrs['class'] += ' center-block'
- else:
- doc = None
- if node.source:
- doc = node.source
- if node.line:
- doc += ':%d' % node.line
- self.builder.app.warn(
- "Unsupported alignment value \"%s\"" % node['align'],
- location=doc
- )
- elif 'align' in node.parent and node.parent['align'] == 'center':
- # figure > image
- attrs['class'] += ' center-block'
-
- # todo: explicit width/height/scale?
- self.body.append(self.starttag(node, 'img', **attrs))
- def depart_image(self, node): pass
- def visit_figure(self, node):
- self.body.append(self.starttag(node, 'div'))
- def depart_figure(self, node):
- self.body.append(u'</div>')
- def visit_caption(self, node):
- # first paragraph of figure content
- self.body.append(self.starttag(node, 'h4'))
- def depart_caption(self, node):
- self.body.append(u'</h4>')
- def visit_legend(self, node): pass
- def depart_legend(self, node): pass
-
- def visit_line(self, node):
- self.body.append(self.starttag(node, 'div', CLASS='line'))
- # ensure the line still takes the room it needs
- if not len(node): self.body.append(u'<br />')
- def depart_line(self, node):
- self.body.append(u'</div>')
-
- def visit_line_block(self, node):
- self.body.append(self.starttag(node, 'div', CLASS='line-block'))
- def depart_line_block(self, node):
- self.body.append(u'</div>')
-
- def visit_table(self, node):
- self.body.append(self.starttag(node, 'table', CLASS='table'))
- def depart_table(self, node):
- self.body.append(u'</table>')
- def visit_tgroup(self, node): pass
- def depart_tgroup(self, node): pass
- def visit_colspec(self, node): raise nodes.SkipNode
- def visit_thead(self, node):
- self.body.append(self.starttag(node, 'thead'))
- def depart_thead(self, node):
- self.body.append(u'</thead>')
- def visit_tbody(self, node):
- self.body.append(self.starttag(node, 'tbody'))
- def depart_tbody(self, node):
- self.body.append(u'</tbody>')
- def visit_row(self, node):
- self.body.append(self.starttag(node, 'tr'))
- def depart_row(self, node):
- self.body.append(u'</tr>')
- def visit_entry(self, node):
- if isinstance(node.parent.parent, nodes.thead):
- tagname = 'th'
- else:
- tagname = 'td'
- self.body.append(self.starttag(node, tagname))
- self.context.append(tagname)
- def depart_entry(self, node):
- self.body.append(u'</{}>'.format(self.context.pop()))
-
- def visit_Text(self, node):
- self.body.append(self.encode(node.astext()))
- def depart_Text(self, node):
- pass
- def visit_literal(self, node):
- self.body.append(self.starttag(node, 'code'))
- def depart_literal(self, node):
- self.body.append(u'</code>')
- visit_literal_emphasis = visit_literal
- depart_literal_emphasis = depart_literal
- def visit_emphasis(self, node):
- self.body.append(self.starttag(node, 'em'))
- def depart_emphasis(self, node):
- self.body.append(u'</em>')
- def visit_strong(self, node):
- self.body.append(self.starttag(node, 'strong'))
- def depart_strong(self, node):
- self.body.append(u'</strong>')
- visit_literal_strong = visit_strong
- depart_literal_strong = depart_strong
- def visit_inline(self, node):
- self.body.append(self.starttag(node, 'span'))
- def depart_inline(self, node):
- self.body.append(u'</span>')
- def visit_abbreviation(self, node):
- attrs = {}
- if 'explanation' in node:
- attrs['title'] = node['explanation']
- self.body.append(self.starttag(node, 'abbr', **attrs))
- def depart_abbreviation(self, node):
- self.body.append(u'</abbr>')
-
- def visit_reference(self, node):
- attrs = {
- 'class': 'reference',
- 'href': node['refuri'] if 'refuri' in node else '#' + node['refid']
- }
- attrs['class'] += ' internal' if (node.get('internal') or 'refuri' not in node) else ' external'
- if any(isinstance(ancestor, nodes.Admonition) for ancestor in _parents(node)):
- attrs['class'] += ' alert-link'
-
- if 'reftitle' in node:
- attrs['title'] = node['reftitle']
-
- self.body.append(self.starttag(node, 'a', **attrs))
- def depart_reference(self, node):
- self.body.append(u'</a>')
- def visit_download_reference(self, node):
- # type: (nodes.Node) -> None
- if node.hasattr('filename'):
- self.body.append(
- '<a class="reference download internal" href="%s" download="">' %
- posixpath.join(self.builder.dlpath, node['filename']))
- self.body.append(node.astext())
- self.body.append('</a>')
- raise nodes.SkipNode
- else:
- self.context.append('')
- def depart_download_reference(self, node):
- # type: (nodes.Node) -> None
- self.body.append(self.context.pop())
- def visit_target(self, node): pass
- def depart_target(self, node): pass
- def visit_footnote(self, node):
- self.body.append(self.starttag(node, 'div', CLASS='footnote'))
- self.footnote_backrefs(node)
- def depart_footnote(self, node):
- self.body.append(u'</div>')
- def visit_footnote_reference(self, node):
- self.body.append(self.starttag(
- node, 'a', href='#' + node['refid'], CLASS="footnote-ref"))
- def depart_footnote_reference(self, node):
- self.body.append(u'</a>')
- def visit_label(self, node):
- self.body.append(self.starttag(node, 'span', CLASS='footnote-label'))
- self.body.append(u'%s[' % self.context.pop())
- def depart_label(self, node):
- # Context added in footnote_backrefs.
- self.body.append(u']%s</span> %s' % (self.context.pop(), self.context.pop()))
- def footnote_backrefs(self, node):
- # should store following data on context stack (in that order since
- # they'll be popped so LIFO)
- #
- # * outside (after) label
- # * after label text
- # * before label text
- backrefs = node['backrefs']
- if not backrefs:
- self.context.extend(['', '', ''])
- elif len(backrefs) == 1:
- self.context.extend([
- '',
- '</a>',
- '<a class="footnote-backref" href="#%s">' % backrefs[0]
- ])
- else:
- backlinks = (
- '<a class="footnote-backref" href="#%s">%s</a>' % (backref, i)
- for i, backref in enumerate(backrefs, start=1)
- )
- self.context.extend([
- '<em class="footnote-backrefs">(%s)</em> ' % ', '.join(backlinks),
- '',
- ''
- ])
-
- def visit_desc(self, node):
- self.body.append(self.starttag(node, 'section', CLASS='code-' + node['objtype']))
- def depart_desc(self, node):
- self.body.append(u'</section>')
- def visit_desc_signature(self, node):
- self.body.append(self.starttag(node, 'h6'))
- self.body.append(u'<code>')
- def depart_desc_signature(self, node):
- self.body.append(u'</code>')
- self.body.append(u'</h6>')
- def visit_desc_addname(self, node): pass
- def depart_desc_addname(self, node): pass
- def visit_desc_type(self, node): pass
- def depart_desc_type(self, node): pass
- def visit_desc_returns(self, node):
- self.body.append(u' → ')
- def depart_desc_returns(self, node):
- pass
- def visit_desc_name(self, node): pass
- def depart_desc_name(self, node): pass
- def visit_desc_parameterlist(self, node):
- self.body.append(u'(')
- self.first_param = True
- self.optional_param_level = 0
- # How many required parameters are left.
- self.required_params_left = sum(isinstance(c, addnodes.desc_parameter) for c in node.children)
- self.param_separator = node.child_text_separator
- def depart_desc_parameterlist(self, node):
- self.body.append(u')')
- # If required parameters are still to come, then put the comma after
- # the parameter. Otherwise, put the comma before. This ensures that
- # signatures like the following render correctly (see issue #1001):
- #
- # foo([a, ]b, c[, d])
- #
- def visit_desc_parameter(self, node):
- if self.first_param:
- self.first_param = 0
- elif not self.required_params_left:
- self.body.append(self.param_separator)
- if self.optional_param_level == 0:
- self.required_params_left -= 1
- if 'noemph' not in node: self.body.append(u'<em>')
- def depart_desc_parameter(self, node):
- if 'noemph' not in node: self.body.append(u'</em>')
- if self.required_params_left:
- self.body.append(self.param_separator)
- def visit_desc_optional(self, node):
- self.optional_param_level += 1
- self.body.append(u'[')
- def depart_desc_optional(self, node):
- self.optional_param_level -= 1
- self.body.append(u']')
- def visit_desc_annotation(self, node):
- self.body.append(self.starttag(node, 'em'))
- def depart_desc_annotation(self, node):
- self.body.append(u'</em>')
- def visit_desc_content(self, node): pass
- def depart_desc_content(self, node): pass
- def visit_field_list(self, node):
- self.body.append(self.starttag(node, 'div', CLASS='code-fields'))
- def depart_field_list(self, node):
- self.body.append(u'</div>')
- def visit_field(self, node):
- self.body.append(self.starttag(node, 'div', CLASS='code-field'))
- def depart_field(self, node):
- self.body.append(u'</div>')
- def visit_field_name(self, node):
- self.body.append(self.starttag(node, 'div', CLASS='code-field-name'))
- def depart_field_name(self, node):
- self.body.append(u'</div>')
- def visit_field_body(self, node):
- self.body.append(self.starttag(node, 'div', CLASS='code-field-body'))
- def depart_field_body(self, node):
- self.body.append(u'</div>')
-
- def visit_glossary(self, node): pass
- def depart_glossary(self, node): pass
-
- def visit_comment(self, node): raise nodes.SkipNode
- def visit_toctree(self, node):
- # div class=row {{ section_type }}
- # h2 class=col-sm-12
- # {{ section title }}
- # div class=col-sm-6 col-md-3
- # figure class=card
- # a href=current_link style=background-image: document-image-attribute class=card-img
- # figcaption
- # {{ card title }}
- env = self.builder.env
- conf = self.builder.app.config
- for title, ref in ((e[0], e[1]) for e in node['entries']):
- # external URL, no toc, can't recurse into
- if ref not in env.tocs:
- continue
- toc = env.tocs[ref].traverse(addnodes.toctree)
-
- classes = env.metadata[ref].get('types', 'tutorials')
- classes += ' toc-single-entry' if not toc else ' toc-section'
- self.body.append(self.starttag(node, 'div', CLASS="row " + classes))
- self.body.append(u'<div class="col-sm-12"><h2>')
- self.body.append(title if title else util.nodes.clean_astext(env.titles[ref]))
- self.body.append(u'</h2></div>')
-
- entries = [(title, ref)] if not toc else ((e[0], e[1]) for e in toc[0]['entries'])
- for subtitle, subref in entries:
- baseuri = self.builder.get_target_uri(node['parent'])
-
- if subref in env.metadata:
- cover = env.metadata[subref].get('banner', conf.odoo_cover_default)
- elif subref in conf.odoo_cover_external:
- cover = conf.odoo_cover_external[subref]
- else:
- cover = conf.odoo_cover_default_external
-
- if cover:
- banner = '_static/' + cover
- base, ext = os.path.splitext(banner)
- small = "{}.small{}".format(base, ext)
- if os.path.isfile(url2pathname(small)):
- banner = small
- style = u"background-image: url('{}')".format(
- util.relative_uri(baseuri, banner) or '#')
- else:
- style = u''
-
- self.body.append(u"""
- <div class="col-sm-6 col-md-3">
- <figure class="card">
- <a href="{link}" class="card-img">
- <span style="{style}"></span>
- <figcaption>{title}</figcaption>
- </a>
- </figure>
- </div>
- """.format(
- link=subref if util.url_re.match(subref) else util.relative_uri(
- baseuri, self.builder.get_target_uri(subref)),
- style=style,
- title=subtitle if subtitle else util.nodes.clean_astext(env.titles[subref]),
- ))
-
- self.body.append(u'</div>')
- raise nodes.SkipNode
-
- def visit_index(self, node): raise nodes.SkipNode
-
- def visit_raw(self, node):
- if 'html' in node.get('format', '').split():
- t = 'span' if isinstance(node.parent, nodes.TextElement) else 'div'
- if node['classes']:
- self.body.append(self.starttag(node, t))
- self.body.append(node.astext())
- if node['classes']:
- self.body.append('</%s>' % t)
- # Keep non-HTML raw text out of output:
- raise nodes.SkipNode
-
- # internal node
- def visit_substitution_definition(self, node): raise nodes.SkipNode
-
- # without set_translator, add_node doesn't work correctly, so the
- # serialization of html_domain nodes needs to be embedded here
- def visit_div(self, node):
- self.body.append(self.starttag(node, 'div'))
- def depart_div(self, node):
- self.body.append(u'</div>\n')
- def visit_address(self, node):
- self.body.append(self.starttag(node, 'address'))
- def depart_address(self, node):
- self.body.append(u'</address>')
- # TODO: inline elements
diff --git a/doc/_extensions/pyjsdoc/LICENSE b/doc/_extensions/pyjsdoc/LICENSE
deleted file mode 100644
index dd5b3a58aa1..00000000000
--- a/doc/_extensions/pyjsdoc/LICENSE
+++ /dev/null
@@ -1,174 +0,0 @@
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
diff --git a/doc/_extensions/pyjsdoc/__init__.py b/doc/_extensions/pyjsdoc/__init__.py
deleted file mode 100644
index 8368f73083e..00000000000
--- a/doc/_extensions/pyjsdoc/__init__.py
+++ /dev/null
@@ -1,408 +0,0 @@
-from __future__ import division
-import re, json
-
-##### Parsing utilities #####
-
-def split_delimited(delimiters, split_by, text):
- """
- Generator that walks the ``text`` and splits it into an array on
- ``split_by``, being careful not to break inside a delimiter pair.
- ``delimiters`` should be an even-length string with each pair of matching
- delimiters listed together, open first.
-
-
- >>> list(split_delimited('{}[]', ',', ''))
- ['']
- >>> list(split_delimited('', ',', 'foo,bar'))
- ['foo', 'bar']
- >>> list(split_delimited('[]', ',', 'foo,[bar, baz]'))
- ['foo', '[bar, baz]']
- >>> list(split_delimited('{}', ' ', '{Type Name} name Desc'))
- ['{Type Name}', 'name', 'Desc']
- >>> list(split_delimited('[]{}', ',', '[{foo,[bar, baz]}]'))
- ['[{foo,[bar, baz]}]']
-
- Two adjacent delimiters result in a zero-length string between them:
-
- >>> list(split_delimited('{}', ' ', '{Type Name} Desc'))
- ['{Type Name}', '', 'Desc']
-
- ``split_by`` may be a predicate function instead of a string, in which
- case it should return true on a character to split.
-
- >>> list(split_delimited('', lambda c: c in '[]{}, ', '[{foo,[bar, baz]}]'))
- ['', '', 'foo', '', 'bar', '', 'baz', '', '', '']
-
- """
- delims = [0] * (len(delimiters) // 2)
- actions = {}
- for i in range(0, len(delimiters), 2):
- actions[delimiters[i]] = (i // 2, 1)
- actions[delimiters[i + 1]] = (i // 2, -1)
-
- if isinstance(split_by, str):
- def split_fn(c):
- return c == split_by
- else:
- split_fn = split_by
- last = 0
-
- for i in range(len(text)):
- c = text[i]
- if split_fn(c) and not any(delims):
- yield text[last:i]
- last = i + 1
- try:
- which, dir = actions[c]
- delims[which] = delims[which] + dir
- except KeyError:
- pass # Normal character
- yield text[last:]
-
-
-def strip_stars(doc_comment):
- r"""
- Strip leading stars from a doc comment.
-
- >>> strip_stars('/** This is a comment. */')
- 'This is a comment.'
- >>> strip_stars('/**\n * This is a\n * multiline comment. */')
- 'This is a\n multiline comment.'
- >>> strip_stars('/** \n\t * This is a\n\t * multiline comment. \n*/')
- 'This is a\n multiline comment.'
-
- """
- return re.sub('\n\s*?\*\s*?', '\n', doc_comment[3:-2]).strip()
-
-
-def split_tag(section):
- """
- Split the JSDoc tag text (everything following the @) at the first
- whitespace. Returns a tuple of (tagname, body).
- """
- splitval = re.split('\s+', section, 1)
- tag, body = len(splitval) > 1 and splitval or (splitval[0], '')
- return tag.strip(), body.strip()
-
-
-FUNCTION_REGEXPS = [
- 'function (\w+)',
- '(\w+):\sfunction',
- '\.(\w+)\s*=\s*function',
-]
-
-
-def guess_function_name(next_line, regexps=FUNCTION_REGEXPS):
- """
- Attempt to determine the function name from the first code line
- following the comment. The patterns recognized are described by
- `regexps`, which defaults to FUNCTION_REGEXPS. If a match is successful,
- returns the function name. Otherwise, returns None.
- """
- for regexp in regexps:
- match = re.search(regexp, next_line)
- if match:
- return match.group(1)
- return None
-
-
-def guess_parameters(next_line):
- """
- Attempt to guess parameters based on the presence of a parenthesized
- group of identifiers. If successful, returns a list of parameter names;
- otherwise, returns None.
- """
- match = re.search('\(([\w\s,]+)\)', next_line)
- if match:
- return [arg.strip() for arg in match.group(1).split(',')]
- else:
- return None
-
-
-def parse_comment(doc_comment, next_line):
- r"""
- Split the raw comment text into a dictionary of tags. The main comment
- body is included as 'doc'.
-
- >>> comment = get_doc_comments(read_file('examples/module.js'))[4][0]
- >>> parse_comment(strip_stars(comment), '')['doc']
- 'This is the documentation for the fourth function.\n\n Since the function being documented is itself generated from another\n function, its name needs to be specified explicitly. using the @function tag'
- >>> parse_comment(strip_stars(comment), '')['function']
- 'not_auto_discovered'
-
- If there are multiple tags with the same name, they're included as a list:
-
- >>> parse_comment(strip_stars(comment), '')['param']
- ['{String} arg1 The first argument.', '{Int} arg2 The second argument.']
-
- """
- sections = re.split('\n\s*@', doc_comment)
- tags = {
- 'doc': sections[0].strip(),
- 'guessed_function': guess_function_name(next_line),
- 'guessed_params': guess_parameters(next_line)
- }
- for section in sections[1:]:
- tag, body = split_tag(section)
- if tag in tags:
- existing = tags[tag]
- try:
- existing.append(body)
- except AttributeError:
- tags[tag] = [existing, body]
- else:
- tags[tag] = body
- return tags
-
-
-#### Classes #####
-
-class CommentDoc(object):
- """
- Base class for all classes that represent a parsed comment of some sort.
- """
-
- def __init__(self, parsed_comment):
- self.parsed = parsed_comment
-
- def __str__(self):
- return "Docs for " + self.name
-
- def __repr__(self):
- return str(self)
-
- def __contains__(self, tag_name):
- return tag_name in self.parsed
-
- def __getitem__(self, tag_name):
- return self.get(tag_name)
-
- def get(self, tag_name, default=''):
- """
- Return the value of a particular tag, or None if that tag doesn't
- exist. Use 'doc' for the comment body itself.
- """
- return self.parsed.get(tag_name, default)
-
- def get_as_list(self, tag_name):
- """
- Return the value of a tag, making sure that it's a list. Absent
- tags are returned as an empty-list; single tags are returned as a
- one-element list.
-
- The returned list is a copy, and modifications do not affect the
- original object.
- """
- val = self.get(tag_name, [])
- if isinstance(val, list):
- return val[:]
- else:
- return [val]
-
- @property
- def doc(self):
- """
- Return the comment body.
- """
- return self.get('doc')
-
- @property
- def url(self):
- """
- Return a URL for the comment, within the page.
- """
- return '#' + self.name
-
- @property
- def see(self):
- """
- Return a list of all @see tags on the comment.
- """
- return self.get_as_list('see')
-
- def to_json(self):
- """
- Return a JSON representation of the CommentDoc. Keys are as per
- to_dict.
- """
- return json.dumps(self.to_dict())
-
- def to_dict(self):
- """
- Return a dictionary representation of the CommentDoc. The keys of
- this correspond to the tags in the comment, with the comment body in
- `doc`.
- """
- return self.parsed.copy()
-
-class ParamDoc(object):
- """
- Represents a parameter, option, or parameter-like object, basically
- anything that has a name, a type, and a description, separated by spaces.
- This is also used for return types and exceptions, which use an empty
- string for the name.
-
- >>> param = ParamDoc('{Array<DOM>} elems The elements to act upon')
- >>> param.name
- 'elems'
- >>> param.doc
- 'The elements to act upon'
- >>> param.type
- 'Array<DOM>'
-
- You can also omit the type: if the first element is not surrounded by
- curly braces, it's assumed to be the name instead:
-
- >>> param2 = ParamDoc('param1 The first param')
- >>> param2.type
- ''
- >>> param2.name
- 'param1'
- >>> param2.doc
- 'The first param'
-
- """
-
- def __init__(self, text):
- parsed = list(split_delimited('{}', ' ', text))
- if parsed[0].startswith('{') and parsed[0].endswith('}'):
- self.type = parsed[0][1:-1]
- self.name = parsed[1]
- self.doc = ' '.join(parsed[2:])
- else:
- self.type = ''
- self.name = parsed[0]
- self.doc = ' '.join(parsed[1:])
-
- def to_dict(self):
- """
- Convert this to a dict. Keys (all strings) are:
-
- - **name**: Parameter name
- - **type**: Parameter type
- - **doc**: Parameter description
- """
- return {
- 'name': self.name,
- 'type': self.type,
- 'doc': self.doc
- }
-
- def to_html(self, css_class=''):
- """
- Returns the parameter as a dt/dd pair.
- """
- if self.name and self.type:
- header_text = '%s (%s)' % (self.name, self.type)
- elif self.type:
- header_text = self.type
- else:
- header_text = self.name
- return '<dt>%s</dt><dd>%s</dd>' % (header_text, self.doc)
-
-
-##### DEPENDENCIES #####
-
-class CyclicDependency(Exception):
- """
- Exception raised if there is a cyclic dependency.
- """
-
- def __init__(self, remaining_dependencies):
- self.values = remaining_dependencies
-
- def __str__(self):
- return ('The following dependencies result in a cycle: '
- + ', '.join(self.values))
-
-
-class MissingDependency(Exception):
- """
- Exception raised if a file references a dependency that doesn't exist.
- """
-
- def __init__(self, file, dependency):
- self.file = file
- self.dependency = dependency
-
- def __str__(self):
- return "Couldn't find dependency %s when processing %s" % \
- (self.dependency, self.file)
-
-
-def build_dependency_graph(start_nodes, js_doc):
- """
- Build a graph where nodes are filenames and edges are reverse dependencies
- (so an edge from jquery.js to jquery.dimensions.js indicates that jquery.js
- must be included before jquery.dimensions.js). The graph is represented
- as a dictionary from filename to (in-degree, edges) pair, for ease of
- topological sorting. Also returns a list of nodes of degree zero.
- """
- queue = []
- dependencies = {}
- start_sort = []
-
- def add_vertex(file):
- in_degree = len(js_doc[file].module.dependencies)
- dependencies[file] = [in_degree, []]
- queue.append(file)
- if in_degree == 0:
- start_sort.append(file)
-
- def add_edge(from_file, to_file):
- dependencies[from_file][1].append(to_file)
-
- def is_in_graph(file):
- return file in dependencies
-
- for file in start_nodes:
- add_vertex(file)
- for file in queue:
- for dependency in js_doc[file].module.dependencies:
- if dependency not in js_doc:
- raise MissingDependency(file, dependency)
- if not is_in_graph(dependency):
- add_vertex(dependency)
- add_edge(dependency, file)
- return dependencies, start_sort
-
-
-def topological_sort(dependencies, start_nodes):
- """
- Perform a topological sort on the dependency graph `dependencies`, starting
- from list `start_nodes`.
- """
- retval = []
-
- def edges(node):
- return dependencies[node][1]
-
- def in_degree(node):
- return dependencies[node][0]
-
- def remove_incoming(node):
- dependencies[node][0] = in_degree(node) - 1
-
- while start_nodes:
- node = start_nodes.pop()
- retval.append(node)
- for child in edges(node):
- remove_incoming(child)
- if not in_degree(child):
- start_nodes.append(child)
- leftover_nodes = [node for node in dependencies.keys()
- if in_degree(node) > 0]
- if leftover_nodes:
- raise CyclicDependency(leftover_nodes)
- else:
- return retval
-
-
-def find_dependencies(start_nodes, js_doc):
- """
- Sort the dependency graph, taking in a list of starting module names and a
- CodeBaseDoc (or equivalent dictionary). Returns an ordered list of
- transitive dependencies such that no module appears before its
- dependencies.
- """
- return topological_sort(*build_dependency_graph(start_nodes, js_doc))
diff --git a/doc/_extensions/pyjsparser/LICENSE b/doc/_extensions/pyjsparser/LICENSE
deleted file mode 100644
index 5f5aff9f636..00000000000
--- a/doc/_extensions/pyjsparser/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
-MIT License
-
-Copyright (c) 2017 Piotr Dabkowski
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
diff --git a/doc/_extensions/pyjsparser/README b/doc/_extensions/pyjsparser/README
deleted file mode 100644
index 574593bbf2e..00000000000
--- a/doc/_extensions/pyjsparser/README
+++ /dev/null
@@ -1,4 +0,0 @@
-Vendoring of pyjsparser to add comments support as we need them for autojsdoc.
-
-Alternative: use https://github.com/Kronuz/esprima-python instead, seems to
-support comments though may be attaching them differently.
diff --git a/doc/_extensions/pyjsparser/__init__.py b/doc/_extensions/pyjsparser/__init__.py
deleted file mode 100644
index 19036bddbf1..00000000000
--- a/doc/_extensions/pyjsparser/__init__.py
+++ /dev/null
@@ -1,4 +0,0 @@
-s__all__ = ['PyJsParser', 'parse', 'JsSyntaxError']
-__author__ = 'Piotr Dabkowski'
-__version__ = '2.2.0'
-from .parser import PyJsParser, parse, JsSyntaxError
diff --git a/doc/_extensions/pyjsparser/parser.py b/doc/_extensions/pyjsparser/parser.py
deleted file mode 100644
index 69729c44889..00000000000
--- a/doc/_extensions/pyjsparser/parser.py
+++ /dev/null
@@ -1,2920 +0,0 @@
-# The MIT License
-#
-# Copyright 2014, 2015 Piotr Dabkowski
-#
-# Permission is hereby granted, free of charge, to any person obtaining
-# a copy of this software and associated documentation files (the 'Software'),
-# to deal in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
-# the Software, and to permit persons to whom the Software is furnished to do so, subject
-# to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in all copies or
-# substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
-# LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
-# OR THE USE OR OTHER DEALINGS IN THE SOFTWARE
-from __future__ import unicode_literals
-from .pyjsparserdata import *
-from .std_nodes import *
-from pprint import pprint
-import sys
-
-__all__ = ['PyJsParser', 'parse', 'ENABLE_JS2PY_ERRORS', 'ENABLE_PYIMPORT', 'JsSyntaxError']
-REGEXP_SPECIAL_SINGLE = ('\\', '^', '$', '*', '+', '?', '.', '[', ']', '(', ')', '{', '{', '|', '-')
-ENABLE_PYIMPORT = False
-ENABLE_JS2PY_ERRORS = False
-ESPRIMA_VERSION = '2.2.0'
-
-DEBUG = False
-# Small naming convention changes
-# len -> leng
-# id -> d
-# type -> typ
-# str -> st
-true = True
-false = False
-null = None
-
-
-class PyJsParser:
- """ Usage:
- parser = PyJsParser()
- parser.parse('var JavaScriptCode = 5.1')
- """
-
- def __init__(self):
- self.clean()
-
- def test(self, code):
- pprint(self.parse(code))
-
- def clean(self):
- self.strict = None
- self.sourceType = None
- self.index = 0
- self.lineNumber = 1
- self.lineStart = 0
- self.hasLineTerminator = None
- self.lastIndex = None
- self.lastLineNumber = None
- self.lastLineStart = None
- self.startIndex = None
- self.startLineNumber = None
- self.startLineStart = None
- self.scanning = None
- self.lookahead = None
- self.state = None
- self.extra = None
- self.isBindingElement = None
- self.isAssignmentTarget = None
- self.firstCoverInitializedNameError = None
-
- # 7.4 Comments
-
- def skipSingleLineComment(self, offset):
- start = self.index - offset;
- while self.index < self.length:
- ch = self.source[self.index];
- self.index += 1
- if isLineTerminator(ch):
- if (ord(ch) == 13 and ord(self.source[self.index]) == 10):
- self.index += 1
- self.lineNumber += 1
- self.hasLineTerminator = True
- self.lineStart = self.index
- return {
- 'type': 'Line',
- 'value': self.source[start + offset:self.index-2],
- 'leading': True,
- 'trailing': False,
- 'loc': None,
- }
-
- def skipMultiLineComment(self):
- start = self.index
- while self.index < self.length:
- ch = ord(self.source[self.index])
- if isLineTerminator(ch):
- if (ch == 0x0D and ord(self.source[self.index + 1]) == 0x0A):
- self.index += 1
- self.lineNumber += 1
- self.index += 1
- self.hasLineTerminator = True
- self.lineStart = self.index
- elif ch == 0x2A:
- # Block comment ends with '*/'.
- if ord(self.source[self.index + 1]) == 0x2F:
- self.index += 2
- return {
- 'type': 'Block',
- 'value': self.source[start:self.index-2],
- 'leading': True,
- 'trailing': False,
- 'loc': None,
- }
- self.index += 1
- else:
- self.index += 1
- self.tolerateUnexpectedToken()
-
- def skipComment(self):
- self.hasLineTerminator = False
- startIndex = self.index
- start = (self.index == 0)
- comments = []
- while self.index < self.length:
- ch = ord(self.source[self.index])
- if isWhiteSpace(ch):
- self.index += 1
- elif isLineTerminator(ch):
- self.hasLineTerminator = True
- self.index += 1
- if (ch == 0x0D and ord(self.source[self.index]) == 0x0A):
- self.index += 1
- self.lineNumber += 1
- self.lineStart = self.index
- start = True
- elif (ch == 0x2F): # U+002F is '/'
- ch = ord(self.source[self.index + 1])
- if (ch == 0x2F):
- self.index += 2
- comments.append(self.skipSingleLineComment(2))
- start = True
- elif (ch == 0x2A): # U+002A is '*'
- self.index += 2
- comments.append(self.skipMultiLineComment())
- else:
- break
- elif (start and ch == 0x2D): # U+002D is '-'
- # U+003E is '>'
- if (ord(self.source[self.index + 1]) == 0x2D) and (ord(self.source[self.index + 2]) == 0x3E):
- # '-->' is a single-line comment
- self.index += 3
- self.skipSingleLineComment(3)
- else:
- break
- elif (ch == 0x3C): # U+003C is '<'
- if self.source[self.index + 1: self.index + 4] == '!--':
- # <!--
- self.index += 4
- self.skipSingleLineComment(4)
- else:
- break
- else:
- break
- return [c for c in comments if c]
-
- def scanHexEscape(self, prefix):
- code = 0
- leng = 4 if (prefix == 'u') else 2
- for i in range(leng):
- if self.index < self.length and isHexDigit(self.source[self.index]):
- ch = self.source[self.index]
- self.index += 1
- code = code * 16 + HEX_CONV[ch]
- else:
- return ''
- return chr(code)
-
- def scanUnicodeCodePointEscape(self):
- ch = self.source[self.index]
- code = 0
- # At least, one hex digit is required.
- if ch == '}':
- self.throwUnexpectedToken()
- while (self.index < self.length):
- ch = self.source[self.index]
- self.index += 1
- if not isHexDigit(ch):
- break
- code = code * 16 + HEX_CONV[ch]
- if code > 0x10FFFF or ch != '}':
- self.throwUnexpectedToken()
- # UTF-16 Encoding
- if (code <= 0xFFFF):
- return chr(code)
- cu1 = ((code - 0x10000) >> 10) + 0xD800;
- cu2 = ((code - 0x10000) & 1023) + 0xDC00;
- return chr(cu1) + chr(cu2)
-
- def ccode(self, offset=0):
- return ord(self.source[self.index + offset])
-
- def log_err_case(self):
- if not DEBUG:
- return
- print('INDEX', self.index)
- print(self.source[self.index - 10:self.index + 10])
- print('')
-
- def at(self, loc):
- return None if loc >= self.length else self.source[loc]
-
- def substr(self, le, offset=0):
- return self.source[self.index + offset:self.index + offset + le]
-
- def getEscapedIdentifier(self):
- d = self.source[self.index]
- ch = ord(d)
- self.index += 1
- # '\u' (U+005C, U+0075) denotes an escaped character.
- if (ch == 0x5C):
- if (ord(self.source[self.index]) != 0x75):
- self.throwUnexpectedToken()
- self.index += 1
- ch = self.scanHexEscape('u')
- if not ch or ch == '\\' or not isIdentifierStart(ch[0]):
- self.throwUnexpectedToken()
- d = ch
- while (self.index < self.length):
- ch = self.ccode()
- if not isIdentifierPart(ch):
- break
- self.index += 1
- d += unichr(ch)
-
- # '\u' (U+005C, U+0075) denotes an escaped character.
- if (ch == 0x5C):
- d = d[0: len(d) - 1]
- if (self.ccode() != 0x75):
- self.throwUnexpectedToken()
- self.index += 1
- ch = self.scanHexEscape('u');
- if (not ch or ch == '\\' or not isIdentifierPart(ch[0])):
- self.throwUnexpectedToken()
- d += ch
- return d
-
- def getIdentifier(self):
- start = self.index
- self.index += 1
- while (self.index < self.length):
- ch = self.ccode()
- if (ch == 0x5C):
- # Blackslash (U+005C) marks Unicode escape sequence.
- self.index = start
- return self.getEscapedIdentifier()
- if (isIdentifierPart(ch)):
- self.index += 1
- else:
- break
- return self.source[start: self.index]
-
- def scanIdentifier(self):
- start = self.index
-
- # Backslash (U+005C) starts an escaped character.
- d = self.getEscapedIdentifier() if (self.ccode() == 0x5C) else self.getIdentifier()
-
- # There is no keyword or literal with only one character.
- # Thus, it must be an identifier.
- if (len(d) == 1):
- type = Token.Identifier
- elif (isKeyword(d)):
- type = Token.Keyword
- elif (d == 'null'):
- type = Token.NullLiteral
- elif (d == 'true' or d == 'false'):
- type = Token.BooleanLiteral
- else:
- type = Token.Identifier;
- return {
- 'type': type,
- 'value': d,
- 'lineNumber': self.lineNumber,
- 'lineStart': self.lineStart,
- 'start': start,
- 'end': self.index
- }
-
- # 7.7 Punctuators
-
- def scanPunctuator(self):
- token = {
- 'type': Token.Punctuator,
- 'value': '',
- 'lineNumber': self.lineNumber,
- 'lineStart': self.lineStart,
- 'start': self.index,
- 'end': self.index
- }
- # Check for most common single-character punctuators.
- st = self.source[self.index]
- if st == '{':
- self.state['curlyStack'].append('{')
- self.index += 1
- elif st == '}':
- self.index += 1
- self.state['curlyStack'].pop()
- elif st in ('.', '(', ')', ';', ',', '[', ']', ':', '?', '~'):
- self.index += 1
- else:
- # 4-character punctuator.
- st = self.substr(4)
- if (st == '>>>='):
- self.index += 4
- else:
- # 3-character punctuators.
- st = st[0:3]
- if st in ('===', '!==', '>>>', '<<=', '>>='):
- self.index += 3
- else:
- # 2-character punctuators.
- st = st[0:2]
- if st in ('&&', '||', '==', '!=', '+=', '-=', '*=', '/=', '++', '--', '<<', '>>', '&=', '|=', '^=',
- '%=', '<=', '>=', '=>'):
- self.index += 2
- else:
- # 1-character punctuators.
- st = self.source[self.index]
- if st in ('<', '>', '=', '!', '+', '-', '*', '%', '&', '|', '^', '/'):
- self.index += 1
- if self.index == token['start']:
- self.throwUnexpectedToken()
- token['end'] = self.index;
- token['value'] = st
- return token
-
- # 7.8.3 Numeric Literals
-
- def scanHexLiteral(self, start):
- number = ''
- while (self.index < self.length):
- if (not isHexDigit(self.source[self.index])):
- break
- number += self.source[self.index]
- self.index += 1
- if not number:
- self.throwUnexpectedToken()
- if isIdentifierStart(self.ccode()):
- self.throwUnexpectedToken()
- return {
- 'type': Token.NumericLiteral,
- 'value': int(number, 16),
- 'lineNumber': self.lineNumber,
- 'lineStart': self.lineStart,
- 'start': start,
- 'end': self.index}
-
- def scanBinaryLiteral(self, start):
- number = ''
- while (self.index < self.length):
- ch = self.source[self.index]
- if (ch != '0' and ch != '1'):
- break
- number += self.source[self.index]
- self.index += 1
-
- if not number:
- # only 0b or 0B
- self.throwUnexpectedToken()
- if (self.index < self.length):
- ch = self.source[self.index]
- # istanbul ignore else
- if (isIdentifierStart(ch) or isDecimalDigit(ch)):
- self.throwUnexpectedToken();
- return {
- 'type': Token.NumericLiteral,
- 'value': int(number, 2),
- 'lineNumber': self.lineNumber,
- 'lineStart': self.lineStart,
- 'start': start,
- 'end': self.index}
-
- def scanOctalLiteral(self, prefix, start):
- if isOctalDigit(prefix):
- octal = True
- number = '0' + self.source[self.index]
- self.index += 1
- else:
- octal = False
- self.index += 1
- number = ''
- while (self.index < self.length):
- if (not isOctalDigit(self.source[self.index])):
- break
- number += self.source[self.index]
- self.index += 1
- if (not octal and not number):
- # only 0o or 0O
- self.throwUnexpectedToken()
- if (isIdentifierStart(self.ccode()) or isDecimalDigit(self.ccode())):
- self.throwUnexpectedToken()
- return {
- 'type': Token.NumericLiteral,
- 'value': int(number, 8),
- 'lineNumber': self.lineNumber,
- 'lineStart': self.lineStart,
- 'start': start,
- 'end': self.index}
-
- def octalToDecimal(self, ch):
- # \0 is not octal escape sequence
- octal = (ch != '0')
- code = int(ch, 8)
-
- if (self.index < self.length and isOctalDigit(self.source[self.index])):
- octal = True
- code = code * 8 + int(self.source[self.index], 8)
- self.index += 1
-
- # 3 digits are only allowed when string starts
- # with 0, 1, 2, 3
- if (ch in '0123' and self.index < self.length and isOctalDigit(self.source[self.index])):
- code = code * 8 + int((self.source[self.index]), 8)
- self.index += 1
- return {
- 'code': code,
- 'octal': octal}
-
- def isImplicitOctalLiteral(self):
- # Implicit octal, unless there is a non-octal digit.
- # (Annex B.1.1 on Numeric Literals)
- for i in range(self.index + 1, self.length):
- ch = self.source[i];
- if (ch == '8' or ch == '9'):
- return False;
- if (not isOctalDigit(ch)):
- return True
- return True
-
- def scanNumericLiteral(self):
- ch = self.source[self.index]
- assert isDecimalDigit(ch) or (ch == '.'), 'Numeric literal must start with a decimal digit or a decimal point'
- start = self.index
- number = ''
- if ch != '.':
- number = self.source[self.index]
- self.index += 1
- ch = self.source[self.index]
- # Hex number starts with '0x'.
- # Octal number starts with '0'.
- # Octal number in ES6 starts with '0o'.
- # Binary number in ES6 starts with '0b'.
- if (number == '0'):
- if (ch == 'x' or ch == 'X'):
- self.index += 1
- return self.scanHexLiteral(start);
- if (ch == 'b' or ch == 'B'):
- self.index += 1
- return self.scanBinaryLiteral(start)
- if (ch == 'o' or ch == 'O'):
- return self.scanOctalLiteral(ch, start)
- if (isOctalDigit(ch)):
- if (self.isImplicitOctalLiteral()):
- return self.scanOctalLiteral(ch, start);
- while (isDecimalDigit(self.ccode())):
- number += self.source[self.index]
- self.index += 1
- ch = self.source[self.index];
- if (ch == '.'):
- number += self.source[self.index]
- self.index += 1
- while (isDecimalDigit(self.source[self.index])):
- number += self.source[self.index]
- self.index += 1
- ch = self.source[self.index]
- if (ch == 'e' or ch == 'E'):
- number += self.source[self.index]
- self.index += 1
- ch = self.source[self.index]
- if (ch == '+' or ch == '-'):
- number += self.source[self.index]
- self.index += 1
- if (isDecimalDigit(self.source[self.index])):
- while (isDecimalDigit(self.source[self.index])):
- number += self.source[self.index]
- self.index += 1
- else:
- self.throwUnexpectedToken()
- if (isIdentifierStart(self.source[self.index])):
- self.throwUnexpectedToken();
- return {
- 'type': Token.NumericLiteral,
- 'value': float(number),
- 'lineNumber': self.lineNumber,
- 'lineStart': self.lineStart,
- 'start': start,
- 'end': self.index}
-
- # 7.8.4 String Literals
-
- def _interpret_regexp(self, string, flags):
- '''Perform sctring escape - for regexp literals'''
- self.index = 0
- self.length = len(string)
- self.source = string
- self.lineNumber = 0
- self.lineStart = 0
- octal = False
- st = ''
- inside_square = 0
- while (self.index < self.length):
- template = '[%s]' if not inside_square else '%s'
- ch = self.source[self.index]
- self.index += 1
- if ch == '\\':
- ch = self.source[self.index]
- self.index += 1
- if (not isLineTerminator(ch)):
- if ch == 'u':
- digs = self.source[self.index:self.index + 4]
- if len(digs) == 4 and all(isHexDigit(d) for d in digs):
- st += template % chr(int(digs, 16))
- self.index += 4
- else:
- st += 'u'
- elif ch == 'x':
- digs = self.source[self.index:self.index + 2]
- if len(digs) == 2 and all(isHexDigit(d) for d in digs):
- st += template % chr(int(digs, 16))
- self.index += 2
- else:
- st += 'x'
- # special meaning - single char.
- elif ch == '0':
- st += '\\0'
- elif ch == 'n':
- st += '\\n'
- elif ch == 'r':
- st += '\\r'
- elif ch == 't':
- st += '\\t'
- elif ch == 'f':
- st += '\\f'
- elif ch == 'v':
- st += '\\v'
-
- # unescape special single characters like . so that they are interpreted literally
- elif ch in REGEXP_SPECIAL_SINGLE:
- st += '\\' + ch
-
- # character groups
- elif ch == 'b':
- st += '\\b'
- elif ch == 'B':
- st += '\\B'
- elif ch == 'w':
- st += '\\w'
- elif ch == 'W':
- st += '\\W'
- elif ch == 'd':
- st += '\\d'
- elif ch == 'D':
- st += '\\D'
- elif ch == 's':
- st += template % u' \f\n\r\t\v\u00a0\u1680\u180e\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff'
- elif ch == 'S':
- st += template % u'\u0000-\u0008\u000e-\u001f\u0021-\u009f\u00a1-\u167f\u1681-\u180d\u180f-\u1fff\u200b-\u2027\u202a-\u202e\u2030-\u205e\u2060-\u2fff\u3001-\ufefe\uff00-\uffff'
- else:
- if isDecimalDigit(ch):
- num = ch
- while self.index < self.length and isDecimalDigit(self.source[self.index]):
- num += self.source[self.index]
- self.index += 1
- st += '\\' + num
-
- else:
- st += ch # DONT ESCAPE!!!
- else:
- self.lineNumber += 1
- if (ch == '\r' and self.source[self.index] == '\n'):
- self.index += 1
- self.lineStart = self.index
- else:
- if ch == '[':
- inside_square = True
- elif ch == ']':
- inside_square = False
- st += ch
- # print string, 'was transformed to', st
- return st
-
- def scanStringLiteral(self):
- st = ''
- octal = False
-
- quote = self.source[self.index]
- assert quote == '\'' or quote == '"', 'String literal must starts with a quote'
- start = self.index;
- self.index += 1
-
- while (self.index < self.length):
- ch = self.source[self.index]
- self.index += 1
- if (ch == quote):
- quote = ''
- break
- elif (ch == '\\'):
- ch = self.source[self.index]
- self.index += 1
- if (not isLineTerminator(ch)):
- if ch in 'ux':
- if (self.source[self.index] == '{'):
- self.index += 1
- st += self.scanUnicodeCodePointEscape()
- else:
- unescaped = self.scanHexEscape(ch)
- if (not unescaped):
- self.throwUnexpectedToken() # with throw I don't know whats the difference
- st += unescaped
- elif ch == 'n':
- st += '\n';
- elif ch == 'r':
- st += '\r';
- elif ch == 't':
- st += '\t';
- elif ch == 'b':
- st += '\b';
- elif ch == 'f':
- st += '\f';
- elif ch == 'v':
- st += '\x0B'
- # elif ch in '89':
- # self.throwUnexpectedToken() # again with throw....
- else:
- if isOctalDigit(ch):
- octToDec = self.octalToDecimal(ch)
- octal = octToDec.get('octal') or octal
- st += unichr(octToDec['code'])
- else:
- st += ch
- else:
- self.lineNumber += 1
- if (ch == '\r' and self.source[self.index] == '\n'):
- self.index += 1
- self.lineStart = self.index
- elif isLineTerminator(ch):
- break
- else:
- st += ch;
- if (quote != ''):
- self.throwUnexpectedToken()
- return {
- 'type': Token.StringLiteral,
- 'value': st,
- 'octal': octal,
- 'lineNumber': self.lineNumber,
- 'lineStart': self.startLineStart,
- 'start': start,
- 'end': self.index}
-
- def scanTemplate(self):
- cooked = ''
- terminated = False
- tail = False
- start = self.index
- head = (self.source[self.index] == '`')
- rawOffset = 2
-
- self.index += 1
-
- while (self.index < self.length):
- ch = self.source[self.index]
- self.index += 1
- if (ch == '`'):
- rawOffset = 1;
- tail = True
- terminated = True
- break
- elif (ch == '$'):
- if (self.source[self.index] == '{'):
- self.state['curlyStack'].append('${')
- self.index += 1
- terminated = True
- break;
- cooked += ch
- elif (ch == '\\'):
- ch = self.source[self.index]
- self.index += 1
- if (not isLineTerminator(ch)):
- if ch == 'n':
- cooked += '\n'
- elif ch == 'r':
- cooked += '\r'
- elif ch == 't':
- cooked += '\t'
- elif ch in 'ux':
- if (self.source[self.index] == '{'):
- self.index += 1
- cooked += self.scanUnicodeCodePointEscape()
- else:
- restore = self.index
- unescaped = self.scanHexEscape(ch)
- if (unescaped):
- cooked += unescaped
- else:
- self.index = restore
- cooked += ch
- elif ch == 'b':
- cooked += '\b'
- elif ch == 'f':
- cooked += '\f'
- elif ch == 'v':
- cooked += '\v'
- else:
- if (ch == '0'):
- if isDecimalDigit(self.ccode()):
- # Illegal: \01 \02 and so on
- self.throwError(Messages.TemplateOctalLiteral)
- cooked += '\0'
- elif (isOctalDigit(ch)):
- # Illegal: \1 \2
- self.throwError(Messages.TemplateOctalLiteral)
- else:
- cooked += ch
- else:
- self.lineNumber += 1
- if (ch == '\r' and self.source[self.index] == '\n'):
- self.index += 1
- self.lineStart = self.index
- elif (isLineTerminator(ch)):
- self.lineNumber += 1
- if (ch == '\r' and self.source[self.index] == '\n'):
- self.index += 1
- self.lineStart = self.index
- cooked += '\n'
- else:
- cooked += ch;
- if (not terminated):
- self.throwUnexpectedToken()
-
- if (not head):
- self.state['curlyStack'].pop();
-
- return {
- 'type': Token.Template,
- 'value': {
- 'cooked': cooked,
- 'raw': self.source[start + 1:self.index - rawOffset]},
- 'head': head,
- 'tail': tail,
- 'lineNumber': self.lineNumber,
- 'lineStart': self.lineStart,
- 'start': start,
- 'end': self.index}
-
- def testRegExp(self, pattern, flags):
- # todo: you should return python regexp object
- return (pattern, flags)
-
- def scanRegExpBody(self):
- ch = self.source[self.index]
- assert ch == '/', 'Regular expression literal must start with a slash'
- st = ch
- self.index += 1
-
- classMarker = False
- terminated = False
- while (self.index < self.length):
- ch = self.source[self.index]
- self.index += 1
- st += ch
- if (ch == '\\'):
- ch = self.source[self.index]
- self.index += 1
- # ECMA-262 7.8.5
- if (isLineTerminator(ch)):
- self.throwUnexpectedToken(None, Messages.UnterminatedRegExp)
- st += ch
- elif (isLineTerminator(ch)):
- self.throwUnexpectedToken(None, Messages.UnterminatedRegExp)
- elif (classMarker):
- if (ch == ']'):
- classMarker = False
- else:
- if (ch == '/'):
- terminated = True
- break
- elif (ch == '['):
- classMarker = True;
- if (not terminated):
- self.throwUnexpectedToken(None, Messages.UnterminatedRegExp)
-
- # Exclude leading and trailing slash.
- body = st[1:-1]
- return {
- 'value': body,
- 'literal': st}
-
- def scanRegExpFlags(self):
- st = ''
- flags = ''
- while (self.index < self.length):
- ch = self.source[self.index]
- if (not isIdentifierPart(ch)):
- break
- self.index += 1
- if (ch == '\\' and self.index < self.length):
- ch = self.source[self.index]
- if (ch == 'u'):
- self.index += 1
- restore = self.index
- ch = self.scanHexEscape('u')
- if (ch):
- flags += ch
- st += '\\u'
- while restore < self.index:
- st += self.source[restore]
- restore += 1
- else:
- self.index = restore
- flags += 'u'
- st += '\\u'
- self.tolerateUnexpectedToken()
- else:
- st += '\\'
- self.tolerateUnexpectedToken()
- else:
- flags += ch
- st += ch
- return {
- 'value': flags,
- 'literal': st}
-
- def scanRegExp(self, comments):
- self.scanning = True
- self.lookahead = None
- comments.extend(self.skipComment())
- start = self.index
-
- body = self.scanRegExpBody()
- flags = self.scanRegExpFlags()
- value = self.testRegExp(body['value'], flags['value'])
- scanning = False
- return {
- 'literal': body['literal'] + flags['literal'],
- 'value': value,
- 'regex': {
- 'pattern': body['value'],
- 'flags': flags['value']
- },
- 'start': start,
- 'end': self.index,
- 'comments': comments}
-
- def collectRegex(self):
- return self.scanRegExp(self.skipComment())
-
- def isIdentifierName(self, token):
- return token['type'] in (1, 3, 4, 5)
-
- # def advanceSlash(self): ???
-
- def advanceWithComments(self, comments):
- token = self.advance()
- token['comments'] = comments
- return token
-
- def advance(self):
- if (self.index >= self.length):
- return {
- 'type': Token.EOF,
- 'lineNumber': self.lineNumber,
- 'lineStart': self.lineStart,
- 'start': self.index,
- 'end': self.index}
- ch = self.ccode()
-
- if isIdentifierStart(ch):
- token = self.scanIdentifier()
- if (self.strict and isStrictModeReservedWord(token['value'])):
- token['type'] = Token.Keyword
- return token
- # Very common: ( and ) and ;
- if (ch == 0x28 or ch == 0x29 or ch == 0x3B):
- return self.scanPunctuator()
-
- # String literal starts with single quote (U+0027) or double quote (U+0022).
- if (ch == 0x27 or ch == 0x22):
- return self.scanStringLiteral()
-
- # Dot (.) U+002E can also start a floating-point number, hence the need
- # to check the next character.
- if (ch == 0x2E):
- if (isDecimalDigit(self.ccode(1))):
- return self.scanNumericLiteral()
- return self.scanPunctuator();
-
- if (isDecimalDigit(ch)):
- return self.scanNumericLiteral()
-
- # Slash (/) U+002F can also start a regex.
- # if (extra.tokenize && ch == 0x2F):
- # return advanceSlash();
-
- # Template literals start with ` (U+0060) for template head
- # or } (U+007D) for template middle or template tail.
- if (ch == 0x60 or (ch == 0x7D and self.state['curlyStack'][len(self.state['curlyStack']) - 1] == '${')):
- return self.scanTemplate()
- return self.scanPunctuator();
-
- # def collectToken(self):
- # loc = {
- # 'start': {
- # 'line': self.lineNumber,
- # 'column': self.index - self.lineStart}}
- #
- # token = self.advance()
- #
- # loc['end'] = {
- # 'line': self.lineNumber,
- # 'column': self.index - self.lineStart}
- # if (token['type'] != Token.EOF):
- # value = self.source[token['start']: token['end']]
- # entry = {
- # 'type': TokenName[token['type']],
- # 'value': value,
- # 'range': [token['start'], token['end']],
- # 'loc': loc}
- # if (token.get('regex')):
- # entry['regex'] = {
- # 'pattern': token['regex']['pattern'],
- # 'flags': token['regex']['flags']}
- # self.extra['tokens'].append(entry)
- # return token;
-
-
- def lex(self):
- self.scanning = True
-
- self.lastIndex = self.index
- self.lastLineNumber = self.lineNumber
- self.lastLineStart = self.lineStart
-
- comments = self.skipComment()
-
- token = self.lookahead
-
- self.startIndex = self.index
- self.startLineNumber = self.lineNumber
- self.startLineStart = self.lineStart
-
- self.lookahead = self.advanceWithComments(comments)
- self.scanning = False
- return token
-
- def peek(self):
- self.scanning = True
-
- comments = self.skipComment()
-
- self.lastIndex = self.index
- self.lastLineNumber = self.lineNumber
- self.lastLineStart = self.lineStart
-
- self.startIndex = self.index
- self.startLineNumber = self.lineNumber
- self.startLineStart = self.lineStart
-
- self.lookahead = self.advanceWithComments(comments)
- self.scanning = False
-
- def createError(self, line, pos, description):
- global ENABLE_PYIMPORT
- if ENABLE_JS2PY_ERRORS:
- old_pyimport = ENABLE_PYIMPORT # ENABLE_PYIMPORT will be affected by js2py import
- self.log_err_case()
- try:
- from js2py.base import ERRORS, Js, JsToPyException
- except:
- raise Exception("ENABLE_JS2PY_ERRORS was set to True, but Js2Py was not found!")
- ENABLE_PYIMPORT = old_pyimport
- error = ERRORS['SyntaxError']('Line ' + str(line) + ': ' + str(description))
- error.put('index', Js(pos))
- error.put('lineNumber', Js(line))
- error.put('column', Js(pos - (self.lineStart if self.scanning else self.lastLineStart) + 1))
- error.put('description', Js(description))
- return JsToPyException(error)
- else:
- return JsSyntaxError('Line ' + str(line) + ': ' + str(description))
-
-
- # Throw an exception
-
- def throwError(self, messageFormat, *args):
- msg = messageFormat % tuple(str(e) for e in args)
- raise self.createError(self.lastLineNumber, self.lastIndex, msg);
-
- def tolerateError(self, messageFormat, *args):
- return self.throwError(messageFormat, *args)
-
- # Throw an exception because of the token.
-
- def unexpectedTokenError(self, token={}, message=''):
- msg = message or Messages.UnexpectedToken
- if (token):
- typ = token['type']
- if (not message):
- if typ == Token.EOF:
- msg = Messages.UnexpectedEOS
- elif (typ == Token.Identifier):
- msg = Messages.UnexpectedIdentifier
- elif (typ == Token.NumericLiteral):
- msg = Messages.UnexpectedNumber
- elif (typ == Token.StringLiteral):
- msg = Messages.UnexpectedString
- elif (typ == Token.Template):
- msg = Messages.UnexpectedTemplate
- else:
- msg = Messages.UnexpectedToken;
- if (typ == Token.Keyword):
- if (isFutureReservedWord(token['value'])):
- msg = Messages.UnexpectedReserved
- elif (self.strict and isStrictModeReservedWord(token['value'])):
- msg = Messages.StrictReservedWord
- value = token['value']['raw'] if (typ == Token.Template) else token.get('value')
- else:
- value = 'ILLEGAL'
- msg = msg.replace('%s', str(value))
-
- return (self.createError(token['lineNumber'], token['start'], msg) if (token and token.get('lineNumber')) else
- self.createError(self.lineNumber if self.scanning else self.lastLineNumber,
- self.index if self.scanning else self.lastIndex, msg))
-
- def throwUnexpectedToken(self, token={}, message=''):
- raise self.unexpectedTokenError(token, message)
-
- def tolerateUnexpectedToken(self, token={}, message=''):
- self.throwUnexpectedToken(token, message)
-
- # Expect the next token to match the specified punctuator.
- # If not, an exception will be thrown.
-
- def expect(self, value):
- token = self.lex()
- if (token['type'] != Token.Punctuator or token['value'] != value):
- self.throwUnexpectedToken(token)
-
- # /**
- # * @name expectCommaSeparator
- # * @description Quietly expect a comma when in tolerant mode, otherwise delegates
- # * to <code>expect(value)</code>
- # * @since 2.0
- # */
- def expectCommaSeparator(self):
- self.expect(',')
-
- # Expect the next token to match the specified keyword.
- # If not, an exception will be thrown.
-
- def expectKeyword(self, keyword):
- token = self.lex();
- if (token['type'] != Token.Keyword or token['value'] != keyword):
- self.throwUnexpectedToken(token)
-
- # Return true if the next token matches the specified punctuator.
-
- def match(self, value):
- return self.lookahead['type'] == Token.Punctuator and self.lookahead['value'] == value
-
- # Return true if the next token matches the specified keyword
-
- def matchKeyword(self, keyword):
- return self.lookahead['type'] == Token.Keyword and self.lookahead['value'] == keyword
-
- # Return true if the next token matches the specified contextual keyword
- # (where an identifier is sometimes a keyword depending on the context)
-
- def matchContextualKeyword(self, keyword):
- return self.lookahead['type'] == Token.Identifier and self.lookahead['value'] == keyword
-
- # Return true if the next token is an assignment operator
-
- def matchAssign(self):
- if (self.lookahead['type'] != Token.Punctuator):
- return False;
- op = self.lookahead['value']
- return op in ('=', '*=', '/=', '%=', '+=', '-=', '<<=', '>>=', '>>>=', '&=', '^=', '|=')
-
- def consumeSemicolon(self):
- # Catch the very common case first: immediately a semicolon (U+003B).
-
- if (self.at(self.startIndex) == ';' or self.match(';')):
- self.lex()
- return
-
- if (self.hasLineTerminator):
- return
-
- # TODO: FIXME(ikarienator): this is seemingly an issue in the previous location info convention.
- self.lastIndex = self.startIndex
- self.lastLineNumber = self.startLineNumber
- self.lastLineStart = self.startLineStart
-
- if (self.lookahead['type'] != Token.EOF and not self.match('}')):
- self.throwUnexpectedToken(self.lookahead)
-
- # // Cover grammar support.
- # //
- # // When an assignment expression position starts with an left parenthesis, the determination of the type
- # // of the syntax is to be deferred arbitrarily long until the end of the parentheses pair (plus a lookahead)
- # // or the first comma. This situation also defers the determination of all the expressions nested in the pair.
- # //
- # // There are three productions that can be parsed in a parentheses pair that needs to be determined
- # // after the outermost pair is closed. They are:
- # //
- # // 1. AssignmentExpression
- # // 2. BindingElements
- # // 3. AssignmentTargets
- # //
- # // In order to avoid exponential backtracking, we use two flags to denote if the production can be
- # // binding element or assignment target.
- # //
- # // The three productions have the relationship:
- # //
- # // BindingElements <= AssignmentTargets <= AssignmentExpression
- # //
- # // with a single exception that CoverInitializedName when used directly in an Expression, generates
- # // an early error. Therefore, we need the third state, firstCoverInitializedNameError, to track the
- # // first usage of CoverInitializedName and report it when we reached the end of the parentheses pair.
- # //
- # // isolateCoverGrammar function runs the given parser function with a new cover grammar context, and it does not
- # // effect the current flags. This means the production the parser parses is only used as an expression. Therefore
- # // the CoverInitializedName check is conducted.
- # //
- # // inheritCoverGrammar function runs the given parse function with a new cover grammar context, and it propagates
- # // the flags outside of the parser. This means the production the parser parses is used as a part of a potential
- # // pattern. The CoverInitializedName check is deferred.
-
- def isolateCoverGrammar(self, parser):
- oldIsBindingElement = self.isBindingElement
- oldIsAssignmentTarget = self.isAssignmentTarget
- oldFirstCoverInitializedNameError = self.firstCoverInitializedNameError
- self.isBindingElement = true
- self.isAssignmentTarget = true
- self.firstCoverInitializedNameError = null
- result = parser()
- if (self.firstCoverInitializedNameError != null):
- self.throwUnexpectedToken(self.firstCoverInitializedNameError)
- self.isBindingElement = oldIsBindingElement
- self.isAssignmentTarget = oldIsAssignmentTarget
- self.firstCoverInitializedNameError = oldFirstCoverInitializedNameError
- return result
-
- def inheritCoverGrammar(self, parser):
- oldIsBindingElement = self.isBindingElement
- oldIsAssignmentTarget = self.isAssignmentTarget
- oldFirstCoverInitializedNameError = self.firstCoverInitializedNameError
- self.isBindingElement = true
- self.isAssignmentTarget = true
- self.firstCoverInitializedNameError = null
- result = parser()
- self.isBindingElement = self.isBindingElement and oldIsBindingElement
- self.isAssignmentTarget = self.isAssignmentTarget and oldIsAssignmentTarget
- self.firstCoverInitializedNameError = oldFirstCoverInitializedNameError or self.firstCoverInitializedNameError
- return result
-
- def parseArrayPattern(self):
- node = Node()
- elements = []
- self.expect('[');
- while (not self.match(']')):
- if (self.match(',')):
- self.lex()
- elements.append(null)
- else:
- if (self.match('...')):
- restNode = Node()
- self.lex()
- rest = self.parseVariableIdentifier()
- elements.append(restNode.finishRestElement(rest))
- break
- else:
- elements.append(self.parsePatternWithDefault())
- if (not self.match(']')):
- self.expect(',')
- self.expect(']')
- return node.finishArrayPattern(elements)
-
- def parsePropertyPattern(self):
- node = Node()
- computed = self.match('[')
- if (self.lookahead['type'] == Token.Identifier):
- key = self.parseVariableIdentifier()
- if (self.match('=')):
- self.lex();
- init = self.parseAssignmentExpression()
- return node.finishProperty(
- 'init', key, false, WrappingNode(key).finishAssignmentPattern(key, init), false, false)
- elif (not self.match(':')):
- return node.finishProperty('init', key, false, key, false, true)
- else:
- key = self.parseObjectPropertyKey()
- self.expect(':')
- init = self.parsePatternWithDefault()
- return node.finishProperty('init', key, computed, init, false, false)
-
- def parseObjectPattern(self):
- node = Node()
- properties = []
- self.expect('{')
- while (not self.match('}')):
- properties.append(self.parsePropertyPattern())
- if (not self.match('}')):
- self.expect(',')
- self.lex()
- return node.finishObjectPattern(properties)
-
- def parsePattern(self):
- if (self.lookahead['type'] == Token.Identifier):
- return self.parseVariableIdentifier()
- elif (self.match('[')):
- return self.parseArrayPattern()
- elif (self.match('{')):
- return self.parseObjectPattern()
- self.throwUnexpectedToken(self.lookahead)
-
- def parsePatternWithDefault(self):
- startToken = self.lookahead
-
- pattern = self.parsePattern()
- if (self.match('=')):
- self.lex()
- right = self.isolateCoverGrammar(self.parseAssignmentExpression)
- pattern = WrappingNode(startToken).finishAssignmentPattern(pattern, right)
- return pattern
-
- # 11.1.4 Array Initialiser
-
- def parseArrayInitialiser(self):
- elements = []
- node = Node()
-
- self.expect('[')
-
- while (not self.match(']')):
- if (self.match(',')):
- self.lex()
- elements.append(null)
- elif (self.match('...')):
- restSpread = Node()
- self.lex()
- restSpread.finishSpreadElement(self.inheritCoverGrammar(self.parseAssignmentExpression))
- if (not self.match(']')):
- self.isAssignmentTarget = self.isBindingElement = false
- self.expect(',')
- elements.append(restSpread)
- else:
- elements.append(self.inheritCoverGrammar(self.parseAssignmentExpression))
- if (not self.match(']')):
- self.expect(',')
- self.lex();
-
- return node.finishArrayExpression(elements)
-
- # 11.1.5 Object Initialiser
-
- def parsePropertyFunction(self, node, paramInfo):
-
- self.isAssignmentTarget = self.isBindingElement = false;
-
- previousStrict = self.strict;
- body = self.isolateCoverGrammar(self.parseFunctionSourceElements);
-
- if (self.strict and paramInfo['firstRestricted']):
- self.tolerateUnexpectedToken(paramInfo['firstRestricted'], paramInfo.get('message'))
- if (self.strict and paramInfo.get('stricted')):
- self.tolerateUnexpectedToken(paramInfo.get('stricted'), paramInfo.get('message'));
-
- self.strict = previousStrict;
- return node.finishFunctionExpression(null, paramInfo.get('params'), paramInfo.get('defaults'), body)
-
- def parsePropertyMethodFunction(self):
- node = Node();
-
- params = self.parseParams(null);
- method = self.parsePropertyFunction(node, params);
- return method;
-
- def parseObjectPropertyKey(self):
- node = Node()
-
- token = self.lex();
-
- # // Note: This function is called only from parseObjectProperty(), where
- # // EOF and Punctuator tokens are already filtered out.
-
- typ = token['type']
-
- if typ in [Token.StringLiteral, Token.NumericLiteral]:
- if self.strict and token.get('octal'):
- self.tolerateUnexpectedToken(token, Messages.StrictOctalLiteral);
- return node.finishLiteral(token);
- elif typ in (Token.Identifier, Token.BooleanLiteral, Token.NullLiteral, Token.Keyword):
- return node.finishIdentifier(token['value']);
- elif typ == Token.Punctuator:
- if (token['value'] == '['):
- expr = self.isolateCoverGrammar(self.parseAssignmentExpression)
- self.expect(']')
- return expr
- self.throwUnexpectedToken(token)
-
- def lookaheadPropertyName(self):
- typ = self.lookahead['type']
- if typ in (Token.Identifier, Token.StringLiteral, Token.BooleanLiteral, Token.NullLiteral, Token.NumericLiteral,
- Token.Keyword):
- return true
- if typ == Token.Punctuator:
- return self.lookahead['value'] == '['
- return false
-
- # // This function is to try to parse a MethodDefinition as defined in 14.3. But in the case of object literals,
- # // it might be called at a position where there is in fact a short hand identifier pattern or a data property.
- # // This can only be determined after we consumed up to the left parentheses.
- # //
- # // In order to avoid back tracking, it returns `null` if the position is not a MethodDefinition and the caller
- # // is responsible to visit other options.
- def tryParseMethodDefinition(self, token, key, computed, node):
- if (token['type'] == Token.Identifier):
- # check for `get` and `set`;
-
- if (token['value'] == 'get' and self.lookaheadPropertyName()):
- computed = self.match('[');
- key = self.parseObjectPropertyKey()
- methodNode = Node()
- self.expect('(')
- self.expect(')')
- value = self.parsePropertyFunction(methodNode, {
- 'params': [],
- 'defaults': [],
- 'stricted': null,
- 'firstRestricted': null,
- 'message': null
- })
- return node.finishProperty('get', key, computed, value, false, false)
- elif (token['value'] == 'set' and self.lookaheadPropertyName()):
- computed = self.match('[')
- key = self.parseObjectPropertyKey()
- methodNode = Node()
- self.expect('(')
-
- options = {
- 'params': [],
- 'defaultCount': 0,
- 'defaults': [],
- 'firstRestricted': null,
- 'paramSet': {}
- }
- if (self.match(')')):
- self.tolerateUnexpectedToken(self.lookahead);
- else:
- self.parseParam(options);
- if (options['defaultCount'] == 0):
- options['defaults'] = []
- self.expect(')')
-
- value = self.parsePropertyFunction(methodNode, options);
- return node.finishProperty('set', key, computed, value, false, false);
- if (self.match('(')):
- value = self.parsePropertyMethodFunction();
- return node.finishProperty('init', key, computed, value, true, false)
- return null;
-
- def checkProto(self, key, computed, hasProto):
- if (computed == false and (key['type'] == Syntax.Identifier and key['name'] == '__proto__' or
- key['type'] == Syntax.Literal and key['value'] == '__proto__')):
- if (hasProto['value']):
- self.tolerateError(Messages.DuplicateProtoProperty);
- else:
- hasProto['value'] = true;
-
- def parseObjectProperty(self, hasProto):
- token = self.lookahead
- node = Node()
- node.comments = self.lookahead.get('comments', [])
-
- computed = self.match('[');
- key = self.parseObjectPropertyKey();
- maybeMethod = self.tryParseMethodDefinition(token, key, computed, node)
-
- if (maybeMethod):
- self.checkProto(maybeMethod['key'], maybeMethod['computed'], hasProto);
- return maybeMethod;
-
- # // init property or short hand property.
- self.checkProto(key, computed, hasProto);
-
- if (self.match(':')):
- self.lex();
- value = self.inheritCoverGrammar(self.parseAssignmentExpression)
- return node.finishProperty('init', key, computed, value, false, false)
-
- if (token['type'] == Token.Identifier):
- if (self.match('=')):
- self.firstCoverInitializedNameError = self.lookahead;
- self.lex();
- value = self.isolateCoverGrammar(self.parseAssignmentExpression);
- return node.finishProperty('init', key, computed,
- WrappingNode(token).finishAssignmentPattern(key, value), false, true)
- return node.finishProperty('init', key, computed, key, false, true)
- self.throwUnexpectedToken(self.lookahead)
-
- def parseObjectInitialiser(self):
- properties = []
- hasProto = {'value': false}
- node = Node();
- node.comments = self.lookahead.get('comments', [])
- self.expect('{');
- while (not self.match('}')):
- properties.append(self.parseObjectProperty(hasProto));
-
- if (not self.match('}')):
- self.expectCommaSeparator()
- self.expect('}');
- return node.finishObjectExpression(properties)
-
- def reinterpretExpressionAsPattern(self, expr):
- typ = (expr['type'])
- if typ in (Syntax.Identifier, Syntax.MemberExpression, Syntax.RestElement, Syntax.AssignmentPattern):
- pass
- elif typ == Syntax.SpreadElement:
- expr['type'] = Syntax.RestElement
- self.reinterpretExpressionAsPattern(expr.argument)
- elif typ == Syntax.ArrayExpression:
- expr['type'] = Syntax.ArrayPattern
- for i in range(len(expr['elements'])):
- if (expr['elements'][i] != null):
- self.reinterpretExpressionAsPattern(expr['elements'][i])
- elif typ == Syntax.ObjectExpression:
- expr['type'] = Syntax.ObjectPattern
- for i in range(len(expr['properties'])):
- self.reinterpretExpressionAsPattern(expr['properties'][i]['value']);
- elif Syntax.AssignmentExpression:
- expr['type'] = Syntax.AssignmentPattern;
- self.reinterpretExpressionAsPattern(expr['left'])
- else:
- # // Allow other node type for tolerant parsing.
- return
-
- def parseTemplateElement(self, option):
-
- if (self.lookahead['type'] != Token.Template or (option['head'] and not self.lookahead['head'])):
- self.throwUnexpectedToken()
-
- node = Node();
- token = self.lex();
-
- return node.finishTemplateElement({'raw': token['value']['raw'], 'cooked': token['value']['cooked']},
- token['tail'])
-
- def parseTemplateLiteral(self):
- node = Node()
-
- quasi = self.parseTemplateElement({'head': true})
- quasis = [quasi]
- expressions = []
-
- while (not quasi['tail']):
- expressions.append(self.parseExpression());
- quasi = self.parseTemplateElement({'head': false});
- quasis.append(quasi)
- return node.finishTemplateLiteral(quasis, expressions)
-
- # 11.1.6 The Grouping Operator
-
- def parseGroupExpression(self):
- self.expect('(');
-
- if (self.match(')')):
- self.lex();
- if (not self.match('=>')):
- self.expect('=>')
- return {
- 'type': PlaceHolders.ArrowParameterPlaceHolder,
- 'params': []}
-
- startToken = self.lookahead
- if (self.match('...')):
- expr = self.parseRestElement();
- self.expect(')');
- if (not self.match('=>')):
- self.expect('=>')
- return {
- 'type': PlaceHolders.ArrowParameterPlaceHolder,
- 'params': [expr]}
-
- self.isBindingElement = true;
- expr = self.inheritCoverGrammar(self.parseAssignmentExpression);
-
- if (self.match(',')):
- self.isAssignmentTarget = false;
- expressions = [expr]
-
- while (self.startIndex < self.length):
- if (not self.match(',')):
- break
- self.lex();
-
- if (self.match('...')):
- if (not self.isBindingElement):
- self.throwUnexpectedToken(self.lookahead)
- expressions.append(self.parseRestElement())
- self.expect(')');
- if (not self.match('=>')):
- self.expect('=>');
- self.isBindingElement = false
- for i in range(len(expressions)):
- self.reinterpretExpressionAsPattern(expressions[i])
- return {
- 'type': PlaceHolders.ArrowParameterPlaceHolder,
- 'params': expressions}
- expressions.append(self.inheritCoverGrammar(self.parseAssignmentExpression))
- expr = WrappingNode(startToken).finishSequenceExpression(expressions);
- self.expect(')')
-
- if (self.match('=>')):
- if (not self.isBindingElement):
- self.throwUnexpectedToken(self.lookahead);
- if (expr['type'] == Syntax.SequenceExpression):
- for i in range(len(expr.expressions)):
- self.reinterpretExpressionAsPattern(expr['expressions'][i])
- else:
- self.reinterpretExpressionAsPattern(expr);
- expr = {
- 'type': PlaceHolders.ArrowParameterPlaceHolder,
- 'params': expr['expressions'] if expr['type'] == Syntax.SequenceExpression else [expr]}
- self.isBindingElement = false
- return expr
-
- # 11.1 Primary Expressions
-
- def parsePrimaryExpression(self):
- if (self.match('(')):
- self.isBindingElement = false;
- return self.inheritCoverGrammar(self.parseGroupExpression)
- if (self.match('[')):
- return self.inheritCoverGrammar(self.parseArrayInitialiser)
-
- if (self.match('{')):
- return self.inheritCoverGrammar(self.parseObjectInitialiser)
-
- typ = self.lookahead['type']
- node = Node();
- node.comments = self.lookahead.get('comments', [])
-
- if (typ == Token.Identifier):
- expr = node.finishIdentifier(self.lex()['value']);
- elif (typ == Token.StringLiteral or typ == Token.NumericLiteral):
- self.isAssignmentTarget = self.isBindingElement = false
- if (self.strict and self.lookahead.get('octal')):
- self.tolerateUnexpectedToken(self.lookahead, Messages.StrictOctalLiteral)
- expr = node.finishLiteral(self.lex())
- elif (typ == Token.Keyword):
- self.isAssignmentTarget = self.isBindingElement = false
- if (self.matchKeyword('function')):
- return self.parseFunctionExpression()
- if (self.matchKeyword('this')):
- self.lex()
- return node.finishThisExpression()
- if (self.matchKeyword('class')):
- return self.parseClassExpression()
- self.throwUnexpectedToken(self.lex())
- elif (typ == Token.BooleanLiteral):
- isAssignmentTarget = self.isBindingElement = false
- token = self.lex();
- token['value'] = (token['value'] == 'true')
- expr = node.finishLiteral(token)
- elif (typ == Token.NullLiteral):
- self.isAssignmentTarget = self.isBindingElement = false
- token = self.lex()
- token['value'] = null;
- expr = node.finishLiteral(token)
- elif (self.match('/') or self.match('/=')):
- self.isAssignmentTarget = self.isBindingElement = false;
- self.index = self.startIndex;
- token = self.scanRegExp([]); # hehe, here you are!
- self.lex();
- expr = node.finishLiteral(token);
- elif (typ == Token.Template):
- expr = self.parseTemplateLiteral()
- else:
- self.throwUnexpectedToken(self.lex());
- return expr;
-
- # 11.2 Left-Hand-Side Expressions
-
- def parseArguments(self):
- args = [];
-
- self.expect('(');
- if (not self.match(')')):
- while (self.startIndex < self.length):
- args.append(self.isolateCoverGrammar(self.parseAssignmentExpression))
- if (self.match(')')):
- break
- self.expectCommaSeparator()
- self.expect(')')
- return args;
-
- def parseNonComputedProperty(self):
- node = Node()
-
- token = self.lex();
-
- if (not self.isIdentifierName(token)):
- self.throwUnexpectedToken(token)
- return node.finishIdentifier(token['value'])
-
- def parseNonComputedMember(self):
- self.expect('.')
- return self.parseNonComputedProperty();
-
- def parseComputedMember(self):
- self.expect('[')
-
- expr = self.isolateCoverGrammar(self.parseExpression)
- self.expect(']')
-
- return expr
-
- def parseNewExpression(self):
- node = Node()
- self.expectKeyword('new')
- callee = self.isolateCoverGrammar(self.parseLeftHandSideExpression)
- args = self.parseArguments() if self.match('(') else []
-
- self.isAssignmentTarget = self.isBindingElement = false
-
- return node.finishNewExpression(callee, args)
-
- def parseLeftHandSideExpressionAllowCall(self):
- previousAllowIn = self.state['allowIn']
-
- startToken = self.lookahead;
- self.state['allowIn'] = true;
-
- if (self.matchKeyword('super') and self.state['inFunctionBody']):
- expr = Node();
- self.lex();
- expr = expr.finishSuper()
- if (not self.match('(') and not self.match('.') and not self.match('[')):
- self.throwUnexpectedToken(self.lookahead);
- else:
- expr = self.inheritCoverGrammar(
- self.parseNewExpression if self.matchKeyword('new') else self.parsePrimaryExpression)
- while True:
- if (self.match('.')):
- self.isBindingElement = false;
- self.isAssignmentTarget = true;
- property = self.parseNonComputedMember();
- expr = WrappingNode(startToken).finishMemberExpression('.', expr, property)
- elif (self.match('(')):
- self.isBindingElement = false;
- self.isAssignmentTarget = false;
- args = self.parseArguments();
- expr = WrappingNode(startToken).finishCallExpression(expr, args)
- elif (self.match('[')):
- self.isBindingElement = false;
- self.isAssignmentTarget = true;
- property = self.parseComputedMember();
- expr = WrappingNode(startToken).finishMemberExpression('[', expr, property)
- elif (self.lookahead['type'] == Token.Template and self.lookahead['head']):
- quasi = self.parseTemplateLiteral()
- expr = WrappingNode(startToken).finishTaggedTemplateExpression(expr, quasi)
- else:
- break
- self.state['allowIn'] = previousAllowIn
-
- return expr
-
- def parseLeftHandSideExpression(self):
- assert self.state['allowIn'], 'callee of new expression always allow in keyword.'
-
- startToken = self.lookahead
-
- if (self.matchKeyword('super') and self.state['inFunctionBody']):
- expr = Node();
- self.lex();
- expr = expr.finishSuper();
- if (not self.match('[') and not self.match('.')):
- self.throwUnexpectedToken(self.lookahead)
- else:
- expr = self.inheritCoverGrammar(
- self.parseNewExpression if self.matchKeyword('new') else self.parsePrimaryExpression);
-
- while True:
- if (self.match('[')):
- self.isBindingElement = false;
- self.isAssignmentTarget = true;
- property = self.parseComputedMember();
- expr = WrappingNode(startToken).finishMemberExpression('[', expr, property)
- elif (self.match('.')):
- self.isBindingElement = false;
- self.isAssignmentTarget = true;
- property = self.parseNonComputedMember();
- expr = WrappingNode(startToken).finishMemberExpression('.', expr, property);
- elif (self.lookahead['type'] == Token.Template and self.lookahead['head']):
- quasi = self.parseTemplateLiteral();
- expr = WrappingNode(startToken).finishTaggedTemplateExpression(expr, quasi)
- else:
- break
- return expr
-
- # 11.3 Postfix Expressions
-
- def parsePostfixExpression(self):
- startToken = self.lookahead
-
- expr = self.inheritCoverGrammar(self.parseLeftHandSideExpressionAllowCall)
-
- if (not self.hasLineTerminator and self.lookahead['type'] == Token.Punctuator):
- if (self.match('++') or self.match('--')):
- # 11.3.1, 11.3.2
- if (self.strict and expr.type == Syntax.Identifier and isRestrictedWord(expr.name)):
- self.tolerateError(Messages.StrictLHSPostfix)
- if (not self.isAssignmentTarget):
- self.tolerateError(Messages.InvalidLHSInAssignment);
- self.isAssignmentTarget = self.isBindingElement = false;
-
- token = self.lex();
- expr = WrappingNode(startToken).finishPostfixExpression(token['value'], expr);
- return expr;
-
- # 11.4 Unary Operators
-
- def parseUnaryExpression(self):
-
- if (self.lookahead['type'] != Token.Punctuator and self.lookahead['type'] != Token.Keyword):
- expr = self.parsePostfixExpression();
- elif (self.match('++') or self.match('--')):
- startToken = self.lookahead;
- token = self.lex();
- expr = self.inheritCoverGrammar(self.parseUnaryExpression);
- # 11.4.4, 11.4.5
- if (self.strict and expr.type == Syntax.Identifier and isRestrictedWord(expr.name)):
- self.tolerateError(Messages.StrictLHSPrefix)
- if (not self.isAssignmentTarget):
- self.tolerateError(Messages.InvalidLHSInAssignment)
- expr = WrappingNode(startToken).finishUnaryExpression(token['value'], expr)
- self.isAssignmentTarget = self.isBindingElement = false
- elif (self.match('+') or self.match('-') or self.match('~') or self.match('!')):
- startToken = self.lookahead;
- token = self.lex();
- expr = self.inheritCoverGrammar(self.parseUnaryExpression);
- expr = WrappingNode(startToken).finishUnaryExpression(token['value'], expr)
- self.isAssignmentTarget = self.isBindingElement = false;
- elif (self.matchKeyword('delete') or self.matchKeyword('void') or self.matchKeyword('typeof')):
- startToken = self.lookahead;
- token = self.lex();
- expr = self.inheritCoverGrammar(self.parseUnaryExpression);
- expr = WrappingNode(startToken).finishUnaryExpression(token['value'], expr);
- if (self.strict and expr.operator == 'delete' and expr.argument.type == Syntax.Identifier):
- self.tolerateError(Messages.StrictDelete)
- self.isAssignmentTarget = self.isBindingElement = false;
- else:
- expr = self.parsePostfixExpression()
- return expr
-
- def binaryPrecedence(self, token, allowIn):
- prec = 0;
- typ = token['type']
- if (typ != Token.Punctuator and typ != Token.Keyword):
- return 0;
- val = token['value']
- if val == 'in' and not allowIn:
- return 0
- return PRECEDENCE.get(val, 0)
-
- # 11.5 Multiplicative Operators
- # 11.6 Additive Operators
- # 11.7 Bitwise Shift Operators
- # 11.8 Relational Operators
- # 11.9 Equality Operators
- # 11.10 Binary Bitwise Operators
- # 11.11 Binary Logical Operators
-
- def parseBinaryExpression(self):
-
- marker = self.lookahead;
- left = self.inheritCoverGrammar(self.parseUnaryExpression);
-
- token = self.lookahead;
- prec = self.binaryPrecedence(token, self.state['allowIn']);
- if (prec == 0):
- return left
- self.isAssignmentTarget = self.isBindingElement = false;
- token['prec'] = prec
- self.lex()
-
- markers = [marker, self.lookahead];
- right = self.isolateCoverGrammar(self.parseUnaryExpression);
-
- stack = [left, token, right];
-
- while True:
- prec = self.binaryPrecedence(self.lookahead, self.state['allowIn'])
- if not prec > 0:
- break
- # Reduce: make a binary expression from the three topmost entries.
- while ((len(stack) > 2) and (prec <= stack[len(stack) - 2]['prec'])):
- right = stack.pop();
- operator = stack.pop()['value']
- left = stack.pop()
- markers.pop()
- expr = WrappingNode(markers[len(markers) - 1]).finishBinaryExpression(operator, left, right)
- stack.append(expr)
-
- # Shift
- token = self.lex();
- token['prec'] = prec;
- stack.append(token);
- markers.append(self.lookahead);
- expr = self.isolateCoverGrammar(self.parseUnaryExpression);
- stack.append(expr);
-
- # Final reduce to clean-up the stack.
- i = len(stack) - 1;
- expr = stack[i]
- markers.pop()
- while (i > 1):
- expr = WrappingNode(markers.pop()).finishBinaryExpression(stack[i - 1]['value'], stack[i - 2], expr);
- i -= 2
- return expr
-
- # 11.12 Conditional Operator
-
- def parseConditionalExpression(self):
-
- startToken = self.lookahead
-
- expr = self.inheritCoverGrammar(self.parseBinaryExpression);
- if (self.match('?')):
- self.lex()
- previousAllowIn = self.state['allowIn']
- self.state['allowIn'] = true;
- consequent = self.isolateCoverGrammar(self.parseAssignmentExpression);
- self.state['allowIn'] = previousAllowIn;
- self.expect(':');
- alternate = self.isolateCoverGrammar(self.parseAssignmentExpression)
-
- expr = WrappingNode(startToken).finishConditionalExpression(expr, consequent, alternate);
- self.isAssignmentTarget = self.isBindingElement = false;
- return expr
-
- # [ES6] 14.2 Arrow Function
-
- def parseConciseBody(self):
- if (self.match('{')):
- return self.parseFunctionSourceElements()
- return self.isolateCoverGrammar(self.parseAssignmentExpression)
-
- def checkPatternParam(self, options, param):
- typ = param.type
- if typ == Syntax.Identifier:
- self.validateParam(options, param, param.name);
- elif typ == Syntax.RestElement:
- self.checkPatternParam(options, param.argument)
- elif typ == Syntax.AssignmentPattern:
- self.checkPatternParam(options, param.left)
- elif typ == Syntax.ArrayPattern:
- for i in range(len(param.elements)):
- if (param.elements[i] != null):
- self.checkPatternParam(options, param.elements[i]);
- else:
- assert typ == Syntax.ObjectPattern, 'Invalid type'
- for i in range(len(param.properties)):
- self.checkPatternParam(options, param.properties[i]['value']);
-
- def reinterpretAsCoverFormalsList(self, expr):
- defaults = [];
- defaultCount = 0;
- params = [expr];
- typ = expr.type
- if typ == Syntax.Identifier:
- pass
- elif typ == PlaceHolders.ArrowParameterPlaceHolder:
- params = expr.params
- else:
- return null
- options = {
- 'paramSet': {}}
- le = len(params)
- for i in range(le):
- param = params[i]
- if param.type == Syntax.AssignmentPattern:
- params[i] = param.left;
- defaults.append(param.right);
- defaultCount += 1
- self.checkPatternParam(options, param.left);
- else:
- self.checkPatternParam(options, param);
- params[i] = param;
- defaults.append(null);
- if (options.get('message') == Messages.StrictParamDupe):
- token = options.get('stricted') if self.strict else options['firstRestricted']
- self.throwUnexpectedToken(token, options.get('message'));
- if (defaultCount == 0):
- defaults = []
- return {
- 'params': params,
- 'defaults': defaults,
- 'stricted': options['stricted'],
- 'firstRestricted': options['firstRestricted'],
- 'message': options.get('message')}
-
- def parseArrowFunctionExpression(self, options, node):
- if (self.hasLineTerminator):
- self.tolerateUnexpectedToken(self.lookahead)
- self.expect('=>')
- previousStrict = self.strict;
-
- body = self.parseConciseBody();
-
- if (self.strict and options['firstRestricted']):
- self.throwUnexpectedToken(options['firstRestricted'], options.get('message'));
- if (self.strict and options['stricted']):
- self.tolerateUnexpectedToken(options['stricted'], options['message']);
-
- self.strict = previousStrict
-
- return node.finishArrowFunctionExpression(options['params'], options['defaults'], body,
- body.type != Syntax.BlockStatement)
-
- # 11.13 Assignment Operators
-
- def parseAssignmentExpression(self):
- startToken = self.lookahead;
- token = self.lookahead;
-
- expr = self.parseConditionalExpression();
-
- if (expr.type == PlaceHolders.ArrowParameterPlaceHolder or self.match('=>')):
- self.isAssignmentTarget = self.isBindingElement = false;
- lis = self.reinterpretAsCoverFormalsList(expr)
-
- if (lis):
- self.firstCoverInitializedNameError = null;
- return self.parseArrowFunctionExpression(lis, WrappingNode(startToken))
- return expr
-
- if (self.matchAssign()):
- if (not self.isAssignmentTarget):
- self.tolerateError(Messages.InvalidLHSInAssignment)
- # 11.13.1
-
- if (self.strict and expr.type == Syntax.Identifier and isRestrictedWord(expr.name)):
- self.tolerateUnexpectedToken(token, Messages.StrictLHSAssignment);
- if (not self.match('=')):
- self.isAssignmentTarget = self.isBindingElement = false;
- else:
- self.reinterpretExpressionAsPattern(expr)
- token = self.lex();
- right = self.isolateCoverGrammar(self.parseAssignmentExpression)
- expr = WrappingNode(startToken).finishAssignmentExpression(token['value'], expr, right);
- self.firstCoverInitializedNameError = null
- return expr
-
- # 11.14 Comma Operator
-
- def parseExpression(self):
- startToken = self.lookahead
- expr = self.isolateCoverGrammar(self.parseAssignmentExpression)
-
- if (self.match(',')):
- expressions = [expr];
-
- while (self.startIndex < self.length):
- if (not self.match(',')):
- break
- self.lex();
- expressions.append(self.isolateCoverGrammar(self.parseAssignmentExpression))
- expr = WrappingNode(startToken).finishSequenceExpression(expressions);
- return expr
-
- # 12.1 Block
-
- def parseStatementListItem(self):
- if (self.lookahead['type'] == Token.Keyword):
- val = (self.lookahead['value'])
- if val == 'export':
- if (self.sourceType != 'module'):
- self.tolerateUnexpectedToken(self.lookahead, Messages.IllegalExportDeclaration)
- return self.parseExportDeclaration();
- elif val == 'import':
- if (self.sourceType != 'module'):
- self.tolerateUnexpectedToken(self.lookahead, Messages.IllegalImportDeclaration);
- return self.parseImportDeclaration();
- elif val == 'const' or val == 'let':
- return self.parseLexicalDeclaration({'inFor': false});
- elif val == 'function':
- return self.parseFunctionDeclaration(Node());
- elif val == 'class':
- return self.parseClassDeclaration();
- elif ENABLE_PYIMPORT and val == 'pyimport': # <<<<< MODIFIED HERE
- return self.parsePyimportStatement()
- return self.parseStatement();
-
- def parsePyimportStatement(self):
- print(ENABLE_PYIMPORT)
- assert ENABLE_PYIMPORT
- n = Node()
- self.lex()
- n.finishPyimport(self.parseVariableIdentifier())
- self.consumeSemicolon()
- return n
-
- def parseStatementList(self):
- list = [];
- while (self.startIndex < self.length):
- if (self.match('}')):
- break
- list.append(self.parseStatementListItem())
- return list
-
- def parseBlock(self):
- node = Node();
-
- self.expect('{');
-
- block = self.parseStatementList()
-
- self.expect('}');
-
- return node.finishBlockStatement(block);
-
- # 12.2 Variable Statement
-
- def parseVariableIdentifier(self):
- node = Node()
-
- token = self.lex()
-
- if (token['type'] != Token.Identifier):
- if (self.strict and token['type'] == Token.Keyword and isStrictModeReservedWord(token['value'])):
- self.tolerateUnexpectedToken(token, Messages.StrictReservedWord);
- else:
- self.throwUnexpectedToken(token)
- return node.finishIdentifier(token['value'])
-
- def parseVariableDeclaration(self):
- init = null
- node = Node();
- d = self.parsePattern();
-
- # 12.2.1
- if (self.strict and isRestrictedWord(d.name)):
- self.tolerateError(Messages.StrictVarName);
-
- if (self.match('=')):
- self.lex();
- init = self.isolateCoverGrammar(self.parseAssignmentExpression);
- elif (d.type != Syntax.Identifier):
- self.expect('=')
- return node.finishVariableDeclarator(d, init)
-
- def parseVariableDeclarationList(self):
- lis = []
-
- while True:
- lis.append(self.parseVariableDeclaration())
- if (not self.match(',')):
- break
- self.lex();
- if not (self.startIndex < self.length):
- break
-
- return lis;
-
- def parseVariableStatement(self, node):
- self.expectKeyword('var')
- declarations = self.parseVariableDeclarationList()
-
- self.consumeSemicolon()
-
- return node.finishVariableDeclaration(declarations)
-
- def parseLexicalBinding(self, kind, options):
- init = null
- node = Node()
-
- d = self.parsePattern();
-
- # 12.2.1
- if (self.strict and d.type == Syntax.Identifier and isRestrictedWord(d.name)):
- self.tolerateError(Messages.StrictVarName);
-
- if (kind == 'const'):
- if (not self.matchKeyword('in')):
- self.expect('=')
- init = self.isolateCoverGrammar(self.parseAssignmentExpression)
- elif ((not options['inFor'] and d.type != Syntax.Identifier) or self.match('=')):
- self.expect('=');
- init = self.isolateCoverGrammar(self.parseAssignmentExpression);
- return node.finishVariableDeclarator(d, init)
-
- def parseBindingList(self, kind, options):
- list = [];
-
- while True:
- list.append(self.parseLexicalBinding(kind, options));
- if (not self.match(',')):
- break
- self.lex();
- if not (self.startIndex < self.length):
- break
- return list;
-
- def parseLexicalDeclaration(self, options):
- node = Node();
-
- kind = self.lex()['value']
- assert kind == 'let' or kind == 'const', 'Lexical declaration must be either let or const'
- declarations = self.parseBindingList(kind, options);
- self.consumeSemicolon();
- return node.finishLexicalDeclaration(declarations, kind);
-
- def parseRestElement(self):
- node = Node();
-
- self.lex();
-
- if (self.match('{')):
- self.throwError(Messages.ObjectPatternAsRestParameter)
- param = self.parseVariableIdentifier();
- if (self.match('=')):
- self.throwError(Messages.DefaultRestParameter);
-
- if (not self.match(')')):
- self.throwError(Messages.ParameterAfterRestParameter);
- return node.finishRestElement(param);
-
- # 12.3 Empty Statement
-
- def parseEmptyStatement(self, node):
- self.expect(';');
- return node.finishEmptyStatement()
-
- # 12.4 Expression Statement
-
- def parseExpressionStatement(self, node):
- expr = self.parseExpression();
- self.consumeSemicolon();
- return node.finishExpressionStatement(expr);
-
- # 12.5 If statement
-
- def parseIfStatement(self, node):
- self.expectKeyword('if');
-
- self.expect('(');
-
- test = self.parseExpression();
-
- self.expect(')');
-
- consequent = self.parseStatement();
-
- if (self.matchKeyword('else')):
- self.lex();
- alternate = self.parseStatement();
- else:
- alternate = null;
- return node.finishIfStatement(test, consequent, alternate)
-
- # 12.6 Iteration Statements
-
- def parseDoWhileStatement(self, node):
-
- self.expectKeyword('do')
-
- oldInIteration = self.state['inIteration']
- self.state['inIteration'] = true
-
- body = self.parseStatement();
-
- self.state['inIteration'] = oldInIteration;
-
- self.expectKeyword('while');
-
- self.expect('(');
-
- test = self.parseExpression();
-
- self.expect(')')
-
- if (self.match(';')):
- self.lex()
- return node.finishDoWhileStatement(body, test)
-
- def parseWhileStatement(self, node):
-
- self.expectKeyword('while')
-
- self.expect('(')
-
- test = self.parseExpression()
-
- self.expect(')')
-
- oldInIteration = self.state['inIteration']
- self.state['inIteration'] = true
-
- body = self.parseStatement()
-
- self.state['inIteration'] = oldInIteration
-
- return node.finishWhileStatement(test, body)
-
- def parseForStatement(self, node):
- previousAllowIn = self.state['allowIn']
-
- init = test = update = null
-
- self.expectKeyword('for')
-
- self.expect('(')
-
- if (self.match(';')):
- self.lex()
- else:
- if (self.matchKeyword('var')):
- init = Node()
- self.lex()
-
- self.state['allowIn'] = false;
- init = init.finishVariableDeclaration(self.parseVariableDeclarationList())
- self.state['allowIn'] = previousAllowIn
-
- if (len(init.declarations) == 1 and self.matchKeyword('in')):
- self.lex()
- left = init
- right = self.parseExpression()
- init = null
- else:
- self.expect(';')
- elif (self.matchKeyword('const') or self.matchKeyword('let')):
- init = Node()
- kind = self.lex()['value']
-
- self.state['allowIn'] = false
- declarations = self.parseBindingList(kind, {'inFor': true})
- self.state['allowIn'] = previousAllowIn
-
- if (len(declarations) == 1 and declarations[0].init == null and self.matchKeyword('in')):
- init = init.finishLexicalDeclaration(declarations, kind);
- self.lex();
- left = init;
- right = self.parseExpression();
- init = null;
- else:
- self.consumeSemicolon();
- init = init.finishLexicalDeclaration(declarations, kind);
- else:
- initStartToken = self.lookahead
- self.state['allowIn'] = false
- init = self.inheritCoverGrammar(self.parseAssignmentExpression);
- self.state['allowIn'] = previousAllowIn;
-
- if (self.matchKeyword('in')):
- if (not self.isAssignmentTarget):
- self.tolerateError(Messages.InvalidLHSInForIn)
- self.lex();
- self.reinterpretExpressionAsPattern(init);
- left = init;
- right = self.parseExpression();
- init = null;
- else:
- if (self.match(',')):
- initSeq = [init];
- while (self.match(',')):
- self.lex();
- initSeq.append(self.isolateCoverGrammar(self.parseAssignmentExpression))
- init = WrappingNode(initStartToken).finishSequenceExpression(initSeq)
- self.expect(';');
-
- if ('left' not in locals()):
- if (not self.match(';')):
- test = self.parseExpression();
-
- self.expect(';');
-
- if (not self.match(')')):
- update = self.parseExpression();
-
- self.expect(')');
-
- oldInIteration = self.state['inIteration']
- self.state['inIteration'] = true;
-
- body = self.isolateCoverGrammar(self.parseStatement)
-
- self.state['inIteration'] = oldInIteration;
-
- return node.finishForStatement(init, test, update, body) if (
- 'left' not in locals()) else node.finishForInStatement(left, right, body);
-
- # 12.7 The continue statement
-
- def parseContinueStatement(self, node):
- label = null
-
- self.expectKeyword('continue');
-
- # Optimize the most common form: 'continue;'.
- if ord(self.source[self.startIndex]) == 0x3B:
- self.lex();
- if (not self.state['inIteration']):
- self.throwError(Messages.IllegalContinue)
- return node.finishContinueStatement(null)
- if (self.hasLineTerminator):
- if (not self.state['inIteration']):
- self.throwError(Messages.IllegalContinue);
- return node.finishContinueStatement(null);
-
- if (self.lookahead['type'] == Token.Identifier):
- label = self.parseVariableIdentifier();
-
- key = '$' + label.name;
- if not key in self.state['labelSet']: # todo make sure its correct!
- self.throwError(Messages.UnknownLabel, label.name);
- self.consumeSemicolon()
-
- if (label == null and not self.state['inIteration']):
- self.throwError(Messages.IllegalContinue)
- return node.finishContinueStatement(label)
-
- # 12.8 The break statement
-
- def parseBreakStatement(self, node):
- label = null
-
- self.expectKeyword('break');
-
- # Catch the very common case first: immediately a semicolon (U+003B).
- if (ord(self.source[self.lastIndex]) == 0x3B):
- self.lex();
-
- if (not (self.state['inIteration'] or self.state['inSwitch'])):
- self.throwError(Messages.IllegalBreak)
- return node.finishBreakStatement(null)
- if (self.hasLineTerminator):
- if (not (self.state['inIteration'] or self.state['inSwitch'])):
- self.throwError(Messages.IllegalBreak);
- return node.finishBreakStatement(null);
- if (self.lookahead['type'] == Token.Identifier):
- label = self.parseVariableIdentifier();
-
- key = '$' + label.name;
- if not (key in self.state['labelSet']):
- self.throwError(Messages.UnknownLabel, label.name);
- self.consumeSemicolon();
-
- if (label == null and not (self.state['inIteration'] or self.state['inSwitch'])):
- self.throwError(Messages.IllegalBreak)
- return node.finishBreakStatement(label);
-
- # 12.9 The return statement
-
- def parseReturnStatement(self, node):
- argument = null;
-
- self.expectKeyword('return');
-
- if (not self.state['inFunctionBody']):
- self.tolerateError(Messages.IllegalReturn);
-
- # 'return' followed by a space and an identifier is very common.
- if (ord(self.source[self.lastIndex]) == 0x20):
- if (isIdentifierStart(self.source[self.lastIndex + 1])):
- argument = self.parseExpression();
- self.consumeSemicolon();
- return node.finishReturnStatement(argument)
- if (self.hasLineTerminator):
- # HACK
- return node.finishReturnStatement(null)
-
- if (not self.match(';')):
- if (not self.match('}') and self.lookahead['type'] != Token.EOF):
- argument = self.parseExpression();
- self.consumeSemicolon();
-
- return node.finishReturnStatement(argument);
-
- # 12.10 The with statement
-
- def parseWithStatement(self, node):
- if (self.strict):
- self.tolerateError(Messages.StrictModeWith)
-
- self.expectKeyword('with');
-
- self.expect('(');
-
- obj = self.parseExpression();
-
- self.expect(')');
-
- body = self.parseStatement();
-
- return node.finishWithStatement(obj, body);
-
- # 12.10 The swith statement
-
- def parseSwitchCase(self):
- consequent = []
- node = Node();
-
- if (self.matchKeyword('default')):
- self.lex();
- test = null;
- else:
- self.expectKeyword('case');
- test = self.parseExpression();
-
- self.expect(':');
-
- while (self.startIndex < self.length):
- if (self.match('}') or self.matchKeyword('default') or self.matchKeyword('case')):
- break
- statement = self.parseStatementListItem()
- consequent.append(statement)
- return node.finishSwitchCase(test, consequent)
-
- def parseSwitchStatement(self, node):
-
- self.expectKeyword('switch');
-
- self.expect('(');
-
- discriminant = self.parseExpression();
-
- self.expect(')');
-
- self.expect('{');
-
- cases = [];
-
- if (self.match('}')):
- self.lex();
- return node.finishSwitchStatement(discriminant, cases);
-
- oldInSwitch = self.state['inSwitch'];
- self.state['inSwitch'] = true;
- defaultFound = false;
-
- while (self.startIndex < self.length):
- if (self.match('}')):
- break;
- clause = self.parseSwitchCase();
- if (clause.test == null):
- if (defaultFound):
- self.throwError(Messages.MultipleDefaultsInSwitch);
- defaultFound = true;
- cases.append(clause);
-
- self.state['inSwitch'] = oldInSwitch;
-
- self.expect('}');
-
- return node.finishSwitchStatement(discriminant, cases);
-
- # 12.13 The throw statement
-
- def parseThrowStatement(self, node):
-
- self.expectKeyword('throw');
-
- if (self.hasLineTerminator):
- self.throwError(Messages.NewlineAfterThrow);
-
- argument = self.parseExpression();
-
- self.consumeSemicolon();
-
- return node.finishThrowStatement(argument);
-
- # 12.14 The try statement
-
- def parseCatchClause(self):
- node = Node();
-
- self.expectKeyword('catch');
-
- self.expect('(');
- if (self.match(')')):
- self.throwUnexpectedToken(self.lookahead);
- param = self.parsePattern();
-
- # 12.14.1
- if (self.strict and isRestrictedWord(param.name)):
- self.tolerateError(Messages.StrictCatchVariable);
-
- self.expect(')');
- body = self.parseBlock();
- return node.finishCatchClause(param, body);
-
- def parseTryStatement(self, node):
- handler = null
- finalizer = null;
-
- self.expectKeyword('try');
-
- block = self.parseBlock();
-
- if (self.matchKeyword('catch')):
- handler = self.parseCatchClause()
-
- if (self.matchKeyword('finally')):
- self.lex();
- finalizer = self.parseBlock();
-
- if (not handler and not finalizer):
- self.throwError(Messages.NoCatchOrFinally)
-
- return node.finishTryStatement(block, handler, finalizer)
-
- # 12.15 The debugger statement
-
- def parseDebuggerStatement(self, node):
- self.expectKeyword('debugger');
-
- self.consumeSemicolon();
-
- return node.finishDebuggerStatement();
-
- # 12 Statements
-
- def parseStatement(self):
- typ = self.lookahead['type']
-
- if (typ == Token.EOF):
- self.throwUnexpectedToken(self.lookahead)
-
- if (typ == Token.Punctuator and self.lookahead['value'] == '{'):
- return self.parseBlock()
-
- self.isAssignmentTarget = self.isBindingElement = true;
- node = Node();
- node.comments = self.lookahead.get('comments', [])
- val = self.lookahead['value']
-
- if (typ == Token.Punctuator):
- if val == ';':
- return self.parseEmptyStatement(node);
- elif val == '(':
- return self.parseExpressionStatement(node);
- elif (typ == Token.Keyword):
- if val == 'break':
- return self.parseBreakStatement(node);
- elif val == 'continue':
- return self.parseContinueStatement(node);
- elif val == 'debugger':
- return self.parseDebuggerStatement(node);
- elif val == 'do':
- return self.parseDoWhileStatement(node);
- elif val == 'for':
- return self.parseForStatement(node);
- elif val == 'function':
- return self.parseFunctionDeclaration(node);
- elif val == 'if':
- return self.parseIfStatement(node);
- elif val == 'return':
- return self.parseReturnStatement(node);
- elif val == 'switch':
- return self.parseSwitchStatement(node);
- elif val == 'throw':
- return self.parseThrowStatement(node);
- elif val == 'try':
- return self.parseTryStatement(node);
- elif val == 'var':
- return self.parseVariableStatement(node);
- elif val == 'while':
- return self.parseWhileStatement(node);
- elif val == 'with':
- return self.parseWithStatement(node);
-
- expr = self.parseExpression();
-
- # 12.12 Labelled Statements
- if ((expr.type == Syntax.Identifier) and self.match(':')):
- self.lex();
-
- key = '$' + expr.name
- if key in self.state['labelSet']:
- self.throwError(Messages.Redeclaration, 'Label', expr.name);
- self.state['labelSet'][key] = true
- labeledBody = self.parseStatement()
- del self.state['labelSet'][key]
- return node.finishLabeledStatement(expr, labeledBody)
- self.consumeSemicolon();
- return node.finishExpressionStatement(expr)
-
- # 13 Function Definition
-
- def parseFunctionSourceElements(self):
- body = []
- node = Node()
- firstRestricted = None
-
- self.expect('{')
-
- while (self.startIndex < self.length):
- if (self.lookahead['type'] != Token.StringLiteral):
- break
- token = self.lookahead;
-
- statement = self.parseStatementListItem()
- body.append(statement)
- if (statement.expression.type != Syntax.Literal):
- # this is not directive
- break
- directive = self.source[token['start'] + 1: token['end'] - 1]
- if (directive == 'use strict'):
- self.strict = true;
- if (firstRestricted):
- self.tolerateUnexpectedToken(firstRestricted, Messages.StrictOctalLiteral);
- else:
- if (not firstRestricted and token.get('octal')):
- firstRestricted = token;
-
- oldLabelSet = self.state['labelSet']
- oldInIteration = self.state['inIteration']
- oldInSwitch = self.state['inSwitch']
- oldInFunctionBody = self.state['inFunctionBody']
- oldParenthesisCount = self.state['parenthesizedCount']
-
- self.state['labelSet'] = {}
- self.state['inIteration'] = false
- self.state['inSwitch'] = false
- self.state['inFunctionBody'] = true
- self.state['parenthesizedCount'] = 0
-
- while (self.startIndex < self.length):
- if (self.match('}')):
- break
- body.append(self.parseStatementListItem())
- self.expect('}')
-
- self.state['labelSet'] = oldLabelSet;
- self.state['inIteration'] = oldInIteration;
- self.state['inSwitch'] = oldInSwitch;
- self.state['inFunctionBody'] = oldInFunctionBody;
- self.state['parenthesizedCount'] = oldParenthesisCount;
-
- return node.finishBlockStatement(body)
-
- def validateParam(self, options, param, name):
- key = '$' + name
- if (self.strict):
- if (isRestrictedWord(name)):
- options['stricted'] = param;
- options['message'] = Messages.StrictParamName
- if key in options['paramSet']:
- options['stricted'] = param;
- options['message'] = Messages.StrictParamDupe;
- elif (not options['firstRestricted']):
- if (isRestrictedWord(name)):
- options['firstRestricted'] = param;
- options['message'] = Messages.StrictParamName;
- elif (isStrictModeReservedWord(name)):
- options['firstRestricted'] = param;
- options['message'] = Messages.StrictReservedWord;
- elif key in options['paramSet']:
- options['firstRestricted'] = param
- options['message'] = Messages.StrictParamDupe;
- options['paramSet'][key] = true
-
- def parseParam(self, options):
- token = self.lookahead
- de = None
- if (token['value'] == '...'):
- param = self.parseRestElement();
- self.validateParam(options, param.argument, param.argument.name);
- options['params'].append(param);
- options['defaults'].append(null);
- return false
- param = self.parsePatternWithDefault();
- self.validateParam(options, token, token['value']);
-
- if (param.type == Syntax.AssignmentPattern):
- de = param.right;
- param = param.left;
- options['defaultCount'] += 1
- options['params'].append(param);
- options['defaults'].append(de)
- return not self.match(')')
-
- def parseParams(self, firstRestricted):
- options = {
- 'params': [],
- 'defaultCount': 0,
- 'defaults': [],
- 'firstRestricted': firstRestricted}
-
- self.expect('(');
-
- if (not self.match(')')):
- options['paramSet'] = {};
- while (self.startIndex < self.length):
- if (not self.parseParam(options)):
- break
- self.expect(',');
- self.expect(')');
-
- if (options['defaultCount'] == 0):
- options['defaults'] = [];
-
- return {
- 'params': options['params'],
- 'defaults': options['defaults'],
- 'stricted': options.get('stricted'),
- 'firstRestricted': options.get('firstRestricted'),
- 'message': options.get('message')}
-
- def parseFunctionDeclaration(self, node, identifierIsOptional=None):
- node.comments = self.lookahead.get('comments', [])
- d = null
- params = []
- defaults = []
- message = None
- firstRestricted = None
-
- self.expectKeyword('function');
- if (identifierIsOptional or not self.match('(')):
- token = self.lookahead;
- d = self.parseVariableIdentifier();
- if (self.strict):
- if (isRestrictedWord(token['value'])):
- self.tolerateUnexpectedToken(token, Messages.StrictFunctionName);
- else:
- if (isRestrictedWord(token['value'])):
- firstRestricted = token;
- message = Messages.StrictFunctionName;
- elif (isStrictModeReservedWord(token['value'])):
- firstRestricted = token;
- message = Messages.StrictReservedWord;
-
- tmp = self.parseParams(firstRestricted);
- params = tmp['params']
- defaults = tmp['defaults']
- stricted = tmp.get('stricted')
- firstRestricted = tmp['firstRestricted']
- if (tmp.get('message')):
- message = tmp['message'];
-
- previousStrict = self.strict;
- body = self.parseFunctionSourceElements();
- if (self.strict and firstRestricted):
- self.throwUnexpectedToken(firstRestricted, message);
-
- if (self.strict and stricted):
- self.tolerateUnexpectedToken(stricted, message);
- self.strict = previousStrict;
-
- return node.finishFunctionDeclaration(d, params, defaults, body);
-
- def parseFunctionExpression(self):
- id = null
- params = []
- defaults = []
- node = Node();
- node.comments = self.lookahead.get('comments', [])
- firstRestricted = None
- message = None
-
- self.expectKeyword('function');
-
- if (not self.match('(')):
- token = self.lookahead;
- id = self.parseVariableIdentifier();
- if (self.strict):
- if (isRestrictedWord(token['value'])):
- self.tolerateUnexpectedToken(token, Messages.StrictFunctionName);
- else:
- if (isRestrictedWord(token['value'])):
- firstRestricted = token;
- message = Messages.StrictFunctionName;
- elif (isStrictModeReservedWord(token['value'])):
- firstRestricted = token;
- message = Messages.StrictReservedWord;
- tmp = self.parseParams(firstRestricted);
- params = tmp['params']
- defaults = tmp['defaults']
- stricted = tmp.get('stricted')
- firstRestricted = tmp['firstRestricted']
- if (tmp.get('message')):
- message = tmp['message']
-
- previousStrict = self.strict;
- body = self.parseFunctionSourceElements();
- if (self.strict and firstRestricted):
- self.throwUnexpectedToken(firstRestricted, message);
- if (self.strict and stricted):
- self.tolerateUnexpectedToken(stricted, message);
- self.strict = previousStrict;
-
- return node.finishFunctionExpression(id, params, defaults, body);
-
- # todo Translate parse class functions!
-
- def parseClassExpression(self):
- raise NotImplementedError()
-
- def parseClassDeclaration(self):
- raise NotImplementedError()
-
- # 14 Program
-
- def parseScriptBody(self):
- body = []
- firstRestricted = None
-
- while (self.startIndex < self.length):
- token = self.lookahead;
- if (token['type'] != Token.StringLiteral):
- break
- statement = self.parseStatementListItem();
- body.append(statement);
- if (statement.expression.type != Syntax.Literal):
- # this is not directive
- break
- directive = self.source[token['start'] + 1: token['end'] - 1]
- if (directive == 'use strict'):
- self.strict = true;
- if (firstRestricted):
- self.tolerateUnexpectedToken(firstRestricted, Messages.StrictOctalLiteral)
- else:
- if (not firstRestricted and token.get('octal')):
- firstRestricted = token;
- while (self.startIndex < self.length):
- statement = self.parseStatementListItem();
- # istanbul ignore if
- if (statement is None):
- break
- body.append(statement);
- return body;
-
- def parseProgram(self):
- self.peek()
- node = Node()
-
- body = self.parseScriptBody()
- return node.finishProgram(body)
-
- # DONE!!!
- def parse(self, code, options={}):
- if options:
- raise NotImplementedError('Options not implemented! You can only use default settings.')
-
- self.clean()
- self.source = str(code) + ' \n ; //END' # I have to add it in order not to check for EOF every time
- self.index = 0
- self.lineNumber = 1 if len(self.source) > 0 else 0
- self.lineStart = 0
- self.startIndex = self.index
- self.startLineNumber = self.lineNumber;
- self.startLineStart = self.lineStart;
- self.length = len(self.source)
- self.lookahead = null;
- self.state = {
- 'allowIn': true,
- 'labelSet': {},
- 'inFunctionBody': false,
- 'inIteration': false,
- 'inSwitch': false,
- 'lastCommentStart': -1,
- 'curlyStack': [],
- 'parenthesizedCount': None}
- self.sourceType = 'script';
- self.strict = false;
- program = self.parseProgram();
- return node_to_dict(program)
-
-
-
-def parse(javascript_code):
- """Returns syntax tree of javascript_code.
- Same as PyJsParser().parse For your convenience :) """
- p = PyJsParser()
- return p.parse(javascript_code)
-
-
-if __name__ == '__main__':
- import time
-
- test_path = None
- if test_path:
- f = open(test_path, 'rb')
- x = f.read()
- f.close()
- else:
- x = 'var $ = "Hello!"'
- p = PyJsParser()
- t = time.time()
- res = p.parse(x)
- dt = time.time() - t + 0.000000001
- if test_path:
- print(len(res))
- else:
- pprint(res)
- print()
- print('Parsed everyting in', round(dt, 5), 'seconds.')
- print('Thats %d characters per second' % int(len(x) / dt))
-
-
-
diff --git a/doc/_extensions/pyjsparser/pyjsparserdata.py b/doc/_extensions/pyjsparser/pyjsparserdata.py
deleted file mode 100644
index 5db295a34b5..00000000000
--- a/doc/_extensions/pyjsparser/pyjsparserdata.py
+++ /dev/null
@@ -1,297 +0,0 @@
-# The MIT License
-#
-# Copyright 2014, 2015 Piotr Dabkowski
-#
-# Permission is hereby granted, free of charge, to any person obtaining
-# a copy of this software and associated documentation files (the 'Software'),
-# to deal in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
-# the Software, and to permit persons to whom the Software is furnished to do so, subject
-# to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in all copies or
-# substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
-# LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
-# OR THE USE OR OTHER DEALINGS IN THE SOFTWARE
-from __future__ import unicode_literals
-
-import sys
-import unicodedata
-from collections import defaultdict
-
-
-token = {
- 'BooleanLiteral': 1,
- 'EOF': 2,
- 'Identifier': 3,
- 'Keyword': 4,
- 'NullLiteral': 5,
- 'NumericLiteral': 6,
- 'Punctuator': 7,
- 'StringLiteral': 8,
- 'RegularExpression': 9,
- 'Template': 10
- }
-
-
-TokenName = dict((v,k) for k,v in token.items())
-
-FnExprTokens = ['(', '{', '[', 'in', 'typeof', 'instanceof', 'new',
- 'return', 'case', 'delete', 'throw', 'void',
- # assignment operators
- '=', '+=', '-=', '*=', '/=', '%=', '<<=', '>>=', '>>>=',
- '&=', '|=', '^=', ',',
- # binary/unary operators
- '+', '-', '*', '/', '%', '++', '--', '<<', '>>', '>>>', '&',
- '|', '^', '!', '~', '&&', '||', '?', ':', '===', '==', '>=',
- '<=', '<', '>', '!=', '!==']
-
-syntax= set(('AssignmentExpression',
- 'AssignmentPattern',
- 'ArrayExpression',
- 'ArrayPattern',
- 'ArrowFunctionExpression',
- 'BlockStatement',
- 'BinaryExpression',
- 'BreakStatement',
- 'CallExpression',
- 'CatchClause',
- 'ClassBody',
- 'ClassDeclaration',
- 'ClassExpression',
- 'ConditionalExpression',
- 'ContinueStatement',
- 'DoWhileStatement',
- 'DebuggerStatement',
- 'EmptyStatement',
- 'ExportAllDeclaration',
- 'ExportDefaultDeclaration',
- 'ExportNamedDeclaration',
- 'ExportSpecifier',
- 'ExpressionStatement',
- 'ForStatement',
- 'ForInStatement',
- 'FunctionDeclaration',
- 'FunctionExpression',
- 'Identifier',
- 'IfStatement',
- 'ImportDeclaration',
- 'ImportDefaultSpecifier',
- 'ImportNamespaceSpecifier',
- 'ImportSpecifier',
- 'Literal',
- 'LabeledStatement',
- 'LogicalExpression',
- 'MemberExpression',
- 'MethodDefinition',
- 'NewExpression',
- 'ObjectExpression',
- 'ObjectPattern',
- 'Program',
- 'Property',
- 'RestElement',
- 'ReturnStatement',
- 'SequenceExpression',
- 'SpreadElement',
- 'Super',
- 'SwitchCase',
- 'SwitchStatement',
- 'TaggedTemplateExpression',
- 'TemplateElement',
- 'TemplateLiteral',
- 'ThisExpression',
- 'ThrowStatement',
- 'TryStatement',
- 'UnaryExpression',
- 'UpdateExpression',
- 'VariableDeclaration',
- 'VariableDeclarator',
- 'WhileStatement',
- 'WithStatement'))
-
-
-# Error messages should be identical to V8.
-messages = {
- 'UnexpectedToken': 'Unexpected token %s',
- 'UnexpectedNumber': 'Unexpected number',
- 'UnexpectedString': 'Unexpected string',
- 'UnexpectedIdentifier': 'Unexpected identifier',
- 'UnexpectedReserved': 'Unexpected reserved word',
- 'UnexpectedTemplate': 'Unexpected quasi %s',
- 'UnexpectedEOS': 'Unexpected end of input',
- 'NewlineAfterThrow': 'Illegal newline after throw',
- 'InvalidRegExp': 'Invalid regular expression',
- 'UnterminatedRegExp': 'Invalid regular expression: missing /',
- 'InvalidLHSInAssignment': 'Invalid left-hand side in assignment',
- 'InvalidLHSInForIn': 'Invalid left-hand side in for-in',
- 'MultipleDefaultsInSwitch': 'More than one default clause in switch statement',
- 'NoCatchOrFinally': 'Missing catch or finally after try',
- 'UnknownLabel': 'Undefined label \'%s\'',
- 'Redeclaration': '%s \'%s\' has already been declared',
- 'IllegalContinue': 'Illegal continue statement',
- 'IllegalBreak': 'Illegal break statement',
- 'IllegalReturn': 'Illegal return statement',
- 'StrictModeWith': 'Strict mode code may not include a with statement',
- 'StrictCatchVariable': 'Catch variable may not be eval or arguments in strict mode',
- 'StrictVarName': 'Variable name may not be eval or arguments in strict mode',
- 'StrictParamName': 'Parameter name eval or arguments is not allowed in strict mode',
- 'StrictParamDupe': 'Strict mode function may not have duplicate parameter names',
- 'StrictFunctionName': 'Function name may not be eval or arguments in strict mode',
- 'StrictOctalLiteral': 'Octal literals are not allowed in strict mode.',
- 'StrictDelete': 'Delete of an unqualified identifier in strict mode.',
- 'StrictLHSAssignment': 'Assignment to eval or arguments is not allowed in strict mode',
- 'StrictLHSPostfix': 'Postfix increment/decrement may not have eval or arguments operand in strict mode',
- 'StrictLHSPrefix': 'Prefix increment/decrement may not have eval or arguments operand in strict mode',
- 'StrictReservedWord': 'Use of future reserved word in strict mode',
- 'TemplateOctalLiteral': 'Octal literals are not allowed in template strings.',
- 'ParameterAfterRestParameter': 'Rest parameter must be last formal parameter',
- 'DefaultRestParameter': 'Unexpected token =',
- 'ObjectPatternAsRestParameter': 'Unexpected token {',
- 'DuplicateProtoProperty': 'Duplicate __proto__ fields are not allowed in object literals',
- 'ConstructorSpecialMethod': 'Class constructor may not be an accessor',
- 'DuplicateConstructor': 'A class may only have one constructor',
- 'StaticPrototype': 'Classes may not have static property named prototype',
- 'MissingFromClause': 'Unexpected token',
- 'NoAsAfterImportNamespace': 'Unexpected token',
- 'InvalidModuleSpecifier': 'Unexpected token',
- 'IllegalImportDeclaration': 'Unexpected token',
- 'IllegalExportDeclaration': 'Unexpected token'}
-
-PRECEDENCE = {'||':1,
- '&&':2,
- '|':3,
- '^':4,
- '&':5,
- '==':6,
- '!=':6,
- '===':6,
- '!==':6,
- '<':7,
- '>':7,
- '<=':7,
- '>=':7,
- 'instanceof':7,
- 'in':7,
- '<<':8,
- '>>':8,
- '>>>':8,
- '+':9,
- '-':9,
- '*':11,
- '/':11,
- '%':11}
-
-class Token: pass
-class Syntax: pass
-class Messages: pass
-class PlaceHolders:
- ArrowParameterPlaceHolder = 'ArrowParameterPlaceHolder'
-
-for k,v in token.items():
- setattr(Token, k, v)
-
-for e in syntax:
- setattr(Syntax, e, e)
-
-for k,v in messages.items():
- setattr(Messages, k, v)
-
-#http://stackoverflow.com/questions/14245893/efficiently-list-all-characters-in-a-given-unicode-category
-BOM = u'\uFEFF'
-ZWJ = u'\u200D'
-ZWNJ = u'\u200C'
-TAB = u'\u0009'
-VT = u'\u000B'
-FF = u'\u000C'
-SP = u'\u0020'
-NBSP = u'\u00A0'
-LF = u'\u000A'
-CR = u'\u000D'
-LS = u'\u2028'
-PS = u'\u2029'
-
-U_CATEGORIES = defaultdict(list)
-for c in map(chr, range(sys.maxunicode + 1)):
- U_CATEGORIES[unicodedata.category(c)].append(c)
-UNICODE_LETTER = set(U_CATEGORIES['Lu']+U_CATEGORIES['Ll']+
- U_CATEGORIES['Lt']+U_CATEGORIES['Lm']+
- U_CATEGORIES['Lo']+U_CATEGORIES['Nl'])
-UNICODE_COMBINING_MARK = set(U_CATEGORIES['Mn']+U_CATEGORIES['Mc'])
-UNICODE_DIGIT = set(U_CATEGORIES['Nd'])
-UNICODE_CONNECTOR_PUNCTUATION = set(U_CATEGORIES['Pc'])
-IDENTIFIER_START = UNICODE_LETTER.union(set(('$','_', '\\'))) # and some fucking unicode escape sequence
-IDENTIFIER_PART = IDENTIFIER_START.union(UNICODE_COMBINING_MARK).union(UNICODE_DIGIT)\
- .union(UNICODE_CONNECTOR_PUNCTUATION).union(set((ZWJ, ZWNJ)))
-
-WHITE_SPACE = set((0x20, 0x09, 0x0B, 0x0C, 0xA0, 0x1680,
- 0x180E, 0x2000, 0x2001, 0x2002, 0x2003,
- 0x2004, 0x2005, 0x2006, 0x2007, 0x2008,
- 0x2009, 0x200A, 0x202F, 0x205F, 0x3000,
- 0xFEFF))
-
-LINE_TERMINATORS = set((0x0A, 0x0D, 0x2028, 0x2029))
-
-def isIdentifierStart(ch):
- return (ch if isinstance(ch, str) else chr(ch)) in IDENTIFIER_START
-
-def isIdentifierPart(ch):
- return (ch if isinstance(ch, str) else chr(ch)) in IDENTIFIER_PART
-
-def isWhiteSpace(ch):
- return (ord(ch) if isinstance(ch, str) else ch) in WHITE_SPACE
-
-def isLineTerminator(ch):
- return (ord(ch) if isinstance(ch, str) else ch) in LINE_TERMINATORS
-
-OCTAL = set(('0', '1', '2', '3', '4', '5', '6', '7'))
-DEC = set(('0', '1', '2', '3', '4', '5', '6', '7', '8', '9'))
-HEX = set('0123456789abcdefABCDEF')
-HEX_CONV = dict(('0123456789abcdef'[n],n) for n in range(16))
-for i,e in enumerate('ABCDEF', 10):
- HEX_CONV[e] = i
-
-
-def isDecimalDigit(ch):
- return (ch if isinstance(ch, str) else chr(ch)) in DEC
-
-def isHexDigit(ch):
- return (ch if isinstance(ch, str) else chr(ch)) in HEX
-
-def isOctalDigit(ch):
- return (ch if isinstance(ch, str) else chr(ch)) in OCTAL
-
-def isFutureReservedWord(w):
- return w in ('enum', 'export', 'import', 'super')
-
-
-RESERVED_WORD = set(('implements', 'interface', 'package', 'private', 'protected', 'public', 'static', 'yield', 'let'))
-def isStrictModeReservedWord(w):
- return w in RESERVED_WORD
-
-def isRestrictedWord(w):
- return w in ('eval', 'arguments')
-
-
-KEYWORDS = set(('if', 'in', 'do', 'var', 'for', 'new', 'try', 'let', 'this', 'else', 'case',
- 'void', 'with', 'enum', 'while', 'break', 'catch', 'throw', 'const', 'yield',
- 'class', 'super', 'return', 'typeof', 'delete', 'switch', 'export', 'import',
- 'default', 'finally', 'extends', 'function', 'continue', 'debugger', 'instanceof', 'pyimport'))
-def isKeyword(w):
- # 'const' is specialized as Keyword in V8.
- # 'yield' and 'let' are for compatibility with SpiderMonkey and ES.next.
- # Some others are from future reserved words.
- return w in KEYWORDS
-
-
-class JsSyntaxError(Exception): pass
-
-if __name__=='__main__':
- assert isLineTerminator('\n')
- assert isLineTerminator(0x0A)
- assert isIdentifierStart('$')
- assert isIdentifierStart(100)
- assert isWhiteSpace(' ')
diff --git a/doc/_extensions/pyjsparser/std_nodes.py b/doc/_extensions/pyjsparser/std_nodes.py
deleted file mode 100644
index bee67b86c6c..00000000000
--- a/doc/_extensions/pyjsparser/std_nodes.py
+++ /dev/null
@@ -1,470 +0,0 @@
-from .pyjsparserdata import *
-
-
-class BaseNode:
- def finish(self):
- pass
-
- def finishArrayExpression(self, elements):
- self.type = Syntax.ArrayExpression
- self.elements = elements
- self.finish()
- return self
-
- def finishArrayPattern(self, elements):
- self.type = Syntax.ArrayPattern
- self.elements = elements
- self.finish()
- return self
-
- def finishArrowFunctionExpression(self, params, defaults, body, expression):
- self.type = Syntax.ArrowFunctionExpression
- self.id = None
- self.params = params
- self.defaults = defaults
- self.body = body
- self.generator = False
- self.expression = expression
- self.finish()
- return self
-
- def finishAssignmentExpression(self, operator, left, right):
- self.type = Syntax.AssignmentExpression
- self.operator = operator
- self.left = left
- self.right = right
- self.finish()
- return self
-
- def finishAssignmentPattern(self, left, right):
- self.type = Syntax.AssignmentPattern
- self.left = left
- self.right = right
- self.finish()
- return self
-
- def finishBinaryExpression(self, operator, left, right):
- self.type = Syntax.LogicalExpression if (operator == '||' or operator == '&&') else Syntax.BinaryExpression
- self.operator = operator
- self.left = left
- self.right = right
- self.finish()
- return self
-
- def finishBlockStatement(self, body):
- self.type = Syntax.BlockStatement
- self.body = body
- self.finish()
- return self
-
- def finishBreakStatement(self, label):
- self.type = Syntax.BreakStatement
- self.label = label
- self.finish()
- return self
-
- def finishCallExpression(self, callee, args):
- self.type = Syntax.CallExpression
- self.callee = callee
- self.arguments = args
- self.finish()
- return self
-
- def finishCatchClause(self, param, body):
- self.type = Syntax.CatchClause
- self.param = param
- self.body = body
- self.finish()
- return self
-
- def finishClassBody(self, body):
- self.type = Syntax.ClassBody
- self.body = body
- self.finish()
- return self
-
- def finishClassDeclaration(self, id, superClass, body):
- self.type = Syntax.ClassDeclaration
- self.id = id
- self.superClass = superClass
- self.body = body
- self.finish()
- return self
-
- def finishClassExpression(self, id, superClass, body):
- self.type = Syntax.ClassExpression
- self.id = id
- self.superClass = superClass
- self.body = body
- self.finish()
- return self
-
- def finishConditionalExpression(self, test, consequent, alternate):
- self.type = Syntax.ConditionalExpression
- self.test = test
- self.consequent = consequent
- self.alternate = alternate
- self.finish()
- return self
-
- def finishContinueStatement(self, label):
- self.type = Syntax.ContinueStatement
- self.label = label
- self.finish()
- return self
-
- def finishDebuggerStatement(self, ):
- self.type = Syntax.DebuggerStatement
- self.finish()
- return self
-
- def finishDoWhileStatement(self, body, test):
- self.type = Syntax.DoWhileStatement
- self.body = body
- self.test = test
- self.finish()
- return self
-
- def finishEmptyStatement(self, ):
- self.type = Syntax.EmptyStatement
- self.finish()
- return self
-
- def finishExpressionStatement(self, expression):
- self.type = Syntax.ExpressionStatement
- self.expression = expression
- self.finish()
- return self
-
- def finishForStatement(self, init, test, update, body):
- self.type = Syntax.ForStatement
- self.init = init
- self.test = test
- self.update = update
- self.body = body
- self.finish()
- return self
-
- def finishForInStatement(self, left, right, body):
- self.type = Syntax.ForInStatement
- self.left = left
- self.right = right
- self.body = body
- self.each = False
- self.finish()
- return self
-
- def finishFunctionDeclaration(self, id, params, defaults, body):
- self.type = Syntax.FunctionDeclaration
- self.id = id
- self.params = params
- self.defaults = defaults
- self.body = body
- self.generator = False
- self.expression = False
- self.finish()
- return self
-
- def finishFunctionExpression(self, id, params, defaults, body):
- self.type = Syntax.FunctionExpression
- self.id = id
- self.params = params
- self.defaults = defaults
- self.body = body
- self.generator = False
- self.expression = False
- self.finish()
- return self
-
- def finishIdentifier(self, name):
- self.type = Syntax.Identifier
- self.name = name
- self.finish()
- return self
-
- def finishIfStatement(self, test, consequent, alternate):
- self.type = Syntax.IfStatement
- self.test = test
- self.consequent = consequent
- self.alternate = alternate
- self.finish()
- return self
-
- def finishLabeledStatement(self, label, body):
- self.type = Syntax.LabeledStatement
- self.label = label
- self.body = body
- self.finish()
- return self
-
- def finishLiteral(self, token):
- self.type = Syntax.Literal
- self.value = token['value']
- self.raw = None # todo fix it?
- if token.get('regex'):
- self.regex = token['regex']
- self.finish()
- return self
-
- def finishMemberExpression(self, accessor, object, property):
- self.type = Syntax.MemberExpression
- self.computed = accessor == '['
- self.object = object
- self.property = property
- self.finish()
- return self
-
- def finishNewExpression(self, callee, args):
- self.type = Syntax.NewExpression
- self.callee = callee
- self.arguments = args
- self.finish()
- return self
-
- def finishObjectExpression(self, properties):
- self.type = Syntax.ObjectExpression
- self.properties = properties
- self.finish()
- return self
-
- def finishObjectPattern(self, properties):
- self.type = Syntax.ObjectPattern
- self.properties = properties
- self.finish()
- return self
-
- def finishPostfixExpression(self, operator, argument):
- self.type = Syntax.UpdateExpression
- self.operator = operator
- self.argument = argument
- self.prefix = False
- self.finish()
- return self
-
- def finishProgram(self, body):
- self.type = Syntax.Program
- self.body = body
- self.finish()
- return self
-
- def finishPyimport(self, imp):
- self.type = 'PyimportStatement'
- self.imp = imp
- self.finish()
- return self
-
- def finishProperty(self, kind, key, computed, value, method, shorthand):
- self.type = Syntax.Property
- self.key = key
- self.computed = computed
- self.value = value
- self.kind = kind
- self.method = method
- self.shorthand = shorthand
- self.finish()
- return self
-
- def finishRestElement(self, argument):
- self.type = Syntax.RestElement
- self.argument = argument
- self.finish()
- return self
-
- def finishReturnStatement(self, argument):
- self.type = Syntax.ReturnStatement
- self.argument = argument
- self.finish()
- return self
-
- def finishSequenceExpression(self, expressions):
- self.type = Syntax.SequenceExpression
- self.expressions = expressions
- self.finish()
- return self
-
- def finishSpreadElement(self, argument):
- self.type = Syntax.SpreadElement
- self.argument = argument
- self.finish()
- return self
-
- def finishSwitchCase(self, test, consequent):
- self.type = Syntax.SwitchCase
- self.test = test
- self.consequent = consequent
- self.finish()
- return self
-
- def finishSuper(self, ):
- self.type = Syntax.Super
- self.finish()
- return self
-
- def finishSwitchStatement(self, discriminant, cases):
- self.type = Syntax.SwitchStatement
- self.discriminant = discriminant
- self.cases = cases
- self.finish()
- return self
-
- def finishTaggedTemplateExpression(self, tag, quasi):
- self.type = Syntax.TaggedTemplateExpression
- self.tag = tag
- self.quasi = quasi
- self.finish()
- return self
-
- def finishTemplateElement(self, value, tail):
- self.type = Syntax.TemplateElement
- self.value = value
- self.tail = tail
- self.finish()
- return self
-
- def finishTemplateLiteral(self, quasis, expressions):
- self.type = Syntax.TemplateLiteral
- self.quasis = quasis
- self.expressions = expressions
- self.finish()
- return self
-
- def finishThisExpression(self, ):
- self.type = Syntax.ThisExpression
- self.finish()
- return self
-
- def finishThrowStatement(self, argument):
- self.type = Syntax.ThrowStatement
- self.argument = argument
- self.finish()
- return self
-
- def finishTryStatement(self, block, handler, finalizer):
- self.type = Syntax.TryStatement
- self.block = block
- self.guardedHandlers = []
- self.handlers = [handler] if handler else []
- self.handler = handler
- self.finalizer = finalizer
- self.finish()
- return self
-
- def finishUnaryExpression(self, operator, argument):
- self.type = Syntax.UpdateExpression if (operator == '++' or operator == '--') else Syntax.UnaryExpression
- self.operator = operator
- self.argument = argument
- self.prefix = True
- self.finish()
- return self
-
- def finishVariableDeclaration(self, declarations):
- self.type = Syntax.VariableDeclaration
- self.declarations = declarations
- self.kind = 'var'
- self.finish()
- return self
-
- def finishLexicalDeclaration(self, declarations, kind):
- self.type = Syntax.VariableDeclaration
- self.declarations = declarations
- self.kind = kind
- self.finish()
- return self
-
- def finishVariableDeclarator(self, id, init):
- self.type = Syntax.VariableDeclarator
- self.id = id
- self.init = init
- self.finish()
- return self
-
- def finishWhileStatement(self, test, body):
- self.type = Syntax.WhileStatement
- self.test = test
- self.body = body
- self.finish()
- return self
-
- def finishWithStatement(self, object, body):
- self.type = Syntax.WithStatement
- self.object = object
- self.body = body
- self.finish()
- return self
-
- def finishExportSpecifier(self, local, exported):
- self.type = Syntax.ExportSpecifier
- self.exported = exported or local
- self.local = local
- self.finish()
- return self
-
- def finishImportDefaultSpecifier(self, local):
- self.type = Syntax.ImportDefaultSpecifier
- self.local = local
- self.finish()
- return self
-
- def finishImportNamespaceSpecifier(self, local):
- self.type = Syntax.ImportNamespaceSpecifier
- self.local = local
- self.finish()
- return self
-
- def finishExportNamedDeclaration(self, declaration, specifiers, src):
- self.type = Syntax.ExportNamedDeclaration
- self.declaration = declaration
- self.specifiers = specifiers
- self.source = src
- self.finish()
- return self
-
- def finishExportDefaultDeclaration(self, declaration):
- self.type = Syntax.ExportDefaultDeclaration
- self.declaration = declaration
- self.finish()
- return self
-
- def finishExportAllDeclaration(self, src):
- self.type = Syntax.ExportAllDeclaration
- self.source = src
- self.finish()
- return self
-
- def finishImportSpecifier(self, local, imported):
- self.type = Syntax.ImportSpecifier
- self.local = local or imported
- self.imported = imported
- self.finish()
- return self
-
- def finishImportDeclaration(self, specifiers, src):
- self.type = Syntax.ImportDeclaration
- self.specifiers = specifiers
- self.source = src
- self.finish()
- return self
-
- def __getitem__(self, item):
- return getattr(self, item)
-
- def __setitem__(self, key, value):
- setattr(self, key, value)
-
-class Node(BaseNode):
- pass
-
-
-class WrappingNode(BaseNode):
- def __init__(self, startToken=None):
- pass
-
-
-def node_to_dict(node): # extremely important for translation speed
- if isinstance(node, list):
- return [node_to_dict(e) for e in node]
- elif isinstance(node, dict):
- return dict((k, node_to_dict(v)) for k, v in node.items())
- elif not isinstance(node, BaseNode):
- return node
- return dict((k, node_to_dict(v)) for k, v in node.__dict__.items())
diff --git a/doc/_static/.placeholder b/doc/_static/.placeholder
deleted file mode 100644
index e69de29bb2d..00000000000
--- a/doc/_static/.placeholder
+++ /dev/null
diff --git a/doc/_static/banners/actions.jpg b/doc/_static/banners/actions.jpg
deleted file mode 100644
index fb08a23436c..00000000000
--- a/doc/_static/banners/actions.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/_static/banners/actions.small.jpg b/doc/_static/banners/actions.small.jpg
deleted file mode 100644
index be664dafc80..00000000000
--- a/doc/_static/banners/actions.small.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/_static/banners/build_a_module.jpg b/doc/_static/banners/build_a_module.jpg
deleted file mode 100644
index e885caba7ff..00000000000
--- a/doc/_static/banners/build_a_module.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/_static/banners/build_a_module.small.jpg b/doc/_static/banners/build_a_module.small.jpg
deleted file mode 100644
index 272eb7cd61a..00000000000
--- a/doc/_static/banners/build_a_module.small.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/_static/banners/build_a_theme.jpg b/doc/_static/banners/build_a_theme.jpg
deleted file mode 100644
index ea9a5268823..00000000000
--- a/doc/_static/banners/build_a_theme.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/_static/banners/build_a_theme.small.jpg b/doc/_static/banners/build_a_theme.small.jpg
deleted file mode 100644
index df27fec5ddf..00000000000
--- a/doc/_static/banners/build_a_theme.small.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/_static/banners/build_a_website.jpg b/doc/_static/banners/build_a_website.jpg
deleted file mode 100644
index f302d7e34ab..00000000000
--- a/doc/_static/banners/build_a_website.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/_static/banners/build_a_website.small.jpg b/doc/_static/banners/build_a_website.small.jpg
deleted file mode 100644
index 198d4dad9c9..00000000000
--- a/doc/_static/banners/build_a_website.small.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/_static/banners/build_interface_ext.jpg b/doc/_static/banners/build_interface_ext.jpg
deleted file mode 100644
index ab0c93b5159..00000000000
--- a/doc/_static/banners/build_interface_ext.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/_static/banners/build_interface_ext.small.jpg b/doc/_static/banners/build_interface_ext.small.jpg
deleted file mode 100644
index 6c197b3942a..00000000000
--- a/doc/_static/banners/build_interface_ext.small.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/_static/banners/cdn.jpg b/doc/_static/banners/cdn.jpg
deleted file mode 100644
index 098541df3db..00000000000
--- a/doc/_static/banners/cdn.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/_static/banners/cdn.small.jpg b/doc/_static/banners/cdn.small.jpg
deleted file mode 100644
index fb423e0c56f..00000000000
--- a/doc/_static/banners/cdn.small.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/_static/banners/cmdline.jpg b/doc/_static/banners/cmdline.jpg
deleted file mode 100644
index 386bb0fa93f..00000000000
--- a/doc/_static/banners/cmdline.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/_static/banners/cmdline.small.jpg b/doc/_static/banners/cmdline.small.jpg
deleted file mode 100644
index 4727b1063d9..00000000000
--- a/doc/_static/banners/cmdline.small.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/_static/banners/company.jpg b/doc/_static/banners/company.jpg
deleted file mode 100644
index cdecba72666..00000000000
--- a/doc/_static/banners/company.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/_static/banners/data_files.jpg b/doc/_static/banners/data_files.jpg
deleted file mode 100644
index 9218bab9ad2..00000000000
--- a/doc/_static/banners/data_files.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/_static/banners/data_files.small.jpg b/doc/_static/banners/data_files.small.jpg
deleted file mode 100644
index 957e5ffe47d..00000000000
--- a/doc/_static/banners/data_files.small.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/_static/banners/deploying_odoo.jpg b/doc/_static/banners/deploying_odoo.jpg
deleted file mode 100644
index a12213599e8..00000000000
--- a/doc/_static/banners/deploying_odoo.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/_static/banners/deploying_odoo.small.jpg b/doc/_static/banners/deploying_odoo.small.jpg
deleted file mode 100644
index 84ade466a69..00000000000
--- a/doc/_static/banners/deploying_odoo.small.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/_static/banners/email_gateway.jpg b/doc/_static/banners/email_gateway.jpg
deleted file mode 100644
index b9301e27040..00000000000
--- a/doc/_static/banners/email_gateway.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/_static/banners/email_gateway.small.jpg b/doc/_static/banners/email_gateway.small.jpg
deleted file mode 100644
index 435c312eb52..00000000000
--- a/doc/_static/banners/email_gateway.small.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/_static/banners/enterprise.jpg b/doc/_static/banners/enterprise.jpg
deleted file mode 100644
index 7c56721c7aa..00000000000
--- a/doc/_static/banners/enterprise.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/_static/banners/enterprise.small.jpg b/doc/_static/banners/enterprise.small.jpg
deleted file mode 100644
index 172fbf5a3da..00000000000
--- a/doc/_static/banners/enterprise.small.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/_static/banners/extract_api.jpg b/doc/_static/banners/extract_api.jpg
deleted file mode 100644
index c58a958f2d0..00000000000
--- a/doc/_static/banners/extract_api.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/_static/banners/extract_api.small.jpg b/doc/_static/banners/extract_api.small.jpg
deleted file mode 100644
index 435e37369d0..00000000000
--- a/doc/_static/banners/extract_api.small.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/_static/banners/iap.jpg b/doc/_static/banners/iap.jpg
deleted file mode 100644
index 410d62294b8..00000000000
--- a/doc/_static/banners/iap.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/_static/banners/iap.small.jpg b/doc/_static/banners/iap.small.jpg
deleted file mode 100644
index 186c446d807..00000000000
--- a/doc/_static/banners/iap.small.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/_static/banners/index.jpg b/doc/_static/banners/index.jpg
deleted file mode 100644
index 1edec3005d0..00000000000
--- a/doc/_static/banners/index.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/_static/banners/installing_odoo.jpg b/doc/_static/banners/installing_odoo.jpg
deleted file mode 100644
index 1b33e69eeb9..00000000000
--- a/doc/_static/banners/installing_odoo.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/_static/banners/installing_odoo.small.jpg b/doc/_static/banners/installing_odoo.small.jpg
deleted file mode 100644
index fdddc8c7a8b..00000000000
--- a/doc/_static/banners/installing_odoo.small.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/_static/banners/iot.jpg b/doc/_static/banners/iot.jpg
deleted file mode 100644
index 537527d7b14..00000000000
--- a/doc/_static/banners/iot.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/_static/banners/javascript.jpg b/doc/_static/banners/javascript.jpg
deleted file mode 100644
index 672a79e0332..00000000000
--- a/doc/_static/banners/javascript.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/_static/banners/javascript.small.jpg b/doc/_static/banners/javascript.small.jpg
deleted file mode 100644
index f315a888e94..00000000000
--- a/doc/_static/banners/javascript.small.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/_static/banners/localization.jpg b/doc/_static/banners/localization.jpg
deleted file mode 100644
index 1939c85debb..00000000000
--- a/doc/_static/banners/localization.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/_static/banners/m_1.small.jpg b/doc/_static/banners/m_1.small.jpg
deleted file mode 100644
index af8f57824b5..00000000000
--- a/doc/_static/banners/m_1.small.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/_static/banners/m_2.small.jpg b/doc/_static/banners/m_2.small.jpg
deleted file mode 100644
index cd3b1dd8217..00000000000
--- a/doc/_static/banners/m_2.small.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/_static/banners/m_accounting.small.jpg b/doc/_static/banners/m_accounting.small.jpg
deleted file mode 100644
index 9e4a0228d1a..00000000000
--- a/doc/_static/banners/m_accounting.small.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/_static/banners/mixins.jpg b/doc/_static/banners/mixins.jpg
deleted file mode 100644
index 4c9800fe1af..00000000000
--- a/doc/_static/banners/mixins.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/_static/banners/mixins.small.jpg b/doc/_static/banners/mixins.small.jpg
deleted file mode 100644
index 2e5d8eef60e..00000000000
--- a/doc/_static/banners/mixins.small.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/_static/banners/mobile.jpg b/doc/_static/banners/mobile.jpg
deleted file mode 100644
index f0667cfafc7..00000000000
--- a/doc/_static/banners/mobile.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/_static/banners/module.jpg b/doc/_static/banners/module.jpg
deleted file mode 100644
index 2ef413d40a4..00000000000
--- a/doc/_static/banners/module.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/_static/banners/module.small.jpg b/doc/_static/banners/module.small.jpg
deleted file mode 100644
index 18db8003a91..00000000000
--- a/doc/_static/banners/module.small.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/_static/banners/odoo_guideline.jpg b/doc/_static/banners/odoo_guideline.jpg
deleted file mode 100644
index 322ac65d2d1..00000000000
--- a/doc/_static/banners/odoo_guideline.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/_static/banners/odoo_guideline.small.jpg b/doc/_static/banners/odoo_guideline.small.jpg
deleted file mode 100644
index 1d784d87e12..00000000000
--- a/doc/_static/banners/odoo_guideline.small.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/_static/banners/orm_api.jpg b/doc/_static/banners/orm_api.jpg
deleted file mode 100644
index 04d51fd916e..00000000000
--- a/doc/_static/banners/orm_api.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/_static/banners/orm_api.small.jpg b/doc/_static/banners/orm_api.small.jpg
deleted file mode 100644
index 770b5ffa9ac..00000000000
--- a/doc/_static/banners/orm_api.small.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/_static/banners/qweb.jpg b/doc/_static/banners/qweb.jpg
deleted file mode 100644
index 2c61bf0e9ce..00000000000
--- a/doc/_static/banners/qweb.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/_static/banners/qweb.small.jpg b/doc/_static/banners/qweb.small.jpg
deleted file mode 100644
index 8db574c4cf3..00000000000
--- a/doc/_static/banners/qweb.small.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/_static/banners/reports.jpg b/doc/_static/banners/reports.jpg
deleted file mode 100644
index b2ff103efac..00000000000
--- a/doc/_static/banners/reports.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/_static/banners/reports.small.jpg b/doc/_static/banners/reports.small.jpg
deleted file mode 100644
index 36bcc3a59f3..00000000000
--- a/doc/_static/banners/reports.small.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/_static/banners/security.jpg b/doc/_static/banners/security.jpg
deleted file mode 100644
index 67bcb9f831a..00000000000
--- a/doc/_static/banners/security.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/_static/banners/security.small.jpg b/doc/_static/banners/security.small.jpg
deleted file mode 100644
index ac6f79db9b6..00000000000
--- a/doc/_static/banners/security.small.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/_static/banners/testing_modules.jpg b/doc/_static/banners/testing_modules.jpg
deleted file mode 100644
index 8931371d765..00000000000
--- a/doc/_static/banners/testing_modules.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/_static/banners/testing_modules.small.jpg b/doc/_static/banners/testing_modules.small.jpg
deleted file mode 100644
index 3ed683f04a2..00000000000
--- a/doc/_static/banners/testing_modules.small.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/_static/banners/translate.jpg b/doc/_static/banners/translate.jpg
deleted file mode 100644
index 6795a3aa10f..00000000000
--- a/doc/_static/banners/translate.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/_static/banners/translate.small.jpg b/doc/_static/banners/translate.small.jpg
deleted file mode 100644
index c225049dba3..00000000000
--- a/doc/_static/banners/translate.small.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/_static/banners/upgrade_api.jpg b/doc/_static/banners/upgrade_api.jpg
deleted file mode 100644
index 04a9422f915..00000000000
--- a/doc/_static/banners/upgrade_api.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/_static/banners/views.jpg b/doc/_static/banners/views.jpg
deleted file mode 100644
index 4d9fd0e2090..00000000000
--- a/doc/_static/banners/views.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/_static/banners/views.small.jpg b/doc/_static/banners/views.small.jpg
deleted file mode 100644
index 34aa32d40eb..00000000000
--- a/doc/_static/banners/views.small.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/_static/banners/web_controllers.jpg b/doc/_static/banners/web_controllers.jpg
deleted file mode 100644
index 347698b527e..00000000000
--- a/doc/_static/banners/web_controllers.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/_static/banners/web_controllers.small.jpg b/doc/_static/banners/web_controllers.small.jpg
deleted file mode 100644
index 596b28456b6..00000000000
--- a/doc/_static/banners/web_controllers.small.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/_static/banners/web_service_api.jpg b/doc/_static/banners/web_service_api.jpg
deleted file mode 100644
index aa70ba8c56e..00000000000
--- a/doc/_static/banners/web_service_api.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/_static/banners/web_service_api.small.jpg b/doc/_static/banners/web_service_api.small.jpg
deleted file mode 100644
index 63b3adf27c6..00000000000
--- a/doc/_static/banners/web_service_api.small.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/_static/extract_api_implementation.py b/doc/_static/extract_api_implementation.py
deleted file mode 100644
index bb2a8bca629..00000000000
--- a/doc/_static/extract_api_implementation.py
+++ /dev/null
@@ -1,100 +0,0 @@
-import base64
-import time
-import sys
-import json
-import requests
-
-account_token = "integration_token" # Use your token
-domain_name = "https://iap-extract.odoo.com"
-path_to_pdf = "/path/to/invoice_file"
-
-API_VERSION = 120 # Do not change
-SUCCESS = 0
-NOT_READY = 1
-
-def jsonrpc(path, params):
- payload = {
- 'jsonrpc': '2.0',
- 'method': 'call',
- 'params': params,
- 'id': 0,
- }
- req = requests.post(domain_name+path, json=payload, timeout=10)
- req.raise_for_status()
- resp = req.json()
- return resp
-
-
-with open(path_to_pdf, "rb") as file:
- params = {
- 'account_token': account_token,
- 'version': API_VERSION,
- 'documents': [base64.b64encode(file.read()).decode('ascii')],
- }
-
-response = jsonrpc("/iap/invoice_extract/parse", params)
-print("/parse call status: ", response['result']['status_msg'])
-
-if response['result']['status_code'] != SUCCESS:
- sys.exit(1)
-
-# You received an id that you can use to poll the server to get the result of the ocr when it will be ready
-document_id = response['result']['document_id']
-params = {
- 'version': API_VERSION,
- 'document_ids': [document_id], # you can request the results of multiple documents at once if wanted
-}
-
-response = jsonrpc("/iap/invoice_extract/get_results", params)
-document_id = str(document_id) # /get_results expects a string despite the fact that the returned document_id is a int
-
-while response['result'][document_id]['status_code'] == NOT_READY: # 1 is the status code indicating that the server is still processing the document
- print("Still processing... Retrying in 5 seconds")
- time.sleep(5)
- response = jsonrpc("/iap/invoice_extract/get_results", params)
-
-with open('results.txt', 'w') as outfile:
- json.dump(response, outfile, indent=2)
-print("\nResult saved in results.txt")
-
-if response['result'][document_id]['status_code'] != SUCCESS:
- print(response['result'][document_id]['status_msg']) # if it isn't a success, print the error message
- sys.exit(1)
-
-document_results = response['result'][document_id]['results'][0]
-print("\nTotal:", document_results['total']['selected_value']['content'])
-print("Subtotal:", document_results['subtotal']['selected_value']['content'])
-print("Invoice id:", document_results['invoice_id']['selected_value']['content'])
-print("Date:", document_results['date']['selected_value']['content'])
-print("...\n")
-
-params = {
- 'document_id': document_id,
- 'values': {
- 'total': {'content': 100.0},
- 'subtotal': {'content': 100.0},
- 'global_taxes': {'content': []},
- 'global_taxes_amount': {'content': 0.0},
- 'date': {'content': '2020-09-25'},
- 'due_date': {'content': '2020-09-25'},
- 'invoice_id': {'content': document_results['invoice_id']['selected_value']['content']},
- 'partner': {'content': 'twinnta'},
- 'VAT_Number': {'content': 'BE23252248420'},
- 'currency': {'content': 'USD'},
- 'merged_lines': False,
- 'invoice_lines': {'lines': [{'description': 'Total TVA ',
- 'quantity': 1.0,
- 'unit_price': 100.0,
- 'product': False,
- 'taxes_amount': 0.0,
- 'taxes': [],
- 'subtotal': 100.0,
- 'total': 100.0}]
- }
- }
-}
-response = jsonrpc("/iap/invoice_extract/validate", params)
-if response['result']['status_code'] == SUCCESS:
- print("/validate call status: Success")
-else:
- print("/validate call status: wrong format")
diff --git a/doc/_static/issue_template.md b/doc/_static/issue_template.md
deleted file mode 100644
index 7ede783f5d7..00000000000
--- a/doc/_static/issue_template.md
+++ /dev/null
@@ -1,19 +0,0 @@
-Short description of the issue
-
-***Impacted versions:***
-
- -
-
-***Steps to reproduce:***
-
- 1.
- 2.
- 3.
-
-***Current behavior:***
-
- -
-
-***Expected behavior:***
-
- -
diff --git a/doc/_static/odoo.css b/doc/_static/odoo.css
deleted file mode 100644
index c370773fd28..00000000000
--- a/doc/_static/odoo.css
+++ /dev/null
@@ -1,26 +0,0 @@
-@import "style.css";
-
-p.rubric {
- font-family: Lato, Arial, sans-serif;
- font-weight: 500;
- line-height: 1.1;
- color: inherit;
- margin-top: 10px;
- margin-bottom: 8px;
-}
-
-.section p.rubric {
- font-size: 30px;
-}
-.section .section p.rubric {
- font-size: 24px;
-}
-.section .section .section p.rubric {
- font-size: 18px;
-}
-.section .section .section .section p.rubric {
- font-size: 14px;
-}
-.section .section .section .section .section p.rubric {
- font-size: 12px;
-}
diff --git a/doc/_static/pull-request-version.png b/doc/_static/pull-request-version.png
deleted file mode 100644
index dd45388d072..00000000000
--- a/doc/_static/pull-request-version.png
+++ /dev/null
Binary files differ
diff --git a/doc/conf.py b/doc/conf.py
deleted file mode 100644
index a0979ba336f..00000000000
--- a/doc/conf.py
+++ /dev/null
@@ -1,241 +0,0 @@
-# -*- coding: utf-8 -*-
-import sys, os
-import sphinx
-
-# If extensions (or modules to document with autodoc) are in another directory,
-# add these directories to sys.path here. If the directory is relative to the
-# documentation root, use os.path.abspath to make it absolute, like shown here.
-DIR = os.path.dirname(__file__)
-sys.path.insert(0,
- os.path.abspath(
- os.path.join(DIR, '_extensions')))
-# put current odoo's source on PYTHONPATH for autodoc
-sys.path.insert(0, os.path.abspath(os.path.join(DIR, '..')))
-
-# -- General configuration -----------------------------------------------------
-
-# If your documentation needs a minimal Sphinx version, state it here.
-needs_sphinx = '1.2'
-
-# Add any Sphinx extension module names here, as strings. They can be extensions
-# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
-extensions = [
- 'sphinx.ext.ifconfig',
- 'sphinx.ext.todo',
- 'sphinx.ext.autodoc',
- 'sphinx.ext.intersphinx',
- 'sphinx.ext.linkcode',
- # 'autojsdoc.ext',
- 'github_link',
- 'odoo_ext',
- 'html_domain',
- 'exercise_admonition',
- 'patchqueue'
-]
-
-# Add any paths that contain templates here, relative to this directory.
-templates_path = ['_templates']
-
-# The suffix of source filenames.
-source_suffix = '.rst'
-
-# The encoding of source files.
-#source_encoding = 'utf-8-sig'
-
-# The master toctree document.
-master_doc = 'index'
-
-# General information about the project.
-project = u'odoo'
-copyright = u'Odoo S.A.'
-
-# The version info for the project you're documenting, acts as replacement for
-# |version| and |release|, also used in various other places throughout the
-# built documents.
-#
-# The short X.Y version.
-version = '14.0'
-# The full version, including alpha/beta/rc tags.
-release = '14.0'
-
-# There are two options for replacing |today|: either, you set today to some
-# non-false value, then it is used:
-#today = ''
-# Else, today_fmt is used as the format for a strftime call.
-today_fmt = '%B %d, %Y'
-
-# List of patterns, relative to source directory, that match files and
-# directories to ignore when looking for source files.
-exclude_patterns = ['_build']
-
-# markdown compatibility: make `foo` behave like ``foo``, the rst default is
-# title-reference which is never what people are looking for
-default_role = 'literal'
-
-# If true, '()' will be appended to :func: etc. cross-reference text.
-add_function_parentheses = True
-
-# If true, the current module name will be prepended to all description
-# unit titles (such as .. function::).
-#add_module_names = True
-
-# If true, sectionauthor and moduleauthor directives will be shown in the
-# output. They are ignored by default.
-#show_authors = False
-
-# The name of the Pygments (syntax highlighting) style to use.
-pygments_style = 'odoo'
-
-# A list of ignored prefixes for module index sorting.
-#modindex_common_prefix = []
-
-
-# -- Options for HTML output ---------------------------------------------------
-# The theme to use for HTML and HTML Help pages. See the documentation for
-# a list of builtin themes.
-html_theme = 'odoo_ext'
-
-odoo_cover_default = 'banners/installing_odoo.jpg'
-
-# Theme options are theme-specific and customize the look and feel of a theme
-# further. For a list of options available for each theme, see the
-# documentation.
-#html_theme_options = {}
-
-# Add any paths that contain custom themes here, relative to this directory.
-html_theme_path = ['_extensions']
-
-# The name for this set of Sphinx documents. If None, it defaults to
-# "<project> v<release> documentation".
-#html_title = None
-
-# A shorter title for the navigation bar. Default is the same as html_title.
-#html_short_title = None
-
-# The name of an image file (relative to this directory) to place at the top
-# of the sidebar.
-#html_logo = None
-
-# The name of an image file (within the static path) to use as favicon of the
-# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
-# pixels large.
-#html_favicon = None
-
-# Add any paths that contain custom static files (such as style sheets) here,
-# relative to this directory. They are copied after the builtin static files,
-# so a file named "default.css" will overwrite the builtin "default.css".
-html_static_path = ['_static']
-
-html_add_permalinks = u''
-
-# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
-# using the given strftime format.
-#html_last_updated_fmt = '%b %d, %Y'
-
-# If true, SmartyPants will be used to convert quotes and dashes to
-# typographically correct entities.
-#html_use_smartypants = True
-
-# Custom sidebar templates, maps document names to template names.
-# FIXME: no sidebar on index?
-html_sidebars = {
-}
-
-# Additional templates that should be rendered to pages, maps page names to
-# template names.
-#html_additional_pages = {}
-
-# If false, no module index is generated.
-#html_domain_indices = True
-
-# If false, no index is generated.
-#html_use_index = True
-
-# If true, the index is split into individual pages for each letter.
-#html_split_index = False
-
-# If true, links to the reST sources are added to the pages.
-#html_show_sourcelink = True
-
-# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
-#html_show_sphinx = True
-
-# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
-#html_show_copyright = True
-
-# If true, an OpenSearch description file will be output, and all pages will
-# contain a <link> tag referring to it. The value of this option must be the
-# base URL from which the finished HTML is served.
-#html_use_opensearch = ''
-
-latex_elements = {
- 'papersize': r'a4paper',
- 'preamble': u'''\\setcounter{tocdepth}{2}
-''',
-}
-
-# default must be set otherwise ifconfig blows up
-todo_include_todos = False
-
-intersphinx_mapping = {
- 'python': ('https://docs.python.org/3/', None),
- 'werkzeug': ('http://werkzeug.pocoo.org/docs/', None),
-}
-
-github_user = 'odoo'
-github_project = 'odoo'
-
-# monkeypatch PHP lexer to not require <?php
-from sphinx.highlighting import lexers
-from pygments.lexers.web import PhpLexer
-lexers['php'] = PhpLexer(startinline=True)
-
-def setup(app):
- app.connect('html-page-context', canonicalize)
- app.add_config_value('canonical_root', None, 'env')
- app.add_config_value('canonical_branch', 'master', 'env')
-
- app.connect('html-page-context', versionize)
- app.add_config_value('versions', '', 'env')
-
- app.connect('html-page-context', analytics)
- app.add_config_value('google_analytics_key', '', 'env')
-
-def canonicalize(app, pagename, templatename, context, doctree):
- """ Adds a 'canonical' URL for the current document in the rendering
- context. Requires the ``canonical_root`` setting being set. The canonical
- branch is ``master`` but can be overridden using ``canonical_branch``.
- """
- if not app.config.canonical_root:
- return
-
- context['canonical'] = _build_url(
- app.config.canonical_root, app.config.canonical_branch, pagename)
-
-def versionize(app, pagename, templatename, context, doctree):
- """ Adds a version switcher below the menu, requires ``canonical_root``
- and ``versions`` (an ordered, space-separated lists of all possible
- versions).
- """
- if not (app.config.canonical_root and app.config.versions):
- return
-
- context['versions'] = [
- (vs, _build_url(app.config.canonical_root, vs, pagename))
- for vs in app.config.versions.split(',')
- if vs != app.config.version
- ]
-
-def analytics(app, pagename, templatename, context, doctree):
- if not app.config.google_analytics_key:
- return
-
- context['google_analytics_key'] = app.config.google_analytics_key
-
-def _build_url(root, branch, pagename):
- return "{canonical_url}{canonical_branch}/{canonical_page}".format(
- canonical_url=root,
- canonical_branch=branch,
- canonical_page=(pagename + '.html').replace('index.html', '')
- .replace('index/', ''),
- )
diff --git a/doc/glossary.rst b/doc/glossary.rst
deleted file mode 100644
index 7afeebbed35..00000000000
--- a/doc/glossary.rst
+++ /dev/null
@@ -1,43 +0,0 @@
-:orphan: true
-
-========
-Glossary
-========
-
-.. glossary::
-
- external id
- external identifier
- external identifiers
- string identifier stored in ``ir.model.data``, can be used to refer
- to a record regardless of its database identifier during data imports
- or export/import roundtrips.
-
- External identifiers are in the form :samp:`{module}.{id}` (e.g.
- ``account.invoice_graph``). From within a module, the
- :samp:`{module}.` prefix can be left out.
-
- Sometimes referred to as "xml id" or ``xml_id`` as XML-based
- :ref:`reference/data` make extensive use of them.
-
- format string
- inspired by `jinja variables`_, format strings allow more easily
- mixing literal content and computed content (expressions): content
- between ``{{`` and ``}}`` is interpreted as an expression and
- evaluated, other content is interpreted as literal strings and
- displayed as-is
-
- GIS
- Geographic Information System
- any computer system or subsystem to capture, store, manipulate,
- analyze, manage or present spatial and geographical data.
-
- minified
- minification
- process of removing extraneous/non-necessary sections of files
- (comments, whitespace) and possibly recompiling them using equivalent
- but shorter structures (`ternary operator`_ instead of ``if/else``) in
- order to reduce network traffic
-
-.. _jinja variables: http://jinja.pocoo.org/docs/dev/templates/#variables
-.. _ternary operator: http://en.wikipedia.org/wiki/%3F:
diff --git a/doc/howtos/backend.rst b/doc/howtos/backend.rst
deleted file mode 100644
index 4b63e4dd8a1..00000000000
--- a/doc/howtos/backend.rst
+++ /dev/null
@@ -1,1822 +0,0 @@
-:banner: banners/build_a_module.jpg
-
-.. queue:: backend/series
-
-.. _howto/base:
-.. _howto/module:
-
-=================
-Building a Module
-=================
-
-.. warning::
-
- This tutorial requires :ref:`having installed Odoo <setup/install>`
-
-Start/Stop the Odoo server
-==========================
-
-Odoo uses a client/server architecture in which clients are web browsers
-accessing the Odoo server via RPC.
-
-Business logic and extension is generally performed on the server side,
-although supporting client features (e.g. new data representation such as
-interactive maps) can be added to the client.
-
-In order to start the server, simply invoke the command :ref:`odoo-bin
-<reference/cmdline>` in the shell, adding the full path to the file if
-necessary:
-
-.. code:: bash
-
- odoo-bin
-
-The server is stopped by hitting ``Ctrl-C`` twice from the terminal, or by
-killing the corresponding OS process.
-
-Build an Odoo module
-====================
-
-Both server and client extensions are packaged as *modules* which are
-optionally loaded in a *database*.
-
-Odoo modules can either add brand new business logic to an Odoo system, or
-alter and extend existing business logic: a module can be created to add your
-country's accounting rules to Odoo's generic accounting support, while the
-next module adds support for real-time visualisation of a bus fleet.
-
-Everything in Odoo thus starts and ends with modules.
-
-Composition of a module
------------------------
-
-An Odoo module can contain a number of elements:
-
-Business objects
- Declared as Python classes, these resources are automatically persisted
- by Odoo based on their configuration
-
-:ref:`Object views <reference/views>`
- Definition of business objects UI display
-
-:ref:`Data files <reference/data>`
- XML or CSV files declaring the model metadata :
-
- * :ref:`views <reference/views>` or :ref:`reports <reference/reports>`,
- * configuration data (modules parametrization, :ref:`security rules <reference/security>`),
- * demonstration data
- * and more
-
-:ref:`Web controllers <reference/controllers>`
- Handle requests from web browsers
-
-Static web data
- Images, CSS or javascript files used by the web interface or website
-
-Module structure
-----------------
-
-Each module is a directory within a *module directory*. Module directories
-are specified by using the :option:`--addons-path <odoo-bin --addons-path>`
-option.
-
-.. tip::
- :class: aphorism
-
- most command-line options can also be set using :ref:`a configuration
- file <reference/cmdline/config>`
-
-An Odoo module is declared by its :ref:`manifest <reference/module/manifest>`.
-
-A module is also a
-`Python package <http://docs.python.org/2/tutorial/modules.html#packages>`_
-with a ``__init__.py`` file, containing import instructions for various Python
-files in the module.
-
-For instance, if the module has a single ``mymodule.py`` file ``__init__.py``
-might contain::
-
- from . import mymodule
-
-Odoo provides a mechanism to help set up a new module, :ref:`odoo-bin
-<reference/cmdline/server>` has a subcommand :ref:`scaffold
-<reference/cmdline/scaffold>` to create an empty module:
-
-.. code-block:: console
-
- $ odoo-bin scaffold <module name> <where to put it>
-
-The command creates a subdirectory for your module, and automatically creates a
-bunch of standard files for a module. Most of them simply contain commented code
-or XML. The usage of most of those files will be explained along this tutorial.
-
-.. exercise:: Module creation
-
- Use the command line above to create an empty module Open Academy, and
- install it in Odoo.
-
- .. only:: solutions
-
- #. Invoke the command ``odoo-bin scaffold openacademy addons``.
- #. Adapt the manifest file to your module.
- #. Don't bother about the other files.
-
- .. patch::
-
-Object-Relational Mapping
--------------------------
-
-A key component of Odoo is the :abbr:`ORM (Object-Relational Mapping)` layer.
-This layer avoids having to write most :abbr:`SQL (Structured Query Language)`
-by hand and provides extensibility and security services\ [#rawsql]_.
-
-Business objects are declared as Python classes extending
-:class:`~odoo.models.Model` which integrates them into the automated
-persistence system.
-
-Models can be configured by setting a number of attributes at their
-definition. The most important attribute is
-:attr:`~odoo.models.Model._name` which is required and defines the name for
-the model in the Odoo system. Here is a minimally complete definition of a
-model::
-
- from odoo import models
- class MinimalModel(models.Model):
- _name = 'test.model'
-
-Model fields
-------------
-
-Fields are used to define what the model can store and where. Fields are
-defined as attributes on the model class::
-
- from odoo import models, fields
-
- class LessMinimalModel(models.Model):
- _name = 'test.model2'
-
- name = fields.Char()
-
-Common Attributes
-#################
-
-Much like the model itself, its fields can be configured, by passing
-configuration attributes as parameters::
-
- name = field.Char(required=True)
-
-Some attributes are available on all fields, here are the most common ones:
-
-:attr:`~odoo.fields.Field.string` (``unicode``, default: field's name)
- The label of the field in UI (visible by users).
-:attr:`~odoo.fields.Field.required` (``bool``, default: ``False``)
- If ``True``, the field can not be empty, it must either have a default
- value or always be given a value when creating a record.
-:attr:`~odoo.fields.Field.help` (``unicode``, default: ``''``)
- Long-form, provides a help tooltip to users in the UI.
-:attr:`~odoo.fields.Field.index` (``bool``, default: ``False``)
- Requests that Odoo create a `database index`_ on the column.
-
-Simple fields
-#############
-
-There are two broad categories of fields: "simple" fields which are atomic
-values stored directly in the model's table and "relational" fields linking
-records (of the same model or of different models).
-
-Example of simple fields are :class:`~odoo.fields.Boolean`,
-:class:`~odoo.fields.Date`, :class:`~odoo.fields.Char`.
-
-Reserved fields
-###############
-
-Odoo creates a few fields in all models\ [#autofields]_. These fields are
-managed by the system and shouldn't be written to. They can be read if
-useful or necessary:
-
-:attr:`~odoo.fields.Model.id` (:class:`~odoo.fields.Id`)
- The unique identifier for a record in its model.
-:attr:`~odoo.fields.Model.create_date` (:class:`~odoo.fields.Datetime`)
- Creation date of the record.
-:attr:`~odoo.fields.Model.create_uid` (:class:`~odoo.fields.Many2one`)
- User who created the record.
-:attr:`~odoo.fields.Model.write_date` (:class:`~odoo.fields.Datetime`)
- Last modification date of the record.
-:attr:`~odoo.fields.Model.write_uid` (:class:`~odoo.fields.Many2one`)
- user who last modified the record.
-
-Special fields
-##############
-
-By default, Odoo also requires a ``name`` field on all models for various
-display and search behaviors. The field used for these purposes can be
-overridden by setting :attr:`~odoo.models.Model._rec_name`.
-
-.. exercise:: Define a model
-
- Define a new data model *Course* in the *openacademy* module. A course
- has a title and a description. Courses must have a title.
-
- .. only:: solutions
-
- Edit the file ``openacademy/models/models.py`` to include a *Course* class.
-
- .. patch::
-
-Data files
-----------
-
-Odoo is a highly data driven system. Although behavior is customized using
-Python_ code part of a module's value is in the data it sets up when loaded.
-
-.. tip:: some modules exist solely to add data into Odoo
- :class: aphorism
-
-Module data is declared via :ref:`data files <reference/data>`, XML files with
-``<record>`` elements. Each ``<record>`` element creates or updates a database
-record.
-
-.. code-block:: xml
-
- <odoo>
-
- <record model="{model name}" id="{record identifier}">
- <field name="{a field name}">{a value}</field>
- </record>
-
- </odoo>
-
-* ``model`` is the name of the Odoo model for the record.
-* ``id`` is an :term:`external identifier`, it allows referring to the record
- (without having to know its in-database identifier).
-* ``<field>`` elements have a ``name`` which is the name of the field in the
- model (e.g. ``description``). Their body is the field's value.
-
-Data files have to be declared in the manifest file to be loaded, they can
-be declared in the ``'data'`` list (always loaded) or in the ``'demo'`` list
-(only loaded in demonstration mode).
-
-.. exercise:: Define demonstration data
-
- Create demonstration data filling the *Courses* model with a few
- demonstration courses.
-
- .. only:: solutions
-
- Edit the file ``openacademy/demo/demo.xml`` to include some data.
-
- .. patch::
-
-.. tip:: The content of the data files is only loaded when a module is
- installed or updated.
-
- After making some changes, do not forget to use
- :ref:`odoo-bin -u openacademy <reference/cmdline>` to save the changes
- to your database.
-
-.. _howtos/module/actions:
-
-Actions and Menus
------------------
-
-Actions and menus are regular records in database, usually declared through
-data files. Actions can be triggered in three ways:
-
-#. by clicking on menu items (linked to specific actions)
-#. by clicking on buttons in views (if these are connected to actions)
-#. as contextual actions on object
-
-Because menus are somewhat complex to declare there is a ``<menuitem>``
-shortcut to declare an ``ir.ui.menu`` and connect it to the corresponding
-action more easily.
-
-.. code-block:: xml
-
- <record model="ir.actions.act_window" id="action_list_ideas">
- <field name="name">Ideas</field>
- <field name="res_model">idea.idea</field>
- <field name="view_mode">tree,form</field>
- </record>
- <menuitem id="menu_ideas" parent="menu_root" name="Ideas" sequence="10"
- action="action_list_ideas"/>
-
-.. danger::
- :class: aphorism
-
- The action must be declared before its corresponding menu in the XML file.
-
- Data files are executed sequentially, the action's ``id`` must be present
- in the database before the menu can be created.
-
-.. exercise:: Define new menu entries
-
- Define new menu entries to access courses under the
- OpenAcademy menu entry. A user should be able to :
-
- - display a list of all the courses
- - create/modify courses
-
- .. only:: solutions
-
- #. Create ``openacademy/views/openacademy.xml`` with an action and
- the menus triggering the action
- #. Add it to the ``data`` list of ``openacademy/__manifest__.py``
-
- .. patch::
-
-Basic views
-===========
-
-Views define the way the records of a model are displayed. Each type of view
-represents a mode of visualization (a list of records, a graph of their
-aggregation, …). Views can either be requested generically via their type
-(e.g. *a list of partners*) or specifically via their id. For generic
-requests, the view with the correct type and the lowest priority will be
-used (so the lowest-priority view of each type is the default view for that
-type).
-
-:ref:`View inheritance <reference/views/inheritance>` allows altering views
-declared elsewhere (adding or removing content).
-
-Generic view declaration
-------------------------
-
-A view is declared as a record of the model ``ir.ui.view``. The view type
-is implied by the root element of the ``arch`` field:
-
-.. code-block:: xml
-
- <record model="ir.ui.view" id="view_id">
- <field name="name">view.name</field>
- <field name="model">object_name</field>
- <field name="priority" eval="16"/>
- <field name="arch" type="xml">
- <!-- view content: <form>, <tree>, <graph>, ... -->
- </field>
- </record>
-
-.. danger:: The view's content is XML.
- :class: aphorism
-
- The ``arch`` field must thus be declared as ``type="xml"`` to be parsed
- correctly.
-
-Tree views
-----------
-
-Tree views, also called list views, display records in a tabular form.
-
-Their root element is ``<tree>``. The simplest form of the tree view simply
-lists all the fields to display in the table (each field as a column):
-
-.. code-block:: xml
-
- <tree string="Idea list">
- <field name="name"/>
- <field name="inventor_id"/>
- </tree>
-
-.. _howtos/module/views/form:
-
-Form views
-----------
-
-Forms are used to create and edit single records.
-
-
-Their root element is ``<form>``. They are composed of high-level structure
-elements (groups, notebooks) and interactive elements (buttons and fields):
-
-.. code-block:: xml
-
- <form string="Idea form">
- <group colspan="4">
- <group colspan="2" col="2">
- <separator string="General stuff" colspan="2"/>
- <field name="name"/>
- <field name="inventor_id"/>
- </group>
-
- <group colspan="2" col="2">
- <separator string="Dates" colspan="2"/>
- <field name="active"/>
- <field name="invent_date" readonly="1"/>
- </group>
-
- <notebook colspan="4">
- <page string="Description">
- <field name="description" nolabel="1"/>
- </page>
- </notebook>
-
- <field name="state"/>
- </group>
- </form>
-
-.. exercise:: Customise form view using XML
-
- Create your own form view for the Course object. Data displayed should be:
- the name and the description of the course.
-
- .. only:: solutions
-
- .. patch::
-
-.. exercise:: Notebooks
-
- In the Course form view, put the description field under a tab, such that
- it will be easier to add other tabs later, containing additional
- information.
-
- .. only:: solutions
-
- Modify the Course form view as follows:
-
- .. patch::
-
-Form views can also use plain HTML for more flexible layouts:
-
-.. code-block:: xml
-
- <form string="Idea Form">
- <header>
- <button string="Confirm" type="object" name="action_confirm"
- states="draft" class="oe_highlight" />
- <button string="Mark as done" type="object" name="action_done"
- states="confirmed" class="oe_highlight"/>
- <button string="Reset to draft" type="object" name="action_draft"
- states="confirmed,done" />
- <field name="state" widget="statusbar"/>
- </header>
- <sheet>
- <div class="oe_title">
- <label for="name" class="oe_edit_only" string="Idea Name" />
- <h1><field name="name" /></h1>
- </div>
- <separator string="General" colspan="2" />
- <group colspan="2" col="2">
- <field name="description" placeholder="Idea description..." />
- </group>
- </sheet>
- </form>
-
-Search views
-------------
-
-Search views customize the search field associated with the list view (and
-other aggregated views). Their root element is ``<search>`` and they're
-composed of fields defining which fields can be searched on:
-
-.. code-block:: xml
-
- <search>
- <field name="name"/>
- <field name="inventor_id"/>
- </search>
-
-If no search view exists for the model, Odoo generates one which only allows
-searching on the ``name`` field.
-
-.. exercise:: Search courses
-
- Allow searching for courses based on their title or their description.
-
- .. only:: solutions
-
- .. patch::
-
-Relations between models
-========================
-
-A record from a model may be related to a record from another model. For
-instance, a sale order record is related to a client record that contains the
-client data; it is also related to its sale order line records.
-
-.. exercise:: Create a session model
-
- For the module Open Academy, we consider a model for *sessions*: a session
- is an occurrence of a course taught at a given time for a given audience.
-
- Create a model for *sessions*. A session has a name, a start date, a
- duration and a number of seats. Add an action and a menu item to display
- them. Make the new model visible via a menu item.
-
- .. only:: solutions
-
- #. Create the class *Session* in ``openacademy/models/models.py``.
- #. Add access to the session object in ``openacademy/view/openacademy.xml``.
-
- .. patch::
-
- .. note:: ``digits=(6, 2)`` specifies the precision of a float number:
- 6 is the total number of digits, while 2 is the number of
- digits after the comma. Note that it results in the number
- digits before the comma is a maximum 4
-
-Relational fields
------------------
-
-Relational fields link records, either of the same model (hierarchies) or
-between different models.
-
-Relational field types are:
-
-:class:`Many2one(other_model, ondelete='set null') <odoo.fields.Many2one>`
- A simple link to an other object::
-
- print foo.other_id.name
-
- .. seealso:: `foreign keys <http://www.postgresql.org/docs/9.3/static/tutorial-fk.html>`_
-
-:class:`One2many(other_model, related_field) <odoo.fields.One2many>`
- A virtual relationship, inverse of a :class:`~odoo.fields.Many2one`.
- A :class:`~odoo.fields.One2many` behaves as a container of records,
- accessing it results in a (possibly empty) set of records::
-
- for other in foo.other_ids:
- print other.name
-
- .. danger::
-
- Because a :class:`~odoo.fields.One2many` is a virtual relationship,
- there *must* be a :class:`~odoo.fields.Many2one` field in the
- :samp:`{other_model}`, and its name *must* be :samp:`{related_field}`
-
-:class:`Many2many(other_model) <odoo.fields.Many2many>`
- Bidirectional multiple relationship, any record on one side can be related
- to any number of records on the other side. Behaves as a container of
- records, accessing it also results in a possibly empty set of records::
-
- for other in foo.other_ids:
- print other.name
-
-.. exercise:: Many2one relations
-
- Using a many2one, modify the *Course* and *Session* models to reflect their
- relation with other models:
-
- - A course has a *responsible* user; the value of that field is a record of
- the built-in model ``res.users``.
- - A session has an *instructor*; the value of that field is a record of the
- built-in model ``res.partner``.
- - A session is related to a *course*; the value of that field is a record
- of the model ``openacademy.course`` and is required.
- - Adapt the views.
-
- .. only:: solutions
-
- #. Add the relevant ``Many2one`` fields to the models, and
- #. add them in the views.
-
- .. patch::
-
-.. exercise:: Inverse one2many relations
-
- Using the inverse relational field one2many, modify the models to reflect
- the relation between courses and sessions.
-
- .. only:: solutions
-
- #. Modify the ``Course`` class, and
- #. add the field in the course form view.
-
- .. patch::
-
-.. exercise:: Multiple many2many relations
-
- Using the relational field many2many, modify the *Session* model to relate
- every session to a set of *attendees*. Attendees will be represented by
- partner records, so we will relate to the built-in model ``res.partner``.
- Adapt the views accordingly.
-
- .. only:: solutions
-
- #. Modify the ``Session`` class, and
- #. add the field in the form view.
-
- .. patch::
-
-Inheritance
-===========
-
-Model inheritance
------------------
-
-Odoo provides two *inheritance* mechanisms to extend an existing model in a
-modular way.
-
-The first inheritance mechanism allows a module to modify the behavior of a
-model defined in another module:
-
-- add fields to a model,
-- override the definition of fields on a model,
-- add constraints to a model,
-- add methods to a model,
-- override existing methods on a model.
-
-The second inheritance mechanism (delegation) allows to link every record of a
-model to a record in a parent model, and provides transparent access to the
-fields of the parent record.
-
-.. image:: ../images/inheritance_methods.png
- :align: center
-
-.. seealso::
-
- * :attr:`~odoo.models.Model._inherit`
- * :attr:`~odoo.models.Model._inherits`
-
-View inheritance
-----------------
-
-Instead of modifying existing views in place (by overwriting them), Odoo
-provides view inheritance where children "extension" views are applied on top of
-root views, and can add or remove content from their parent.
-
-An extension view references its parent using the ``inherit_id`` field, and
-instead of a single view its ``arch`` field is composed of any number of
-``xpath`` elements selecting and altering the content of their parent view:
-
-.. code-block:: xml
-
- <!-- improved idea categories list -->
- <record id="idea_category_list2" model="ir.ui.view">
- <field name="name">id.category.list2</field>
- <field name="model">idea.category</field>
- <field name="inherit_id" ref="id_category_list"/>
- <field name="arch" type="xml">
- <!-- find field description and add the field
- idea_ids after it -->
- <xpath expr="//field[@name='description']" position="after">
- <field name="idea_ids" string="Number of ideas"/>
- </xpath>
- </field>
- </record>
-
-``expr``
- An XPath_ expression selecting a single element in the parent view.
- Raises an error if it matches no element or more than one
-``position``
- Operation to apply to the matched element:
-
- ``inside``
- appends ``xpath``'s body at the end of the matched element
- ``replace``
- replaces the matched element with the ``xpath``'s body, replacing any ``$0`` node occurrence
- in the new body with the original element
- ``before``
- inserts the ``xpath``'s body as a sibling before the matched element
- ``after``
- inserts the ``xpaths``'s body as a sibling after the matched element
- ``attributes``
- alters the attributes of the matched element using special
- ``attribute`` elements in the ``xpath``'s body
-
-.. tip::
-
- When matching a single element, the ``position`` attribute can be set directly
- on the element to be found. Both inheritances below will give the same result.
-
- .. code-block:: xml
-
- <xpath expr="//field[@name='description']" position="after">
- <field name="idea_ids" />
- </xpath>
-
- <field name="description" position="after">
- <field name="idea_ids" />
- </field>
-
-
-.. exercise:: Alter existing content
-
- * Using model inheritance, modify the existing *Partner* model to add an
- ``instructor`` boolean field, and a many2many field that corresponds to
- the session-partner relation
- * Using view inheritance, display this fields in the partner form view
-
- .. only:: solutions
-
- .. note::
-
- This is the opportunity to introduce the developer mode to
- inspect the view, find its external ID and the place to put the
- new field.
-
- #. Create a file ``openacademy/models/partner.py`` and import it in
- ``__init__.py``
- #. Create a file ``openacademy/views/partner.xml`` and add it to
- ``__manifest__.py``
-
- .. patch::
-
-Domains
-#######
-
-In Odoo, :ref:`reference/orm/domains` are values that encode conditions on
-records. A domain is a list of criteria used to select a subset of a model's
-records. Each criteria is a triple with a field name, an operator and a value.
-
-For instance, when used on the *Product* model the following domain selects
-all *services* with a unit price over *1000*::
-
- [('product_type', '=', 'service'), ('unit_price', '>', 1000)]
-
-By default criteria are combined with an implicit AND. The logical operators
-``&`` (AND), ``|`` (OR) and ``!`` (NOT) can be used to explicitly combine
-criteria. They are used in prefix position (the operator is inserted before
-its arguments rather than between). For instance to select products "which are
-services *OR* have a unit price which is *NOT* between 1000 and 2000"::
-
- ['|',
- ('product_type', '=', 'service'),
- '!', '&',
- ('unit_price', '>=', 1000),
- ('unit_price', '<', 2000)]
-
-A ``domain`` parameter can be added to relational fields to limit valid
-records for the relation when trying to select records in the client interface.
-
-.. exercise:: Domains on relational fields
-
- When selecting the instructor for a *Session*, only instructors (partners
- with ``instructor`` set to ``True``) should be visible.
-
- .. only:: solutions
-
- .. patch::
-
- .. note::
-
- A domain declared as a literal list is evaluated server-side and
- can't refer to dynamic values on the right-hand side, a domain
- declared as a string is evaluated client-side and allows
- field names on the right-hand side
-
-.. exercise:: More complex domains
-
- Create new partner categories *Teacher / Level 1* and *Teacher / Level 2*.
- The instructor for a session can be either an instructor or a teacher
- (of any level).
-
- .. only:: solutions
-
- #. Modify the *Session* model's domain
- #. Modify ``openacademy/view/partner.xml`` to get access to
- *Partner categories*:
-
- .. patch::
-
-Computed fields and default values
-==================================
-
-So far fields have been stored directly in and retrieved directly from the
-database. Fields can also be *computed*. In that case, the field's value is not
-retrieved from the database but computed on-the-fly by calling a method of the
-model.
-
-To create a computed field, create a field and set its attribute
-:attr:`~odoo.fields.Field.compute` to the name of a method. The computation
-method should simply set the value of the field to compute on every record in
-``self``.
-
-.. danger:: ``self`` is a collection
- :class: aphorism
-
- The object ``self`` is a *recordset*, i.e., an ordered collection of
- records. It supports the standard Python operations on collections, like
- ``len(self)`` and ``iter(self)``, plus extra set operations like ``recs1 +
- recs2``.
-
- Iterating over ``self`` gives the records one by one, where each record is
- itself a collection of size 1. You can access/assign fields on single
- records by using the dot notation, like ``record.name``.
-
-.. code-block:: python
-
- import random
- from odoo import models, fields, api
-
- class ComputedModel(models.Model):
- _name = 'test.computed'
-
- name = fields.Char(compute='_compute_name')
-
- def _compute_name(self):
- for record in self:
- record.name = str(random.randint(1, 1e6))
-
-
-Dependencies
-------------
-
-The value of a computed field usually depends on the values of other fields on
-the computed record. The ORM expects the developer to specify those dependencies
-on the compute method with the decorator :func:`~odoo.api.depends`.
-The given dependencies are used by the ORM to trigger the recomputation of the
-field whenever some of its dependencies have been modified::
-
- from odoo import models, fields, api
-
- class ComputedModel(models.Model):
- _name = 'test.computed'
-
- name = fields.Char(compute='_compute_name')
- value = fields.Integer()
-
- @api.depends('value')
- def _compute_name(self):
- for record in self:
- record.name = "Record with value %s" % record.value
-
-.. exercise:: Computed fields
-
- * Add the percentage of taken seats to the *Session* model
- * Display that field in the tree and form views
- * Display the field as a progress bar
-
- .. only:: solutions
-
- #. Add a computed field to *Session*
- #. Show the field in the *Session* view:
-
- .. patch::
-
-Default values
---------------
-
-Any field can be given a default value. In the field definition, add the option
-``default=X`` where ``X`` is either a Python literal value (boolean, integer,
-float, string), or a function taking a recordset and returning a value::
-
- name = fields.Char(default="Unknown")
- user_id = fields.Many2one('res.users', default=lambda self: self.env.user)
-
-.. note::
-
- The object ``self.env`` gives access to request parameters and other useful
- things:
-
- - ``self.env.cr`` or ``self._cr`` is the database *cursor* object; it is
- used for querying the database
- - ``self.env.uid`` or ``self._uid`` is the current user's database id
- - ``self.env.user`` is the current user's record
- - ``self.env.context`` or ``self._context`` is the context dictionary
- - ``self.env.ref(xml_id)`` returns the record corresponding to an XML id
- - ``self.env[model_name]`` returns an instance of the given model
-
-.. exercise:: Active objects – Default values
-
- * Define the start_date default value as today (see
- :class:`~odoo.fields.Date`).
- * Add a field ``active`` in the class Session, and set sessions as active by
- default.
-
- .. only:: solutions
-
- .. patch::
-
- .. note::
-
- Odoo has built-in rules making records with an ``active`` field set
- to ``False`` invisible.
-
-Onchange
-========
-
-The "onchange" mechanism provides a way for the client interface to update a
-form whenever the user has filled in a value in a field, without saving anything
-to the database.
-
-For instance, suppose a model has three fields ``amount``, ``unit_price`` and
-``price``, and you want to update the price on the form when any of the other
-fields is modified. To achieve this, define a method where ``self`` represents
-the record in the form view, and decorate it with :func:`~odoo.api.onchange`
-to specify on which field it has to be triggered. Any change you make on
-``self`` will be reflected on the form.
-
-.. code-block:: xml
-
- <!-- content of form view -->
- <field name="amount"/>
- <field name="unit_price"/>
- <field name="price" readonly="1"/>
-
-.. code-block:: python
-
- # onchange handler
- @api.onchange('amount', 'unit_price')
- def _onchange_price(self):
- # set auto-changing field
- self.price = self.amount * self.unit_price
- # Can optionally return a warning and domains
- return {
- 'warning': {
- 'title': "Something bad happened",
- 'message': "It was very bad indeed",
- }
- }
-
-For computed fields, valued ``onchange`` behavior is built-in as can be seen by
-playing with the *Session* form: change the number of seats or participants, and
-the ``taken_seats`` progressbar is automatically updated.
-
-.. exercise:: Warning
-
- Add an explicit onchange to warn about invalid values, like a negative
- number of seats, or more participants than seats.
-
- .. only:: solutions
-
- .. patch::
-
-Model constraints
-=================
-
-Odoo provides two ways to set up automatically verified invariants:
-:func:`Python constraints <odoo.api.constrains>` and
-:attr:`SQL constraints <odoo.models.Model._sql_constraints>`.
-
-A Python constraint is defined as a method decorated with
-:func:`~odoo.api.constrains`, and invoked on a recordset. The decorator
-specifies which fields are involved in the constraint, so that the constraint is
-automatically evaluated when one of them is modified. The method is expected to
-raise an exception if its invariant is not satisfied::
-
- from odoo.exceptions import ValidationError
-
- @api.constrains('age')
- def _check_something(self):
- for record in self:
- if record.age > 20:
- raise ValidationError("Your record is too old: %s" % record.age)
- # all records passed the test, don't return anything
-
-.. exercise:: Add Python constraints
-
- Add a constraint that checks that the instructor is not present in the
- attendees of his/her own session.
-
- .. only:: solutions
-
- .. patch::
-
-SQL constraints are defined through the model attribute
-:attr:`~odoo.models.Model._sql_constraints`. The latter is assigned to a list
-of triples of strings ``(name, sql_definition, message)``, where ``name`` is a
-valid SQL constraint name, ``sql_definition`` is a table_constraint_ expression,
-and ``message`` is the error message.
-
-.. exercise:: Add SQL constraints
-
- With the help of `PostgreSQL's documentation`_ , add the following
- constraints:
-
- #. CHECK that the course description and the course title are different
- #. Make the Course's name UNIQUE
-
- .. only:: solutions
-
- .. patch::
-
-.. exercise:: Exercise 6 - Add a duplicate option
-
- Since we added a constraint for the Course name uniqueness, it is not
- possible to use the "duplicate" function anymore (:menuselection:`Form -->
- Duplicate`).
-
- Re-implement your own "copy" method which allows to duplicate the Course
- object, changing the original name into "Copy of [original name]".
-
- .. only:: solutions
-
- .. patch::
-
-Advanced Views
-==============
-
-Tree views
-----------
-
-Tree views can take supplementary attributes to further customize their
-behavior:
-
-``decoration-{$name}``
- allow changing the style of a row's text based on the corresponding
- record's attributes.
-
- Values are Python expressions. For each record, the expression is evaluated
- with the record's attributes as context values and if ``true``, the
- corresponding style is applied to the row. Here are some of the other values
- available in the context:
-
- * ``uid``: the id of the current user,
- * ``today``: the current local date as a string of the form ``YYYY-MM-DD``,
- * ``now``: same as ``today`` with the addition of the current time.
- This value is formatted as ``YYYY-MM-DD hh:mm:ss``.
-
- ``{$name}`` can be ``bf`` (``font-weight: bold``), ``it``
- (``font-style: italic``), or any `bootstrap contextual color
- <https://getbootstrap.com/docs/3.3/components/#available-variations>`_ (``danger``,
- ``info``, ``muted``, ``primary``, ``success`` or ``warning``).
-
- .. code-block:: xml
-
- <tree string="Idea Categories" decoration-info="state=='draft'"
- decoration-danger="state=='trashed'">
- <field name="name"/>
- <field name="state"/>
- </tree>
-
-``editable``
- Either ``"top"`` or ``"bottom"``. Makes the tree view editable in-place
- (rather than having to go through the form view), the value is the
- position where new rows appear.
-
-.. exercise:: List coloring
-
- Modify the Session tree view in such a way that sessions lasting less than
- 5 days are colored blue, and the ones lasting more than 15 days are
- colored red.
-
- .. only:: solutions
-
- Modify the session tree view:
-
- .. patch::
-
-Calendars
----------
-
-Displays records as calendar events. Their root element is ``<calendar>`` and
-their most common attributes are:
-
-``color``
- The name of the field used for *color segmentation*. Colors are
- automatically distributed to events, but events in the same color segment
- (records which have the same value for their ``@color`` field) will be
- given the same color.
-``date_start``
- record's field holding the start date/time for the event
-``date_stop`` (optional)
-   record's field holding the end date/time for the event
-``string``
- record's field to define the label for each calendar event
-
-.. code-block:: xml
-
- <calendar string="Ideas" date_start="invent_date" color="inventor_id">
- <field name="name"/>
- </calendar>
-
-.. exercise:: Calendar view
-
- Add a Calendar view to the *Session* model enabling the user to view the
- events associated to the Open Academy.
-
- .. only:: solutions
-
- #. Add an ``end_date`` field computed from ``start_date`` and
- ``duration``
-
- .. tip:: the inverse function makes the field writable, and allows
- moving the sessions (via drag and drop) in the calendar view
-
- #. Add a calendar view to the *Session* model
- #. And add the calendar view to the *Session* model's actions
-
- .. patch::
-
-Search views
-------------
-
-Search view ``<field>`` elements can have a ``@filter_domain`` that overrides
-the domain generated for searching on the given field. In the given domain,
-``self`` represents the value entered by the user. In the example below, it is
-used to search on both fields ``name`` and ``description``.
-
-Search views can also contain ``<filter>`` elements, which act as toggles for
-predefined searches. Filters must have one of the following attributes:
-
-``domain``
- add the given domain to the current search
-``context``
- add some context to the current search; use the key ``group_by`` to group
- results on the given field name
-
-.. code-block:: xml
-
- <search string="Ideas">
- <field name="name"/>
- <field name="description" string="Name and description"
- filter_domain="['|', ('name', 'ilike', self), ('description', 'ilike', self)]"/>
- <field name="inventor_id"/>
- <field name="country_id" widget="selection"/>
-
- <filter name="my_ideas" string="My Ideas"
- domain="[('inventor_id', '=', uid)]"/>
- <group string="Group By">
- <filter name="group_by_inventor" string="Inventor"
- context="{'group_by': 'inventor_id'}"/>
- </group>
- </search>
-
-To use a non-default search view in an action, it should be linked using the
-``search_view_id`` field of the action record.
-
-The action can also set default values for search fields through its
-``context`` field: context keys of the form
-:samp:`search_default_{field_name}` will initialize *field_name* with the
-provided value. Search filters must have an optional ``@name`` to have a
-default and behave as booleans (they can only be enabled by default).
-
-.. exercise:: Search views
-
- #. Add a button to filter the courses for which the current user is the
- responsible in the course search view. Make it selected by default.
- #. Add a button to group courses by responsible user.
-
- .. only:: solutions
-
- .. patch::
-
-Gantt
------
-
-.. warning::
-
- The gantt view requires the web_gantt module which is present in
- :ref:`the enterprise edition <setup/install/editions>` version.
-
-Horizontal bar charts typically used to show project planning and advancement,
-their root element is ``<gantt>``.
-
-.. code-block:: xml
-
- <gantt string="Ideas"
- date_start="invent_date"
- date_stop="date_finished"
- progress="progress"
- default_group_by="inventor_id" />
-
-.. exercise:: Gantt charts
-
- Add a Gantt Chart enabling the user to view the sessions scheduling linked
- to the Open Academy module. The sessions should be grouped by instructor.
-
- .. only:: solutions
-
- #. Add the gantt view's definition, and add the gantt view to the
- *Session* model's action
-
- .. patch::
-
-Graph views
------------
-
-Graph views allow aggregated overview and analysis of models, their root
-element is ``<graph>``.
-
-.. note::
- Pivot views (element ``<pivot>``) a multidimensional table, allows the
- selection of filers and dimensions to get the right aggregated dataset
- before moving to a more graphical overview. The pivot view shares the same
- content definition as graph views.
-
-Graph views have 4 display modes, the default mode is selected using the
-``@type`` attribute.
-
-Bar (default)
- a bar chart, the first dimension is used to define groups on the
- horizontal axis, other dimensions define aggregated bars within each group.
-
- By default bars are side-by-side, they can be stacked by using
- ``@stacked="True"`` on the ``<graph>``
-Line
- 2-dimensional line chart
-Pie
- 2-dimensional pie
-
-Graph views contain ``<field>`` with a mandatory ``@type`` attribute taking
-the values:
-
-``row`` (default)
- the field should be aggregated by default
-``measure``
- the field should be aggregated rather than grouped on
-
-.. code-block:: xml
-
- <graph string="Total idea score by Inventor">
- <field name="inventor_id"/>
- <field name="score" type="measure"/>
- </graph>
-
-.. warning::
-
- Graph views perform aggregations on database values, they do not work
- with non-stored computed fields.
-
-.. exercise:: Graph view
-
- Add a Graph view in the Session object that displays, for each course, the
- number of attendees under the form of a bar chart.
-
- .. only:: solutions
-
- #. Add the number of attendees as a stored computed field
- #. Then add the relevant view
-
- .. patch::
-
-Kanban
-------
-
-Used to organize tasks, production processes, etc… their root element is
-``<kanban>``.
-
-A kanban view shows a set of cards possibly grouped in columns. Each card
-represents a record, and each column the values of an aggregation field.
-
-For instance, project tasks may be organized by stage (each column is a
-stage), or by responsible (each column is a user), and so on.
-
-Kanban views define the structure of each card as a mix of form elements
-(including basic HTML) and :ref:`reference/qweb`.
-
-.. exercise:: Kanban view
-
- Add a Kanban view that displays sessions grouped by course (columns are
- thus courses).
-
- .. only:: solutions
-
- #. Add an integer ``color`` field to the *Session* model
- #. Add the kanban view and update the action
-
- .. patch::
-
-Security
-========
-
-Access control mechanisms must be configured to achieve a coherent security
-policy.
-
-Group-based access control mechanisms
--------------------------------------
-
-Groups are created as normal records on the model ``res.groups``, and granted
-menu access via menu definitions. However even without a menu, objects may
-still be accessible indirectly, so actual object-level permissions (read,
-write, create, unlink) must be defined for groups. They are usually inserted
-via CSV files inside modules. It is also possible to restrict access to
-specific fields on a view or object using the field's groups attribute.
-
-Access rights
--------------
-
-Access rights are defined as records of the model ``ir.model.access``. Each
-access right is associated to a model, a group (or no group for global
-access), and a set of permissions: read, write, create, unlink. Such access
-rights are usually created by a CSV file named after its model:
-``ir.model.access.csv``.
-
-.. code-block:: text
-
- id,name,model_id/id,group_id/id,perm_read,perm_write,perm_create,perm_unlink
- access_idea_idea,idea.idea,model_idea_idea,base.group_user,1,1,1,0
- access_idea_vote,idea.vote,model_idea_vote,base.group_user,1,1,1,0
-
-.. exercise:: Add access control through the Odoo interface
-
- Create a new user "John Smith". Then create a group
- "OpenAcademy / Session Read" with read access to the *Session* model.
-
- .. only:: solutions
-
- #. Create a new user *John Smith* through
- :menuselection:`Settings --> Users --> Users`
- #. Create a new group ``session_read`` through
- :menuselection:`Settings --> Users --> Groups`, it should have
- read access on the *Session* model
- #. Edit *John Smith* to make them a member of ``session_read``
- #. Log in as *John Smith* to check the access rights are correct
-
-.. exercise:: Add access control through data files in your module
-
- Using data files,
-
- * Create a group *OpenAcademy / Manager* with full access to all
- OpenAcademy models
- * Make *Session* and *Course* readable by all users
-
- .. only:: solutions
-
- #. Create a new file ``openacademy/security/security.xml`` to
- hold the OpenAcademy Manager group
- #. Edit the file ``openacademy/security/ir.model.access.csv`` with
- the access rights to the models
- #. Finally update ``openacademy/__manifest__.py`` to add the new data
- files to it
-
- .. patch::
-
-Record rules
-------------
-
-A record rule restricts the access rights to a subset of records of the given
-model. A rule is a record of the model ``ir.rule``, and is associated to a
-model, a number of groups (many2many field), permissions to which the
-restriction applies, and a domain. The domain specifies to which records the
-access rights are limited.
-
-Here is an example of a rule that prevents the deletion of leads that are not
-in state ``cancel``. Notice that the value of the field ``groups`` must follow
-the same convention as the method :meth:`~odoo.models.Model.write` of the ORM.
-
-.. code-block:: xml
-
- <record id="delete_cancelled_only" model="ir.rule">
- <field name="name">Only cancelled leads may be deleted</field>
- <field name="model_id" ref="crm.model_crm_lead"/>
- <field name="groups" eval="[(4, ref('sales_team.group_sale_manager'))]"/>
- <field name="perm_read" eval="0"/>
- <field name="perm_write" eval="0"/>
- <field name="perm_create" eval="0"/>
- <field name="perm_unlink" eval="1" />
- <field name="domain_force">[('state','=','cancel')]</field>
- </record>
-
-.. exercise:: Record rule
-
- Add a record rule for the model Course and the group
- "OpenAcademy / Manager", that restricts ``write`` and ``unlink`` accesses
- to the responsible of a course. If a course has no responsible, all users
- of the group must be able to modify it.
-
- .. only:: solutions
-
- Create a new rule in ``openacademy/security/security.xml``:
-
- .. patch::
-
-.. _howto/module/wizard:
-
-Wizards
-=======
-
-Wizards describe interactive sessions with the user (or dialog boxes) through
-dynamic forms. A wizard is simply a model that extends the class
-:class:`~odoo.models.TransientModel` instead of
-:class:`~odoo.models.Model`. The class
-:class:`~odoo.models.TransientModel` extends :class:`~odoo.models.Model`
-and reuse all its existing mechanisms, with the following particularities:
-
-- Wizard records are not meant to be persistent; they are automatically deleted
- from the database after a certain time. This is why they are called
- *transient*.
-- Wizard records may refer to regular records or wizard records through relational
- fields(many2one or many2many), but regular records *cannot* refer to wizard records through a
- many2one field.
-
-We want to create a wizard that allow users to create attendees for a particular
-session, or for a list of sessions at once.
-
-.. exercise:: Define the wizard
-
- Create a wizard model with a many2one relationship with the *Session*
- model and a many2many relationship with the *Partner* model.
-
- .. only:: solutions
-
- Add a new file ``openacademy/wizard.py``:
-
- .. patch::
-
-Launching wizards
------------------
-
-Wizards are simply :ref:`window actions <howtos/module/actions>` with a ``target``
-field set to the value ``new``, which opens the view
-(usually :ref:`a form <howtos/module/views/form>`) in a separate dialog. The
-action may be triggered via a menu item, but is more generally triggered by a
-button.
-
-An other way to launch wizards is through the :menuselection:`Action` menu of
-a tree or form view. This is done through the ``binding_model_id`` field of the
-action. Setting this field will make the action appear on the views of the model
-the action is "bound" to.
-
-.. code:: xml
-
- <record id="launch_the_wizard" model="ir.actions.act_window">
- <field name="name">Launch the Wizard</field>
- <field name="model">wizard.model.name</field>
- <field name="view_mode">form</field>
- <field name="target">new<field>
- <field name="binding_model_id" ref="model_context_model_ref"/>
- </record>
-
-.. tip::
-
- While wizards use regular views and buttons, normally clicking any button in
- a form would first save the form then close the dialog. Because this is
- often undesirable in wizards, a special attribute ``special="cancel"`` is
- available which immediately closes the wizard without saving the form.
-
-.. exercise:: Launch the wizard
-
- #. Define a form view for the wizard.
- #. Add the action to launch it in the context of the *Session* model.
- #. Define a default value for the session field in the wizard; use the
- context parameter ``self._context`` to retrieve the current session.
-
- .. only:: solutions
-
- .. patch::
-
-.. exercise:: Register attendees
-
- Add buttons to the wizard, and implement the corresponding method for adding
- the attendees to the given session.
-
- .. only:: solutions
-
- .. patch::
-
-.. exercise:: Register attendees to multiple sessions
-
- Modify the wizard model so that attendees can be registered to multiple
- sessions.
-
- .. only:: solutions
-
- .. patch::
-
-Internationalization
-====================
-
-Each module can provide its own translations within the i18n directory, by
-having files named LANG.po where LANG is the locale code for the language, or
-the language and country combination when they differ (e.g. pt.po or
-pt_BR.po). Translations will be loaded automatically by Odoo for all
-enabled languages. Developers always use English when creating a module, then
-export the module terms using Odoo's gettext POT export feature
-(:menuselection:`Settings --> Translations --> Import/Export --> Export
-Translation` without specifying a language), to create the module template POT
-file, and then derive the translated PO files. Many IDE's have plugins or modes
-for editing and merging PO/POT files.
-
-.. tip:: The Portable Object files generated by Odoo are published on
- `Transifex <https://www.transifex.com/odoo/public/>`__, making it
- easy to translate the software.
-
-.. code-block:: text
-
- |- idea/ # The module directory
- |- i18n/ # Translation files
- | - idea.pot # Translation Template (exported from Odoo)
- | - fr.po # French translation
- | - pt_BR.po # Brazilian Portuguese translation
- | (...)
-
-.. tip::
-
- By default Odoo's POT export only extracts labels inside XML files or
- inside field definitions in Python code, but any Python string can be
- translated this way by surrounding it with the function :func:`odoo._`
- (e.g. ``_("Label")``)
-
-.. exercise:: Translate a module
-
- Choose a second language for your Odoo installation. Translate your
- module using the facilities provided by Odoo.
-
- .. only:: solutions
-
- #. Create a directory ``openacademy/i18n/``
- #. You will need to activate the developer mode
- to access the menus mentioned below (
- :menuselection:`Settings --> Activate the developer mode`
- )
- #. Install whichever language you want (
- :menuselection:`Settings --> Translations --> Languages`)
- #. Generate the missing terms (:menuselection:`Settings -->
- Translations --> Application Terms --> Generate Missing Terms`)
- #. Create a template translation file by exporting (
- :menuselection:`Settings --> Translations --> Import/Export
- --> Export Translation`) without specifying a language, save in
- ``openacademy/i18n/``
- #. Create a translation file by exporting (
- :menuselection:`Settings --> Translations --> Import/Export
- --> Export Translation`) and specifying a language. Save it in
- ``openacademy/i18n/``
- #. Open the exported translation file (with a basic text editor or a
- dedicated PO-file editor e.g. POEdit_ and translate the missing
- terms
-
- #. In ``models.py``, add an import statement for the function
- ``odoo._`` and mark missing strings as translatable
-
- #. Repeat steps 3-6
-
- .. patch::
-
- .. todo:: do we never reload translations?
-
-
-Reporting
-=========
-
-Printed reports
----------------
-
-Odoo uses a report engine based on :ref:`reference/qweb`,
-`Twitter Bootstrap`_ and Wkhtmltopdf_.
-
-A report is a combination two elements:
-
-* an ``ir.actions.report`` which configures various basic parameters for the
- report (default type, whether the report should be saved to the database
- after generation,…)
-
- .. code-block:: xml
-
- <record id="account_invoices" model="ir.actions.report">
- <field name="name">Invoices</field>
- <field name="model">account.invoice</field>
- <field name="report_type">qweb-pdf</field>
- <field name="report_name">account.report_invoice</field>
- <field name="report_file">account.report_invoice</field>
- <field name="attachment_use" eval="True"/>
- <field name="attachment">(object.state in ('open','paid')) and
- ('INV'+(object.number or '').replace('/','')+'.pdf')</field>
- <field name="binding_model_id" ref="model_account_invoice"/>
- <field name="binding_type">report</field>
- </record>
-
- .. tip::
-
- Because it largerly a standard action, as with :ref:`howto/module/wizard`
- it is generally useful to add the report as a *contextual item* on the
- tree and / or form views of the model being reported on via the
- ``binding_model_id`` field.
-
- Here we are also using ``binding_type`` in order for the report to be in
- the *report* contextual menu rather than the *action* one. There is no
- technical difference but putting elements in the right place helps users.
-
-* A standard :ref:`QWeb view <reference/views/qweb>` for the actual report:
-
- .. code-block:: xml
-
- <t t-call="web.html_container">
- <t t-foreach="docs" t-as="o">
- <t t-call="web.external_layout">
- <div class="page">
- <h2>Report title</h2>
- </div>
- </t>
- </t>
- </t>
-
- the standard rendering context provides a number of elements, the most
- important being:
-
- ``docs``
- the records for which the report is printed
- ``user``
- the user printing the report
-
-Because reports are standard web pages, they are available through a URL and
-output parameters can be manipulated through this URL, for instance the HTML
-version of the *Invoice* report is available through
-http://localhost:8069/report/html/account.report_invoice/1 (if ``account`` is
-installed) and the PDF version through
-http://localhost:8069/report/pdf/account.report_invoice/1.
-
-.. _reference/backend/reporting/printed-reports/pdf-without-styles:
-
-.. danger::
-
- If it appears that your PDF report is missing the styles (i.e. the text
- appears but the style/layout is different from the html version), probably
- your wkhtmltopdf_ process cannot reach your web server to download them.
-
- If you check your server logs and see that the CSS styles are not being
- downloaded when generating a PDF report, most surely this is the problem.
-
- The wkhtmltopdf_ process will use the ``web.base.url`` system parameter as
- the *root path* to all linked files, but this parameter is automatically
- updated each time the Administrator is logged in. If your server resides
- behind some kind of proxy, that could not be reachable. You can fix this by
- adding one of these system parameters:
-
- - ``report.url``, pointing to an URL reachable from your server
- (probably ``http://localhost:8069`` or something similar). It will be
- used for this particular purpose only.
-
- - ``web.base.url.freeze``, when set to ``True``, will stop the
- automatic updates to ``web.base.url``.
-
-.. exercise:: Create a report for the Session model
-
- For each session, it should display session's name, its start and end,
- and list the session's attendees.
-
- .. only:: solutions
-
- .. patch::
-
-Dashboards
-----------
-
-.. exercise:: Define a Dashboard
-
- Define a dashboard containing the graph view you created, the sessions
- calendar view and a list view of the courses (switchable to a form
- view). This dashboard should be available through a menuitem in the menu,
- and automatically displayed in the web client when the OpenAcademy main
- menu is selected.
-
- .. only:: solutions
-
- #. Create a file ``openacademy/views/session_board.xml``. It should contain
- the board view, the actions referenced in that view, an action to
- open the dashboard and a re-definition of the main menu item to add
- the dashboard action
-
- .. note:: Available dashboard styles are ``1``, ``1-1``, ``1-2``,
- ``2-1`` and ``1-1-1``
-
- #. Update ``openacademy/__manifest__.py`` to reference the new data
- file
-
- .. patch::
-
-WebServices
-===========
-
-The web-service module offer a common interface for all web-services :
-
-- XML-RPC
-- JSON-RPC
-
-Business objects can also be accessed via the distributed object
-mechanism. They can all be modified via the client interface with contextual
-views.
-
-Odoo is accessible through XML-RPC/JSON-RPC interfaces, for which libraries
-exist in many languages.
-
-XML-RPC Library
----------------
-
-The following example is a Python 3 program that interacts with an Odoo
-server with the library ``xmlrpc.client``::
-
- import xmlrpc.client
-
- root = 'http://%s:%d/xmlrpc/' % (HOST, PORT)
-
- uid = xmlrpc.client.ServerProxy(root + 'common').login(DB, USER, PASS)
- print("Logged in as %s (uid: %d)" % (USER, uid))
-
- # Create a new note
- sock = xmlrpc.client.ServerProxy(root + 'object')
- args = {
- 'color' : 8,
- 'memo' : 'This is a note',
- 'create_uid': uid,
- }
- note_id = sock.execute(DB, uid, PASS, 'note.note', 'create', args)
-
-.. exercise:: Add a new service to the client
-
- Write a Python program able to send XML-RPC requests to a PC running
- Odoo (yours, or your instructor's). This program should display all
- the sessions, and their corresponding number of seats. It should also
- create a new session for one of the courses.
-
- .. only:: solutions
-
- .. code-block:: python
-
- import functools
- import xmlrpc.client
- HOST = 'localhost'
- PORT = 8069
- DB = 'openacademy'
- USER = 'admin'
- PASS = 'admin'
- ROOT = 'http://%s:%d/xmlrpc/' % (HOST,PORT)
-
- # 1. Login
- uid = xmlrpc.client.ServerProxy(ROOT + 'common').login(DB,USER,PASS)
- print("Logged in as %s (uid:%d)" % (USER,uid))
-
- call = functools.partial(
- xmlrpc.client.ServerProxy(ROOT + 'object').execute,
- DB, uid, PASS)
-
- # 2. Read the sessions
- sessions = call('openacademy.session','search_read', [], ['name','seats'])
- for session in sessions:
- print("Session %s (%s seats)" % (session['name'], session['seats']))
- # 3.create a new session
- session_id = call('openacademy.session', 'create', {
- 'name' : 'My session',
- 'course_id' : 2,
- })
-
- Instead of using a hard-coded course id, the code can look up a course
- by name::
-
- # 3.create a new session for the "Functional" course
- course_id = call('openacademy.course', 'search', [('name','ilike','Functional')])[0]
- session_id = call('openacademy.session', 'create', {
- 'name' : 'My session',
- 'course_id' : course_id,
- })
-
-JSON-RPC Library
-----------------
-
-The following example is a Python 3 program that interacts with an Odoo server
-with the standard Python libraries ``urllib.request`` and ``json``. This
-example assumes the **Productivity** app (``note``) is installed::
-
- import json
- import random
- import urllib.request
-
- HOST = 'localhost'
- PORT = 8069
- DB = 'openacademy'
- USER = 'admin'
- PASS = 'admin'
-
- def json_rpc(url, method, params):
- data = {
- "jsonrpc": "2.0",
- "method": method,
- "params": params,
- "id": random.randint(0, 1000000000),
- }
- req = urllib.request.Request(url=url, data=json.dumps(data).encode(), headers={
- "Content-Type":"application/json",
- })
- reply = json.loads(urllib.request.urlopen(req).read().decode('UTF-8'))
- if reply.get("error"):
- raise Exception(reply["error"])
- return reply["result"]
-
- def call(url, service, method, *args):
- return json_rpc(url, "call", {"service": service, "method": method, "args": args})
-
- # log in the given database
- url = "http://%s:%s/jsonrpc" % (HOST, PORT)
- uid = call(url, "common", "login", DB, USER, PASS)
-
- # create a new note
- args = {
- 'color': 8,
- 'memo': 'This is another note',
- 'create_uid': uid,
- }
- note_id = call(url, "object", "execute", DB, uid, PASS, 'note.note', 'create', args)
-
-Examples can be easily adapted from XML-RPC to JSON-RPC.
-
-.. note::
-
- There are a number of high-level APIs in various languages to access Odoo
- systems without *explicitly* going through XML-RPC or JSON-RPC, such as:
-
- * https://github.com/akretion/ooor
- * https://github.com/OCA/odoorpc
- * https://github.com/nicolas-van/openerp-client-lib
- * http://pythonhosted.org/OdooRPC
- * https://github.com/abhishek-jaiswal/php-openerp-lib
-
-.. [#autofields] it is possible to :ref:`disable the automatic creation of some
- fields <reference/fields/automatic/log_access>`
-.. [#rawsql] writing raw SQL queries is possible, but requires care as it
- bypasses all Odoo authentication and security mechanisms.
-
-.. _database index:
- http://use-the-index-luke.com/sql/preface
-
-.. _POEdit: http://poedit.net
-
-.. _PostgreSQL's documentation:
-.. _table_constraint:
- http://www.postgresql.org/docs/9.3/static/ddl-constraints.html
-
-.. _python: http://python.org
-
-.. _XPath: http://w3.org/TR/xpath
-
-.. _twitter bootstrap: http://getbootstrap.com
-
-.. _wkhtmltopdf: http://wkhtmltopdf.org
diff --git a/doc/howtos/backend/exercise-access-rights b/doc/howtos/backend/exercise-access-rights
deleted file mode 100644
index 465dffea804..00000000000
--- a/doc/howtos/backend/exercise-access-rights
+++ /dev/null
@@ -1,40 +0,0 @@
-# HG changeset patch
-# Parent 303a5f4f011822dcb42b5833d579eabd3f03f4bf
-
-Index: addons/openacademy/__manifest__.py
-===================================================================
---- addons.orig/openacademy/__manifest__.py 2014-08-26 17:26:18.143783102 +0200
-+++ addons/openacademy/__manifest__.py 2014-08-26 17:26:18.135783102 +0200
-@@ -25,7 +25,8 @@
-
- # always loaded
- 'data': [
-- # 'security/ir.model.access.csv',
-+ 'security/security.xml',
-+ 'security/ir.model.access.csv',
- 'templates.xml',
- 'views/openacademy.xml',
- 'views/partner.xml',
-Index: addons/openacademy/security/ir.model.access.csv
-===================================================================
---- addons.orig/openacademy/security/ir.model.access.csv 2014-08-26 17:26:18.143783102 +0200
-+++ addons/openacademy/security/ir.model.access.csv 2014-08-26 17:26:18.135783102 +0200
-@@ -1,2 +1,5 @@
- id,name,model_id/id,group_id/id,perm_read,perm_write,perm_create,perm_unlink
--access_openacademy_openacademy,openacademy.openacademy,model_openacademy_openacademy,,1,0,0,0
-+course_manager,course manager,model_openacademy_course,group_manager,1,1,1,1
-+session_manager,session manager,model_openacademy_session,group_manager,1,1,1,1
-+course_read_all,course all,model_openacademy_course,,1,0,0,0
-+session_read_all,session all,model_openacademy_session,,1,0,0,0
-Index: addons/openacademy/security/security.xml
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ addons/openacademy/security/security.xml 2014-08-26 17:26:18.135783102 +0200
-@@ -0,0 +1,7 @@
-+<odoo>
-+
-+ <record id="group_manager" model="res.groups">
-+ <field name="name">OpenAcademy / Manager</field>
-+ </record>
-+
-+</odoo>
diff --git a/doc/howtos/backend/exercise-access-rules b/doc/howtos/backend/exercise-access-rules
deleted file mode 100644
index d6290dfdbe1..00000000000
--- a/doc/howtos/backend/exercise-access-rules
+++ /dev/null
@@ -1,27 +0,0 @@
-# HG changeset patch
-# Parent 0602022dc2a428f9995c886df33b699b6d3bcb69
-
-Index: addons/openacademy/security/security.xml
-===================================================================
---- addons.orig/openacademy/security/security.xml 2014-08-26 17:26:18.971783090 +0200
-+++ addons/openacademy/security/security.xml 2014-08-26 17:26:18.967783090 +0200
-@@ -3,5 +3,19 @@
- <record id="group_manager" model="res.groups">
- <field name="name">OpenAcademy / Manager</field>
- </record>
-+
-+ <record id="only_responsible_can_modify" model="ir.rule">
-+ <field name="name">Only Responsible can modify Course</field>
-+ <field name="model_id" ref="model_openacademy_course"/>
-+ <field name="groups" eval="[(4, ref('openacademy.group_manager'))]"/>
-+ <field name="perm_read" eval="0"/>
-+ <field name="perm_write" eval="1"/>
-+ <field name="perm_create" eval="0"/>
-+ <field name="perm_unlink" eval="1"/>
-+ <field name="domain_force">
-+ ['|', ('responsible_id','=',False),
-+ ('responsible_id','=',user.id)]
-+ </field>
-+ </record>
-
- </odoo>
diff --git a/doc/howtos/backend/exercise-advanced-treeview b/doc/howtos/backend/exercise-advanced-treeview
deleted file mode 100644
index 69ddd66cfef..00000000000
--- a/doc/howtos/backend/exercise-advanced-treeview
+++ /dev/null
@@ -1,19 +0,0 @@
-# HG changeset patch
-# Parent f8d2422e87b3ff566dc947ad582608db3b15e077
-
-Index: addons/openacademy/views/openacademy.xml
-===================================================================
---- addons.orig/openacademy/views/openacademy.xml 2014-08-26 17:26:09.283783234 +0200
-+++ addons/openacademy/views/openacademy.xml 2014-08-26 17:26:09.279783234 +0200
-@@ -115,9 +115,10 @@
- <field name="name">session.tree</field>
- <field name="model">openacademy.session</field>
- <field name="arch" type="xml">
-- <tree string="Session Tree">
-+ <tree string="Session Tree" decoration-info="duration&lt;5" decoration-danger="duration&gt;15">
- <field name="name"/>
- <field name="course_id"/>
-+ <field name="duration" invisible="1"/>
- <field name="taken_seats" widget="progressbar"/>
- </tree>
- </field>
diff --git a/doc/howtos/backend/exercise-basic-action b/doc/howtos/backend/exercise-basic-action
deleted file mode 100644
index 65e788b804b..00000000000
--- a/doc/howtos/backend/exercise-basic-action
+++ /dev/null
@@ -1,53 +0,0 @@
-# HG changeset patch
-# Parent 16e4cb131d9f7f3a72a8a1b0bc46c2ce9ac76435
-Index: addons/openacademy/__manifest__.py
-===================================================================
---- addons.orig/openacademy/__manifest__.py 2014-08-26 17:25:53.519783468 +0200
-+++ addons/openacademy/__manifest__.py 2014-08-26 17:25:53.511783468 +0200
-@@ -27,6 +27,7 @@
- 'data': [
- # 'security/ir.model.access.csv',
- 'templates.xml',
-+ 'views/openacademy.xml',
- ],
- # only loaded in demonstration mode
- 'demo': [
-Index: addons/openacademy/views/openacademy.xml
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ addons/openacademy/views/openacademy.xml 2014-08-26 17:25:53.511783468 +0200
-@@ -0,0 +1,34 @@
-+<?xml version="1.0" encoding="UTF-8"?>
-+<odoo>
-+
-+ <!-- window action -->
-+ <!--
-+ The following tag is an action definition for a "window action",
-+ that is an action opening a view or a set of views
-+ -->
-+ <record model="ir.actions.act_window" id="course_list_action">
-+ <field name="name">Courses</field>
-+ <field name="res_model">openacademy.course</field>
-+ <field name="view_mode">tree,form</field>
-+ <field name="help" type="html">
-+ <p class="o_view_nocontent_smiling_face">Create the first course
-+ </p>
-+ </field>
-+ </record>
-+
-+ <!-- top level menu: no parent -->
-+ <menuitem id="main_openacademy_menu" name="Open Academy"/>
-+ <!-- A first level in the left side menu is needed
-+ before using action= attribute -->
-+ <menuitem id="openacademy_menu" name="Open Academy"
-+ parent="main_openacademy_menu"/>
-+ <!-- the following menuitem should appear *after*
-+ its parent openacademy_menu and *after* its
-+ action course_list_action -->
-+ <menuitem id="courses_menu" name="Courses" parent="openacademy_menu"
-+ action="course_list_action"/>
-+ <!-- Full id location:
-+ action="openacademy.course_list_action"
-+ It is not required when it is the same module -->
-+
-+</odoo>
diff --git a/doc/howtos/backend/exercise-calendar b/doc/howtos/backend/exercise-calendar
deleted file mode 100644
index 56689b02223..00000000000
--- a/doc/howtos/backend/exercise-calendar
+++ /dev/null
@@ -1,77 +0,0 @@
-# HG changeset patch
-# Parent 85a8d7317b9e13480f39ad739955442d15144451
-# Parent 16fcdc4c6462a7872636f3c19550c16879af5281
-
-diff --git a/openacademy/models.py b/openacademy/models.py
---- a/openacademy/models.py
-+++ b/openacademy/models.py
-@@ -1,5 +1,6 @@
- # -*- coding: utf-8 -*-
-
-+from datetime import timedelta
- from odoo import models, fields, api, exceptions
-
- class Course(models.Model):
-@@ -57,6 +58,8 @@ class Session(models.Model):
- attendee_ids = fields.Many2many('res.partner', string="Attendees")
-
- taken_seats = fields.Float(string="Taken seats", compute='_taken_seats')
-+ end_date = fields.Date(string="End Date", store=True,
-+ compute='_get_end_date', inverse='_set_end_date')
-
- @api.depends('seats', 'attendee_ids')
- def _taken_seats(self):
-@@ -83,6 +86,27 @@ class Session(models.Model):
- },
- }
-
-+ @api.depends('start_date', 'duration')
-+ def _get_end_date(self):
-+ for r in self:
-+ if not (r.start_date and r.duration):
-+ r.end_date = r.start_date
-+ continue
-+
-+ # Add duration to start_date, but: Monday + 5 days = Saturday, so
-+ # subtract one second to get on Friday instead
-+ duration = timedelta(days=r.duration, seconds=-1)
-+ r.end_date = r.start_date + duration
-+
-+ def _set_end_date(self):
-+ for r in self:
-+ if not (r.start_date and r.end_date):
-+ continue
-+
-+ # Compute the difference between dates, but: Friday - Monday = 4 days,
-+ # so add one day to get 5 days instead
-+ r.duration = (r.end_date - r.start_date).days + 1
-+
- @api.constrains('instructor_id', 'attendee_ids')
- def _check_instructor_not_in_attendees(self):
- for r in self:
-diff --git a/openacademy/views/openacademy.xml b/openacademy/views/openacademy.xml
---- a/openacademy/views/openacademy.xml
-+++ b/openacademy/views/openacademy.xml
-@@ -124,10 +124,21 @@
- </field>
- </record>
-
-+ <!-- calendar view -->
-+ <record model="ir.ui.view" id="session_calendar_view">
-+ <field name="name">session.calendar</field>
-+ <field name="model">openacademy.session</field>
-+ <field name="arch" type="xml">
-+ <calendar string="Session Calendar" date_start="start_date" date_stop="end_date" color="instructor_id">
-+ <field name="name"/>
-+ </calendar>
-+ </field>
-+ </record>
-+
- <record model="ir.actions.act_window" id="session_list_action">
- <field name="name">Sessions</field>
- <field name="res_model">openacademy.session</field>
-- <field name="view_mode">tree,form</field>
-+ <field name="view_mode">tree,form,calendar</field>
- </record>
-
- <menuitem id="session_menu" name="Sessions"
diff --git a/doc/howtos/backend/exercise-computed b/doc/howtos/backend/exercise-computed
deleted file mode 100644
index 6736368dcd8..00000000000
--- a/doc/howtos/backend/exercise-computed
+++ /dev/null
@@ -1,40 +0,0 @@
-# HG changeset patch
-# Parent a358be0a577b0569831958a8ec1302825c645dee
-# Parent 59107edbe5f81bab5e7db172bf2bffa504ce399a
-
-diff --git a/openacademy/models.py b/openacademy/models.py
---- a/openacademy/models.py
-+++ b/openacademy/models.py
-@@ -30,3 +30,13 @@ class Session(models.Model):
- course_id = fields.Many2one('openacademy.course',
- ondelete='cascade', string="Course", required=True)
- attendee_ids = fields.Many2many('res.partner', string="Attendees")
-+
-+ taken_seats = fields.Float(string="Taken seats", compute='_taken_seats')
-+
-+ @api.depends('seats', 'attendee_ids')
-+ def _taken_seats(self):
-+ for r in self:
-+ if not r.seats:
-+ r.taken_seats = 0.0
-+ else:
-+ r.taken_seats = 100.0 * len(r.attendee_ids) / r.seats
-diff --git a/openacademy/views/openacademy.xml b/openacademy/views/openacademy.xml
---- a/openacademy/views/openacademy.xml
-+++ b/openacademy/views/openacademy.xml
-@@ -99,6 +99,7 @@
- <field name="start_date"/>
- <field name="duration"/>
- <field name="seats"/>
-+ <field name="taken_seats" widget="progressbar"/>
- </group>
- </group>
- <label for="attendee_ids"/>
-@@ -116,6 +117,7 @@
- <tree string="Session Tree">
- <field name="name"/>
- <field name="course_id"/>
-+ <field name="taken_seats" widget="progressbar"/>
- </tree>
- </field>
- </record>
diff --git a/doc/howtos/backend/exercise-constraint-python b/doc/howtos/backend/exercise-constraint-python
deleted file mode 100644
index 248507a241f..00000000000
--- a/doc/howtos/backend/exercise-constraint-python
+++ /dev/null
@@ -1,25 +0,0 @@
-# HG changeset patch
-# Parent 7a7d003fe38426a405ce0657a627a139133ec4dd
-# Parent 52f54b46487c8224a5aade4b921be77360ed3eae
-
-diff --git a/openacademy/models.py b/openacademy/models.py
---- a/openacademy/models.py
-+++ b/openacademy/models.py
-@@ -1,6 +1,6 @@
- # -*- coding: utf-8 -*-
-
--from odoo import models, fields, api
-+from odoo import models, fields, api, exceptions
-
- class Course(models.Model):
- _name = 'openacademy.course'
-@@ -58,3 +58,9 @@ class Session(models.Model):
- 'message': "Increase seats or remove excess attendees",
- },
- }
-+
-+ @api.constrains('instructor_id', 'attendee_ids')
-+ def _check_instructor_not_in_attendees(self):
-+ for r in self:
-+ if r.instructor_id and r.instructor_id in r.attendee_ids:
-+ raise exceptions.ValidationError("A session's instructor can't be an attendee")
diff --git a/doc/howtos/backend/exercise-constraint-sql b/doc/howtos/backend/exercise-constraint-sql
deleted file mode 100644
index 5595a6db3c6..00000000000
--- a/doc/howtos/backend/exercise-constraint-sql
+++ /dev/null
@@ -1,24 +0,0 @@
-# HG changeset patch
-# Parent 121bbfe120be3007f5e04611dbc27038abafcce8
-
-Index: addons/openacademy/models.py
-===================================================================
---- addons.orig/openacademy/models.py
-+++ addons/openacademy/models.py
-@@ -14,6 +14,16 @@
- session_ids = fields.One2many(
- 'openacademy.session', 'course_id', string="Sessions")
-
-+ _sql_constraints = [
-+ ('name_description_check',
-+ 'CHECK(name != description)',
-+ "The title of the course should not be the description"),
-+
-+ ('name_unique',
-+ 'UNIQUE(name)',
-+ "The course title must be unique"),
-+ ]
-+
-
- class Session(models.Model):
- _name = 'openacademy.session'
diff --git a/doc/howtos/backend/exercise-copy-override b/doc/howtos/backend/exercise-copy-override
deleted file mode 100644
index 119ed8ca2f7..00000000000
--- a/doc/howtos/backend/exercise-copy-override
+++ /dev/null
@@ -1,27 +0,0 @@
-# HG changeset patch
-# Parent 7d14b75cdfd4c7a272a13572947de5d47f3e851f
-# Parent f400352a70963801f0b4732d33a0183e4f6800ff
-
-diff --git a/openacademy/models.py b/openacademy/models.py
---- a/openacademy/models.py
-+++ b/openacademy/models.py
-@@ -14,6 +14,19 @@ class Course(models.Model):
- session_ids = fields.One2many(
- 'openacademy.session', 'course_id', string="Sessions")
-
-+ def copy(self, default=None):
-+ default = dict(default or {})
-+
-+ copied_count = self.search_count(
-+ [('name', '=like', u"Copy of {}%".format(self.name))])
-+ if not copied_count:
-+ new_name = u"Copy of {}".format(self.name)
-+ else:
-+ new_name = u"Copy of {} ({})".format(self.name, copied_count)
-+
-+ default['name'] = new_name
-+ return super(Course, self).copy(default)
-+
- _sql_constraints = [
- ('name_description_check',
- 'CHECK(name != description)',
diff --git a/doc/howtos/backend/exercise-creation b/doc/howtos/backend/exercise-creation
deleted file mode 100644
index f5510aa8743..00000000000
--- a/doc/howtos/backend/exercise-creation
+++ /dev/null
@@ -1,152 +0,0 @@
-# HG changeset patch
-# Parent 0000000000000000000000000000000000000000
-Index: addons/openacademy/__manifest__.py
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ addons/openacademy/__manifest__.py 2014-08-26 17:25:49.787783523 +0200
-@@ -0,0 +1,35 @@
-+# -*- coding: utf-8 -*-
-+{
-+ 'name': "Open Academy",
-+
-+ 'summary': """Manage trainings""",
-+
-+ 'description': """
-+ Open Academy module for managing trainings:
-+ - training courses
-+ - training sessions
-+ - attendees registration
-+ """,
-+
-+ 'author': "My Company",
-+ 'website': "http://www.yourcompany.com",
-+
-+ # Categories can be used to filter modules in modules listing
-+ # Check https://github.com/odoo/odoo/blob/14.0/odoo/addons/base/data/ir_module_category_data.xml
-+ # for the full list
-+ 'category': 'Test',
-+ 'version': '0.1',
-+
-+ # any module necessary for this one to work correctly
-+ 'depends': ['base'],
-+
-+ # always loaded
-+ 'data': [
-+ # 'security/ir.model.access.csv',
-+ 'templates.xml',
-+ ],
-+ # only loaded in demonstration mode
-+ 'demo': [
-+ 'demo.xml',
-+ ],
-+}
-Index: addons/openacademy/__init__.py
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ addons/openacademy/__init__.py 2014-08-26 17:25:49.791783523 +0200
-@@ -0,0 +1,3 @@
-+# -*- coding: utf-8 -*-
-+from . import controllers
-+from . import models
-Index: addons/openacademy/controllers.py
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ addons/openacademy/controllers.py 2014-08-26 17:25:49.791783523 +0200
-@@ -0,0 +1,20 @@
-+# -*- coding: utf-8 -*-
-+from odoo import http
-+
-+# class Openacademy(http.Controller):
-+# @http.route('/openacademy/openacademy/', auth='public')
-+# def index(self, **kw):
-+# return "Hello, world"
-+
-+# @http.route('/openacademy/openacademy/objects/', auth='public')
-+# def list(self, **kw):
-+# return http.request.render('openacademy.listing', {
-+# 'root': '/openacademy/openacademy',
-+# 'objects': http.request.env['openacademy.openacademy'].search([]),
-+# })
-+
-+# @http.route('/openacademy/openacademy/objects/<model("openacademy.openacademy"):obj>/', auth='public')
-+# def object(self, obj, **kw):
-+# return http.request.render('openacademy.object', {
-+# 'object': obj
-+# })
-Index: addons/openacademy/demo.xml
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ addons/openacademy/demo.xml 2014-08-26 17:25:49.791783523 +0200
-@@ -0,0 +1,25 @@
-+<odoo>
-+
-+ <!-- -->
-+ <!-- <record id="object0" model="openacademy.openacademy"> -->
-+ <!-- <field name="name">Object 0</field> -->
-+ <!-- </record> -->
-+ <!-- -->
-+ <!-- <record id="object1" model="openacademy.openacademy"> -->
-+ <!-- <field name="name">Object 1</field> -->
-+ <!-- </record> -->
-+ <!-- -->
-+ <!-- <record id="object2" model="openacademy.openacademy"> -->
-+ <!-- <field name="name">Object 2</field> -->
-+ <!-- </record> -->
-+ <!-- -->
-+ <!-- <record id="object3" model="openacademy.openacademy"> -->
-+ <!-- <field name="name">Object 3</field> -->
-+ <!-- </record> -->
-+ <!-- -->
-+ <!-- <record id="object4" model="openacademy.openacademy"> -->
-+ <!-- <field name="name">Object 4</field> -->
-+ <!-- </record> -->
-+ <!-- -->
-+
-+</odoo>
-Index: addons/openacademy/models.py
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ addons/openacademy/models.py 2014-08-26 17:25:49.791783523 +0200
-@@ -0,0 +1,8 @@
-+# -*- coding: utf-8 -*-
-+
-+from odoo import models, fields, api
-+
-+# class openacademy(models.Model):
-+# _name = 'openacademy.openacademy'
-+
-+# name = fields.Char()
-Index: addons/openacademy/security/ir.model.access.csv
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ addons/openacademy/security/ir.model.access.csv 2014-08-26 17:25:49.791783523 +0200
-@@ -0,0 +1,2 @@
-+id,name,model_id/id,group_id/id,perm_read,perm_write,perm_create,perm_unlink
-+access_openacademy_openacademy,openacademy.openacademy,model_openacademy_openacademy,,1,0,0,0
-Index: addons/openacademy/templates.xml
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ addons/openacademy/templates.xml 2014-08-26 17:25:49.791783523 +0200
-@@ -0,0 +1,22 @@
-+<odoo>
-+
-+ <!-- <template id="listing"> -->
-+ <!-- <ul> -->
-+ <!-- <li t-foreach="objects" t-as="object"> -->
-+ <!-- <a t-attf-href="{{ root }}/objects/{{ object.id }}"> -->
-+ <!-- <t t-esc="object.display_name"/> -->
-+ <!-- </a> -->
-+ <!-- </li> -->
-+ <!-- </ul> -->
-+ <!-- </template> -->
-+ <!-- <template id="object"> -->
-+ <!-- <h1><t t-esc="object.display_name"/></h1> -->
-+ <!-- <dl> -->
-+ <!-- <t t-foreach="object._fields" t-as="field"> -->
-+ <!-- <dt><t t-esc="field"/></dt> -->
-+ <!-- <dd><t t-esc="object[field]"/></dd> -->
-+ <!-- </t> -->
-+ <!-- </dl> -->
-+ <!-- </template> -->
-+
-+</odoo>
diff --git a/doc/howtos/backend/exercise-dashboard b/doc/howtos/backend/exercise-dashboard
deleted file mode 100644
index 9e5eb41b779..00000000000
--- a/doc/howtos/backend/exercise-dashboard
+++ /dev/null
@@ -1,91 +0,0 @@
-# HG changeset patch
-# Parent 643813940cbea07bec792f9e1c60022a9292fa90
-
-Index: addons/openacademy/__manifest__.py
-===================================================================
---- addons.orig/openacademy/__manifest__.py 2014-08-26 17:26:21.535783052 +0200
-+++ addons/openacademy/__manifest__.py 2014-08-26 17:26:21.531783052 +0200
-@@ -21,7 +21,7 @@
- 'version': '0.1',
-
- # any module necessary for this one to work correctly
-- 'depends': ['base'],
-+ 'depends': ['base', 'board'],
-
- # always loaded
- 'data': [
-@@ -30,6 +30,7 @@
- 'templates.xml',
- 'views/openacademy.xml',
- 'views/partner.xml',
-+ 'views/session_board.xml',
- 'reports.xml',
- ],
- # only loaded in demonstration mode
-Index: addons/openacademy/views/session_board.xml
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ addons/openacademy/views/session_board.xml 2014-08-26 17:26:21.531783052 +0200
-@@ -0,0 +1,62 @@
-+<?xml version="1.0"?>
-+<odoo>
-+
-+ <record model="ir.actions.act_window" id="act_session_graph">
-+ <field name="name">Attendees by course</field>
-+ <field name="res_model">openacademy.session</field>
-+ <field name="view_mode">graph</field>
-+ <field name="view_id"
-+ ref="openacademy.openacademy_session_graph_view"/>
-+ </record>
-+ <record model="ir.actions.act_window" id="act_session_calendar">
-+ <field name="name">Sessions</field>
-+ <field name="res_model">openacademy.session</field>
-+ <field name="view_mode">calendar</field>
-+ <field name="view_id" ref="openacademy.session_calendar_view"/>
-+ </record>
-+ <record model="ir.actions.act_window" id="act_course_list">
-+ <field name="name">Courses</field>
-+ <field name="res_model">openacademy.course</field>
-+ <field name="view_mode">tree,form</field>
-+ </record>
-+ <record model="ir.ui.view" id="board_session_form">
-+ <field name="name">Session Dashboard Form</field>
-+ <field name="model">board.board</field>
-+ <field name="type">form</field>
-+ <field name="arch" type="xml">
-+ <form string="Session Dashboard">
-+ <board style="2-1">
-+ <column>
-+ <action
-+ string="Attendees by course"
-+ name="%(act_session_graph)d"
-+ height="150"
-+ width="510"/>
-+ <action
-+ string="Sessions"
-+ name="%(act_session_calendar)d"/>
-+ </column>
-+ <column>
-+ <action
-+ string="Courses"
-+ name="%(act_course_list)d"/>
-+ </column>
-+ </board>
-+ </form>
-+ </field>
-+ </record>
-+ <record model="ir.actions.act_window" id="open_board_session">
-+ <field name="name">Session Dashboard</field>
-+ <field name="res_model">board.board</field>
-+ <field name="view_mode">form</field>
-+ <field name="usage">menu</field>
-+ <field name="view_id" ref="board_session_form"/>
-+ </record>
-+
-+ <menuitem
-+ name="Session Dashboard" parent="base.menu_reporting_dashboard"
-+ action="open_board_session"
-+ sequence="1"
-+ id="menu_board_session"/>
-+
-+</odoo>
diff --git a/doc/howtos/backend/exercise-defaults b/doc/howtos/backend/exercise-defaults
deleted file mode 100644
index 6365f44171a..00000000000
--- a/doc/howtos/backend/exercise-defaults
+++ /dev/null
@@ -1,28 +0,0 @@
-Index: addons/openacademy/models.py
-===================================================================
---- addons.orig/openacademy/models.py
-+++ addons/openacademy/models.py
-@@ -20,9 +20,10 @@
- _description = "OpenAcademy Sessions"
-
- name = fields.Char(required=True)
-- start_date = fields.Date()
-+ start_date = fields.Date(default=fields.Date.today)
- duration = fields.Float(digits=(6, 2), help="Duration in days")
- seats = fields.Integer(string="Number of seats")
-+ active = fields.Boolean(default=True)
-
- instructor_id = fields.Many2one('res.partner', string="Instructor",
- domain=['|', ('instructor', '=', True),
-Index: addons/openacademy/views/openacademy.xml
-===================================================================
---- addons.orig/openacademy/views/openacademy.xml
-+++ addons/openacademy/views/openacademy.xml
-@@ -94,6 +94,7 @@
- <field name="course_id"/>
- <field name="name"/>
- <field name="instructor_id"/>
-+ <field name="active"/>
- </group>
- <group string="Schedule">
- <field name="start_date"/>
diff --git a/doc/howtos/backend/exercise-demo b/doc/howtos/backend/exercise-demo
deleted file mode 100644
index 50a9564424a..00000000000
--- a/doc/howtos/backend/exercise-demo
+++ /dev/null
@@ -1,48 +0,0 @@
-# HG changeset patch
-# Parent 84e2b0b43fc61fd0bcbb44c1929755d44ee58ae5
-
-Index: addons/openacademy/demo.xml
-===================================================================
---- addons.orig/openacademy/demo.xml 2014-08-26 17:25:52.683783480 +0200
-+++ addons/openacademy/demo.xml 2014-08-26 17:25:52.679783480 +0200
-@@ -1,25 +1,19 @@
- <odoo>
-
-- <!-- -->
-- <!-- <record id="object0" model="openacademy.openacademy"> -->
-- <!-- <field name="name">Object 0</field> -->
-- <!-- </record> -->
-- <!-- -->
-- <!-- <record id="object1" model="openacademy.openacademy"> -->
-- <!-- <field name="name">Object 1</field> -->
-- <!-- </record> -->
-- <!-- -->
-- <!-- <record id="object2" model="openacademy.openacademy"> -->
-- <!-- <field name="name">Object 2</field> -->
-- <!-- </record> -->
-- <!-- -->
-- <!-- <record id="object3" model="openacademy.openacademy"> -->
-- <!-- <field name="name">Object 3</field> -->
-- <!-- </record> -->
-- <!-- -->
-- <!-- <record id="object4" model="openacademy.openacademy"> -->
-- <!-- <field name="name">Object 4</field> -->
-- <!-- </record> -->
-- <!-- -->
-+ <record model="openacademy.course" id="course0">
-+ <field name="name">Course 0</field>
-+ <field name="description">Course 0's description
-+
-+Can have multiple lines
-+ </field>
-+ </record>
-+ <record model="openacademy.course" id="course1">
-+ <field name="name">Course 1</field>
-+ <!-- no description for this one -->
-+ </record>
-+ <record model="openacademy.course" id="course2">
-+ <field name="name">Course 2</field>
-+ <field name="description">Course 2's description</field>
-+ </record>
-
- </odoo>
diff --git a/doc/howtos/backend/exercise-domain-advanced b/doc/howtos/backend/exercise-domain-advanced
deleted file mode 100644
index 9b96a44599f..00000000000
--- a/doc/howtos/backend/exercise-domain-advanced
+++ /dev/null
@@ -1,42 +0,0 @@
-# HG changeset patch
-# Parent 69d1f2d359eb8ef304a9d99f17790c78b35eda1a
-
-Index: addons/openacademy/models.py
-===================================================================
---- addons.orig/openacademy/models.py
-+++ addons/openacademy/models.py
-@@ -25,7 +25,8 @@
- seats = fields.Integer(string="Number of seats")
-
- instructor_id = fields.Many2one('res.partner', string="Instructor",
-- domain=[('instructor', '=', True)])
-+ domain=['|', ('instructor', '=', True),
-+ ('category_id.name', 'ilike', "Teacher")])
- course_id = fields.Many2one('openacademy.course',
- ondelete='cascade', string="Course", required=True)
- attendee_ids = fields.Many2many('res.partner', string="Attendees")
-Index: addons/openacademy/views/partner.xml
-===================================================================
---- addons.orig/openacademy/views/partner.xml
-+++ addons/openacademy/views/partner.xml
-@@ -29,4 +29,20 @@
- parent="configuration_menu"
- action="contact_list_action"/>
-
-+ <record model="ir.actions.act_window" id="contact_cat_list_action">
-+ <field name="name">Contact Tags</field>
-+ <field name="res_model">res.partner.category</field>
-+ <field name="view_mode">tree,form</field>
-+ </record>
-+ <menuitem id="contact_cat_menu" name="Contact Tags"
-+ parent="configuration_menu"
-+ action="contact_cat_list_action"/>
-+
-+ <record model="res.partner.category" id="teacher1">
-+ <field name="name">Teacher / Level 1</field>
-+ </record>
-+ <record model="res.partner.category" id="teacher2">
-+ <field name="name">Teacher / Level 2</field>
-+ </record>
-+
- </odoo>
diff --git a/doc/howtos/backend/exercise-domain-basic b/doc/howtos/backend/exercise-domain-basic
deleted file mode 100644
index 71ee608cfbc..00000000000
--- a/doc/howtos/backend/exercise-domain-basic
+++ /dev/null
@@ -1,17 +0,0 @@
-# HG changeset patch
-# Parent 142c5065ff1b7266d944d4ef5239e814ae22f0df
-
-Index: addons/openacademy/models.py
-===================================================================
---- addons.orig/openacademy/models.py
-+++ addons/openacademy/models.py
-@@ -24,7 +24,8 @@
- duration = fields.Float(digits=(6, 2), help="Duration in days")
- seats = fields.Integer(string="Number of seats")
-
-- instructor_id = fields.Many2one('res.partner', string="Instructor")
-+ instructor_id = fields.Many2one('res.partner', string="Instructor",
-+ domain=[('instructor', '=', True)])
- course_id = fields.Many2one('openacademy.course',
- ondelete='cascade', string="Course", required=True)
- attendee_ids = fields.Many2many('res.partner', string="Attendees")
diff --git a/doc/howtos/backend/exercise-formview b/doc/howtos/backend/exercise-formview
deleted file mode 100644
index 9f80bc2f768..00000000000
--- a/doc/howtos/backend/exercise-formview
+++ /dev/null
@@ -1,29 +0,0 @@
-# HG changeset patch
-# Parent 4a0db1d29257764f4df5cb1ee0be7e59e8c8d0d8
-
-Index: addons/openacademy/views/openacademy.xml
-===================================================================
---- addons.orig/openacademy/views/openacademy.xml 2014-08-26 17:25:54.291783456 +0200
-+++ addons/openacademy/views/openacademy.xml 2014-08-26 17:25:54.283783457 +0200
-@@ -1,6 +1,21 @@
- <?xml version="1.0" encoding="UTF-8"?>
- <odoo>
-
-+ <record model="ir.ui.view" id="course_form_view">
-+ <field name="name">course.form</field>
-+ <field name="model">openacademy.course</field>
-+ <field name="arch" type="xml">
-+ <form string="Course Form">
-+ <sheet>
-+ <group>
-+ <field name="name"/>
-+ <field name="description"/>
-+ </group>
-+ </sheet>
-+ </form>
-+ </field>
-+ </record>
-+
- <!-- window action -->
- <!--
- The following tag is an action definition for a "window action",
diff --git a/doc/howtos/backend/exercise-formview-notebooks b/doc/howtos/backend/exercise-formview-notebooks
deleted file mode 100644
index d0ef27f5fce..00000000000
--- a/doc/howtos/backend/exercise-formview-notebooks
+++ /dev/null
@@ -1,24 +0,0 @@
-# HG changeset patch
-# Parent 5508a5440faa7b607d057c4e4ae70af6b6f7cac9
-
-Index: addons/openacademy/views/openacademy.xml
-===================================================================
---- addons.orig/openacademy/views/openacademy.xml 2014-08-26 17:25:55.023783446 +0200
-+++ addons/openacademy/views/openacademy.xml 2014-08-26 17:25:55.015783446 +0200
-@@ -9,8 +9,15 @@
- <sheet>
- <group>
- <field name="name"/>
-- <field name="description"/>
- </group>
-+ <notebook>
-+ <page string="Description">
-+ <field name="description"/>
-+ </page>
-+ <page string="About">
-+ This is an example of notebooks
-+ </page>
-+ </notebook>
- </sheet>
- </form>
- </field>
diff --git a/doc/howtos/backend/exercise-gantt b/doc/howtos/backend/exercise-gantt
deleted file mode 100644
index e1e68cbb9cd..00000000000
--- a/doc/howtos/backend/exercise-gantt
+++ /dev/null
@@ -1,30 +0,0 @@
-# HG changeset patch
-# Parent dba00a105dd2a82490394b8dec5fea5f1d8847e1
-# Parent f4374b6e2e661e0782e396b24c57c1eb97d13288
-
-diff --git a/openacademy/views/openacademy.xml b/openacademy/views/openacademy.xml
---- a/openacademy/views/openacademy.xml
-+++ b/openacademy/views/openacademy.xml
-@@ -142,10 +142,21 @@
- </field>
- </record>
-
-+ <record model="ir.ui.view" id="session_gantt_view">
-+ <field name="name">session.gantt</field>
-+ <field name="model">openacademy.session</field>
-+ <field name="arch" type="xml">
-+ <gantt string="Session Gantt"
-+ date_start="start_date" date_stop="end_date"
-+ default_group_by='instructor_id'>
-+ </gantt>
-+ </field>
-+ </record>
-+
- <record model="ir.actions.act_window" id="session_list_action">
- <field name="name">Sessions</field>
- <field name="res_model">openacademy.session</field>
-- <field name="view_mode">tree,form,calendar</field>
-+ <field name="view_mode">tree,form,calendar,gantt</field>
- </record>
-
- <menuitem id="session_menu" name="Sessions"
diff --git a/doc/howtos/backend/exercise-graph b/doc/howtos/backend/exercise-graph
deleted file mode 100644
index 3696bd288f7..00000000000
--- a/doc/howtos/backend/exercise-graph
+++ /dev/null
@@ -1,55 +0,0 @@
-# HG changeset patch
-# Parent a6fe4d3923db1f8f5dff2c39a711a814b0a0f549
-# Parent 0687e07f570f363bf5005c6337e0c565a63a6bac
-
-diff --git a/openacademy/models.py b/openacademy/models.py
---- a/openacademy/models.py
-+++ b/openacademy/models.py
-@@ -60,6 +60,9 @@ class Session(models.Model):
- end_date = fields.Date(string="End Date", store=True,
- compute='_get_end_date', inverse='_set_end_date')
-
-+ attendees_count = fields.Integer(
-+ string="Attendees count", compute='_get_attendees_count', store=True)
-+
- @api.depends('seats', 'attendee_ids')
- def _taken_seats(self):
- for r in self:
-@@ -106,6 +109,11 @@ class Session(models.Model):
- # so add one day to get 5 days instead
- r.duration = (r.end_date - r.start_date).days + 1
-
-+ @api.depends('attendee_ids')
-+ def _get_attendees_count(self):
-+ for r in self:
-+ r.attendees_count = len(r.attendee_ids)
-+
- @api.constrains('instructor_id', 'attendee_ids')
- def _check_instructor_not_in_attendees(self):
- for r in self:
-diff --git a/openacademy/views/openacademy.xml b/openacademy/views/openacademy.xml
---- a/openacademy/views/openacademy.xml
-+++ b/openacademy/views/openacademy.xml
-@@ -153,10 +153,21 @@
- </field>
- </record>
-
-+ <record model="ir.ui.view" id="openacademy_session_graph_view">
-+ <field name="name">openacademy.session.graph</field>
-+ <field name="model">openacademy.session</field>
-+ <field name="arch" type="xml">
-+ <graph string="Participations by Courses">
-+ <field name="course_id"/>
-+ <field name="attendees_count" type="measure"/>
-+ </graph>
-+ </field>
-+ </record>
-+
- <record model="ir.actions.act_window" id="session_list_action">
- <field name="name">Sessions</field>
- <field name="res_model">openacademy.session</field>
-- <field name="view_mode">tree,form,calendar,gantt</field>
-+ <field name="view_mode">tree,form,calendar,gantt,graph</field>
- </record>
-
- <menuitem id="session_menu" name="Sessions"
diff --git a/doc/howtos/backend/exercise-kanban b/doc/howtos/backend/exercise-kanban
deleted file mode 100644
index 42cbd8b096b..00000000000
--- a/doc/howtos/backend/exercise-kanban
+++ /dev/null
@@ -1,77 +0,0 @@
-# HG changeset patch
-# Parent 8d66f7620781558d4520f97e4cebc14ed180683e
-
-Index: addons/openacademy/models.py
-===================================================================
---- addons.orig/openacademy/models.py
-+++ addons/openacademy/models.py
-@@ -49,6 +49,7 @@
- duration = fields.Float(digits=(6, 2), help="Duration in days")
- seats = fields.Integer(string="Number of seats")
- active = fields.Boolean(default=True)
-+ color = fields.Integer()
-
- instructor_id = fields.Many2one('res.partner', string="Instructor",
- domain=['|', ('instructor', '=', True),
-Index: addons/openacademy/views/openacademy.xml
-===================================================================
---- addons.orig/openacademy/views/openacademy.xml
-+++ addons/openacademy/views/openacademy.xml
-@@ -165,10 +165,56 @@
- </field>
- </record>
-
-+ <record model="ir.ui.view" id="view_openacad_session_kanban">
-+ <field name="name">openacademy.session.kanban</field>
-+ <field name="model">openacademy.session</field>
-+ <field name="arch" type="xml">
-+ <kanban default_group_by="course_id">
-+ <field name="color"/>
-+ <templates>
-+ <t t-name="kanban-box">
-+ <div
-+ t-attf-class="oe_kanban_color_{{kanban_getcolor(record.color.raw_value)}}
-+ oe_kanban_global_click_edit oe_semantic_html_override
-+ oe_kanban_card {{record.group_fancy==1 ? 'oe_kanban_card_fancy' : ''}}">
-+ <div class="oe_dropdown_kanban">
-+ <!-- dropdown menu -->
-+ <div class="oe_dropdown_toggle">
-+ <i class="fa fa-bars fa-lg" title="Manage" aria-label="Manage"/>
-+ <ul class="oe_dropdown_menu">
-+ <li>
-+ <a type="delete">Delete</a>
-+ </li>
-+ <li>
-+ <ul class="oe_kanban_colorpicker"
-+ data-field="color"/>
-+ </li>
-+ </ul>
-+ </div>
-+ <div class="oe_clear"></div>
-+ </div>
-+ <div t-attf-class="oe_kanban_content">
-+ <!-- title -->
-+ Session name:
-+ <field name="name"/>
-+ <br/>
-+ Start date:
-+ <field name="start_date"/>
-+ <br/>
-+ duration:
-+ <field name="duration"/>
-+ </div>
-+ </div>
-+ </t>
-+ </templates>
-+ </kanban>
-+ </field>
-+ </record>
-+
- <record model="ir.actions.act_window" id="session_list_action">
- <field name="name">Sessions</field>
- <field name="res_model">openacademy.session</field>
-- <field name="view_mode">tree,form,calendar,gantt,graph</field>
-+ <field name="view_mode">tree,form,calendar,gantt,graph,kanban</field>
- </record>
-
- <menuitem id="session_menu" name="Sessions"
diff --git a/doc/howtos/backend/exercise-many2many b/doc/howtos/backend/exercise-many2many
deleted file mode 100644
index 315bd21fa33..00000000000
--- a/doc/howtos/backend/exercise-many2many
+++ /dev/null
@@ -1,22 +0,0 @@
-Index: addons/openacademy/models.py
-===================================================================
---- addons.orig/openacademy/models.py
-+++ addons/openacademy/models.py
-@@ -27,3 +27,4 @@
- instructor_id = fields.Many2one('res.partner', string="Instructor")
- course_id = fields.Many2one('openacademy.course',
- ondelete='cascade', string="Course", required=True)
-+ attendee_ids = fields.Many2many('res.partner', string="Attendees")
-Index: addons/openacademy/views/openacademy.xml
-===================================================================
---- addons.orig/openacademy/views/openacademy.xml
-+++ addons/openacademy/views/openacademy.xml
-@@ -101,6 +101,8 @@
- <field name="seats"/>
- </group>
- </group>
-+ <label for="attendee_ids"/>
-+ <field name="attendee_ids"/>
- </sheet>
- </form>
- </field>
diff --git a/doc/howtos/backend/exercise-many2one b/doc/howtos/backend/exercise-many2one
deleted file mode 100644
index fe71441eb4d..00000000000
--- a/doc/howtos/backend/exercise-many2one
+++ /dev/null
@@ -1,95 +0,0 @@
-# HG changeset patch
-# Parent a6e217b1fbbc64111581c269629b1c25c23abb99
-
-Index: addons/openacademy/models.py
-===================================================================
---- addons.orig/openacademy/models.py
-+++ addons/openacademy/models.py
-@@ -9,6 +9,9 @@
- name = fields.Char(string="Title", required=True)
- description = fields.Text()
-
-+ responsible_id = fields.Many2one('res.users',
-+ ondelete='set null', string="Responsible", index=True)
-+
-
- class Session(models.Model):
- _name = 'openacademy.session'
-@@ -18,3 +21,7 @@
- start_date = fields.Date()
- duration = fields.Float(digits=(6, 2), help="Duration in days")
- seats = fields.Integer(string="Number of seats")
-+
-+ instructor_id = fields.Many2one('res.partner', string="Instructor")
-+ course_id = fields.Many2one('openacademy.course',
-+ ondelete='cascade', string="Course", required=True)
-Index: addons/openacademy/views/openacademy.xml
-===================================================================
---- addons.orig/openacademy/views/openacademy.xml
-+++ addons/openacademy/views/openacademy.xml
-@@ -9,6 +9,7 @@
- <sheet>
- <group>
- <field name="name"/>
-+ <field name="responsible_id"/>
- </group>
- <notebook>
- <page string="Description">
-@@ -34,6 +35,18 @@
- </field>
- </record>
-
-+ <!-- override the automatically generated list view for courses -->
-+ <record model="ir.ui.view" id="course_tree_view">
-+ <field name="name">course.tree</field>
-+ <field name="model">openacademy.course</field>
-+ <field name="arch" type="xml">
-+ <tree string="Course Tree">
-+ <field name="name"/>
-+ <field name="responsible_id"/>
-+ </tree>
-+ </field>
-+ </record>
-+
- <!-- window action -->
- <!--
- The following tag is an action definition for a "window action",
-@@ -72,16 +85,34 @@
- <form string="Session Form">
- <sheet>
- <group>
-- <field name="name"/>
-- <field name="start_date"/>
-- <field name="duration"/>
-- <field name="seats"/>
-+ <group string="General">
-+ <field name="course_id"/>
-+ <field name="name"/>
-+ <field name="instructor_id"/>
-+ </group>
-+ <group string="Schedule">
-+ <field name="start_date"/>
-+ <field name="duration"/>
-+ <field name="seats"/>
-+ </group>
- </group>
- </sheet>
- </form>
- </field>
- </record>
-
-+ <!-- session tree/list view -->
-+ <record model="ir.ui.view" id="session_tree_view">
-+ <field name="name">session.tree</field>
-+ <field name="model">openacademy.session</field>
-+ <field name="arch" type="xml">
-+ <tree string="Session Tree">
-+ <field name="name"/>
-+ <field name="course_id"/>
-+ </tree>
-+ </field>
-+ </record>
-+
- <record model="ir.actions.act_window" id="session_list_action">
- <field name="name">Sessions</field>
- <field name="res_model">openacademy.session</field>
diff --git a/doc/howtos/backend/exercise-model b/doc/howtos/backend/exercise-model
deleted file mode 100644
index 6180794d100..00000000000
--- a/doc/howtos/backend/exercise-model
+++ /dev/null
@@ -1,19 +0,0 @@
-# HG changeset patch
-# Parent e3bb12713a6d38c28f50d46e8c1bab74ac40c1be
-Index: addons/openacademy/models.py
-===================================================================
---- addons.orig/openacademy/models.py
-+++ addons/openacademy/models.py
-@@ -2,7 +2,9 @@
-
- from odoo import models, fields, api
-
--# class openacademy(models.Model):
--# _name = 'openacademy.openacademy'
-+class Course(models.Model):
-+ _name = 'openacademy.course'
-+ _description = "OpenAcademy Courses"
-
--# name = fields.Char()
-+ name = fields.Char(string="Title", required=True)
-+ description = fields.Text()
diff --git a/doc/howtos/backend/exercise-model-inheritance b/doc/howtos/backend/exercise-model-inheritance
deleted file mode 100644
index 073d706c89a..00000000000
--- a/doc/howtos/backend/exercise-model-inheritance
+++ /dev/null
@@ -1,78 +0,0 @@
-# HG changeset patch
-# Parent d903c828fb10f2b38e5f43e9ceaeae0a9db7f858
-
-Index: addons/openacademy/__init__.py
-===================================================================
---- addons.orig/openacademy/__init__.py 2014-08-26 17:26:01.227783353 +0200
-+++ addons/openacademy/__init__.py 2014-08-26 17:26:01.219783354 +0200
-@@ -1,3 +1,4 @@
- # -*- coding: utf-8 -*-
- from . import controllers
- from . import models
-+from . import partner
-Index: addons/openacademy/__manifest__.py
-===================================================================
---- addons.orig/openacademy/__manifest__.py 2014-08-26 17:26:01.227783353 +0200
-+++ addons/openacademy/__manifest__.py 2014-08-26 17:26:01.223783354 +0200
-@@ -28,6 +28,7 @@
- # 'security/ir.model.access.csv',
- 'templates.xml',
- 'views/openacademy.xml',
-+ 'views/partner.xml',
- ],
- # only loaded in demonstration mode
- 'demo': [
-Index: addons/openacademy/partner.py
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ addons/openacademy/partner.py 2014-08-26 17:26:01.223783354 +0200
-@@ -0,0 +1,12 @@
-+# -*- coding: utf-8 -*-
-+from odoo import fields, models
-+
-+class Partner(models.Model):
-+ _inherit = 'res.partner'
-+
-+ # Add a new column to the res.partner model, by default partners are not
-+ # instructors
-+ instructor = fields.Boolean("Instructor", default=False)
-+
-+ session_ids = fields.Many2many('openacademy.session',
-+ string="Attended Sessions", readonly=True)
-Index: addons/openacademy/views/partner.xml
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ addons/openacademy/views/partner.xml 2014-08-26 17:26:01.223783354 +0200
-@@ -0,0 +1,32 @@
-+<?xml version="1.0" encoding="UTF-8"?>
-+ <odoo>
-+
-+ <!-- Add instructor field to existing view -->
-+ <record model="ir.ui.view" id="partner_instructor_form_view">
-+ <field name="name">partner.instructor</field>
-+ <field name="model">res.partner</field>
-+ <field name="inherit_id" ref="base.view_partner_form"/>
-+ <field name="arch" type="xml">
-+ <notebook position="inside">
-+ <page string="Sessions">
-+ <group>
-+ <field name="instructor"/>
-+ <field name="session_ids"/>
-+ </group>
-+ </page>
-+ </notebook>
-+ </field>
-+ </record>
-+
-+ <record model="ir.actions.act_window" id="contact_list_action">
-+ <field name="name">Contacts</field>
-+ <field name="res_model">res.partner</field>
-+ <field name="view_mode">tree,form</field>
-+ </record>
-+ <menuitem id="configuration_menu" name="Configuration"
-+ parent="main_openacademy_menu"/>
-+ <menuitem id="contact_menu" name="Contacts"
-+ parent="configuration_menu"
-+ action="contact_list_action"/>
-+
-+</odoo>
diff --git a/doc/howtos/backend/exercise-onchange b/doc/howtos/backend/exercise-onchange
deleted file mode 100644
index 355e5ad700c..00000000000
--- a/doc/howtos/backend/exercise-onchange
+++ /dev/null
@@ -1,28 +0,0 @@
-# HG changeset patch
-# Parent 8d5573b704b2867788dd6895503f1871c2976a29
-# Parent 9eb163e5da677a0d09e01a354ba56697b576a4bc
-
-diff --git a/openacademy/models.py b/openacademy/models.py
---- a/openacademy/models.py
-+++ b/openacademy/models.py
-@@ -41,3 +41,20 @@ class Session(models.Model):
- r.taken_seats = 0.0
- else:
- r.taken_seats = 100.0 * len(r.attendee_ids) / r.seats
-+
-+ @api.onchange('seats', 'attendee_ids')
-+ def _verify_valid_seats(self):
-+ if self.seats < 0:
-+ return {
-+ 'warning': {
-+ 'title': "Incorrect 'seats' value",
-+ 'message': "The number of available seats may not be negative",
-+ },
-+ }
-+ if self.seats < len(self.attendee_ids):
-+ return {
-+ 'warning': {
-+ 'title': "Too many attendees",
-+ 'message': "Increase seats or remove excess attendees",
-+ },
-+ }
diff --git a/doc/howtos/backend/exercise-one2many b/doc/howtos/backend/exercise-one2many
deleted file mode 100644
index 67ded32da8a..00000000000
--- a/doc/howtos/backend/exercise-one2many
+++ /dev/null
@@ -1,36 +0,0 @@
-# HG changeset patch
-# Parent cb05882d4fe73e97b9d34a69190ced14d1a50c24
-
-Index: addons/openacademy/models.py
-===================================================================
---- addons.orig/openacademy/models.py
-+++ addons/openacademy/models.py
-@@ -11,6 +11,8 @@
-
- responsible_id = fields.Many2one('res.users',
- ondelete='set null', string="Responsible", index=True)
-+ session_ids = fields.One2many(
-+ 'openacademy.session', 'course_id', string="Sessions")
-
-
- class Session(models.Model):
-Index: addons/openacademy/views/openacademy.xml
-===================================================================
---- addons.orig/openacademy/views/openacademy.xml
-+++ addons/openacademy/views/openacademy.xml
-@@ -15,8 +15,13 @@
- <page string="Description">
- <field name="description"/>
- </page>
-- <page string="About">
-- This is an example of notebooks
-+ <page string="Sessions">
-+ <field name="session_ids">
-+ <tree string="Registered sessions">
-+ <field name="name"/>
-+ <field name="instructor_id"/>
-+ </tree>
-+ </field>
- </page>
- </notebook>
- </sheet>
diff --git a/doc/howtos/backend/exercise-report b/doc/howtos/backend/exercise-report
deleted file mode 100644
index 9cf3e990f91..00000000000
--- a/doc/howtos/backend/exercise-report
+++ /dev/null
@@ -1,52 +0,0 @@
-# HG changeset patch
-# Parent c140f0a861a08881d8737bca0ffb83904a2059a3
-
-Index: addons/openacademy/__manifest__.py
-===================================================================
---- addons.orig/openacademy/__manifest__.py 2014-08-29 08:39:43.975536806 +0200
-+++ addons/openacademy/__manifest__.py 2014-08-29 08:39:52.000000000 +0200
-@@ -30,6 +30,7 @@
- 'templates.xml',
- 'views/openacademy.xml',
- 'views/partner.xml',
-+ 'reports.xml',
- ],
- # only loaded in demonstration mode
- 'demo': [
-Index: foo/openacademy/reports.xml
-===================================================================
---- /dev/null
-+++ foo/openacademy/reports.xml
-@@ -0,0 +1,32 @@
-+<odoo>
-+
-+ <record id="report_session" model="ir.actions.report">
-+ <field name="name">Session Report</field>
-+ <field name="model">openacademy.session</field>
-+ <field name="report_type">qweb-pdf</field>
-+ <field name="report_name">openacademy.report_session_view</field>
-+ <field name="report_file">openacademy.report_session</field>
-+ <field name="binding_model_id" ref="model_openacademy_session"/>
-+ <field name="binding_type">report</field>
-+ </record>
-+
-+ <template id="report_session_view">
-+ <t t-call="web.html_container">
-+ <t t-foreach="docs" t-as="doc">
-+ <t t-call="web.external_layout">
-+ <div class="page">
-+ <h2 t-field="doc.name"/>
-+ <p>From <span t-field="doc.start_date"/> to <span t-field="doc.end_date"/></p>
-+ <h3>Attendees:</h3>
-+ <ul>
-+ <t t-foreach="doc.attendee_ids" t-as="attendee">
-+ <li><span t-field="attendee.name"/></li>
-+ </t>
-+ </ul>
-+ </div>
-+ </t>
-+ </t>
-+ </t>
-+ </template>
-+
-+</odoo>
diff --git a/doc/howtos/backend/exercise-searchview b/doc/howtos/backend/exercise-searchview
deleted file mode 100644
index 1f7ef805cb9..00000000000
--- a/doc/howtos/backend/exercise-searchview
+++ /dev/null
@@ -1,28 +0,0 @@
-# HG changeset patch
-# Parent 93a45ab8dd0a76c131cb5eeca6e44b71dca9f100
-
-Index: addons/openacademy/views/openacademy.xml
-===================================================================
---- addons.orig/openacademy/views/openacademy.xml 2014-08-28 14:01:45.299033618 +0200
-+++ addons/openacademy/views/openacademy.xml 2014-08-28 14:18:58.847018275 +0200
-@@ -36,6 +36,12 @@
- <search>
- <field name="name"/>
- <field name="description"/>
-+ <filter name="my_courses" string="My Courses"
-+ domain="[('responsible_id', '=', uid)]"/>
-+ <group string="Group By">
-+ <filter name="by_responsible" string="Responsible"
-+ context="{'group_by': 'responsible_id'}"/>
-+ </group>
- </search>
- </field>
- </record>
-@@ -61,6 +67,7 @@
- <field name="name">Courses</field>
- <field name="res_model">openacademy.course</field>
- <field name="view_mode">tree,form</field>
-+ <field name="context" eval="{'search_default_my_courses': 1}"/>
- <field name="help" type="html">
- <p class="o_view_nocontent_smiling_face">Create the first course
- </p>
diff --git a/doc/howtos/backend/exercise-searchview-basic b/doc/howtos/backend/exercise-searchview-basic
deleted file mode 100644
index a04813351d2..00000000000
--- a/doc/howtos/backend/exercise-searchview-basic
+++ /dev/null
@@ -1,24 +0,0 @@
-# HG changeset patch
-# Parent b9bfc8929e0ffc3eb153641e14952fe5d99eb908
-Index: addons/openacademy/views/openacademy.xml
-===================================================================
---- addons.orig/openacademy/views/openacademy.xml 2014-08-26 17:25:55.807783434 +0200
-+++ addons/openacademy/views/openacademy.xml 2014-08-26 17:25:55.799783434 +0200
-@@ -23,6 +23,17 @@
- </field>
- </record>
-
-+ <record model="ir.ui.view" id="course_search_view">
-+ <field name="name">course.search</field>
-+ <field name="model">openacademy.course</field>
-+ <field name="arch" type="xml">
-+ <search>
-+ <field name="name"/>
-+ <field name="description"/>
-+ </search>
-+ </field>
-+ </record>
-+
- <!-- window action -->
- <!--
- The following tag is an action definition for a "window action",
diff --git a/doc/howtos/backend/exercise-session b/doc/howtos/backend/exercise-session
deleted file mode 100644
index cde89478160..00000000000
--- a/doc/howtos/backend/exercise-session
+++ /dev/null
@@ -1,57 +0,0 @@
-# HG changeset patch
-# Parent 22f8d180a7f9ad209d7e98cf7d1bd0fee1f05350
-Index: addons/openacademy/models.py
-===================================================================
---- addons.orig/openacademy/models.py
-+++ addons/openacademy/models.py
-@@ -8,3 +8,13 @@
-
- name = fields.Char(string="Title", required=True)
- description = fields.Text()
-+
-+
-+class Session(models.Model):
-+ _name = 'openacademy.session'
-+ _description = "OpenAcademy Sessions"
-+
-+ name = fields.Char(required=True)
-+ start_date = fields.Date()
-+ duration = fields.Float(digits=(6, 2), help="Duration in days")
-+ seats = fields.Integer(string="Number of seats")
-Index: addons/openacademy/views/openacademy.xml
-===================================================================
---- addons.orig/openacademy/views/openacademy.xml
-+++ addons/openacademy/views/openacademy.xml
-@@ -64,4 +64,32 @@
- action="openacademy.course_list_action"
- It is not required when it is the same module -->
-
-+ <!-- session form view -->
-+ <record model="ir.ui.view" id="session_form_view">
-+ <field name="name">session.form</field>
-+ <field name="model">openacademy.session</field>
-+ <field name="arch" type="xml">
-+ <form string="Session Form">
-+ <sheet>
-+ <group>
-+ <field name="name"/>
-+ <field name="start_date"/>
-+ <field name="duration"/>
-+ <field name="seats"/>
-+ </group>
-+ </sheet>
-+ </form>
-+ </field>
-+ </record>
-+
-+ <record model="ir.actions.act_window" id="session_list_action">
-+ <field name="name">Sessions</field>
-+ <field name="res_model">openacademy.session</field>
-+ <field name="view_mode">tree,form</field>
-+ </record>
-+
-+ <menuitem id="session_menu" name="Sessions"
-+ parent="openacademy_menu"
-+ action="session_list_action"/>
-+
- </odoo>
diff --git a/doc/howtos/backend/exercise-translations b/doc/howtos/backend/exercise-translations
deleted file mode 100644
index 02b656efe76..00000000000
--- a/doc/howtos/backend/exercise-translations
+++ /dev/null
@@ -1,56 +0,0 @@
-# HG changeset patch
-# Parent 7c95aad3b60e4c2006c5f706bd157e8e05318bfa
-
-diff --git a/openacademy/models.py b/openacademy/models.py
---- a/openacademy/models.py
-+++ b/openacademy/models.py
-@@ -1,7 +1,7 @@
- # -*- coding: utf-8 -*-
-
- from datetime import timedelta
--from odoo import models, fields, api, exceptions
-+from odoo import models, fields, api, exceptions, _
-
- class Course(models.Model):
- _name = 'openacademy.course'
-@@ -20,11 +20,11 @@ class Course(models.Model):
- default = dict(default or {})
-
- copied_count = self.search_count(
-- [('name', '=like', u"Copy of {}%".format(self.name))])
-+ [('name', '=like', _(u"Copy of {}%").format(self.name))])
- if not copied_count:
-- new_name = u"Copy of {}".format(self.name)
-+ new_name = _(u"Copy of {}").format(self.name)
- else:
-- new_name = u"Copy of {} ({})".format(self.name, copied_count)
-+ new_name = _(u"Copy of {} ({})").format(self.name, copied_count)
-
- default['name'] = new_name
- return super(Course, self).copy(default)
-@@ -81,15 +81,15 @@ class Session(models.Model):
- if self.seats < 0:
- return {
- 'warning': {
-- 'title': "Incorrect 'seats' value",
-- 'message': "The number of available seats may not be negative",
-+ 'title': _("Incorrect 'seats' value"),
-+ 'message': _("The number of available seats may not be negative"),
- },
- }
- if self.seats < len(self.attendee_ids):
- return {
- 'warning': {
-- 'title': "Too many attendees",
-- 'message': "Increase seats or remove excess attendees",
-+ 'title': _("Too many attendees"),
-+ 'message': _("Increase seats or remove excess attendees"),
- },
- }
-
-@@ -114,4 +114,4 @@ class Session(models.Model):
- def _check_instructor_not_in_attendees(self):
- for r in self:
- if r.instructor_id and r.instructor_id in r.attendee_ids:
-- raise exceptions.ValidationError("A session's instructor can't be an attendee")
-+ raise exceptions.ValidationError(_("A session's instructor can't be an attendee"))
diff --git a/doc/howtos/backend/exercise-wizard b/doc/howtos/backend/exercise-wizard
deleted file mode 100644
index 9c44d71ca49..00000000000
--- a/doc/howtos/backend/exercise-wizard
+++ /dev/null
@@ -1,36 +0,0 @@
-Index: addons/openacademy/__init__.py
-===================================================================
---- addons.orig/openacademy/__init__.py
-+++ addons/openacademy/__init__.py
-@@ -2,3 +2,4 @@
- from . import controllers
- from . import models
- from . import partner
-+from . import wizard
-Index: addons/openacademy/wizard.py
-===================================================================
---- /dev/null
-+++ addons/openacademy/wizard.py
-@@ -0,0 +1,11 @@
-+# -*- coding: utf-8 -*-
-+
-+from odoo import models, fields, api
-+
-+class Wizard(models.TransientModel):
-+ _name = 'openacademy.wizard'
-+ _description = "Wizard: Quick Registration of Attendees to Sessions"
-+
-+ session_id = fields.Many2one('openacademy.session',
-+ string="Session", required=True)
-+ attendee_ids = fields.Many2many('res.partner', string="Attendees")
-Index: foo/openacademy/security/ir.model.access.csv
-===================================================================
---- foo.orig/openacademy/security/ir.model.access.csv
-+++ foo/openacademy/security/ir.model.access.csv
-@@ -1,5 +1,6 @@
- id,name,model_id/id,group_id/id,perm_read,perm_write,perm_create,perm_unlink
- course_manager,course manager,model_openacademy_course,group_manager,1,1,1,1
- session_manager,session manager,model_openacademy_session,group_manager,1,1,1,1
-+wizard_manager,wizard session manager,model_openacademy_wizard,group_manager,1,1,1,1
- course_read_all,course all,model_openacademy_course,,1,0,0,0
- session_read_all,session all,model_openacademy_session,,1,0,0,0
diff --git a/doc/howtos/backend/exercise-wizard-action b/doc/howtos/backend/exercise-wizard-action
deleted file mode 100644
index 305b5859bbb..00000000000
--- a/doc/howtos/backend/exercise-wizard-action
+++ /dev/null
@@ -1,29 +0,0 @@
-Index: addons/openacademy/views/openacademy.xml
-===================================================================
---- addons.orig/openacademy/views/openacademy.xml
-+++ addons/openacademy/views/openacademy.xml
-@@ -232,6 +232,12 @@
- <field name="session_id"/>
- <field name="attendee_ids"/>
- </group>
-+ <footer>
-+ <button name="subscribe" type="object"
-+ string="Subscribe" class="oe_highlight"/>
-+ or
-+ <button special="cancel" string="Cancel"/>
-+ </footer>
- </form>
- </field>
- </record>
-Index: addons/openacademy/wizard.py
-===================================================================
---- addons.orig/openacademy/wizard.py
-+++ addons/openacademy/wizard.py
-@@ -12,3 +12,7 @@
- session_id = fields.Many2one('openacademy.session',
- string="Session", required=True, default=_default_session)
- attendee_ids = fields.Many2many('res.partner', string="Attendees")
-+
-+ def subscribe(self):
-+ self.session_id.attendee_ids |= self.attendee_ids
-+ return {}
diff --git a/doc/howtos/backend/exercise-wizard-launch b/doc/howtos/backend/exercise-wizard-launch
deleted file mode 100644
index 65b7be8451d..00000000000
--- a/doc/howtos/backend/exercise-wizard-launch
+++ /dev/null
@@ -1,45 +0,0 @@
-Index: addons/openacademy/wizard.py
-===================================================================
---- addons.orig/openacademy/wizard.py
-+++ addons/openacademy/wizard.py
-@@ -6,6 +6,9 @@ class Wizard(models.TransientModel):
- _name = 'openacademy.wizard'
- _description = "Wizard: Quick Registration of Attendees to Sessions"
-
-+ def _default_session(self):
-+ return self.env['openacademy.session'].browse(self._context.get('active_id'))
-+
- session_id = fields.Many2one('openacademy.session',
-- string="Session", required=True)
-+ string="Session", required=True, default=_default_session)
- attendee_ids = fields.Many2many('res.partner', string="Attendees")
-Index: foo/openacademy/views/openacademy.xml
-===================================================================
---- foo.orig/openacademy/views/openacademy.xml
-+++ foo/openacademy/views/openacademy.xml
-@@ -220,4 +220,25 @@
- parent="openacademy_menu"
- action="session_list_action"/>
-
-+ <record model="ir.ui.view" id="wizard_form_view">
-+ <field name="name">wizard.form</field>
-+ <field name="model">openacademy.wizard</field>
-+ <field name="arch" type="xml">
-+ <form string="Add Attendees">
-+ <group>
-+ <field name="session_id"/>
-+ <field name="attendee_ids"/>
-+ </group>
-+ </form>
-+ </field>
-+ </record>
-+
-+ <record id="launch_session_wizard" model="ir.actions.act_window">
-+ <field name="name">Add Attendees</field>
-+ <field name="res_model">openacademy.wizard</field>
-+ <field name="view_mode">form</field>
-+ <field name="target">new</field>
-+ <field name="binding_model_id" ref="model_openacademy_session"/>
-+ </record>
-+
- </odoo>
diff --git a/doc/howtos/backend/exercise-wizard-multi b/doc/howtos/backend/exercise-wizard-multi
deleted file mode 100644
index 8e8805e52c0..00000000000
--- a/doc/howtos/backend/exercise-wizard-multi
+++ /dev/null
@@ -1,37 +0,0 @@
-Index: addons/openacademy/views/openacademy.xml
-===================================================================
---- addons.orig/openacademy/views/openacademy.xml
-+++ addons/openacademy/views/openacademy.xml
-@@ -229,7 +229,7 @@
- <field name="arch" type="xml">
- <form string="Add Attendees">
- <group>
-- <field name="session_id"/>
-+ <field name="session_ids"/>
- <field name="attendee_ids"/>
- </group>
- <footer>
-Index: addons/openacademy/wizard.py
-===================================================================
---- addons.orig/openacademy/wizard.py
-+++ addons/openacademy/wizard.py
-@@ -6,13 +6,14 @@ class Wizard(models.TransientModel):
- _name = 'openacademy.wizard'
- _description = "Wizard: Quick Registration of Attendees to Sessions"
-
-- def _default_session(self):
-- return self.env['openacademy.session'].browse(self._context.get('active_id'))
-+ def _default_sessions(self):
-+ return self.env['openacademy.session'].browse(self._context.get('active_ids'))
-
-- session_id = fields.Many2one('openacademy.session',
-- string="Session", required=True, default=_default_session)
-+ session_ids = fields.Many2many('openacademy.session',
-+ string="Sessions", required=True, default=_default_sessions)
- attendee_ids = fields.Many2many('res.partner', string="Attendees")
-
- def subscribe(self):
-- self.session_id.attendee_ids |= self.attendee_ids
-+ for session in self.session_ids:
-+ session.attendee_ids |= self.attendee_ids
- return {}
diff --git a/doc/howtos/backend/series b/doc/howtos/backend/series
deleted file mode 100644
index e48d05914e9..00000000000
--- a/doc/howtos/backend/series
+++ /dev/null
@@ -1,35 +0,0 @@
-exercise-creation
-exercise-model
-exercise-demo
-exercise-basic-action
-exercise-formview
-exercise-formview-notebooks
-exercise-searchview-basic
-exercise-session
-exercise-many2one
-exercise-one2many
-exercise-many2many
-exercise-model-inheritance
-exercise-domain-basic
-exercise-domain-advanced
-exercise-computed
-exercise-defaults
-exercise-onchange
-exercise-constraint-python
-exercise-constraint-sql
-exercise-copy-override
-exercise-advanced-treeview
-exercise-calendar
-exercise-searchview
-exercise-gantt
-exercise-graph
-exercise-kanban
-exercise-access-rights
-exercise-access-rules
-exercise-wizard
-exercise-wizard-launch
-exercise-wizard-action
-exercise-wizard-multi
-exercise-translations
-exercise-report
-exercise-dashboard
diff --git a/doc/howtos/company.rst b/doc/howtos/company.rst
deleted file mode 100644
index 559a0a79608..00000000000
--- a/doc/howtos/company.rst
+++ /dev/null
@@ -1,230 +0,0 @@
-:banner: banners/company.jpg
-
-.. _reference/howtos/company:
-
-========================
-Multi-company Guidelines
-========================
-
-.. warning::
-
- This tutorial requires good knowledge of Odoo.
- Please refer to the :ref:`basic tutorial <howto/base>` first if needed.
-
-As of version 13.0, a user can be logged in multiple companies at once. This allows the user to
-access information from multiple companies but also to create/edit records in a multi-company
-environment.
-
-If not handled correctly, it may be the source of a lot of inconsistent multi-company behaviors.
-For instance, a user logged in both companies A and B could create a sales order in company A and
-add products belonging to company B to it. It is only when the user will log out from company B that
-access errors will occur for the sales order.
-
-To correctly manage multi-company behaviors, Odoo's ORM provides multiple features:
-
-- :ref:`Company-dependent fields <howto/company/company_dependent>`
-- :ref:`Multi-company consistency <howto/company/check_company>`
-- :ref:`Default company <howto/company/default_company>`
-- :ref:`Views <howto/company/views>`
-- :ref:`Security rules <howto/company/security>`
-
-.. _howto/company/company_dependent:
-
-Company-dependent fields
-------------------------
-
-When a record is available from multiple companies, we must expect that different values will be
-assigned to a given field depending on the company from which the value is set.
-
-For the field of a same record to support several values, it must be defined with the attribute
-`company_dependent` set to `True`.
-
-.. code-block:: python
-
- from odoo import api, fields, models
-
- class Record(models.Model):
- _name = 'record.public'
-
- info = fields.Text()
- company_info = fields.Text(company_dependent=True)
- display_info = fields.Text(string='Infos', compute='_compute_display_info')
-
- @api.depends_context('company')
- def _compute_display_info(self):
- for record in self:
- record.display_info = record.info + record.company_info
-
-.. note:: The `_compute_display_info` method is decorated with `depends_context('company')`
- (see :attr:`~odoo.api.depends_context`) to ensure that the computed field is recomputed
- depending on the current company (`self.env.company`).
-
-When a company-dependent field is read, the current company is used to retrieve its value. In other
-words, if a user is logged in companies A and B with A as main company and creates a record for
-company B, the values of company-dependent fields will be that of company A.
-
-To read the values of company-dependent fields set from another company than the current one, we need
-to ensure the company we are using is the correct one. This can be done with :meth:`~odoo.models.Model.with_company`,
-which updates the current company.
-
-.. code-block:: python
-
- # Accessed as main company (self.env.company)
- val = record.company_dependent_field
-
- # Accessed as desired company (company_B)
- val = record.with_company(company_B).company_dependent_field
- # record.with_company(company_B).env.company == company_B
-
-.. warning::
-
- Whenever you are computing/creating/... things that may behave differently
- in different companies, you should make sure whatever you are doing is done
- in the right company. It doesn't cost much to always use `with_company` to
- avoid problems later on.
-
- .. code-block:: python
-
- @api.onchange('field_name')
- def _onchange_field_name(self):
- self = self.with_company(self.company_id)
- ...
-
- @api.depends('field_2')
- def _compute_field_3(self):
- for record in self:
- record = record.with_company(record.company_id)
- ...
-
-.. _howto/company/check_company:
-
-Multi-company consistency
--------------------------
-
-When a record is made shareable between several companies by the mean of a `company_id` field, we
-must take care that it cannot be linked to the record of another company through a relational field.
-For instance, we do not want to have a sales order and its invoice belonging to different companies.
-
-To ensure this multi-company consistency, you must:
-
-* Set the class attribute `_check_company_auto` to `True`.
-* Define relational fields with the attribute `check_company` set to `True` if their model has a
- `company_id` field.
-
-On each :meth:`~odoo.models.Model.create` and :meth:`~odoo.models.Model.write`, automatic checks
-will be triggered to ensure the multi-company consistency of the record.
-
-.. code-block:: python
-
- from odoo import fields, models
-
- class Record(models.Model):
- _name = 'record.shareable'
- _check_company_auto = True
-
- company_id = fields.Many2one('res.company')
- other_record_id = fields.Many2one('other.record', check_company=True)
-
-.. note:: The field `company_id` must not be defined with `check_company=True`.
-
-.. currentmodule:: odoo.models
-.. automethod:: Model._check_company
-
-.. warning:: The `check_company` feature performs a strict check ! It means that if a record has no
- `company_id` (i.e. the field is not required), it cannot be linked to a record whose
- `company_id` is set.
-
-.. note::
-
- When no domain is defined on the field and `check_company` is set to `True`, a default domain is
- added: `['|', '('company_id', '=', False), ('company_id', '=', company_id)]`
-
-.. _howto/company/default_company:
-
-Default company
----------------
-
-When the field `company_id` is made required on a model, a good practice is to set a default
-company. It eases the setup flow for the user or even guarantees its validity when the company is
-hidden from the view. Indeed, the company is usually hidden if the user does not have access to
-multiple companies (i.e. when the user does not have the group `base.group_multi_company`).
-
-.. code-block:: python
-
- from odoo import api, fields, models
-
- class Record(models.Model):
- _name = 'record.restricted'
- _check_company_auto = True
-
- company_id = fields.Many2one(
- 'res.company', required=True, default=lambda self: self.env.company
- )
- other_record_id = fields.Many2one('other.record', check_company=True)
-
-
-.. _howto/company/views:
-
-Views
------
-
-As stated in :ref:`above <howto/company/default_company>`, the company is usually hidden
-from the view if the user does not have access to multiple companies. This is tested with the group
-`base.group_multi_company`.
-
-.. code-block:: xml
-
- <record model="ir.ui.view" id="record_form_view">
- <field name="name">record.restricted.form</field>
- <field name="model">record.restricted</field>
- <field name="arch" type="xml">
- <form>
- <sheet>
- <group>
- <group>
- <field name="company_id" groups="base.group_multi_company"/>
- <field name="other_record_id"/>
- </group>
- </group>
- </sheet>
- </form>
- </field>
- </record>
-
-
-.. _howto/company/security:
-
-Security rules
---------------
-
-When working with records shared across companies or restricted to a single company, we must take
-care that a user does not have access to records belonging to other companies.
-
-This is achieved with security rules based on `company_ids`, which contains the current companies of
-the user (the companies the user checked in the multi-company widget).
-
-.. code-block:: xml
-
- <!-- Shareable Records -->
- <record model="ir.rule" id="record_shared_company_rule">
- <field name="name">Shared Record: multi-company</field>
- <field name="model_id" ref="model_record_shared"/>
- <field name="global" eval="True"/>
- <field name="domain_force">
- ['|', ('company_id', '=', False), ('company_id', 'in', company_ids)]
- </field>
- </record>
-
-.. code-block:: xml
-
- <!-- Company-restricted Records -->
- <record model="ir.rule" id="record_restricted_company_rule">
- <field name="name">Restricted Record: multi-company</field>
- <field name="model_id" ref="model_record_restricted"/>
- <field name="global" eval="True"/>
- <field name="domain_force">
- [('company_id', 'in', company_ids)]
- </field>
- </record>
-
-.. todo:: check_company on company_dependent fields.
diff --git a/doc/howtos/profile/flamegraph.svg b/doc/howtos/profile/flamegraph.svg
deleted file mode 100644
index a20921ad0ae..00000000000
--- a/doc/howtos/profile/flamegraph.svg
+++ /dev/null
@@ -1,315 +0,0 @@
-<svg width="1200" height="1078" onload="init(evt)" viewBox="0 0 1200 1078" xmlns="http://www.w3.org/2000/svg"><defs><linearGradient id="background" y2="1" x2="0"><stop stop-color="#eee" offset="5%"/><stop stop-color="#eeeeb0" offset="95%"/></linearGradient></defs><style>.func_g:hover{stroke:#000;stroke-width:.5;cursor:pointer}</style><script type="text/ecmascript"><![CDATA[
- var details, searchbtn, matchedtxt, svg;
- function init(evt) {
- details = document.getElementById("details").firstChild;
- searchbtn = document.getElementById("search");
- matchedtxt = document.getElementById("matched");
- svg = document.getElementsByTagName("svg")[0];
- searching = 0;
- }
-
- // mouse-over for info
- function s(node) { // show
- info = g_to_text(node);
- details.nodeValue = "Function: " + info;
- }
- function c() { // clear
- details.nodeValue = ' ';
- }
-
- // ctrl-F for search
- window.addEventListener("keydown",function (e) {
- if (e.keyCode === 114 || (e.ctrlKey && e.keyCode === 70)) {
- e.preventDefault();
- search_prompt();
- }
- })
-
- // functions
- function find_child(parent, name, attr) {
- var children = parent.childNodes;
- for (var i=0; i<children.length;i++) {
- if (children[i].tagName == name)
- return (attr != undefined) ? children[i].attributes[attr].value : children[i];
- }
- return;
- }
- function orig_save(e, attr, val) {
- if (e.attributes["_orig_"+attr] != undefined) return;
- if (e.attributes[attr] == undefined) return;
- if (val == undefined) val = e.attributes[attr].value;
- e.setAttribute("_orig_"+attr, val);
- }
- function orig_load(e, attr) {
- if (e.attributes["_orig_"+attr] == undefined) return;
- e.attributes[attr].value = e.attributes["_orig_"+attr].value;
- e.removeAttribute("_orig_"+attr);
- }
- function g_to_text(e) {
- var text = find_child(e, "title").firstChild.nodeValue;
- return (text)
- }
- function g_to_func(e) {
- var func = g_to_text(e);
- // if there's any manipulation we want to do to the function
- // name before it's searched, do it here before returning.
- return (func);
- }
- function update_text(e) {
- var r = find_child(e, "rect");
- var t = find_child(e, "text");
- var w = parseFloat(r.attributes["width"].value) -3;
- var txt = find_child(e, "title").textContent.replace(/\([^(]*\)$/,"");
- t.attributes["x"].value = parseFloat(r.attributes["x"].value) +3;
-
- // Smaller than this size won't fit anything
- if (w < 2*12*0.59) {
- t.textContent = "";
- return;
- }
-
- t.textContent = txt;
- // Fit in full text width
- if (/^ *$/.test(txt) || t.getSubStringLength(0, txt.length) < w)
- return;
-
- for (var x=txt.length-2; x>0; x--) {
- if (t.getSubStringLength(0, x+2) <= w) {
- t.textContent = txt.substring(0,x) + "..";
- return;
- }
- }
- t.textContent = "";
- }
-
- // zoom
- function zoom_reset(e) {
- if (e.attributes != undefined) {
- orig_load(e, "x");
- orig_load(e, "width");
- }
- if (e.childNodes == undefined) return;
- for(var i=0, c=e.childNodes; i<c.length; i++) {
- zoom_reset(c[i]);
- }
- }
- function zoom_child(e, x, ratio) {
- if (e.attributes != undefined) {
- if (e.attributes["x"] != undefined) {
- orig_save(e, "x");
- e.attributes["x"].value = (parseFloat(e.attributes["x"].value) - x - 10) * ratio + 10;
- if(e.tagName == "text") e.attributes["x"].value = find_child(e.parentNode, "rect", "x") + 3;
- }
- if (e.attributes["width"] != undefined) {
- orig_save(e, "width");
- e.attributes["width"].value = parseFloat(e.attributes["width"].value) * ratio;
- }
- }
-
- if (e.childNodes == undefined) return;
- for(var i=0, c=e.childNodes; i<c.length; i++) {
- zoom_child(c[i], x-10, ratio);
- }
- }
- function zoom_parent(e) {
- if (e.attributes) {
- if (e.attributes["x"] != undefined) {
- orig_save(e, "x");
- e.attributes["x"].value = 10;
- }
- if (e.attributes["width"] != undefined) {
- orig_save(e, "width");
- e.attributes["width"].value = parseInt(svg.width.baseVal.value) - (10*2);
- }
- }
- if (e.childNodes == undefined) return;
- for(var i=0, c=e.childNodes; i<c.length; i++) {
- zoom_parent(c[i]);
- }
- }
- function zoom(node) {
- var attr = find_child(node, "rect").attributes;
- var width = parseFloat(attr["width"].value);
- var xmin = parseFloat(attr["x"].value);
- var xmax = parseFloat(xmin + width);
- var ymin = parseFloat(attr["y"].value);
- var ratio = (svg.width.baseVal.value - 2*10) / width;
-
- // XXX: Workaround for JavaScript float issues (fix me)
- var fudge = 0.0001;
-
- var unzoombtn = document.getElementById("unzoom");
- unzoombtn.style["opacity"] = "1.0";
-
- var el = document.getElementsByTagName("g");
- for(var i=0;i<el.length;i++){
- var e = el[i];
- var a = find_child(e, "rect").attributes;
- var ex = parseFloat(a["x"].value);
- var ew = parseFloat(a["width"].value);
- // Is it an ancestor
- if (0 == 0) {
- var upstack = parseFloat(a["y"].value) > ymin;
- } else {
- var upstack = parseFloat(a["y"].value) < ymin;
- }
- if (upstack) {
- // Direct ancestor
- if (ex <= xmin && (ex+ew+fudge) >= xmax) {
- e.style["opacity"] = "0.5";
- zoom_parent(e);
- e.onclick = function(e){unzoom(); zoom(this);};
- update_text(e);
- }
- // not in current path
- else
- e.style["display"] = "none";
- }
- // Children maybe
- else {
- // no common path
- if (ex < xmin || ex + fudge >= xmax) {
- e.style["display"] = "none";
- }
- else {
- zoom_child(e, xmin, ratio);
- e.onclick = function(e){zoom(this);};
- update_text(e);
- }
- }
- }
- }
- function unzoom() {
- var unzoombtn = document.getElementById("unzoom");
- unzoombtn.style["opacity"] = "0.0";
-
- var el = document.getElementsByTagName("g");
- for(i=0;i<el.length;i++) {
- el[i].style["display"] = "block";
- el[i].style["opacity"] = "1";
- zoom_reset(el[i]);
- update_text(el[i]);
- }
- }
-
- // search
- function reset_search() {
- var el = document.getElementsByTagName("rect");
- for (var i=0; i < el.length; i++) {
- orig_load(el[i], "fill")
- }
- }
- function search_prompt() {
- if (!searching) {
- var term = prompt("Enter a search term (regexp " +
- "allowed, eg: ^ext4_)", "");
- if (term != null) {
- search(term)
- }
- } else {
- reset_search();
- searching = 0;
- searchbtn.style["opacity"] = "0.1";
- searchbtn.firstChild.nodeValue = "Search"
- matchedtxt.style["opacity"] = "0.0";
- matchedtxt.firstChild.nodeValue = ""
- }
- }
- function search(term) {
- var re = new RegExp(term);
- var el = document.getElementsByTagName("g");
- var matches = new Object();
- var maxwidth = 0;
- for (var i = 0; i < el.length; i++) {
- var e = el[i];
- if (e.attributes["class"].value != "func_g")
- continue;
- var func = g_to_func(e);
- var rect = find_child(e, "rect");
- if (rect == null) {
- // the rect might be wrapped in an anchor
- // if nameattr href is being used
- if (rect = find_child(e, "a")) {
- rect = find_child(r, "rect");
- }
- }
- if (func == null || rect == null)
- continue;
-
- // Save max width. Only works as we have a root frame
- var w = parseFloat(rect.attributes["width"].value);
- if (w > maxwidth)
- maxwidth = w;
-
- if (func.match(re)) {
- // highlight
- var x = parseFloat(rect.attributes["x"].value);
- orig_save(rect, "fill");
- rect.attributes["fill"].value =
- "rgb(230,0,230)";
-
- // remember matches
- if (matches[x] == undefined) {
- matches[x] = w;
- } else {
- if (w > matches[x]) {
- // overwrite with parent
- matches[x] = w;
- }
- }
- searching = 1;
- }
- }
- if (!searching)
- return;
-
- searchbtn.style["opacity"] = "1.0";
- searchbtn.firstChild.nodeValue = "Reset Search"
-
- // calculate percent matched, excluding vertical overlap
- var count = 0;
- var lastx = -1;
- var lastw = 0;
- var keys = Array();
- for (k in matches) {
- if (matches.hasOwnProperty(k))
- keys.push(k);
- }
- // sort the matched frames by their x location
- // ascending, then width descending
- keys.sort(function(a, b){
- return a - b;
- });
- // Step through frames saving only the biggest bottom-up frames
- // thanks to the sort order. This relies on the tree property
- // where children are always smaller than their parents.
- var fudge = 0.0001; // JavaScript floating point
- for (var k in keys) {
- var x = parseFloat(keys[k]);
- var w = matches[keys[k]];
- if (x >= lastx + lastw - fudge) {
- count += w;
- lastx = x;
- lastw = w;
- }
- }
- // display matched percent
- matchedtxt.style["opacity"] = "1.0";
- pct = 100 * count / maxwidth;
- if (pct == 100)
- pct = "100"
- else
- pct = pct.toFixed(1)
- matchedtxt.firstChild.nodeValue = "Matched: " + pct + "%";
- }
- function searchover(e) {
- searchbtn.style["opacity"] = "1.0";
- }
- function searchout(e) {
- if (searching) {
- searchbtn.style["opacity"] = "1.0";
- } else {
- searchbtn.style["opacity"] = "0.1";
- }
- }
-]]></script><path fill="url(#background)" d="M0 0H1200V1078H0z"/><text text-anchor="middle" x="600" y="24" font-size="17" font-family="Verdana">Flame Graph</text><text x="10" y="1061" font-size="12" font-family="Verdana" id="details"></text><text x="10" y="24" font-size="12" font-family="Verdana" id="unzoom" onclick="unzoom()" opacity="0.0" cursor="pointer">Reset Zoom</text><text x="1090" y="24" font-size="12" font-family="Verdana" id="search" onmouseover="searchover()" onmouseout="searchout()" onclick="search_prompt()" opacity="0.1" cursor="pointer">Search</text><text x="1090" y="1061" font-size="12" font-family="Verdana" id="matched"></text><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:browse:4237 (11 samples, 8.33%)</title><rect x="760.9" y="85" width="98.3" height="15" fill="#D93707" rx="2" ry="2"/><text x="763.91" y="95.5" font-size="12" font-family="Verdana">/datas/prog..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/fields.py:__get__:948 (1 samples, 0.76%)</title><rect x="1181.1" y="357" width="8.9" height="15" fill="#CD8D24" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/api.py:__new__:735 (3 samples, 2.27%)</title><rect x="188.8" y="197" width="26.8" height="15" fill="#D9B31D" rx="2" ry="2"/><text x="191.79" y="207.5" font-size="12" font-family="Verdana">/..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/fields.py:__get__:948 (38 samples, 28.79%)</title><rect x="617.9" y="181" width="339.7" height="15" fill="#DF2D2E" rx="2" ry="2"/><text x="620.88" y="191.5" font-size="12" font-family="Verdana">/datas/progs/odoo/odoo/fields.py:__get__:948</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/api.py:__new__:736 (5 samples, 3.79%)</title><rect x="1064.8" y="213" width="44.7" height="15" fill="#D64A2F" rx="2" ry="2"/><text x="1067.85" y="223.5" font-size="12" font-family="Verdana">/dat..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>&lt;string&gt;:__new__:14 (1 samples, 0.76%)</title><rect x="144.1" y="213" width="8.9" height="15" fill="#DD3515" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:_normalize_ids:5206 (1 samples, 0.76%)</title><rect x="752" y="69" width="8.9" height="15" fill="#F38E29" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>&lt;frozen importlib._bootstrap&gt;:_call_with_frames_removed:219 (1 samples, 0.76%)</title><rect x="10" y="389" width="8.9" height="15" fill="#EF6504" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:sudo:4310 (3 samples, 2.27%)</title><rect x="510.6" y="197" width="26.8" height="15" fill="#DBDB2A" rx="2" ry="2"/><text x="513.61" y="207.5" font-size="12" font-family="Verdana">/..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>&lt;frozen importlib._bootstrap&gt;:_call_with_frames_removed:219 (1 samples, 0.76%)</title><rect x="10" y="181" width="8.9" height="15" fill="#D4982C" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/api.py:__new__:736 (1 samples, 0.76%)</title><rect x="528.5" y="165" width="8.9" height="15" fill="#F97923" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>&lt;frozen importlib._bootstrap_external&gt;:exec_module:678 (1 samples, 0.76%)</title><rect x="10" y="197" width="8.9" height="15" fill="#D64B33" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/fields.py:convert_to_cache:1230 (6 samples, 4.55%)</title><rect x="957.6" y="261" width="53.6" height="15" fill="#DF7430" rx="2" ry="2"/><text x="960.58" y="271.5" font-size="12" font-family="Verdana">/data..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/api.py:__new__:736 (1 samples, 0.76%)</title><rect x="179.8" y="181" width="9" height="15" fill="#D85228" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/api.py:__hash__:777 (1 samples, 0.76%)</title><rect x="1002.3" y="165" width="8.9" height="15" fill="#CE0819" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/api.py:__new__:736 (1 samples, 0.76%)</title><rect x="376.5" y="165" width="9" height="15" fill="#D1C90E" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/sql_db.py:execute:242 (1 samples, 0.76%)</title><rect x="153" y="229" width="9" height="15" fill="#E4C120" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:_read_group_raw:1924 (7 samples, 5.30%)</title><rect x="448" y="245" width="62.6" height="15" fill="#E90326" rx="2" ry="2"/><text x="451.03" y="255.5" font-size="12" font-family="Verdana">/datas..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:qualify:2612 (1 samples, 0.76%)</title><rect x="877.1" y="85" width="9" height="15" fill="#D2021E" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/addons/auth_signup/models/ir_http.py:_dispatch:19 (128 samples, 96.97%)</title><rect x="45.8" y="613" width="1144.2" height="15" fill="#DED709" rx="2" ry="2"/><text x="48.76" y="623.5" font-size="12" font-family="Verdana">/datas/progs/odoo/addons/auth_signup/models/ir_http.py:_dispatch:19</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/api.py:__new__:742 (1 samples, 0.76%)</title><rect x="993.3" y="213" width="9" height="15" fill="#EFC30D" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>&lt;string&gt;:change_digit:9 (6 samples, 4.55%)</title><rect x="957.6" y="229" width="53.6" height="15" fill="#CD520C" rx="2" ry="2"/><text x="960.58" y="239.5" font-size="12" font-family="Verdana">&lt;stri..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/usr/local/lib/python3.6/encodings/utf_8.py:decode:16 (1 samples, 0.76%)</title><rect x="886.1" y="69" width="8.9" height="15" fill="#E90B24" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/fields.py:convert_to_cache:1230 (7 samples, 5.30%)</title><rect x="1109.5" y="261" width="62.6" height="15" fill="#E35B00" rx="2" ry="2"/><text x="1112.55" y="271.5" font-size="12" font-family="Verdana">/datas..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:_read_group_resolve_many2one_fields:1944 (6 samples, 4.55%)</title><rect x="457" y="229" width="53.6" height="15" fill="#F30305" rx="2" ry="2"/><text x="459.97" y="239.5" font-size="12" font-family="Verdana">/data..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/addons/stock_account/models/product.py:do_change_standard_price:126 (20 samples, 15.15%)</title><rect x="135.2" y="373" width="178.7" height="15" fill="#FB602C" rx="2" ry="2"/><text x="138.15" y="383.5" font-size="12" font-family="Verdana">/datas/progs/odoo/addon..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:read_group:1828 (13 samples, 9.85%)</title><rect x="394.4" y="261" width="116.2" height="15" fill="#D40708" rx="2" ry="2"/><text x="397.39" y="271.5" font-size="12" font-family="Verdana">/datas/progs/o..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/api.py:__new__:736 (1 samples, 0.76%)</title><rect x="215.6" y="197" width="8.9" height="15" fill="#E9460A" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/fields.py:convert_to_record:1989 (3 samples, 2.27%)</title><rect x="930.8" y="85" width="26.8" height="15" fill="#FED836" rx="2" ry="2"/><text x="933.76" y="95.5" font-size="12" font-family="Verdana">/..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:recompute:4791 (1 samples, 0.76%)</title><rect x="1172.1" y="309" width="9" height="15" fill="#FEA503" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/fields.py:__get__:944 (1 samples, 0.76%)</title><rect x="921.8" y="101" width="9" height="15" fill="#D4A60E" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:browse:4235 (2 samples, 1.52%)</title><rect x="743" y="85" width="17.9" height="15" fill="#FAAE2C" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/api.py:add:939 (1 samples, 0.76%)</title><rect x="1002.3" y="197" width="8.9" height="15" fill="#DADE0D" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/osv/expression.py:&lt;listcomp&gt;:1204 (1 samples, 0.76%)</title><rect x="421.2" y="181" width="9" height="15" fill="#D70535" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>&lt;decorator-gen-112&gt;:precision_get:2 (1 samples, 0.76%)</title><rect x="242.4" y="197" width="9" height="15" fill="#EEB30B" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/osv/expression.py:get_unaccent_wrapper:455 (1 samples, 0.76%)</title><rect x="394.4" y="197" width="8.9" height="15" fill="#E0740D" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/usr/local/lib/python3.6/site-packages/werkzeug/routing.py:add:1197 (1 samples, 0.76%)</title><rect x="45.8" y="517" width="8.9" height="15" fill="#D8D51D" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:_read_group_raw:1924 (3 samples, 2.27%)</title><rect x="510.6" y="245" width="26.8" height="15" fill="#F9501F" rx="2" ry="2"/><text x="513.61" y="255.5" font-size="12" font-family="Verdana">/..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/usr/local/lib/python3.6/site-packages/werkzeug/serving.py:run_wsgi:193 (132 samples, 100.00%)</title><rect x="10" y="741" width="1180" height="15" fill="#EFCB17" rx="2" ry="2"/><text x="13" y="751.5" font-size="12" font-family="Verdana">/usr/local/lib/python3.6/site-packages/werkzeug/serving.py:run_wsgi:193</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/api.py:get_todo:911 (1 samples, 0.76%)</title><rect x="1172.1" y="293" width="9" height="15" fill="#F96003" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>odoo-bin:&lt;module&gt;:8 (132 samples, 100.00%)</title><rect x="10" y="1013" width="1180" height="15" fill="#D4BD19" rx="2" ry="2"/><text x="13" y="1023.5" font-size="12" font-family="Verdana">odoo-bin:&lt;module&gt;:8</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/fields.py:__set__:966 (7 samples, 5.30%)</title><rect x="242.4" y="261" width="62.6" height="15" fill="#E91221" rx="2" ry="2"/><text x="245.42" y="271.5" font-size="12" font-family="Verdana">/datas..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/modules/loading.py:load_modules:339 (1 samples, 0.76%)</title><rect x="10" y="565" width="8.9" height="15" fill="#D9A614" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/usr/local/lib/python3.6/_weakrefset.py:__iter__:60 (1 samples, 0.76%)</title><rect x="510.6" y="149" width="8.9" height="15" fill="#E7671A" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:_read_from_database:2618 (1 samples, 0.76%)</title><rect x="877.1" y="117" width="9" height="15" fill="#E12023" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:&lt;listcomp&gt;:2618 (1 samples, 0.76%)</title><rect x="877.1" y="101" width="9" height="15" fill="#DA2B27" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>all (132 samples, 100%)</title><rect x="10" y="1029" width="1180" height="15" fill="#D25631" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/usr/local/lib/python3.6/sre_compile.py:compile:566 (1 samples, 0.76%)</title><rect x="45.8" y="437" width="8.9" height="15" fill="#F82D25" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/service/server.py:run:743 (132 samples, 100.00%)</title><rect x="10" y="885" width="1180" height="15" fill="#F2AF01" rx="2" ry="2"/><text x="13" y="895.5" font-size="12" font-family="Verdana">/datas/progs/odoo/odoo/service/server.py:run:743</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/api.py:__call__:789 (9 samples, 6.82%)</title><rect x="537.4" y="245" width="80.5" height="15" fill="#F29D08" rx="2" ry="2"/><text x="540.42" y="255.5" font-size="12" font-family="Verdana">/datas/pr..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/cli/server.py:main:169 (132 samples, 100.00%)</title><rect x="10" y="965" width="1180" height="15" fill="#D9AB07" rx="2" ry="2"/><text x="13" y="975.5" font-size="12" font-family="Verdana">/datas/progs/odoo/odoo/cli/server.py:main:169</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/addons/stock/models/product.py:_compute_quantities_dict:124 (13 samples, 9.85%)</title><rect x="394.4" y="277" width="116.2" height="15" fill="#DE7202" rx="2" ry="2"/><text x="397.39" y="287.5" font-size="12" font-family="Verdana">/datas/progs/o..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:__setitem__:4666 (7 samples, 5.30%)</title><rect x="242.4" y="277" width="62.6" height="15" fill="#F56320" rx="2" ry="2"/><text x="245.42" y="287.5" font-size="12" font-family="Verdana">/datas..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:_read_group_raw:1889 (1 samples, 0.76%)</title><rect x="430.2" y="245" width="8.9" height="15" fill="#EACB1F" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:__bool__:4521 (1 samples, 0.76%)</title><rect x="859.2" y="101" width="9" height="15" fill="#FB6826" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/addons/base/res/ir_property.py:get_multi:160 (6 samples, 4.55%)</title><rect x="188.8" y="277" width="53.6" height="15" fill="#F62A2D" rx="2" ry="2"/><text x="191.79" y="287.5" font-size="12" font-family="Verdana">/data..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/fields.py:__get__:948 (96 samples, 72.73%)</title><rect x="313.9" y="357" width="858.2" height="15" fill="#D53920" rx="2" ry="2"/><text x="316.94" y="367.5" font-size="12" font-family="Verdana">/datas/progs/odoo/odoo/fields.py:__get__:948</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/fields.py:convert_to_cache:1227 (1 samples, 0.76%)</title><rect x="1038" y="261" width="9" height="15" fill="#DF3E0C" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/addons/base/res/ir_property.py:get_multi:150 (5 samples, 3.79%)</title><rect x="144.1" y="277" width="44.7" height="15" fill="#E1AA21" rx="2" ry="2"/><text x="147.09" y="287.5" font-size="12" font-family="Verdana">/dat..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:_prefetch_field:2533 (27 samples, 20.45%)</title><rect x="617.9" y="149" width="241.3" height="15" fill="#D8172A" rx="2" ry="2"/><text x="620.88" y="159.5" font-size="12" font-family="Verdana">/datas/progs/odoo/odoo/models.py..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/usr/local/lib/python3.6/_weakrefset.py:__iter__:60 (3 samples, 2.27%)</title><rect x="537.4" y="213" width="26.8" height="15" fill="#EBCF06" rx="2" ry="2"/><text x="540.42" y="223.5" font-size="12" font-family="Verdana">/..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:_search:3664 (4 samples, 3.03%)</title><rect x="188.8" y="245" width="35.7" height="15" fill="#CD2D35" rx="2" ry="2"/><text x="191.79" y="255.5" font-size="12" font-family="Verdana">/da..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/usr/local/lib/python3.6/_weakrefset.py:__iter__:61 (3 samples, 2.27%)</title><rect x="1118.5" y="197" width="26.8" height="15" fill="#F70A2E" rx="2" ry="2"/><text x="1121.48" y="207.5" font-size="12" font-family="Verdana">/..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:_where_calc:3469 (3 samples, 2.27%)</title><rect x="394.4" y="229" width="26.8" height="15" fill="#EC142C" rx="2" ry="2"/><text x="397.39" y="239.5" font-size="12" font-family="Verdana">/..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/addons/base/ir/ir_http.py:_find_handler:84 (1 samples, 0.76%)</title><rect x="45.8" y="565" width="8.9" height="15" fill="#D57C08" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/api.py:__new__:736 (2 samples, 1.52%)</title><rect x="1020.2" y="213" width="17.8" height="15" fill="#EB972C" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/api.py:__new__:103 (1 samples, 0.76%)</title><rect x="10" y="149" width="8.9" height="15" fill="#D74807" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/api.py:__call__:789 (6 samples, 4.55%)</title><rect x="457" y="181" width="53.6" height="15" fill="#F02015" rx="2" ry="2"/><text x="459.97" y="191.5" font-size="12" font-family="Verdana">/data..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/addons/stock/models/product.py:&lt;lambda&gt;:200 (38 samples, 28.79%)</title><rect x="617.9" y="197" width="339.7" height="15" fill="#CFC014" rx="2" ry="2"/><text x="620.88" y="207.5" font-size="12" font-family="Verdana">/datas/progs/odoo/addons/stock/models/product..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/modules/registry.py:setup_models:276 (3 samples, 2.27%)</title><rect x="18.9" y="549" width="26.9" height="15" fill="#FE6C23" rx="2" ry="2"/><text x="21.94" y="559.5" font-size="12" font-family="Verdana">/..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/api.py:__new__:735 (2 samples, 1.52%)</title><rect x="162" y="181" width="17.8" height="15" fill="#E9662C" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/api.py:call_kw_multi:680 (1 samples, 0.76%)</title><rect x="1181.1" y="405" width="8.9" height="15" fill="#E86424" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>&lt;frozen importlib._bootstrap&gt;:_handle_fromlist:1017 (1 samples, 0.76%)</title><rect x="10" y="405" width="8.9" height="15" fill="#DACD03" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/http.py:dispatch:683 (127 samples, 96.21%)</title><rect x="54.7" y="549" width="1135.3" height="15" fill="#DF3A32" rx="2" ry="2"/><text x="57.7" y="559.5" font-size="12" font-family="Verdana">/datas/progs/odoo/odoo/http.py:dispatch:683</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/fields.py:determine_value:1049 (38 samples, 28.79%)</title><rect x="617.9" y="165" width="339.7" height="15" fill="#F30A2D" rx="2" ry="2"/><text x="620.88" y="175.5" font-size="12" font-family="Verdana">/datas/progs/odoo/odoo/fields.py:determine_va..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/usr/local/lib/python3.6/site-packages/werkzeug/serving.py:handle_one_request:251 (132 samples, 100.00%)</title><rect x="10" y="757" width="1180" height="15" fill="#D5881B" rx="2" ry="2"/><text x="13" y="767.5" font-size="12" font-family="Verdana">/usr/local/lib/python3.6/site-packages/werkzeug/serving.py:handle_one_request:251</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/sql_db.py:wrapper:155 (2 samples, 1.52%)</title><rect x="144.1" y="245" width="17.9" height="15" fill="#F29F29" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/http.py:routing_map:978 (1 samples, 0.76%)</title><rect x="45.8" y="533" width="8.9" height="15" fill="#F8860E" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>&lt;frozen importlib._bootstrap&gt;:_handle_fromlist:1017 (1 samples, 0.76%)</title><rect x="10" y="277" width="8.9" height="15" fill="#F73103" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/addons/fetchmail/models/fetchmail.py:&lt;module&gt;:21 (1 samples, 0.76%)</title><rect x="10" y="165" width="8.9" height="15" fill="#E2CB31" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:read:2509 (1 samples, 0.76%)</title><rect x="1181.1" y="229" width="8.9" height="15" fill="#FE230C" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/http.py:_call_function:339 (127 samples, 96.21%)</title><rect x="54.7" y="533" width="1135.3" height="15" fill="#E42B0F" rx="2" ry="2"/><text x="57.7" y="543.5" font-size="12" font-family="Verdana">/datas/progs/odoo/odoo/http.py:_call_function:339</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/fields.py:compute_value:1015 (1 samples, 0.76%)</title><rect x="1181.1" y="325" width="8.9" height="15" fill="#F91E13" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/usr/local/lib/python3.6/_weakrefset.py:__iter__:59 (1 samples, 0.76%)</title><rect x="188.8" y="181" width="8.9" height="15" fill="#DB0F2D" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/usr/local/lib/python3.6/sre_compile.py:_code:551 (1 samples, 0.76%)</title><rect x="45.8" y="421" width="8.9" height="15" fill="#EEB30C" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/osv/expression.py:get_alias_from_query:380 (1 samples, 0.76%)</title><rect x="430.2" y="197" width="8.9" height="15" fill="#E98425" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/fields.py:determine_value:1049 (1 samples, 0.76%)</title><rect x="1181.1" y="261" width="8.9" height="15" fill="#F0AA02" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/addons/stock_account/models/product.py:do_change_standard_price:131 (96 samples, 72.73%)</title><rect x="313.9" y="373" width="858.2" height="15" fill="#FD301C" rx="2" ry="2"/><text x="316.94" y="383.5" font-size="12" font-family="Verdana">/datas/progs/odoo/addons/stock_account/models/product.py:do_change_standard_price:131</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/fields.py:__get__:951 (1 samples, 0.76%)</title><rect x="305" y="357" width="8.9" height="15" fill="#DBE321" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:read:2509 (5 samples, 3.79%)</title><rect x="859.2" y="133" width="44.7" height="15" fill="#EB2933" rx="2" ry="2"/><text x="862.24" y="143.5" font-size="12" font-family="Verdana">/dat..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/addons/web/controllers/main.py:call_button:928 (126 samples, 95.45%)</title><rect x="54.7" y="453" width="1126.4" height="15" fill="#D8DC0E" rx="2" ry="2"/><text x="57.7" y="463.5" font-size="12" font-family="Verdana">/datas/progs/odoo/addons/web/controllers/main.py:call_button:928</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:_read_group_raw:1854 (1 samples, 0.76%)</title><rect x="331.8" y="245" width="9" height="15" fill="#F96A2A" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:_where_calc:3462 (1 samples, 0.76%)</title><rect x="224.5" y="229" width="9" height="15" fill="#CE8708" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/fields.py:determine_value:1059 (1 samples, 0.76%)</title><rect x="1181.1" y="341" width="8.9" height="15" fill="#D24E08" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/service/server.py:process_request:767 (132 samples, 100.00%)</title><rect x="10" y="853" width="1180" height="15" fill="#F40610" rx="2" ry="2"/><text x="13" y="863.5" font-size="12" font-family="Verdana">/datas/progs/odoo/odoo/service/server.py:process_request:767</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/addons/stock/models/product.py:_compute_quantities_dict:123 (9 samples, 6.82%)</title><rect x="313.9" y="277" width="80.5" height="15" fill="#FAB717" rx="2" ry="2"/><text x="316.94" y="287.5" font-size="12" font-family="Verdana">/datas/pr..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/tools/cache.py:lookup:81 (1 samples, 0.76%)</title><rect x="242.4" y="181" width="9" height="15" fill="#DC6726" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/modules/module.py:load_module:82 (1 samples, 0.76%)</title><rect x="10" y="437" width="8.9" height="15" fill="#DB4827" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/modules/loading.py:load_modules:346 (3 samples, 2.27%)</title><rect x="18.9" y="565" width="26.9" height="15" fill="#FE7B1E" rx="2" ry="2"/><text x="21.94" y="575.5" font-size="12" font-family="Verdana">/..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/fields.py:__set__:966 (6 samples, 4.55%)</title><rect x="957.6" y="277" width="53.6" height="15" fill="#CD642A" rx="2" ry="2"/><text x="960.58" y="287.5" font-size="12" font-family="Verdana">/data..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/usr/local/lib/python3.6/sre_compile.py:_compile:81 (1 samples, 0.76%)</title><rect x="45.8" y="405" width="8.9" height="15" fill="#ED0E12" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:_browse:4218 (1 samples, 0.76%)</title><rect x="903.9" y="101" width="9" height="15" fill="#E7D411" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>&lt;frozen importlib._bootstrap&gt;:_call_with_frames_removed:219 (1 samples, 0.76%)</title><rect x="10" y="261" width="8.9" height="15" fill="#CE0730" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>&lt;frozen importlib._bootstrap&gt;:_load_unlocked:656 (1 samples, 0.76%)</title><rect x="10" y="469" width="8.9" height="15" fill="#DD840B" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:&lt;listcomp&gt;:2618 (1 samples, 0.76%)</title><rect x="1181.1" y="197" width="8.9" height="15" fill="#F39E06" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>&lt;frozen importlib._bootstrap&gt;:_load_backward_compatible:626 (1 samples, 0.76%)</title><rect x="10" y="453" width="8.9" height="15" fill="#D61E09" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/osv/query.py:get_sql:144 (1 samples, 0.76%)</title><rect x="430.2" y="229" width="8.9" height="15" fill="#F7491C" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/api.py:__new__:735 (2 samples, 1.52%)</title><rect x="510.6" y="165" width="17.9" height="15" fill="#ECDD15" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:_read_from_database:2589 (1 samples, 0.76%)</title><rect x="859.2" y="117" width="9" height="15" fill="#F3AD0B" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:_browse:4224 (5 samples, 3.79%)</title><rect x="814.5" y="69" width="44.7" height="15" fill="#F02012" rx="2" ry="2"/><text x="817.55" y="79.5" font-size="12" font-family="Verdana">/dat..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/osv/expression.py:is_leaf:422 (1 samples, 0.76%)</title><rect x="403.3" y="181" width="9" height="15" fill="#FAA20C" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/service/server.py:process_work:776 (132 samples, 100.00%)</title><rect x="10" y="869" width="1180" height="15" fill="#F5352D" rx="2" ry="2"/><text x="13" y="879.5" font-size="12" font-family="Verdana">/datas/progs/odoo/odoo/service/server.py:process_work:776</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/fields.py:digits:1209 (3 samples, 2.27%)</title><rect x="1011.2" y="245" width="26.8" height="15" fill="#FC981F" rx="2" ry="2"/><text x="1014.21" y="255.5" font-size="12" font-family="Verdana">/..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/fields.py:__get__:956 (3 samples, 2.27%)</title><rect x="930.8" y="101" width="26.8" height="15" fill="#D4DB0C" rx="2" ry="2"/><text x="933.76" y="111.5" font-size="12" font-family="Verdana">/..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/http.py:dispatch:1456 (4 samples, 3.03%)</title><rect x="10" y="629" width="35.8" height="15" fill="#E02C31" rx="2" ry="2"/><text x="13" y="639.5" font-size="12" font-family="Verdana">/da..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/api.py:__call__:789 (4 samples, 3.03%)</title><rect x="188.8" y="213" width="35.7" height="15" fill="#E94425" rx="2" ry="2"/><text x="191.79" y="223.5" font-size="12" font-family="Verdana">/da..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/usr/local/lib/python3.6/_weakrefset.py:__iter__:60 (1 samples, 0.76%)</title><rect x="1055.9" y="197" width="8.9" height="15" fill="#F79715" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:_where_calc:3469 (1 samples, 0.76%)</title><rect x="313.9" y="229" width="9" height="15" fill="#F4A80E" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/usr/local/lib/python3.6/_weakrefset.py:__iter__:60 (2 samples, 1.52%)</title><rect x="197.7" y="181" width="17.9" height="15" fill="#D7BE1C" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/addons/stock/models/product.py:_compute_quantities:85 (8 samples, 6.06%)</title><rect x="1038" y="293" width="71.5" height="15" fill="#DE5B02" rx="2" ry="2"/><text x="1041.03" y="303.5" font-size="12" font-family="Verdana">/datas/p..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:_where_calc:3471 (1 samples, 0.76%)</title><rect x="233.5" y="229" width="8.9" height="15" fill="#E1DC32" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/tools/lru.py:__getitem__:45 (1 samples, 0.76%)</title><rect x="340.8" y="133" width="8.9" height="15" fill="#EBB20F" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/usr/local/lib/python3.6/site-packages/werkzeug/serving.py:handle:216 (132 samples, 100.00%)</title><rect x="10" y="789" width="1180" height="15" fill="#E02820" rx="2" ry="2"/><text x="13" y="799.5" font-size="12" font-family="Verdana">/usr/local/lib/python3.6/site-packages/werkzeug/serving.py:handle:216</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/addons/stock/models/product.py:_compute_quantities:86 (7 samples, 5.30%)</title><rect x="1109.5" y="293" width="62.6" height="15" fill="#F8C136" rx="2" ry="2"/><text x="1112.55" y="303.5" font-size="12" font-family="Verdana">/datas..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:__getitem__:4657 (5 samples, 3.79%)</title><rect x="912.9" y="117" width="44.7" height="15" fill="#E08D1F" rx="2" ry="2"/><text x="915.88" y="127.5" font-size="12" font-family="Verdana">/dat..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/service/server.py:process_spawn:539 (132 samples, 100.00%)</title><rect x="10" y="917" width="1180" height="15" fill="#DA7F14" rx="2" ry="2"/><text x="13" y="927.5" font-size="12" font-family="Verdana">/datas/progs/odoo/odoo/service/server.py:process_spawn:539</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/usr/local/lib/python3.6/http/server.py:handle:418 (132 samples, 100.00%)</title><rect x="10" y="773" width="1180" height="15" fill="#E54536" rx="2" ry="2"/><text x="13" y="783.5" font-size="12" font-family="Verdana">/usr/local/lib/python3.6/http/server.py:handle:418</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/api.py:__new__:744 (1 samples, 0.76%)</title><rect x="296.1" y="197" width="8.9" height="15" fill="#D8070C" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/usr/local/lib/python3.6/_weakrefset.py:__iter__:60 (1 samples, 0.76%)</title><rect x="1109.5" y="197" width="9" height="15" fill="#F17A26" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:qualify:2612 (1 samples, 0.76%)</title><rect x="1181.1" y="181" width="8.9" height="15" fill="#D0CA32" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/usr/local/lib/python3.6/_weakrefset.py:__iter__:60 (1 samples, 0.76%)</title><rect x="1011.2" y="197" width="9" height="15" fill="#E44732" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>&lt;frozen importlib._bootstrap&gt;:_find_and_load_unlocked:955 (1 samples, 0.76%)</title><rect x="10" y="229" width="8.9" height="15" fill="#F04F0B" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/addons/product/models/product.py:name_get:372 (1 samples, 0.76%)</title><rect x="340.8" y="213" width="8.9" height="15" fill="#F5562A" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/addons/stock/models/product.py:_compute_quantities:81 (72 samples, 54.55%)</title><rect x="313.9" y="293" width="643.7" height="15" fill="#EEDC25" rx="2" ry="2"/><text x="316.94" y="303.5" font-size="12" font-family="Verdana">/datas/progs/odoo/addons/stock/models/product.py:_compute_quantities:81</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/addons/stock/models/product.py:_compute_quantities:84 (3 samples, 2.27%)</title><rect x="1011.2" y="293" width="26.8" height="15" fill="#F07E12" rx="2" ry="2"/><text x="1014.21" y="303.5" font-size="12" font-family="Verdana">/..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/addons/base/res/ir_property.py:_get_domain:134 (2 samples, 1.52%)</title><rect x="144.1" y="261" width="17.9" height="15" fill="#CFB508" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:_read_from_database:2628 (1 samples, 0.76%)</title><rect x="886.1" y="117" width="8.9" height="15" fill="#CDAE1B" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/api.py:__call__:789 (8 samples, 6.06%)</title><rect x="63.6" y="341" width="71.6" height="15" fill="#E4A718" rx="2" ry="2"/><text x="66.64" y="351.5" font-size="12" font-family="Verdana">/datas/p..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:_in_cache_without:4684 (27 samples, 20.45%)</title><rect x="617.9" y="133" width="241.3" height="15" fill="#FD0734" rx="2" ry="2"/><text x="620.88" y="143.5" font-size="12" font-family="Verdana">/datas/progs/odoo/odoo/models.py..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/osv/expression.py:__leaf_to_sql:1204 (1 samples, 0.76%)</title><rect x="421.2" y="197" width="9" height="15" fill="#DB8C1E" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/usr/local/lib/python3.6/_weakrefset.py:__iter__:61 (1 samples, 0.76%)</title><rect x="483.8" y="149" width="8.9" height="15" fill="#D51035" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/api.py:__new__:735 (1 samples, 0.76%)</title><rect x="1011.2" y="213" width="9" height="15" fill="#DD1B2B" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:_read_group_resolve_many2one_fields:1944 (3 samples, 2.27%)</title><rect x="510.6" y="229" width="26.8" height="15" fill="#D72602" rx="2" ry="2"/><text x="513.61" y="239.5" font-size="12" font-family="Verdana">/..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/fields.py:_compute_company_dependent:636 (11 samples, 8.33%)</title><rect x="144.1" y="293" width="98.3" height="15" fill="#F35A22" rx="2" ry="2"/><text x="147.09" y="303.5" font-size="12" font-family="Verdana">/datas/prog..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/fields.py:convert_to_cache:1230 (3 samples, 2.27%)</title><rect x="1011.2" y="261" width="26.8" height="15" fill="#F96134" rx="2" ry="2"/><text x="1014.21" y="271.5" font-size="12" font-family="Verdana">/..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/api.py:__new__:735 (4 samples, 3.03%)</title><rect x="537.4" y="229" width="35.8" height="15" fill="#F8C401" rx="2" ry="2"/><text x="540.42" y="239.5" font-size="12" font-family="Verdana">/da..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>&lt;frozen importlib._bootstrap&gt;:_load_unlocked:665 (1 samples, 0.76%)</title><rect x="10" y="213" width="8.9" height="15" fill="#FA3A14" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/addons/stock/models/product.py:_compute_quantities_dict:93 (38 samples, 28.79%)</title><rect x="617.9" y="277" width="339.7" height="15" fill="#E35E09" rx="2" ry="2"/><text x="620.88" y="287.5" font-size="12" font-family="Verdana">/datas/progs/odoo/addons/stock/models/product..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/addons/stock/models/product.py:_get_domain_locations:191 (38 samples, 28.79%)</title><rect x="617.9" y="261" width="339.7" height="15" fill="#F94725" rx="2" ry="2"/><text x="620.88" y="271.5" font-size="12" font-family="Verdana">/datas/progs/odoo/addons/stock/models/product..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/usr/local/lib/python3.6/enum.py:__and__:804 (1 samples, 0.76%)</title><rect x="45.8" y="389" width="8.9" height="15" fill="#F6B312" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/api.py:call_kw_multi:680 (126 samples, 95.45%)</title><rect x="54.7" y="405" width="1126.4" height="15" fill="#F9BA22" rx="2" ry="2"/><text x="57.7" y="415.5" font-size="12" font-family="Verdana">/datas/progs/odoo/odoo/api.py:call_kw_multi:680</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/addons/base/res/res_company.py:_company_default_get:181 (3 samples, 2.27%)</title><rect x="162" y="245" width="26.8" height="15" fill="#DD352E" rx="2" ry="2"/><text x="164.97" y="255.5" font-size="12" font-family="Verdana">/..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/usr/local/lib/python3.6/_weakrefset.py:__iter__:61 (1 samples, 0.76%)</title><rect x="564.2" y="213" width="9" height="15" fill="#D82C19" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:with_context:4333 (9 samples, 6.82%)</title><rect x="537.4" y="261" width="80.5" height="15" fill="#D10727" rx="2" ry="2"/><text x="540.42" y="271.5" font-size="12" font-family="Verdana">/datas/pr..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:_read_from_database:2618 (1 samples, 0.76%)</title><rect x="1181.1" y="213" width="8.9" height="15" fill="#F70110" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:_add_field:288 (1 samples, 0.76%)</title><rect x="27.9" y="517" width="8.9" height="15" fill="#D0DB15" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/api.py:__getitem__:760 (1 samples, 0.76%)</title><rect x="939.7" y="69" width="8.9" height="15" fill="#D5612F" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/fields.py:determine_value:1059 (96 samples, 72.73%)</title><rect x="313.9" y="341" width="858.2" height="15" fill="#F89D35" rx="2" ry="2"/><text x="316.94" y="351.5" font-size="12" font-family="Verdana">/datas/progs/odoo/odoo/fields.py:determine_value:1059</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>&lt;string&gt;:change_digit:9 (6 samples, 4.55%)</title><rect x="251.4" y="213" width="53.6" height="15" fill="#DDC711" rx="2" ry="2"/><text x="254.36" y="223.5" font-size="12" font-family="Verdana">&lt;stri..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:browse:4237 (1 samples, 0.76%)</title><rect x="448" y="213" width="9" height="15" fill="#DD6824" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:read:2520 (5 samples, 3.79%)</title><rect x="912.9" y="133" width="44.7" height="15" fill="#D6BF1A" rx="2" ry="2"/><text x="915.88" y="143.5" font-size="12" font-family="Verdana">/dat..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/osv/expression.py:parse:813 (1 samples, 0.76%)</title><rect x="412.3" y="197" width="8.9" height="15" fill="#E9490A" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:_prefetch_field:2565 (1 samples, 0.76%)</title><rect x="1181.1" y="245" width="8.9" height="15" fill="#DE6625" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/usr/local/lib/python3.6/_weakrefset.py:__iter__:61 (1 samples, 0.76%)</title><rect x="984.4" y="197" width="8.9" height="15" fill="#D8530A" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/service/wsgi_server.py:application:166 (132 samples, 100.00%)</title><rect x="10" y="709" width="1180" height="15" fill="#CE2517" rx="2" ry="2"/><text x="13" y="719.5" font-size="12" font-family="Verdana">/datas/progs/odoo/odoo/service/wsgi_server.py:application:166</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/service/server.py:run:635 (132 samples, 100.00%)</title><rect x="10" y="933" width="1180" height="15" fill="#E4DD2D" rx="2" ry="2"/><text x="13" y="943.5" font-size="12" font-family="Verdana">/datas/progs/odoo/odoo/service/server.py:run:635</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:_inherits_join_calc:1985 (1 samples, 0.76%)</title><rect x="877.1" y="69" width="9" height="15" fill="#DC1F10" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:_browse:4219 (2 samples, 1.52%)</title><rect x="778.8" y="69" width="17.9" height="15" fill="#FC7429" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/api.py:__new__:736 (5 samples, 3.79%)</title><rect x="573.2" y="229" width="44.7" height="15" fill="#F9B713" rx="2" ry="2"/><text x="576.18" y="239.5" font-size="12" font-family="Verdana">/dat..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/fields.py:convert_to_cache:1230 (7 samples, 5.30%)</title><rect x="1047" y="261" width="62.5" height="15" fill="#E24601" rx="2" ry="2"/><text x="1049.97" y="271.5" font-size="12" font-family="Verdana">/datas..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/tools/lru.py:__setitem__:56 (1 samples, 0.76%)</title><rect x="340.8" y="101" width="8.9" height="15" fill="#D37D20" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>&lt;frozen importlib._bootstrap_external&gt;:exec_module:678 (1 samples, 0.76%)</title><rect x="10" y="325" width="8.9" height="15" fill="#D4C619" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/__init__.py:registry:76 (4 samples, 3.03%)</title><rect x="10" y="613" width="35.8" height="15" fill="#EEB91C" rx="2" ry="2"/><text x="13" y="623.5" font-size="12" font-family="Verdana">/da..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/fields.py:convert_to_column:776 (1 samples, 0.76%)</title><rect x="421.2" y="165" width="9" height="15" fill="#DF9A1F" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/api.py:__new__:735 (4 samples, 3.03%)</title><rect x="957.6" y="213" width="35.7" height="15" fill="#D24804" rx="2" ry="2"/><text x="960.58" y="223.5" font-size="12" font-family="Verdana">/da..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>&lt;frozen importlib._bootstrap&gt;:_load_unlocked:665 (1 samples, 0.76%)</title><rect x="10" y="341" width="8.9" height="15" fill="#F5E107" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>&lt;string&gt;:change_digit:10 (1 samples, 0.76%)</title><rect x="242.4" y="213" width="9" height="15" fill="#EEE113" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/fields.py:__set__:966 (3 samples, 2.27%)</title><rect x="1011.2" y="277" width="26.8" height="15" fill="#CF6C01" rx="2" ry="2"/><text x="1014.21" y="287.5" font-size="12" font-family="Verdana">/..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/fields.py:_compute_company_dependent:638 (7 samples, 5.30%)</title><rect x="242.4" y="293" width="62.6" height="15" fill="#E3B426" rx="2" ry="2"/><text x="245.42" y="303.5" font-size="12" font-family="Verdana">/datas..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/addons/stock/models/product.py:_get_domain_locations_new:200 (38 samples, 28.79%)</title><rect x="617.9" y="245" width="339.7" height="15" fill="#D24912" rx="2" ry="2"/><text x="620.88" y="255.5" font-size="12" font-family="Verdana">/datas/progs/odoo/addons/stock/models/product..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/modules/loading.py:load_marked_modules:242 (1 samples, 0.76%)</title><rect x="10" y="549" width="8.9" height="15" fill="#F21617" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/sql_db.py:execute:232 (1 samples, 0.76%)</title><rect x="144.1" y="229" width="8.9" height="15" fill="#D4B617" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/api.py:call_kw:689 (1 samples, 0.76%)</title><rect x="1181.1" y="421" width="8.9" height="15" fill="#F38C21" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/modules/registry.py:new:85 (4 samples, 3.03%)</title><rect x="10" y="581" width="35.8" height="15" fill="#D3DC2B" rx="2" ry="2"/><text x="13" y="591.5" font-size="12" font-family="Verdana">/da..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>&lt;decorator-gen-37&gt;:check:2 (1 samples, 0.76%)</title><rect x="340.8" y="181" width="8.9" height="15" fill="#EA2A2B" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>&lt;frozen importlib._bootstrap&gt;:_find_and_load:971 (1 samples, 0.76%)</title><rect x="10" y="373" width="8.9" height="15" fill="#D46227" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/addons/web/controllers/main.py:_call_kw:916 (126 samples, 95.45%)</title><rect x="54.7" y="437" width="1126.4" height="15" fill="#E4622B" rx="2" ry="2"/><text x="57.7" y="447.5" font-size="12" font-family="Verdana">/datas/progs/odoo/addons/web/controllers/main.py:_call_kw:916</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/fields.py:digits:1209 (7 samples, 5.30%)</title><rect x="242.4" y="229" width="62.6" height="15" fill="#D5960E" rx="2" ry="2"/><text x="245.42" y="239.5" font-size="12" font-family="Verdana">/datas..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/usr/local/lib/python3.6/socketserver.py:__init__:696 (132 samples, 100.00%)</title><rect x="10" y="805" width="1180" height="15" fill="#F5472B" rx="2" ry="2"/><text x="13" y="815.5" font-size="12" font-family="Verdana">/usr/local/lib/python3.6/socketserver.py:__init__:696</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/service/model.py:wrapper:97 (127 samples, 96.21%)</title><rect x="54.7" y="517" width="1135.3" height="15" fill="#E33829" rx="2" ry="2"/><text x="57.7" y="527.5" font-size="12" font-family="Verdana">/datas/progs/odoo/odoo/service/model.py:wrapper:97</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/addons/base/ir/ir_http.py:_dispatch:208 (127 samples, 96.21%)</title><rect x="54.7" y="565" width="1135.3" height="15" fill="#F05B0E" rx="2" ry="2"/><text x="57.7" y="575.5" font-size="12" font-family="Verdana">/datas/progs/odoo/odoo/addons/base/ir/ir_http.py:_dispatch:208</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/http.py:__call__:1272 (132 samples, 100.00%)</title><rect x="10" y="661" width="1180" height="15" fill="#F58B07" rx="2" ry="2"/><text x="13" y="671.5" font-size="12" font-family="Verdana">/datas/progs/odoo/odoo/http.py:__call__:1272</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/usr/local/lib/python3.6/_weakrefset.py:__iter__:60 (2 samples, 1.52%)</title><rect x="966.5" y="197" width="17.9" height="15" fill="#F86430" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>&lt;frozen importlib._bootstrap&gt;:_find_and_load_unlocked:955 (1 samples, 0.76%)</title><rect x="10" y="357" width="8.9" height="15" fill="#F58716" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:_read_group_raw:1918 (1 samples, 0.76%)</title><rect x="439.1" y="245" width="8.9" height="15" fill="#CF0F35" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:filtered:4439 (38 samples, 28.79%)</title><rect x="617.9" y="229" width="339.7" height="15" fill="#DC3722" rx="2" ry="2"/><text x="620.88" y="239.5" font-size="12" font-family="Verdana">/datas/progs/odoo/odoo/models.py:filtered:4439</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/addons/stock_account/models/product.py:do_change_standard_price:156 (1 samples, 0.76%)</title><rect x="1172.1" y="373" width="9" height="15" fill="#D8A72A" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/api.py:__new__:735 (4 samples, 3.03%)</title><rect x="1109.5" y="213" width="35.8" height="15" fill="#EDA22A" rx="2" ry="2"/><text x="1112.55" y="223.5" font-size="12" font-family="Verdana">/da..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/service/server.py:worker_spawn:457 (132 samples, 100.00%)</title><rect x="10" y="901" width="1180" height="15" fill="#F64208" rx="2" ry="2"/><text x="13" y="911.5" font-size="12" font-family="Verdana">/datas/progs/odoo/odoo/service/server.py:worker_spawn:457</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/addons/stock/models/product.py:_compute_quantities_dict:125 (3 samples, 2.27%)</title><rect x="510.6" y="277" width="26.8" height="15" fill="#D6AD35" rx="2" ry="2"/><text x="513.61" y="287.5" font-size="12" font-family="Verdana">/..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:_read_from_database:2597 (1 samples, 0.76%)</title><rect x="868.2" y="117" width="8.9" height="15" fill="#FA9705" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/addons/stock/models/product.py:_compute_quantities_dict:134 (9 samples, 6.82%)</title><rect x="537.4" y="277" width="80.5" height="15" fill="#FBC926" rx="2" ry="2"/><text x="540.42" y="287.5" font-size="12" font-family="Verdana">/datas/pr..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/osv/expression.py:__init__:668 (1 samples, 0.76%)</title><rect x="412.3" y="213" width="8.9" height="15" fill="#EB3B03" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:_where_calc:3471 (1 samples, 0.76%)</title><rect x="421.2" y="229" width="9" height="15" fill="#FE0700" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:__iter__:4531 (1 samples, 0.76%)</title><rect x="903.9" y="117" width="9" height="15" fill="#E51F31" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/fields.py:cache_key:766 (2 samples, 1.52%)</title><rect x="725.2" y="85" width="17.8" height="15" fill="#D96708" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/fields.py:__set__:966 (8 samples, 6.06%)</title><rect x="1038" y="277" width="71.5" height="15" fill="#E8642A" rx="2" ry="2"/><text x="1041.03" y="287.5" font-size="12" font-family="Verdana">/datas/p..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:_read_group_raw:1851 (2 samples, 1.52%)</title><rect x="313.9" y="245" width="17.9" height="15" fill="#F88313" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:_prefetch_field:2565 (11 samples, 8.33%)</title><rect x="859.2" y="149" width="98.4" height="15" fill="#CDD42D" rx="2" ry="2"/><text x="862.24" y="159.5" font-size="12" font-family="Verdana">/datas/prog..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:check_access_rights:2781 (1 samples, 0.76%)</title><rect x="340.8" y="197" width="8.9" height="15" fill="#D4E127" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:_generate_translated_field:3553 (1 samples, 0.76%)</title><rect x="877.1" y="53" width="9" height="15" fill="#EC1711" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/usr/local/lib/python3.6/_weakrefset.py:__iter__:61 (1 samples, 0.76%)</title><rect x="519.5" y="149" width="9" height="15" fill="#EB5433" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/usr/local/lib/python3.6/site-packages/werkzeug/wsgi.py:__call__:599 (132 samples, 100.00%)</title><rect x="10" y="645" width="1180" height="15" fill="#E94D18" rx="2" ry="2"/><text x="13" y="655.5" font-size="12" font-family="Verdana">/usr/local/lib/python3.6/site-packages/werkzeug/wsgi.py:__call__:599</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:read_group:1830 (1 samples, 0.76%)</title><rect x="385.5" y="261" width="8.9" height="15" fill="#F3C302" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/http.py:response_wrap:512 (127 samples, 96.21%)</title><rect x="54.7" y="469" width="1135.3" height="15" fill="#DC5718" rx="2" ry="2"/><text x="57.7" y="479.5" font-size="12" font-family="Verdana">/datas/progs/odoo/odoo/http.py:response_wrap:512</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:_browse:4224 (1 samples, 0.76%)</title><rect x="948.6" y="69" width="9" height="15" fill="#FE0A32" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>&lt;decorator-gen-112&gt;:precision_get:2 (1 samples, 0.76%)</title><rect x="1047" y="213" width="8.9" height="15" fill="#E98C05" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/api.py:__new__:735 (1 samples, 0.76%)</title><rect x="63.6" y="325" width="9" height="15" fill="#E1130D" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:&lt;listcomp&gt;:4439 (38 samples, 28.79%)</title><rect x="617.9" y="213" width="339.7" height="15" fill="#F6A520" rx="2" ry="2"/><text x="620.88" y="223.5" font-size="12" font-family="Verdana">/datas/progs/odoo/odoo/models.py:&lt;listcomp&gt;:4..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/sql_db.py:execute:239 (1 samples, 0.76%)</title><rect x="439.1" y="213" width="8.9" height="15" fill="#D2B51E" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/addons/fetchmail/models/__init__.py:&lt;module&gt;:4 (1 samples, 0.76%)</title><rect x="10" y="293" width="8.9" height="15" fill="#EE6200" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:_read_group_resolve_many2one_fields:1943 (1 samples, 0.76%)</title><rect x="448" y="229" width="9" height="15" fill="#F0C026" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:_read_group_raw:1924 (5 samples, 3.79%)</title><rect x="340.8" y="245" width="44.7" height="15" fill="#FD1D0D" rx="2" ry="2"/><text x="343.76" y="255.5" font-size="12" font-family="Verdana">/dat..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/api.py:__call__:789 (4 samples, 3.03%)</title><rect x="349.7" y="181" width="35.8" height="15" fill="#D7D632" rx="2" ry="2"/><text x="352.7" y="191.5" font-size="12" font-family="Verdana">/da..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/usr/local/lib/python3.6/_weakrefset.py:__enter__:24 (1 samples, 0.76%)</title><rect x="188.8" y="165" width="8.9" height="15" fill="#DFB524" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/addons/web_editor/models/ir_http.py:_dispatch:21 (128 samples, 96.97%)</title><rect x="45.8" y="597" width="1144.2" height="15" fill="#DBCA22" rx="2" ry="2"/><text x="48.76" y="607.5" font-size="12" font-family="Verdana">/datas/progs/odoo/addons/web_editor/models/ir_http.py:_dispatch:21</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/sql_db.py:execute:232 (1 samples, 0.76%)</title><rect x="886.1" y="85" width="8.9" height="15" fill="#DE7622" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:_in_cache_without:4684 (1 samples, 0.76%)</title><rect x="135.2" y="325" width="8.9" height="15" fill="#F6140E" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/fields.py:_setup_attrs:446 (1 samples, 0.76%)</title><rect x="27.9" y="485" width="8.9" height="15" fill="#E67713" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/addons/http_routing/models/ir_http.py:_dispatch:325 (1 samples, 0.76%)</title><rect x="45.8" y="581" width="8.9" height="15" fill="#F42403" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/usr/local/lib/python3.6/enum.py:__call__:291 (1 samples, 0.76%)</title><rect x="45.8" y="373" width="8.9" height="15" fill="#DC6804" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/osv/query.py:_get_alias_mapping:75 (1 samples, 0.76%)</title><rect x="430.2" y="213" width="8.9" height="15" fill="#FB4E0A" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/addons/base/res/res_users.py:_get_company:217 (3 samples, 2.27%)</title><rect x="162" y="229" width="26.8" height="15" fill="#D8A201" rx="2" ry="2"/><text x="164.97" y="239.5" font-size="12" font-family="Verdana">/..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/service/wsgi_server.py:application_unproxied:154 (132 samples, 100.00%)</title><rect x="10" y="693" width="1180" height="15" fill="#DA5809" rx="2" ry="2"/><text x="13" y="703.5" font-size="12" font-family="Verdana">/datas/progs/odoo/odoo/service/wsgi_server.py:application_unproxied:154</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/api.py:__new__:736 (5 samples, 3.79%)</title><rect x="251.4" y="197" width="44.7" height="15" fill="#F72E0B" rx="2" ry="2"/><text x="254.36" y="207.5" font-size="12" font-family="Verdana">/dat..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/usr/local/lib/python3.6/inspect.py:getmembers:333 (1 samples, 0.76%)</title><rect x="18.9" y="517" width="9" height="15" fill="#E4BC1F" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/http.py:dispatch:1473 (128 samples, 96.97%)</title><rect x="45.8" y="629" width="1144.2" height="15" fill="#ED8C15" rx="2" ry="2"/><text x="48.76" y="639.5" font-size="12" font-family="Verdana">/datas/progs/odoo/odoo/http.py:dispatch:1473</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:_add_field:284 (1 samples, 0.76%)</title><rect x="36.8" y="501" width="9" height="15" fill="#F32A19" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/osv/expression.py:distribute_not:302 (1 samples, 0.76%)</title><rect x="403.3" y="197" width="9" height="15" fill="#E9D315" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:_browse:4224 (1 samples, 0.76%)</title><rect x="939.7" y="53" width="8.9" height="15" fill="#F8902A" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/api.py:__new__:747 (1 samples, 0.76%)</title><rect x="1002.3" y="213" width="8.9" height="15" fill="#CFB01E" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/osv/expression.py:to_sql:1271 (1 samples, 0.76%)</title><rect x="322.9" y="213" width="8.9" height="15" fill="#F42622" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>&lt;string&gt;:change_digit:10 (1 samples, 0.76%)</title><rect x="1047" y="229" width="8.9" height="15" fill="#D35C23" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/addons/http_routing/models/ir_http.py:_dispatch:397 (127 samples, 96.21%)</title><rect x="54.7" y="581" width="1135.3" height="15" fill="#FB200E" rx="2" ry="2"/><text x="57.7" y="591.5" font-size="12" font-family="Verdana">/datas/progs/odoo/addons/http_routing/models/ir_http.py:_dispatch:397</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/sql_db.py:wrapper:155 (1 samples, 0.76%)</title><rect x="439.1" y="229" width="8.9" height="15" fill="#E0B30C" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:_setup_base:2311 (1 samples, 0.76%)</title><rect x="27.9" y="533" width="8.9" height="15" fill="#DCA216" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/fields.py:__get__:2523 (1 samples, 0.76%)</title><rect x="54.7" y="357" width="8.9" height="15" fill="#F33209" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/modules/registry.py:__new__:61 (4 samples, 3.03%)</title><rect x="10" y="597" width="35.8" height="15" fill="#F46102" rx="2" ry="2"/><text x="13" y="607.5" font-size="12" font-family="Verdana">/da..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>&lt;frozen importlib._bootstrap&gt;:_find_and_load_unlocked:955 (1 samples, 0.76%)</title><rect x="10" y="485" width="8.9" height="15" fill="#EA3427" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/fields.py:compute_value:1015 (96 samples, 72.73%)</title><rect x="313.9" y="325" width="858.2" height="15" fill="#D66402" rx="2" ry="2"/><text x="316.94" y="335.5" font-size="12" font-family="Verdana">/datas/progs/odoo/odoo/fields.py:compute_value:1015</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/fields.py:cache_key:765 (2 samples, 1.52%)</title><rect x="707.3" y="85" width="17.9" height="15" fill="#F99217" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/fields.py:convert_to_cache:1230 (7 samples, 5.30%)</title><rect x="242.4" y="245" width="62.6" height="15" fill="#D57C23" rx="2" ry="2"/><text x="245.42" y="255.5" font-size="12" font-family="Verdana">/datas..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/sql_db.py:wrapper:155 (1 samples, 0.76%)</title><rect x="886.1" y="101" width="8.9" height="15" fill="#F75C27" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:_browse:4222 (2 samples, 1.52%)</title><rect x="796.7" y="69" width="17.8" height="15" fill="#FE3906" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/usr/local/lib/python3.6/_weakrefset.py:__iter__:61 (1 samples, 0.76%)</title><rect x="63.6" y="309" width="9" height="15" fill="#E4CF21" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:_read_group_resolve_many2one_fields:1944 (5 samples, 3.79%)</title><rect x="340.8" y="229" width="44.7" height="15" fill="#EBDD21" rx="2" ry="2"/><text x="343.76" y="239.5" font-size="12" font-family="Verdana">/dat..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:sudo:4310 (4 samples, 3.03%)</title><rect x="349.7" y="197" width="35.8" height="15" fill="#E9011C" rx="2" ry="2"/><text x="352.7" y="207.5" font-size="12" font-family="Verdana">/da..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>&lt;frozen importlib._bootstrap&gt;:_call_with_frames_removed:219 (1 samples, 0.76%)</title><rect x="10" y="309" width="8.9" height="15" fill="#EDB026" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/osv/expression.py:__leaf_to_sql:1197 (1 samples, 0.76%)</title><rect x="322.9" y="197" width="8.9" height="15" fill="#EF540C" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/osv/expression.py:to_sql:1271 (1 samples, 0.76%)</title><rect x="421.2" y="213" width="9" height="15" fill="#EE442F" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/cli/command.py:main:60 (132 samples, 100.00%)</title><rect x="10" y="997" width="1180" height="15" fill="#F4B416" rx="2" ry="2"/><text x="13" y="1007.5" font-size="12" font-family="Verdana">/datas/progs/odoo/odoo/cli/command.py:main:60</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:read:2516 (1 samples, 0.76%)</title><rect x="903.9" y="133" width="9" height="15" fill="#E35A26" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/usr/local/lib/python3.6/re.py:compile:233 (1 samples, 0.76%)</title><rect x="45.8" y="469" width="8.9" height="15" fill="#E79A20" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/addons/stock/models/product.py:_compute_quantities:83 (6 samples, 4.55%)</title><rect x="957.6" y="293" width="53.6" height="15" fill="#F38410" rx="2" ry="2"/><text x="960.58" y="303.5" font-size="12" font-family="Verdana">/data..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/addons/stock_account/models/product.py:do_change_standard_price:125 (9 samples, 6.82%)</title><rect x="54.7" y="373" width="80.5" height="15" fill="#E31106" rx="2" ry="2"/><text x="57.7" y="383.5" font-size="12" font-family="Verdana">/datas/pr..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>&lt;frozen importlib._bootstrap&gt;:_find_and_load:971 (1 samples, 0.76%)</title><rect x="10" y="501" width="8.9" height="15" fill="#FA2F0B" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:create:3278 (1 samples, 0.76%)</title><rect x="1172.1" y="341" width="9" height="15" fill="#F09120" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/sql_db.py:dbname:477 (1 samples, 0.76%)</title><rect x="993.3" y="197" width="9" height="15" fill="#E6D617" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/addons/product/models/product.py:name_get:376 (6 samples, 4.55%)</title><rect x="457" y="213" width="53.6" height="15" fill="#D5BF1F" rx="2" ry="2"/><text x="459.97" y="223.5" font-size="12" font-family="Verdana">/data..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/api.py:__call__:789 (3 samples, 2.27%)</title><rect x="510.6" y="181" width="26.8" height="15" fill="#FDA500" rx="2" ry="2"/><text x="513.61" y="191.5" font-size="12" font-family="Verdana">/..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/http.py:__call__:927 (127 samples, 96.21%)</title><rect x="54.7" y="485" width="1135.3" height="15" fill="#F0A023" rx="2" ry="2"/><text x="57.7" y="495.5" font-size="12" font-family="Verdana">/datas/progs/odoo/odoo/http.py:__call__:927</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/fields.py:__get__:948 (1 samples, 0.76%)</title><rect x="1181.1" y="277" width="8.9" height="15" fill="#CF4829" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:_add_magic_fields:330 (1 samples, 0.76%)</title><rect x="36.8" y="517" width="9" height="15" fill="#DB8010" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/modules/registry.py:&lt;dictcomp&gt;:201 (1 samples, 0.76%)</title><rect x="1172.1" y="245" width="9" height="15" fill="#FE0F28" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/fields.py:_compute_value:1006 (1 samples, 0.76%)</title><rect x="1181.1" y="309" width="8.9" height="15" fill="#E88B36" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:read_group:1828 (8 samples, 6.06%)</title><rect x="313.9" y="261" width="71.6" height="15" fill="#FBCD07" rx="2" ry="2"/><text x="316.94" y="271.5" font-size="12" font-family="Verdana">/datas/p..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/usr/local/lib/python3.6/site-packages/werkzeug/routing.py:bind:681 (1 samples, 0.76%)</title><rect x="45.8" y="501" width="8.9" height="15" fill="#E6471C" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/tools/misc.py:__init__:990 (1 samples, 0.76%)</title><rect x="331.8" y="229" width="9" height="15" fill="#ED3F11" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/fields.py:determine_value:1057 (1 samples, 0.76%)</title><rect x="135.2" y="341" width="8.9" height="15" fill="#DD8A08" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/addons/base/ir/ir_http.py:routing_map:238 (1 samples, 0.76%)</title><rect x="45.8" y="549" width="8.9" height="15" fill="#E40C0B" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/usr/local/lib/python3.6/site-packages/werkzeug/routing.py:compile:742 (1 samples, 0.76%)</title><rect x="45.8" y="485" width="8.9" height="15" fill="#EB481B" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/http.py:checked_call:332 (127 samples, 96.21%)</title><rect x="54.7" y="501" width="1135.3" height="15" fill="#F4CD18" rx="2" ry="2"/><text x="57.7" y="511.5" font-size="12" font-family="Verdana">/datas/progs/odoo/odoo/http.py:checked_call:332</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/osv/expression.py:to_sql:1280 (1 samples, 0.76%)</title><rect x="233.5" y="213" width="8.9" height="15" fill="#FA3C11" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/addons/web/controllers/main.py:_call_kw:916 (1 samples, 0.76%)</title><rect x="1181.1" y="437" width="8.9" height="15" fill="#D0A608" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/addons/product/models/product.py:name_get:376 (4 samples, 3.03%)</title><rect x="349.7" y="213" width="35.8" height="15" fill="#DBD936" rx="2" ry="2"/><text x="352.7" y="223.5" font-size="12" font-family="Verdana">/da..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:_inherits_join_calc:1973 (1 samples, 0.76%)</title><rect x="1181.1" y="165" width="8.9" height="15" fill="#FAB01E" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:_setup_base:2308 (1 samples, 0.76%)</title><rect x="18.9" y="533" width="9" height="15" fill="#D7CF1C" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/fields.py:__get__:948 (19 samples, 14.39%)</title><rect x="135.2" y="357" width="169.8" height="15" fill="#FA2619" rx="2" ry="2"/><text x="138.15" y="367.5" font-size="12" font-family="Verdana">/datas/progs/odoo/odo..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/modules/module.py:load_openerp_module:368 (1 samples, 0.76%)</title><rect x="10" y="517" width="8.9" height="15" fill="#E89C16" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/api.py:call_kw:689 (126 samples, 95.45%)</title><rect x="54.7" y="421" width="1126.4" height="15" fill="#F7A916" rx="2" ry="2"/><text x="57.7" y="431.5" font-size="12" font-family="Verdana">/datas/progs/odoo/odoo/api.py:call_kw:689</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/fields.py:digits:1209 (6 samples, 4.55%)</title><rect x="957.6" y="245" width="53.6" height="15" fill="#DE0321" rx="2" ry="2"/><text x="960.58" y="255.5" font-size="12" font-family="Verdana">/data..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:_where_calc:3471 (1 samples, 0.76%)</title><rect x="322.9" y="229" width="8.9" height="15" fill="#FEC130" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/http.py:__call__:1298 (132 samples, 100.00%)</title><rect x="10" y="677" width="1180" height="15" fill="#E81D1B" rx="2" ry="2"/><text x="13" y="687.5" font-size="12" font-family="Verdana">/datas/progs/odoo/odoo/http.py:__call__:1298</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/addons/account/models/account_move.py:create:126 (1 samples, 0.76%)</title><rect x="1172.1" y="357" width="9" height="15" fill="#F30725" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/api.py:__new__:735 (4 samples, 3.03%)</title><rect x="457" y="165" width="35.7" height="15" fill="#E0AC2D" rx="2" ry="2"/><text x="459.97" y="175.5" font-size="12" font-family="Verdana">/da..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/osv/expression.py:__init__:665 (1 samples, 0.76%)</title><rect x="403.3" y="213" width="9" height="15" fill="#EEE523" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/tools/cache.py:lookup:84 (1 samples, 0.76%)</title><rect x="340.8" y="165" width="8.9" height="15" fill="#E8350E" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/api.py:__new__:736 (2 samples, 1.52%)</title><rect x="492.7" y="165" width="17.9" height="15" fill="#CF5331" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/usr/local/lib/python3.6/socketserver.py:finish_request:361 (132 samples, 100.00%)</title><rect x="10" y="821" width="1180" height="15" fill="#F60B1B" rx="2" ry="2"/><text x="13" y="831.5" font-size="12" font-family="Verdana">/usr/local/lib/python3.6/socketserver.py:finish_request:361</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/osv/query.py:add_join:136 (1 samples, 0.76%)</title><rect x="877.1" y="37" width="9" height="15" fill="#EF6C2F" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/fields.py:set_all_attrs:360 (1 samples, 0.76%)</title><rect x="27.9" y="469" width="8.9" height="15" fill="#CFDB05" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/osv/expression.py:__init__:660 (1 samples, 0.76%)</title><rect x="394.4" y="213" width="8.9" height="15" fill="#F5D622" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/usr/local/lib/python3.6/re.py:_compile:301 (1 samples, 0.76%)</title><rect x="45.8" y="453" width="8.9" height="15" fill="#FE1301" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/fields.py:_compute_value:1008 (18 samples, 13.64%)</title><rect x="144.1" y="309" width="160.9" height="15" fill="#DBAD29" rx="2" ry="2"/><text x="147.09" y="319.5" font-size="12" font-family="Verdana">/datas/progs/odoo/od..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/fields.py:digits:1209 (7 samples, 5.30%)</title><rect x="1109.5" y="245" width="62.6" height="15" fill="#EBAE30" rx="2" ry="2"/><text x="1112.55" y="255.5" font-size="12" font-family="Verdana">/datas..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/api.py:get:959 (1 samples, 0.76%)</title><rect x="921.8" y="85" width="9" height="15" fill="#FAAD03" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/cli/server.py:run:175 (132 samples, 100.00%)</title><rect x="10" y="981" width="1180" height="15" fill="#CF8136" rx="2" ry="2"/><text x="13" y="991.5" font-size="12" font-family="Verdana">/datas/progs/odoo/odoo/cli/server.py:run:175</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/fields.py:determine_value:1059 (18 samples, 13.64%)</title><rect x="144.1" y="341" width="160.9" height="15" fill="#E40E19" rx="2" ry="2"/><text x="147.09" y="351.5" font-size="12" font-family="Verdana">/datas/progs/odoo/od..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:_read_from_database:2646 (1 samples, 0.76%)</title><rect x="895" y="117" width="8.9" height="15" fill="#E54111" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:search:1407 (6 samples, 4.55%)</title><rect x="188.8" y="261" width="53.6" height="15" fill="#F86213" rx="2" ry="2"/><text x="191.79" y="271.5" font-size="12" font-family="Verdana">/data..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/addons/stock_account/wizard/stock_change_standard_price.py:change_price:43 (126 samples, 95.45%)</title><rect x="54.7" y="389" width="1126.4" height="15" fill="#E42022" rx="2" ry="2"/><text x="57.7" y="399.5" font-size="12" font-family="Verdana">/datas/progs/odoo/addons/stock_account/wizard/stock_change_standard_price.py:change_price:43</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:compute_concurrency_field_with_access:356 (1 samples, 0.76%)</title><rect x="1181.1" y="293" width="8.9" height="15" fill="#CE3532" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/usr/local/lib/python3.6/_weakrefset.py:__iter__:60 (3 samples, 2.27%)</title><rect x="457" y="149" width="26.8" height="15" fill="#EE411A" rx="2" ry="2"/><text x="459.97" y="159.5" font-size="12" font-family="Verdana">/..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:_search:3674 (2 samples, 1.52%)</title><rect x="224.5" y="245" width="17.9" height="15" fill="#CEE502" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:read_group:1828 (3 samples, 2.27%)</title><rect x="510.6" y="261" width="26.8" height="15" fill="#FB110B" rx="2" ry="2"/><text x="513.61" y="271.5" font-size="12" font-family="Verdana">/..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/usr/local/lib/python3.6/_weakrefset.py:add:84 (1 samples, 0.76%)</title><rect x="1002.3" y="181" width="8.9" height="15" fill="#F98412" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/osv/expression.py:get_unaccent_wrapper:455 (1 samples, 0.76%)</title><rect x="313.9" y="197" width="9" height="15" fill="#F61433" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/api.py:__new__:735 (3 samples, 2.27%)</title><rect x="349.7" y="165" width="26.8" height="15" fill="#E92209" rx="2" ry="2"/><text x="352.7" y="175.5" font-size="12" font-family="Verdana">/..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/fields.py:__set__:966 (7 samples, 5.30%)</title><rect x="1109.5" y="277" width="62.6" height="15" fill="#F96615" rx="2" ry="2"/><text x="1112.55" y="287.5" font-size="12" font-family="Verdana">/datas..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/api.py:__new__:735 (1 samples, 0.76%)</title><rect x="1055.9" y="213" width="8.9" height="15" fill="#E7DA11" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/api.py:__call__:789 (3 samples, 2.27%)</title><rect x="162" y="197" width="26.8" height="15" fill="#E69818" rx="2" ry="2"/><text x="164.97" y="207.5" font-size="12" font-family="Verdana">/..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/tools/func.py:wrapper:68 (1 samples, 0.76%)</title><rect x="340.8" y="149" width="8.9" height="15" fill="#F68510" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/service/server.py:start:991 (132 samples, 100.00%)</title><rect x="10" y="949" width="1180" height="15" fill="#EB4E10" rx="2" ry="2"/><text x="13" y="959.5" font-size="12" font-family="Verdana">/datas/progs/odoo/odoo/service/server.py:start:991</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/modules/registry.py:field_sequence:200 (1 samples, 0.76%)</title><rect x="1172.1" y="261" width="9" height="15" fill="#EA592F" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/tools/func.py:wrapper:68 (1 samples, 0.76%)</title><rect x="340.8" y="117" width="8.9" height="15" fill="#D97D1B" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>&lt;string&gt;:change_digit:9 (3 samples, 2.27%)</title><rect x="1011.2" y="229" width="26.8" height="15" fill="#D4B032" rx="2" ry="2"/><text x="1014.21" y="239.5" font-size="12" font-family="Verdana">&lt;..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:sudo:4310 (6 samples, 4.55%)</title><rect x="457" y="197" width="53.6" height="15" fill="#DB5E2C" rx="2" ry="2"/><text x="459.97" y="207.5" font-size="12" font-family="Verdana">/data..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/api.py:__new__:736 (3 samples, 2.27%)</title><rect x="1145.3" y="213" width="26.8" height="15" fill="#DA980D" rx="2" ry="2"/><text x="1148.3" y="223.5" font-size="12" font-family="Verdana">/..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:_read_group_raw:1851 (4 samples, 3.03%)</title><rect x="394.4" y="245" width="35.8" height="15" fill="#E16827" rx="2" ry="2"/><text x="397.39" y="255.5" font-size="12" font-family="Verdana">/da..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:read:2520 (1 samples, 0.76%)</title><rect x="1181.1" y="389" width="8.9" height="15" fill="#D20022" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/addons/product/models/product.py:name_get:376 (3 samples, 2.27%)</title><rect x="510.6" y="213" width="26.8" height="15" fill="#DC2B22" rx="2" ry="2"/><text x="513.61" y="223.5" font-size="12" font-family="Verdana">/..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>&lt;string&gt;:&lt;module&gt;:4 (1 samples, 0.76%)</title><rect x="10" y="421" width="8.9" height="15" fill="#F76C1F" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/usr/local/lib/python3.6/socketserver.py:process_request:348 (132 samples, 100.00%)</title><rect x="10" y="837" width="1180" height="15" fill="#CD6331" rx="2" ry="2"/><text x="13" y="847.5" font-size="12" font-family="Verdana">/usr/local/lib/python3.6/socketserver.py:process_request:348</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/api.py:get_records:1009 (27 samples, 20.45%)</title><rect x="617.9" y="117" width="241.3" height="15" fill="#DF280E" rx="2" ry="2"/><text x="620.88" y="127.5" font-size="12" font-family="Verdana">/datas/progs/odoo/odoo/api.py:ge..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>&lt;frozen importlib._bootstrap&gt;:_find_and_load:971 (1 samples, 0.76%)</title><rect x="10" y="245" width="8.9" height="15" fill="#EE7332" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/tools/func.py:__get__:23 (1 samples, 0.76%)</title><rect x="1172.1" y="277" width="9" height="15" fill="#F92324" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:__getitem__:4657 (1 samples, 0.76%)</title><rect x="1181.1" y="373" width="8.9" height="15" fill="#F3BC04" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/usr/local/lib/python3.6/_weakrefset.py:__iter__:61 (2 samples, 1.52%)</title><rect x="162" y="165" width="17.8" height="15" fill="#EFA626" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/api.py:__new__:736 (7 samples, 5.30%)</title><rect x="72.6" y="325" width="62.6" height="15" fill="#EB0F17" rx="2" ry="2"/><text x="75.58" y="335.5" font-size="12" font-family="Verdana">/datas..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/osv/expression.py:__init__:660 (1 samples, 0.76%)</title><rect x="313.9" y="213" width="9" height="15" fill="#DB5C05" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/usr/local/lib/python3.6/_weakrefset.py:__iter__:61 (1 samples, 0.76%)</title><rect x="367.6" y="149" width="8.9" height="15" fill="#FE0B0C" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/api.py:user:798 (3 samples, 2.27%)</title><rect x="162" y="213" width="26.8" height="15" fill="#FB8F0D" rx="2" ry="2"/><text x="164.97" y="223.5" font-size="12" font-family="Verdana">/..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:_create:3435 (1 samples, 0.76%)</title><rect x="1172.1" y="325" width="9" height="15" fill="#D60C0E" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/fields.py:_compute_value:1006 (96 samples, 72.73%)</title><rect x="313.9" y="309" width="858.2" height="15" fill="#DF2E11" rx="2" ry="2"/><text x="316.94" y="319.5" font-size="12" font-family="Verdana">/datas/progs/odoo/odoo/fields.py:_compute_value:1006</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:_normalize_ids:5197 (1 samples, 0.76%)</title><rect x="743" y="69" width="9" height="15" fill="#E1C615" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/fields.py:setup_base:389 (1 samples, 0.76%)</title><rect x="27.9" y="501" width="8.9" height="15" fill="#FC892D" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:sudo:4310 (4 samples, 3.03%)</title><rect x="188.8" y="229" width="35.7" height="15" fill="#F1AB29" rx="2" ry="2"/><text x="191.79" y="239.5" font-size="12" font-family="Verdana">/da..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:with_context:4333 (8 samples, 6.06%)</title><rect x="63.6" y="357" width="71.6" height="15" fill="#FD7111" rx="2" ry="2"/><text x="66.64" y="367.5" font-size="12" font-family="Verdana">/datas/p..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/modules/loading.py:load_module_graph:121 (1 samples, 0.76%)</title><rect x="10" y="533" width="8.9" height="15" fill="#E05820" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:_browse:4218 (1 samples, 0.76%)</title><rect x="769.8" y="69" width="9" height="15" fill="#F9BC00" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>&lt;string&gt;:change_digit:9 (7 samples, 5.30%)</title><rect x="1109.5" y="229" width="62.6" height="15" fill="#E0772E" rx="2" ry="2"/><text x="1112.55" y="239.5" font-size="12" font-family="Verdana">&lt;strin..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/addons/base/res/ir_property.py:_get_domain:138 (3 samples, 2.27%)</title><rect x="162" y="261" width="26.8" height="15" fill="#F8480C" rx="2" ry="2"/><text x="164.97" y="271.5" font-size="12" font-family="Verdana">/..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/fields.py:compute_value:1015 (18 samples, 13.64%)</title><rect x="144.1" y="325" width="160.9" height="15" fill="#F84F10" rx="2" ry="2"/><text x="147.09" y="335.5" font-size="12" font-family="Verdana">/datas/progs/odoo/od..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>&lt;string&gt;:change_digit:9 (6 samples, 4.55%)</title><rect x="1055.9" y="229" width="53.6" height="15" fill="#F6282A" rx="2" ry="2"/><text x="1058.91" y="239.5" font-size="12" font-family="Verdana">&lt;stri..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/usr/local/lib/python3.6/site-packages/werkzeug/serving.py:execute:181 (132 samples, 100.00%)</title><rect x="10" y="725" width="1180" height="15" fill="#EEDC11" rx="2" ry="2"/><text x="13" y="735.5" font-size="12" font-family="Verdana">/usr/local/lib/python3.6/site-packages/werkzeug/serving.py:execute:181</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/api.py:&lt;listcomp&gt;:1010 (27 samples, 20.45%)</title><rect x="617.9" y="101" width="241.3" height="15" fill="#F3B71C" rx="2" ry="2"/><text x="620.88" y="111.5" font-size="12" font-family="Verdana">/datas/progs/odoo/odoo/api.py:&lt;l..</text></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/addons/web/controllers/main.py:call_kw:924 (1 samples, 0.76%)</title><rect x="1181.1" y="453" width="8.9" height="15" fill="#D24720" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/models.py:_setup_base:2312 (1 samples, 0.76%)</title><rect x="36.8" y="533" width="9" height="15" fill="#DD6829" rx="2" ry="2"/></g><g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)"><title>/datas/progs/odoo/odoo/fields.py:digits:1209 (7 samples, 5.30%)</title><rect x="1047" y="245" width="62.5" height="15" fill="#CD001F" rx="2" ry="2"/><text x="1049.97" y="255.5" font-size="12" font-family="Verdana">/datas..</text></g></svg> \ No newline at end of file
diff --git a/doc/howtos/profilecode.rst b/doc/howtos/profilecode.rst
deleted file mode 100644
index dcb86338c8a..00000000000
--- a/doc/howtos/profilecode.rst
+++ /dev/null
@@ -1,131 +0,0 @@
-===================
-Profiling Odoo code
-===================
-
-.. warning::
-
- This tutorial requires :ref:`having installed Odoo <setup/install>`
- and :doc:`writing Odoo code <backend>`
-
-Graph a method
-==============
-
-Odoo embeds a profiler of code. This embedded profiler output can be used to
-generate a graph of calls triggered by the method, number of queries, percentage
-of time taken in the method itself as well as the time that the method took and
-its sub-called methods.
-
-.. code:: python
-
- from odoo.tools.misc import profile
- [...]
- @profile('/temp/prof.profile')
- def mymethod(...)
-
-This produces a file called /temp/prof.profile
-
-A tool called *gprof2dot* will produce a graph with this result:
-
-.. code:: bash
-
- gprof2dot -f pstats -o /temp/prof.xdot /temp/prof.profile
-
-A tool called *xdot* will display the resulting graph:
-
-.. code:: bash
-
- xdot /temp/prof.xdot
-
-Log a method
-============
-
-Another profiler can be used to log statistics on a method:
-
-.. code:: python
-
- from odoo.tools.profiler import profile
- [...]
- @profile
- @api.model
- def mymethod(...):
-
-The statistics will be displayed into the logs once the method to be analysed is
-completely reviewed.
-
-.. code:: bash
-
- 2018-03-28 06:18:23,196 22878 INFO openerp odoo.tools.profiler:
- calls queries ms
- project.task ------------------------ /home/odoo/src/odoo/addons/project/models/project.py, 638
-
- 1 0 0.02 @profile
- @api.model
- def create(self, vals):
- # context: no_log, because subtype already handle this
- 1 0 0.01 context = dict(self.env.context, mail_create_nolog=True)
-
- # for default stage
- 1 0 0.01 if vals.get('project_id') and not context.get('default_project_id'):
- context['default_project_id'] = vals.get('project_id')
- # user_id change: update date_assign
- 1 0 0.01 if vals.get('user_id'):
- vals['date_assign'] = fields.Datetime.now()
- # Stage change: Update date_end if folded stage
- 1 0 0.0 if vals.get('stage_id'):
- vals.update(self.update_date_end(vals['stage_id']))
- 1 108 631.8 task = super(Task, self.with_context(context)).create(vals)
- 1 0 0.01 return task
-
- Total:
- 1 108 631.85
-
-Dump stack
-==========
-
-Sending the SIGQUIT signal to an Odoo process (only available on POSIX) makes
-this process output the current stack trace to log, with info level. When an
-odoo process seems stucked, sending this signal to the process permit to know
-what the process is doing, and letting the process continue his job.
-
-Tracing code execution
-======================
-
-Instead of sending the SIGQUIT signal to an Odoo process often enough, to check
-where the processes are performing worse than expected, we can use the `py-spy`_ tool to
-do it for us.
-
-Install py-spy
---------------
-
-.. code:: bash
-
- python3 -m pip install py-spy
-
-Record executed code
---------------------
-
-As py-spy is installed, we now record the executed code lines.
-This tool will record, multiple times a second, the stacktrace of the process.
-
-.. code:: bash
-
- # record to raw file
- py-spy record -o profile.json -f speedscope --pid <PID>
-
- # OR record directly to svg
- py-spy record -o profile.svg --pid <PID>
-
-where <PID> is the process ID of the odoo process you want to graph.
-
-To open profile.json you can use online tool `speedscope.app`_.
-
-To open profile.svg you should use browser, because other viewer may not
-support interactive part.
-
-
-.. image:: profile/flamegraph.svg
-
-
-.. _py-spy: https://github.com/benfred/py-spy
-
-.. _speedscope.app: https://www.speedscope.app/
diff --git a/doc/howtos/theme_tutorial_assets/img/Intro.jpg b/doc/howtos/theme_tutorial_assets/img/Intro.jpg
deleted file mode 100644
index 62c6c3625ab..00000000000
--- a/doc/howtos/theme_tutorial_assets/img/Intro.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/howtos/theme_tutorial_assets/img/after-menu.png b/doc/howtos/theme_tutorial_assets/img/after-menu.png
deleted file mode 100755
index cccb40e28ef..00000000000
--- a/doc/howtos/theme_tutorial_assets/img/after-menu.png
+++ /dev/null
Binary files differ
diff --git a/doc/howtos/theme_tutorial_assets/img/cms.jpg b/doc/howtos/theme_tutorial_assets/img/cms.jpg
deleted file mode 100755
index 00ed6bb8516..00000000000
--- a/doc/howtos/theme_tutorial_assets/img/cms.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/howtos/theme_tutorial_assets/img/def_structure.jpg b/doc/howtos/theme_tutorial_assets/img/def_structure.jpg
deleted file mode 100644
index 0af442123a8..00000000000
--- a/doc/howtos/theme_tutorial_assets/img/def_structure.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/howtos/theme_tutorial_assets/img/functionalities.jpg b/doc/howtos/theme_tutorial_assets/img/functionalities.jpg
deleted file mode 100755
index ef99c10d334..00000000000
--- a/doc/howtos/theme_tutorial_assets/img/functionalities.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/howtos/theme_tutorial_assets/img/page.jpg b/doc/howtos/theme_tutorial_assets/img/page.jpg
deleted file mode 100755
index 296f3cd5b5d..00000000000
--- a/doc/howtos/theme_tutorial_assets/img/page.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/howtos/theme_tutorial_assets/img/page_structure.jpg b/doc/howtos/theme_tutorial_assets/img/page_structure.jpg
deleted file mode 100755
index f2a991a3311..00000000000
--- a/doc/howtos/theme_tutorial_assets/img/page_structure.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/howtos/theme_tutorial_assets/img/restart.png b/doc/howtos/theme_tutorial_assets/img/restart.png
deleted file mode 100644
index 54fc03c45f6..00000000000
--- a/doc/howtos/theme_tutorial_assets/img/restart.png
+++ /dev/null
Binary files differ
diff --git a/doc/howtos/theme_tutorial_assets/img/seo_promote.png b/doc/howtos/theme_tutorial_assets/img/seo_promote.png
deleted file mode 100644
index 54ca048eac0..00000000000
--- a/doc/howtos/theme_tutorial_assets/img/seo_promote.png
+++ /dev/null
Binary files differ
diff --git a/doc/howtos/theme_tutorial_assets/img/seo_snippet_good.png b/doc/howtos/theme_tutorial_assets/img/seo_snippet_good.png
deleted file mode 100644
index 4c23455069f..00000000000
--- a/doc/howtos/theme_tutorial_assets/img/seo_snippet_good.png
+++ /dev/null
Binary files differ
diff --git a/doc/howtos/theme_tutorial_assets/img/seo_snippet_wrong.png b/doc/howtos/theme_tutorial_assets/img/seo_snippet_wrong.png
deleted file mode 100644
index 235b6982396..00000000000
--- a/doc/howtos/theme_tutorial_assets/img/seo_snippet_wrong.png
+++ /dev/null
Binary files differ
diff --git a/doc/howtos/theme_tutorial_assets/img/services_page_menu.png b/doc/howtos/theme_tutorial_assets/img/services_page_menu.png
deleted file mode 100755
index 6098fbdbb6f..00000000000
--- a/doc/howtos/theme_tutorial_assets/img/services_page_menu.png
+++ /dev/null
Binary files differ
diff --git a/doc/howtos/theme_tutorial_assets/img/services_page_nostyle.png b/doc/howtos/theme_tutorial_assets/img/services_page_nostyle.png
deleted file mode 100755
index daf08f43b62..00000000000
--- a/doc/howtos/theme_tutorial_assets/img/services_page_nostyle.png
+++ /dev/null
Binary files differ
diff --git a/doc/howtos/theme_tutorial_assets/img/services_page_styled.png b/doc/howtos/theme_tutorial_assets/img/services_page_styled.png
deleted file mode 100755
index bd66b70e5d9..00000000000
--- a/doc/howtos/theme_tutorial_assets/img/services_page_styled.png
+++ /dev/null
Binary files differ
diff --git a/doc/howtos/theme_tutorial_assets/img/snippet.jpg b/doc/howtos/theme_tutorial_assets/img/snippet.jpg
deleted file mode 100755
index 9bd37ff07fd..00000000000
--- a/doc/howtos/theme_tutorial_assets/img/snippet.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/howtos/theme_tutorial_assets/img/snippet_bar.png b/doc/howtos/theme_tutorial_assets/img/snippet_bar.png
deleted file mode 100755
index 3a4666a104b..00000000000
--- a/doc/howtos/theme_tutorial_assets/img/snippet_bar.png
+++ /dev/null
Binary files differ
diff --git a/doc/howtos/theme_tutorial_assets/img/snippet_custom_method.png b/doc/howtos/theme_tutorial_assets/img/snippet_custom_method.png
deleted file mode 100644
index b880055cde1..00000000000
--- a/doc/howtos/theme_tutorial_assets/img/snippet_custom_method.png
+++ /dev/null
Binary files differ
diff --git a/doc/howtos/theme_tutorial_assets/img/snippet_default.png b/doc/howtos/theme_tutorial_assets/img/snippet_default.png
deleted file mode 100755
index 042e8f770e6..00000000000
--- a/doc/howtos/theme_tutorial_assets/img/snippet_default.png
+++ /dev/null
Binary files differ
diff --git a/doc/howtos/theme_tutorial_assets/img/snippet_options.png b/doc/howtos/theme_tutorial_assets/img/snippet_options.png
deleted file mode 100755
index bda2e4118f1..00000000000
--- a/doc/howtos/theme_tutorial_assets/img/snippet_options.png
+++ /dev/null
Binary files differ
diff --git a/doc/howtos/theme_tutorial_assets/img/snippet_options2.png b/doc/howtos/theme_tutorial_assets/img/snippet_options2.png
deleted file mode 100755
index 531acd103f9..00000000000
--- a/doc/howtos/theme_tutorial_assets/img/snippet_options2.png
+++ /dev/null
Binary files differ
diff --git a/doc/howtos/theme_tutorial_assets/img/styles.jpg b/doc/howtos/theme_tutorial_assets/img/styles.jpg
deleted file mode 100755
index d8756d1f63b..00000000000
--- a/doc/howtos/theme_tutorial_assets/img/styles.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/howtos/theme_tutorial_assets/img/theme_folder.jpg b/doc/howtos/theme_tutorial_assets/img/theme_folder.jpg
deleted file mode 100755
index 066e85c6158..00000000000
--- a/doc/howtos/theme_tutorial_assets/img/theme_folder.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/howtos/theme_tutorial_assets/img/upgrade_module.png b/doc/howtos/theme_tutorial_assets/img/upgrade_module.png
deleted file mode 100644
index 3806cfb9bd5..00000000000
--- a/doc/howtos/theme_tutorial_assets/img/upgrade_module.png
+++ /dev/null
Binary files differ
diff --git a/doc/howtos/themes.rst b/doc/howtos/themes.rst
deleted file mode 100644
index 5cdfd20181e..00000000000
--- a/doc/howtos/themes.rst
+++ /dev/null
@@ -1,1117 +0,0 @@
-:banner: banners/build_a_theme.jpg
-
-=====================
-Theme Tutorial
-=====================
-
-.. warning::
-
- This tutorial provides a great overview of what you can do creating an
- Odoo theme. It is however incomplete. We are currently working on a new
- detailed theme tutorial, come back here soon to unleash the true power of
- Odoo themes!
-
-.. rst-class:: lead
-
-Odoo celebrates freedom. Freedom for the designer to go further and
-freedom for the user to customize everything according to their needs.
-
-Ready to create your own theme? Great. Here are some things you should know before you begin. This tutorial is a guide to creating an Odoo theme.
-
-.. image:: theme_tutorial_assets/img/Intro.jpg
-
-
-An introduction for web designers
-=================================
-
-If you are a web designer using Odoo for the first time, you are in the right place.
-This introduction will outline the basics of Odoo theme creation. Odoo’s team has created a framework that’s powerful and easy to use.
-
-From common CMS to Odoo
------------------------
-
-.. note::
-
- If you always think and work in the same way, you’ll probably get the same results. If you want something completely new, then try something different.
-
-..
-
- Where is my header.php file?
-
-This is usually the first question from a web designer used to working with Wordpress or Joomla and coming to Odoo for the first time.
-
-.. container:: row
-
- .. container:: col-sm-4
-
- .. image:: theme_tutorial_assets/img/cms.jpg
-
- .. container:: col-sm-7
-
- Indeed, when using common CMSs, you have to code several files (like header.php, page.php, post.php, etc.) in order to create a basic structure for your website. With those systems, this base structure acts as a design foundation that you have to update over time to ensure compatibility within your CMS. So, even after you have spent hours coding the files, you have not even started on the design yet.
-
- This **does not** apply to creating Odoo themes.
-
-
-.. note::
- We think that theme design should be simple (and powerful). When we created our Website Builder, we decided to start from scratch instead of relying on what already existed. This approach gave us the freedom to focus on the things that are really important for designers: styles, content and the logic behind them. No more struggling with technical stuff.
-
-Odoo default theme structure
-----------------------------
-
-.. container:: row
-
- .. container:: col-sm-8
-
- Odoo comes with a default website structure.
- It is a very basic “theme” that provides minimal structure and layout. When you create a new theme, you are actually **extending** this.
- Indeed it’s always enabled in your setup and it acts exactly like the CMS’s base structure we mentioned above, except that you don’t have to create or maintain it.
- It will upgrade automatically within your Odoo installation and, since it is included in the Website Builder module, everything is smoothly integrated by default.
-
- As a result, you are totally free to focus on design while this structure does the job of providing integrations and functionality.
-
- .. container:: col-sm-4
-
- .. image:: theme_tutorial_assets/img/def_structure.jpg
-
-.. container:: row
-
- .. container:: col-md-6
-
- **Main features:**
-
- * Basic layouts for pages, blog, eCommerce and much more
- * Website Builder integration
- * Basic Snippets
- * Automatic Sass compiling
- * Automatic Js and CSS minification and combination
-
- .. container:: col-md-6
-
- **Main technologies:**
-
- * Twitter Bootstrap
- * jQuery
- * jQuery UI
- * underscore.js
-
-Thinking "modular"
-==================
-
-An Odoo theme is not a folder containing HTML or PHP files, it’s a modular framework written in XML. Never worked with XML files before? Don’t worry, after following the tutorial, you’ll be able to create your first theme with only basic knowledge of HTML.
-
-Using classical web design workflows, you usually code the layout of the entire page. The result of this is a “static” web page. You can update the content, of course, but your client will need you to work on making even basic changes.
-
-Creating themes for Odoo is a total change of perspective. Instead of defining the complete layout for a page, you can create blocks (snippets) and let the user choose where to “drag&drop” them, creating the page layout on their own.
-We call this modular design.
-
-Imagine an Odoo theme as a “list” of elements and options that you have to create or extend.
-As a designer, your goal is to style these elements in order to achieve a wonderful result, regardless of where the end user chooses to place them.
-
-Let’s take a tour of our “list” elements:
-
-.. container:: row
-
- .. figure:: theme_tutorial_assets/img/snippet.jpg
- :figclass: col-sm-6
-
- Snippets (or building-blocks)
-
- A piece of HTML code. The user will drag&drop, modify and combine them using our built-in Website Builder interface. You can define sets of options and styles for each snippet. The user will choose from them according to their needs.
-
- .. figure:: theme_tutorial_assets/img/page.jpg
- :figclass: col-sm-6
-
- Pages
-
- These are normal web pages, except that they will be editable by the final user and that you can define an empty area that the user can “fill” by dragging snippets into it.
-
-.. raw:: html
-
- <div class="clearfix themes"></div>
-
-.. container:: row
-
- .. figure:: theme_tutorial_assets/img/styles.jpg
- :figclass: col-sm-6
-
- Styles
-
- Styles are defined using SCSS files (or you can use standard CSS files). You can define a style as **default** or **optional**. The default styles are always active in your theme, the optional styles can be enabled or disabled by the user.
-
- .. figure:: theme_tutorial_assets/img/functionalities.jpg
- :figclass: col-sm-6
-
- Functionalities
-
- Thanks to Odoo’s modularity, everything can be personalized even more. This means there are endless possibilities for your creativity. Adding functionalities is easy and it’s simple to provide the end user with customizable options.
-
-
-Odoo's XML files, an overview
------------------------------
-
-Any Odoo XML file starts with encoding specifications.
-After that, you have to write your code inside a ``<odoo>`` tag.
-
-.. code-block:: xml
-
- [XML]
- <?xml version="1.0" encoding="utf-8" ?>
- <odoo>
-  
-   ## YOUR CODE HERE
-  
- </odoo>
-
-Almost every element and option that you create has to be placed inside a ``<template>`` tag, like in this example.
-
-.. code-block:: xml
-
- [XML]
- <template id="my_title" name="My title">
- <h1>This is an HTML block</h1>
- <h2 class="lead">And this is a subtitle</h2>
- </template>
-
-.. important::
-
- don't misunderstand what ``template`` means. A template tag only
- defines a piece of html code or options - but it does not
- necessarily coincide with a visual arrangement of elements.
-
-The previous code defines a title, but it will not be displayed
-anywhere because that *template* is not associated with any part of
-the **Odoo default structure**. In order to do that you can use
-**xpath**, **qWeb** or a combination of both.
-
-Keep reading the tutorial to learn to how properly extend it with your own code.
-
-
-Create a theme module
-======================
-
-Odoo’s themes are packaged like modules. Even if you are designing a very simple website for your company or client, you need to package the theme like an Odoo module.
-
-``main folder``
- Create a folder and name it like this: ``theme_`` followed by your
- theme's name.
-
-``__manifest__.py``
- Create an empty document and save it to your folder as
- ``__manifest__.py``. This will contain the configuration info for
- your theme.
-
-``__init__.py``
- Create another empty file and name it ``__init__.py``. It's a
- mandatory system file. Create and leave it blank.
-
-``views`` and ``static`` folders
- Create them in the main folder. In ``views`` you'll place your xml
- files that define your snippets, your pages and your
- options. ``static`` folder is the right place for your style ,
- images and custom js code.
-
-.. important::
-
- Use two underscore characters at the beginning
- and two at the end of odoo and init file names.
-
-The final result should be like this:
-
-.. image:: theme_tutorial_assets/img/theme_folder.jpg
-
-Edit ``__manifest__.py``
-------------------------
-
-Open the ``__manifest__.py`` you created and copy/paste the following:
-
-.. code-block:: python
-
- {
- 'name': 'Tutorial theme',
- 'description': 'A description for your theme.',
- 'version': '1.0',
- 'author': 'Your name',
- 'category': 'Theme/Creative',
-
- 'depends': ['website', 'website_theme_install'],
- 'data': [
- ],
- }
-
-Replace the first four property’s values with anything you like.
-These values will be used to identify your new theme in Odoo’s backend.
-
-``category`` defines your module category (always “Theme”) and, after a slash, the subcategory. You can use one subcategory from the Odoo Apps categories list. (https://www.odoo.com/apps/themes)
-
-``depends`` specifies the modules needed by our theme to work properly. For our tutorial theme, we only need website and website_theme_install to install/update.
-If you need blogging or eCommerce features as well, you have to add those modules too.
-If you plan to offer your theme to the majority of users, it is however recommended that you only depend on website and website_theme_install for the base of your theme. You can then create a second theme, which is an extension of the first one and another Odoo feature like the eCommerce.
-
-.. code-block:: python
-
- 'depends': ['theme_tutorial', 'website_sale'],
-
-The ``data`` property will contain the xml files list. Right now it’s empty, but we will add any new files created.
-
-
-Installing your theme
----------------------
-
-To install your theme, you just place your theme folder inside addons in your Odoo installation.
-
-After that, navigate to the Odoo **Website** module, go to
-:menuselection:`Configuration --> Settings`.
-
-Under **Website** section click the **Pick a Theme** button, then hover over
-your theme and click **Use this theme**.
-
-Update your theme
------------------
-
-Since XML files are only loaded when you install the theme, you will have to force reloading every time you make changes on an xml file.
-
-To do that, click on the Upgrade button in the theme selection screen.
-
-.. image:: theme_tutorial_assets/img/restart.png
-
-Structure of an Odoo page
-=========================
-
-An Odoo page is the visual result of a combination of 2 kind of elements, **cross-pages** and **unique**.
-By default, Odoo provides you with a **Header** and a **Footer** (cross-pages) and a unique main element that contains the content that makes your page unique.
-
-.. note::
-
- Cross-pages elements will be the same on every page. Unique elements are related to a specific page only.
-
-.. image:: theme_tutorial_assets/img/page_structure.jpg
-
-To inspect the default layout, simply create a new page using the
-Website Builder. Click on :menuselection:`New --> New Page` and
-add a page name. Inspect the page using your browser.
-
-.. code-block:: html
-
- <div id=“wrapwrap”>
- <header/>
- <main/>
- <footer/>
- </div>
-
-
-Add Styles
-==========
-
-Introduction
-------------
-
-The most important feature or your theme should be the style it provides.
-Odoo includes Bootstrap by default. This means that you can take advantage of all Bootstrap styles and layout functionalities out of the box.
-
-Of course Bootstrap is not enough if you want to provide a unique design. The following steps will guide you through how to add custom styles to your theme.
-The final result won't be pretty, but will provide you with enough information to build upon on your own.
-
-Let’s start by creating an empty file called **style.scss** and place it in a folder called **scss** in your static folder.
-Let's add an example rule which adds a top border on the footer. Copy and paste it, then save the file.
-
-.. code-block:: scss
-
- footer {
- border-top: 5px solid theme-color('primary');
- }
-
-Our file is ready but it is not included in our theme yet.
-
-Let’s navigate to the view folder and create an XML file called *assets.xml*.
-Add the default Odoo xml markup as seen before then copy/paste the following
-code between the Odoo tags. Remember to replace ``theme_tutorial`` with your
-theme’s main folder name.
-
-.. code-block:: xml
-
- <template id="assets_frontend" name="My style" inherit_id="website.assets_frontend">
- <xpath expr="link[last()]" position="after">
- <link rel="stylesheet" type="text/scss" href="/theme_tutorial/static/scss/style.scss"/>
- </xpath>
- </template>
-
-We just created a template specifying our scss file. As you can see,
-our template has a special attribute called ``inherit_id``. This
-attribute tells Odoo that our template is referring to another one in
-order to operate.
-
-In this case, we are referring to ``assets_frontend`` template,
-located in the ``website`` module. ``assets_frontend`` specifies the
-list of assets loaded by the website builder and our goal is to add
-our scss file to this list.
-
-This can be achieved using xpath with the attributes
-``expr="link[last()]"`` and ``position="after"``, which means "*take my
-style file and place it after the last link in the list of
-assets*".
-
-Placing it after the last one, we ensure that our file will
-be loaded at the end and takes priority.
-
-Finally add **assets.xml** in your **__manifest__.py** file in the data section.
-
-Update your theme.
-
-.. image:: theme_tutorial_assets/img/restart.png
-
-
-Our scss file is now included in our theme, it will be automatically compiled, minified and combined with all Odoo’s assets.
-
-You can now see the beautiful footer border on the website.
-
-
-Advanced tips for styling
--------------------------
-
-In the introduction, we saw how to add a basic file of CSS rules into the
-system to extend the website. This is actually the last step you should need to
-add style to your theme.
-
-The Odoo website builder already allows the user to create pages by adding a
-large variety of default well-designed blocks. It also allows a large set of
-customization possibilities. What may not be straightforward for the user is to
-combine all of those options to make something really beautiful. This is where
-your theme can shine. First try to construct the spirit of your theme by
-enabling a nice set of Odoo default options. This also allows you to ensure two
-things:
-
-- You do not re-invent something which already exists. If Odoo provides an
- option to have a border on the footer, don't recode it yourself. Enable it,
- then extend it if needed.
-
-- You ensure that the user can still use all of Odoo features with your theme.
- Again, if Odoo provides an option to have a border on the footer and that you
- recode it yourself, you may break the default option or make it useless,
- making the user have a bad experience. Your option might also not work as well
- with all the other Odoo features relying on it.
-
-So here are the steps to create a robust and consistent style for your theme:
-
-\(1) Set the values for Odoo-provided SCSS variables
-
-Odoo declares many CSS rules, most being entirely customizable by overridding
-the related SCSS variables. First, create a new file called primary_variables.scss
-and add it the same way as the style.scss file. The only difference it that
-you won't add it in the ``assets_frontend`` template but in the ``_assets_primary_variables``
-template.
-
-.. code-block:: xml
-
- <template id="_assets_primary_variables" name="My SCSS variables" inherit_id="website._assets_primary_variables">
- <xpath expr="link[last()]" position="after">
- <link rel="stylesheet" type="text/scss" href="/theme_tutorial/static/scss/primary_variables.scss"/>
- </xpath>
- </template>
-
-
-.. important::
-
- That file must only contain definition and overrides of SCSS variables and
- mixins.
-
-Add those:
-
-.. code-block:: scss
-
- $o-color-palettes: (
- (
- 'o-color-1': #85AFA8,
- 'o-color-2': #7E566B,
- 'o-color-3': #85909A,
- 'o-color-4': #969397,
- 'o-color-5': #422335,
- ),
- (
- 'o-color-1': #54787D,
- 'o-color-2': #6B9997,
- 'o-color-3': #615145,
- 'o-color-4': #C6CCA5,
- 'o-color-5': #412342,
- ),
- );
-
-This defines two color palettes for the user to choose from. Odoo relies
-on five named colors to be used by the website builder. By defining those in
-your theme, you ensure a consistent colored Odoo theme. Starting with Odoo 14.0,
-a lot more variable are there for you to customize.
-
-.. note::
-
- All variables defined through those "palettes" SCSS maps can later be
- customized by the users themselves.
-
-\(2) Set the values for Bootstrap variables that Odoo do not surcharge
-
-If Odoo does not provide the variable you are looking for, then try to find a
-Bootstrap variable which allows it. Indeed all Odoo layouts respect Bootstrap
-structures and use Bootstrap components or extensions of them. So if you
-customize a bootstrap variable, you add a generic style for the whole user
-website.
-
-Bootstrap values **must** not be overridden in the primary_variables.scss file but
-in another dedicated file, extending the ``_assets_frontend_helpers`` template.
-
-.. code-block:: xml
-
- <template id="_assets_frontend_helpers" inherit_id="website._assets_frontend_helpers">
- <xpath expr="//link[last()]" position="after">
- <link rel="stylesheet" type="text/scss" href="/theme_tutorial/static/src/scss/bootstrap_overridden.scss"/>
- </xpath>
- </template>
-
-With for example:
-
-.. code-block:: scss
-
- $dropdown-min-width: 200px;
-
-.. important::
-
- Make sure to not override Bootstrap variables which depend on Odoo variables
- of step (1). Otherwise, you might break the possibility for the user to
- customize them using the Odoo website builder.
-
-\(3) Add your own CSS rules as seen in the introduction
-
-You may also want to design your snippet first, as we will see in a later
-section of this tutorial.
-
-
-Extend Odoo Layout
-==================
-
-By default, Odoo header contains a responsive navigation menu and the company’s logo. You can easily add new elements or style the existing one.
-
-To do so, create a **layout.xml** file in your **views** folder and add the default Odoo xml markup.
-
-Then copy-pasting the following code.
-
-.. code-block:: xml
-
- <!-- Customize post-header -->
- <template id="custom_message" inherit_id="website.layout" name="Custom Header">
- <!-- Add an element after the top menu -->
- <xpath expr="//div[@id='wrapwrap']/main" position="before">
- <div class="container">
- <div class="alert alert-info mt16" role="alert">
- <strong>Welcome</strong> in our website!
- </div>
- </div>
- </xpath>
- </template>
-
-This xpath will add a welcome message just before the page content. You can do
-a lot more of thing with xpath and qweb, check the related doc for more details.
-
-.. warning::
-
- Be careful replacing default elements attributes. As your theme will extend the default one,
- your changes will take priority in any future Odoo’s update.
-
-The last step is to add layout.xml to the list of xml files used by
-the theme. To do that, edit your ``__manifest__.py`` file like this
-
-.. code-block:: python
-
- 'data': [ 'views/layout.xml' ],
-
-Update your theme
-
-.. image:: theme_tutorial_assets/img/restart.png
-
-Great! We successfully added an id to the
-header and an element after the navigation menu. These changes will be
-applied to each page of the website.
-
-.. image:: theme_tutorial_assets/img/after-menu.png
- :class: shadow-0
-
-Create a specific page layout
-=============================
-
-Imagine that we want to create a specific layout for a Services page.
-For this page, we need to add a list of services to the top and give the client the possibility of setting the rest of the page’s layout using snippets.
-
-Inside your *views* folder, create a **pages.xml** file and add the
-default Odoo markup. Inside ``<odoo>``, instead of defining a ``<template>``,
-we will create a *page* object.
-
-.. code-block:: xml
-
- <?xml version="1.0" encoding="utf-8" ?>
- <odoo>
-
- <!-- === Services Page === -->
- <record id="services_page" model="website.page">
- <field name="name">Services page</field>
- <field name="website_published">True</field>
- <field name="url">/services</field>
- <field name="type">qweb</field>
- <field name="key">theme_tutorial.services_page</field>
- <field name="arch" type="xml">
- <t t-name="theme_tutorial.services_page_template">
- <h1>Our Services</h1>
- <ul class="services">
- <li>Cloud Hosting</li>
- <li>Support</li>
- <li>Unlimited space</li>
- </ul>
- </t>
- </field>
- </record>
-
- </odoo>
-
-As you can see, pages come with many additional properties like the *name* or
-the *url* where it is reachable.
-
-We successfully created a new page layout, but we haven't told the
-system **how to use it**. To do that, we can use **QWeb**. Wrap the
-html code into a ``<t>`` tag, like in this example.
-
-.. code-block:: xml
-
- <!-- === Services Page === -->
- <record id="services_page" model="website.page">
- <field name="name">Services page</field>
- <field name="website_published">True</field>
- <field name="url">/services</field>
- <field name="type">qweb</field>
- <field name="key">theme_tutorial.services_page</field>
- <field name="arch" type="xml">
- <t t-name="theme_tutorial.services_page_template">
- <t t-call="website.layout">
- <div id="wrap">
- <div class="container">
- <h1>Our Services</h1>
- <ul class="services">
- <li>Cloud Hosting</li>
- <li>Support</li>
- <li>Unlimited space</li>
- </ul>
- </div>
- </div>
- </t>
- </t>
- </field>
- </record>
-
-Using ``<t t-call="website.layout">`` we will use the Odoo
-default page layout with our code.
-
-As you can see, we wrapped our code into two ``<div>``, one with ID ``wrap`` and the other one with class ``container``. This is to provide a minimal layout.
-
-The next step is to add an empty area that the user
-can fill with snippets. To achieve this, just create a ``div`` with
-``oe_structure`` class just before closing the ``div#wrap`` element.
-
-.. code-block:: xml
-
- <?xml version="1.0" encoding="utf-8" ?>
- <odoo>
-
- <!-- === Services Page === -->
- <record id="services_page" model="website.page">
- <field name="name">Services page</field>
- <field name="website_published">True</field>
- <field name="url">/services</field>
- <field name="type">qweb</field>
- <field name="key">theme_tutorial.services_page</field>
- <field name="arch" type="xml">
- <t t-name="theme_tutorial.services_page_template">
- <t t-call="website.layout">
- <div id="wrap">
- <div class="container">
- <h1>Our Services</h1>
- <ul class="services">
- <li>Cloud Hosting</li>
- <li>Support</li>
- <li>Unlimited space</li>
- </ul>
- </div>
- <!-- === Snippets' area === -->
- <div class="oe_structure" />
- </div>
- </t>
- </t>
- </field>
- </record>
-
- </odoo>
-
-.. tip::
-
- You can create as many snippet areas as you like and place them anywhere in your pages.
-
-It is worth mentioning there is an alternative to create pages using the
-``<template>`` directive we saw before.
-
-.. code-block:: xml
-
- <?xml version="1.0" encoding="utf-8" ?>
- <odoo>
-
- <!-- === Services Page === -->
- <template id="services_page_template">
- <t t-call="website.layout">
- <div id="wrap">
- <div class="container">
- <h1>Our Services</h1>
- <ul class="services">
- <li>Cloud Hosting</li>
- <li>Support</li>
- <li>Unlimited space</li>
- </ul>
-
- <!-- === Snippets' area === -->
- <div class="oe_structure" />
- </div>
- </div>
- </t>
- </template>
- <record id="services_page" model="website.page">
- <field name="name">Services page</field>
- <field name="website_published">True</field>
- <field name="url">/services</field>
- <field name="view_id" ref="services_page_template"/>
- </record>
-
- </odoo>
-
-This would allow your page content to be further customized using ``<xpath>``.
-
-Our page is almost ready. Now all we have to do is add **pages.xml** in our **__manifest__.py** file
-
-.. code-block:: python
-
- 'data': [
- 'views/layout.xml',
- 'views/pages.xml'
- ],
-
-Update your theme
-
-.. image:: theme_tutorial_assets/img/restart.png
-
-Great, our Services page is ready and you’ll be able to access it by navigating to ``<yourwebsite>/services`` (the URL we chose above).
-
-You will notice that it's possible to drag/drop snippets underneath the
-*Our Services* list.
-
-.. image:: theme_tutorial_assets/img/services_page_nostyle.png
- :class: shadow-0
-
-Now let's go back to our *pages.xml* and, after our page template,
-copy/paste the following code.
-
-.. code-block:: xml
-
- <record id="services_page_link" model="website.menu">
- <field name="name">Services</field>
- <field name="page_id" ref="services_page"/>
- <field name="parent_id" ref="website.main_menu" />
- <field name="sequence" type="int">99</field>
- </record>
-
-This code will add a link to the main menu, referring to the page we created.
-
-.. image:: theme_tutorial_assets/img/services_page_menu.png
- :class: shadow-0
-
-The **sequence** attribute defines the link’s position in the top menu.
-In our example, we set the value to ``99`` in order to place it last. I you want to place it in a particular position, you have to replace the value according to your needs.
-
-As you can see inspecting the *data.xml* file in the ``website`` module, the **Home** link is set to ``10`` and the **Contact** us one is set to ``60`` by default.
-If, for example, you want to place your link in the **middle**, you can set your link’s sequence value to ``40``.
-
-Create Snippets
-===============
-
-Since snippets are how users design and layout pages, they are the most important XML elements of your design.
-Let’s create a snippet for our Service page. The snippet will display three testimonials and it will be editable by the end user using the Website Builder UI.
-Navigate to the view folder and create an XML file called **snippets.xml**.
-Add the default Odoo xml markup and copy/paste the following code.
-The template contains the HTML markup that will be displayed by the snippet.
-
-.. code-block:: xml
-
- <template id="s_testimonial" name="Testimonial snippet">
- <section class="s_testimonial">
- <div class="container">
- <div class="row">
- <div class="col-lg-4 text-center">
- <img alt="client" class="rounded-circle" src="/theme_tutorial/static/src/img/client_1.jpg"/>
- <h3>Client Name</h3>
- <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
- </div>
- <div class="col-lg-4 text-center">
- <img alt="client" class="rounded-circle" src="/theme_tutorial/static/src/img/client_2.jpg"/>
- <h3>Client Name</h3>
- <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
- </div>
- <div class="col-lg-4 text-center">
- <img alt="client" class="rounded-circle" src="/theme_tutorial/static/src/img/client_3.jpg"/>
- <h3>Client Name</h3>
- <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
- </div>
- </div>
- </div>
- </section>
- </template>
-
-As you can see, we used Bootstrap default classes for our three columns. It’s not just about layout, these classes **will be triggered by the Website Builder to make them resizable by the user**.
-
-The previous code will create the snippet’s content, but we still need to place it into the editor bar, so the user will be able to drag&drop it into the page. Copy/paste this template in your **snippets.xml** file.
-
-.. code-block:: xml
-
- <template id="place_into_bar" inherit_id="website.snippets" name="Place into bar">
- <xpath expr="//div[@id='snippet_structure']/div[hasclass('o_panel_body')]" position="inside">
- <t t-snippet="theme_tutorial.s_testimonial"
- t-thumbnail="/theme_tutorial/static/src/img/ui/snippet_thumb.jpg"/>
- </xpath>
- </template>
-
-.. rst-class:: col-sm-6
-
-Using xpath, we are targeting a particular element with id
-``snippet_structure``. This means that the snippet will appear in the
-Structure tab. If you want to change the destination tab, you have just to replace the ``id`` value in the xpath expression.
-
-
-
-.. image:: theme_tutorial_assets/img/snippet_bar.png
- :class: col-sm-6 shadow-0
-
-
-
-============ ==================================
-Tab Name Xpath expression
-============ ==================================
-Structure ``//div[@id='snippet_structure']``
-Content ``//div[@id='snippet_content']``
-Feature ``//div[@id='snippet_feature']``
-Effect ``//div[@id='snippet_effect']``
-============ ==================================
-
-The ``<t>`` tag will call our snippet's template and will assign a thumbnail placed in the img folder.
-You can now drag your snippet from the snippet bar, drop it in your page and see the result.
-
-.. image:: theme_tutorial_assets/img/snippet_default.png
-
-
-Snippet options
-===============
-
-Options allow publishers to edit a snippet’s appearance using the Website Builder’s UI.
-Using Website Builder functionalities, you can create snippet options easily and automatically add them to the UI.
-
-Options group properties
--------------------------
-
-Options are wrapped in groups. Groups can have properties that define how the included options will interact with the user interface.
-
-``data-selector="[css selector(s)]"``
- Bind all the options included into the group to a particular element.
-``data-js=" custom method name "``
- Is used to bind custom Javascript methods.
-``data-drop-in="[css selector(s)]"``
- Defines the list of elements where the snippet can be dropped into.
-``data-drop-near="[css selector(s)]"``
- Defines the list of elements that the snippet can be dropped beside.
-
-Default option methods
------------------------
-
-Options apply standard CSS classes to the snippet. Depending on the method that you choose, the UI will behave differently.
-
-``data-select-class="[class name]"``
- More data-select-class in the same group defines a list of classes that the user can choose to apply. Only one option can be enabled at a time.
-
-``data-toggle-class="[class name]"``
- The data-toggle-class is used to apply one or more CSS classes from the list to a snippet. Multiple selections can be applied at once.
-
-Let's demonstrate how default options work with a basic example.
-
-We start by adding a new file in our views folder - name it **options.xml** and add the default Odoo XML markup. Create a new template copy/pasting the following
-
-
-.. code-block:: xml
-
- <template id="snippet_testimonial_opt" name="Snippet Testimonial Options" inherit_id="website.snippet_options">
- <xpath expr="//div[@data-js='Box']" position="after">
- <div data-selector=".snippet_testimonial"> <!-- Options group -->
- <div class="dropdown-submenu">
- <a href="#" class="dropdown-item">Your Option</a>
- <div class="dropdown-menu"><!-- Options list -->
- <a href="#" class="dropdown-item" data-select-class="opt_shadow">Shadow Images</a>
- <a href="#" class="dropdown-item" data-select-class="opt_grey_bg">Grey Bg</a>
- <a href="#" class="dropdown-item" data-select-class="">None</a>
- </div>
- </div>
- </div>
- </xpath>
- </template>
-
-.. note::
-
- The previous template will inherit the default **snippet_options template** adding our options after the **background** options (xpath expr attribute).
- To place your options in a particular order, inspect the **snippet_options template** from the **website module** and add your options before/after the desired position.
-
-As you can see, we wrapped all our options inside a DIV tag that will
-group our options and that will target them to the right selector
-(``data-selector=".s_testimonial"``).
-
-To define our options we applied ``data-select-class`` attributes to the
-``li`` elements. When the user selects an option, the class contained in
-the attribute will automatically be applied to the element.
-
-Since ``selectClass`` method avoids multiple selections, the last "empty"
-option will reset the snippet to default.
-
-Add **options.xml** to ``__manifest__.py`` and update your theme.
-
-.. image:: theme_tutorial_assets/img/restart.png
-
-Dropping our snippet onto the page, you will notice that our new options are automatically added to the customize menu. Inspecting the page, you will also notice that the class will be applied to the element when selecting an option.
-
-.. image:: theme_tutorial_assets/img/snippet_options.png
-
-Let’s create some css rules in order to provide a visual feedback for our options. Open our **style.scss** file and add the following
-
-.. code-block:: scss
-
- // These lines will add a default style for our snippet. Now let's create our custom rules for the options.
-
- .s_testimonial {
- border: 1px solid #EAEAEA;
- padding: 20px;
-
- &.s_testimonial_shadow img {
- box-shadow: 0 2px 5px rgba(51, 51, 51, 0.4);
- }
- &.s_testimonial_grey_bg {
- border: none;
- background-color: #EAEAEA;
- }
- }
-
-.. image:: theme_tutorial_assets/img/snippet_options2.png
- :class: shadow-0
-
-Great! We successfully created options for our snippet.
-
-Any time the publisher clicks on an option, the system will add the class specified in the data-select-class attribute.
-
-By replacing ``data-select-class`` with ``data-toggle-class`` you will be able to select
-more classes at the same time.
-
-
-Javascript Options
-------------------
-
-``data-select-class`` and ``data-toggle-class`` are great if you need to perform
-simple class change operations. But what if your snippet’s customization needs something more?
-
-As we said before, ``data-js`` propriety can be assigned to an options group in order to define a custom method. Let’s create one for our *testimonials snippet* by adding a ``data-js`` attribute to the option’s group div that we created earlier.
-
-.. code-block:: xml
-
- <div data-js="s_testimonial_options" data-selector=".s_testimonial">
- <!-- ... -->
- </div>
-
-Done. From now on, the Website Builder will look for a
-``s_testimonial_options`` JS option each time the publisher enters in edit
-mode.
-
-Let's go one step further by creating a javascript file, name
-it **tutorial_editor.js** and place it into the **static** folder. Copy/paste
-the following code
-
-.. code-block:: javascript
-
- odoo.define('theme_tutorial.s_testimonial_options', function (require) {
- var options = require('web_editor.snippets.options');
- });
-
-Great, we successfully created our javascript editor file. This file will contain all the javascript functions used by our snippets in edit mode. Let’s create a new function for our testimonial snippet using the ``s_testimonial_options`` name that we used before.
-
-.. code-block:: javascript
-
- odoo.define('theme_tutorial.s_testimonial_options', function (require) {
- var options = require('web_editor.snippets.options');
- options.registry.s_testimonial_options = options.Class.extend({
- onFocus: function () {
- alert("On focus!")
- },
- });
- });
-
-As you will notice, we used a method called ``onFocus`` to trigger our function. The Website Builder provides several events you can use to trigger your custom functions.
-
-=========================== ==================================
-Event Description
-=========================== ==================================
-``start`` Fires when the publisher selects the snippet for the first time in an editing session or when the snippet is drag-dropped into the page
-``onFocus`` Fires each time the snippet is selected by the user or when the snippet is drag-dropped into the page.
-``onBlur`` This event occurs when a snippet loses focus.
-``onClone`` Fires just after a snippet is duplicated.
-``onRemove`` It occurs just before that the snippet is removed.
-``onBuilt`` Fires just after that the snippet is drag and dropped into a drop zone. When this event is triggered, the content is already inserted in the page.
-``cleanForSave`` It trigger before the publisher saves the page.
-=========================== ==================================
-
-Let’s add our new javascript files to the editor assets list.
-Go back to **assets.xml** and create a new template like the previous one.
-This time we have to inherit ``assets_editor`` instead of ``assets_frontend``.
-
-.. code-block:: xml
-
- <template id="my_js" inherit_id="website.assets_editor" name="My Js">
- <xpath expr="script[last()]" position="after">
- <script type="text/javascript" src="/theme_tutorial/static/src/js/tutorial_editor.js" />
- </xpath>
- </template>
-
-Update your theme
-
-.. image:: theme_tutorial_assets/img/restart.png
-
-
-Let’s test our new javascript function. Enter in Edit mode and drop into the page.
-You should now see the javascript alert that we bound on the ``onFocus`` event.
-If you close it, then click outside of your snippet and then click in it again, the event will trigger again.
-
-.. image:: theme_tutorial_assets/img/snippet_custom_method.png
- :class: shadow-0
-
-
-
-Editing Reference Guide
-=======================
-
-Basically all the elements in a page can be edited by the publisher.
-Besides that, some element types and css classes will trigger special Website Builder functionalities when edited.
-
-Layout
-------
-
-``<section />``
- Any section element can be edited like a block of content. The publisher can move or duplicate it. It’s also possible to set a background image or color. Section is the standard main container of any snippet.
-
-``.row > .col-lg-*``
- Any large bootstrap columns directly descending from a .row element (respecting Bootstrap structure), will be resizable by the publisher.
-
-``contenteditable="False"``
- This attribute will prevent editing to the element and all its children.
-
-``contenteditable="True"``
- Apply it to an element inside a contenteditable="False" element in order to create an exception and make the element and its children editable.
-
-``<a href=”#” />``
- In Edit Mode, any link can be edited and styled. Using the “Link Modal” it’s also possible to replace it with a button.
-
-Media
------
-
-``<span class=”fa” />``
- Pictogram elements. Editing this element will open the Pictogram library to replace the icon. It’s also possible to transform the elements using CSS.
-
-``<img />``
- Once clicked, the Image Library will open and you can replace images. Transformation is also possible for this kind of element.
-
-.. code-block:: html
-
- <div class="media_iframe_video" data-src="[your url]" >
- <div class="css_editable_mode_display"/>
- <div class="media_iframe_video_size"/>
- <iframe src="[your url]"/>
- </div>
-
-This html structure will create an ``<iframe>`` element editable by the publisher.
-
-
-SEO best practice
-=================
-
-Facilitate content insertion
-----------------------------
-
-Modern search engine algorithms increasingly focus on content, which means there is less focus on **keyword saturation** and more focus on whether or not the content is **actually relevant to the keywords**.
-
-As content is so important for SEO, you should concentrate on giving publishers the tools to easily insert it. It is important that your snippets are “content-responsive”, meaning that they should fit the publisher’s content regardless of size.
-
-Let’s have a look to this example of a classic two column snippet, implemented in two different ways.
-
-.. container:: row
-
- .. container:: col-sm-7
-
- .. image:: theme_tutorial_assets/img/seo_snippet_wrong.png
-
- .. container:: col-sm-5
-
- **Bad**
-
- Using fixed image, the publisher will be forced to limit the text in order to follow the layout.
-
-.. container:: row
-
- .. container:: col-sm-7
-
- .. image:: theme_tutorial_assets/img/seo_snippet_good.png
-
- .. container:: col-sm-5
-
- **Good**
-
- Using background images that fit the column height, the publisher will be free to add the content regardless of the image’s height.
-
-
-
-Page segmentation
------------------
-
-Basically, page segmentation means that a page is divided into several separate parts and these parts are treated as separate entries by search engines.
-When you design pages or snippets, you should be sure to use the right tags in order to facilitate search engine indexing.
-
-``<article>``
- Specifies an independent block of content. Within it should be a piece of self-contained content that should make sense on its own. You can nest ``<article>`` elements within one another. In this case, it’s implied that the nested elements are related to the outer ``<article>`` element.
-
-``<header>``
- Indicates the header section of a self-contained block of content (an ``<article>``).
-
-``<section>``
- Is the snippet default tag and it specifies a subsection of a block of content. It can be used to split ``<article>`` content into several parts. It’s advisable to use a heading element (``<h1>`` – ``<h6>``) to define the section’s topic.
-
-``<hgroup>``
- Is used to wrap a section of headings (``<h1>`` - ``<h6>``). A great example would be an article with both a headline and sub-headline at the top:
-
- .. code-block:: html
-
- <hgroup>
- <h1>Main Title</h1>
- <h2>Subheading</h2>
- </hgroup>
-
-Describe your page
-------------------
-
-Define keywords
-'''''''''''''''
-You should use appropriate, relevant keywords and synonyms for those keywords. You can define them for each page using the built-in “Promote” function found in the bar at the top.
-
-Define a title and a description
-''''''''''''''''''''''''''''''''
-
-Define them using the “Promote” function. Keep your page titles short and include the main keyword phrase for the page.
-Good titles evoke an emotional response, ask a question or promise something.
-
-Descriptions, while not important to search engine rankings, are extremely important in gaining user click-through. These are an opportunity to advertise content and to let people searching know exactly whether the given page contains the information they're looking for. It is important that titles and descriptions on each page are unique.
diff --git a/doc/howtos/web.rst b/doc/howtos/web.rst
deleted file mode 100644
index e430460fc35..00000000000
--- a/doc/howtos/web.rst
+++ /dev/null
@@ -1,2330 +0,0 @@
-:banner: banners/build_interface_ext.jpg
-
-=============================
-Customizing the web client
-=============================
-
-Note: this section is really really out of date. It will be updated someday,
-but meanwhile, this tutorial will probably be frustrating to follow, since it
-was written a long time ago.
-
-
-.. highlight:: javascript
-
-.. default-domain:: js
-
-This guide is about creating modules for Odoo's web client.
-
-To create websites with Odoo, see :doc:`website`; to add business capabilities
-or extend existing business systems of Odoo, see :doc:`backend`.
-
-.. warning::
-
- This guide assumes knowledge of:
-
- * Javascript basics and good practices
- * jQuery_
- * `Underscore.js`_
-
- It also requires :ref:`an installed Odoo <setup/install>`, and Git_.
-
-
-A Simple Module
-===============
-
-Let's start with a simple Odoo module holding basic web component
-configuration and letting us test the web framework.
-
-The example module is available online and can be downloaded using the
-following command:
-
-.. code-block:: console
-
- $ git clone http://github.com/odoo/petstore
-
-This will create a ``petstore`` folder wherever you executed the command.
-You then need to add that folder to Odoo's
-:option:`addons path <odoo-bin --addons-path>`, create a new database and
-install the ``oepetstore`` module.
-
-If you browse the ``petstore`` folder, you should see the following content:
-
-.. code-block:: text
-
- oepetstore
- |-- images
- | |-- alligator.jpg
- | |-- ball.jpg
- | |-- crazy_circle.jpg
- | |-- fish.jpg
- | `-- mice.jpg
- |-- __init__.py
- |-- oepetstore.message_of_the_day.csv
- |-- __manifest__.py
- |-- petstore_data.xml
- |-- petstore.py
- |-- petstore.xml
- `-- static
- `-- src
- |-- css
- | `-- petstore.css
- |-- js
- | `-- petstore.js
- `-- xml
- `-- petstore.xml
-
-The module already holds various server customizations. We'll come back to
-these later, for now let's focus on the web-related content, in the ``static``
-folder.
-
-Files used in the "web" side of an Odoo module must be placed in a ``static``
-folder so they are available to a web browser, files outside that folder can
-not be fetched by browsers. The ``src/css``, ``src/js`` and ``src/xml``
-sub-folders are conventional and not strictly necessary.
-
-``oepetstore/static/css/petstore.css``
- Currently empty, will hold the CSS_ for pet store content
-``oepetstore/static/xml/petstore.xml``
- Mostly empty, will hold :ref:`reference/qweb` templates
-``oepetstore/static/js/petstore.js``
- The most important (and interesting) part, contains the logic of the
- application (or at least its web-browser side) as javascript. It should
- currently look like::
-
- odoo.oepetstore = function(instance, local) {
- var _t = instance.web._t,
- _lt = instance.web._lt;
- var QWeb = instance.web.qweb;
-
- local.HomePage = instance.Widget.extend({
- start: function() {
- console.log("pet store home page loaded");
- },
- });
-
- instance.web.client_actions.add(
- 'petstore.homepage', 'instance.oepetstore.HomePage');
- }
-
-Which only prints a small message in the browser's console.
-
-The files in the ``static`` folder, need to be defined within the module in order for them to be loaded correctly. Everything in ``src/xml`` is defined in ``__manifest__.py`` while the contents of ``src/css`` and ``src/js`` are defined in ``petstore.xml``, or a similar file.
-
-.. warning::
-
- All JavaScript files are concatenated and :term:`minified` to improve
- application load time.
-
- One of the drawback is debugging becomes more difficult as
- individual files disappear and the code is made significantly less
- readable. It is possible to disable this process by enabling the
- "developer mode": log into your Odoo instance (user *admin* password
- *admin* by default) open the user menu (in the top-right corner of the
- Odoo screen) and select :guilabel:`About Odoo` then :guilabel:`Activate
- the developer mode`:
-
- .. image:: web/about_odoo.png
- :align: center
-
- .. image:: web/devmode.png
- :align: center
-
- This will reload the web client with optimizations disabled, making
- development and debugging significantly more comfortable.
-
-.. todo:: qweb files hooked via __manifest__.py, but js and CSS use bundles
-
-Odoo JavaScript Module
-======================
-
-Javascript doesn't have built-in modules. As a result variables defined in
-different files are all mashed together and may conflict. This has given rise
-to various module patterns used to build clean namespaces and limit risks of
-naming conflicts.
-
-The Odoo framework uses one such pattern to define modules within web addons,
-in order to both namespace code and correctly order its loading.
-
-``oepetstore/static/js/petstore.js`` contains a module declaration::
-
- odoo.oepetstore = function(instance, local) {
- local.xxx = ...;
- }
-
-In Odoo web, modules are declared as functions set on the global ``odoo``
-variable. The function's name must be the same as the addon (in this case
-``oepetstore``) so the framework can find it, and automatically initialize it.
-
-When the web client loads your module it will call the root function
-and provide two parameters:
-
-* the first parameter is the current instance of the Odoo web client, it gives
- access to various capabilities defined by the Odoo (translations,
- network services) as well as objects defined by the core or by other
- modules.
-* the second parameter is your own local namespace automatically created by
- the web client. Objects and variables which should be accessible from
- outside your module (either because the Odoo web client needs to call them
- or because others may want to customize them) should be set inside that
- namespace.
-
-Classes
-=======
-
-Much as modules, and contrary to most object-oriented languages, javascript
-does not build in *classes*\ [#classes]_ although it provides roughly
-equivalent (if lower-level and more verbose) mechanisms.
-
-For simplicity and developer-friendliness Odoo web provides a class
-system based on John Resig's `Simple JavaScript Inheritance`_.
-
-New classes are defined by calling the :func:`~odoo.web.Class.extend`
-method of :class:`odoo.web.Class`::
-
- var MyClass = instance.web.Class.extend({
- say_hello: function() {
- console.log("hello");
- },
- });
-
-The :func:`~odoo.web.Class.extend` method takes a dictionary describing
-the new class's content (methods and static attributes). In this case, it will
-only have a ``say_hello`` method which takes no parameters.
-
-Classes are instantiated using the ``new`` operator::
-
- var my_object = new MyClass();
- my_object.say_hello();
- // print "hello" in the console
-
-And attributes of the instance can be accessed via ``this``::
-
- var MyClass = instance.web.Class.extend({
- say_hello: function() {
- console.log("hello", this.name);
- },
- });
-
- var my_object = new MyClass();
- my_object.name = "Bob";
- my_object.say_hello();
- // print "hello Bob" in the console
-
-Classes can provide an initializer to perform the initial setup of the
-instance, by defining an ``init()`` method. The initializer receives the
-parameters passed when using the ``new`` operator::
-
- var MyClass = instance.web.Class.extend({
- init: function(name) {
- this.name = name;
- },
- say_hello: function() {
- console.log("hello", this.name);
- },
- });
-
- var my_object = new MyClass("Bob");
- my_object.say_hello();
- // print "hello Bob" in the console
-
-It is also possible to create subclasses from existing (used-defined) classes
-by calling :func:`~odoo.web.Class.extend` on the parent class, as is done
-to subclass :class:`~odoo.web.Class`::
-
- var MySpanishClass = MyClass.extend({
- say_hello: function() {
- console.log("hola", this.name);
- },
- });
-
- var my_object = new MySpanishClass("Bob");
- my_object.say_hello();
- // print "hola Bob" in the console
-
-When overriding a method using inheritance, you can use ``this._super()`` to
-call the original method::
-
- var MySpanishClass = MyClass.extend({
- say_hello: function() {
- this._super();
- console.log("translation in Spanish: hola", this.name);
- },
- });
-
- var my_object = new MySpanishClass("Bob");
- my_object.say_hello();
- // print "hello Bob \n translation in Spanish: hola Bob" in the console
-
-.. warning::
-
- ``_super`` is not a standard method, it is set on-the-fly to the next
- method in the current inheritance chain, if any. It is only defined
- during the *synchronous* part of a method call, for use in asynchronous
- handlers (after network calls or in ``setTimeout`` callbacks) a reference
- to its value should be retained, it should not be accessed via ``this``::
-
- // broken, will generate an error
- say_hello: function () {
- setTimeout(function () {
- this._super();
- }.bind(this), 0);
- }
-
- // correct
- say_hello: function () {
- // don't forget .bind()
- var _super = this._super.bind(this);
- setTimeout(function () {
- _super();
- }.bind(this), 0);
- }
-
-Widgets Basics
-==============
-
-The Odoo web client bundles jQuery_ for easy DOM manipulation. It is useful
-and provides a better API than standard `W3C DOM`_\ [#dombugs]_, but
-insufficient to structure complex applications leading to difficult
-maintenance.
-
-Much like object-oriented desktop UI toolkits (e.g. Qt_, Cocoa_ or GTK_),
-Odoo Web makes specific components responsible for sections of a page. In
-Odoo web, the base for such components is the :class:`~odoo.Widget`
-class, a component specialized in handling a page section and displaying
-information for the user.
-
-Your First Widget
------------------
-
-The initial demonstration module already provides a basic widget::
-
- local.HomePage = instance.Widget.extend({
- start: function() {
- console.log("pet store home page loaded");
- },
- });
-
-It extends :class:`~odoo.Widget` and overrides the standard method
-:func:`~odoo.Widget.start`, which — much like the previous ``MyClass``
-— does little for now.
-
-This line at the end of the file::
-
- instance.web.client_actions.add(
- 'petstore.homepage', 'instance.oepetstore.HomePage');
-
-registers our basic widget as a client action. Client actions will be
-explained later, for now this is just what allows our widget to
-be called and displayed when we select the
-:menuselection:`Pet Store --> Pet Store --> Home Page` menu.
-
-.. warning::
-
- because the widget will be called from outside our module, the web client
- needs its "fully qualified" name, not the local version.
-
-Display Content
----------------
-
-Widgets have a number of methods and features, but the basics are simple:
-
-* set up a widget
-* format the widget's data
-* display the widget
-
-The ``HomePage`` widget already has a :func:`~odoo.Widget.start`
-method. That method is part of the normal widget lifecycle and automatically
-called once the widget is inserted in the page. We can use it to display some
-content.
-
-All widgets have a :attr:`~odoo.Widget.$el` which represents the
-section of page they're in charge of (as a jQuery_ object). Widget content
-should be inserted there. By default, :attr:`~odoo.Widget.$el` is an
-empty ``<div>`` element.
-
-A ``<div>`` element is usually invisible to the user if it has no content (or
-without specific styles giving it a size) which is why nothing is displayed
-on the page when ``HomePage`` is launched.
-
-Let's add some content to the widget's root element, using jQuery::
-
- local.HomePage = instance.Widget.extend({
- start: function() {
- this.$el.append("<div>Hello dear Odoo user!</div>");
- },
- });
-
-That message will now appear when you open :menuselection:`Pet Store
---> Pet Store --> Home Page`
-
-.. note::
-
- to refresh the javascript code loaded in Odoo Web, you will need to reload
- the page. There is no need to restart the Odoo server.
-
-The ``HomePage`` widget is used by Odoo Web and managed automatically.
-To learn how to use a widget "from scratch" let's create a new one::
-
- local.GreetingsWidget = instance.Widget.extend({
- start: function() {
- this.$el.append("<div>We are so happy to see you again in this menu!</div>");
- },
- });
-
-We can now add our ``GreetingsWidget`` to the ``HomePage`` by using the
-``GreetingsWidget``'s :func:`~odoo.Widget.appendTo` method::
-
- local.HomePage = instance.Widget.extend({
- start: function() {
- this.$el.append("<div>Hello dear Odoo user!</div>");
- var greeting = new local.GreetingsWidget(this);
- return greeting.appendTo(this.$el);
- },
- });
-
-* ``HomePage`` first adds its own content to its DOM root
-* ``HomePage`` then instantiates ``GreetingsWidget``
-* Finally it tells ``GreetingsWidget`` where to insert itself, delegating part
- of its :attr:`~odoo.Widget.$el` to the ``GreetingsWidget``.
-
-When the :func:`~odoo.Widget.appendTo` method is called, it asks the
-widget to insert itself at the specified position and to display its content.
-The :func:`~odoo.Widget.start` method will be called during the call
-to :func:`~odoo.Widget.appendTo`.
-
-To see what happens under the displayed interface, we will use the browser's
-DOM Explorer. But first let's alter our widgets slightly so we can more easily
-find where they are, by :attr:`adding a class to their root elements
-<odoo.Widget.className>`::
-
- local.HomePage = instance.Widget.extend({
- className: 'oe_petstore_homepage',
- ...
- });
- local.GreetingsWidget = instance.Widget.extend({
- className: 'oe_petstore_greetings',
- ...
- });
-
-If you can find the relevant section of the DOM (right-click on the text
-then :guilabel:`Inspect Element`), it should look like this:
-
-.. code-block:: html
-
- <div class="oe_petstore_homepage">
- <div>Hello dear Odoo user!</div>
- <div class="oe_petstore_greetings">
- <div>We are so happy to see you again in this menu!</div>
- </div>
- </div>
-
-Which clearly shows the two ``<div>`` elements automatically created by
-:class:`~odoo.Widget`, because we added some classes on them.
-
-We can also see the two message-holding divs we added ourselves
-
-Finally, note the ``<div class="oe_petstore_greetings">`` element which
-represents the ``GreetingsWidget`` instance is *inside* the
-``<div class="oe_petstore_homepage">`` which represents the ``HomePage``
-instance, since we appended
-
-Widget Parents and Children
----------------------------
-
-In the previous part, we instantiated a widget using this syntax::
-
- new local.GreetingsWidget(this);
-
-The first argument is ``this``, which in that case was a ``HomePage``
-instance. This tells the widget being created which other widget is its
-*parent*.
-
-As we've seen, widgets are usually inserted in the DOM by another widget and
-*inside* that other widget's root element. This means most widgets are "part"
-of another widget, and exist on behalf of it. We call the container the
-*parent*, and the contained widget the *child*.
-
-Due to multiple technical and conceptual reasons, it is necessary for a widget
-to know who is its parent and who are its children.
-
-:func:`~odoo.Widget.getParent`
- can be used to get the parent of a widget::
-
- local.GreetingsWidget = instance.Widget.extend({
- start: function() {
- console.log(this.getParent().$el );
- // will print "div.oe_petstore_homepage" in the console
- },
- });
-
-:func:`~odoo.Widget.getChildren`
- can be used to get a list of its children::
-
- local.HomePage = instance.Widget.extend({
- start: function() {
- var greeting = new local.GreetingsWidget(this);
- greeting.appendTo(this.$el);
- console.log(this.getChildren()[0].$el);
- // will print "div.oe_petstore_greetings" in the console
- },
- });
-
-When overriding the :func:`~odoo.Widget.init` method of a widget it is
-*of the utmost importance* to pass the parent to the ``this._super()`` call,
-otherwise the relation will not be set up correctly::
-
- local.GreetingsWidget = instance.Widget.extend({
- init: function(parent, name) {
- this._super(parent);
- this.name = name;
- },
- });
-
-Finally, if a widget does not have a parent (e.g. because it's the root
-widget of the application), ``null`` can be provided as parent::
-
- new local.GreetingsWidget(null);
-
-Destroying Widgets
-------------------
-
-If you can display content to your users, you should also be able to erase
-it. This is done via the :func:`~odoo.Widget.destroy` method::
-
- greeting.destroy();
-
-When a widget is destroyed it will first call
-:func:`~odoo.Widget.destroy` on all its children. Then it erases itself
-from the DOM. If you have set up permanent structures in
-:func:`~odoo.Widget.init` or :func:`~odoo.Widget.start` which
-must be explicitly cleaned up (because the garbage collector will not handle
-them), you can override :func:`~odoo.Widget.destroy`.
-
-.. danger::
-
- when overriding :func:`~odoo.Widget.destroy`, ``_super()``
- *must always* be called otherwise the widget and its children are not
- correctly cleaned up leaving possible memory leaks and "phantom events",
- even if no error is displayed
-
-The QWeb Template Engine
-========================
-
-In the previous section we added content to our widgets by directly
-manipulating (and adding to) their DOM::
-
- this.$el.append("<div>Hello dear Odoo user!</div>");
-
-This allows generating and displaying any type of content, but gets unwieldy
-when generating significant amounts of DOM (lots of duplication, quoting
-issues, ...)
-
-As many other environments, Odoo's solution is to use a `template engine`_.
-Odoo's template engine is called :ref:`reference/qweb`.
-
-QWeb is an XML-based templating language, similar to `Genshi
-<http://en.wikipedia.org/wiki/Genshi_(templating_language)>`_, `Thymeleaf
-<http://en.wikipedia.org/wiki/Thymeleaf>`_ or `Facelets
-<http://en.wikipedia.org/wiki/Facelets>`_. It has the following
-characteristics:
-
-* It's implemented fully in JavaScript and rendered in the browser
-* Each template file (XML files) contains multiple templates
-* It has special support in Odoo Web's :class:`~odoo.Widget`, though it
- can be used outside of Odoo's web client (and it's possible to use
- :class:`~odoo.Widget` without relying on QWeb)
-
-.. note::
-
- The rationale behind using QWeb instead of existing javascript template
- engines is the extensibility of pre-existing (third-party) templates, much
- like Odoo :ref:`views <reference/views>`.
-
- Most javascript template engines are text-based which precludes easy
- structural extensibility where an XML-based templating engine can be
- generically altered using e.g. XPath or CSS and a tree-alteration DSL (or
- even just XSLT). This flexibility and extensibility is a core
- characteristic of Odoo, and losing it was considered unacceptable.
-
-Using QWeb
-----------
-
-First let's define a simple QWeb template in the almost-empty
-``oepetstore/static/src/xml/petstore.xml`` file:
-
-.. code-block:: xml
-
- <?xml version="1.0" encoding="UTF-8"?>
- <templates xml:space="preserve">
- <t t-name="HomePageTemplate">
- <div style="background-color: red;">This is some simple HTML</div>
- </t>
- </templates>
-
-Now we can use this template inside of the ``HomePage`` widget. Using the
-``QWeb`` loader variable defined at the top of the page, we can call to the
-template defined in the XML file::
-
- local.HomePage = instance.Widget.extend({
- start: function() {
- this.$el.append(QWeb.render("HomePageTemplate"));
- },
- });
-
-:func:`QWeb.render` looks for the specified template, renders it to a string
-and returns the result.
-
-However, because :class:`~odoo.Widget` has special integration for QWeb
-the template can be set directly on the widget via its
-:attr:`~odoo.Widget.template` attribute::
-
- local.HomePage = instance.Widget.extend({
- template: "HomePageTemplate",
- start: function() {
- ...
- },
- });
-
-Although the result looks similar, there are two differences between these
-usages:
-
-* with the second version, the template is rendered right before
- :func:`~odoo.Widget.start` is called
-* in the first version the template's content is added to the widget's root
- element, whereas in the second version the template's root element is
- directly *set as* the widget's root element. Which is why the "greetings"
- sub-widget also gets a red background
-
-.. warning::
-
- templates should have a single non-``t`` root element, especially if
- they're set as a widget's :attr:`~odoo.Widget.template`. If there are
- multiple "root elements", results are undefined (usually only the first
- root element will be used and the others will be ignored)
-
-QWeb Context
-''''''''''''
-
-QWeb templates can be given data and can contain basic display logic.
-
-For explicit calls to :func:`QWeb.render`, the template data is passed as
-second parameter::
-
- QWeb.render("HomePageTemplate", {name: "Klaus"});
-
-with the template modified to:
-
-.. code-block:: xml
-
- <t t-name="HomePageTemplate">
- <div>Hello <t t-esc="name"/></div>
- </t>
-
-will result in:
-
-.. code-block:: html
-
- <div>Hello Klaus</div>
-
-When using :class:`~odoo.Widget`'s integration it is not possible to
-provide additional data to the template. The template will be given a single
-``widget`` context variable, referencing the widget being rendered right
-before :func:`~odoo.Widget.start` is called (the widget's state will
-essentially be that set up by :func:`~odoo.Widget.init`):
-
-.. code-block:: xml
-
- <t t-name="HomePageTemplate">
- <div>Hello <t t-esc="widget.name"/></div>
- </t>
-
-::
-
- local.HomePage = instance.Widget.extend({
- template: "HomePageTemplate",
- init: function(parent) {
- this._super(parent);
- this.name = "Mordecai";
- },
- start: function() {
- },
- });
-
-Result:
-
-.. code-block:: html
-
- <div>Hello Mordecai</div>
-
-Template Declaration
-''''''''''''''''''''
-
-We've seen how to *render* QWeb templates, let's now see the syntax of
-the templates themselves.
-
-A QWeb template is composed of regular XML mixed with QWeb *directives*. A
-QWeb directive is declared with XML attributes starting with ``t-``.
-
-The most basic directive is ``t-name``, used to declare new templates in
-a template file:
-
-.. code-block:: xml
-
- <templates>
- <t t-name="HomePageTemplate">
- <div>This is some simple HTML</div>
- </t>
- </templates>
-
-``t-name`` takes the name of the template being defined, and declares that
-it can be called using :func:`QWeb.render`. It can only be used at the
-top-level of a template file.
-
-Escaping
-''''''''
-
-The ``t-esc`` directive can be used to output text:
-
-.. code-block:: xml
-
- <div>Hello <t t-esc="name"/></div>
-
-It takes a Javascript expression which is evaluated, the result of the
-expression is then HTML-escaped and inserted in the document. Since it's an
-expression it's possible to provide just a variable name as above, or a more
-complex expression like a computation:
-
-.. code-block:: xml
-
- <div><t t-esc="3+5"/></div>
-
-or method calls:
-
-.. code-block:: xml
-
- <div><t t-esc="name.toUpperCase()"/></div>
-
-Outputting HTML
-'''''''''''''''
-
-To inject HTML in the page being rendered, use ``t-raw``. Like ``t-esc`` it
-takes an arbitrary Javascript expression as parameter, but it does not
-perform an HTML-escape step.
-
-.. code-block:: xml
-
- <div><t t-raw="name.link(user_account)"/></div>
-
-.. danger::
-
- ``t-raw`` *must not* be used on any data which may contain non-escaped
- user-provided content as this leads to `cross-site scripting`_
- vulnerabilities
-
-Conditionals
-''''''''''''
-
-QWeb can have conditional blocks using ``t-if``. The directive takes an
-arbitrary expression, if the expression is falsy (``false``, ``null``, ``0``
-or an empty string) the whole block is suppressed, otherwise it is displayed.
-
-.. code-block:: xml
-
- <div>
- <t t-if="true == true">
- true is true
- </t>
- <t t-if="true == false">
- true is not true
- </t>
- </div>
-
-.. note::
-
- QWeb doesn't have an "else" structure, use a second ``t-if`` with the
- original condition inverted. You may want to store the condition in a
- local variable if it's a complex or expensive expression.
-
-Iteration
-'''''''''
-
-To iterate on a list, use ``t-foreach`` and ``t-as``. ``t-foreach`` takes an
-expression returning a list to iterate on ``t-as`` takes a variable name to
-bind to each item during iteration.
-
-.. code-block:: xml
-
- <div>
- <t t-foreach="names" t-as="name">
- <div>
- Hello <t t-esc="name"/>
- </div>
- </t>
- </div>
-
-.. note:: ``t-foreach`` can also be used with numbers and objects
- (dictionaries)
-
-Defining attributes
-'''''''''''''''''''
-
-QWeb provides two related directives to define computed attributes:
-:samp:`t-att-{name}` and :samp:`t-attf-{name}`. In either case, *name* is the
-name of the attribute to create (e.g. ``t-att-id`` defines the attribute
-``id`` after rendering).
-
-``t-att-`` takes a javascript expression whose result is set as the
-attribute's value, it is most useful if all of the attribute's value is
-computed:
-
-.. code-block:: xml
-
- <div>
- Input your name:
- <input type="text" t-att-value="defaultName"/>
- </div>
-
-``t-attf-`` takes a *format string*. A format string is literal text with
-interpolation blocks inside, an interpolation block is a javascript
-expression between ``{{`` and ``}}``, which will be replaced by the result
-of the expression. It is most useful for attributes which are partially
-literal and partially computed such as a class:
-
-.. code-block:: xml
-
- <div t-attf-class="container {{ left ? 'text-left' : '' }} {{ extra_class }}">
- insert content here
- </div>
-
-Calling other templates
-'''''''''''''''''''''''
-
-Templates can be split into sub-templates (for simplicity, maintainability,
-reusability or to avoid excessive markup nesting).
-
-This is done using the ``t-call`` directive, which takes the name of the
-template to render:
-
-.. code-block:: xml
-
- <t t-name="A">
- <div class="i-am-a">
- <t t-call="B"/>
- </div>
- </t>
- <t t-name="B">
- <div class="i-am-b"/>
- </t>
-
-rendering the ``A`` template will result in:
-
-.. code-block:: xml
-
- <div class="i-am-a">
- <div class="i-am-b"/>
- </div>
-
-Sub-templates inherit the rendering context of their caller.
-
-To Learn More About QWeb
-''''''''''''''''''''''''
-
-For a QWeb reference, see :ref:`reference/qweb`.
-
-Exercise
-''''''''
-
-.. exercise:: Usage of QWeb in Widgets
-
- Create a widget whose constructor takes two parameters aside from
- ``parent``: ``product_names`` and ``color``.
-
- * ``product_names`` should an array of strings, each one the name of a
- product
- * ``color`` is a string containing a color in CSS color format (ie:
- ``#000000`` for black).
-
- The widget should display the given product names one under the other,
- each one in a separate box with a background color with the value of
- ``color`` and a border. You should use QWeb to render the HTML. Any
- necessary CSS should be in ``oepetstore/static/src/css/petstore.css``.
-
- Use the widget in ``HomePage`` with half a dozen products.
-
- .. only:: solutions
-
- ::
-
- odoo.oepetstore = function(instance, local) {
- var _t = instance.web._t,
- _lt = instance.web._lt;
- var QWeb = instance.web.qweb;
-
- local.HomePage = instance.Widget.extend({
- start: function() {
- var products = new local.ProductsWidget(
- this, ["cpu", "mouse", "keyboard", "graphic card", "screen"], "#00FF00");
- products.appendTo(this.$el);
- },
- });
-
- local.ProductsWidget = instance.Widget.extend({
- template: "ProductsWidget",
- init: function(parent, products, color) {
- this._super(parent);
- this.products = products;
- this.color = color;
- },
- });
-
- instance.web.client_actions.add(
- 'petstore.homepage', 'instance.oepetstore.HomePage');
- }
-
- .. code-block:: xml
-
- <?xml version="1.0" encoding="UTF-8"?>
- <templates xml:space="preserve">
- <t t-name="ProductsWidget">
- <div>
- <t t-foreach="widget.products" t-as="product">
- <span class="oe_products_item"
- t-attf-style="background-color: {{ widget.color }};">
- <t t-esc="product"/>
- </span>
- <br/>
- </t>
- </div>
- </t>
- </templates>
-
- .. code-block:: css
-
- .oe_products_item {
- display: inline-block;
- padding: 3px;
- margin: 5px;
- border: 1px solid black;
- border-radius: 3px;
- }
-
- .. image:: web/qweb.*
- :align: center
- :width: 70%
-
-Widget Helpers
-==============
-
-``Widget``'s jQuery Selector
-----------------------------
-
-Selecting DOM elements within a widget can be performed by calling the
-``find()`` method on the widget's DOM root::
-
- this.$el.find("input.my_input")...
-
-But because it's a common operation, :class:`~odoo.Widget` provides an
-equivalent shortcut through the :func:`~odoo.Widget.$` method::
-
- local.MyWidget = instance.Widget.extend({
- start: function() {
- this.$("input.my_input")...
- },
- });
-
-.. warning::
-
- The global jQuery function ``$()`` should *never* be used unless it is
- absolutely necessary: selection on a widget's root are scoped to the
- widget and local to it, but selections with ``$()`` are global to the
- page/application and may match parts of other widgets and views, leading
- to odd or dangerous side-effects. Since a widget should generally act
- only on the DOM section it owns, there is no cause for global selection.
-
-Easier DOM Events Binding
--------------------------
-
-We have previously bound DOM events using normal jQuery event handlers (e.g.
-``.click()`` or ``.change()``) on widget elements::
-
- local.MyWidget = instance.Widget.extend({
- start: function() {
- var self = this;
- this.$(".my_button").click(function() {
- self.button_clicked();
- });
- },
- button_clicked: function() {
- ..
- },
- });
-
-While this works it has a few issues:
-
-1. it is rather verbose
-2. it does not support replacing the widget's root element at runtime as
- the binding is only performed when ``start()`` is run (during widget
- initialization)
-3. it requires dealing with ``this``-binding issues
-
-Widgets thus provide a shortcut to DOM event binding via
-:attr:`~odoo.Widget.events`::
-
- local.MyWidget = instance.Widget.extend({
- events: {
- "click .my_button": "button_clicked",
- },
- button_clicked: function() {
- ..
- }
- });
-
-:attr:`~odoo.Widget.events` is an object (mapping) of an event to the
-function or method to call when the event is triggered:
-
-* the key is an event name, possibly refined with a CSS selector in which
- case only if the event happens on a selected sub-element will the function
- or method run: ``click`` will handle all clicks within the widget, but
- ``click .my_button`` will only handle clicks in elements bearing the
- ``my_button`` class
-* the value is the action to perform when the event is triggered
-
- It can be either a function::
-
- events: {
- 'click': function (e) { /* code here */ }
- }
-
- or the name of a method on the object (see example above).
-
- In either case, the ``this`` is the widget instance and the handler is given
- a single parameter, the `jQuery event object`_ for the event.
-
-Widget Events and Properties
-============================
-
-Events
-------
-
-Widgets provide an event system (separate from the DOM/jQuery event system
-described above): a widget can fire events on itself, and other widgets (or
-itself) can bind themselves and listen for these events::
-
- local.ConfirmWidget = instance.Widget.extend({
- events: {
- 'click button.ok_button': function () {
- this.trigger('user_chose', true);
- },
- 'click button.cancel_button': function () {
- this.trigger('user_chose', false);
- }
- },
- start: function() {
- this.$el.append("<div>Are you sure you want to perform this action?</div>" +
- "<button class='ok_button'>Ok</button>" +
- "<button class='cancel_button'>Cancel</button>");
- },
- });
-
-This widget acts as a facade, transforming user input (through DOM events)
-into a documentable internal event to which parent widgets can bind
-themselves.
-
-:func:`~odoo.Widget.trigger` takes the name of the event to trigger as
-its first (mandatory) argument, any further arguments are treated as event
-data and passed directly to listeners.
-
-We can then set up a parent event instantiating our generic widget and
-listening to the ``user_chose`` event using :func:`~odoo.Widget.on`::
-
- local.HomePage = instance.Widget.extend({
- start: function() {
- var widget = new local.ConfirmWidget(this);
- widget.on("user_chose", this, this.user_chose);
- widget.appendTo(this.$el);
- },
- user_chose: function(confirm) {
- if (confirm) {
- console.log("The user agreed to continue");
- } else {
- console.log("The user refused to continue");
- }
- },
- });
-
-:func:`~odoo.Widget.on` binds a function to be called when the
-event identified by ``event_name`` is. The ``func`` argument is the
-function to call and ``object`` is the object to which that function is
-related if it is a method. The bound function will be called with the
-additional arguments of :func:`~odoo.Widget.trigger` if it has
-any. Example::
-
- start: function() {
- var widget = ...
- widget.on("my_event", this, this.my_event_triggered);
- widget.trigger("my_event", 1, 2, 3);
- },
- my_event_triggered: function(a, b, c) {
- console.log(a, b, c);
- // will print "1 2 3"
- }
-
-.. note::
-
- Triggering events on an other widget is generally a bad idea. The main
- exception to that rule is ``odoo.web.bus`` which exists specifically
- to broadcasts evens in which any widget could be interested throughout
- the Odoo web application.
-
-Properties
-----------
-
-Properties are very similar to normal object attributes in that they allow
-storing data on a widget instance, however they have the additional feature
-that they trigger events when set::
-
- start: function() {
- this.widget = ...
- this.widget.on("change:name", this, this.name_changed);
- this.widget.set("name", "Nicolas");
- },
- name_changed: function() {
- console.log("The new value of the property 'name' is", this.widget.get("name"));
- }
-
-* :func:`~odoo.Widget.set` sets the value of a property and triggers
- :samp:`change:{propname}` (where *propname* is the property name passed as
- first parameter to :func:`~odoo.Widget.set`) and ``change``
-* :func:`~odoo.Widget.get` retrieves the value of a property.
-
-Exercise
---------
-
-.. exercise:: Widget Properties and Events
-
- Create a widget ``ColorInputWidget`` that will display 3 ``<input
- type="text">``. Each of these ``<input>`` is dedicated to type a
- hexadecimal number from 00 to FF. When any of these ``<input>`` is
- modified by the user the widget must query the content of the three
- ``<input>``, concatenate their values to have a complete CSS color code
- (ie: ``#00FF00``) and put the result in a property named ``color``. Please
- note the jQuery ``change()`` event that you can bind on any HTML
- ``<input>`` element and the ``val()`` method that can query the current
- value of that ``<input>`` could be useful to you for this exercise.
-
- Then, modify the ``HomePage`` widget to instantiate ``ColorInputWidget``
- and display it. The ``HomePage`` widget should also display an empty
- rectangle. That rectangle must always, at any moment, have the same
- background color as the color in the ``color`` property of the
- ``ColorInputWidget`` instance.
-
- Use QWeb to generate all HTML.
-
- .. only:: solutions
-
- ::
-
- odoo.oepetstore = function(instance, local) {
- var _t = instance.web._t,
- _lt = instance.web._lt;
- var QWeb = instance.web.qweb;
-
- local.ColorInputWidget = instance.Widget.extend({
- template: "ColorInputWidget",
- events: {
- 'change input': 'input_changed'
- },
- start: function() {
- this.input_changed();
- return this._super();
- },
- input_changed: function() {
- var color = [
- "#",
- this.$(".oe_color_red").val(),
- this.$(".oe_color_green").val(),
- this.$(".oe_color_blue").val()
- ].join('');
- this.set("color", color);
- },
- });
-
- local.HomePage = instance.Widget.extend({
- template: "HomePage",
- start: function() {
- this.colorInput = new local.ColorInputWidget(this);
- this.colorInput.on("change:color", this, this.color_changed);
- return this.colorInput.appendTo(this.$el);
- },
- color_changed: function() {
- this.$(".oe_color_div").css("background-color", this.colorInput.get("color"));
- },
- });
-
- instance.web.client_actions.add('petstore.homepage', 'instance.oepetstore.HomePage');
- }
-
- .. code-block:: xml
-
- <?xml version="1.0" encoding="UTF-8"?>
- <templates xml:space="preserve">
- <t t-name="ColorInputWidget">
- <div>
- Red: <input type="text" class="oe_color_red" value="00"></input><br />
- Green: <input type="text" class="oe_color_green" value="00"></input><br />
- Blue: <input type="text" class="oe_color_blue" value="00"></input><br />
- </div>
- </t>
- <t t-name="HomePage">
- <div>
- <div class="oe_color_div"></div>
- </div>
- </t>
- </templates>
-
- .. code-block:: css
-
- .oe_color_div {
- width: 100px;
- height: 100px;
- margin: 10px;
- }
-
-Modify existing widgets and classes
-===================================
-
-The class system of the Odoo web framework allows direct modification of
-existing classes using the :func:`~odoo.web.Class.include` method::
-
- var TestClass = instance.web.Class.extend({
- testMethod: function() {
- return "hello";
- },
- });
-
- TestClass.include({
- testMethod: function() {
- return this._super() + " world";
- },
- });
-
- console.log(new TestClass().testMethod());
- // will print "hello world"
-
-This system is similar to the inheritance mechanism, except it will alter the
-target class in-place instead of creating a new class.
-
-In that case, ``this._super()`` will call the original implementation of a
-method being replaced/redefined. If the class already had sub-classes, all
-calls to ``this._super()`` in sub-classes will call the new implementations
-defined in the call to :func:`~odoo.web.Class.include`. This will also work
-if some instances of the class (or of any of its sub-classes) were created
-prior to the call to :func:`~odoo.Widget.include`.
-
-Translations
-============
-
-The process to translate text in Python and JavaScript code is very
-similar. You could have noticed these lines at the beginning of the
-``petstore.js`` file::
-
- var _t = instance.web._t,
- _lt = instance.web._lt;
-
-These lines are simply used to import the translation functions in the current
-JavaScript module. They are used thus::
-
- this.$el.text(_t("Hello user!"));
-
-In Odoo, translations files are automatically generated by scanning the source
-code. All piece of code that calls a certain function are detected and their
-content is added to a translation file that will then be sent to the
-translators. In Python, the function is ``_()``. In JavaScript the function is
-:func:`~odoo.web._t` (and also :func:`~odoo.web._lt`).
-
-``_t()`` will return the translation defined for the text it is given. If no
-translation is defined for that text, it will return the original text as-is.
-
-.. note::
-
- To inject user-provided values in translatable strings, it is recommended
- to use `_.str.sprintf
- <http://gabceb.github.io/underscore.string.site/#sprintf>`_ with named
- arguments *after* the translation::
-
- this.$el.text(_.str.sprintf(
- _t("Hello, %(user)s!"), {
- user: "Ed"
- }));
-
- This makes translatable strings more readable to translators, and gives
- them more flexibility to reorder or ignore parameters.
-
-:func:`~odoo.web._lt` ("lazy translate") is similar but somewhat more
-complex: instead of translating its parameter immediately, it returns
-an object which, when converted to a string, will perform the translation.
-
-It is used to define translatable terms before the translations system is
-initialized, for class attributes for instance (as modules are loaded before
-the user's language is configured and translations are downloaded).
-
-Communication with the Odoo Server
-==================================
-
-Contacting Models
------------------
-
-Most operations with Odoo involve communicating with *models* implementing
-business concern, these models will then (potentially) interact with some
-storage engine (usually PostgreSQL_).
-
-Although jQuery_ provides a `$.ajax`_ function for network interactions,
-communicating with Odoo requires additional metadata whose setup before every
-call would be verbose and error-prone. As a result, Odoo web provides
-higher-level communication primitives.
-
-To demonstrate this, the file ``petstore.py`` already contains a small model
-with a sample method:
-
-.. code-block:: python
-
- class message_of_the_day(models.Model):
- _name = "oepetstore.message_of_the_day"
-
- @api.model
- def my_method(self):
- return {"hello": "world"}
-
- message = fields.Text(),
- color = fields.Char(size=20),
-
-This declares a model with two fields, and a method ``my_method()`` which
-returns a literal dictionary.
-
-Here is a sample widget that calls ``my_method()`` and displays the result::
-
- local.HomePage = instance.Widget.extend({
- start: function() {
- var self = this;
- var model = new instance.web.Model("oepetstore.message_of_the_day");
- model.call("my_method", {context: new instance.web.CompoundContext()}).then(function(result) {
- self.$el.append("<div>Hello " + result["hello"] + "</div>");
- // will show "Hello world" to the user
- });
- },
- });
-
-The class used to call Odoo models is :class:`odoo.Model`. It is
-instantiated with the Odoo model's name as first parameter
-(``oepetstore.message_of_the_day`` here).
-
-:func:`~odoo.web.Model.call` can be used to call any (public) method of an
-Odoo model. It takes the following positional arguments:
-
-``name``
- The name of the method to call, ``my_method`` here
-``args``
- an array of `positional arguments`_ to provide to the method. Because the
- example has no positional argument to provide, the ``args`` parameter is not
- provided.
-
- Here is an other example with positional arguments:
-
- .. code-block:: python
-
- @api.model
- def my_method2(self, a, b, c): ...
-
- .. code-block:: javascript
-
- model.call("my_method", [1, 2, 3], ...
- // with this a=1, b=2 and c=3
-
-``kwargs``
- a mapping of `keyword arguments`_ to pass. The example provides a single
- named argument ``context``.
-
- .. code-block:: python
-
- @api.model
- def my_method2(self, a, b, c): ...
-
- .. code-block:: javascript
-
- model.call("my_method", [], {a: 1, b: 2, c: 3, ...
- // with this a=1, b=2 and c=3
-
-:func:`~odoo.Widget.call` returns a deferred resolved with the value
-returned by the model's method as first argument.
-
-CompoundContext
----------------
-
-The previous section used a ``context`` argument which was not explained in
-the method call::
-
- model.call("my_method", {context: new instance.web.CompoundContext()})
-
-The context is like a "magic" argument that the web client will always give to
-the server when calling a method. The context is a dictionary containing
-multiple keys. One of the most important key is the language of the user, used
-by the server to translate all the messages of the application. Another one is
-the time zone of the user, used to compute correctly dates and times if Odoo
-is used by people in different countries.
-
-The ``argument`` is necessary in all methods, otherwise bad things could
-happen (such as the application not being translated correctly). That's why,
-when you call a model's method, you should always provide that argument. The
-solution to achieve that is to use :class:`odoo.web.CompoundContext`.
-
-:class:`~odoo.web.CompoundContext` is a class used to pass the user's
-context (with language, time zone, etc...) to the server as well as adding new
-keys to the context (some models' methods use arbitrary keys added to the
-context). It is created by giving to its constructor any number of
-dictionaries or other :class:`~odoo.web.CompoundContext` instances. It will
-merge all those contexts before sending them to the server.
-
-.. code-block:: javascript
-
- model.call("my_method", {context: new instance.web.CompoundContext({'new_key': 'key_value'})})
-
-.. code-block:: python
-
- @api.model
- def my_method(self):
- print self.env.context
- // will print: {'lang': 'en_US', 'new_key': 'key_value', 'tz': 'Europe/Brussels', 'uid': 1}
-
-You can see the dictionary in the argument ``context`` contains some keys that
-are related to the configuration of the current user in Odoo plus the
-``new_key`` key that was added when instantiating
-:class:`~odoo.web.CompoundContext`.
-
-Queries
--------
-
-While :func:`~odoo.Model.call` is sufficient for any interaction with Odoo
-models, Odoo Web provides a helper for simpler and clearer querying of models
-(fetching of records based on various conditions):
-:func:`~odoo.Model.query` which acts as a shortcut for the common
-combination of :py:meth:`~odoo.models.Model.search` and
-::py:meth:`~odoo.models.Model.read`. It provides a clearer syntax to search
-and read models::
-
- model.query(['name', 'login', 'user_email', 'signature'])
- .filter([['active', '=', true], ['company_id', '=', main_company]])
- .limit(15)
- .all().then(function (users) {
- // do work with users records
- });
-
-versus::
-
- model.call('search', [['active', '=', true], ['company_id', '=', main_company]], {limit: 15})
- .then(function (ids) {
- return model.call('read', [ids, ['name', 'login', 'user_email', 'signature']]);
- })
- .then(function (users) {
- // do work with users records
- });
-
-* :func:`~odoo.web.Model.query` takes an optional list of fields as
- parameter (if no field is provided, all fields of the model are fetched). It
- returns a :class:`odoo.web.Query` which can be further customized before
- being executed
-* :class:`~odoo.web.Query` represents the query being built. It is
- immutable, methods to customize the query actually return a modified copy,
- so it's possible to use the original and the new version side-by-side. See
- :class:`~odoo.web.Query` for its customization options.
-
-When the query is set up as desired, simply call
-:func:`~odoo.web.Query.all` to execute it and return a
-deferred to its result. The result is the same as
-:py:meth:`~odoo.models.Model.read`'s, an array of dictionaries where each
-dictionary is a requested record, with each requested field a dictionary key.
-
-Exercises
-=========
-
-.. exercise:: Message of the Day
-
- Create a ``MessageOfTheDay`` widget displaying the last record of the
- ``oepetstore.message_of_the_day`` model. The widget should fetch its
- record as soon as it is displayed.
-
- Display the widget in the Pet Store home page.
-
- .. only:: solutions
-
- .. code-block:: javascript
-
- odoo.oepetstore = function(instance, local) {
- var _t = instance.web._t,
- _lt = instance.web._lt;
- var QWeb = instance.web.qweb;
-
- local.HomePage = instance.Widget.extend({
- template: "HomePage",
- start: function() {
- return new local.MessageOfTheDay(this).appendTo(this.$el);
- },
- });
-
- instance.web.client_actions.add('petstore.homepage', 'instance.oepetstore.HomePage');
-
- local.MessageOfTheDay = instance.Widget.extend({
- template: "MessageOfTheDay",
- start: function() {
- var self = this;
- return new instance.web.Model("oepetstore.message_of_the_day")
- .query(["message"])
- .order_by('-create_date', '-id')
- .first()
- .then(function(result) {
- self.$(".oe_mywidget_message_of_the_day").text(result.message);
- });
- },
- });
-
- }
-
- .. code-block:: xml
-
- <?xml version="1.0" encoding="UTF-8"?>
- <templates xml:space="preserve">
- <t t-name="HomePage">
- <div class="oe_petstore_homepage">
- </div>
- </t>
- <t t-name="MessageOfTheDay">
- <div class="oe_petstore_motd">
- <p class="oe_mywidget_message_of_the_day"></p>
- </div>
- </t>
- </templates>
-
- .. code-block:: css
-
- .oe_petstore_motd {
- margin: 5px;
- padding: 5px;
- border-radius: 3px;
- background-color: #F0EEEE;
- }
-
-.. exercise:: Pet Toys List
-
- Create a ``PetToysList`` widget displaying 5 toys (using their name and
- their images).
-
- The pet toys are not stored in a new model, instead they're stored in
- ``product.product`` using a special category *Pet Toys*. You can see the
- pre-generated toys and add new ones by going to
- :menuselection:`Pet Store --> Pet Store --> Pet Toys`. You will probably
- need to explore ``product.product`` to create the right domain to
- select just pet toys.
-
- In Odoo, images are generally stored in regular fields encoded as
- base64_, HTML supports displaying images straight from base64 with
- :samp:`<img src="data:{mime_type};base64,{base64_image_data}"/>`
-
- The ``PetToysList`` widget should be displayed on the home page on the
- right of the ``MessageOfTheDay`` widget. You will need to make some layout
- with CSS to achieve this.
-
- .. only:: solutions
-
- .. code-block:: javascript
-
- odoo.oepetstore = function(instance, local) {
- var _t = instance.web._t,
- _lt = instance.web._lt;
- var QWeb = instance.web.qweb;
-
- local.HomePage = instance.Widget.extend({
- template: "HomePage",
- start: function () {
- return Promise.all([
- new local.PetToysList(this).appendTo(this.$('.oe_petstore_homepage_left')),
- new local.MessageOfTheDay(this).appendTo(this.$('.oe_petstore_homepage_right'))
- ]);
- }
- });
- instance.web.client_actions.add('petstore.homepage', 'instance.oepetstore.HomePage');
-
- local.MessageOfTheDay = instance.Widget.extend({
- template: 'MessageOfTheDay',
- start: function () {
- var self = this;
- return new instance.web.Model('oepetstore.message_of_the_day')
- .query(["message"])
- .order_by('-create_date', '-id')
- .first()
- .then(function (result) {
- self.$(".oe_mywidget_message_of_the_day").text(result.message);
- });
- }
- });
-
- local.PetToysList = instance.Widget.extend({
- template: 'PetToysList',
- start: function () {
- var self = this;
- return new instance.web.Model('product.product')
- .query(['name', 'image'])
- .filter([['categ_id.name', '=', "Pet Toys"]])
- .limit(5)
- .all()
- .then(function (results) {
- _(results).each(function (item) {
- self.$el.append(QWeb.render('PetToy', {item: item}));
- });
- });
- }
- });
- }
-
- .. code-block:: xml
-
- <?xml version="1.0" encoding="UTF-8"?>
-
- <templates xml:space="preserve">
- <t t-name="HomePage">
- <div class="oe_petstore_homepage">
- <div class="oe_petstore_homepage_left"></div>
- <div class="oe_petstore_homepage_right"></div>
- </div>
- </t>
- <t t-name="MessageOfTheDay">
- <div class="oe_petstore_motd">
- <p class="oe_mywidget_message_of_the_day"></p>
- </div>
- </t>
- <t t-name="PetToysList">
- <div class="oe_petstore_pettoyslist">
- </div>
- </t>
- <t t-name="PetToy">
- <div class="oe_petstore_pettoy">
- <p><t t-esc="item.name"/></p>
- <p><img t-att-src="'data:image/jpg;base64,'+item.image"/></p>
- </div>
- </t>
- </templates>
-
- .. code-block:: css
-
- .oe_petstore_homepage {
- display: table;
- }
-
- .oe_petstore_homepage_left {
- display: table-cell;
- width : 300px;
- }
-
- .oe_petstore_homepage_right {
- display: table-cell;
- width : 300px;
- }
-
- .oe_petstore_motd {
- margin: 5px;
- padding: 5px;
- border-radius: 3px;
- background-color: #F0EEEE;
- }
-
- .oe_petstore_pettoyslist {
- padding: 5px;
- }
-
- .oe_petstore_pettoy {
- margin: 5px;
- padding: 5px;
- border-radius: 3px;
- background-color: #F0EEEE;
- }
-
-
-Existing web components
-=======================
-
-The Action Manager
-------------------
-
-In Odoo, many operations start from an :ref:`action <reference/actions>`:
-opening a menu item (to a view), printing a report, ...
-
-Actions are pieces of data describing how a client should react to the
-activation of a piece of content. Actions can be stored (and read through a
-model) or they can be generated on-the fly (locally to the client by
-javascript code, or remotely by a method of a model).
-
-In Odoo Web, the component responsible for handling and reacting to these
-actions is the *Action Manager*.
-
-Using the Action Manager
-''''''''''''''''''''''''
-
-The action manager can be invoked explicitly from javascript code by creating
-a dictionary describing :ref:`an action <reference/actions>` of the right
-type, and calling an action manager instance with it.
-
-:func:`~odoo.Widget.do_action` is a shortcut of :class:`~odoo.Widget`
-looking up the "current" action manager and executing the action::
-
- instance.web.TestWidget = instance.Widget.extend({
- dispatch_to_new_action: function() {
- this.do_action({
- type: 'ir.actions.act_window',
- res_model: "product.product",
- res_id: 1,
- views: [[false, 'form']],
- target: 'current',
- context: {},
- });
- },
- });
-
-The most common action ``type`` is ``ir.actions.act_window`` which provides
-views to a model (displays a model in various manners), its most common
-attributes are:
-
-``res_model``
- The model to display in views
-``res_id`` (optional)
- For form views, a preselected record in ``res_model``
-``views``
- Lists the views available through the action. A list of
- ``[view_id, view_type]``, ``view_id`` can either be the database identifier
- of a view of the right type, or ``false`` to use the view by default for
- the specified type. View types can not be present multiple times. The action
- will open the first view of the list by default.
-``target``
- Either ``current`` (the default) which replaces the "content" section of the
- web client by the action, or ``new`` to open the action in a dialog box.
-``context``
- Additional context data to use within the action.
-
-.. exercise:: Jump to Product
-
- Modify the ``PetToysList`` component so clicking on a toy replaces the
- homepage by the toy's form view.
-
- .. only:: solutions
-
- .. code-block:: javascript
-
- local.PetToysList = instance.Widget.extend({
- template: 'PetToysList',
- events: {
- 'click .oe_petstore_pettoy': 'selected_item',
- },
- start: function () {
- var self = this;
- return new instance.web.Model('product.product')
- .query(['name', 'image'])
- .filter([['categ_id.name', '=', "Pet Toys"]])
- .limit(5)
- .all()
- .then(function (results) {
- _(results).each(function (item) {
- self.$el.append(QWeb.render('PetToy', {item: item}));
- });
- });
- },
- selected_item: function (event) {
- this.do_action({
- type: 'ir.actions.act_window',
- res_model: 'product.product',
- res_id: $(event.currentTarget).data('id'),
- views: [[false, 'form']],
- });
- },
- });
-
- .. code-block:: xml
-
- <t t-name="PetToy">
- <div class="oe_petstore_pettoy" t-att-data-id="item.id">
- <p><t t-esc="item.name"/></p>
- <p><img t-attf-src="data:image/jpg;base64,{{item.image}}"/></p>
- </div>
- </t>
-
-.. _howtos/web/client_actions:
-
-Client Actions
---------------
-
-Throughout this guide, we used a simple ``HomePage`` widget which the web
-client automatically starts when we select the right menu item. But how did
-the Odoo web know to start this widget? Because the widget is registered as
-a *client action*.
-
-A client action is (as its name implies) an action type defined almost
-entirely in the client, in javascript for Odoo web. The server simply sends
-an action tag (an arbitrary name), and optionally adds a few parameters, but
-beyond that *everything* is handled by custom client code.
-
-Our widget is registered as the handler for the client action through this::
-
- instance.web.client_actions.add('petstore.homepage', 'instance.oepetstore.HomePage');
-
-
-``instance.web.client_actions`` is a :class:`~odoo.web.Registry` in which
-the action manager looks up client action handlers when it needs to execute
-one. The first parameter of :class:`~odoo.web.Registry.add` is the name
-(tag) of the client action, and the second parameter is the path to the widget
-from the Odoo web client root.
-
-When a client action must be executed, the action manager looks up its tag
-in the registry, walks the specified path and displays the widget it finds at
-the end.
-
-.. note:: a client action handler can also be a regular function, in whch case
- it'll be called and its result (if any) will be interpreted as the
- next action to execute.
-
-On the server side, we had simply defined an ``ir.actions.client`` action:
-
-.. code-block:: xml
-
- <record id="action_home_page" model="ir.actions.client">
- <field name="tag">petstore.homepage</field>
- </record>
-
-and a menu opening the action:
-
-.. code-block:: xml
-
- <menuitem id="home_page_petstore_menu" parent="petstore_menu"
- name="Home Page" action="action_home_page"/>
-
-Architecture of the Views
--------------------------
-
-Much of Odoo web's usefulness (and complexity) resides in views. Each view
-type is a way of displaying a model in the client.
-
-The View Manager
-''''''''''''''''
-
-When an ``ActionManager`` instance receive an action of type
-``ir.actions.act_window``, it delegates the synchronization and handling of
-the views themselves to a *view manager*, which will then set up one or
-multiple views depending on the original action's requirements:
-
-.. image:: web/viewarchitecture.*
- :align: center
- :width: 40%
-
-The Views
-'''''''''
-
-Most :ref:`Odoo views <reference/views>` are implemented through a subclass
-of :class:`odoo.web.View` which provides a bit of generic basic structure
-for handling events and displaying model information.
-
-The *search view* is considered a view type by the main Odoo framework, but
-handled separately by the web client (as it's a more permanent fixture and
-can interact with other views, which regular views don't do).
-
-A view is responsible for loading its own description XML (using
-:py:class:`~odoo.models.Model.fields_view_get`) and any other data source
-it needs. To that purpose, views are provided with an optional view
-identifier set as the :attr:`~odoo.web.View.view_id` attribute.
-
-Views are also provided with a :class:`~odoo.web.DataSet` instance which
-holds most necessary model information (the model name and possibly various
-record ids).
-
-Views may also want to handle search queries by overriding
-:func:`~odoo.web.View.do_search`, and updating their
-:class:`~odoo.web.DataSet` as necessary.
-
-The Form View Fields
---------------------
-
-A common need is the extension of the web form view to add new ways of
-displaying fields.
-
-All built-in fields have a default display implementation, a new
-form widget may be necessary to correctly interact with a new field type
-(e.g. a :term:`GIS` field) or to provide new representations and ways to
-interact with existing field types (e.g. validate
-:py:class:`~odoo.fields.Char` fields which should contain email addresses
-and display them as email links).
-
-To explicitly specify which form widget should be used to display a field,
-simply use the ``widget`` attribute in the view's XML description:
-
-.. code-block:: xml
-
- <field name="contact_mail" widget="email"/>
-
-.. note::
-
- * the same widget is used in both "view" (read-only) and "edit" modes
- of a form view, it's not possible to use a widget in one and an other
- widget in the other
- * and a given field (name) can not be used multiple times in the same form
- * a widget may ignore the current mode of the form view and remain the
- same in both view and edit modes
-
-.. todo:: most of this should probably move to an advanced form view guide
-
-Fields are instantiated by the form view after it has read its XML description
-and constructed the corresponding HTML representing that description. After
-that, the form view will communicate with the field objects using some
-methods. These methods are defined by the ``FieldInterface``
-interface. Almost all fields inherit the ``AbstractField`` abstract
-class. That class defines some default mechanisms that need to be implemented
-by most fields.
-
-Here are some of the responsibilities of a field class:
-
-* The field class must display and allow the user to edit the value of the field.
-* It must correctly implement the 3 field attributes available in all fields
- of Odoo. The ``AbstractField`` class already implements an algorithm that
- dynamically calculates the value of these attributes (they can change at any
- moment because their value change according to the value of other
- fields). Their values are stored in *Widget Properties* (the widget
- properties were explained earlier in this guide). It is the responsibility
- of each field class to check these widget properties and dynamically adapt
- depending of their values. Here is a description of each of these
- attributes:
-
- * ``required``: The field must have a value before saving. If ``required``
- is ``true`` and the field doesn't have a value, the method
- ``is_valid()`` of the field must return ``false``.
- * ``invisible``: When this is ``true``, the field must be invisible. The
- ``AbstractField`` class already has a basic implementation of this
- behavior that fits most fields.
- * ``readonly``: When ``true``, the field must not be editable by the
- user. Most fields in Odoo have a completely different behavior depending
- on the value of ``readonly``. As example, the ``FieldChar`` displays an
- HTML ``<input>`` when it is editable and simply displays the text when
- it is read-only. This also means it has much more code it would need to
- implement only one behavior, but this is necessary to ensure a good user
- experience.
-
-* Fields have two methods, ``set_value()`` and ``get_value()``, which are
- called by the form view to give it the value to display and get back the new
- value entered by the user. These methods must be able to handle the value as
- given by the Odoo server when a ``read()`` is performed on a model and give
- back a valid value for a ``write()``. Remember that the JavaScript/Python
- data types used to represent the values given by ``read()`` and given to
- ``write()`` is not necessarily the same in Odoo. As example, when you read a
- many2one, it is always a tuple whose first value is the id of the pointed
- record and the second one is the name get (ie: ``(15, "Agrolait")``). But
- when you write a many2one it must be a single integer, not a tuple
- anymore. ``AbstractField`` has a default implementation of these methods
- that works well for simple data type and set a widget property named
- ``value``.
-
-Please note that, to better understand how to implement fields, you are
-strongly encouraged to look at the definition of the ``FieldInterface``
-interface and the ``AbstractField`` class directly in the code of the Odoo web
-client.
-
-Creating a New Type of Field
-''''''''''''''''''''''''''''
-
-In this part we will explain how to create a new type of field. The example
-here will be to re-implement the ``FieldChar`` class and progressively explain
-each part.
-
-Simple Read-Only Field
-""""""""""""""""""""""
-
-Here is a first implementation that will only display text. The
-user will not be able to modify the content of the field.
-
-.. code-block:: javascript
-
- local.FieldChar2 = instance.web.form.AbstractField.extend({
- init: function() {
- this._super.apply(this, arguments);
- this.set("value", "");
- },
- render_value: function() {
- this.$el.text(this.get("value"));
- },
- });
-
- instance.web.form.widgets.add('char2', 'instance.oepetstore.FieldChar2');
-
-In this example, we declare a class named ``FieldChar2`` inheriting from
-``AbstractField``. We also register this class in the registry
-``instance.web.form.widgets`` under the key ``char2``. That will allow us to
-use this new field in any form view by specifying ``widget="char2"`` in the
-``<field/>`` tag in the XML declaration of the view.
-
-In this example, we define a single method: ``render_value()``. All it does is
-display the widget property ``value``. Those are two tools defined by the
-``AbstractField`` class. As explained before, the form view will call the
-method ``set_value()`` of the field to set the value to display. This method
-already has a default implementation in ``AbstractField`` which simply sets
-the widget property ``value``. ``AbstractField`` also watch the
-``change:value`` event on itself and calls the ``render_value()`` when it
-occurs. So, ``render_value()`` is a convenience method to implement in child
-classes to perform some operation each time the value of the field changes.
-
-In the ``init()`` method, we also define the default value of the field if
-none is specified by the form view (here we assume the default value of a
-``char`` field should be an empty string).
-
-Read-Write Field
-""""""""""""""""
-
-Read-only fields, which only display content and don't allow the
-user to modify it can be useful, but most fields in Odoo also allow editing.
-This makes the field classes more complicated, mostly because fields are
-supposed to handle both editable and non-editable mode, those modes are
-often completely different (for design and usability purpose) and the fields
-must be able to switch between modes at any moment.
-
-To know in which mode the current field should be, the ``AbstractField`` class
-sets a widget property named ``effective_readonly``. The field should watch
-for changes in that widget property and display the correct mode
-accordingly. Example::
-
- local.FieldChar2 = instance.web.form.AbstractField.extend({
- init: function() {
- this._super.apply(this, arguments);
- this.set("value", "");
- },
- start: function() {
- this.on("change:effective_readonly", this, function() {
- this.display_field();
- this.render_value();
- });
- this.display_field();
- return this._super();
- },
- display_field: function() {
- var self = this;
- this.$el.html(QWeb.render("FieldChar2", {widget: this}));
- if (! this.get("effective_readonly")) {
- this.$("input").change(function() {
- self.internal_set_value(self.$("input").val());
- });
- }
- },
- render_value: function() {
- if (this.get("effective_readonly")) {
- this.$el.text(this.get("value"));
- } else {
- this.$("input").val(this.get("value"));
- }
- },
- });
-
- instance.web.form.widgets.add('char2', 'instance.oepetstore.FieldChar2');
-
-.. code-block:: xml
-
- <t t-name="FieldChar2">
- <div class="oe_field_char2">
- <t t-if="! widget.get('effective_readonly')">
- <input type="text"></input>
- </t>
- </div>
- </t>
-
-In the ``start()`` method (which is called immediately after a widget has been
-appended to the DOM), we bind on the event ``change:effective_readonly``. That
-allows us to redisplay the field each time the widget property
-``effective_readonly`` changes. This event handler will call
-``display_field()``, which is also called directly in ``start()``. This
-``display_field()`` was created specifically for this field, it's not a method
-defined in ``AbstractField`` or any other class. We can use this method
-to display the content of the field depending on the current mode.
-
-From now on the conception of this field is typical, except there is a
-lot of verifications to know the state of the ``effective_readonly`` property:
-
-* In the QWeb template used to display the content of the widget, it displays
- an ``<input type="text" />`` if we are in read-write mode and nothing in
- particular in read-only mode.
-* In the ``display_field()`` method, we have to bind on the ``change`` event
- of the ``<input type="text" />`` to know when the user has changed the
- value. When it happens, we call the ``internal_set_value()`` method with the
- new value of the field. This is a convenience method provided by the
- ``AbstractField`` class. That method will set a new value in the ``value``
- property but will not trigger a call to ``render_value()`` (which is not
- necessary since the ``<input type="text" />`` already contains the correct
- value).
-* In ``render_value()``, we use a completely different code to display the
- value of the field depending if we are in read-only or in read-write mode.
-
-.. exercise:: Create a Color Field
-
- Create a ``FieldColor`` class. The value of this field should be a string
- containing a color code like those used in CSS (example: ``#FF0000`` for
- red). In read-only mode, this color field should display a little block
- whose color corresponds to the value of the field. In read-write mode, you
- should display an ``<input type="color" />``. That type of ``<input />``
- is an HTML5 component that doesn't work in all browsers but works well in
- Google Chrome. So it's OK to use as an exercise.
-
- You can use that widget in the form view of the ``message_of_the_day``
- model for its field named ``color``. As a bonus, you can change the
- ``MessageOfTheDay`` widget created in the previous part of this guide to
- display the message of the day with the background color indicated in the
- ``color`` field.
-
- .. only:: solutions
-
- .. code-block:: javascript
-
- local.FieldColor = instance.web.form.AbstractField.extend({
- events: {
- 'change input': function (e) {
- if (!this.get('effective_readonly')) {
- this.internal_set_value($(e.currentTarget).val());
- }
- }
- },
- init: function() {
- this._super.apply(this, arguments);
- this.set("value", "");
- },
- start: function() {
- this.on("change:effective_readonly", this, function() {
- this.display_field();
- this.render_value();
- });
- this.display_field();
- return this._super();
- },
- display_field: function() {
- this.$el.html(QWeb.render("FieldColor", {widget: this}));
- },
- render_value: function() {
- if (this.get("effective_readonly")) {
- this.$(".oe_field_color_content").css("background-color", this.get("value") || "#FFFFFF");
- } else {
- this.$("input").val(this.get("value") || "#FFFFFF");
- }
- },
- });
- instance.web.form.widgets.add('color', 'instance.oepetstore.FieldColor');
-
- .. code-block:: xml
-
- <t t-name="FieldColor">
- <div class="oe_field_color">
- <t t-if="widget.get('effective_readonly')">
- <div class="oe_field_color_content" />
- </t>
- <t t-if="! widget.get('effective_readonly')">
- <input type="color"></input>
- </t>
- </div>
- </t>
-
- .. code-block:: css
-
- .oe_field_color_content {
- height: 20px;
- width: 50px;
- border: 1px solid black;
- }
-
-The Form View Custom Widgets
-----------------------------
-
-Form fields are used to edit a single field, and are intrinsically linked to
-a field. Because this may be limiting, it is also possible to create
-*form widgets* which are not so restricted and have less ties to a specific
-lifecycle.
-
-Custom form widgets can be added to a form view through the ``widget`` tag:
-
-.. code-block:: xml
-
- <widget type="xxx" />
-
-This type of widget will simply be created by the form view during the
-creation of the HTML according to the XML definition. They have properties in
-common with the fields (like the ``effective_readonly`` property) but they are
-not assigned a precise field. And so they don't have methods like
-``get_value()`` and ``set_value()``. They must inherit from the ``FormWidget``
-abstract class.
-
-Form widgets can interact with form fields by listening for their changes and
-fetching or altering their values. They can access form fields through
-their :attr:`~odoo.web.form.FormWidget.field_manager` attribute::
-
- local.WidgetMultiplication = instance.web.form.FormWidget.extend({
- start: function() {
- this._super();
- this.field_manager.on("field_changed:integer_a", this, this.display_result);
- this.field_manager.on("field_changed:integer_b", this, this.display_result);
- this.display_result();
- },
- display_result: function() {
- var result = this.field_manager.get_field_value("integer_a") *
- this.field_manager.get_field_value("integer_b");
- this.$el.text("a*b = " + result);
- }
- });
-
- instance.web.form.custom_widgets.add('multiplication', 'instance.oepetstore.WidgetMultiplication');
-
-:attr:`~odoo.web.form.FormWidget` is generally the
-:class:`~odoo.web.form.FormView` itself, but features used from it should
-be limited to those defined by :class:`~odoo.web.form.FieldManagerMixin`,
-the most useful being:
-
-* :func:`~odoo.web.form.FieldManagerMixin.get_field_value(field_name)`
- which returns the value of a field.
-* :func:`~odoo.web.form.FieldManagerMixin.set_values(values)` sets multiple
- field values, takes a mapping of ``{field_name: value_to_set}``
-* An event :samp:`field_changed:{field_name}` is triggered any time the value
- of the field called ``field_name`` is changed
-
-.. exercise:: Show Coordinates on Google Map
-
- Add two fields to ``product.product`` storing a latitude and a longitude,
- then create a new form widget to display the latitude and longitude of
- a product's origin on a map
-
- To display the map, use Google Map's embedding:
-
- .. code-block:: html
-
- <iframe width="400" height="300" src="https://maps.google.com/?ie=UTF8&amp;ll=XXX,YYY&amp;output=embed">
- </iframe>
-
- where ``XXX`` should be replaced by the latitude and ``YYY`` by the
- longitude.
-
- Display the two position fields and a map widget using them in a new
- notebook page of the product's form view.
-
- .. only:: solutions
-
- .. code-block:: javascript
-
- local.WidgetCoordinates = instance.web.form.FormWidget.extend({
- start: function() {
- this._super();
- this.field_manager.on("field_changed:provider_latitude", this, this.display_map);
- this.field_manager.on("field_changed:provider_longitude", this, this.display_map);
- this.display_map();
- },
- display_map: function() {
- this.$el.html(QWeb.render("WidgetCoordinates", {
- "latitude": this.field_manager.get_field_value("provider_latitude") || 0,
- "longitude": this.field_manager.get_field_value("provider_longitude") || 0,
- }));
- }
- });
-
- instance.web.form.custom_widgets.add('coordinates', 'instance.oepetstore.WidgetCoordinates');
-
- .. code-block:: xml
-
- <t t-name="WidgetCoordinates">
- <iframe width="400" height="300"
- t-attf-src="https://maps.google.com/?ie=UTF8&amp;ll={{latitude}},{{longitude}}&amp;output=embed">
- </iframe>
- </t>
-
-.. exercise:: Get the Current Coordinate
-
- Add a button resetting the product's coordinates to the location of the
- user, you can get these coordinates using the
- `javascript geolocation API`_.
-
- Now we would like to display an additional button to automatically set the
- coordinates to the location of the current user.
-
- To get the coordinates of the user, an easy way is to use the geolocation
- JavaScript API. `See the online documentation to know how to use it`_.
-
- .. _See the online documentation to know how to use it: http://www.w3schools.com/html/html5_geolocation.asp
-
- Please also note that the user should not be able to
- click on that button when the form view is in read-only mode. So, this
- custom widget should handle correctly the ``effective_readonly`` property
- just like any field. One way to do this would be to make the button
- disappear when ``effective_readonly`` is true.
-
- .. only:: solutions
-
- .. code-block:: javascript
-
- local.WidgetCoordinates = instance.web.form.FormWidget.extend({
- events: {
- 'click button': function () {
- navigator.geolocation.getCurrentPosition(
- this.proxy('received_position'));
- }
- },
- start: function() {
- var sup = this._super();
- this.field_manager.on("field_changed:provider_latitude", this, this.display_map);
- this.field_manager.on("field_changed:provider_longitude", this, this.display_map);
- this.on("change:effective_readonly", this, this.display_map);
- this.display_map();
- return sup;
- },
- display_map: function() {
- this.$el.html(QWeb.render("WidgetCoordinates", {
- "latitude": this.field_manager.get_field_value("provider_latitude") || 0,
- "longitude": this.field_manager.get_field_value("provider_longitude") || 0,
- }));
- this.$("button").toggle(! this.get("effective_readonly"));
- },
- received_position: function(obj) {
- this.field_manager.set_values({
- "provider_latitude": obj.coords.latitude,
- "provider_longitude": obj.coords.longitude,
- });
- },
- });
-
- instance.web.form.custom_widgets.add('coordinates', 'instance.oepetstore.WidgetCoordinates');
-
- .. code-block:: xml
-
- <t t-name="WidgetCoordinates">
- <iframe width="400" height="300"
- t-attf-src="https://maps.google.com/?ie=UTF8&amp;ll={{latitude}},{{longitude}}&amp;output=embed">
- </iframe>
- <button>Get My Current Coordinate</button>
- </t>
-
-.. [#classes] as a separate concept from instances. In many languages classes
- are full-fledged objects and themselves instance (of
- metaclasses) but there remains two fairly separate hierarchies
- between classes and instances
-.. [#dombugs] as well as papering over cross-browser differences, although
- this has become less necessary over time
-
-.. _jQuery: http://jquery.org
-.. _Underscore.js: http://underscorejs.org
-.. _git: http://git-scm.com
-.. _CSS: http://www.w3.org/Style/CSS/Overview.en.html
-.. _Simple JavaScript Inheritance:
- http://ejohn.org/blog/simple-javascript-inheritance/
-.. _W3C DOM: http://www.w3.org/TR/DOM-Level-3-Core/
-.. _Qt: http://qt-project.org
-.. _Cocoa: https://developer.apple.com/technologies/mac/cocoa.html
-.. _GTK: http://www.gtk.org
-.. _template engine: http://en.wikipedia.org/wiki/Web_template_system
-.. _cross-site scripting: http://en.wikipedia.org/wiki/Cross-site_scripting
-.. _jQuery event object: http://api.jquery.com/category/events/event-object/
-.. _$.ajax: http://api.jquery.com/jquery.ajax/
-.. _base64: http://en.wikipedia.org/wiki/Base64
-.. _javascript geolocation API:
- http://diveintohtml5.info/geolocation.html
-.. _PostgreSQL: http://en.wikipedia.org/wiki/PostgreSQL
-.. _positional arguments:
-.. _keyword arguments:
- https://docs.python.org/2/glossary.html#term-argument
diff --git a/doc/howtos/web/about_odoo.png b/doc/howtos/web/about_odoo.png
deleted file mode 100644
index c155c5cf7f3..00000000000
--- a/doc/howtos/web/about_odoo.png
+++ /dev/null
Binary files differ
diff --git a/doc/howtos/web/devmode.png b/doc/howtos/web/devmode.png
deleted file mode 100644
index 52cfdcec44d..00000000000
--- a/doc/howtos/web/devmode.png
+++ /dev/null
Binary files differ
diff --git a/doc/howtos/web/qweb.png b/doc/howtos/web/qweb.png
deleted file mode 100644
index 56b4a635230..00000000000
--- a/doc/howtos/web/qweb.png
+++ /dev/null
Binary files differ
diff --git a/doc/howtos/web/viewarchitecture.dia b/doc/howtos/web/viewarchitecture.dia
deleted file mode 100644
index 0c28960a1ed..00000000000
--- a/doc/howtos/web/viewarchitecture.dia
+++ /dev/null
Binary files differ
diff --git a/doc/howtos/web/viewarchitecture.png b/doc/howtos/web/viewarchitecture.png
deleted file mode 100644
index 2d324ea599b..00000000000
--- a/doc/howtos/web/viewarchitecture.png
+++ /dev/null
Binary files differ
diff --git a/doc/howtos/web/viewarchitecture.svg b/doc/howtos/web/viewarchitecture.svg
deleted file mode 100644
index 170213ff14c..00000000000
--- a/doc/howtos/web/viewarchitecture.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg width="20cm" height="20cm" viewBox="301 86 387 399" xmlns="http://www.w3.org/2000/svg"><path fill="#ffffff" d="M414 87H560.55V115H414z"/><path fill="none" stroke-width="2" stroke="#000000" d="M414 87H560.55V115H414z"/><text font-size="16" x="487.275" y="106" fill="#000000" text-anchor="middle" font-family="sans-serif" font-weight="700">ActionManager</text><path fill="#ffffff" d="M414 115H560.55V123H414z"/><path fill="none" stroke-width="2" stroke="#000000" d="M414 115H560.55V123H414z"/><path fill="#ffffff" d="M414 123H560.55V131H414z"/><path fill="none" stroke-width="2" stroke="#000000" d="M414 123H560.55V131H414z"/><path fill="#ffffff" d="M460 320H513.25V348H460z"/><path fill="none" stroke-width="2" stroke="#000000" d="M460 320H513.25V348H460z"/><text font-size="16" x="486.625" y="339" fill="#000000" text-anchor="middle" font-family="sans-serif" font-style="italic" font-weight="700">View</text><path fill="#ffffff" d="M460 348H513.25V356H460z"/><path fill="none" stroke-width="2" stroke="#000000" d="M460 348H513.25V356H460z"/><path fill="#ffffff" d="M460 356H513.25V364H460z"/><path fill="none" stroke-width="2" stroke="#000000" d="M460 356H513.25V364H460z"/><g><path fill="#ffffff" d="M421 204H553.35V232H421z"/><path fill="none" stroke-width="2" stroke="#000000" d="M421 204H553.35V232H421z"/><text font-size="16" x="487.175" y="223" fill="#000000" text-anchor="middle" font-family="sans-serif" font-weight="700">ViewManager</text><path fill="#ffffff" d="M421 232H553.35V240H421z"/><path fill="none" stroke-width="2" stroke="#000000" d="M421 232H553.35V240H421z"/><path fill="#ffffff" d="M421 240H553.35V248H421z"/><path fill="none" stroke-width="2" stroke="#000000" d="M421 240H553.35V248H421z"/></g><g><path fill="none" stroke-width="2" stroke="#000000" d="M487.275 157.177L487.275 174.5 487.175 174.5 487.175 202.994"/><path fill="#000000" d="M487.275 132.006L492.075 146.006 487.275 160.006 482.475 146.006z"/><path fill="none" stroke-width="2" stroke="#000000" d="M487.275 132.006L492.075 146.006 487.275 160.006 482.475 146.006z"/><text font-size="12.8" x="491.175" y="198.994" fill="#000000" font-family="monospace">1</text></g><g><path fill="none" stroke-width="2" stroke="#000000" d="M487.175 274.177L487.175 291 486.625 291 486.625 318.994"/><path fill="#000000" d="M487.175 249.006L491.975 263.006 487.175 277.006 482.375 263.006z"/><path fill="none" stroke-width="2" stroke="#000000" d="M487.175 249.006L491.975 263.006 487.175 277.006 482.375 263.006z"/><text font-size="12.8" x="490.625" y="314.994" fill="#000000" font-family="monospace">1..*</text></g><g><path fill="#ffffff" d="M302 440H401.1V468H302z"/><path fill="none" stroke-width="2" stroke="#000000" d="M302 440H401.1V468H302z"/><text font-size="16" x="351.55" y="459" fill="#000000" text-anchor="middle" font-family="sans-serif" font-weight="700">FormView</text><path fill="#ffffff" d="M302 468H401.1V476H302z"/><path fill="none" stroke-width="2" stroke="#000000" d="M302 468H401.1V476H302z"/><path fill="#ffffff" d="M302 476H401.1V484H302z"/><path fill="none" stroke-width="2" stroke="#000000" d="M302 476H401.1V484H302z"/></g><g><path fill="#ffffff" d="M443.8 438.8H529.9V466.8H443.8z"/><path fill="none" stroke-width="2" stroke="#000000" d="M443.8 438.8H529.9V466.8H443.8z"/><text font-size="16" x="486.85" y="457.8" fill="#000000" text-anchor="middle" font-family="sans-serif" font-weight="700">ListView</text><path fill="#ffffff" d="M443.8 466.8H529.9V474.8H443.8z"/><path fill="none" stroke-width="2" stroke="#000000" d="M443.8 466.8H529.9V474.8H443.8z"/><path fill="#ffffff" d="M443.8 474.8H529.9V482.8H443.8z"/><path fill="none" stroke-width="2" stroke="#000000" d="M443.8 474.8H529.9V482.8H443.8z"/></g><g><path fill="#ffffff" d="M564.8 438.8H686.3V466.8H564.8z"/><path fill="none" stroke-width="2" stroke="#000000" d="M564.8 438.8H686.3V466.8H564.8z"/><text font-size="16" x="625.55" y="457.8" fill="#000000" text-anchor="middle" font-family="sans-serif" font-weight="700">KanbanView</text><path fill="#ffffff" d="M564.8 466.8H686.3V474.8H564.8z"/><path fill="none" stroke-width="2" stroke="#000000" d="M564.8 466.8H686.3V474.8H564.8z"/><path fill="#ffffff" d="M564.8 474.8H686.3V482.8H564.8z"/><path fill="none" stroke-width="2" stroke="#000000" d="M564.8 474.8H686.3V482.8H564.8z"/></g><g><path fill="none" stroke-width="2" stroke-dasharray="8" stroke="#000000" d="M486.625 382.236L486.625 410 351.55 410 351.55 440"/><path fill="#ffffff" d="M494.625 382.236L486.625 366.236 478.625 382.236z"/><path fill="none" stroke-width="2" stroke="#000000" d="M494.625 382.236L486.625 366.236 478.625 382.236z"/></g><g><path fill="none" stroke-width="2" stroke-dasharray="8" stroke="#000000" d="M486.625 383.242L486.625 409.903 486.85 409.903 486.85 438.8"/><path fill="#ffffff" d="M494.625 383.242L486.625 367.242 478.625 383.242z"/><path fill="none" stroke-width="2" stroke="#000000" d="M494.625 383.242L486.625 367.242 478.625 383.242z"/></g><g><path fill="none" stroke-width="2" stroke-dasharray="8" stroke="#000000" d="M486.625 383.242L486.625 409.903 625.55 409.903 625.55 438.8"/><path fill="#ffffff" d="M494.625 383.242L486.625 367.242 478.625 383.242z"/><path fill="none" stroke-width="2" stroke="#000000" d="M494.625 383.242L486.625 367.242 478.625 383.242z"/></g></svg> \ No newline at end of file
diff --git a/doc/howtos/website.rst b/doc/howtos/website.rst
deleted file mode 100644
index 28e817da408..00000000000
--- a/doc/howtos/website.rst
+++ /dev/null
@@ -1,513 +0,0 @@
-:banner: banners/build_a_website.jpg
-
-.. queue:: website/series
-
-==================
-Building a Website
-==================
-
-.. warning::
-
- * This guide assumes `basic knowledge of Python
- <http://docs.python.org/2/tutorial/>`_
- * This guide assumes :ref:`an installed Odoo <setup/install>`
-
-Creating a basic module
-=======================
-
-In Odoo, tasks are performed by creating modules.
-
-Modules customize the behavior of an Odoo installation, either by adding new
-behaviors or by altering existing ones (including behaviors added by other
-modules).
-
-:ref:`Odoo's scaffolding <reference/cmdline/scaffold>` can setup a basic
-module. To quickly get started simply invoke:
-
-.. code-block:: console
-
- $ ./odoo-bin scaffold Academy my-modules
-
-This will automatically create a ``my-modules`` *module directory* with an
-``academy`` module inside. The directory can be an existing module directory
-if you want, but the module name must be unique within the directory.
-
-.. patch::
- :hidden:
-
-A demonstration module
-======================
-
-We have a "complete" module ready for installation.
-
-Although it does absolutely nothing we can install it:
-
-* start the Odoo server
-
- .. code-block:: console
-
- $ ./odoo-bin --addons-path addons,my-modules
-
-* go to http://localhost:8069
-* create a new database including demonstration data
-* to go :menuselection:`Settings --> Modules --> Modules`
-* in the top-right corner remove the *Installed* filter and search for
- *academy*
-* click the :guilabel:`Install` button for the *Academy* module
-
-To the browser
-==============
-
-:ref:`Controllers <reference/controllers>` interpret browser requests and
-send data back.
-
-Add a simple controller and ensure it is imported by ``__init__.py`` (so
-Odoo can find it):
-
-.. patch::
-
-Shut down your server (:kbd:`^C`) then restart it:
-
-.. code-block:: console
-
- $ ./odoo-bin --addons-path addons,my-modules
-
-and open a page to http://localhost:8069/academy/academy/, you should see your
-"page" appear:
-
-.. figure:: website/helloworld.png
-
-Templates
-=========
-
-Generating HTML in Python isn't very pleasant.
-
-The usual solution is templates_, pseudo-documents with placeholders and
-display logic. Odoo allows any Python templating system, but provides its
-own :ref:`QWeb <reference/qweb>` templating system which integrates with other
-features.
-
-Create a template and ensure the template file is registered in the
-``__manifest__.py`` manifest, and alter the controller to use our template:
-
-.. patch::
-
-The templates iterates (``t-foreach``) on all the teachers (passed through the
-*template context*), and prints each teacher in its own paragraph.
-
-Finally restart Odoo and update the module's data (to install the template)
-by going to :menuselection:`Settings --> Modules --> Modules -->
-Academy` and clicking :guilabel:`Upgrade`.
-
-.. tip::
-
- Alternatively, Odoo can be restarted :option:`and update modules at
- the same time<odoo-bin -u>`:
-
- .. code-block:: console
-
- $ odoo-bin --addons-path addons,my-modules -d academy -u academy
-
-Going to http://localhost:8069/academy/academy/ should now result in:
-
-.. image:: website/basic-list.png
-
-Storing data in Odoo
-====================
-
-:ref:`Odoo models <reference/orm/model>` map to database tables.
-
-In the previous section we just displayed a list of string entered statically
-in the Python code. This doesn't allow modifications or persistent storage
-so we'll now move our data to the database.
-
-Defining the data model
------------------------
-
-Define a teacher model, and ensure it is imported from ``__init__.py`` so it
-is correctly loaded:
-
-.. patch::
-
-Then setup :ref:`basic access control <reference/security/acl>` for the model
-and add them to the manifest:
-
-.. patch::
-
-this simply gives read access (``perm_read``) to all users (``group_id:id``
-left empty).
-
-.. note::
-
- :ref:`Data files <reference/data>` (XML or CSV) must be added to the
- module manifest, Python files (models or controllers) don't but have to
- be imported from ``__init__.py`` (directly or indirectly)
-
-.. warning::
-
- the administrator user bypasses access control, they have access to all
- models even if not given access
-
-Demonstration data
-------------------
-
-The second step is to add some demonstration data to the system so it's
-possible to test it easily. This is done by adding a ``demo``
-:ref:`data file <reference/data>`, which must be linked from the manifest:
-
-.. patch::
-
-.. tip::
-
- :ref:`Data files <reference/data>` can be used for demo and non-demo data.
- Demo data are only loaded in "demonstration mode" and can be used for flow
- testing and demonstration, non-demo data are always loaded and used as
- initial system setup.
-
- In this case we're using demonstration data because an actual user of the
- system would want to input or import their own teachers list, this list
- is only useful for testing.
-
-Accessing the data
-------------------
-
-The last step is to alter model and template to use our demonstration data:
-
-#. fetch the records from the database instead of having a static list
-#. Because :meth:`~odoo.models.Model.search` returns a set of records
- matching the filter ("all records" here), alter the template to print each
- teacher's ``name``
-
-.. patch::
-
-Restart the server and update the module (in order to update the manifest
-and templates and load the demo file) then navigate to
-http://localhost:8069/academy/academy/. The page should look slightly
-different: names should simply be prefixed by a number (the database
-identifier for the teacher).
-
-Website support
-===============
-
-Odoo bundles a module dedicated to building websites.
-
-So far we've used controllers fairly directly, but Odoo 8 added deeper
-integration and a few other services (e.g. default styling, theming) via the
-``website`` module.
-
-#. first, add ``website`` as a dependency to ``academy``
-#. then add the ``website=True`` flag on the controller, this sets up a few
- new variables on :ref:`the request object <reference/http/request>` and
- allows using the website layout in our template
-#. use the website layout in the template
-
-.. patch::
-
-After restarting the server while updating the module (in order to update the
-manifest and template) access http://localhost:8069/academy/academy/ should
-yield a nicer looking page with branding and a number of built-in page
-elements (top-level menu, footer, …)
-
-.. image:: website/layout.png
-
-The website layout also provides support for editing tools: click
-:guilabel:`Sign In` (in the top-right), fill the credentials in (``admin`` /
-``admin`` by default) then click :guilabel:`Log In`.
-
-You're now in Odoo "proper": the administrative interface. For now click on
-the :guilabel:`Website` menu item (top-left corner.
-
-We're back in the website but as an administrator, with access to advanced
-editing features provided by the *website* support:
-
-* a template code editor (:menuselection:`Customize --> HTML Editor`) where
- you can see and edit all templates used for the current page
-* the :guilabel:`Edit` button in the top-left switches to "editing mode" where
- blocks (snippets) and rich text editing are available
-* a number of other features such as mobile preview or :abbr:`SEO (Search
- Engine Optimization)`
-
-URLs and routing
-================
-
-Controller methods are associated with *routes* via the
-:func:`~odoo.http.route` decorator which takes a routing string and a
-number of attributes to customise its behavior or security.
-
-We've seen a "literal" routing string, which matches a URL section exactly,
-but routing strings can also use `converter patterns`_ which match bits
-of URLs and make those available as local variables. For instance we can
-create a new controller method which takes a bit of URL and prints it out:
-
-.. patch::
-
-restart Odoo, access http://localhost:8069/academy/Alice/ and
-http://localhost:8069/academy/Bob/ and see the difference.
-
-As the name indicates, `converter patterns`_ don't just do extraction, they
-also do *validation* and *conversion*, so we can change the new controller
-to only accept integers:
-
-.. patch::
-
-Restart Odoo, access http://localhost:8069/academy/2, note how the old value
-was a string, but the new one was converted to an integers. Try accessing
-http://localhost:8069/academy/Carol/ and note that the page was not found:
-since "Carol" is not an integer, the route was ignored and no route could be
-found.
-
-Odoo provides an additional converter called ``model`` which provides records
-directly when given their id. Let's use this to create a generic page for
-teacher biographies:
-
-.. patch::
-
-then change the list of model to link to our new controller:
-
-.. patch::
-
-Restart Odoo and upgrade the module, then you can visit each teacher's page.
-As an exercise, try adding blocks to a teacher's page to write a biography,
-then go to another teacher's page and so forth. You will discover, that your
-biography is shared between all teachers, because blocks are added to the
-*template*, and the *biography* template is shared between all teachers, when
-one page is edited they're all edited at the same time.
-
-Field editing
-=============
-
-Data which is specific to a record should be saved on that record, so let us
-add a new biography field to our teachers:
-
-.. patch::
-
-Restart Odoo and update the views, reload the teacher's page and… the field
-is invisible since it contains nothing.
-
-.. todo:: the view has been set to noupdate because modified previously,
- force via ``-i`` or do something else?
-
-For record fields, templates can use a special ``t-field`` directive which
-allows editing the field content from the website using field-specific
-interfaces. Change the *person* template to use ``t-field``:
-
-.. patch::
-
-Restart Odoo and upgrade the module, there is now a placeholder under the
-teacher's name and a new zone for blocks in :guilabel:`Edit` mode. Content
-dropped there is stored in the corresponding teacher's ``biography`` field, and
-thus specific to that teacher.
-
-The teacher's name is also editable, and when saved the change is visible on
-the index page.
-
-``t-field`` can also take formatting options which depend on the exact field.
-For instance if we display the modification date for a teacher's record:
-
-.. patch::
-
-it is displayed in a very "computery" manner and hard to read, but we could
-ask for a human-readable version:
-
-.. patch::
-
-or a relative display:
-
-.. patch::
-
-Administration and ERP integration
-==================================
-
-A brief and incomplete introduction to the Odoo administration
---------------------------------------------------------------
-
-The Odoo administration was briefly seen during the `website support`_ section.
-We can go back to it using :menuselection:`Administrator --> Administrator` in
-the menu (or :guilabel:`Sign In` if you're signed out).
-
-The conceptual structure of the Odoo backend is simple:
-
-#. first are menus, a tree (menus can have sub-menus) of records. Menus
- without children map to…
-#. actions. Actions have various types: links, reports, code which Odoo should
- execute or data display. Data display actions are called *window actions*,
- and tell Odoo to display a given *model* according to a set of views…
-#. a view has a type, a broad category to which it corresponds (a list,
- a graph, a calendar) and an *architecture* which customises the way the
- model is displayed inside the view.
-
-Editing in the Odoo administration
-----------------------------------
-
-By default, an Odoo model is essentially invisible to a user. To make it
-visible it must be available through an action, which itself needs to be
-reachable, generally through a menu.
-
-Let's create a menu for our model:
-
-.. patch::
-
-then accessing http://localhost:8069/web/ in the top left should be a menu
-:guilabel:`Academy`, which is selected by default, as it is the first menu,
-and having opened a listing of teachers. From the listing it is possible to
-:guilabel:`Create` new teacher records, and to switch to the "form" by-record
-view.
-
-If there is no definition of how to present records (a
-:ref:`view <reference/views>`) Odoo will automatically create a basic one
-on-the-fly. In our case it works for the "list" view for now (only displays
-the teacher's name) but in the "form" view the HTML ``biography`` field is
-displayed side-by-side with the ``name`` field and not given enough space.
-Let's define a custom form view to make viewing and editing teacher records
-a better experience:
-
-.. patch::
-
-Relations between models
-------------------------
-
-We have seen a pair of "basic" fields stored directly in the record. There are
-:ref:`a number of basic fields <reference/fields/basic>`. The second
-broad categories of fields are :ref:`relational
-<reference/fields/relational>` and used to link records to one another
-(within a model or across models).
-
-For demonstration, let's create a *courses* model. Each course should have a
-``teacher`` field, linking to a single teacher record, but each teacher can
-teach many courses:
-
-.. patch::
-
-let's also add views so we can see and edit a course's teacher:
-
-.. patch::
-
-It should also be possible to create new courses directly from a teacher's
-page, or to see all the courses they teach, so add
-:class:`the inverse relationship <odoo.fields.One2many>` to the *teachers*
-model:
-
-.. patch::
-
-Discussions and notifications
------------------------------
-
-Odoo provides technical models, which don't directly fulfill business needs
-but which add capabilities to business objects without having to build
-them by hand.
-
-One of these is the *Chatter* system, part of Odoo's email and messaging
-system, which can add notifications and discussion threads to any model.
-The model simply has to :attr:`~odoo.models.Model._inherit`
-``mail.thread``, and add the ``message_ids`` field to its form view to display
-the discussion thread. Discussion threads are per-record.
-
-For our academy, it makes sense to allow discussing courses to handle e.g.
-scheduling changes or discussions between teachers and assistants:
-
-.. patch::
-
-At the bottom of each course form, there is now a discussion thread and the
-possibility for users of the system to leave messages and follow or unfollow
-discussions linked to specific courses.
-
-Selling courses
----------------
-
-Odoo also provides business models which allow using or opting in business
-needs more directly. For instance the ``website_sale`` module sets up an
-e-commerce site based on the products in the Odoo system. We can easily make
-course subscriptions sellable by making our courses specific kinds of
-products.
-
-Rather than the previous classical inheritance, this means replacing our
-*course* model by the *product* model, and extending products in-place (to
-add anything we need to it).
-
-First of all we need to add a dependency on ``website_sale`` so we get both
-products (via ``sale``) and the ecommerce interface:
-
-.. patch::
-
-restart Odoo, update your module, there is now a :guilabel:`Shop` section in
-the website, listing a number of pre-filled (via demonstration data) products.
-
-The second step is to replace the *courses* model by ``product.template``,
-and add a new category of product for courses:
-
-.. patch::
-
-With this installed, a few courses are now available in the :guilabel:`Shop`,
-though they may have to be looked for.
-
-.. note::
-
- * to extend a model in-place, it's :attr:`inherited
- <odoo.models.Model._inherit>` without giving it a new
- :attr:`~odoo.models.Model._name`
- * ``product.template`` already uses the discussions system, so we can
- remove it from our extension model
- * we're creating our courses as *published* by default so they can be
- seen without having to log in
-
-Altering existing views
------------------------
-
-So far, we have briefly seen:
-
-* the creation of new models
-* the creation of new views
-* the creation of new records
-* the alteration of existing models
-
-We're left with the alteration of existing records and the alteration of
-existing views. We'll do both on the :guilabel:`Shop` pages.
-
-View alteration is done by creating *extension* views, which are applied on
-top of the original view and alter it. These alteration views can be added or
-removed without modifying the original, making it easier to try things out and
-roll changes back.
-
-Since our courses are free, there is no reason to display their price on the
-shop page, so we're going to alter the view and hide the price if it's 0. The
-first task is finding out which view displays the price, this can be done via
-:menuselection:`Customize --> HTML Editor` which lets us read the various
-templates involved in rendering a page. Going through a few of them, "Product
-item" looks a likely culprit.
-
-Altering view architectures is done in 3 steps:
-
-#. Create a new view
-#. Extend the view to modify by setting the new view's ``inherit_id`` to the
- modified view's external id
-#. In the architecture, use the ``xpath`` tag to select and alter elements
- from the modified view
-
-.. patch::
-
-The second thing we will change is making the product categories sidebar
-visible by default: :menuselection:`Customize --> Product Categories` lets
-you toggle a tree of product categories (used to filter the main display) on
-and off.
-
-This is done via the ``customize_show`` and ``active`` fields of extension
-templates: an extension template (such as the one we've just created) can be
-*customize_show=True*. This choice will display the view in the :guilabel:`Customize`
-menu with a check box, allowing administrators to activate or disable them
-(and easily customize their website pages).
-
-We simply need to modify the *Product Categories* record and set its default
-to *active="True"*:
-
-.. patch::
-
-With this, the *Product Categories* sidebar will automatically be enabled when
-the *Academy* module is installed.
-
-.. _templates: http://en.wikipedia.org/wiki/Web_template
-.. _postgres:
-.. _postgresql:
- http://www.postgresql.org
-.. _converter pattern:
-.. _converter patterns:
- http://werkzeug.pocoo.org/docs/routing/#rule-format
diff --git a/doc/howtos/website/basic-acl b/doc/howtos/website/basic-acl
deleted file mode 100644
index c31576ce159..00000000000
--- a/doc/howtos/website/basic-acl
+++ /dev/null
@@ -1,23 +0,0 @@
-# HG changeset patch
-# Parent 91c0cc5b319e7bf240d359817b8bd044769a4f5c
-# Parent 0a9ec16d98785205f25868bc23485569a1444cf3
-
-diff --git a/academy/__manifest__.py b/academy/__manifest__.py
---- a/academy/__manifest__.py
-+++ b/academy/__manifest__.py
-@@ -24,7 +24,7 @@
-
- # always loaded
- 'data': [
-- # 'security/ir.model.access.csv',
-+ 'security/ir.model.access.csv',
- 'templates.xml',
- ],
- # only loaded in demonstration mode
-diff --git a/academy/security/ir.model.access.csv b/academy/security/ir.model.access.csv
---- a/academy/security/ir.model.access.csv
-+++ b/academy/security/ir.model.access.csv
-@@ -1,2 +1,2 @@
- id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
--access_academy_academy,academy.academy,model_academy_academy,,1,0,0,0
-+access_academy_teachers,access_academy_teachers,model_academy_teachers,,1,0,0,0
diff --git a/doc/howtos/website/basic-controller b/doc/howtos/website/basic-controller
deleted file mode 100644
index 831ecf6fa25..00000000000
--- a/doc/howtos/website/basic-controller
+++ /dev/null
@@ -1,22 +0,0 @@
-# HG changeset patch
-# Parent 78b4476f35cbef86ee4f858daf843e3b932fb9fa
-# Parent 0a4f5e3206a0738201a40d2d1a88f41fdbbc98bf
-
-diff --git a/academy/controllers.py b/academy/controllers.py
---- a/academy/controllers.py
-+++ b/academy/controllers.py
-@@ -1,10 +1,10 @@
- # -*- coding: utf-8 -*-
- from odoo import http
-
--# class Academy(http.Controller):
--# @http.route('/academy/academy/', auth='public')
--# def index(self, **kw):
--# return "Hello, world"
-+class Academy(http.Controller):
-+ @http.route('/academy/academy/', auth='public')
-+ def index(self, **kw):
-+ return "Hello, world"
-
- # @http.route('/academy/academy/objects/', auth='public')
- # def list(self, **kw):
diff --git a/doc/howtos/website/basic-list.png b/doc/howtos/website/basic-list.png
deleted file mode 100644
index 3eb76ddf7c2..00000000000
--- a/doc/howtos/website/basic-list.png
+++ /dev/null
Binary files differ
diff --git a/doc/howtos/website/basic-model b/doc/howtos/website/basic-model
deleted file mode 100644
index a27d0543bce..00000000000
--- a/doc/howtos/website/basic-model
+++ /dev/null
@@ -1,18 +0,0 @@
-# HG changeset patch
-# Parent 3e800beb7db0f9f05bfd4db275c86e8903d4f127
-# Parent 4082801768b28c2871920e41d23b7879763e763e
-
-diff --git a/academy/models.py b/academy/models.py
---- a/academy/models.py
-+++ b/academy/models.py
-@@ -2,7 +2,7 @@
-
- from odoo import models, fields, api
-
--# class academy(models.Model):
--# _name = 'academy.academy'
-+class Teachers(models.Model):
-+ _name = 'academy.teachers'
-
--# name = fields.Char()
-+ name = fields.Char()
diff --git a/doc/howtos/website/biography-esc b/doc/howtos/website/biography-esc
deleted file mode 100644
index 345623aa903..00000000000
--- a/doc/howtos/website/biography-esc
+++ /dev/null
@@ -1,23 +0,0 @@
-# HG changeset patch
-# Parent 4814709fe1c52515f5108623c2c8f0bce57ffac0
-# Parent 926b3fdd1bba025d9543bb85ac40159b392ba13c
-
-diff --git a/academy/models.py b/academy/models.py
---- a/academy/models.py
-+++ b/academy/models.py
-@@ -6,3 +6,4 @@ class Teachers(models.Model):
- _name = 'academy.teachers'
-
- name = fields.Char()
-+ biography = fields.Html()
-diff --git a/academy/templates.xml b/academy/templates.xml
---- a/academy/templates.xml
-+++ b/academy/templates.xml
-@@ -21,6 +21,7 @@
- <div class="oe_structure">
- <div class="container">
- <h3><t t-esc="person.name"/></h3>
-+ <div><t t-esc="person.biography"/></div>
- </div>
- </div>
- <div class="oe_structure"/>
diff --git a/doc/howtos/website/biography-field b/doc/howtos/website/biography-field
deleted file mode 100644
index 0fb14a2e565..00000000000
--- a/doc/howtos/website/biography-field
+++ /dev/null
@@ -1,18 +0,0 @@
-# HG changeset patch
-# Parent 216904cc7636679adbf1a5a211070e739c59c3a8
-# Parent edeaf1ebff99c9b3d7cbe1925ca3d2ece519ba52
-
-diff --git a/academy/templates.xml b/academy/templates.xml
---- a/academy/templates.xml
-+++ b/academy/templates.xml
-@@ -20,8 +20,8 @@
- <div class="oe_structure"/>
- <div class="oe_structure">
- <div class="container">
-- <h3><t t-esc="person.name"/></h3>
-- <div><t t-esc="person.biography"/></div>
-+ <h3 t-field="person.name"/>
-+ <div t-field="person.biography"/>
- </div>
- </div>
- <div class="oe_structure"/>
diff --git a/doc/howtos/website/chatter-backend b/doc/howtos/website/chatter-backend
deleted file mode 100644
index 1521a78a272..00000000000
--- a/doc/howtos/website/chatter-backend
+++ /dev/null
@@ -1,29 +0,0 @@
-# HG changeset patch
-# Parent 957395d27f63dfdb2ea0dacdbe72bc35e724ddcc
-# Parent 7156498d3cffb6128e73da2e351f2b5af5f7be63
-
-diff --git a/academy/models.py b/academy/models.py
---- a/academy/models.py
-+++ b/academy/models.py
-@@ -12,6 +12,7 @@ class Teachers(models.Model):
-
- class Courses(models.Model):
- _name = 'academy.courses'
-+ _inherit = 'mail.thread'
-
- name = fields.Char()
- teacher_id = fields.Many2one('academy.teachers', string="Teacher")
-diff --git a/academy/views.xml b/academy/views.xml
---- a/academy/views.xml
-+++ b/academy/views.xml
-@@ -61,6 +61,10 @@
- <label for="teacher_id"/>
- <field name="teacher_id"/>
- </sheet>
-+ <div class="oe_chatter">
-+ <field name="message_follower_ids" widget="mail_followers"/>
-+ <field name="message_ids" widget="mail_thread"/>
-+ </div>
- </form>
- </field>
- </record>
diff --git a/doc/howtos/website/converter-model b/doc/howtos/website/converter-model
deleted file mode 100644
index 3cd0e86da21..00000000000
--- a/doc/howtos/website/converter-model
+++ /dev/null
@@ -1,44 +0,0 @@
-# HG changeset patch
-# Parent 122340f4360287bbc53f54e53ac609a8e7237796
-# Parent 1f9194514fa81c49b9bc7922a010513d816a0c2e
-
-diff --git a/academy/controllers.py b/academy/controllers.py
---- a/academy/controllers.py
-+++ b/academy/controllers.py
-@@ -9,9 +9,11 @@ class Academy(http.Controller):
- 'teachers': Teachers.search([])
- })
-
-- @http.route('/academy/<int:id>/', auth='public', website=True)
-- def teacher(self, id):
-- return '<h1>{} ({})</h1>'.format(id, type(id).__name__)
-+ @http.route('/academy/<model("academy.teachers"):teacher>/', auth='public', website=True)
-+ def teacher(self, teacher):
-+ return http.request.render('academy.biography', {
-+ 'person': teacher
-+ })
-
-
- # @http.route('/academy/academy/objects/', auth='public')
-diff --git a/academy/templates.xml b/academy/templates.xml
---- a/academy/templates.xml
-+++ b/academy/templates.xml
-@@ -12,6 +12,18 @@
- </div>
- </t>
- </template>
-+ <template id="biography">
-+ <t t-call="website.layout">
-+ <t t-set="title">Academy</t>
-+ <div class="oe_structure"/>
-+ <div class="oe_structure">
-+ <div class="container">
-+ <p><t t-esc="person.id"/> <t t-esc="person.name"/></p>
-+ </div>
-+ </div>
-+ <div class="oe_structure"/>
-+ </t>
-+ </template>
- <!-- <template id="object"> -->
- <!-- <h1><t t-esc="object.display_name"/></h1> -->
- <!-- <dl> -->
diff --git a/doc/howtos/website/course-m2o b/doc/howtos/website/course-m2o
deleted file mode 100644
index d70c0f524da..00000000000
--- a/doc/howtos/website/course-m2o
+++ /dev/null
@@ -1,24 +0,0 @@
-# HG changeset patch
-# Parent c3705f93fcea86a279f2c31204cc0c2914e784d8
-# Parent 8f2d190d879cdf6464bd61f7994b8b582befcafd
-
-diff --git a/academy/models.py b/academy/models.py
---- a/academy/models.py
-+++ b/academy/models.py
-@@ -7,3 +7,9 @@ class Teachers(models.Model):
-
- name = fields.Char()
- biography = fields.Html()
-+
-+class Courses(models.Model):
-+ _name = 'academy.courses'
-+
-+ name = fields.Char()
-+ teacher_id = fields.Many2one('academy.teachers', string="Teacher")
-diff --git a/academy/security/ir.model.access.csv b/academy/security/ir.model.access.csv
---- a/academy/security/ir.model.access.csv
-+++ b/academy/security/ir.model.access.csv
-@@ -1,2 +1,3 @@
- id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
- access_academy_teachers,access_academy_teachers,model_academy_teachers,,1,0,0,0
-+access_academy_courses,access_academy_courses,model_academy_courses,,1,0,0,0
diff --git a/doc/howtos/website/course-no-price b/doc/howtos/website/course-no-price
deleted file mode 100644
index 5a67a9ae892..00000000000
--- a/doc/howtos/website/course-no-price
+++ /dev/null
@@ -1,21 +0,0 @@
-# HG changeset patch
-# Parent 1708c59c9731207e06ca84529c839c571e622481
-# Parent ac472417df8770ce9b6922968aa86779a86be35c
-
-diff --git a/academy/templates.xml b/academy/templates.xml
---- a/academy/templates.xml
-+++ b/academy/templates.xml
-@@ -28,6 +28,13 @@
- <div class="oe_structure"/>
- </t>
- </template>
-+
-+ <template id="product_item_hide_no_price" inherit_id="website_sale.products_item">
-+ <xpath expr="//div[hasclass('product_price')]/b" position="attributes">
-+ <attribute name="t-if">product.price &gt; 0</attribute>
-+ </xpath>
-+ </template>
-+
- <!-- <template id="object"> -->
- <!-- <h1><t t-esc="object.display_name"/></h1> -->
- <!-- <dl> -->
diff --git a/doc/howtos/website/course-o2m b/doc/howtos/website/course-o2m
deleted file mode 100644
index f68c0f90b90..00000000000
--- a/doc/howtos/website/course-o2m
+++ /dev/null
@@ -1,33 +0,0 @@
-# HG changeset patch
-# Parent c3619e60d819e746dcaae49a99d7ca1f4c58593c
-diff -r c3619e60d819 -r 957395d27f63 academy/models.py
---- a/academy/models.py Wed Aug 13 14:29:45 2014 +0200
-+++ b/academy/models.py Wed Aug 13 15:06:30 2014 +0200
-@@ -8,6 +8,8 @@ class Teachers(models.Model):
- name = fields.Char()
- biography = fields.Html()
-
-+ course_ids = fields.One2many('academy.courses', 'teacher_id', string="Courses")
-+
- class Courses(models.Model):
- _name = 'academy.courses'
-
-diff -r c3619e60d819 -r 957395d27f63 academy/views.xml
---- a/academy/views.xml Wed Aug 13 14:29:45 2014 +0200
-+++ b/academy/views.xml Wed Aug 13 15:06:30 2014 +0200
-@@ -12,8 +12,15 @@
- <form>
- <sheet>
- <label for="name"/> <field name="name"/>
-+
- <label for="biography"/>
- <field name="biography"/>
-+
-+ <field name="course_ids">
-+ <tree string="Courses" editable="bottom">
-+ <field name="name"/>
-+ </tree>
-+ </field>
- </sheet>
- </form>
- </field>
diff --git a/doc/howtos/website/course-product b/doc/howtos/website/course-product
deleted file mode 100644
index aa9dc716b49..00000000000
--- a/doc/howtos/website/course-product
+++ /dev/null
@@ -1,142 +0,0 @@
-# HG changeset patch
-# Parent 2ee7212e5de4702dff08d9b5e4268e7dc261d038
-# Parent 4ca7b848bb60c3573de7ed41a28b4b65186a5725
-
-diff --git a/academy/__manifest__.py b/academy/__manifest__.py
---- a/academy/__manifest__.py
-+++ b/academy/__manifest__.py
-@@ -27,6 +27,7 @@
- 'security/ir.model.access.csv',
- 'templates.xml',
- 'views.xml',
-+ 'data.xml',
- ],
- # only loaded in demonstration mode
- 'demo': [
-diff --git a/academy/data.xml b/academy/data.xml
-new file mode 100644
---- /dev/null
-+++ b/academy/data.xml
-@@ -0,0 +1,6 @@
-+<odoo>
-+ <record model="product.public.category" id="category_courses">
-+ <field name="name">Courses</field>
-+ <field name="parent_id" ref="website_sale.categ_others"/>
-+ </record>
-+</odoo>
-diff --git a/academy/demo.xml b/academy/demo.xml
---- a/academy/demo.xml
-+++ b/academy/demo.xml
-@@ -10,4 +10,29 @@
- <field name="name">Lester Vaughn</field>
- </record>
-
-+ <record id="course0" model="product.template">
-+ <field name="name">Course 0</field>
-+ <field name="teacher_id" ref="padilla"/>
-+ <field name="public_categ_ids" eval="[(4, ref('academy.category_courses'), False)]"/>
-+ <field name="is_published">True</field>
-+ <field name="list_price" type="float">0</field>
-+ <field name="type">service</field>
-+ </record>
-+ <record id="course1" model="product.template">
-+ <field name="name">Course 1</field>
-+ <field name="teacher_id" ref="padilla"/>
-+ <field name="public_categ_ids" eval="[(4, ref('academy.category_courses'), False)]"/>
-+ <field name="is_published">True</field>
-+ <field name="list_price" type="float">0</field>
-+ <field name="type">service</field>
-+ </record>
-+ <record id="course2" model="product.template">
-+ <field name="name">Course 2</field>
-+ <field name="teacher_id" ref="vaughn"/>
-+ <field name="public_categ_ids" eval="[(4, ref('academy.category_courses'), False)]"/>
-+ <field name="is_published">True</field>
-+ <field name="list_price" type="float">0</field>
-+ <field name="type">service</field>
-+ </record>
-+
- </odoo>
-diff --git a/academy/models.py b/academy/models.py
---- a/academy/models.py
-+++ b/academy/models.py
-@@ -8,11 +8,9 @@ class Teachers(models.Model):
- name = fields.Char()
- biography = fields.Html()
-
-- course_ids = fields.One2many('academy.courses', 'teacher_id', string="Courses")
-+ course_ids = fields.One2many('product.template', 'teacher_id', string="Courses")
-
- class Courses(models.Model):
-- _name = 'academy.courses'
-- _inherit = 'mail.thread'
-+ _inherit = 'product.template'
-
-- name = fields.Char()
- teacher_id = fields.Many2one('academy.teachers', string="Teacher")
-diff --git a/academy/security/ir.model.access.csv b/academy/security/ir.model.access.csv
---- a/academy/security/ir.model.access.csv
-+++ b/academy/security/ir.model.access.csv
-@@ -1,3 +1,2 @@
- id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
- access_academy_teachers,access_academy_teachers,model_academy_teachers,,1,0,0,0
--access_academy_courses,access_academy_courses,model_academy_courses,,1,0,0,0
-diff --git a/academy/views.xml b/academy/views.xml
---- a/academy/views.xml
-+++ b/academy/views.xml
-@@ -26,55 +26,9 @@
- </field>
- </record>
-
-- <record id="action_academy_courses" model="ir.actions.act_window">
-- <field name="name">Academy courses</field>
-- <field name="res_model">academy.courses</field>
-- </record>
-- <record id="academy_course_search" model="ir.ui.view">
-- <field name="name">Academy courses: search</field>
-- <field name="model">academy.courses</field>
-- <field name="arch" type="xml">
-- <search>
-- <field name="name"/>
-- <field name="teacher_id"/>
-- </search>
-- </field>
-- </record>
-- <record id="academy_course_list" model="ir.ui.view">
-- <field name="name">Academy courses: list</field>
-- <field name="model">academy.courses</field>
-- <field name="arch" type="xml">
-- <tree string="Courses">
-- <field name="name"/>
-- <field name="teacher_id"/>
-- </tree>
-- </field>
-- </record>
-- <record id="academy_course_form" model="ir.ui.view">
-- <field name="name">Academy courses: form</field>
-- <field name="model">academy.courses</field>
-- <field name="arch" type="xml">
-- <form>
-- <sheet>
-- <label for="name"/>
-- <field name="name"/>
-- <label for="teacher_id"/>
-- <field name="teacher_id"/>
-- </sheet>
-- <div class="oe_chatter">
-- <field name="message_follower_ids" widget="mail_followers"/>
-- <field name="message_ids" widget="mail_thread"/>
-- </div>
-- </form>
-- </field>
-- </record>
--
- <menuitem sequence="0" id="menu_academy" name="Academy"/>
- <menuitem id="menu_academy_content" parent="menu_academy"
- name="Academy Content"/>
-- <menuitem id="menu_academy_content_courses"
-- parent="menu_academy_content"
-- action="action_academy_courses"/>
- <menuitem id="menu_academy_content_teachers"
- parent="menu_academy_content"
- action="action_academy_teachers"/>
diff --git a/doc/howtos/website/course-products-sidebar b/doc/howtos/website/course-products-sidebar
deleted file mode 100644
index 03de4bdb1de..00000000000
--- a/doc/howtos/website/course-products-sidebar
+++ /dev/null
@@ -1,18 +0,0 @@
-# HG changeset patch
-# Parent c706c2ec28328a65a8aee6a7ba7d06896468c1e3
-# Parent 053262442acdbe3c803c29ce35002ec69452c5fd
-
-diff --git a/academy/templates.xml b/academy/templates.xml
---- a/academy/templates.xml
-+++ b/academy/templates.xml
-@@ -35,6 +35,10 @@
- </xpath>
- </template>
-
-+ <record id="website_sale.products_categories" model="ir.ui.view">
-+ <field name="active" eval="True"/>
-+ </record>
-+
- <!-- <template id="object"> -->
- <!-- <h1><t t-esc="object.display_name"/></h1> -->
- <!-- <dl> -->
diff --git a/doc/howtos/website/course-views b/doc/howtos/website/course-views
deleted file mode 100644
index a624ef9dc8b..00000000000
--- a/doc/howtos/website/course-views
+++ /dev/null
@@ -1,57 +0,0 @@
-# HG changeset patch
-# Parent c687289c105fe855f799a1e5b498382edbd80cb3
-diff -r c687289c105f -r 1012f1736bb6 academy/views.xml
---- a/academy/views.xml Thu Aug 14 12:58:50 2014 +0200
-+++ b/academy/views.xml Thu Aug 14 13:00:19 2014 +0200
-@@ -19,9 +19,51 @@
- </field>
- </record>
-
-+ <record id="action_academy_courses" model="ir.actions.act_window">
-+ <field name="name">Academy courses</field>
-+ <field name="res_model">academy.courses</field>
-+ </record>
-+ <record id="academy_course_search" model="ir.ui.view">
-+ <field name="name">Academy courses: search</field>
-+ <field name="model">academy.courses</field>
-+ <field name="arch" type="xml">
-+ <search>
-+ <field name="name"/>
-+ <field name="teacher_id"/>
-+ </search>
-+ </field>
-+ </record>
-+ <record id="academy_course_list" model="ir.ui.view">
-+ <field name="name">Academy courses: list</field>
-+ <field name="model">academy.courses</field>
-+ <field name="arch" type="xml">
-+ <tree string="Courses">
-+ <field name="name"/>
-+ <field name="teacher_id"/>
-+ </tree>
-+ </field>
-+ </record>
-+ <record id="academy_course_form" model="ir.ui.view">
-+ <field name="name">Academy courses: form</field>
-+ <field name="model">academy.courses</field>
-+ <field name="arch" type="xml">
-+ <form>
-+ <sheet>
-+ <label for="name"/>
-+ <field name="name"/>
-+ <label for="teacher_id"/>
-+ <field name="teacher_id"/>
-+ </sheet>
-+ </form>
-+ </field>
-+ </record>
-+
- <menuitem sequence="0" id="menu_academy" name="Academy"/>
- <menuitem id="menu_academy_content" parent="menu_academy"
- name="Academy Content"/>
-+ <menuitem id="menu_academy_content_courses"
-+ parent="menu_academy_content"
-+ action="action_academy_courses"/>
- <menuitem id="menu_academy_content_teachers"
- parent="menu_academy_content"
- action="action_academy_teachers"/>
diff --git a/doc/howtos/website/data-retrieval-orm b/doc/howtos/website/data-retrieval-orm
deleted file mode 100644
index 425ba41b4d0..00000000000
--- a/doc/howtos/website/data-retrieval-orm
+++ /dev/null
@@ -1,30 +0,0 @@
-# HG changeset patch
-# Parent f0a3629abb17ca9f4dddd8885321d9ca5de14b55
-# Parent 4c1c3d77ba8ad35dc759405a0db39a6eae943b0f
-
-diff --git a/academy/controllers.py b/academy/controllers.py
---- a/academy/controllers.py
-+++ b/academy/controllers.py
-@@ -4,8 +4,9 @@ from odoo import http
- class Academy(http.Controller):
- @http.route('/academy/academy/', auth='public')
- def index(self, **kw):
-+ Teachers = http.request.env['academy.teachers']
- return http.request.render('academy.index', {
-- 'teachers': ["Diana Padilla", "Jody Caroll", "Lester Vaughn"],
-+ 'teachers': Teachers.search([])
- })
-
- # @http.route('/academy/academy/objects/', auth='public')
-diff --git a/academy/templates.xml b/academy/templates.xml
---- a/academy/templates.xml
-+++ b/academy/templates.xml
-@@ -3,7 +3,7 @@
- <template id="index">
- <title>Academy</title>
- <t t-foreach="teachers" t-as="teacher">
-- <p><t t-esc="teacher"/></p>
-+ <p><t t-esc="teacher.id"/> <t t-esc="teacher.name"/></p>
- </t>
- </template>
- <!-- <template id="object"> -->
diff --git a/doc/howtos/website/demo-data b/doc/howtos/website/demo-data
deleted file mode 100644
index bf50fd31632..00000000000
--- a/doc/howtos/website/demo-data
+++ /dev/null
@@ -1,42 +0,0 @@
-# HG changeset patch
-# Parent c77aa2c3341b9ab3a4e9ed05874e8a278fe69453
-# Parent f416ab6c60f9cb3a803d30ff4dbff880eaa44a65
-
-diff --git a/academy/demo.xml b/academy/demo.xml
---- a/academy/demo.xml
-+++ b/academy/demo.xml
-@@ -1,25 +1,13 @@
- <odoo>
-
-- <!-- -->
-- <!-- <record id="object0" model="academy.academy"> -->
-- <!-- <field name="name">Object 0</field> -->
-- <!-- </record> -->
-- <!-- -->
-- <!-- <record id="object1" model="academy.academy"> -->
-- <!-- <field name="name">Object 1</field> -->
-- <!-- </record> -->
-- <!-- -->
-- <!-- <record id="object2" model="academy.academy"> -->
-- <!-- <field name="name">Object 2</field> -->
-- <!-- </record> -->
-- <!-- -->
-- <!-- <record id="object3" model="academy.academy"> -->
-- <!-- <field name="name">Object 3</field> -->
-- <!-- </record> -->
-- <!-- -->
-- <!-- <record id="object4" model="academy.academy"> -->
-- <!-- <field name="name">Object 4</field> -->
-- <!-- </record> -->
-- <!-- -->
-+ <record id="padilla" model="academy.teachers">
-+ <field name="name">Diana Padilla</field>
-+ </record>
-+ <record id="carroll" model="academy.teachers">
-+ <field name="name">Jody Carroll</field>
-+ </record>
-+ <record id="vaughn" model="academy.teachers">
-+ <field name="name">Lester Vaughn</field>
-+ </record>
-
- </odoo>
diff --git a/doc/howtos/website/field-format b/doc/howtos/website/field-format
deleted file mode 100644
index 930ccfa0fa6..00000000000
--- a/doc/howtos/website/field-format
+++ /dev/null
@@ -1,16 +0,0 @@
-# HG changeset patch
-# Parent f3ad3f919b49bc70c87e1500ec0d39f741243b3d
-# Parent 07a68419287382d7dd9d600c8b813c3c37a88864
-
-diff --git a/academy/templates.xml b/academy/templates.xml
---- a/academy/templates.xml
-+++ b/academy/templates.xml
-@@ -21,7 +21,7 @@
- <div class="oe_structure">
- <div class="container">
- <h3 t-field="person.name"/>
-- <p>Last modified: <i t-field="person.write_date"/></p>
-+ <p>Last modified: <i t-field="person.write_date" t-options='{"format": "long"}'/></p>
- <div t-field="person.biography"/>
- </div>
- </div>
diff --git a/doc/howtos/website/field-raw b/doc/howtos/website/field-raw
deleted file mode 100644
index e1b4ef76abb..00000000000
--- a/doc/howtos/website/field-raw
+++ /dev/null
@@ -1,15 +0,0 @@
-# HG changeset patch
-# Parent d5b8a2de3e35c26c29f85ce500d41ccd2373c508
-# Parent 65d27383542ef9214ff9e2c308aa54b042cff2d9
-
-diff --git a/academy/templates.xml b/academy/templates.xml
---- a/academy/templates.xml
-+++ b/academy/templates.xml
-@@ -21,6 +21,7 @@
- <div class="oe_structure">
- <div class="container">
- <h3 t-field="person.name"/>
-+ <p>Last modified: <i t-field="person.write_date"/></p>
- <div t-field="person.biography"/>
- </div>
- </div>
diff --git a/doc/howtos/website/field-widget b/doc/howtos/website/field-widget
deleted file mode 100644
index ea3ddce562a..00000000000
--- a/doc/howtos/website/field-widget
+++ /dev/null
@@ -1,16 +0,0 @@
-# HG changeset patch
-# Parent c3d04f578b762612422e09777e0ac5b3863d6ea6
-# Parent 0bc39fe6579c4e48b61e77bc970da2e1784f1a67
-
-diff --git a/academy/templates.xml b/academy/templates.xml
---- a/academy/templates.xml
-+++ b/academy/templates.xml
-@@ -21,7 +21,7 @@
- <div class="oe_structure">
- <div class="container">
- <h3 t-field="person.name"/>
-- <p>Last modified: <i t-field="person.write_date" t-options='{"format": "long"}'/></p>
-+ <p>Last modified: <i t-field="person.write_date" t-options='{"widget": "relative"}'/></p>
- <div t-field="person.biography"/>
- </div>
- </div>
diff --git a/doc/howtos/website/helloworld.png b/doc/howtos/website/helloworld.png
deleted file mode 100644
index fe76ad88bf7..00000000000
--- a/doc/howtos/website/helloworld.png
+++ /dev/null
Binary files differ
diff --git a/doc/howtos/website/layout.png b/doc/howtos/website/layout.png
deleted file mode 100644
index f3fcaf3ac99..00000000000
--- a/doc/howtos/website/layout.png
+++ /dev/null
Binary files differ
diff --git a/doc/howtos/website/module-empty b/doc/howtos/website/module-empty
deleted file mode 100644
index 17529591106..00000000000
--- a/doc/howtos/website/module-empty
+++ /dev/null
@@ -1,153 +0,0 @@
-# HG changeset patch
-# Parent 0000000000000000000000000000000000000000
-# Parent 0000000000000000000000000000000000000000
-
-diff --git a/academy/__init__.py b/academy/__init__.py
-new file mode 100644
---- /dev/null
-+++ b/academy/__init__.py
-@@ -0,0 +1,3 @@
-+# -*- coding: utf-8 -*-
-+import controllers
-+import models
-diff --git a/academy/__manifest__.py b/academy/__manifest__.py
-new file mode 100644
---- /dev/null
-+++ b/academy/__manifest__.py
-@@ -0,0 +1,34 @@
-+# -*- coding: utf-8 -*-
-+{
-+ 'name': "Academy",
-+
-+ 'summary': """
-+ Short (1 phrase/line) summary of the module's purpose, used as
-+ subtitle on modules listing or apps.odoo.com""",
-+
-+ 'description': """
-+ Long description of module's purpose
-+ """,
-+
-+ 'author': "My Company",
-+ 'website': "https://www.yourcompany.com",
-+
-+ # Categories can be used to filter modules in modules listing
-+ # Check https://github.com/odoo/odoo/blob/14.0/odoo/addons/base/data/ir_module_category_data.xml
-+ # for the full list
-+ 'category': 'Uncategorized',
-+ 'version': '0.1',
-+
-+ # any module necessary for this one to work correctly
-+ 'depends': ['base'],
-+
-+ # always loaded
-+ 'data': [
-+ # 'security/ir.model.access.csv',
-+ 'templates.xml',
-+ ],
-+ # only loaded in demonstration mode
-+ 'demo': [
-+ 'demo.xml',
-+ ],
-+}
-diff --git a/academy/controllers.py b/academy/controllers.py
-new file mode 100644
---- /dev/null
-+++ b/academy/controllers.py
-@@ -0,0 +1,20 @@
-+# -*- coding: utf-8 -*-
-+from odoo import http
-+
-+# class Academy(http.Controller):
-+# @http.route('/academy/academy/', auth='public')
-+# def index(self, **kw):
-+# return "Hello, world"
-+
-+# @http.route('/academy/academy/objects/', auth='public')
-+# def list(self, **kw):
-+# return http.request.render('academy.listing', {
-+# 'root': '/academy/academy',
-+# 'objects': http.request.env['academy.academy'].search([]),
-+# })
-+
-+# @http.route('/academy/academy/objects/<model("academy.academy"):obj>/', auth='public')
-+# def object(self, obj, **kw):
-+# return http.request.render('academy.object', {
-+# 'object': obj
-+# })
-diff --git a/academy/demo.xml b/academy/demo.xml
-new file mode 100644
---- /dev/null
-+++ b/academy/demo.xml
-@@ -0,0 +1,25 @@
-+<odoo>
-+
-+ <!-- -->
-+ <!-- <record id="object0" model="academy.academy"> -->
-+ <!-- <field name="name">Object 0</field> -->
-+ <!-- </record> -->
-+ <!-- -->
-+ <!-- <record id="object1" model="academy.academy"> -->
-+ <!-- <field name="name">Object 1</field> -->
-+ <!-- </record> -->
-+ <!-- -->
-+ <!-- <record id="object2" model="academy.academy"> -->
-+ <!-- <field name="name">Object 2</field> -->
-+ <!-- </record> -->
-+ <!-- -->
-+ <!-- <record id="object3" model="academy.academy"> -->
-+ <!-- <field name="name">Object 3</field> -->
-+ <!-- </record> -->
-+ <!-- -->
-+ <!-- <record id="object4" model="academy.academy"> -->
-+ <!-- <field name="name">Object 4</field> -->
-+ <!-- </record> -->
-+ <!-- -->
-+
-+</odoo>
-diff --git a/academy/models.py b/academy/models.py
-new file mode 100644
---- /dev/null
-+++ b/academy/models.py
-@@ -0,0 +1,8 @@
-+# -*- coding: utf-8 -*-
-+
-+from odoo import models, fields, api
-+
-+# class academy(models.Model):
-+# _name = 'academy.academy'
-+
-+# name = fields.Char()
-diff --git a/academy/security/ir.model.access.csv b/academy/security/ir.model.access.csv
-new file mode 100644
---- /dev/null
-+++ b/academy/security/ir.model.access.csv
-@@ -0,0 +1,2 @@
-+id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
-+access_academy_academy,academy.academy,model_academy_academy,,1,0,0,0
-diff --git a/academy/templates.xml b/academy/templates.xml
-new file mode 100644
---- /dev/null
-+++ b/academy/templates.xml
-@@ -0,0 +1,22 @@
-+<odoo>
-+
-+ <!-- <template id="listing"> -->
-+ <!-- <ul> -->
-+ <!-- <li t-foreach="objects" t-as="object"> -->
-+ <!-- <a t-attf-href="#{ root }/objects/#{ object.id }"> -->
-+ <!-- <t t-esc="object.display_name"/> -->
-+ <!-- </a> -->
-+ <!-- </li> -->
-+ <!-- </ul> -->
-+ <!-- </template> -->
-+ <!-- <template id="object"> -->
-+ <!-- <h1><t t-esc="object.display_name"/></h1> -->
-+ <!-- <dl> -->
-+ <!-- <t t-foreach="object._fields" t-as="field"> -->
-+ <!-- <dt><t t-esc="field"/></dt> -->
-+ <!-- <dd><t t-esc="object[field]"/></dd> -->
-+ <!-- </t> -->
-+ <!-- </dl> -->
-+ <!-- </template> -->
-+
-+</odoo>
diff --git a/doc/howtos/website/product-dependency b/doc/howtos/website/product-dependency
deleted file mode 100644
index e835628a16d..00000000000
--- a/doc/howtos/website/product-dependency
+++ /dev/null
@@ -1,16 +0,0 @@
-# HG changeset patch
-# Parent 6106208621f01d5aea67727f09adf5c5b2a38642
-# Parent ae97cfb61fd0e1a47727a9d8ed4a702116254eff
-
-diff --git a/academy/__manifest__.py b/academy/__manifest__.py
---- a/academy/__manifest__.py
-+++ b/academy/__manifest__.py
-@@ -20,7 +20,7 @@
- 'version': '0.1',
-
- # any module necessary for this one to work correctly
-- 'depends': ['website'],
-+ 'depends': ['website_sale'],
-
- # always loaded
- 'data': [
diff --git a/doc/howtos/website/routing-basic b/doc/howtos/website/routing-basic
deleted file mode 100644
index 933b6540b27..00000000000
--- a/doc/howtos/website/routing-basic
+++ /dev/null
@@ -1,19 +0,0 @@
-# HG changeset patch
-# Parent 0795247fa6cbb63238941f3dd26a8b6144fa71ee
-# Parent f66ff336f8ed20e022660bd74a43af1b44a1f275
-
-diff --git a/academy/controllers.py b/academy/controllers.py
---- a/academy/controllers.py
-+++ b/academy/controllers.py
-@@ -9,6 +9,11 @@ class Academy(http.Controller):
- 'teachers': Teachers.search([])
- })
-
-+ @http.route('/academy/<name>/', auth='public', website=True)
-+ def teacher(self, name):
-+ return '<h1>{}</h1>'.format(name)
-+
-+
- # @http.route('/academy/academy/objects/', auth='public')
- # def list(self, **kw):
- # return http.request.render('academy.listing', {
diff --git a/doc/howtos/website/routing-converter b/doc/howtos/website/routing-converter
deleted file mode 100644
index bebdc7d9ff7..00000000000
--- a/doc/howtos/website/routing-converter
+++ /dev/null
@@ -1,20 +0,0 @@
-# HG changeset patch
-# Parent e9d9740fa1852c80541c6b5b94280c8ec74cc4bb
-# Parent cf501446e2f8d7a059ef7bd16866ed03c8f2a04f
-
-diff --git a/academy/controllers.py b/academy/controllers.py
---- a/academy/controllers.py
-+++ b/academy/controllers.py
-@@ -9,9 +9,9 @@ class Academy(http.Controller):
- 'teachers': Teachers.search([])
- })
-
-- @http.route('/academy/<name>/', auth='public', website=True)
-- def teacher(self, name):
-- return '<h1>{}</h1>'.format(name)
-+ @http.route('/academy/<int:id>/', auth='public', website=True)
-+ def teacher(self, id):
-+ return '<h1>{} ({})</h1>'.format(id, type(id).__name__)
-
-
- # @http.route('/academy/academy/objects/', auth='public')
diff --git a/doc/howtos/website/series b/doc/howtos/website/series
deleted file mode 100644
index 5520ad4d5ec..00000000000
--- a/doc/howtos/website/series
+++ /dev/null
@@ -1,27 +0,0 @@
-module-empty
-basic-controller
-template
-basic-model
-basic-acl
-demo-data
-data-retrieval-orm
-website-support
-routing-basic
-routing-converter
-converter-model
-teacher-links
-biography-esc
-biography-field
-field-raw
-field-format
-field-widget
-teachers-menu
-teachers-formview
-course-m2o
-course-views
-course-o2m
-chatter-backend
-product-dependency
-course-product
-course-no-price
-course-products-sidebar
diff --git a/doc/howtos/website/teacher-links b/doc/howtos/website/teacher-links
deleted file mode 100644
index e6c6e8284a0..00000000000
--- a/doc/howtos/website/teacher-links
+++ /dev/null
@@ -1,27 +0,0 @@
-# HG changeset patch
-# Parent 91ffd360f3ffd44acb605c09753498b3d5f3f210
-# Parent 976a92eff9104d355cb86a0b41e883a19e75e923
-
-diff --git a/academy/templates.xml b/academy/templates.xml
---- a/academy/templates.xml
-+++ b/academy/templates.xml
-@@ -6,7 +6,9 @@
- <div class="oe_structure">
- <div class="container">
- <t t-foreach="teachers" t-as="teacher">
-- <p><t t-esc="teacher.id"/> <t t-esc="teacher.name"/></p>
-+ <p><a t-attf-href="/academy/{{ slug(teacher) }}">
-+ <t t-esc="teacher.name"/></a>
-+ </p>
- </t>
- </div>
- </div>
-@@ -18,7 +20,7 @@
- <div class="oe_structure"/>
- <div class="oe_structure">
- <div class="container">
-- <p><t t-esc="person.id"/> <t t-esc="person.name"/></p>
-+ <h3><t t-esc="person.name"/></h3>
- </div>
- </div>
- <div class="oe_structure"/>
diff --git a/doc/howtos/website/teachers-formview b/doc/howtos/website/teachers-formview
deleted file mode 100644
index 407938fde83..00000000000
--- a/doc/howtos/website/teachers-formview
+++ /dev/null
@@ -1,26 +0,0 @@
-# HG changeset patch
-# Parent 0201053e995dff675aac7499eaa88eaf68bd2882
-diff -r 0201053e995d -r c3705f93fcea academy/views.xml
---- a/academy/views.xml Wed Aug 13 11:04:49 2014 +0200
-+++ b/academy/views.xml Wed Aug 13 11:04:55 2014 +0200
-@@ -5,6 +5,20 @@
- <field name="res_model">academy.teachers</field>
- </record>
-
-+ <record id="academy_teacher_form" model="ir.ui.view">
-+ <field name="name">Academy teachers: form</field>
-+ <field name="model">academy.teachers</field>
-+ <field name="arch" type="xml">
-+ <form>
-+ <sheet>
-+ <label for="name"/> <field name="name"/>
-+ <label for="biography"/>
-+ <field name="biography"/>
-+ </sheet>
-+ </form>
-+ </field>
-+ </record>
-+
- <menuitem sequence="0" id="menu_academy" name="Academy"/>
- <menuitem id="menu_academy_content" parent="menu_academy"
- name="Academy Content"/>
diff --git a/doc/howtos/website/teachers-menu b/doc/howtos/website/teachers-menu
deleted file mode 100644
index 6e7bdbc1aaa..00000000000
--- a/doc/howtos/website/teachers-menu
+++ /dev/null
@@ -1,35 +0,0 @@
-# HG changeset patch
-# Parent c8cc9e66a2701dad6589ff1d950e1cb7738d0854
-# Parent 44a09b8865d418cda8b7c46dfb70fadc86e22184
-
-diff --git a/academy/__manifest__.py b/academy/__manifest__.py
---- a/academy/__manifest__.py
-+++ b/academy/__manifest__.py
-@@ -26,6 +26,7 @@
- 'data': [
- 'security/ir.model.access.csv',
- 'templates.xml',
-+ 'views.xml',
- ],
- # only loaded in demonstration mode
- 'demo': [
-diff --git a/academy/views.xml b/academy/views.xml
-new file mode 100644
---- /dev/null
-+++ b/academy/views.xml
-@@ -0,0 +1,13 @@
-+<odoo>
-+
-+ <record id="action_academy_teachers" model="ir.actions.act_window">
-+ <field name="name">Academy teachers</field>
-+ <field name="res_model">academy.teachers</field>
-+ </record>
-+
-+ <menuitem sequence="0" id="menu_academy" name="Academy"/>
-+ <menuitem id="menu_academy_content" parent="menu_academy"
-+ name="Academy Content"/>
-+ <menuitem id="menu_academy_content_teachers"
-+ parent="menu_academy_content"
-+ action="action_academy_teachers"/>
-+
-+</odoo>
diff --git a/doc/howtos/website/template b/doc/howtos/website/template
deleted file mode 100644
index a7e68254c65..00000000000
--- a/doc/howtos/website/template
+++ /dev/null
@@ -1,42 +0,0 @@
-# HG changeset patch
-# Parent d5ad2ad84a5db0668e4e08fefb6e3f628c2e14d1
-# Parent e65c9826721cb2421131399bc9223e03b482d38f
-
-diff --git a/academy/controllers.py b/academy/controllers.py
---- a/academy/controllers.py
-+++ b/academy/controllers.py
-@@ -4,7 +4,9 @@ from odoo import http
- class Academy(http.Controller):
- @http.route('/academy/academy/', auth='public')
- def index(self, **kw):
-- return "Hello, world"
-+ return http.request.render('academy.index', {
-+ 'teachers': ["Diana Padilla", "Jody Caroll", "Lester Vaughn"],
-+ })
-
- # @http.route('/academy/academy/objects/', auth='public')
- # def list(self, **kw):
-diff --git a/academy/templates.xml b/academy/templates.xml
---- a/academy/templates.xml
-+++ b/academy/templates.xml
-@@ -1,14 +1,11 @@
- <odoo>
-
-- <!-- <template id="listing"> -->
-- <!-- <ul> -->
-- <!-- <li t-foreach="objects" t-as="object"> -->
-- <!-- <a t-attf-href="#{ root }/objects/#{ object.id }"> -->
-- <!-- <t t-esc="object.display_name"/> -->
-- <!-- </a> -->
-- <!-- </li> -->
-- <!-- </ul> -->
-- <!-- </template> -->
-+ <template id="index">
-+ <title>Academy</title>
-+ <t t-foreach="teachers" t-as="teacher">
-+ <p><t t-esc="teacher"/></p>
-+ </t>
-+ </template>
- <!-- <template id="object"> -->
- <!-- <h1><t t-esc="object.display_name"/></h1> -->
- <!-- <dl> -->
diff --git a/doc/howtos/website/website-support b/doc/howtos/website/website-support
deleted file mode 100644
index 8df46dc7a5a..00000000000
--- a/doc/howtos/website/website-support
+++ /dev/null
@@ -1,50 +0,0 @@
-# HG changeset patch
-# Parent 7ae0db4c2ddf5d0f7f58db2af8976fcec905cc4e
-# Parent 06f959831b14dd5d2e0a57d3e14bf919e18f8e3a
-
-diff --git a/academy/__manifest__.py b/academy/__manifest__.py
---- a/academy/__manifest__.py
-+++ b/academy/__manifest__.py
-@@ -20,7 +20,7 @@
- 'version': '0.1',
-
- # any module necessary for this one to work correctly
-- 'depends': ['base'],
-+ 'depends': ['website'],
-
- # always loaded
- 'data': [
-diff --git a/academy/controllers.py b/academy/controllers.py
---- a/academy/controllers.py
-+++ b/academy/controllers.py
-@@ -2,7 +2,7 @@
- from odoo import http
-
- class Academy(http.Controller):
-- @http.route('/academy/academy/', auth='public')
-+ @http.route('/academy/academy/', auth='public', website=True)
- def index(self, **kw):
- Teachers = http.request.env['academy.teachers']
- return http.request.render('academy.index', {
-diff --git a/academy/templates.xml b/academy/templates.xml
---- a/academy/templates.xml
-+++ b/academy/templates.xml
-@@ -1,9 +1,15 @@
- <odoo>
-
- <template id="index">
-- <title>Academy</title>
-- <t t-foreach="teachers" t-as="teacher">
-- <p><t t-esc="teacher.id"/> <t t-esc="teacher.name"/></p>
-+ <t t-call="website.layout">
-+ <t t-set="title">Academy</t>
-+ <div class="oe_structure">
-+ <div class="container">
-+ <t t-foreach="teachers" t-as="teacher">
-+ <p><t t-esc="teacher.id"/> <t t-esc="teacher.name"/></p>
-+ </t>
-+ </div>
-+ </div>
- </t>
- </template>
- <!-- <template id="object"> -->
diff --git a/doc/images/inheritance_methods.png b/doc/images/inheritance_methods.png
deleted file mode 100644
index 990e7640ab4..00000000000
--- a/doc/images/inheritance_methods.png
+++ /dev/null
Binary files differ
diff --git a/doc/images/rating_request.png b/doc/images/rating_request.png
deleted file mode 100644
index 761794c1659..00000000000
--- a/doc/images/rating_request.png
+++ /dev/null
Binary files differ
diff --git a/doc/index.rst b/doc/index.rst
deleted file mode 100644
index 8035da789f9..00000000000
--- a/doc/index.rst
+++ /dev/null
@@ -1,25 +0,0 @@
-:main-title: Developer Documentation
-:banner: banners/index.jpg
-
-=====
-Index
-=====
-
-.. todo:: what's the documentation's license?
-
-.. rst-class:: index-tree
-.. titlesonly breaks level 3 (~in-document) toc of left navbar, so use
- maxdepth instead
-.. toctree::
- :maxdepth: 2
-
- tutorials
- webservices
- setup
- reference
-
-.. ifconfig:: todo_include_todos
-
- .. rubric:: Things to add and fix
-
- .. todolist::
diff --git a/doc/python3.rst b/doc/python3.rst
deleted file mode 100644
index cfa3389a650..00000000000
--- a/doc/python3.rst
+++ /dev/null
@@ -1,460 +0,0 @@
-:orphan:
-
-==================================
-Python 3 compatibility/conversions
-==================================
-
-Official compatibility: Odoo 11 will be the first LTS release to introduce
-Python 3 compatibility, starting with Python 3.5. It will also be the first
-LTS release to drop official support for Python 2.
-
-Rationale: Python 3 has been around since 2008, and all Python libraries
-used by the official Odoo distribution have been ported and are considered
-stable. Most supported platforms have a Python 3.5 package, or a similar
-way to deploy it. Preserving dual compatibility is therefore considered
-unnecessary, and would represent a significant overhead in testing for the
-lifetime of Odoo 11.
-
-Python 2 and Python 3 are somewhat different language, but following
-backports, forward ports and cross-compatibility library it is possible to
-use a subset of Python 2 and Python 3 in order to have a system compatible
-with both.
-
-Here are a few useful steps or reminders to make Python 2 code compatible
-with Python 3.
-
-.. important::
-
- This is not a general-purpose guide for porting Python 2 to Python 3, it's
- a guide to write 2/3-compatible Odoo code. It does not go through all the
- changes in Python but rather through issues which have been found in the
- standard Odoo distribution in order to show how to evolve such code such
- that it works on both Python 2 and Python 3.
-
-References/useful documents:
-
-* `What's new in Python 3? <https://docs.python.org/3.0/whatsnew/3.0.html>`_
- covers many of the changes between Python 2 and Python 3, though it is
- missing a number of changes which `were backported to Python 2.7 <https://docs.python.org/2.7/whatsnew/2.7.html#python-3-1-features>`_
- as well as :ref:`some feature reintroductions <p3support>` of later Python 3
- revisions
-* `How do I port to Python 3? <https://eev.ee/blog/2016/07/31/python-faq-how-do-i-port-to-python-3/>`_
-* `Python-Future <http://python-future.org/index.html>`_
-* `Porting Python 2 code to Python 3 <https://docs.python.org/3/howto/pyporting.html>`_
-* `Porting to Python 3: A Guide <http://lucumr.pocoo.org/2010/2/11/porting-to-python-3-a-guide/>`_ (a bit outdated but useful for the extensive comments on strings and IO)
-
-.. _p3support:
-
-Versions Support
-================
-
-A cross compatible Odoo would only support Python 2.7 and Python 3.5 and
-above: Python 2.7 backported some Python 3 features, and Python 2 features
-were reintroduced in various Python 3 in order to make conversion easier.
-Python 3.6 adds great features (f-strings, ...) and performance improvements
-(ordered compact dicts) but does not seem to reintroduce compatibility
-features whereas:
-
-* Python 3.5 reintroduced ``%`` for bytes/bytestrings (:pep:`461`)
-* Python 3.4 has no specific compatibility improvement but is the lowest P3
- version for PyLint
-* Python 3.3 reintroduced the "u" prefix for proper (unicode) strings
-* Python 3.2 made ``range`` views more list-like (backported to 2.7)and
- reintroduced ``callable``
-
-
-Semantics changes
-=================
-
-Dict & set iteration order ("Hash Randomisation")
--------------------------------------------------
-
-In Python 2, the iteration order depends on the value's hash (modulo the
-collection's capacity and conflict resolution), which provides a
-spec-undefined but implementation-defined order. While that's not supposed to
-happen, it turns out code may depend on the specific order of iteration over
-a hash collection (``dict`` or ``set``).
-
-Python 3.3 enables `hash randomisation`_ by default (this can be optionally
-enabled on previous versions including Python 2 by providing the ``-R``
-command-line parameter), which means *the order of iteration changes from one
-run to the next*.
-
-When discovered, this can be fixed by one of:
-
-* making iteration steps properly independent (removing the dependency of
- order of iteration)
-* using different checking method (e.g. when serialising sets or dictionaries
- and checking against the specific serialised value)
-* fixing dependencies
-* using a ``collections.OrderedDict`` or ``odoo.tools.misc.OrderedSet`` instead
- of a regular one, they guarantee order of iteration is order of insertion
-* sorting the collection's items before iterating over them (this may require
- adding some sort of iteration key to the items)
-
-Moved and removed
-=================
-
-Standard Library Modules
-------------------------
-
-Python 3 reorganised, moved or removed a number of modules in the standard
-library:
-
-* ``StringIO`` and ``cStringIO`` were removed, you can use ``io.BytesIO`` and
- ``io.StringIO`` to replace them in a cross-version manner (``io.BytesIO``
- for binary data, ``io.StringIO`` for text/unicode data).
-* ``urllib``, ``urllib2`` and ``urlparse`` were redistributed across
- ``urllib.parse`` and ``urllib.request``.
-
- Since `requests`_ and `werkzeug`_ are already hard dependencies of Odoo,
- replace ``urllib[2].urlopen``/``urllib2.Request`` uses by `requests`_, and
- ``urlparse`` and a few utilty functions (``urllib.quote``,
- ``urllib.urlencode``) are available through ``werkzeug.urls``, a backport
- of Python 3's ``urllib.parse``.
-
- .. warning:: `requests`_ does not raise by default on non-200 responses
-
-* ``cgi.escape`` (HTML escaping) is deprecated in Python 3, prefer Odoo's own
- :func:`odoo.tools.misc.html_encode`.
-* Most of ``types``'s content has been stripped out in Python 3: only
- "internal" interpreter types (e.g. CodeType, FrameType, ...) have been left
- in, other types can be obtained directly from the corresponding builtin or
- by getting the ``type()`` of a literal value.
-
-Absolute Imports (:pep:`328`)
------------------------------
-
-.. important::
-
- In Python 3, ``import foo`` can only import from a "top-level" library
- (absolute path). If trying to import a sibling or sub-module you *must*
- use an explicitly *relative import* e.g. ``from . import foo`` or
- ``from .foo import bar``.
-
-In Python 2 ``import`` statements are ambiguous: if a file ``a.py`` contains
-``import b``, the import system will first check if there's a ``b.py`` file
-next to it before checking if there is a package called that on the
-PYTHONPATH.
-
-Furthermore if a sibling file is named the same as top-level package, the
-library becomes inaccessible to both the file itself ans siblings, this has
-actually happened in Odoo with :mod:`odoo.tools.mimetypes`.
-
-Additionally, relative imports allow navigating "up" the tree by using
-multiple leading ``.``.
-
-.. note::
-
- Explicitly relative imports are always available in Python 2, and should
- be used everywhere.
-
- You can ensure you are not using any implicitly relative import by adding
- ``from __future__ import absolute_import`` at the top of your files, or by
- running the ``relative-import`` PyLint.
-
-Exception Handlers
-------------------
-
-.. important::
-
- All exception handlers must be converted to ``except ... as ..``. Valid
- forms are::
-
- except Exception:
- except (Exception1, ...):
- except Exception as name:
- except (Exception1, ...) as name:
-
-In Python 2, ``except`` statements are of the form::
-
- except Exception[, name]:
-
-or::
-
- except (Exception1, Exception2)[, name]:
-
-But because the name is optional, this gets confusing and people can stumble
-into the first form when trying for the second and write::
-
- except Exception1, Exception:
-
-which will *not* yield the expected result.
-
-Python 3 changes this syntax to::
-
- except Exception[ as name]:
-
-or::
-
- except (Exception1, Exception2)[ as name]:
-
-This form was implemented in Python 2.5 and is thus compatible across the
-board.
-
-Operators & keywords
---------------------
-
-.. important:: The backtick operator ```foo``` must be converted to an
- explicit call to the ``repr()`` builtin
-
-.. important:: The ``<>`` operator must be replaced by ``!=``
-
-These two operators were long recommended against/deprecated in Python 2,
-Python 3 removed them from the language.
-
-.. _changed-exec:
-
-.. important:: ``exec`` is now a builtin
-
-In Python 2, ``exec`` is a statement/keyword. Much like ``print``, it's been
-converted to a builtin function in Python 3. However because the Python 2
-version can take a tuple parameter it is easy to convert the odd ``exec``
-statement to the following cross-language forms::
-
- exec(source)
- exec(source, globals)
- exec(source, globals, locals)
-
-List/iteration builtins and methods
------------------------------------
-
-In Python 3, a number of builtins and methods formerly returning *lists* were
-converted to return *iterators* or *views*, with the corresponding redundant
-methods or functions having been *removed entirely*:
-
-* In Python 3, ``map``, ``filter`` and ``zip`` return iterators,
- ``itertools.imap``, ``itertools.ifilter`` and ``itertools.izip`` have been
- removed.
-
- .. important::
-
- When possible, use comprehensions (list, generator, ...) rather than
- ``map`` or ``filter``.
-
-* In Python 3, ``dict.keys``, ``dict.values`` and ``dict.items`` return
- *views* rather than lists, and the ``iter*`` and ``view*`` methods have
- been removed.
-
- .. important::
-
- When the result of the above methods is used for more than a one-shot
- loop (e.g. to be included in returned value), or when the dict needs
- to be modified during iteration, wrap the calls in a ``list()``.
-
-builtins
---------
-
-``cmp``
-#######
-
-The ``cmp`` builtin function has been removed from Python 3.
-
-* Most of its uses are in ``cmp=`` parameters to sort functions where it can
- usually be replaced by a key function.
-* Other uses found were obtaining the sign of an item (``cmp(item, 0)``), this
- can be replicated using the standard library's ``math.copysign`` e.g.
- ``math.copysign(1, item)`` will return ``1.0`` if ``item`` is positive and
- ``-1.0`` if ``item`` is negative.
-
-``execfile``
-############
-
-``execfile(path)`` has been removed completely from Python 3 but it is
-trivially replaceable in all cases by::
-
- exec(open(path, 'rb').open())
-
-of a variant thereof (see :ref:`exec changes <changed-exec>` for details)
-
-``file``
-########
-
-The ``file`` builtin has been removed in Python 3. Generally, it can just
-be replaced by the ``open`` builtin, although you may want to use ``io.open``
-which is more flexible and better handles the binary/text dichotomy,
-:ref:`a big issue in cross-version Python <changed-strings>`.
-
-.. note::
-
- In Python 3, the ``open`` builtin is actually an alias for ``io.open``.
-
-``long``
-########
-
-In Python 2, integers can be either ``int`` or ``long``. Python 3 unifies this
-under the single ``int`` type.
-
-.. important::
-
- * the ``L`` suffix for integer literals must be removed
- * calls to ``long`` must be replaced by calls to ``int``
-
-
-* the ``L`` suffix on numbers is unsupported in Python 3, and unnecessary in
- Python 2 as "overflowing" integer literals will implicitly instantiate long.
-* in Python 2, a call to ``int()`` will implicitly create a ``long`` object if
- necessary.
-* type-testing is the last and bigger issue as in Python 2 ``long`` is not a
- subtype of ``int`` (nor the reverse), and ``isinstance(value, (int, long))``
- is thus generally necessary to catch all integrals.
-
-``reduce``
-##########
-
-In Python 3, ``reduce`` has been demoted from builtin to ``functools.reduce``.
-However this is because *most uses of ``reduce`` can be replaced by ``sum``,
-``all``, ``any``* or a list comprehension for a more readable and faster
-result.
-
-It is easy enough to just add ``from functools import reduce`` to the file
-and compatible with Python 2.6 and later, but consider whether you get better
-code by replacing it with some other method altogether.
-
-``xrange``
-##########
-
-In Python 3, ``range()`` behaves the same as Python 2's ``xrange``.
-
-For cross-version code, you can just use ``range()`` everywhere: while this
-will incur a slight allocation cost on Python 2, Python 3's ``range`` supports
-the entire Sequence protocol and thus behaves very much like a regular
-list or tuple.
-
-Removed/renamed methods
------------------------
-
-.. important::
-
- * the ``has_key`` method on dicts must be replaced by use of the ``in``
- operator e.g. ``foo.has_key(bar)`` becomes ``bar in foo``.
-
-``in`` for dicts was introduced in Python 2.3, leading to ``has_key`` being
-redundant, and removed in Python 3.
-
-Minor syntax changes
---------------------
-
-* the ability to unpack a parameter (in the parameter declaration list) has
- been removed in Python 3 e.g.::
-
- def foo((bar, baz), qux):
- …
-
- is now invalid
-
-* octal literals must be prefixed by ``0o`` (or ``0O``). Following the C
- family, in Python 2 an octal literal simply has a leading 0, which can be
- confusing and easy to get wrong when e.g. padding for readability (e.g.
- ``0013`` would be the decimal 11 rather than 13).
-
- In Python 3, leading zeroes followed by neither a 0 nor a period is an
- error, octal literals now follow the hexadecimal convention with a ``0o``
- prefix.
-
-.. _changed-strings:
-
-Bytes/String/Text: The Big One
-==============================
-
-The most impactful Python 3 change by far is to the text model: for historical
-reasons the distinction Python 2's bytestrings (``bytes``/``str``) and text
-strings (``unicode``) is fuzzy and it will try to implicitly convert between
-one and the other using the ASCII encoding.
-
-Python 3 changes this, it removes the implicit conversions, removes APIs which
-contribute to the fuzz and tends to strictly segregate other to work on either
-bytes or text.
-
-This is fundamentally good and mostly sensible, but it means lots of breakage:
-
-the builtins
-------------
-
-Python 3 removes both ``unicode`` and ``basestring``, and ``str`` now
-corresponds to *text* strings (the old ``unicode``) with ``bytes`` being
-bytestrings in both languages [#bytes]_.
-
-Both versions have the following prefixes for string literals:
-
-* ``b'foo'`` is a bytestring (``bytes`` object).
-
-* ``'foo'`` is that version's ``str`` type, which may be either a bytestring
- or a text string [#native-string]_.
-
-* ``u'foo'`` is that version's text string.
-
-For best cross-version compatibility you should avoid unprefixed string
-literals unless you *specifically* need a "native string" [#native-string]_.
-
-``open``
---------
-
-.. important::
-
- the ``open`` builtin should always be explicitly used in binary mode
- (``rb``, ``wb``, ...)
-
- To read *text* files, use ``io.open``.
-
-On both P2 and P3, ``open`` defaults to returning *native strings* in default
-("text") mode, however in P3 that means it actually decodes the file's bytes
-using whatever encoding was set up (default: UTF-8) while on Python 2 it has
-no concept of encoding.
-
-Using ``open`` in binary mode provides bytestrings on both versions and works
-fine. To read *text* files, use ``io.open`` and provide an explicit encoding.
-
-base64
-------
-
-base64 is a bytes->bytes conversion. bytes->bytes codecs were removed from the
-"native" encoding/decoding system which is now exclusively for bytes<->text
-conversions: text is *encoded* to bytes and bytes are *decoded* to text.
-
-.. important::
-
- both ``bytes.encode('base64')`` and ``bytes.decode('base64')`` must be
- migrated to using ``base64.b64encode`` and ``base64.b64decode``
- respectively.
-
-csv
----
-
-``csv`` is a fairly vicious one: not only is it not a very good format, the
-Python 2 and Python 3 versions of the library are text-model incompatible in
-significant ways:
-
-* Python 2's CSV only works on *ascii-compatible byte streams* (it has no
- encoding support at all) and extracts bytestring values
-* Python 3's CSV only works on *text streams* and extract text values
-* And ``io`` doesn't provide "native string" streaming facilities.
-
-However with respect to Odoo it turns out most or all uses of ``csv`` fit
-inside a model of *byte stream to and from text values*.
-
-The latter is thus a model implemented by cross-version wrappers
-:func:`odoo.tools.pycompat.csv_reader` and
-:func:`odoo.tools.pycompat.csv_writer`: they take a *UTF-8 byte stream* and
-read or write *text* values.
-
-.. _hash randomisation: http://bugs.python.org/issue13703
-
-.. _requests: http://docs.python-requests.org/
-
-.. _werkzeug: http://werkzeug.pocoo.org/docs/urls/
-
-.. [#bytes]
-
- with the caveat that Python 3 makes them less text-y and more byte-y e.g.
- in Python 2 ``b"foo"[0]`` is ``b"f"``, but in Python 3 it's ``102`` (the
- value of the first byte), you'll want to *slice* bytestrings for
- compatibility.
-
-.. [#native-string]
-
- this is important because some API/contexts take a *native string* rather
- than either bytes or text. The ``csv`` module of the standard library is
- one such problematic API (it is also notoriously problematic for its
- terrible support of non-ascii-compatible encodings in Python 2).
- ``email.message_from_string`` is an other one.
diff --git a/doc/reference.rst b/doc/reference.rst
deleted file mode 100644
index 0ff1f80b184..00000000000
--- a/doc/reference.rst
+++ /dev/null
@@ -1,28 +0,0 @@
-:types: reference
-
-=========
-Reference
-=========
-
-.. toctree::
- :titlesonly:
-
- reference/orm
- reference/data
- reference/actions
- reference/views
- reference/module
- reference/cmdline
- reference/security
- reference/testing
-
- reference/http
- reference/qweb
- reference/javascript_cheatsheet
- reference/javascript_reference
- reference/translations
- reference/reports
- reference/mixins
- reference/guidelines
- reference/mobile
- reference/iot
diff --git a/doc/reference/actions.rst b/doc/reference/actions.rst
deleted file mode 100644
index fef80a12737..00000000000
--- a/doc/reference/actions.rst
+++ /dev/null
@@ -1,445 +0,0 @@
-:banner: banners/actions.jpg
-
-.. _reference/actions:
-
-=======
-Actions
-=======
-
-Actions define the behavior of the system in response to user actions: login,
-action button, selection of an invoice, ...
-
-Actions can be stored in the database or returned directly as dictionaries in
-e.g. button methods. All actions share two mandatory attributes:
-
-``type``
- the category of the current action, determines which fields may be
- used and how the action is interpreted
-``name``
- short user-readable description of the action, may be displayed in the
- client's interface
-
-A client can get actions in 4 forms:
-
-* ``False``
- if any action dialog is currently open, close it
-* A string
- if a :ref:`client action <reference/actions/client>` matches, interpret as
- a client action's tag, otherwise treat as a number
-* A number
- read the corresponding action record from the database, may be a database
- identifier or an :term:`external id`
-* A dictionary
- treat as a client action descriptor and execute
-
-.. _reference/bindings:
-
-Bindings
-========
-
-Aside from their two mandatory attributes, all actions also share *optional*
-attributes used to present an action in an arbitrary model's contextual menu:
-
-``binding_model_id``
- specifies which model the action is bound to
-
- .. note:: For Server Actions, use ``model_id``.
-
-``binding_type``
- specifies the type of binding, which is mostly which contextual menu the
- action will appear under
-
- ``action`` (default)
- Specifies that the action will appear in the :menuselection:`Action`
- contextual menu of the bound model.
- ``report``
- Specifies that the action will appear in the :menuselection:`Print`
- contextual menu of the bound model.
-``binding_view_types``
- a comma-separated list of view types for which the action appears in the
- contextual menu, mostly "list" and / or "form". Defaults to ``list,form``
- (both list and form )
-
-.. _reference/actions/window:
-
-Window Actions (``ir.actions.act_window``)
-==========================================
-
-The most common action type, used to present visualisations of a model through
-:ref:`views <reference/views>`: a window action defines a set of view types
-(and possibly specific views) for a model (and possibly specific record of the
-model).
-
-Its fields are:
-
-``res_model``
- model to present views for
-``views``
- a list of ``(view_id, view_type)`` pairs. The second element of each pair
- is the category of the view (tree, form, graph, ...) and the first is
- an optional database id (or ``False``). If no id is provided, the client
- should fetch the default view of the specified type for the requested
- model (this is automatically done by
- :meth:`~odoo.models.Model.fields_view_get`). The first type of the
- list is the default view type and will be open by default when the action
- is executed. Each view type should be present at most once in the list
-``res_id`` (optional)
- if the default view is ``form``, specifies the record to load (otherwise
- a new record should be created)
-``search_view_id`` (optional)
- ``(id, name)`` pair, ``id`` is the database identifier of a specific
- search view to load for the action. Defaults to fetching the default
- search view for the model
-``target`` (optional)
- whether the views should be open in the main content area (``current``),
- in full screen mode (``fullscreen``) or in a dialog/popup (``new``). Use
- ``main`` instead of ``current`` to clear the breadcrumbs. Defaults to
- ``current``.
-``context`` (optional)
- additional context data to pass to the views
-``domain`` (optional)
- filtering domain to implicitly add to all view search queries
-``limit`` (optional)
- number of records to display in lists by default. Defaults to 80 in the
- web client
-
-For instance, to open customers (partner with the ``customer`` flag set) with
-list and form views::
-
- {
- "type": "ir.actions.act_window",
- "res_model": "res.partner",
- "views": [[False, "tree"], [False, "form"]],
- "domain": [["customer", "=", true]],
- }
-
-Or to open the form view of a specific product (obtained separately) in a new
-dialog::
-
- {
- "type": "ir.actions.act_window",
- "res_model": "product.product",
- "views": [[False, "form"]],
- "res_id": a_product_id,
- "target": "new",
- }
-
-In-database window actions have a few different fields which should be ignored
-by clients, mostly to use in composing the ``views`` list:
-
-``view_mode`` (default= ``tree,form`` )
- comma-separated list of view types as a string (/!\\ No spaces /!\\). All of these types will be
- present in the generated ``views`` list (with at least a ``False`` view_id)
-``view_ids``
- M2M\ [#notquitem2m]_ to view objects, defines the initial content of
- ``views``
-
- .. note:: Act_window views can also be defined cleanly through ``ir.actions.act_window.view``.
-
- If you plan to allow multiple views for your model, prefer using
- ir.actions.act_window.view instead of the action ``view_ids``
-
- .. code-block:: xml
-
- <record model="ir.actions.act_window.view" id="test_action_tree">
- <field name="sequence" eval="1"/>
- <field name="view_mode">tree</field>
- <field name="view_id" ref="view_test_tree"/>
- <field name="act_window_id" ref="test_action"/>
- </record>
-
-``view_id``
- specific view added to the ``views`` list in case its type is part of the
- ``view_mode`` list and not already filled by one of the views in
- ``view_ids``
-
-These are mostly used when defining actions from :ref:`reference/data`:
-
-.. code-block:: xml
-
- <record model="ir.actions.act_window" id="test_action">
- <field name="name">A Test Action</field>
- <field name="res_model">some.model</field>
- <field name="view_mode">graph</field>
- <field name="view_id" ref="my_specific_view"/>
- </record>
-
-will use the "my_specific_view" view even if that's not the default view for
-the model.
-
-The server-side composition of the ``views`` sequence is the following:
-
-* get each ``(id, type)`` from ``view_ids`` (ordered by ``sequence``)
-* if ``view_id`` is defined and its type isn't already filled, append its
- ``(id, type)``
-* for each unfilled type in ``view_mode``, append ``(False, type)``
-
-.. todo::
-
- * ``usage``?
- * ``groups_id``?
- * ``filter``?
-
-.. [#notquitem2m] technically not an M2M: adds a sequence field and may be
- composed of just a view type, without a view id.
-
-.. _reference/actions/url:
-
-URL Actions (``ir.actions.act_url``)
-====================================
-
-Allow opening a URL (website/web page) via an Odoo action. Can be customized
-via two fields:
-
-``url``
- the address to open when activating the action
-``target``
- opens the address in a new window/page if ``new``, replaces
- the current content with the page if ``self``. Defaults to ``new``
-
-::
-
- {
- "type": "ir.actions.act_url",
- "url": "https://odoo.com",
- "target": "self",
- }
-
-will replace the current content section by the Odoo home page.
-
-.. _reference/actions/server:
-
-Server Actions (``ir.actions.server``)
-======================================
-
-.. autoclass:: odoo.addons.base.models.ir_actions.IrActionsServer
-
-Allow triggering complex server code from any valid action location. Only
-two fields are relevant to clients:
-
-``id``
- the in-database identifier of the server action to run
-``context`` (optional)
- context data to use when running the server action
-
-In-database records are significantly richer and can perform a number of
-specific or generic actions based on their ``state``. Some fields (and
-corresponding behaviors) are shared between states:
-
-``model_id``
- Odoo model linked to the action.
-
-``state``
-
-* ``code``: Executes python code given through the ``code`` argument.
-
-* ``object_create``: Creates a new record of model ``crud_model_id`` following ``fields_lines`` specifications.
-
-* ``object_write``: Updates the current record(s) following ``fields_lines`` specifications
-
-* ``multi``: Executes serveral actions given through the ``child_ids`` argument.
-
-State fields
-------------
-
-Depending on its state, the behavior is defined through different fields.
-The concerned state is given after each field.
-
-``code`` (code)
- Specify a piece of Python code to execute when the action is called
-
- .. code-block:: xml
-
- <record model="ir.actions.server" id="print_instance">
- <field name="name">Res Partner Server Action</field>
- <field name="model_id" ref="model_res_partner"/>
- <field name="state">code</field>
- <field name="code">
- raise Warning(record.name)
- </field>
- </record>
-
- .. note::
-
- The code segment can define a variable called ``action``, which will be
- returned to the client as the next action to execute:
-
- .. code-block:: xml
-
- <record model="ir.actions.server" id="print_instance">
- <field name="name">Res Partner Server Action</field>
- <field name="model_id" ref="model_res_partner"/>
- <field name="state">code</field>
- <field name="code">
- if record.some_condition():
- action = {
- "type": "ir.actions.act_window",
- "view_mode": "form",
- "res_model": record._name,
- "res_id": record.id,
- }
- </field>
- </record>
-
- will ask the client to open a form for the record if it fulfills some
- condition
-
- .. This tends to be the only action type created from :ref:`data files
- <reference/data>`, other types aside from
- :ref:`reference/actions/server/multi` are simpler than Python code to define
- from the UI, but not from :ref:`data files <reference/data>`.
-
-``crud_model_id`` (create)(required)
- model in which to create a new record
-``link_field_id`` (create)
- many2one to ``ir.model.fields``, specifies the current record's m2o field
- on which the newly created record should be set (models should match)
-
-``fields_lines`` (create/write)
- fields to override when creating or copying the record.
- :class:`~odoo.fields.One2many` with the fields:
-
- ``col1``
- ``ir.model.fields`` to set in the concerned model
- (``crud_model_id`` for creates, ``model_id`` for updates)
- ``value``
- value for the field, interpreted via ``type``
- ``type`` (value|reference|equation)
- If ``value``, the ``value`` field is interpreted as a literal value
- (possibly converted), if ``equation`` the ``value`` field is
- interpreted as a Python expression and evaluated
-
-``child_ids`` (multi)
- Specify the multiple sub-actions (``ir.actions.server``) to enact in state multi.
- If sub-actions themselves return actions, the last
- one will be returned to the client as the multi's own next action
-
-.. _reference/actions/server/context:
-
-Evaluation context
-------------------
-
-A number of keys are available in the evaluation context of or surrounding
-server actions:
-
-* ``model`` model object linked to the action via ``model_id``
-* ``record``/``records`` record/recorset on which the action is triggered, can be void.
-* ``env`` Odoo Environment
-* ``datetime``, ``dateutil``, ``time``, ``timezone`` corresponding Python modules
-* ``log: log(message, level='info')`` logging function to record debug information in ir.logging table
-* ``Warning`` constructor for the ``Warning`` exception
-
-.. _reference/actions/report:
-
-Report Actions (``ir.actions.report``)
-======================================
-
-Triggers the printing of a report.
-
-If you define your report through a `<record>` instead of a `<report>` tag and
-want the action to show up in the Print menu of the model's views, you will
-also need to specify ``binding_model_id`` from :ref:`reference/bindings`. It's
-not necessary to set ``binding_type`` to ``report``, since
-``ir.actions.report`` will implicitly default to that.
-
-
-``name`` (mandatory)
- used as the file name if ``print_report_name`` is not specified.
- Otherwise, only useful as a mnemonic/description of the report
- when looking for one in a list of some sort
-``model`` (mandatory)
- the model your report will be about
-``report_type`` (default=qweb-pdf)
- either ``qweb-pdf`` for PDF reports or ``qweb-html`` for HTML
-``report_name`` (mandatory)
- the name (:term:`external id`) of the qweb template used to render the report
-``print_report_name``
- python expression defining the name of the report.
-``groups_id``
- :class:`~odoo.fields.Many2many` field to the groups allowed to view/use
- the current report
-``multi``
- if set to ``True``, the action will not be displayed on a form view.
-``paperformat_id``
- :class:`~odoo.fields.Many2one` field to the paper format you wish to
- use for this report (if not specified, the company format will be used)
-``attachment_use``
- if set to ``True``, the report is only generated once the first time it is
- requested, and re-printed from the stored report afterwards instead of
- being re-generated every time.
-
- Can be used for reports which must only be generated once (e.g. for legal
- reasons)
-``attachment``
- python expression that defines the name of the report; the record is
- accessible as the variable ``object``
-
-.. _reference/actions/client:
-
-Client Actions (``ir.actions.client``)
-======================================
-
-Triggers an action implemented entirely in the client.
-
-``tag``
- the client-side identifier of the action, an arbitrary string which
- the client should know how to react to
-``params`` (optional)
- a Python dictionary of additional data to send to the client, alongside
- the client action tag
-``target`` (optional)
- whether the client action should be open in the main content area
- (``current``), in full screen mode (``fullscreen``) or in a dialog/popup
- (``new``). Use ``main`` instead of ``current`` to clear the breadcrumbs.
- Defaults to ``current``.
-
-::
-
- {
- "type": "ir.actions.client",
- "tag": "pos.ui"
- }
-
-tells the client to start the Point of Sale interface, the server has no idea
-how the POS interface works.
-
-.. seealso::
- - :ref:`Tutorial: Client Actions <howtos/web/client_actions>`
-
-.. _reference/actions/cron:
-
-Automated Actions (``ir.cron``)
-======================================
-
-Actions triggered automatically on a predefined frequency.
-
-``name``
- Name of the automated action (Mainly used in log display)
-
-``interval_number``
- Number of *interval_type* uom between two executions of the action
-
-``interval_type``
- Unit of measure of frequency interval (``minutes``, ``hours``, ``days``, ``weeks``, ``months``,
-
-``numbercall``
- Number of times this action has to be run.
- If the action is expected to run indefinitely, set to ``-1``.
-
-``doall``
- Boolean precising whether the missed actions have to be executed in case of
- server restarts.
-
-``model_id``
- Model on which this action will be called
-
-``code``
- Code content of the action.
- Can be a simple call to the model's method :
-
- .. code-block:: python
-
- model.<method_name>()
-
-``nextcall``
- Next planned execution date of this action (date/time format)
diff --git a/doc/reference/cmdline.rst b/doc/reference/cmdline.rst
deleted file mode 100644
index 7936a32b888..00000000000
--- a/doc/reference/cmdline.rst
+++ /dev/null
@@ -1,745 +0,0 @@
-:banner: banners/cmdline.jpg
-
-.. _reference/cmdline:
-
-================================
-Command-line interface: odoo-bin
-================================
-
-.. _reference/cmdline/server:
-
-Running the server
-==================
-
-.. program:: odoo-bin
-
-.. option:: -d <database>, --database <database>
-
- database(s) used when installing or updating modules.
- Providing a comma-separated list restrict access to databases provided in
- list.
-
- For advanced database options, take a look :ref:`below <reference/cmdline/server/database>`.
-
-.. option:: -i <modules>, --init <modules>
-
- comma-separated list of modules to install before running the server
- (requires :option:`-d`).
-
-.. option:: -u <modules>, --update <modules>
-
- comma-separated list of modules to update before running the server
- (requires :option:`-d`).
-
-.. option:: --addons-path <directories>
-
- comma-separated list of directories in which modules are stored. These
- directories are scanned for modules.
-
- .. (nb: when and why?)
-
-.. option:: -c <config>, --config <config>
-
- provide an alternate :ref:`configuration file <reference/cmdline/config>`
-
-.. option:: -s, --save
-
- saves the server configuration to the current configuration file
- (:file:`{$HOME}/.odoorc` by default, and can be overridden using
- :option:`-c`).
-
-.. option:: --without-demo
-
- disables demo data loading for modules installed
- comma-separated, use ``all`` for all modules.
-
-.. option:: --test-enable
-
- runs tests after installing modules
-
-.. option:: --test-tags 'tag_1,tag_2,...,-tag_n'
-
- select the tests to run by using tags.
-
-.. option:: --screenshots
-
- Specify directory where to write screenshots when an HttpCase.browser_js test
- fails. It defaults to :file:`/tmp/odoo_tests/{db_name}/screenshots`
-
-.. option:: --screencasts
-
- Enable screencasts and specify directory where to write screencasts files.
- The ``ffmpeg`` utility needs to be installed to encode frames into a video
- file. Otherwise frames will be kept instead of the video file.
-
-.. _reference/cmdline/server/database:
-
-Database
---------
-
-.. option:: -r <user>, --db_user <user>
-
- database username, used to connect to PostgreSQL.
-
-.. option:: -w <password>, --db_password <password>
-
- database password, if using `password authentication`_.
-
-.. option:: --db_host <hostname>
-
- host for the database server
-
- * ``localhost`` on Windows
- * UNIX socket otherwise
-
-.. option:: --db_port <port>
-
- port the database listens on, defaults to 5432
-
-.. option:: --db-filter <filter>
-
- hides databases that do not match ``<filter>``. The filter is a
- `regular expression`_, with the additions that:
-
- - ``%h`` is replaced by the whole hostname the request is made on.
- - ``%d`` is replaced by the subdomain the request is made on, with the
- exception of ``www`` (so domain ``odoo.com`` and ``www.odoo.com`` both
- match the database ``odoo``).
-
- These operations are case sensitive. Add option ``(?i)`` to match all
- databases (so domain ``odoo.com`` using ``(?i)%d`` matches the database
- ``Odoo``).
-
- Since version 11, it's also possible to restrict access to a given database
- listen by using the --database parameter and specifying a comma-separated
- list of databases
-
- When combining the two parameters, db-filter supersedes the comma-separated
- database list for restricting database list, while the comma-separated list
- is used for performing requested operations like upgrade of modules.
-
- .. code-block:: bash
-
- $ odoo-bin --db-filter ^11.*$
-
- Restrict access to databases whose name starts with 11
-
- .. code-block:: bash
-
- $ odoo-bin --database 11firstdatabase,11seconddatabase
-
- Restrict access to only two databases, 11firstdatabase and 11seconddatabase
-
- .. code-block:: bash
-
- $ odoo-bin --database 11firstdatabase,11seconddatabase -u base
-
- Restrict access to only two databases, 11firstdatabase and 11seconddatabase,
- and update base module on one database: 11firstdatabase.
- If database 11seconddatabase doesn't exist, the database is created and base modules
- is installed
-
- .. code-block:: bash
-
- $ odoo-bin --db-filter ^11.*$ --database 11firstdatabase,11seconddatabase -u base
-
- Restrict access to databases whose name starts with 11,
- and update base module on one database: 11firstdatabase.
- If database 11seconddatabase doesn't exist, the database is created and base modules
- is installed
-
-.. option:: --db-template <template>
-
- when creating new databases from the database-management screens, use the
- specified `template database`_. Defaults to ``template0``.
-
-.. option:: --pg_path </path/to/postgresql/binaries>
-
- Path to the PostgreSQL binaries that are used by the database manager to
- dump and restore databases. You have to specify this option only if these
- binaries are located in a non-standard directory.
-
-.. option:: --no-database-list
-
- Suppresses the ability to list databases available on the system
-
-.. option:: --db_sslmode
-
- Control the SSL security of the connection between Odoo and PostgreSQL.
- Value should bve one of 'disable', 'allow', 'prefer', 'require',
- 'verify-ca' or 'verify-full'
- Default value is 'prefer'
-
-.. _reference/cmdline/server/emails:
-
-Emails
-------
-
-.. option:: --email-from <address>
-
- Email address used as <FROM> when Odoo needs to send mails
-
-.. option:: --smtp <server>
-
- Address of the SMTP server to connect to in order to send mails
-
-.. option:: --smtp-port <port>
-
-.. option:: --smtp-ssl
-
- If set, odoo should use SSL/STARTSSL SMTP connections
-
-.. option:: --smtp-user <name>
-
- Username to connect to the SMTP server
-
-.. option:: --smtp-password <password>
-
- Password to connect to the SMTP server
-
-.. _reference/cmdline/server/internationalisation:
-
-Internationalisation
---------------------
-
-Use these options to translate Odoo to another language. See i18n section of
-the user manual. Option '-d' is mandatory. Option '-l' is mandatory in case
-of importation
-
-.. option:: --load-language <languages>
-
- specifies the languages (separated by commas) for the translations you
- want to be loaded
-
-.. option:: -l, --language <language>
-
- specify the language of the translation file. Use it with --i18n-export
- or --i18n-import
-
-.. option:: --i18n-export <filename>
-
- export all sentences to be translated to a CSV file, a PO file or a TGZ
- archive and exit.
-
-.. option:: --i18n-import <filename>
-
- import a CSV or a PO file with translations and exit. The '-l' option is
- required.
-
-.. option:: --i18n-overwrite
-
- overwrites existing translation terms on updating a module or importing
- a CSV or a PO file.
-
-.. option:: --modules
-
- specify modules to export. Use in combination with --i18n-export
-
-.. _reference/cmdline/advanced:
-
-Advanced Options
-----------------
-
-.. _reference/cmdline/dev:
-
-Developer features
-''''''''''''''''''
-
-.. option:: --dev <feature,feature,...,feature>
-
- * ``all``: all the features below are activated
-
- * ``xml``: read template qweb from xml file directly instead of database.
- Once a template has been modified in database, it will be not be read from
- the xml file until the next update/init.
-
- * ``reload``: restart server when python file are updated (may not be detected
- depending on the text editor used)
-
- * ``qweb``: break in the evaluation of qweb template when a node contains ``t-debug='debugger'``
-
- * ``(i)p(u)db``: start the chosen python debugger in the code when an
- unexpected error is raised before logging and returning the error.
-
-
-.. _reference/cmdline/server/http:
-
-HTTP
-''''
-
-.. option:: --no-http
-
- do not start the HTTP or long-polling workers (may still start :ref:`cron <reference/actions/cron>`
- workers)
-
- .. warning:: has no effect if :option:`--test-enable` is set, as tests
- require an accessible HTTP server
-
-.. option:: --http-interface <interface>
-
- TCP/IP address on which the HTTP server listens, defaults to ``0.0.0.0``
- (all addresses)
-
-.. option:: --http-port <port>
-
- Port on which the HTTP server listens, defaults to 8069.
-
-.. option:: --longpolling-port <port>
-
- TCP port for long-polling connections in multiprocessing or gevent mode,
- defaults to 8072. Not used in default (threaded) mode.
-
-.. option:: --proxy-mode
-
- enables the use of ``X-Forwarded-*`` headers through `Werkzeug's proxy
- support`_.
-
- .. warning:: proxy mode *must not* be enabled outside of a reverse proxy
- scenario
-
-.. _reference/cmdline/server/logging:
-
-Logging
-'''''''
-
-By default, Odoo displays all logging of level_ ``info`` except for workflow
-logging (``warning`` only), and log output is sent to ``stdout``. Various
-options are available to redirect logging to other destinations and to
-customize the amount of logging output.
-
-.. option:: --logfile <file>
-
- sends logging output to the specified file instead of stdout. On Unix, the
- file `can be managed by external log rotation programs
- <https://docs.python.org/3/library/logging.handlers.html#watchedfilehandler>`_
- and will automatically be reopened when replaced
-
-.. option:: --syslog
-
- logs to the system's event logger: `syslog on unices <https://docs.python.org/3/library/logging.handlers.html#sysloghandler>`_
- and `the Event Log on Windows <https://docs.python.org/3/library/logging.handlers.html#nteventloghandler>`_.
-
- Neither is configurable
-
-.. option:: --log-db <dbname>
-
- logs to the ``ir.logging`` model (``ir_logging`` table) of the specified
- database. The database can be the name of a database in the "current"
- PostgreSQL, or `a PostgreSQL URI`_ for e.g. log aggregation.
-
-.. option:: --log-handler <handler-spec>
-
- :samp:`{LOGGER}:{LEVEL}`, enables ``LOGGER`` at the provided ``LEVEL``
- e.g. ``odoo.models:DEBUG`` will enable all logging messages at or above
- ``DEBUG`` level in the models.
-
- * The colon ``:`` is mandatory
- * The logger can be omitted to configure the root (default) handler
- * If the level is omitted, the logger is set to ``INFO``
-
- The option can be repeated to configure multiple loggers e.g.
-
- .. code-block:: console
-
- $ odoo-bin --log-handler :DEBUG --log-handler werkzeug:CRITICAL --log-handler odoo.fields:WARNING
-
-.. option:: --log-request
-
- enable DEBUG logging for RPC requests, equivalent to
- ``--log-handler=odoo.http.rpc.request:DEBUG``
-
-.. option:: --log-response
-
- enable DEBUG logging for RPC responses, equivalent to
- ``--log-handler=odoo.http.rpc.response:DEBUG``
-
-.. option:: --log-web
-
- enables DEBUG logging of HTTP requests and responses, equivalent to
- ``--log-handler=odoo.http:DEBUG``
-
-.. option:: --log-sql
-
- enables DEBUG logging of SQL querying, equivalent to
- ``--log-handler=odoo.sql_db:DEBUG``
-
-.. option:: --log-level <level>
-
- Shortcut to more easily set predefined levels on specific loggers. "real"
- levels (``critical``, ``error``, ``warn``, ``debug``) are set on the
- ``odoo`` and ``werkzeug`` loggers (except for ``debug`` which is only
- set on ``odoo``).
-
- Odoo also provides debugging pseudo-levels which apply to different sets
- of loggers:
-
- ``debug_sql``
- sets the SQL logger to ``debug``
-
- equivalent to ``--log-sql``
- ``debug_rpc``
- sets the ``odoo`` and HTTP request loggers to ``debug``
-
- equivalent to ``--log-level debug --log-request``
- ``debug_rpc_answer``
- sets the ``odoo`` and HTTP request and response loggers to
- ``debug``
-
- equivalent to ``--log-level debug --log-request --log-response``
-
- .. note::
-
- In case of conflict between :option:`--log-level` and
- :option:`--log-handler`, the latter is used
-
-.. _reference/cdmline/workers:
-
-Multiprocessing
-'''''''''''''''
-
-.. option:: --workers <count>
-
- if ``count`` is not 0 (the default), enables multiprocessing and sets up
- the specified number of HTTP workers (sub-processes processing HTTP
- and RPC requests).
-
- .. note:: multiprocessing mode is only available on Unix-based systems
-
- A number of options allow limiting and recycling workers:
-
- .. option:: --limit-request <limit>
-
- Number of requests a worker will process before being recycled and
- restarted.
-
- Defaults to *8196*.
-
- .. option:: --limit-memory-soft <limit>
-
- Maximum allowed virtual memory per worker. If the limit is exceeded,
- the worker is killed and recycled at the end of the current request.
-
- Defaults to *2048MiB*.
-
- .. option:: --limit-memory-hard <limit>
-
- Hard limit on virtual memory, any worker exceeding the limit will be
- immediately killed without waiting for the end of the current request
- processing.
-
- Defaults to *2560MiB*.
-
- .. option:: --limit-time-cpu <limit>
-
- Prevents the worker from using more than <limit> CPU seconds for each
- request. If the limit is exceeded, the worker is killed.
-
- Defaults to *60*.
-
- .. option:: --limit-time-real <limit>
-
- Prevents the worker from taking longer than <limit> seconds to process
- a request. If the limit is exceeded, the worker is killed.
-
- Differs from :option:`--limit-time-cpu` in that this is a "wall time"
- limit including e.g. SQL queries.
-
- Defaults to *120*.
-
-.. option:: --max-cron-threads <count>
-
- number of workers dedicated to :ref:`cron <reference/actions/cron>` jobs. Defaults to *2*.
- The workers are threads in multi-threading mode and processes in multi-processing mode.
-
- For multi-processing mode, this is in addition to the HTTP worker processes.
-
-.. _reference/cmdline/config:
-
-Configuration file
-==================
-
-.. program:: odoo-bin
-
-Most of the command-line options can also be specified via a configuration
-file. Most of the time, they use similar names with the prefix ``-`` removed
-and other ``-`` are replaced by ``_`` e.g. :option:`--db-template` becomes
-``db_template``.
-
-Some conversions don't match the pattern:
-
-* :option:`--db-filter` becomes ``dbfilter``
-* :option:`--no-http` corresponds to the ``http_enable`` boolean
-* logging presets (all options starting with ``--log-`` except for
- :option:`--log-handler` and :option:`--log-db`) just add content to
- ``log_handler``, use that directly in the configuration file
-* :option:`--smtp` is stored as ``smtp_server``
-* :option:`--database` is stored as ``db_name``
-* :option:`--i18n-import` and :option:`--i18n-export` aren't available at all
- from configuration files
-
-The default configuration file is :file:`{$HOME}/.odoorc` which
-can be overridden using :option:`--config <odoo-bin -c>`. Specifying
-:option:`--save <odoo-bin -s>` will save the current configuration state back
-to that file. The configuration items relative to the command-line are to be
-specified in the section ``[options]``.
-
-Here is a sample file:
-
-.. code-block:: ini
-
- [options]
- db_user=odoo
- dbfilter=odoo
-
-.. _jinja2: http://jinja.pocoo.org
-.. _regular expression: https://docs.python.org/3/library/re.html
-.. _password authentication:
- https://www.postgresql.org/docs/9.3/static/auth-methods.html#AUTH-PASSWORD
-.. _template database:
- https://www.postgresql.org/docs/9.3/static/manage-ag-templatedbs.html
-.. _level:
- https://docs.python.org/3/library/logging.html#logging.Logger.setLevel
-.. _a PostgreSQL URI:
- https://www.postgresql.org/docs/9.2/static/libpq-connect.html#AEN38208
-.. _Werkzeug's proxy support:
- http://werkzeug.pocoo.org/docs/contrib/fixers/#werkzeug.contrib.fixers.ProxyFix
-.. _pyinotify: https://github.com/seb-m/pyinotify/wiki
-
-
-Shell
-=====
-
-Odoo command-line also allows to launch odoo as a python console environment.
-This enables direct interaction with the :ref:`orm <reference/orm>` and its functionalities.
-
-
-.. code-block:: console
-
- $ odoo_bin shell
-
-.. option:: --shell-interface (ipython|ptpython|bpython|python)
-
- Specify a preferred REPL to use in shell mode.
-
-
-.. _reference/cmdline/scaffold:
-
-Scaffolding
-===========
-
-.. program:: odoo-bin scaffold
-
-Scaffolding is the automated creation of a skeleton structure to simplify
-bootstrapping (of new modules, in the case of Odoo). While not necessary it
-avoids the tedium of setting up basic structures and looking up what all
-starting requirements are.
-
-Scaffolding is available via the :command:`odoo-bin scaffold` subcommand.
-
-.. code-block:: console
-
- $ odoo_bin scaffold my_module /addons/
-
-.. option:: name (required)
-
- the name of the module to create, may munged in various manners to
- generate programmatic names (e.g. module directory name, model names, …)
-
-.. option:: destination (default=current directory)
-
- directory in which to create the new module, defaults to the current
- directory
-
-.. option:: -t <template>
-
- a template directory, files are passed through jinja2_ then copied to
- the ``destination`` directory
-
-
-This will create module *my_module* in directory */addons/*.
-
-.. _reference/cmdline/populate:
-
-Database Population
-===================
-
-.. program:: odoo-bin populate
-
-Odoo CLI supports database population features. If the feature is
-:ref:`implemented on a given model <reference/testing/populate/methods>`, it allows automatic data
-generation of the model's records to test your modules in databases containing non-trivial amounts of records.
-
-.. code-block:: console
-
- $ odoo_bin populate
-
-.. option:: --models
-
- list of models for which the database should be filled
-
-.. option:: --size (small|medium|large)
-
- population size, the actual records number depends on the model's `_populate_sizes` attribute.
- The generated records content is specified by the :meth:`~odoo.models._populate_factories` method
- of a given model (cf. the :file:`populate` folder of modules for further details).
-
-.. seealso::
-
- :ref:`reference/testing/populate`
-
-
-Cloc
-====
-
-.. program:: odoo-bin cloc
-
-Odoo Cloc is a tool to count the number of relevant lines written in
-Python, Javascript or XML. This can be used as a rough metric for pricing
-maintenance of extra modules.
-
-Command-line options
---------------------
-.. option:: -d <database>, --database <database>
-
-| Process the code of all extra modules installed on the provided database,
- and of all server actions and computed fields manually created in the provided
- database.
-| The :option:`--addons-path` option is required to specify the path(s) to the
- module folder(s).
-| If combined with :option:`--path`, the count will be that of the sum of both
- options' results (with possible overlaps). At least one of these two options is
- required to specify which code to process.
-
-.. code-block:: console
-
- $ odoo-bin cloc --addons-path=addons -d my_database
-
-.. seealso::
- - :ref:`reference/cmdline/cloc/database-option`
-
-
-.. option:: -p <path>, --path <path>
-
-| Process the files in the provided path.
-| If combined with :option:`--database`, the count will be that of the sum of both
- options' results (with possible overlaps). At least one of these two options is
- required to specify which code to process.
-
-.. code-block:: console
-
- $ odoo-bin cloc -p addons/account
-
-
-Multiple paths can be provided by repeating the option.
-
-.. code-block:: console
-
- $ odoo-bin cloc -p addons/account -p addons/sale
-
-.. seealso::
- - :ref:`reference/cmdline/cloc/path-option`
-
-
-.. option:: --addons-path <directories>
-
-| Comma-separated list of directories in which modules are stored. These directories
- are scanned for modules.
-| Required if the :option:`--database` option is used.
-
-
-.. option:: -c <directories>
-
-Specify a configuration file to use in place of the :option:`--addons-path` option.
-
-.. code-block:: console
-
- $ odoo-bin cloc -c config.conf -d my_database
-
-
-.. option:: -v, --verbose
-
-Show the details of lines counted for each file.
-
-
-Processed files
----------------
-
-.. _reference/cmdline/cloc/database-option:
-
-With the :option:`--database` option
-''''''''''''''''''''''''''''''''''''
-
-Odoo Cloc counts the lines in each file of extra installed modules in a
-given database. In addition, it counts the Python lines of server actions and
-custom computed fields that have been directly created in the database or
-imported.
-
-Some files are excluded from the count by default:
-
-- The manifest (:file:`__manifest__.py` or :file:`__openerp__.py`)
-- The contents of the folder :file:`static/lib`
-- The tests defined in the folder :file:`tests` and :file:`static/tests`
-- The migrations scripts defined in the folder :file:`migrations`
-- The XML files declared in the ``demo`` or ``demo_xml`` sections of the manifest
-
-For special cases, a list of files that should be ignored by Odoo Cloc can be defined
-per module. This is specified by the ``cloc_exclude`` entry of the manifest:
-
-.. code-block:: python
-
- "cloc_exclude": [
- "lib/common.py", # exclude a single file
- "data/*.xml", # exclude all XML files in a specific folder
- "example/**/*", # exclude all files in a folder hierarchy recursively
- ]
-
-| The pattern ``**/*`` can be used to ignore an entire module. This can be useful
- to exclude a module from maintenance service costs.
-| For more information about the pattern syntax, see `glob
- <https://docs.python.org/3/library/pathlib.html#pathlib.Path.glob>`_.
-
-
-
-.. _reference/cmdline/cloc/path-option:
-
-With the :option:`--path` option
-''''''''''''''''''''''''''''''''
-
-This method works the same as with the :ref:`--database option
-<reference/cmdline/cloc/database-option>` if a manifest file is present in the given
-folder. Otherwise, it counts all files.
-
-
-Identifying Extra Modules
--------------------------
-
-To distinguish between standard and extra modules, Odoo Cloc uses the following heuristic:
-modules that are located (real file system path, after following symbolic links)
-in the same parent directory as the ``base``, ``web`` or ``web_enterprise``
-standard modules are considered standard. Other modules are treated as extra modules.
-
-
-Error Handling
---------------
-
-Some file cannot be counted by Odoo Cloc.
-Those file are reported at the end of the output.
-
-Max file size exceeded
-''''''''''''''''''''''
-
-Odoo Cloc rejects any file larger than 25MB. Usually, source files are smaller
-than 1 MB. If a file is rejected, it may be:
-
-- A generated XML file that contains lots of data. It should be excluded in the manifest.
-- A JavaScript library that should be placed in the :file:`static/lib` folder.
-
-Syntax Error
-''''''''''''
-
-Odoo Cloc cannot count the lines of code of a Python file with a syntax problem.
-If an extra module contains such files, they should be fixed to allow the module to
-load. If the module works despite the presence of those files, they are probably
-not loaded and should therefore be removed from the module, or at least excluded
-in the manifest via ``cloc_exclude``.
-
diff --git a/doc/reference/data.rst b/doc/reference/data.rst
deleted file mode 100644
index 6dd0d7ccd9b..00000000000
--- a/doc/reference/data.rst
+++ /dev/null
@@ -1,301 +0,0 @@
-:banner: banners/data_files.jpg
-
-.. _reference/data:
-
-==========
-Data Files
-==========
-
-Odoo is greatly data-driven, and a big part of modules definition is thus
-the definition of the various records it manages: UI (menus and views),
-security (access rights and access rules), reports and plain data are all
-defined via records.
-
-Structure
-=========
-
-The main way to define data in Odoo is via XML data files: The broad structure
-of an XML data file is the following:
-
-* Any number of operation elements within the root element ``odoo``
-
-.. code-block:: xml
-
- <!-- the root elements of the data file -->
- <?xml version="1.0" encoding="UTF-8"?>
- <odoo>
- <operation/>
- ...
- </odoo>
-
-Data files are executed sequentially, operations can only refer to the result
-of operations defined previously
-
-.. note::
-
- If the content of the data file is expected to be applied only once, you
- can specify the odoo flag ``noupdate`` set to 1. If part of
- the data in the file is expected to be applied once, you can place this part
- of the file in a <data noupdate="1"> domain.
-
- .. code-block:: xml
-
- <odoo>
- <data noupdate="1">
- <!-- Only loaded when installing the module (odoo-bin -i module) -->
- <operation/>
- </data>
-
- <!-- (Re)Loaded at install and update (odoo-bin -i/-u) -->
- <operation/>
- </odoo>
-
-Core operations
-===============
-
-.. _reference/data/record:
-
-``record``
-----------
-
-``record`` appropriately defines or updates a database record, it has the
-following attributes:
-
-``model`` (required)
- name of the model to create (or update)
-``id``
- the :term:`external identifier` for this record. It is strongly
- recommended to provide one
-
- * for record creation, allows subsequent definitions to either modify or
- refer to this record
- * for record modification, the record to modify
-``context``
- context to use when creating the record
-``forcecreate``
- in update mode whether the record should be created if it doesn't exist
-
- Requires an :term:`external id`, defaults to ``True``.
-
-``field``
-----------
-
-Each record can be composed of ``field`` tags, defining values to set when
-creating the record. A ``record`` with no ``field`` will use all default
-values (creation) or do nothing (update).
-
-A ``field`` has a mandatory ``name`` attribute, the name of the field to set,
-and various methods to define the value itself:
-
-Nothing
- if no value is provided for the field, an implicit ``False`` will be set
- on the field. Can be used to clear a field, or avoid using a default value
- for the field.
-``search``
- for :ref:`relational fields <reference/fields/relational>`, should be
- a :ref:`domain <reference/orm/domains>` on the field's model.
-
- Will evaluate the domain, search the field's model using it and set the
- search's result as the field's value. Will only use the first result if
- the field is a :class:`~odoo.fields.Many2one`
-``ref``
- if a ``ref`` attribute is provided, its value must be a valid
- :term:`external id`, which will be looked up and set as the field's value.
-
- Mostly for :class:`~odoo.fields.Many2one` and
- :class:`~odoo.fields.Reference` fields
-``type``
- if a ``type`` attribute is provided, it is used to interpret and convert
- the field's content. The field's content can be provided through an
- external file using the ``file`` attribute, or through the node's body.
-
- Available types are:
-
- ``xml``, ``html``
- extracts the ``field``'s children as a single document, evaluates
- any :term:`external id` specified with the form ``%(external_id)s``.
- ``%%`` can be used to output actual *%* signs.
- ``file``
- ensures that the field content is a valid file path in the current
- model, saves the pair :samp:`{module},{path}` as the field value
- ``char``
- sets the field content directly as the field's value without
- alterations
- ``base64``
- base64_-encodes the field's content, useful combined with the ``file``
- *attribute* to load e.g. image data into attachments
- ``int``
- converts the field's content to an integer and sets it as the field's
- value
- ``float``
- converts the field's content to a float and sets it as the field's
- value
- ``list``, ``tuple``
- should contain any number of ``value`` elements with the same
- properties as ``field``, each element resolves to an item of a
- generated tuple or list, and the generated collection is set as the
- field's value
-``eval``
- for cases where the previous methods are unsuitable, the ``eval``
- attributes simply evaluates whatever Python expression it is provided and
- sets the result as the field's value.
-
- The evaluation context contains various modules (``time``, ``datetime``,
- ``timedelta``, ``relativedelta``), a function to resolve :term:`external
- identifiers` (``ref``) and the model object for the current field if
- applicable (``obj``)
-
-``delete``
-----------
-
-The ``delete`` tag can remove any number of records previously defined. It
-has the following attributes:
-
-``model`` (required)
- the model in which a specified record should be deleted
-``id``
- the :term:`external id` of a record to remove
-``search``
- a :ref:`domain <reference/orm/domains>` to find records of the model to
- remove
-
-``id`` and ``search`` are exclusive
-
-``function``
-------------
-
-The ``function`` tag calls a method on a model, with provided parameters.
-It has two mandatory parameters ``model`` and ``name`` specifying respectively
-the model and the name of the method to call.
-
-Parameters can be provided using ``eval`` (should evaluate to a sequence of
-parameters to call the method with) or ``value`` elements (see ``list``
-values).
-
-.. code-block:: xml
-
- <odoo>
- <data noupdate="1">
- <record name="partner_1" model="res.partner">
- <field name="name">Odude</field>
- </record>
-
- <function model="res.partner" name="send_inscription_notice"
- eval="[[ref('partner_1'), ref('partner_2')]]"/>
-
- <function model="res.users" name="send_vip_inscription_notice">
- <function eval="[[('vip','=',True)]]" model="res.partner" name="search"/>
- </function>
- </data>
-
- <record id="model_form_view" model="ir.ui.view">
-
- </record>
- </odoo>
-
-.. ignored assert
-
-.. _reference/data/shortcuts:
-
-Shortcuts
-=========
-
-Because some important structural models of Odoo are complex and involved,
-data files provide shorter alternatives to defining them using
-:ref:`record tags <reference/data/record>`:
-
-``menuitem``
-------------
-
-Defines an ``ir.ui.menu`` record with a number of defaults and fallbacks:
-
-``parent``
- * If a ``parent`` attribute is set, it should be the :term:`external id`
- of an other menu item, used as the new item's parent
- * If no ``parent`` is provided, tries to interpret the ``name`` attribute
- as a ``/``-separated sequence of menu names and find a place in the menu
- hierarchy. In that interpretation, intermediate menus are automatically
- created
- * Otherwise the menu is defined as a "top-level" menu item (*not* a menu
- with no parent)
-``name``
- If no ``name`` attribute is specified, tries to get the menu name from
- a linked action if any. Otherwise uses the record's ``id``
-``groups``
- A ``groups`` attribute is interpreted as a comma-separated sequence of
- :term:`external identifiers` for ``res.groups`` models. If an
- :term:`external identifier` is prefixed with a minus (``-``), the group
- is *removed* from the menu's groups
-``action``
- if specified, the ``action`` attribute should be the :term:`external id`
- of an action to execute when the menu is open
-``id``
- the menu item's :term:`external id`
-
-.. _reference/data/template:
-
-``template``
-------------
-
-Creates a :ref:`QWeb view <reference/views/qweb>` requiring only the ``arch``
-section of the view, and allowing a few *optional* attributes:
-
-``id``
- the view's :term:`external identifier`
-``name``, ``inherit_id``, ``priority``
- same as the corresponding field on ``ir.ui.view`` (nb: ``inherit_id``
- should be an :term:`external identifier`)
-``primary``
- if set to ``True`` and combined with a ``inherit_id``, defines the view
- as a primary
-``groups``
- comma-separated list of group :term:`external identifiers`
-``page``
- if set to ``"True"``, the template is a website page (linkable to,
- deletable)
-``optional``
- ``enabled`` or ``disabled``, whether the view can be disabled (in the
- website interface) and its default status. If unset, the view is always
- enabled.
-
-.. deprecated act_window & report
-.. ignored url, act_window and ir_set
-
-CSV data files
-==============
-
-XML data files are flexible and self-descriptive, but very verbose when
-creating a number of simple records of the same model in bulk.
-
-For this case, data files can also use csv_, this is often the case for
-:ref:`access rights <reference/security/acl>`:
-
-* the file name is :file:`{model_name}.csv`
-* the first row lists the fields to write, with the special field ``id``
- for :term:`external identifiers` (used for creation or update)
-* each row thereafter creates a new record
-
-Here's the first lines of the data file defining US states
-``res.country.state.csv``
-
-.. literalinclude:: static/res.country.state.csv
- :language: text
-
-rendered in a more readable format:
-
-.. csv-table::
- :file: static/res.country.state.csv
- :header-rows: 1
- :class: table-striped table-hover table-condensed
-
-For each row (record):
-
-* the first column is the :term:`external id` of the record to create or
- update
-* the second column is the :term:`external id` of the country object to link
- to (country objects must have been defined beforehand)
-* the third column is the ``name`` field for ``res.country.state``
-* the fourth column is the ``code`` field for ``res.country.state``
-
-.. _base64: https://tools.ietf.org/html/rfc3548.html#section-3
-.. _csv: https://en.wikipedia.org/wiki/Comma-separated_values
diff --git a/doc/reference/guidelines.rst b/doc/reference/guidelines.rst
deleted file mode 100644
index 09d8fbe1fd8..00000000000
--- a/doc/reference/guidelines.rst
+++ /dev/null
@@ -1,1158 +0,0 @@
-:banner: banners/odoo_guideline.jpg
-
-.. highlight:: python
-
-.. _reference/guidelines:
-
-===============
-Odoo Guidelines
-===============
-
-This page introduces the Odoo Coding Guidelines. Those aim to improve the
-quality of Odoo Apps code. Indeed proper code improves readability, eases
-maintenance, helps debugging, lowers complexity and promotes reliability.
-These guidelines should be applied to every new module and to all new development.
-
-.. warning::
-
- When modifying existing files in **stable version** the original file style
- strictly supersedes any other style guidelines. In other words please never
- modify existing files in order to apply these guidelines. It avoids disrupting
- the revision history of code lines. Diff should be kept minimal. For more
- details, see our `pull request guide <https://odoo.com/submit-pr>`_.
-
-.. warning::
-
- When modifying existing files in **master (development) version** apply those
- guidelines to existing code only for modified code or if most of the file is
- under revision. In other words modify existing files structure only if it is
- going under major changes. In that case first do a **move** commit then apply
- the changes related to the feature.
-
-Module structure
-================
-
-Directories
------------
-A module is organized in important directories. Those contain the business logic;
-having a look at them should make you understand the purpose of the module.
-
-- *data/* : demo and data xml
-- *models/* : models definition
-- *controllers/* : contains controllers (HTTP routes)
-- *views/* : contains the views and templates
-- *static/* : contains the web assets, separated into *css/, js/, img/, lib/, ...*
-
-Other optional directories compose the module.
-
-- *wizard/* : regroups the transient models (``models.TransientModel``) and their views
-- *report/* : contains the printable reports and models based on SQL views. Python objects and XML views are included in this directory
-- *tests/* : contains the Python tests
-
-
-File naming
------------
-
-File naming is important to quickly find information through all odoo addons.
-This section explains how to name files in a standard odoo module. As an
-example we use a `plant nursery <https://github.com/tivisse/odoodays-2018/tree/master/plant_nursery>`_ application.
-It holds two main models *plant.nursery* and *plant.order*.
-
-Concerning *models*, split the business logic by sets of models belonging to
-a same main model. Each set lies in a given file named based on its main model.
-If there is only one model, its name is the same as the module name. Each
-inherited model should be in its own file to help understanding of impacted
-models.
-
-.. code-block:: text
-
- addons/plant_nursery/
- |-- models/
- | |-- plant_nursery.py (first main model)
- | |-- plant_order.py (another main model)
- | |-- res_partner.py (inherited Odoo model)
-
-Concerning *security* and access rights and rules two main files should be used.
-First one is the definition of access rights done in a ``ir.model.access.csv``
-file. User groups are defined in ``<module>_groups.xml``. Access rules are
-defined in ``<model>_security.xml``.
-
-.. code-block:: text
-
- addons/plant_nursery/
- |-- security/
- | |-- ir.model.access.csv
- | |-- plant_nursery_groups.xml
- | |-- plant_nursery_security.xml
- | |-- plant_order_security.xml
-
-Concerning *views*, backend views should be split like models and suffixed
-by ``_views.xml``. Backend views are list, form, kanban, activity, graph, pivot, ..
-views. To ease split by model in views main menus not linked to specific actions
-may be extracted into an optional ``<module>_menus.xml`` file. Templates (QWeb
-pages used notably for portal / website display) and bundles (import of JS and
-CSS assets) are put in separate files. Those are respectively
-``<model>_templates.xml`` and ``assets.xml`` files.
-
-.. code-block:: text
-
- addons/plant_nursery/
- |-- views/
- | | -- assets.xml (import of JS / CSS)
- | | -- plant_nursery_menus.xml (optional definition of main menus)
- | | -- plant_nursery_views.xml (backend views)
- | | -- plant_nursery_templates.xml (portal templates)
- | | -- plant_order_views.xml
- | | -- plant_order_templates.xml
- | | -- res_partner_views.xml
-
-Concerning *data*, split them by purpose (demo or data) and main model. Filenames
-will be the main_model name suffixed by ``_demo.xml`` or ``_data.xml``. For instance
-for an application having demo and data for its main model as well as subtypes,
-activities and mail templates all related to mail module:
-
-.. code-block:: text
-
- addons/plant_nursery/
- |-- data/
- | |-- plant_nursery_data.xml
- | |-- plant_nursery_demo.xml
- | |-- mail_data.xml
-
-Concerning *controllers*, generally all controllers belong to a single controller
-contained in a file named ``<module_name>.py``. An old convention in Odoo is to
-name this file ``main.py`` but it is considered as outdated. If you need to inherit
-an existing controller from another module do it in ``<inherited_module_name>.py``.
-For example adding portal controller in an application is done in ``portal.py``.
-
-.. code-block:: text
-
- addons/plant_nursery/
- |-- controllers/
- | |-- plant_nursery.py
- | |-- portal.py (inheriting portal/controllers/portal.py)
- | |-- main.py (deprecated, replaced by plant_nursery.py)
-
-Concerning *static files*, Javascript files follow globally the same logic as
-python models. Each component should be in its own file with a meaningful name.
-For instance, the activity widgets are located in ``activity.js`` of mail module.
-Subdirectories can also be created to structure the 'package' (see web module
-for more details). The same logic should be applied for the templates of JS
-widgets (static XML files) and for their styles (scss files). Don't link
-data (image, libraries) outside Odoo: do not use an URL to an image but copy
-it in the codebase instead.
-
-Concerning *wizards*, naming convention is the same of for python models:
-``<transient>.py`` and ``<transient>_views.xml``. Both are put in the wizard
-directory. This naming comes from old odoo applications using the wizard
-keyword for transient models.
-
-.. code-block:: text
-
- addons/plant_nursery/
- |-- wizard/
- | |-- make_plant_order.py
- | |-- make_plant_order_views.xml
-
-Concerning *statistics reports* done with python / SQL views and classic views
-naming is the following :
-
-.. code-block:: text
-
- addons/plant_nursery/
- |-- report/
- | |-- plant_order_report.py
- | |-- plant_order_report_views.xml
-
-Concerning *printable reports* which contain mainly data preparation and Qweb
-templates naming is the following :
-
-.. code-block:: text
-
- addons/plant_nursery/
- |-- report/
- | |-- plant_order_reports.xml (report actions, paperformat, ...)
- | |-- plant_order_templates.xml (xml report templates)
-
-The complete tree of our Odoo module therefore looks like
-
-.. code-block:: text
-
- addons/plant_nursery/
- |-- __init__.py
- |-- __manifest__.py
- |-- controllers/
- | |-- __init__.py
- | |-- plant_nursery.py
- | |-- portal.py
- |-- data/
- | |-- plant_nursery_data.xml
- | |-- plant_nursery_demo.xml
- | |-- mail_data.xml
- |-- models/
- | |-- __init__.py
- | |-- plant_nursery.py
- | |-- plant_order.py
- | |-- res_partner.py
- |-- report/
- | |-- __init__.py
- | |-- plant_order_report.py
- | |-- plant_order_report_views.xml
- | |-- plant_order_reports.xml (report actions, paperformat, ...)
- | |-- plant_order_templates.xml (xml report templates)
- |-- security/
- | |-- ir.model.access.csv
- | |-- plant_nursery_groups.xml
- | |-- plant_nursery_security.xml
- | |-- plant_order_security.xml
- |-- static/
- | |-- img/
- | | |-- my_little_kitten.png
- | | |-- troll.jpg
- | |-- lib/
- | | |-- external_lib/
- | |-- src/
- | | |-- js/
- | | | |-- widget_a.js
- | | | |-- widget_b.js
- | | |-- scss/
- | | | |-- widget_a.scss
- | | | |-- widget_b.scss
- | | |-- xml/
- | | | |-- widget_a.xml
- | | | |-- widget_a.xml
- |-- views/
- | |-- assets.xml
- | |-- plant_nursery_menus.xml
- | |-- plant_nursery_views.xml
- | |-- plant_nursery_templates.xml
- | |-- plant_order_views.xml
- | |-- plant_order_templates.xml
- | |-- res_partner_views.xml
- |-- wizard/
- | |--make_plant_order.py
- | |--make_plant_order_views.xml
-
-.. note:: File names should only contain ``[a-z0-9_]`` (lowercase
- alphanumerics and ``_``)
-
-.. warning:: Use correct file permissions : folder 755 and file 644.
-
-.. _reference/guidelines/xml:
-
-XML files
-=========
-
-Format
-------
-To declare a record in XML, the **record** notation (using *<record>*) is recommended:
-
-- Place ``id`` attribute before ``model``
-- For field declaration, ``name`` attribute is first. Then place the
- *value* either in the ``field`` tag, either in the ``eval``
- attribute, and finally other attributes (widget, options, ...)
- ordered by importance.
-
-- Try to group the record by model. In case of dependencies between
- action/menu/views, this convention may not be applicable.
-- Use naming convention defined at the next point
-- The tag *<data>* is only used to set not-updatable data with ``noupdate=1``.
- If there is only not-updatable data in the file, the ``noupdate=1`` can be
- set on the ``<odoo>`` tag and do not set a ``<data>`` tag.
-
-.. code-block:: xml
-
- <record id="view_id" model="ir.ui.view">
- <field name="name">view.name</field>
- <field name="model">object_name</field>
- <field name="priority" eval="16"/>
- <field name="arch" type="xml">
- <tree>
- <field name="my_field_1"/>
- <field name="my_field_2" string="My Label" widget="statusbar" statusbar_visible="draft,sent,progress,done" />
- </tree>
- </field>
- </record>
-
-Odoo supports custom tags acting as syntactic sugar:
-
-- menuitem: use it as a shortcut to declare a ``ir.ui.menu``
-- template: use it to declare a QWeb View requiring only the ``arch`` section of the view.
-- report: use to declare a :ref:`report action <reference/actions/report>`
-- act_window: use it if the record notation can't do what you want
-
-The 4 first tags are preferred over the *record* notation.
-
-
-XML IDs and naming
-------------------
-
-Security, View and Action
-~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Use the following pattern :
-
-* For a menu: :samp:`{<model_name>}_menu`, or :samp:`{<model_name>}_menu_{do_stuff}` for submenus.
-* For a view: :samp:`{<model_name>}_view_{<view_type>}`, where *view_type* is
- ``kanban``, ``form``, ``tree``, ``search``, ...
-* For an action: the main action respects :samp:`{<model_name>}_action`.
- Others are suffixed with :samp:`_{<detail>}`, where *detail* is a
- lowercase string briefly explaining the action. This is used only if
- multiple actions are declared for the model.
-* For window actions: suffix the action name by the specific view information
- like :samp:`{<model_name>}_action_view_{<view_type>}`.
-* For a group: :samp:`{<module_name>}_group_{<group_name>}` where *group_name*
- is the name of the group, generally 'user', 'manager', ...
-* For a rule: :samp:`{<model_name>}_rule_{<concerned_group>}` where
- *concerned_group* is the short name of the concerned group ('user'
- for the 'model_name_group_user', 'public' for public user, 'company'
- for multi-company rules, ...).
-
-Name should be identical to xml id with dots replacing underscores. Actions
-should have a real naming as it is used as display name.
-
-.. code-block:: xml
-
- <!-- views -->
- <record id="model_name_view_form" model="ir.ui.view">
- <field name="name">model.name.view.form</field>
- ...
- </record>
-
- <record id="model_name_view_kanban" model="ir.ui.view">
- <field name="name">model.name.view.kanban</field>
- ...
- </record>
-
- <!-- actions -->
- <record id="model_name_action" model="ir.act.window">
- <field name="name">Model Main Action</field>
- ...
- </record>
-
- <record id="model_name_action_child_list" model="ir.actions.act_window">
- <field name="name">Model Access Childs</field>
- </record>
-
- <!-- menus and sub-menus -->
- <menuitem
- id="model_name_menu_root"
- name="Main Menu"
- sequence="5"
- />
- <menuitem
- id="model_name_menu_action"
- name="Sub Menu 1"
- parent="module_name.module_name_menu_root"
- action="model_name_action"
- sequence="10"
- />
-
- <!-- security -->
- <record id="module_name_group_user" model="res.groups">
- ...
- </record>
-
- <record id="model_name_rule_public" model="ir.rule">
- ...
- </record>
-
- <record id="model_name_rule_company" model="ir.rule">
- ...
- </record>
-
-Inheriting XML
-~~~~~~~~~~~~~~
-
-Xml Ids of inheriting views should use the same ID as the original record.
-It helps finding all inheritance at a glance. As final Xml Ids are prefixed
-by the module that creates them there is no overlap.
-
-Naming should contain an ``.inherit.{details}`` suffix to ease understanding
-the override purpose when looking at its name.
-
-.. code-block:: xml
-
- <record id="model_view_form" model="ir.ui.view">
- <field name="name">model.view.form.inherit.module2</field>
- <field name="inherit_id" ref="module1.model_view_form"/>
- ...
- </record>
-
-New primary views do not require the inherit suffix as those are new records
-based upon the first one.
-
-.. code-block:: xml
-
- <record id="module2.model_view_form" model="ir.ui.view">
- <field name="name">model.view.form.module2</field>
- <field name="inherit_id" ref="module1.model_view_form"/>
- <field name="mode">primary</field>
- ...
- </record>
-
-.. _reference/guidelines/python:
-
-Python
-======
-
-.. warning::
-
- Do not forget to read the :ref:`Security Pitfalls <reference/security/pitfalls>`
- section as well to write secure code.
-
-PEP8 options
-------------
-
-Using a linter can help show syntax and semantic warnings or errors. Odoo
-source code tries to respect Python standard, but some of them can be ignored.
-
-- E501: line too long
-- E301: expected 1 blank line, found 0
-- E302: expected 2 blank lines, found 1
-
-Imports
--------
-The imports are ordered as
-
-#. External libraries (one per line sorted and split in python stdlib)
-#. Imports of ``odoo``
-#. Imports from Odoo modules (rarely, and only if necessary)
-
-Inside these 3 groups, the imported lines are alphabetically sorted.
-
-.. code-block:: python
-
- # 1 : imports of python lib
- import base64
- import re
- import time
- from datetime import datetime
- # 2 : imports of odoo
- import odoo
- from odoo import api, fields, models, _ # alphabetically ordered
- from odoo.tools.safe_eval import safe_eval as eval
- # 3 : imports from odoo addons
- from odoo.addons.website.models.website import slug
- from odoo.addons.web.controllers.main import login_redirect
-
-Idiomatics of Programming (Python)
-----------------------------------
-
-- Each python file should have ``# -*- coding: utf-8 -*-`` as first line.
-- Always favor *readability* over *conciseness* or using the language features or idioms.
-- Don't use ``.clone()``
-
-.. code-block:: python
-
- # bad
- new_dict = my_dict.clone()
- new_list = old_list.clone()
- # good
- new_dict = dict(my_dict)
- new_list = list(old_list)
-
-- Python dictionary : creation and update
-
-.. code-block:: python
-
- # -- creation empty dict
- my_dict = {}
- my_dict2 = dict()
-
- # -- creation with values
- # bad
- my_dict = {}
- my_dict['foo'] = 3
- my_dict['bar'] = 4
- # good
- my_dict = {'foo': 3, 'bar': 4}
-
- # -- update dict
- # bad
- my_dict['foo'] = 3
- my_dict['bar'] = 4
- my_dict['baz'] = 5
- # good
- my_dict.update(foo=3, bar=4, baz=5)
- my_dict = dict(my_dict, **my_dict2)
-
-- Use meaningful variable/class/method names
-- Useless variable : Temporary variables can make the code clearer by giving
- names to objects, but that doesn't mean you should create temporary variables
- all the time:
-
-.. code-block:: python
-
- # pointless
- schema = kw['schema']
- params = {'schema': schema}
- # simpler
- params = {'schema': kw['schema']}
-
-- Multiple return points are OK, when they're simpler
-
-.. code-block:: python
-
- # a bit complex and with a redundant temp variable
- def axes(self, axis):
- axes = []
- if type(axis) == type([]):
- axes.extend(axis)
- else:
- axes.append(axis)
- return axes
-
- # clearer
- def axes(self, axis):
- if type(axis) == type([]):
- return list(axis) # clone the axis
- else:
- return [axis] # single-element list
-
-- Know your builtins : You should at least have a basic understanding of all
- the Python builtins (http://docs.python.org/library/functions.html)
-
-.. code-block:: python
-
- value = my_dict.get('key', None) # very very redundant
- value = my_dict.get('key') # good
-
-Also, ``if 'key' in my_dict`` and ``if my_dict.get('key')`` have very different
-meaning, be sure that you're using the right one.
-
-- Learn list comprehensions : Use list comprehension, dict comprehension, and
- basic manipulation using ``map``, ``filter``, ``sum``, ... They make the code
- easier to read.
-
-.. code-block:: python
-
- # not very good
- cube = []
- for i in res:
- cube.append((i['id'],i['name']))
- # better
- cube = [(i['id'], i['name']) for i in res]
-
-- Collections are booleans too : In python, many objects have "boolean-ish" value
- when evaluated in a boolean context (such as an if). Among these are collections
- (lists, dicts, sets, ...) which are "falsy" when empty and "truthy" when containing
- items:
-
-.. code-block:: python
-
- bool([]) is False
- bool([1]) is True
- bool([False]) is True
-
-So, you can write ``if some_collection:`` instead of ``if len(some_collection):``.
-
-
-- Iterate on iterables
-
-.. code-block:: python
-
- # creates a temporary list and looks bar
- for key in my_dict.keys():
- "do something..."
- # better
- for key in my_dict:
- "do something..."
- # accessing the key,value pair
- for key, value in my_dict.items():
- "do something..."
-
-- Use dict.setdefault
-
-.. code-block:: python
-
- # longer.. harder to read
- values = {}
- for element in iterable:
- if element not in values:
- values[element] = []
- values[element].append(other_value)
-
- # better.. use dict.setdefault method
- values = {}
- for element in iterable:
- values.setdefault(element, []).append(other_value)
-
-- As a good developer, document your code (docstring on methods, simple
- comments for tricky part of code)
-- In additions to these guidelines, you may also find the following link
- interesting: http://python.net/~goodger/projects/pycon/2007/idiomatic/handout.html
- (a little bit outdated, but quite relevant)
-
-Programming in Odoo
--------------------
-
-- Avoid to create generators and decorators: only use the ones provided by
- the Odoo API.
-- As in python, use ``filtered``, ``mapped``, ``sorted``, ... methods to
- ease code reading and performance.
-
-
-Make your method work in batch
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-When adding a function, make sure it can process multiple records by iterating
-on self to treat each record.
-
-.. code-block:: python
-
- def my_method(self)
- for record in self:
- record.do_cool_stuff()
-
-For performance issue, when developing a 'stat button' (for instance), do not
-perform a ``search`` or a ``search_count`` in a loop. It
-is recommended to use ``read_group`` method, to compute all value in only one request.
-
-.. code-block:: python
-
- def _compute_equipment_count(self):
- """ Count the number of equipment per category """
- equipment_data = self.env['hr.equipment'].read_group([('category_id', 'in', self.ids)], ['category_id'], ['category_id'])
- mapped_data = dict([(m['category_id'][0], m['category_id_count']) for m in equipment_data])
- for category in self:
- category.equipment_count = mapped_data.get(category.id, 0)
-
-
-Propagate the context
-~~~~~~~~~~~~~~~~~~~~~
-The context is a ``frozendict`` that cannot be modified. To call a method with
-a different context, the ``with_context`` method should be used :
-
-.. code-block:: python
-
- records.with_context(new_context).do_stuff() # all the context is replaced
- records.with_context(**additionnal_context).do_other_stuff() # additionnal_context values override native context ones
-
-.. warning::
- Passing parameter in context can have dangerous side-effects.
-
- Since the values are propagated automatically, some unexpected behavior may appear.
- Calling ``create()`` method of a model with *default_my_field* key in context
- will set the default value of *my_field* for the concerned model.
- But if during this creation, other objects (such as sale.order.line, on sale.order creation)
- having a field name *my_field* are created, their default value will be set too.
-
-If you need to create a key context influencing the behavior of some object,
-choice a good name, and eventually prefix it by the name of the module to
-isolate its impact. A good example are the keys of ``mail`` module :
-*mail_create_nosubscribe*, *mail_notrack*, *mail_notify_user_signature*, ...
-
-
-Think extendable
-~~~~~~~~~~~~~~~~
-
-Functions and methods should not contain too much logic: having a lot of small
-and simple methods is more advisable than having few large and complex methods.
-A good rule of thumb is to split a method as soon as it has more than one
-responsibility (see http://en.wikipedia.org/wiki/Single_responsibility_principle).
-
-Hardcoding a business logic in a method should be avoided as it prevents to be
-easily extended by a submodule.
-
-.. code-block:: python
-
- # do not do this
- # modifying the domain or criteria implies overriding whole method
- def action(self):
- ... # long method
- partners = self.env['res.partner'].search(complex_domain)
- emails = partners.filtered(lambda r: arbitrary_criteria).mapped('email')
-
- # better but do not do this either
- # modifying the logic forces to duplicate some parts of the code
- def action(self):
- ...
- partners = self._get_partners()
- emails = partners._get_emails()
-
- # better
- # minimum override
- def action(self):
- ...
- partners = self.env['res.partner'].search(self._get_partner_domain())
- emails = partners.filtered(lambda r: r._filter_partners()).mapped('email')
-
-The above code is over extendable for the sake of example but the readability
-must be taken into account and a tradeoff must be made.
-
-Also, name your functions accordingly: small and properly named functions are
-the starting point of readable/maintainable code and tighter documentation.
-
-This recommendation is also relevant for classes, files, modules and packages.
-(See also http://en.wikipedia.org/wiki/Cyclomatic_complexity)
-
-
-Never commit the transaction
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-The Odoo framework is in charge of providing the transactional context for
-all RPC calls. The principle is that a new database cursor is opened at the
-beginning of each RPC call, and committed when the call has returned, just
-before transmitting the answer to the RPC client, approximately like this:
-
-.. code-block:: python
-
- def execute(self, db_name, uid, obj, method, *args, **kw):
- db, pool = pooler.get_db_and_pool(db_name)
- # create transaction cursor
- cr = db.cursor()
- try:
- res = pool.execute_cr(cr, uid, obj, method, *args, **kw)
- cr.commit() # all good, we commit
- except Exception:
- cr.rollback() # error, rollback everything atomically
- raise
- finally:
- cr.close() # always close cursor opened manually
- return res
-
-If any error occurs during the execution of the RPC call, the transaction is
-rolled back atomically, preserving the state of the system.
-
-Similarly, the system also provides a dedicated transaction during the execution
-of tests suites, so it can be rolled back or not depending on the server
-startup options.
-
-The consequence is that if you manually call ``cr.commit()`` anywhere there is
-a very high chance that you will break the system in various ways, because you
-will cause partial commits, and thus partial and unclean rollbacks, causing
-among others:
-
-#. inconsistent business data, usually data loss
-#. workflow desynchronization, documents stuck permanently
-#. tests that can't be rolled back cleanly, and will start polluting the
- database, and triggering error (this is true even if no error occurs
- during the transaction)
-
-Here is the very simple rule:
- You should **NEVER** call ``cr.commit()`` yourself, **UNLESS** you have
- created your own database cursor explicitly! And the situations where you
- need to do that are exceptional!
-
- And by the way if you did create your own cursor, then you need to handle
- error cases and proper rollback, as well as properly close the cursor when
- you're done with it.
-
-And contrary to popular belief, you do not even need to call ``cr.commit()``
-in the following situations:
-- in the ``_auto_init()`` method of an *models.Model* object: this is taken
-care of by the addons initialization method, or by the ORM transaction when
-creating custom models
-- in reports: the ``commit()`` is handled by the framework too, so you can
-update the database even from within a report
-- within *models.Transient* methods: these methods are called exactly like
-regular *models.Model* ones, within a transaction and with the corresponding
-``cr.commit()/rollback()`` at the end
-- etc. (see general rule above if you have in doubt!)
-
-All ``cr.commit()`` calls outside of the server framework from now on must
-have an **explicit comment** explaining why they are absolutely necessary, why
-they are indeed correct, and why they do not break the transactions. Otherwise
-they can and will be removed !
-
-
-Use translation method correctly
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Odoo uses a GetText-like method named "underscore" ``_( )`` to indicate that
-a static string used in the code needs to be translated at runtime using the
-language of the context. This pseudo-method is accessed within your code by
-importing as follows:
-
-.. code-block:: python
-
- from odoo import _
-
-A few very important rules must be followed when using it, in order for it to
-work and to avoid filling the translations with useless junk.
-
-Basically, this method should only be used for static strings written manually
-in the code, it will not work to translate field values, such as Product names,
-etc. This must be done instead using the translate flag on the corresponding
-field.
-
-The method accepts optional positional or named parameter
-The rule is very simple: calls to the underscore method should always be in
-the form ``_('literal string')`` and nothing else:
-
-.. code-block:: python
-
- # good: plain strings
- error = _('This record is locked!')
-
- # good: strings with formatting patterns included
- error = _('Record %s cannot be modified!', record)
-
- # ok too: multi-line literal strings
- error = _("""This is a bad multiline example
- about record %s!""", record)
- error = _('Record %s cannot be modified' \
- 'after being validated!', record)
-
- # bad: tries to translate after string formatting
- # (pay attention to brackets!)
- # This does NOT work and messes up the translations!
- error = _('Record %s cannot be modified!' % record)
-
- # bad: formatting outside of translation
- # This won't benefit from fallback mechanism in case of bad translation
- error = _('Record %s cannot be modified!') % record
-
- # bad: dynamic string, string concatenation, etc are forbidden!
- # This does NOT work and messes up the translations!
- error = _("'" + que_rec['question'] + "' \n")
-
- # bad: field values are automatically translated by the framework
- # This is useless and will not work the way you think:
- error = _("Product %s is out of stock!") % _(product.name)
- # and the following will of course not work as already explained:
- error = _("Product %s is out of stock!" % product.name)
-
- # Instead you can do the following and everything will be translated,
- # including the product name if its field definition has the
- # translate flag properly set:
- error = _("Product %s is not available!", product.name)
-
-
-Also, keep in mind that translators will have to work with the literal values
-that are passed to the underscore function, so please try to make them easy to
-understand and keep spurious characters and formatting to a minimum. Translators
-must be aware that formatting patterns such as ``%s`` or ``%d``, newlines, etc.
-need to be preserved, but it's important to use these in a sensible and obvious
-manner:
-
-.. code-block:: python
-
- # Bad: makes the translations hard to work with
- error = "'" + question + _("' \nPlease enter an integer value ")
-
- # Ok (pay attention to position of the brackets too!)
- error = _("Answer to question %s is not valid.\n" \
- "Please enter an integer value.", question)
-
- # Better
- error = _("Answer to question %(title)s is not valid.\n" \
- "Please enter an integer value.", title=question)
-
-In general in Odoo, when manipulating strings, prefer ``%`` over ``.format()``
-(when only one variable to replace in a string), and prefer ``%(varname)`` instead
-of position (when multiple variables have to be replaced). This makes the
-translation easier for the community translators.
-
-
-Symbols and Conventions
------------------------
-
-- Model name (using the dot notation, prefix by the module name) :
- - When defining an Odoo Model : use singular form of the name (*res.partner*
- and *sale.order* instead of *res.partnerS* and *saleS.orderS*)
- - When defining an Odoo Transient (wizard) : use ``<related_base_model>.<action>``
- where *related_base_model* is the base model (defined in *models/*) related
- to the transient, and *action* is the short name of what the transient do. Avoid the *wizard* word.
- For instance : ``account.invoice.make``, ``project.task.delegate.batch``, ...
- - When defining *report* model (SQL views e.i.) : use
- ``<related_base_model>.report.<action>``, based on the Transient convention.
-
-- Odoo Python Class : use camelcase (Object-oriented style).
-
-
-.. code-block:: python
-
- class AccountInvoice(models.Model):
- ...
-
-- Variable name :
- - use camelcase for model variable
- - use underscore lowercase notation for common variable.
- - suffix your variable name with *_id* or *_ids* if it contains a record id or list of id. Don't use ``partner_id`` to contain a record of res.partner
-
-.. code-block:: python
-
- Partner = self.env['res.partner']
- partners = Partner.browse(ids)
- partner_id = partners[0].id
-
-- ``One2Many`` and ``Many2Many`` fields should always have *_ids* as suffix (example: sale_order_line_ids)
-- ``Many2One`` fields should have *_id* as suffix (example : partner_id, user_id, ...)
-- Method conventions
- - Compute Field : the compute method pattern is *_compute_<field_name>*
- - Search method : the search method pattern is *_search_<field_name>*
- - Default method : the default method pattern is *_default_<field_name>*
- - Selection method: the selection method pattern is *_selection_<field_name>*
- - Onchange method : the onchange method pattern is *_onchange_<field_name>*
- - Constraint method : the constraint method pattern is *_check_<constraint_name>*
- - Action method : an object action method is prefix with *action_*.
- Since it uses only one record, add ``self.ensure_one()``
- at the beginning of the method.
-
-- In a Model attribute order should be
- #. Private attributes (``_name``, ``_description``, ``_inherit``, ...)
- #. Default method and ``_default_get``
- #. Field declarations
- #. Compute, inverse and search methods in the same order as field declaration
- #. Selection method (methods used to return computed values for selection fields)
- #. Constrains methods (``@api.constrains``) and onchange methods (``@api.onchange``)
- #. CRUD methods (ORM overrides)
- #. Action methods
- #. And finally, other business methods.
-
-.. code-block:: python
-
- class Event(models.Model):
- # Private attributes
- _name = 'event.event'
- _description = 'Event'
-
- # Default methods
- def _default_name(self):
- ...
-
- # Fields declaration
- name = fields.Char(string='Name', default=_default_name)
- seats_reserved = fields.Integer(oldname='register_current', string='Reserved Seats',
- store=True, readonly=True, compute='_compute_seats')
- seats_available = fields.Integer(oldname='register_avail', string='Available Seats',
- store=True, readonly=True, compute='_compute_seats')
- price = fields.Integer(string='Price')
- event_type = fields.Selection(string="Type", selection='_selection_type')
-
- # compute and search fields, in the same order of fields declaration
- @api.depends('seats_max', 'registration_ids.state', 'registration_ids.nb_register')
- def _compute_seats(self):
- ...
-
- @api.model
- def _selection_type(self):
- return []
-
- # Constraints and onchanges
- @api.constrains('seats_max', 'seats_available')
- def _check_seats_limit(self):
- ...
-
- @api.onchange('date_begin')
- def _onchange_date_begin(self):
- ...
-
- # CRUD methods (and name_get, name_search, ...) overrides
- def create(self, values):
- ...
-
- # Action methods
- def action_validate(self):
- self.ensure_one()
- ...
-
- # Business methods
- def mail_user_confirm(self):
- ...
-
-.. _reference/guidelines/js:
-
-Javascript and CSS
-==================
-
-Static files organization
---------------------------
-
-Odoo addons have some conventions on how to structure various files. We explain
-here in more details how web assets are supposed to be organized.
-
-The first thing to know is that the Odoo server will serve (statically) all files
-located in a *static/* folder, but prefixed with the addon name. So, for example,
-if a file is located in *addons/web/static/src/js/some_file.js*, then it will be
-statically available at the url *your-odoo-server.com/web/static/src/js/some_file.js*
-
-The convention is to organize the code according to the following structure:
-
-- *static*: all static files in general
-
- - *static/lib*: this is the place where js libs should be located, in a sub folder.
- So, for example, all files from the *jquery* library are in *addons/web/static/lib/jquery*
- - *static/src*: the generic static source code folder
-
- - *static/src/css*: all css files
- - *static/src/fonts*
- - *static/src/img*
- - *static/src/js*
-
- - *static/src/js/tours*: end user tour files (tutorials, not tests)
-
- - *static/src/scss*: scss files
- - *static/src/xml*: all qweb templates that will be rendered in JS
-
- - *static/tests*: this is where we put all test related files.
-
- - *static/tests/tours*: this is where we put all tour test files (not tutorials).
-
-Javascript coding guidelines
-----------------------------
-
-- ``use strict;`` is recommended for all javascript files
-- Use a linter (jshint, ...)
-- Never add minified Javascript Libraries
-- Use camelcase for class declaration
-
-More precise JS guidelines are detailed in the `github wiki <https://github.com/odoo/odoo/wiki/Javascript-coding-guidelines>`_.
-You may also have a look at existing API in Javascript by looking Javascript
-References.
-
-CSS coding guidelines
----------------------
-
-- Prefix all your classes with *o_<module_name>* where *module_name* is the
- technical name of the module ('sale', 'im_chat', ...) or the main route
- reserved by the module (for website module mainly, i.e. : 'o_forum' for
- *website_forum* module). The only exception for this rule is the
- webclient: it simply uses *o_* prefix.
-- Avoid using *id* tag
-- Use Bootstrap native classes
-- Use underscore lowercase notation to name class
-
-.. _reference/guidelines/git:
-
-Git
-===
-
-Configure your git
-------------------
-
-Based on ancestral experience and oral tradition, the following things go a long
-way towards making your commits more helpful:
-
-- Be sure to define both the user.email and user.name in your local git config
-
- .. code-block:: text
-
- git config --global <var> <value>
-
-- Be sure to add your full name to your Github profile here. Please feel fancy
- and add your team, avatar, your favorite quote, and whatnot ;-)
-
-Commit message structure
-------------------------
-
-Commit message has four parts: tag, module, short description and full
-description. Try to follow the preferred structure for your commit messages
-
-.. code-block:: text
-
- [TAG] module: describe your change in a short sentence (ideally < 50 chars)
-
- Long version of the change description, including the rationale for the change,
- or a summary of the feature being introduced.
-
- Please spend a lot more time describing WHY the change is being done rather
- than WHAT is being changed. This is usually easy to grasp by actually reading
- the diff. WHAT should be explained only if there are technical choices
- or decision involved. In that case explain WHY this decision was taken.
-
- End the message with references, such as task or bug numbers, PR numbers, and
- OPW tickets, following the suggested format:
- task-123 (related to task)
- Fixes #123 (close related issue on Github)
- Closes #123 (close related PR on Github)
- opw-123 (related to ticket)
-
-Tag and module name
--------------------
-
-Tags are used to prefix your commit. They should be one of the following
-
-- **[FIX]** for bug fixes: mostly used in stable version but also valid if you
- are fixing a recent bug in development version;
-- **[REF]** for refactoring: when a feature is heavily rewritten;
-- **[ADD]** for adding new modules;
-- **[REM]** for removing resources: removing dead code, removing views,
- removing modules, ...;
-- **[REV]** for reverting commits: if a commit causes issues or is not wanted
- reverting it is done using this tag;
-- **[MOV]** for moving files: use git move and do not change content of moved file
- otherwise Git may loose track and history of the file; also used when moving
- code from one file to another;
-- **[REL]** for release commits: new major or minor stable versions;
-- **[IMP]** for improvements: most of the changes done in development version
- are incremental improvements not related to another tag;
-- **[MERGE]** for merge commits: used in forward port of bug fixes but also as
- main commit for feature involving several separated commits;
-- **[CLA]** for signing the Odoo Individual Contributor License;
-- **[I18N]** for changes in translation files;
-
-After tag comes the modified module name. Use the technical name as functional
-name may change with time. If several modules are modified, list them or use
-various to tell it is cross-modules. Unless really required or easier avoid
-modifying code across several modules in the same commit. Understanding module
-history may become difficult.
-
-Commit message header
----------------------
-
-After tag and module name comes a meaningful commit message header. It should be
-self explanatory and include the reason behind the change. Do not use single words
-like "bugfix" or "improvements". Try to limit the header length to about 50 characters
-for readability.
-
-Commit message header should make a valid sentence once concatenated with
-``if applied, this commit will <header>``. For example ``[IMP] base: prevent to
-archive users linked to active partners`` is correct as it makes a valid sentence
-``if applied, this commit will prevent users to archive...``.
-
-Commit message full description
--------------------------------
-
-In the message description specify the part of the code impacted by your changes
-(module name, lib, transversal object, ...) and a description of the changes.
-
-First explain WHY you are modifying code. What is important if someone goes back
-to your commit in about 4 decades (or 3 days) is why you did it. It is the
-purpose of the change.
-
-What you did can be found in the commit itself. If there was some technical choices
-involved it is a good idea to explain it also in the commit message after the why.
-For Odoo R&D developers "PO team asked me to do it" is not a valid why, by the way.
-
-Please avoid commits which simultaneously impact multiple modules. Try to split
-into different commits where impacted modules are different. It will be helpful
-if we need to revert changes in a given module separately.
-
-Don't hesitate to be a bit verbose. Most people will only see your commit message
-and judge everything you did in your life just based on those few sentences.
-No pressure at all.
-
-**You spend several hours, days or weeks working on meaningful features. Take
-some time to calm down and write clear and understandable commit messages.**
-
-If you are an Odoo R&D developer the WHY should be the purpose of the task you
-are working on. Full specifications make the core of the commit message.
-**If you are working on a task that lacks purpose and specifications please
-consider making them clear before continuing.**
-
-Finally here are some examples of correct commit messages :
-
-.. code-block:: text
-
- [REF] models: use `parent_path` to implement parent_store
-
- This replaces the former modified preorder tree traversal (MPTT) with the
- fields `parent_left`/`parent_right`[...]
-
- [FIX] account: remove frenglish
-
- [...]
-
- Closes #22793
- Fixes #22769
-
- [FIX] website: remove unused alert div, fixes look of input-group-btn
-
- Bootstrap's CSS depends on the input-group-btn
- element being the first/last child of its parent.
- This was not the case because of the invisible
- and useless alert.
-
-.. note:: Use the long description to explain the *why* not the
- *what*, the *what* can be seen in the diff
diff --git a/doc/reference/http.rst b/doc/reference/http.rst
deleted file mode 100644
index 0675847aaa0..00000000000
--- a/doc/reference/http.rst
+++ /dev/null
@@ -1,87 +0,0 @@
-:banner: banners/web_controllers.jpg
-
-.. _reference/controllers:
-
-===============
-Web Controllers
-===============
-
-Controllers
-===========
-
-Controllers need to provide extensibility, much like
-:class:`~odoo.models.Model`, but can't use the same mechanism as the
-pre-requisites (a database with loaded modules) may not be available yet (e.g.
-no database created, or no database selected).
-
-Controllers thus provide their own extension mechanism, separate from that of
-models:
-
-Controllers are created by :ref:`inheriting <python:tut-inheritance>` from :class:`~odoo.http.Controller`.
-Routes are defined through methods decorated with :func:`~odoo.http.route`::
-
- class MyController(odoo.http.Controller):
- @route('/some_url', auth='public')
- def handler(self):
- return stuff()
-
-To *override* a controller, :ref:`inherit <python:tut-inheritance>` from its
-class and override relevant methods, re-exposing them if necessary::
-
- class Extension(MyController):
- @route()
- def handler(self):
- do_before()
- return super(Extension, self).handler()
-
-* decorating with :func:`~odoo.http.route` is necessary to keep the method
- (and route) visible: if the method is redefined without decorating, it
- will be "unpublished"
-* the decorators of all methods are combined, if the overriding method's
- decorator has no argument all previous ones will be kept, any provided
- argument will override previously defined ones e.g.::
-
- class Restrict(MyController):
- @route(auth='user')
- def handler(self):
- return super(Restrict, self).handler()
-
- will change ``/some_url`` from public authentication to user (requiring a
- log-in)
-
-API
-===
-
-.. _reference/http/routing:
-
-Routing
--------
-
-.. autofunction:: odoo.http.route
-
-.. _reference/http/request:
-
-Request
--------
-
-The request object is automatically set on :data:`odoo.http.request` at
-the start of the request
-
-.. autoclass:: odoo.http.WebRequest
- :members:
- :member-order: bysource
-.. autoclass:: odoo.http.HttpRequest
- :members:
-.. autoclass:: odoo.http.JsonRequest
- :members:
-
-Response
---------
-
-.. autoclass:: odoo.http.Response
- :members:
- :member-order: bysource
-
- .. maybe set this to document all the fine methods on Werkzeug's Response
- object? (it works)
- :inherited-members:
diff --git a/doc/reference/images/mobile_contact_create.png b/doc/reference/images/mobile_contact_create.png
deleted file mode 100644
index 53ca9e4998f..00000000000
--- a/doc/reference/images/mobile_contact_create.png
+++ /dev/null
Binary files differ
diff --git a/doc/reference/images/mobile_notification.png b/doc/reference/images/mobile_notification.png
deleted file mode 100644
index ea72d7a6d24..00000000000
--- a/doc/reference/images/mobile_notification.png
+++ /dev/null
Binary files differ
diff --git a/doc/reference/images/mobile_switch_account.png b/doc/reference/images/mobile_switch_account.png
deleted file mode 100644
index 3c7da3e2c31..00000000000
--- a/doc/reference/images/mobile_switch_account.png
+++ /dev/null
Binary files differ
diff --git a/doc/reference/images/mobile_working.jpg b/doc/reference/images/mobile_working.jpg
deleted file mode 100644
index 8243530f715..00000000000
--- a/doc/reference/images/mobile_working.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/reference/images/odoo_mobile_api.png b/doc/reference/images/odoo_mobile_api.png
deleted file mode 100644
index 8fdf37942f4..00000000000
--- a/doc/reference/images/odoo_mobile_api.png
+++ /dev/null
Binary files differ
diff --git a/doc/reference/images/runner.png b/doc/reference/images/runner.png
deleted file mode 100644
index fba0121caf5..00000000000
--- a/doc/reference/images/runner.png
+++ /dev/null
Binary files differ
diff --git a/doc/reference/images/runner2.png b/doc/reference/images/runner2.png
deleted file mode 100644
index 45bb5c5585b..00000000000
--- a/doc/reference/images/runner2.png
+++ /dev/null
Binary files differ
diff --git a/doc/reference/images/snackbar.png b/doc/reference/images/snackbar.png
deleted file mode 100644
index 76ad0f1a9ad..00000000000
--- a/doc/reference/images/snackbar.png
+++ /dev/null
Binary files differ
diff --git a/doc/reference/images/tests.png b/doc/reference/images/tests.png
deleted file mode 100644
index 11552c0539d..00000000000
--- a/doc/reference/images/tests.png
+++ /dev/null
Binary files differ
diff --git a/doc/reference/images/tests2.png b/doc/reference/images/tests2.png
deleted file mode 100644
index b51da6b9e72..00000000000
--- a/doc/reference/images/tests2.png
+++ /dev/null
Binary files differ
diff --git a/doc/reference/images/tests3.png b/doc/reference/images/tests3.png
deleted file mode 100644
index e89da505f52..00000000000
--- a/doc/reference/images/tests3.png
+++ /dev/null
Binary files differ
diff --git a/doc/reference/images/toast.png b/doc/reference/images/toast.png
deleted file mode 100644
index d6f5298a722..00000000000
--- a/doc/reference/images/toast.png
+++ /dev/null
Binary files differ
diff --git a/doc/reference/iot.rst b/doc/reference/iot.rst
deleted file mode 100644
index 2a7e8d66eb1..00000000000
--- a/doc/reference/iot.rst
+++ /dev/null
@@ -1,195 +0,0 @@
-:banner: banners/iot.jpg
-
-==================
-Internet of Things
-==================
-
-IoT Drivers allow any Odoo module to communicate in real-time with any device
-connected to the IoT Box. Communication with the IoT Box goes both ways, so the
-Odoo client can send commands to and receive information from any of the
-supported devices.
-
-To add support for a device, all we need is:
-
-- an `Interface`, to detect connected devices of a specific type
-- a `Driver`, to communicate with an individual device
-
-At each boot, the IoT Box will load all of the Interfaces and Drivers that can
-be located on the connected Odoo instance. Each module can contain an
-`iot_handlers` directory that will be copied to the IoT Box. The structure of
-this directory is the following
-
-.. code-block:: text
-
- your_module
- ├── ...
- └── iot_handlers
- ├── drivers
- │ ├── DriverName.py
- │ └── ...
- │
- └── interfaces
- ├── InterfaceName.py
- └── ...
-
-Detect Devices
-==============
-
-Devices connected to the IoT Box are detected through `Interfaces`. There is an
-Interface for each supported connection type (USB, Bluetooth, Video,
-Printers, Serial, etc.). The interface maintains a list of detected devices
-and associates them with the right Driver.
-
-Supported devices will appear both on the IoT Box Homepage that you can access
-through its IP address and in the IoT module of the connected Odoo instance.
-
-Interface
----------
-
-The role of the Interface is to maintain a list of devices connected through a
-determined connection type. Creating a new interface requires
-
-- Extending the `Interface` class
-- Setting the `connection_type` class attribute
-- Implementing the `get_devices` method, that should return a dictionary
- containing data about each detected device. This data will be given as
- argument to the constructors and `supported` method of the Drivers.
-
-.. note::
- Setting the `_loop_delay` attribute will modify the interval between calls
- to `get_devices`. By default, this interval is set to 3 seconds.
-
-.. code-block:: python
-
- from odoo.addons.hw_drivers.interface import Interface
-
- class InterfaceName(Interface):
- connection_type = 'ConnectionType'
-
- def get_devices(self):
- return {
- 'device_identifier_1': {...},
- ...
- }
-
-Driver
-------
-
-Once the interface has retrieved the list of detected devices, it will loop
-through all of the Drivers that have the same `connection_type` attribute and
-test their respective `supported` method on all detected devices. If the
-supported method of a Driver returns `True`, an instance of this Driver will be
-created for the corresponding device.
-
-.. note::
- `supported` methods of drivers are given a priority order. The `supported`
- method of a child class will always be tested before the one of its parent.
- This priority can be adjusted by modifying the `priority` attribute of the
- Driver.
-
-Creating a new Driver requires:
-
-- Extending `Driver`
-- Setting the `connection_type` class attribute.
-- Setting the `device_type`, `device_connection` and `device_name` attributes.
-- Defining the `supported` method
-
-.. code-block:: python
-
- from odoo.addons.hw_drivers.driver import Driver
-
- class DriverName(Driver):
- connection_type = 'ConnectionType'
-
- def __init__(self, identifier, device):
- super(NewDriver, self).__init__(identifier, device)
- self.device_type = 'DeviceType'
- self.device_connection = 'DeviceConnection'
- self.device_name = 'DeviceName'
-
- @classmethod
- def supported(cls, device):
- ...
-
-Communicate With Devices
-========================
-
-Once your new device is detected and appears in the IoT module, the next step
-is to communicate with it. Since the box only has a local IP address, it can
-only be reached from the same local network. Communication, therefore, needs to
-happen on the browser-side, in JavaScript.
-
-The process depends on the direction of the communication:
-- From the browser to the box, through `Actions`_
-- From the box to the browser, through `Longpolling`_
-
-Both channels are accessed from the same JS object, the `DeviceProxy`, which is
-instantiated using the IP of the IoT Box and the device identifier.
-
-.. code-block:: javascript
-
- var DeviceProxy = require('iot.DeviceProxy');
-
- var iot_device = new DeviceProxy({
- iot_ip: iot_ip,
- identifier: device_identifier
- });
-
-Actions
--------
-
-Actions are used to tell a selected device to execute a specific action,
-such as taking a picture, printing a receipt, etc.
-
-.. note::
- It must be noted that no “answer” will be sent by the box on this route,
- only the request status. The answer to the action, if any, has to be
- retrieved via the longpolling.
-
-An action can be performed on the DeviceProxy Object.
-
-.. code-block:: javascript
-
- iot_device.action(data);
-
-In your driver, define an `action` method that will be executed when called
-from an Odoo module. It takes the data given during the call as argument.
-
-.. code-block:: python
-
- def action(self, data):
- ...
-
-Longpolling
------------
-
-When any module in Odoo wants to read data from a specific device, it creates a
-listener identified by the IP/domain of the box and the device identifier and
-passes it a callback function to be called every time the device status
-changes. The callback is called with the new data as argument.
-
-.. code-block:: javascript
-
- iot_device.add_listener(this._onValueChange.bind(this));
-
- _onValueChange: function (result) {
- ...
- }
-
-In the Driver, an event is released by calling the `device_changed` function
-from the `event_manager`. All callbacks set on the listener will then be called
-with `self.data` as argument.
-
-.. code-block:: python
-
- from odoo.addons.hw_drivers.event_manager import event_manager
-
- class DriverName(Driver):
- connection_type = 'ConnectionType'
-
- def methodName(self):
- self.data = {
- 'value': 0.5,
- ...
- }
- event_manager.device_changed(self)
diff --git a/doc/reference/javascript_cheatsheet.rst b/doc/reference/javascript_cheatsheet.rst
deleted file mode 100644
index 1dfa1937d00..00000000000
--- a/doc/reference/javascript_cheatsheet.rst
+++ /dev/null
@@ -1,545 +0,0 @@
-:banner: banners/javascript.jpg
-
-.. _reference/jscs:
-
-=====================
-Javascript Cheatsheet
-=====================
-
-There are many ways to solve a problem in JavaScript, and in Odoo. However, the
-Odoo framework was designed to be extensible (this is a pretty big constraint),
-and some common problems have a nice standard solution. The standard solution
-has probably the advantage of being easy to understand for an odoo developers,
-and will probably keep working when Odoo is modified.
-
-This document tries to explain the way one could solve some of these issues.
-Note that this is not a reference. This is just a random collection of recipes,
-or explanations on how to proceed in some cases.
-
-
-First of all, remember that the first rule of customizing odoo with JS is:
-*try to do it in python*. This may seem strange, but the python framework is
-quite extensible, and many behaviours can be done simply with a touch of xml or
-python. This has usually a lower cost of maintenance than working with JS:
-
-- the JS framework tends to change more, so JS code needs to be more frequently
- updated
-- it is often more difficult to implement a customized behaviour if it needs to
- communicate with the server and properly integrate with the javascript framework.
- There are many small details taken care by the framework that customized code
- needs to replicate. For example, responsiveness, or updating the url, or
- displaying data without flickering.
-
-
-.. note:: This document does not really explain any concepts. This is more a
- cookbook. For more details, please consult the javascript reference
- page (see :doc:`javascript_reference`)
-
-Creating a new field widget
-===========================
-
-This is probably a really common usecase: we want to display some information in
-a form view in a really specific (maybe business dependent) way. For example,
-assume that we want to change the text color depending on some business condition.
-
-This can be done in three steps: creating a new widget, registering it in the
-field registry, then adding the widget to the field in the form view
-
-- creating a new widget:
- This can be done by extending a widget:
-
- .. code-block:: javascript
-
- var FieldChar = require('web.basic_fields').FieldChar;
-
- var CustomFieldChar = FieldChar.extend({
- _renderReadonly: function () {
- // implement some custom logic here
- },
- });
-
-- registering it in the field registry:
- The web client needs to know the mapping between a widget name and its
- actual class. This is done by a registry:
-
- .. code-block:: javascript
-
- var fieldRegistry = require('web.field_registry');
-
- fieldRegistry.add('my-custom-field', CustomFieldChar);
-
-- adding the widget in the form view
- .. code-block:: xml
-
- <field name="somefield" widget="my-custom-field"/>
-
- Note that only the form, list and kanban views use this field widgets registry.
- These views are tightly integrated, because the list and kanban views can
- appear inside a form view).
-
-Modifying an existing field widget
-==================================
-
-Another use case is that we want to modify an existing field widget. For
-example, the voip addon in odoo need to modify the FieldPhone widget to add the
-possibility to easily call the given number on voip. This is done by *including*
-the FieldPhone widget, so there is no need to change any existing form view.
-
-Field Widgets (instances of (subclass of) AbstractField) are like every other
-widgets, so they can be monkey patched. This looks like this:
-
-.. code-block:: javascript
-
- var basic_fields = require('web.basic_fields');
- var Phone = basic_fields.FieldPhone;
-
- Phone.include({
- events: _.extend({}, Phone.prototype.events, {
- 'click': '_onClick',
- }),
-
- _onClick: function (e) {
- if (this.mode === 'readonly') {
- e.preventDefault();
- var phoneNumber = this.value;
- // call the number on voip...
- }
- },
- });
-
-Note that there is no need to add the widget to the registry, since it is already
-registered.
-
-Modifying a main widget from the interface
-==========================================
-
-Another common usecase is the need to customize some elements from the user
-interface. For example, adding a message in the home menu. The usual process
-in this case is again to *include* the widget. This is the only way to do it,
-since there are no registries for those widgets.
-
-This is usually done with code looking like this:
-
-.. code-block:: javascript
-
- var HomeMenu = require('web_enterprise.HomeMenu');
-
- HomeMenu.include({
- render: function () {
- this._super();
- // do something else here...
- },
- });
-
-
-
-Creating a new view (from scratch)
-==================================
-
-Creating a new view is a more advanced topic. This cheatsheet will only
-highlight the steps that will probably need to be done (in no particular order):
-
-- adding a new view type to the field ``type`` of ``ir.ui.view``::
-
- class View(models.Model):
- _inherit = 'ir.ui.view'
-
- type = fields.Selection(selection_add=[('map', "Map")])
-
-- adding the new view type to the field ``view_mode`` of ``ir.actions.act_window.view``::
-
- class ActWindowView(models.Model):
- _inherit = 'ir.actions.act_window.view'
-
- view_mode = fields.Selection(selection_add=[('map', "Map")])
-
-
-- creating the four main pieces which makes a view (in JavaScript):
- we need a view (a subclass of ``AbstractView``, this is the factory), a
- renderer (from ``AbstractRenderer``), a controller (from ``AbstractController``)
- and a model (from ``AbstractModel``). I suggest starting by simply
- extending the superclasses:
-
- .. code-block:: javascript
-
- var AbstractController = require('web.AbstractController');
- var AbstractModel = require('web.AbstractModel');
- var AbstractRenderer = require('web.AbstractRenderer');
- var AbstractView = require('web.AbstractView');
-
- var MapController = AbstractController.extend({});
- var MapRenderer = AbstractRenderer.extend({});
- var MapModel = AbstractModel.extend({});
-
- var MapView = AbstractView.extend({
- config: {
- Model: MapModel,
- Controller: MapController,
- Renderer: MapRenderer,
- },
- });
-
-- adding the view to the registry:
- As usual, the mapping between a view type and the actual class needs to be
- updated:
-
- .. code-block:: javascript
-
- var viewRegistry = require('web.view_registry');
-
- viewRegistry.add('map', MapView);
-
-- implementing the four main classes:
- The ``View`` class needs to parse the ``arch`` field and setup the other
- three classes. The ``Renderer`` is in charge of representing the data in
- the user interface, the ``Model`` is supposed to talk to the server, to
- load data and process it. And the ``Controller`` is there to coordinate,
- to talk to the web client, ...
-
-- creating some views in the database:
- .. code-block:: xml
-
- <record id="customer_map_view" model="ir.ui.view">
- <field name="name">customer.map.view</field>
- <field name="model">res.partner</field>
- <field name="arch" type="xml">
- <map latitude="partner_latitude" longitude="partner_longitude">
- <field name="name"/>
- </map>
- </field>
- </record>
-
-
-Customizing an existing view
-============================
-
-Assume we need to create a custom version of a generic view. For example, a
-kanban view with some extra *ribbon-like* widget on top (to display some
-specific custom information). In that case, this can be done with 3 steps:
-extend the kanban view (which also probably mean extending controllers/renderers
-and/or models), then registering the view in the view registry, and finally,
-using the view in the kanban arch (a specific example is the helpdesk dashboard).
-
-- extending a view:
- Here is what it could look like:
-
- .. code-block:: javascript
-
- var HelpdeskDashboardRenderer = KanbanRenderer.extend({
- ...
- });
-
- var HelpdeskDashboardModel = KanbanModel.extend({
- ...
- });
-
- var HelpdeskDashboardController = KanbanController.extend({
- ...
- });
-
- var HelpdeskDashboardView = KanbanView.extend({
- config: _.extend({}, KanbanView.prototype.config, {
- Model: HelpdeskDashboardModel,
- Renderer: HelpdeskDashboardRenderer,
- Controller: HelpdeskDashboardController,
- }),
- });
-
-- adding it to the view registry:
- as usual, we need to inform the web client of the mapping between the name
- of the views and the actual class.
-
- .. code-block:: javascript
-
- var viewRegistry = require('web.view_registry');
- viewRegistry.add('helpdesk_dashboard', HelpdeskDashboardView);
-
-- using it in an actual view:
- we now need to inform the web client that a specific ``ir.ui.view`` needs to
- use our new class. Note that this is a web client specific concern. From
- the point of view of the server, we still have a kanban view. The proper
- way to do this is by using a special attribute ``js_class`` (which will be
- renamed someday into ``widget``, because this is really not a good name) on
- the root node of the arch:
-
- .. code-block:: xml
-
- <record id="helpdesk_team_view_kanban" model="ir.ui.view" >
- ...
- <field name="arch" type="xml">
- <kanban js_class="helpdesk_dashboard">
- ...
- </kanban>
- </field>
- </record>
-
-.. note::
-
- Note: you can change the way the view interprets the arch structure. However,
- from the server point of view, this is still a view of the same base type,
- subjected to the same rules (rng validation, for example). So, your views still
- need to have a valid arch field.
-
-Promises and asynchronous code
-===============================
-
-For a very good and complete introduction to promises, please read this excellent article https://github.com/getify/You-Dont-Know-JS/blob/1st-ed/async%20%26%20performance/ch3.md
-
-Creating new Promises
------------------------
-- turn a constant into a promise
- There are 2 static functions on Promise that create a resolved or rejected promise based on a constant:
-
- .. code-block:: javascript
-
- var p = Promise.resolve({blabla: '1'}); // creates a resolved promise
- p.then(function (result) {
- console.log(result); // --> {blabla: '1'};
- });
-
-
- var p2 = Promise.reject({error: 'error message'}); // creates a rejected promise
- p2.catch(function (reason) {
- console.log(reason); // --> {error: 'error message');
- });
-
-
- .. note:: Note that even if the promises are created already resolved or rejected, the `then` or `catch` handlers will still be called asynchronously.
-
-
-- based on an already asynchronous code
- Suppose that in a function you must do a rpc, and when it is completed set the result on this.
- The `this._rpc` is a function that returns a `Promise`.
-
- .. code-block:: javascript
-
- function callRpc() {
- var self = this;
- return this._rpc(...).then(function (result) {
- self.myValueFromRpc = result;
- });
- }
-
-- for callback based function
- Suppose that you were using a function `this.close` that takes as parameter a callback that is called when the closing is finished.
- Now suppose that you are doing that in a method that must send a promise that is resolved when the closing is finished.
-
- .. code-block:: javascript
- :linenos:
-
- function waitForClose() {
- var self = this;
- return new Promise (function(resolve, reject) {
- self.close(resolve);
- });
- }
-
- * line 2: we save the `this` into a variable so that in an inner function, we can access the scope of our component
- * line 3: we create and return a new promise. The constructor of a promise takes a function as parameter. This function itself has 2 parameters that we called here `resolve` and `reject`
- - `resolve` is a function that, when called, puts the promise in the resolved state.
- - `reject` is a function that, when called, puts the promise in the rejected state. We do not use reject here and it can be omitted.
- * line 4: we are calling the function close on our object. It takes a function as parameter (the callback) and it happens that resolve is already a function, so we can pass it directly. To be clearer, we could have written:
-
- .. code-block:: javascript
-
- return new Promise (function (resolve) {
- self.close(function () {
- resolve();
- });
- });
-
-
-
-- creating a promise generator (calling one promise after the other *in sequence* and waiting for the last one)
- Suppose that you need to loop over an array, do an operation *in sequence* and resolve a promise when the last operation is done.
-
- .. code-block:: javascript
-
- function doStuffOnArray(arr) {
- var done = Promise.resolve();
- arr.forEach(function (item) {
- done = done.then(function () {
- return item.doSomethingAsynchronous();
- });
- });
- return done;
- }
-
- This way, the promise you return is effectively the last promise.
-- creating a promise, then resolving it outside the scope of its definition (anti-pattern)
- .. note:: we do not recommend using this, but sometimes it is useful. Think carefully for alternatives first...
-
- .. code-block:: javascript
-
- ...
- var resolver, rejecter;
- var prom = new Promise(function (resolve, reject){
- resolver = resolve;
- rejecter = reject;
- });
- ...
-
- resolver("done"); // will resolve the promise prom with the result "done"
- rejecter("error"); // will reject the promise prom with the reason "error"
-
-Waiting for Promises
---------------------
-- waiting for a number of Promises
- if you have multiple promises that all need to be waited, you can convert them into a single promise that will be resolved when all the promises are resolved using Promise.all(arrayOfPromises).
-
- .. code-block:: javascript
-
- var prom1 = doSomethingThatReturnsAPromise();
- var prom2 = Promise.resolve(true);
- var constant = true;
-
- var all = Promise.all([prom1, prom2, constant]); // all is a promise
- // results is an array, the individual results correspond to the index of their
- // promise as called in Promise.all()
- all.then(function (results) {
- var prom1Result = results[0];
- var prom2Result = results[1];
- var constantResult = results[2];
- });
- return all;
-
-
-- waiting for a part of a promise chain, but not another part
- If you have an asynchronous process that you want to wait to do something, but you also want to return to the caller before that something is done.
-
- .. code-block:: javascript
-
- function returnAsSoonAsAsyncProcessIsDone() {
- var prom = AsyncProcess();
- prom.then(function (resultOfAsyncProcess) {
- return doSomething();
- });
- /* returns prom which will only wait for AsyncProcess(),
- and when it will be resolved, the result will be the one of AsyncProcess */
- return prom;
- }
-
-Error handling
---------------
-
-- in general in promises
- The general idea is that a promise should not be rejected for control flow, but should only be rejected for errors.
- When that is the case, you would have multiple resolutions of your promise with, for instance status codes that you would have to check in the `then` handlers and a single `catch` handler at the end of the promise chain.
-
- .. code-block:: javascript
-
- function a() {
- x.y(); // <-- this is an error: x is undefined
- return Promise.resolve(1);
- }
- function b() {
- return Promise.reject(2);
- }
-
- a().catch(console.log); // will log the error in a
- a().then(b).catch(console.log); // will log the error in a, the then is not executed
- b().catch(console.log); // will log the rejected reason of b (2)
- Promise.resolve(1)
- .then(b) // the then is executed, it executes b
- .then(...) // this then is not executed
- .catch(console.log); // will log the rejected reason of b (2)
-
-
-
-- in Odoo specifically
- In Odoo, it happens that we use promise rejection for control flow, like in mutexes and other concurrency primitives defined in module `web.concurrency`
- We also want to execute the catch for *business* reasons, but not when there is a coding error in the definition of the promise or of the handlers.
- For this, we have introduced the concept of `guardedCatch`. It is called like `catch` but not when the rejected reason is an error
-
- .. code-block:: javascript
-
- function blabla() {
- if (someCondition) {
- return Promise.reject("someCondition is truthy");
- }
- return Promise.resolve();
- }
-
- // ...
-
- var promise = blabla();
- promise.then(function (result) { console.log("everything went fine"); })
- // this will be called if blabla returns a rejected promise, but not if it has an error
- promise.guardedCatch(function (reason) { console.log(reason); });
-
- // ...
-
- var anotherPromise =
- blabla().then(function () { console.log("everything went fine"); })
- // this will be called if blabla returns a rejected promise,
- // but not if it has an error
- .guardedCatch(console.log);
-
-
- .. code-block:: javascript
-
- var promiseWithError = Promise.resolve().then(function () {
- x.y(); // <-- this is an error: x is undefined
- });
- promiseWithError.guardedCatch(function (reason) {console.log(reason);}); // will not be called
- promiseWithError.catch(function (reason) {console.log(reason);}); // will be called
-
-
-
-Testing asynchronous code
---------------------------
-
-- using promises in tests
- In the tests code, we support the latest version of Javascript, including primitives like `async` and `await`. This makes using and waiting for promises very easy.
- Most helper methods also return a promise (either by being marked `async` or by returning a promise directly.
-
- .. code-block:: javascript
-
- var testUtils = require('web.test_utils');
- QUnit.test("My test", async function (assert) {
- // making the function async has 2 advantages:
- // 1) it always returns a promise so you don't need to define `var done = assert.async()`
- // 2) it allows you to use the `await`
- assert.expect(1);
-
- var form = await testUtils.createView({ ... });
- await testUtils.form.clickEdit(form);
- await testUtils.form.click('jquery selector');
- assert.containsOnce('jquery selector');
- form.destroy();
- });
-
- QUnit.test("My test - no async - no done", function (assert) {
- // this function is not async, but it returns a promise.
- // QUnit will wait for for this promise to be resolved.
- assert.expect(1);
-
- return testUtils.createView({ ... }).then(function (form) {
- return testUtils.form.clickEdit(form).then(function () {
- return testUtils.form.click('jquery selector').then(function () {
- assert.containsOnce('jquery selector');
- form.destroy();
- });
- });
- });
- });
-
-
- QUnit.test("My test - no async", function (assert) {
- // this function is not async and does not return a promise.
- // we have to use the done function to signal QUnit that the test is async and will be finished inside an async callback
- assert.expect(1);
- var done = assert.async();
-
- testUtils.createView({ ... }).then(function (form) {
- testUtils.form.clickEdit(form).then(function () {
- testUtils.form.click('jquery selector').then(function () {
- assert.containsOnce('jquery selector');
- form.destroy();
- done();
- });
- });
- });
- });
-
- as you can see, the nicer form is to use `async/await` as it is clearer and shorter to write.
diff --git a/doc/reference/javascript_reference.rst b/doc/reference/javascript_reference.rst
deleted file mode 100644
index 9e6e208648e..00000000000
--- a/doc/reference/javascript_reference.rst
+++ /dev/null
@@ -1,2425 +0,0 @@
-:banner: banners/javascript.jpg
-
-.. highlight:: javascript
-
-.. default-domain:: js
-
-=====================
-Javascript Reference
-=====================
-
-This document presents the Odoo Javascript framework. This
-framework is not a large application in term of lines of code, but it is quite
-generic, because it is basically a machine to turn a declarative interface
-description into a live application, able to interact with every model and
-records in the database. It is even possible to use the web client to modify
-the interface of the web client.
-
-Overview
-=========
-
-The Javascript framework is designed to work with three main use cases:
-
-- the *web client*: this is the private web application, where one can view and
- edit business data. This is a single page application (the page is never
- reloaded, only the new data is fetched from the server whenever it is needed)
-- the *website*: this is the public part of Odoo. It allows an unidentified
- user to browse some content, to shop or to perform many actions, as a client.
- This is a classical website: various routes with controllers and some
- javascript to make it work.
-- the *point of sale*: this is the interface for the point of sale. It is a
- specialized single page application.
-
-Some javascript code is common to these three use cases, and is bundled together
-(see below in the assets section). This document will focus mostly on the web
-client design.
-
-Web client
-==========
-
-Single Page Application
------------------------
-
-In short, the *webClient*, instance of *WebClient* is the root component of the
-whole user interface. Its responsibility is to orchestrate all various
-subcomponents, and to provide services, such as rpcs, local storage and more.
-
-In runtime, the web client is a single page application. It does not need to
-request a full page from the server each time the user perform an action. Instead,
-it only requests what it needs, and then replaces/updates the view. Also, it
-manages the url: it is kept in sync with the web client state.
-
-It means that while a user is working on Odoo, the web client class (and the
-action manager) actually creates and destroys many sub components. The state is
-highly dynamic, and each widget could be destroyed at any time.
-
-Overview of web client JS code
--------------------------------------
-
-Here, we give a very quick overview on the web client code, in
-the *web/static/src/js* addon. Note that it is deliberately not exhaustive.
-We only cover the most important files/folders.
-
-- *boot.js*: this is the file that defines the module system. It needs to be
- loaded first.
-- *core/*: this is a collection of lower level building blocks. Notably, it
- contains the class system, the widget system, concurrency utilities, and many
- other class/functions.
-- *chrome/*: in this folder, we have most large widgets which make up most of
- the user interface.
-- *chrome/abstract_web_client.js* and *chrome/web_client.js*: together, these
- files define the WebClient widget, which is the root widget for the web client.
-- *chrome/action_manager.js*: this is the code that will convert an action into
- a widget (for example a kanban or a form view)
-- *chrome/search_X.js* all these files define the search view (it is not a view
- in the point of view of the web client, only from the server point of view)
-- *fields*: all main view field widgets are defined here
-- *views*: this is where the views are located
-
-Assets Management
-=================
-
-Managing assets in Odoo is not as straightforward as it is in some other apps.
-One of the reason is that we have a variety of situations where some, but not all
-the assets are required. For example, the needs of the web client, the point of
-sale, the website or even the mobile application are different. Also, some
-assets may be large, but are seldom needed. In that case, we sometimes want them
-to be loaded lazily.
-
-The main idea is that we define a set of *bundles* in xml. A bundle is here defined as
-a collection of files (javascript, css, scss). In Odoo, the most important
-bundles are defined in the file *addons/web/views/webclient_templates.xml*. It looks
-like this:
-
-.. code-block:: xml
-
- <template id="web.assets_common" name="Common Assets (used in backend interface and website)">
- <link rel="stylesheet" type="text/css" href="/web/static/lib/jquery.ui/jquery-ui.css"/>
- ...
- <script type="text/javascript" src="/web/static/src/js/boot.js"></script>
- ...
- </template>
-
-
-The files in a bundle can then be inserted into a template by using the *t-call-assets*
-directive:
-
-.. code-block:: xml
-
- <t t-call-assets="web.assets_common" t-js="false"/>
- <t t-call-assets="web.assets_common" t-css="false"/>
-
-Here is what happens when a template is rendered by the server with these directives:
-
-- all the *scss* files described in the bundle are compiled into css files. A file
- named *file.scss* will be compiled in a file named *file.scss.css*.
-
-- if we are in *debug=assets* mode
-
- - the *t-call-assets* directive with the *t-js* attribute set to false will
- be replaced by a list of stylesheet tags pointing to the css files
-
- - the *t-call-assets* directive with the *t-css* attribute set to false will
- be replaced by a list of script tags pointing to the js files
-
-- if we are not in *debug=assets* mode
-
- - the css files will be concatenated and minified, then a stylesheet tag is
- generated
-
- - the js files are concatenated and minified, then a script tag is generated
-
-Note that the assets files are cached, so in theory, a browser should only load
-them once.
-
-Main bundles
-------------
-When the Odoo server is started, it checks the timestamp of each file in a bundle,
-and if necessary, will create/recreate the corresponding bundles.
-
-Here are some important bundles that most developers will need to know:
-
-- *web.assets_common*: this bundle contains most assets which are common to the
- web client, the website, and also the point of sale. This is supposed to contain
- lower level building blocks for the odoo framework. Note that it contains the
- *boot.js* file, which defines the odoo module system.
-
-- *web.assets_backend*: this bundle contains the code specific to the web client
- (notably the web client/action manager/views)
-
-- *web.assets_frontend*: this bundle is about all that is specific to the public
- website: ecommerce, forum, blog, event management, ...
-
-
-Adding files in an asset bundle
--------------------------------
-
-The proper way to add a file located in *addons/web* to a bundle is simple:
-it is just enough to add a *script* or a *stylesheet* tag to the bundle in the
-file *webclient_templates.xml*. But when we work in a different addon, we need
-to add a file from that addon. In that case, it should be done in three steps:
-
-1. add a *assets.xml* file in the *views/* folder
-2. add the string 'views/assets.xml' in the 'data' key in the manifest file
-3. create an inherited view of the desired bundle, and add the file(s) with an
- xpath expression. For example,
-
-.. code-block:: xml
-
- <template id="assets_backend" name="helpdesk assets" inherit_id="web.assets_backend">
- <xpath expr="//script[last()]" position="after">
- <link rel="stylesheet" type="text/scss" href="/helpdesk/static/src/scss/helpdesk.scss"/>
- <script type="text/javascript" src="/helpdesk/static/src/js/helpdesk_dashboard.js"></script>
- </xpath>
- </template>
-
-
-.. note ::
-
- Note that the files in a bundle are all loaded immediately when the user loads the
- odoo web client. This means that the files are transferred through the network
- everytime (except when the browser cache is active). In some cases, it may be
- better to lazyload some assets. For example, if a widget requires a large
- library, and that widget is not a core part of the experience, then it may be
- a good idea to only load the library when the widget is actually created. The
- widget class has actually builtin support just for this use case. (see section
- :ref:`reference/javascript_reference/qweb`)
-
-What to do if a file is not loaded/updated
-------------------------------------------
-
-There are many different reasons why a file may not be properly loaded. Here
-are a few things you can try to solve the issue:
-
-- once the server is started, it does not know if an asset file has been
- modified. So, you can simply restart the server to regenerate the assets.
-- check the console (in the dev tools, usually opened with F12) to make sure
- there are no obvious errors
-- try to add a console.log at the beginning of your file (before any module
- definition), so you can see if a file has been loaded or not
-- in the user interface, in debug mode (INSERT LINK HERE TO DEBUG MODE), there
- is an option to force the server to update its assets files.
-- use the *debug=assets* mode. This will actually bypass the asset bundles (note
- that it does not actually solve the issue. The server still uses outdated bundles)
-- finally, the most convenient way to do it, for a developer, is to start the
- server with the *--dev=all* option. This activates the file watcher options,
- which will automatically invalidate assets when necessary. Note that it does
- not work very well if the OS is Windows.
-- remember to refresh your page!
-- or maybe to save your code file...
-
-.. note::
- Once an asset file has been recreated, you need to refresh the page, to reload
- the proper files (if that does not work, the files may be cached).
-
-
-Javascript Module System
-========================
-
-Once we are able to load our javascript files into the browser, we need to make
-sure they are loaded in the correct order. In order to do that, Odoo has defined
-a small module system (located in the file *addons/web/static/src/js/boot.js*,
-which needs to be loaded first).
-
-The Odoo module system, inspired by AMD, works by defining the function *define*
-on the global odoo object. We then define each javascript module by calling that
-function. In the Odoo framework, a module is a piece of code that will be executed
-as soon as possible. It has a name and potentially some dependencies. When its
-dependencies are loaded, a module will then be loaded as well. The value of the
-module is then the return value of the function defining the module.
-
-
-As an example, it may look like this:
-
-
-.. code-block:: javascript
-
- // in file a.js
- odoo.define('module.A', function (require) {
- "use strict";
-
- var A = ...;
-
- return A;
- });
-
- // in file b.js
- odoo.define('module.B', function (require) {
- "use strict";
-
- var A = require('module.A');
-
- var B = ...; // something that involves A
-
- return B;
- });
-
-An alternative way to define a module is to give explicitly a list of dependencies
-in the second argument.
-
-.. code-block:: javascript
-
- odoo.define('module.Something', ['module.A', 'module.B'], function (require) {
- "use strict";
-
- var A = require('module.A');
- var B = require('module.B');
-
- // some code
- });
-
-
-If some dependencies are missing/non ready, then the module will simply not be
-loaded. There will be a warning in the console after a few seconds.
-
-Note that circular dependencies are not supported. It makes sense, but it means that one
-needs to be careful.
-
-Defining a module
------------------
-
-The *odoo.define* method is given three arguments:
-
-- *moduleName*: the name of the javascript module. It should be a unique string.
- The convention is to have the name of the odoo addon followed by a specific
- description. For example, 'web.Widget' describes a module defined in the *web*
- addon, which exports a *Widget* class (because the first letter is capitalized)
-
- If the name is not unique, an exception will be thrown and displayed in the
- console.
-
-- *dependencies*: the second argument is optional. If given, it should be a list
- of strings, each corresponding to a javascript module. This describes the
- dependencies that are required to be loaded before the module is executed. If
- the dependencies are not explicitly given here, then the module system will
- extract them from the function by calling toString on it, then using a regexp
- to find all *require* statements.
-
-.. code-block:: javascript
-
- odoo.define('module.Something', ['web.ajax'], function (require) {
- "use strict";
-
- var ajax = require('web.ajax');
-
- // some code here
- return something;
- });
-
-- finally, the last argument is a function which defines the module. Its return
- value is the value of the module, which may be passed to other modules requiring
- it. Note that there is a small exception for asynchronous modules, see the
- next section.
-
-If an error happens, it will be logged (in debug mode) in the console:
-
-* ``Missing dependencies``:
- These modules do not appear in the page. It is possible that the JavaScript
- file is not in the page or that the module name is wrong
-* ``Failed modules``:
- A javascript error is detected
-* ``Rejected modules``:
- The module returns a rejected Promise. It (and its dependent modules) is not
- loaded.
-* ``Rejected linked modules``:
- Modules who depend on a rejected module
-* ``Non loaded modules``:
- Modules who depend on a missing or a failed module
-
-
-
-Asynchronous modules
----------------------
-
-It can happen that a module needs to perform some work before it is ready. For
-example, it could do a rpc to load some data. In that case, the module can
-simply return a promise. In that case, the module system will simply
-wait for the promise to complete before registering the module.
-
-.. code-block:: javascript
-
- odoo.define('module.Something', function (require) {
- "use strict";
-
- var ajax = require('web.ajax');
-
- return ajax.rpc(...).then(function (result) {
- // some code here
- return something;
- });
- });
-
-
-Best practices
-----------------
-
-- remember the convention for a module name: *addon name* suffixed with *module
- name*.
-- declare all your dependencies at the top of the module. Also, they should be
- sorted alphabetically by module name. This makes it easier to understand your module.
-- declare all exported values at the end
-- try to avoid exporting too many things from one module. It is usually better
- to simply export one thing in one (small/smallish) module.
-- asynchronous modules can be used to simplify some use cases. For example,
- the *web.dom_ready* module returns a promise which will be resolved when the
- dom is actually ready. So, another module that needs the DOM could simply have
- a `require('web.dom_ready')` statement somewhere, and the code will only be
- executed when the DOM is ready.
-- try to avoid defining more than one module in one file. It may be convenient
- in the short term, but this is actually harder to maintain.
-
-
-Class System
-============
-
-Odoo was developed before ECMAScript 6 classes were available. In Ecmascript 5,
-the standard way to define a class is to define a function and to add methods
-on its prototype object. This is fine, but it is slightly complex when we want
-to use inheritance, mixins.
-
-For these reasons, Odoo decided to use its own class system, inspired by John
-Resig. The base Class is located in *web.Class*, in the file *class.js*.
-
-Creating a subclass
--------------------
-
-Let us discuss how classes are created. The main mechanism is to use the
-*extend* method (this is more or less the equivalent of *extend* in ES6 classes).
-
-.. code-block:: javascript
-
- var Class = require('web.Class');
-
- var Animal = Class.extend({
- init: function () {
- this.x = 0;
- this.hunger = 0;
- },
- move: function () {
- this.x = this.x + 1;
- this.hunger = this.hunger + 1;
- },
- eat: function () {
- this.hunger = 0;
- },
- });
-
-
-In this example, the *init* function is the constructor. It will be called when
-an instance is created. Making an instance is done by using the *new* keyword.
-
-Inheritance
------------
-
-It is convenient to be able to inherit an existing class. This is simply done
-by using the *extend* method on the superclass. When a method is called, the
-framework will secretly rebind a special method: *_super* to the currently
-called method. This allows us to use *this._super* whenever we need to call a
-parent method.
-
-
-.. code-block:: javascript
-
- var Animal = require('web.Animal');
-
- var Dog = Animal.extend({
- move: function () {
- this.bark();
- this._super.apply(this, arguments);
- },
- bark: function () {
- console.log('woof');
- },
- });
-
- var dog = new Dog();
- dog.move()
-
-Mixins
-------
-
-The odoo Class system does not support multiple inheritance, but for those cases
-when we need to share some behaviour, we have a mixin system: the *extend*
-method can actually take an arbitrary number of arguments, and will combine all
-of them in the new class.
-
-.. code-block:: javascript
-
- var Animal = require('web.Animal');
- var DanceMixin = {
- dance: function () {
- console.log('dancing...');
- },
- };
-
- var Hamster = Animal.extend(DanceMixin, {
- sleep: function () {
- console.log('sleeping');
- },
- });
-
-In this example, the *Hamster* class is a subclass of Animal, but it also mix
-the DanceMixin in.
-
-
-Patching an existing class
---------------------------
-
-It is not common, but we sometimes need to modify another class *in place*. The
-goal is to have a mechanism to change a class and all future/present instances.
-This is done by using the *include* method:
-
-.. code-block:: javascript
-
- var Hamster = require('web.Hamster');
-
- Hamster.include({
- sleep: function () {
- this._super.apply(this, arguments);
- console.log('zzzz');
- },
- });
-
-
-This is obviously a dangerous operation and should be done with care. But with
-the way Odoo is structured, it is sometimes necessary in one addon to modify
-the behavior of a widget/class defined in another addon. Note that it will
-modify all instances of the class, even if they have already been created.
-
-
-Widgets
-=======
-
-The *Widget* class is really an important building block of the user interface.
-Pretty much everything in the user interface is under the control of a widget.
-The Widget class is defined in the module *web.Widget*, in *widget.js*.
-
-In short, the features provided by the Widget class include:
-
-* parent/child relationships between widgets (*PropertiesMixin*)
-* extensive lifecycle management with safety features (e.g. automatically
- destroying children widgets during the destruction of a parent)
-* automatic rendering with :ref:`qweb <reference/qweb>`
-* various utility functions to help interacting with the outside environment.
-
-Here is an example of a basic counter widget:
-
-.. code-block:: javascript
-
- var Widget = require('web.Widget');
-
- var Counter = Widget.extend({
- template: 'some.template',
- events: {
- 'click button': '_onClick',
- },
- init: function (parent, value) {
- this._super(parent);
- this.count = value;
- },
- _onClick: function () {
- this.count++;
- this.$('.val').text(this.count);
- },
- });
-
-For this example, assume that the template *some.template* (and is properly
-loaded: the template is in a file, which is properly defined in the *qweb* key
-in the module manifest) is given by:
-
-.. code-block:: xml
-
- <div t-name="some.template">
- <span class="val"><t t-esc="widget.count"/></span>
- <button>Increment</button>
- </div>
-
-This example widget can be used in the following manner:
-
-.. code-block:: javascript
-
- // Create the instance
- var counter = new Counter(this, 4);
- // Render and insert into DOM
- counter.appendTo(".some-div");
-
-This example illustrates a few of the features of the *Widget* class, including
-the event system, the template system, the constructor with the initial *parent* argument.
-
-Widget Lifecycle
-----------------
-
-Like many component systems, the widget class has a well defined lifecycle. The
-usual lifecycle is the following: *init* is called, then *willStart*, then the
-rendering takes place, then *start* and finally *destroy*.
-
-.. function:: Widget.init(parent)
-
- this is the constructor. The init method is supposed to initialize the
- base state of the widget. It is synchronous and can be overridden to
- take more parameters from the widget's creator/parent
-
- :param parent: the new widget's parent, used to handle automatic
- destruction and event propagation. Can be ``null`` for
- the widget to have no parent.
- :type parent: :class:`~Widget`
-
-.. function:: Widget.willStart()
-
- this method will be called once by the framework when a widget is created
- and in the process of being appended to the DOM. The *willStart* method is a
- hook that should return a promise. The JS framework will wait for this promise
- to complete before moving on to the rendering step. Note that at this point,
- the widget does not have a DOM root element. The *willStart* hook is mostly
- useful to perform some asynchronous work, such as fetching data from the server
-
-.. function:: [Rendering]
-
- This step is automatically done by the framework. What happens is
- that the framework checks if a template key is defined on the widget. If that is
- the case, then it will render that template with the *widget* key bound to the
- widget in the rendering context (see the example above: we use *widget.count*
- in the QWeb template to read the value from the widget). If no template is
- defined, we read the *tagName* key and create a corresponding DOM element.
- When the rendering is done, we set the result as the $el property of the widget.
- After this, we automatically bind all events in the events and custom_events
- keys.
-
-.. function:: Widget.start()
-
- when the rendering is complete, the framework will automatically call
- the *start* method. This is useful to perform some specialized post-rendering
- work. For example, setting up a library.
-
- Must return a promise to indicate when its work is done.
-
- :returns: promise
-
-.. function:: Widget.destroy()
-
- This is always the final step in the life of a widget. When a
- widget is destroyed, we basically perform all necessary cleanup operations:
- removing the widget from the component tree, unbinding all events, ...
-
- Automatically called when the widget's parent is destroyed,
- must be called explicitly if the widget has no parent or if it is
- removed but its parent remains.
-
-Note that the willStart and start method are not necessarily called. A widget
-can be created (the *init* method will be called) and then destroyed (*destroy*
-method) without ever having been appended to the DOM. If that is the case, the
-willStart and start will not even be called.
-
-Widget API
-----------
-
-.. attribute:: Widget.tagName
-
- Used if the widget has no template defined. Defaults to ``div``,
- will be used as the tag name to create the DOM element to set as
- the widget's DOM root. It is possible to further customize this
- generated DOM root with the following attributes:
-
-
-.. attribute:: Widget.id
-
- Used to generate an ``id`` attribute on the generated DOM
- root. Note that this is rarely needed, and is probably not a good idea
- if a widget can be used more than once.
-
-.. attribute:: Widget.className
-
- Used to generate a ``class`` attribute on the generated DOM root. Note
- that it can actually contain more than one css class:
- *'some-class other-class'*
-
-.. attribute:: Widget.attributes
-
- Mapping (object literal) of attribute names to attribute
- values. Each of these k:v pairs will be set as a DOM attribute
- on the generated DOM root.
-
-.. attribute:: Widget.el
-
- raw DOM element set as root to the widget (only available after the start
- lifecycle method)
-
-.. attribute:: Widget.$el
-
- jQuery wrapper around :attr:`~Widget.el`. (only available after the start
- lifecycle method)
-
-.. attribute:: Widget.template
-
- Should be set to the name of a :ref:`QWeb template <reference/qweb>`.
- If set, the template will be rendered after the widget has been
- initialized but before it has been started. The root element generated by
- the template will be set as the DOM root of the widget.
-
-.. attribute:: Widget.xmlDependencies
-
- List of paths to xml files that need to be loaded before the
- widget can be rendered. This will not induce loading anything that has already
- been loaded. This is useful when you want to load your templates lazily,
- or if you want to share a widget between the website and the web client
- interface.
-
- .. code-block:: javascript
-
- var EditorMenuBar = Widget.extend({
- xmlDependencies: ['/web_editor/static/src/xml/editor.xml'],
- ...
-
-.. attribute:: Widget.events
-
- Events are a mapping of an event selector (an event name and an optional
- CSS selector separated by a space) to a callback. The callback can
- be the name of a widget's method or a function object. In either case, the
- ``this`` will be set to the widget:
-
- .. code-block:: javascript
-
- events: {
- 'click p.oe_some_class a': 'some_method',
- 'change input': function (e) {
- e.stopPropagation();
- }
- },
-
- The selector is used for jQuery's event delegation, the
- callback will only be triggered for descendants of the DOM root
- matching the selector. If the selector is left out
- (only an event name is specified), the event will be set directly on the
- widget's DOM root.
-
- Note: the use of an inline function is discouraged, and will probably be
- removed sometimes in the future.
-
-.. attribute:: Widget.custom_events
-
- this is almost the same as the *events* attribute, but the keys
- are arbitrary strings. They represent business events triggered by
- some sub widgets. When an event is triggered, it will 'bubble up' the widget
- tree (see the section on component communication for more details).
-
-.. function:: Widget.isDestroyed()
-
- :returns: ``true`` if the widget is being or has been destroyed, ``false``
- otherwise
-
-.. function:: Widget.$(selector)
-
- Applies the CSS selector specified as parameter to the widget's
- DOM root:
-
- .. code-block:: javascript
-
- this.$(selector);
-
- is functionally identical to:
-
- .. code-block:: javascript
-
- this.$el.find(selector);
-
- :param String selector: CSS selector
- :returns: jQuery object
-
- .. note:: this helper method is similar to ``Backbone.View.$``
-
-.. function:: Widget.setElement(element)
-
- Re-sets the widget's DOM root to the provided element, also
- handles re-setting the various aliases of the DOM root as well as
- unsetting and re-setting delegated events.
-
- :param Element element: a DOM element or jQuery object to set as
- the widget's DOM root
-
-
-Inserting a widget in the DOM
------------------------------
-
-.. function:: Widget.appendTo(element)
-
- Renders the widget and inserts it as the last child of the target, uses
- `.appendTo()`_
-
-.. function:: Widget.prependTo(element)
-
- Renders the widget and inserts it as the first child of the target, uses
- `.prependTo()`_
-
-.. function:: Widget.insertAfter(element)
-
- Renders the widget and inserts it as the preceding sibling of the target,
- uses `.insertAfter()`_
-
-.. function:: Widget.insertBefore(element)
-
- Renders the widget and inserts it as the following sibling of the target,
- uses `.insertBefore()`_
-
-All of these methods accept whatever the corresponding jQuery method accepts
-(CSS selectors, DOM nodes or jQuery objects). They all return a promise
-and are charged with three tasks:
-
-* rendering the widget's root element via :func:`~Widget.renderElement`
-* inserting the widget's root element in the DOM using whichever jQuery
- method they match
-* starting the widget, and returning the result of starting it
-
-Widget Guidelines
-----------------------
-
-* Identifiers (``id`` attribute) should be avoided. In generic applications
- and modules, ``id`` limits the re-usability of components and tends to make
- code more brittle. Most of the time, they can be replaced with nothing,
- classes or keeping a reference to a DOM node or jQuery element.
-
- If an ``id`` is absolutely necessary (because a third-party library requires
- one), the id should be partially generated using ``_.uniqueId()`` e.g.:
-
- .. code-block:: javascript
-
- this.id = _.uniqueId('my-widget-');
-
-* Avoid predictable/common CSS class names. Class names such as "content" or
- "navigation" might match the desired meaning/semantics, but it is likely an
- other developer will have the same need, creating a naming conflict and
- unintended behavior. Generic class names should be prefixed with e.g. the
- name of the component they belong to (creating "informal" namespaces, much
- as in C or Objective-C).
-
-* Global selectors should be avoided. Because a component may be used several
- times in a single page (an example in Odoo is dashboards), queries should be
- restricted to a given component's scope. Unfiltered selections such as
- ``$(selector)`` or ``document.querySelectorAll(selector)`` will generally
- lead to unintended or incorrect behavior. Odoo Web's
- :class:`~Widget` has an attribute providing its DOM root
- (:attr:`~Widget.$el`), and a shortcut to select nodes directly
- (:func:`~Widget.$`).
-
-* More generally, never assume your components own or controls anything beyond
- its own personal :attr:`~Widget.$el` (so, avoid using a reference to the
- parent widget)
-
-* Html templating/rendering should use QWeb unless absolutely trivial.
-
-* All interactive components (components displaying information to the screen
- or intercepting DOM events) must inherit from :class:`~Widget`
- and correctly implement and use its API and life cycle.
-
-* Make sure to wait for start to be finished before using $el e.g.:
-
- .. code-block:: javascript
-
- var Widget = require('web.Widget');
-
- var AlmostCorrectWidget = Widget.extend({
- start: function () {
- this.$el.hasClass(....) // in theory, $el is already set, but you don't know what the parent will do with it, better call super first
- return this._super.apply(arguments);
- },
- });
-
- var IncorrectWidget = Widget.extend({
- start: function () {
- this._super.apply(arguments); // the parent promise is lost, nobody will wait for the start of this widget
- this.$el.hasClass(....)
- },
- });
-
- var CorrectWidget = Widget.extend({
- start: function () {
- var self = this;
- return this._super.apply(arguments).then(function() {
- self.$el.hasClass(....) // this works, no promise is lost and the code executes in a controlled order: first super, then our code.
- });
- },
- });
-
-.. _reference/javascript_reference/qweb:
-
-QWeb Template Engine
-====================
-
-The web client uses the :doc:`qweb` template engine to render widgets (unless they
-override the *renderElement* method to do something else).
-The Qweb JS template engine is based on XML, and is mostly compatible with the
-python implementation.
-
-Now, let us explain how the templates are loaded. Whenever the web client
-starts, a rpc is made to the */web/webclient/qweb* route. The server will then
-return a list of all templates defined in data files for each installed modules.
-The correct files are listed in the *qweb* entry in each module manifest.
-
-The web client will wait for that list of template to be loaded, before starting
-its first widget.
-
-This mechanism works quite well for our needs, but sometimes, we want to lazy
-load a template. For example, imagine that we have a widget which is rarely
-used. In that case, maybe we prefer to not load its template in the main file,
-in order to make the web client slightly lighter. In that case, we can use the
-*xmlDependencies* key of the Widget:
-
-.. code-block:: javascript
-
- var Widget = require('web.Widget');
-
- var Counter = Widget.extend({
- template: 'some.template',
- xmlDependencies: ['/myaddon/path/to/my/file.xml'],
-
- ...
-
- });
-
-With this, the *Counter* widget will load the xmlDependencies files in its
-*willStart* method, so the template will be ready when the rendering is performed.
-
-
-Event system
-============
-
-There are currently two event systems supported by Odoo: a simple system which
-allows adding listeners and triggering events, and a more complete system that
-also makes events 'bubble up'.
-
-Both of these event systems are implemented in the *EventDispatcherMixin*, in
-the file *mixins.js*. This mixin is included in the *Widget* class.
-
-Base Event system
------------------
-
-This event system was historically the first. It implements a simple bus
-pattern. We have 4 main methods:
-
-- *on*: this is used to register a listener on an event.
-- *off*: useful to remove events listener.
-- *once*: this is used to register a listener that will only be called once.
-- *trigger*: trigger an event. This will cause each listeners to be called.
-
-Here is an example on how this event system could be used:
-
-.. code-block:: javascript
-
- var Widget = require('web.Widget');
- var Counter = require('myModule.Counter');
-
- var MyWidget = Widget.extend({
- start: function () {
- this.counter = new Counter(this);
- this.counter.on('valuechange', this, this._onValueChange);
- var def = this.counter.appendTo(this.$el);
- return Promise.all([def, this._super.apply(this, arguments)]);
- },
- _onValueChange: function (val) {
- // do something with val
- },
- });
-
- // in Counter widget, we need to call the trigger method:
-
- ... this.trigger('valuechange', someValue);
-
-
-.. warning::
- the use of this event system is discouraged, we plan to replace each
- *trigger* method by the *trigger_up* method from the extended event system
-
-Extended Event System
----------------------
-
-The custom event widgets is a more advanced system, which mimic the DOM events
-API. Whenever an event is triggered, it will 'bubble up' the component tree,
-until it reaches the root widget, or is stopped.
-
-- *trigger_up*: this is the method that will create a small *OdooEvent* and
- dispatch it in the component tree. Note that it will start with the component
- that triggered the event
-- *custom_events*: this is the equivalent of the *event* dictionary, but for
- odoo events.
-
-The OdooEvent class is very simple. It has three public attributes: *target*
-(the widget that triggered the event), *name* (the event name) and *data* (the
-payload). It also has 2 methods: *stopPropagation* and *is_stopped*.
-
-The previous example can be updated to use the custom event system:
-
-.. code-block:: javascript
-
- var Widget = require('web.Widget');
- var Counter = require('myModule.Counter');
-
- var MyWidget = Widget.extend({
- custom_events: {
- valuechange: '_onValueChange'
- },
- start: function () {
- this.counter = new Counter(this);
- var def = this.counter.appendTo(this.$el);
- return Promise.all([def, this._super.apply(this, arguments)]);
- },
- _onValueChange: function(event) {
- // do something with event.data.val
- },
- });
-
- // in Counter widget, we need to call the trigger_up method:
-
- ... this.trigger_up('valuechange', {value: someValue});
-
-
-Registries
-===========
-
-A common need in the Odoo ecosystem is to extend/change the behaviour of the
-base system from the outside (by installing an application, i.e. a different
-module). For example, one may need to add a new widget type in some views. In
-that case, and many others, the usual process is to create the desired component,
-then add it to a registry (registering step), to make the rest of the web client
-aware of its existence.
-
-There are a few registries available in the system:
-
-field registry (exported by :js:data:`web.field_registry`)
- The field registry contains all field widgets known to the web client.
- Whenever a view (typically form or list/kanban) needs a field widget, this
- is where it will look. A typical use case look like this:
-
- .. code-block:: javascript
-
- var fieldRegistry = require('web.field_registry');
-
- var FieldPad = ...;
-
- fieldRegistry.add('pad', FieldPad);
-
- Note that each value should be a subclass of *AbstractField*
-
-view registry
- This registry contains all JS views known to the web client
- (and in particular, the view manager). Each value of this registry should
- be a subclass of *AbstractView*.
-
-action registry
- We keep track of all client actions in this registry. This
- is where the action manager looks up whenever it needs to create a client
- action. In version 11, each value should simply be a subclass of *Widget*.
- However, in version 12, the values are required to be *AbstractAction*.
-
-
-Communication between widgets
-=============================
-
-There are many ways to communicate between components.
-
-From a parent to its child
- This is a simple case. The parent widget can simply call a method on its
- child:
-
- .. code-block:: javascript
-
- this.someWidget.update(someInfo);
-
-From a widget to its parent/some ancestor
- In this case, the widget's job is simply to notify its environment that
- something happened. Since we do not want the widget to have a reference to
- its parent (this would couple the widget with its parent's implementation),
- the best way to proceed is usually to trigger an event, which will bubble up
- the component tree, by using the ``trigger_up`` method:
-
- .. code-block:: javascript
-
- this.trigger_up('open_record', { record: record, id: id});
-
- This event will be triggered on the widget, then will bubble up and be
- eventually caught by some upstream widget:
-
- .. code-block:: javascript
-
- var SomeAncestor = Widget.extend({
- custom_events: {
- 'open_record': '_onOpenRecord',
- },
- _onOpenRecord: function (event) {
- var record = event.data.record;
- var id = event.data.id;
- // do something with the event.
- },
- });
-
-Cross component
- Cross component communication can be achieved by using a bus. This is not
- the preferred form of communication, because it has the disadvantage of
- making the code harder to maintain. However, it has the advantage of
- decoupling the components. In that case, this is simply done by triggering
- and listening to events on a bus. For example:
-
- .. code-block:: javascript
-
- // in WidgetA
- var core = require('web.core');
-
- var WidgetA = Widget.extend({
- ...
- start: function () {
- core.bus.on('barcode_scanned', this, this._onBarcodeScanned);
- },
- });
-
- // in WidgetB
- var WidgetB = Widget.extend({
- ...
- someFunction: function (barcode) {
- core.bus.trigger('barcode_scanned', barcode);
- },
- });
-
-
- In this example, we use the bus exported by *web.core*, but this is not
- required. A bus could be created for a specific purpose.
-
-Services
-========
-
-In version 11.0, we introduced the notion of *service*. The main idea is to
-give to sub components a controlled way to access their environment, in a way
-that allow the framework enough control, and which is testable.
-
-The service system is organized around three ideas: services, service providers
-and widgets. The way it works is that widgets trigger (with *trigger_up*)
-events, these events bubble up to a service provider, which will ask a service
-to perform a task, then maybe return an answer.
-
-Service
---------
-
-A service is an instance of the *AbstractService* class. It basically only has
-a name and a few methods. Its job is to perform some work, typically something
-depending on the environment.
-
-For example, we have the *ajax* service (job is to perform a rpc), the
-*localStorage* (interact with the browser local storage) and many others.
-
-Here is a simplified example on how the ajax service is implemented:
-
-.. code-block:: javascript
-
- var AbstractService = require('web.AbstractService');
-
- var AjaxService = AbstractService.extend({
- name: 'ajax',
- rpc: function (...) {
- return ...;
- },
- });
-
-This service is named 'ajax' and define one method, *rpc*.
-
-Service Provider
-----------------
-
-For services to work, it is necessary that we have a service provider ready to
-dispatch the custom events. In the *backend* (web client), this is done by the
-main web client instance. Note that the code for the service provider comes from
-the *ServiceProviderMixin*.
-
-
-Widget
-------
-
-The widget is the part that requests a service. In order to do that, it simply
-triggers an event *call_service* (typically by using the helper function *call*).
-This event will bubble up and communicate the intent to the rest of the system.
-
-In practice, some functions are so frequently called that we have some helpers
-functions to make them easier to use. For example, the *_rpc* method is a helper
-that helps making a rpc.
-
-.. code-block:: javascript
-
- var SomeWidget = Widget.extend({
- _getActivityModelViewID: function (model) {
- return this._rpc({
- model: model,
- method: 'get_activity_view_id'
- });
- },
- });
-
-.. warning::
- If a widget is destroyed, it will be detached from the main component tree
- and will not have a parent. In that case, the events will not bubble up, which
- means that the work will not be done. This is usually exactly what we want from
- a destroyed widget.
-
-RPCs
-----
-
-The rpc functionality is supplied by the ajax service. But most people will
-probably only interact with the *_rpc* helpers.
-
-There are typically two usecases when working on Odoo: one may need to call a
-method on a (python) model (this goes through a controller *call_kw*), or one
-may need to directly call a controller (available on some route).
-
-* Calling a method on a python model:
-
-.. code-block:: javascript
-
- return this._rpc({
- model: 'some.model',
- method: 'some_method',
- args: [some, args],
- });
-
-* Directly calling a controller:
-
-.. code-block:: javascript
-
- return this._rpc({
- route: '/some/route/',
- params: { some: kwargs},
- });
-
-Notifications
-==============
-
-The Odoo framework has a standard way to communicate various information to the
-user: notifications, which are displayed on the top right of the user interface.
-
-There are two types of notifications:
-
-- *notification*: useful to display some feedback. For example, whenever a user
- unsubscribed to a channel.
-
-- *warning*: useful to display some important/urgent information. Typically
- most kind of (recoverable) errors in the system.
-
-Also, notifications can be used to ask a question to the user without disturbing
-its workflow. Imagine a phone call received through VOIP: a sticky notification
-could be displayed with two buttons *Accept* and *Decline*.
-
-Notification system
--------------------
-
-The notification system in Odoo is designed with the following components:
-
-- a *Notification* widget: this is a simple widget that is meant to be created
- and displayed with the desired information
-
-- a *NotificationService*: a service whose responsibility is to create and
- destroy notifications whenever a request is done (with a custom_event). Note
- that the web client is a service provider.
-
-- a client action *display_notification*: this allows to trigger the display
- of a notification from python (e.g. in the method called when the user
- clicked on a button of type object).
-
-- two helper functions in *ServiceMixin*: *do_notify* and *do_warn*
-
-
-Displaying a notification
--------------------------
-The most common way to display a notification is by using two methods that come
-from the *ServiceMixin*:
-
-- *do_notify(title, message, sticky, className)*:
- Display a notification of type *notification*.
-
- - *title*: string. This will be displayed on the top as a title
-
- - *message*: string, the content of the notification
-
- - *sticky*: boolean, optional. If true, the notification will stay until the
- user dismisses it. Otherwise, the notification will be automatically
- closed after a short delay.
-
- - *className*: string, optional. This is a css class name that will be
- automatically added to the notification. This could be useful for styling
- purpose, even though its use is discouraged.
-
-- *do_warn(title, message, sticky, className)*:
- Display a notification of type *warning*.
-
- - *title*: string. This will be displayed on the top as a title
-
- - *message*: string, the content of the notification
-
- - *sticky*: boolean, optional. If true, the notification will stay until the
- user dismisses it. Otherwise, the notification will be automatically
- closed after a short delay.
-
- - *className*: string, optional. This is a css class name that will be
- automatically added to the notification. This could be useful for styling
- purpose, even though its use is discouraged.
-
-Here are two examples on how to use these methods:
-
-.. code-block:: javascript
-
- // note that we call _t on the text to make sure it is properly translated.
- this.do_notify(_t("Success"), _t("Your signature request has been sent."));
-
- this.do_warn(_t("Error"), _t("Filter name is required."));
-
-Here an example in python:
-
-.. code-block:: python
-
- # note that we call _(string) on the text to make sure it is properly translated.
- def show_notification(self):
- return {
- 'type': 'ir.actions.client',
- 'tag': 'display_notification',
- 'params': {
- 'title': _('Success'),
- 'message': _('Your signature request has been sent.'),
- 'sticky': False,
- }
- }
-
-Systray
-=======
-
-The Systray is the right part of the menu bar in the interface, where the web
-client displays a few widgets, such as a messaging menu.
-
-When the SystrayMenu is created by the menu, it will look for all registered
-widgets and add them as a sub widget at the proper place.
-
-There is currently no specific API for systray widgets. They are supposed to
-be simple widgets, and can communicate with their environment just like other
-widgets with the *trigger_up* method.
-
-Adding a new Systray Item
--------------------------
-
-There is no systray registry. The proper way to add a widget is to add it to
-the class variable SystrayMenu.items.
-
-.. code-block:: javascript
-
- var SystrayMenu = require('web.SystrayMenu');
-
- var MySystrayWidget = Widget.extend({
- ...
- });
-
- SystrayMenu.Items.push(MySystrayWidget);
-
-
-Ordering
---------
-
-Before adding the widget to himself, the Systray Menu will sort the items by
-a sequence property. If that property is not present on the prototype, it will
-use 50 instead. So, to position a systray item to be on the right, one can
-set a very high sequence number (and conversely, a low number to put it on the
-left).
-
-.. code-block:: javascript
-
- MySystrayWidget.prototype.sequence = 100;
-
-
-Translation management
-======================
-
-Some translations are made on the server side (basically all text strings rendered or
-processed by the server), but there are strings in the static files that need
-to be translated. The way it currently works is the following:
-
-- each translatable string is tagged with the special function *_t* (available in
- the JS module *web.core*
-- these strings are used by the server to generate the proper PO files
-- whenever the web client is loaded, it will call the route */web/webclient/translations*,
- which returns a list of all translatable terms
-- in runtime, whenever the function *_t* is called, it will look up in this list
- in order to find a translation, and return it or the original string if none
- is found.
-
-Note that translations are explained in more details, from the server point of
-view, in the document :doc:`translations`.
-
-There are two important functions for the translations in javascript: *_t* and
-*_lt*. The difference is that *_lt* is lazily evaluated.
-
-.. code-block:: javascript
-
- var core = require('web.core');
-
- var _t = core._t;
- var _lt = core._lt;
-
- var SomeWidget = Widget.extend({
- exampleString: _lt('this should be translated'),
- ...
- someMethod: function () {
- var str = _t('some text');
- ...
- },
- });
-
-In this example, the *_lt* is necessary because the translations are not ready
-when the module is loaded.
-
-Note that translation functions need some care. The string given in argument
-should not be dynamic.
-
-Session
-=======
-
-There is a specific module provided by the web client which contains some
-information specific to the user current *session*. Some notable keys are
-
-- uid: the current user ID (its ID as a *res.users*)
-- user_name: the user name, as a string
-- the user context (user ID, language and timezone)
-- partner_id: the ID of the partner associated to the current user
-- db: the name of the database currently being in use
-
-Adding information to the session
----------------------------------
-
-When the /web route is loaded, the server will inject some session information
-in the template a script tag. The information will be read from the method
-*session_info* of the model *ir.http*. So, if one wants to add a specific
-information, it can be done by overriding the session_info method and adding it
-to the dictionary.
-
-.. code-block:: python
-
- from odoo import models
- from odoo.http import request
-
-
- class IrHttp(models.AbstractModel):
- _inherit = 'ir.http'
-
- def session_info(self):
- result = super(IrHttp, self).session_info()
- result['some_key'] = get_some_value_from_db()
- return result
-
-Now, the value can be obtained in javascript by reading it in the session:
-
-.. code-block:: javascript
-
- var session = require('web.session');
- var myValue = session.some_key;
- ...
-
-Note that this mechanism is designed to reduce the amount of communication
-needed by the web client to be ready. It is more appropriate for data which is
-cheap to compute (a slow session_info call will delay the loading for the web
-client for everyone), and for data which is required early in the initialization
-process.
-
-Views
-======
-
-The word 'view' has more than one meaning. This section is about the design of
-the javascript code of the views, not the structure of the *arch* or anything
-else.
-
-In 2017, Odoo replaced the previous view code with a new architecture. The
-main need was to separate the rendering logic from the model logic.
-
-
-Views (in a generic sense) are now described with 4 pieces: a View, a
-Controller, a Renderer and a Model. The API of these 4 pieces is described in
-the AbstractView, AbstractController, AbstractRenderer and AbstractModel classes.
-
-.. raw:: html
-
- <svg width="550" height="173">
- <!-- Created with Method Draw - https://github.com/duopixel/Method-Draw/ -->
- <path id="svg_1" d="m147.42498,79.79206c0.09944,-8.18859 -0.06363,-16.38812 0.81774,-24.5623c21.65679,2.68895 43.05815,7.08874 64.35,11.04543c1.14304,-4.01519 0.60504,-7.34585 1.59817,-11.05817c13.67878,7.81176 27.23421,15.73476 40.23409,24.03505c-12.47212,9.41539 -26.77809,17.592 -40.82272,25.96494c-0.4548,-3.89916 -0.90967,-7.79828 -1.36448,-11.69744c-20.69972,3.77225 -42.59036,7.6724 -63.42391,11.12096c-1.41678,-7.95741 -1.37514,-16.62327 -1.38888,-24.84846z" stroke-width="1.5" stroke="#000" fill="#fff"/>
- <rect id="svg_3" height="41" width="110" y="57.5" x="7" fill-opacity="null" stroke-opacity="null" stroke-width="1.5" stroke="#000" fill="#fff"/>
- <rect stroke="#000" id="svg_5" height="41" width="135" y="20.5" x="328" fill-opacity="null" stroke-opacity="null" stroke-width="1.5" fill="#fff"/>
- <rect stroke="#000" id="svg_6" height="41" width="128" y="102.5" x="262" fill-opacity="null" stroke-opacity="null" stroke-width="1.5" fill="#fff"/>
- <rect stroke="#000" id="svg_7" height="41" width="119" y="100.5" x="417" fill-opacity="null" stroke-opacity="null" stroke-width="1.5" fill="#fff"/>
- <line stroke-linecap="null" stroke-linejoin="null" id="svg_8" y2="96.5" x2="317" y1="65.5" x1="364" fill-opacity="null" stroke-opacity="null" stroke-width="1.5" stroke="#000" fill="none"/>
- <line stroke-linecap="null" stroke-linejoin="null" id="svg_9" y2="96.5" x2="467" y1="63.5" x1="425" fill-opacity="null" stroke-opacity="null" stroke-width="1.5" stroke="#000" fill="none"/>
- <text xml:space="preserve" text-anchor="start" font-family="Helvetica, Arial, sans-serif" font-size="24" id="svg_10" y="83.5" x="38" fill-opacity="null" stroke-opacity="null" stroke-width="0" stroke="#000" fill="#000000">View</text>
- <text xml:space="preserve" text-anchor="start" font-family="Helvetica, Arial, sans-serif" font-size="24" id="svg_11" y="44.5" x="346" fill-opacity="null" stroke-opacity="null" stroke-width="0" stroke="#000" fill="#000000">Controller</text>
- <text xml:space="preserve" text-anchor="start" font-family="Helvetica, Arial, sans-serif" font-size="24" id="svg_12" y="128.5" x="276" fill-opacity="null" stroke-opacity="null" stroke-width="0" stroke="#000" fill="#000000">Renderer</text>
- <text xml:space="preserve" text-anchor="start" font-family="Helvetica, Arial, sans-serif" font-size="24" id="svg_13" y="127.5" x="442" fill-opacity="null" stroke-opacity="null" stroke-width="0" stroke="#000" fill="#000000">Model</text>
- </svg>
-
-- the View is the factory. Its job is to get a set of fields, arch, context and
- some other parameters, then to construct a Controller/Renderer/Model triplet.
-
- The view's role is to properly setup each piece of the MVC pattern, with the correct
- information. Usually, it has to process the arch string and extract the
- data necessary for each other parts of the view.
-
- Note that the view is a class, not a widget. Once its job has been done, it
- can be discarded.
-
-- the Renderer has one job: representing the data being viewed in a DOM element.
- Each view can render the data in a different way. Also, it should listen on
- appropriate user actions and notify its parent (the Controller) if necessary.
-
- The Renderer is the V in the MVC pattern.
-
-- the Model: its job is to fetch and hold the state of the view. Usually, it
- represents in some way a set of records in the database. The Model is the
- owner of the 'business data'. It is the M in the MVC pattern.
-
-- the Controller: its job is to coordinate the renderer and the model. Also, it
- is the main entry point for the rest of the web client. For example, when
- the user changes something in the search view, the *update* method of the
- controller will be called with the appropriate information.
-
- It is the C in the MVC pattern.
-
-.. note::
- The JS code for the views has been designed to be usable outside of the
- context of a view manager/action manager. They could be used in a client action,
- or, they could be displayed in the public website (with some work on the assets).
-
-.. _reference/js/widgets:
-
-Field Widgets
-=============
-
-A good part of the web client experience is about editing and creating data. Most
-of that work is done with the help of field widgets, which are aware of the field
-type and of the specific details on how a value should be displayed and edited.
-
-AbstractField
--------------
-
-The *AbstractField* class is the base class for all widgets in a view, for all
-views that support them (currently: Form, List, Kanban).
-
-There are many differences between the v11 field widgets and the previous versions.
-Let us mention the most important ones:
-
-- the widgets are shared between all views (well, Form/List/Kanban). No need to
- duplicate the implementation anymore. Note that it is possible to have a
- specialized version of a widget for a view, by prefixing it with the view name
- in the view registry: *list.many2one* will be chosen in priority over *many2one*.
-- the widgets are no longer the owner of the field value. They only represent
- the data and communicate with the rest of the view.
-- the widgets do no longer need to be able to switch between edit and readonly
- mode. Now, when such a change is necessary, the widget will be destroyed and
- rerendered again. It is not a problem, since they do not own their value
- anyway
-- the field widgets can be used outside of a view. Their API is slightly
- awkward, but they are designed to be standalone.
-
-Decorations
------------
-
-Like the list view, field widgets have a simple support for decorations. The
-goal of decorations is to have a simple way to specify a text color depending on
-the record current state. For example,
-
-.. code-block:: xml
-
- <field name="state" decoration-danger="amount &lt; 10000"/>
-
-The valid decoration names are:
-
-- decoration-bf
-- decoration-it
-- decoration-danger
-- decoration-info
-- decoration-muted
-- decoration-primary
-- decoration-success
-- decoration-warning
-
-Each decoration *decoration-X* will be mapped to a css class *text-X*, which is
-a standard bootstrap css class (except for *text-it* and *text-bf*, which are
-handled by odoo and correspond to italic and bold, respectively). Note that the
-value of the decoration attribute should be a valid python expression, which
-will be evaluated with the record as evaluation context.
-
-Non relational fields
----------------------
-
-We document here all non relational fields available by default, in no particular
-order.
-
-integer (FieldInteger)
- This is the default field type for fields of type *integer*.
-
- - Supported field types: *integer*
-
- Options:
-
- - type: setting the input type (*text* by default, can be set on *number*)
-
- On edit mode, the field is rendered as an input with the HTML attribute type
- setted on *number* (so user can benefit the native support, especially on
- mobile). In this case, the default formatting is disabled to avoid incompability.
-
- .. code-block:: xml
-
- <field name="int_value" options='{"type": "number"}'/>
-
- - step: set the step to the value up and down when the user click on buttons
- (only for input of type number, 1 by default)
-
- .. code-block:: xml
-
- <field name="int_value" options='{"type": "number", "step": 100}'/>
-
- - format: should the number be formatted. (true by default)
-
- By default, numbers are formatted according to locale parameters.
- This option will prevent the field's value from being formatted.
-
- .. code-block:: xml
-
- <field name="int_value" options='{"format": false}'/>
-
-float (FieldFloat)
- This is the default field type for fields of type *float*.
-
- - Supported field types: *float*
-
- Attributes:
-
- - digits: displayed precision
-
- .. code-block:: xml
-
- <field name="factor" digits="[42,5]"/>
-
- Options:
-
- - type: setting the input type (*text* by default, can be set on *number*)
-
- On edit mode, the field is rendered as an input with the HTML attribute type
- setted on *number* (so user can benefit the native support, especially on
- mobile). In this case, the default formatting is disabled to avoid incompability.
-
- .. code-block:: xml
-
- <field name="int_value" options='{"type": "number"}'/>
-
- - step: set the step to the value up and down when the user click on buttons
- (only for input of type number, 1 by default)
-
- .. code-block:: xml
-
- <field name="int_value" options='{"type": "number", "step": 0.1}'/>
-
- - format: should the number be formatted. (true by default)
-
- By default, numbers are formatted according to locale parameters.
- This option will prevent the field's value from being formatted.
-
- .. code-block:: xml
-
- <field name="int_value" options='{"format": false}'/>
-
-float_time (FieldFloatTime)
- The goal of this widget is to display properly a float value that represents
- a time interval (in hours). So, for example, 0.5 should be formatted as 0:30,
- or 4.75 correspond to 4:45.
-
- - Supported field types: *float*
-
-float_factor (FieldFloatFactor)
- This widget aims to display properly a float value that converted using a factor
- given in its options. So, for example, the value saved in database is 0.5 and the
- factor is 3, the widget value should be formatted as 1.5.
-
- - Supported field types: *float*
-
-float_toggle (FieldFloatToggle)
- The goal of this widget is to replace the input field by a button containing a
- range of possible values (given in the options). Each click allows the user to loop
- in the range. The purpose here is to restrict the field value to a predefined selection.
- Also, the widget support the factor conversion as the *float_factor* widget (Range values
- should be the result of the conversion).
-
- - Supported field types: *float*
-
- .. code-block:: xml
-
- <field name="days_to_close" widget="float_toggle" options='{"factor": 2, "range": [0, 4, 8]}'/>
-
-boolean (FieldBoolean)
- This is the default field type for fields of type *boolean*.
-
- - Supported field types: *boolean*
-
-char (FieldChar)
- This is the default field type for fields of type *char*.
-
- - Supported field types: *char*
-
-date (FieldDate)
- This is the default field type for fields of type *date*. Note that it also
- works with datetime fields. It uses the session timezone when formatting
- dates.
-
- - Supported field types: *date*, *datetime*
-
- Options:
-
- - datepicker: extra settings for the datepicker_ widget.
-
- .. code-block:: xml
-
- <field name="datefield" options='{"datepicker": {"daysOfWeekDisabled": [0, 6]}}'/>
-
-datetime (FieldDateTime)
- This is the default field type for fields of type *datetime*.
-
- - Supported field types: *date*, *datetime*
-
- Options:
-
- - datepicker: extra settings for the datepicker_ widget.
-
- .. code-block:: xml
-
- <field name="datetimefield" options='{"datepicker": {"daysOfWeekDisabled": [0, 6]}}'/>
-
-daterange (FieldDateRange)
- This widget allows the user to select start and end date into a single picker.
-
- - Supported field types: *date*, *datetime*
-
- Options:
-
- - related_start_date: apply on end date field to get start date value which
- is used to display range in the picker.
- - related_end_date: apply on start date field to get end date value which
- is used to display range in the picker.
- - picker_options: extra settings for picker.
-
- .. code-block:: xml
-
- <field name="start_date" widget="daterange" options='{"related_end_date": "end_date"}'/>
-
-remaining_days (RemainingDays)
- This widget can be used on date and datetime fields. In readonly, it displays
- the delta (in days) between the value of the field and today. The widget is
- intended to be used for informative purpose: therefore the value cannot be
- modified in edit mode.
-
- - Supported field types: *date*, *datetime*
-
-monetary (FieldMonetary)
- This is the default field type for fields of type 'monetary'. It is used to
- display a currency. If there is a currency fields given in option, it will
- use that, otherwise it will fall back to the default currency (in the session)
-
- - Supported field types: *monetary*, *float*
-
- Options:
-
- - currency_field: another field name which should be a many2one on currency.
-
- .. code-block:: xml
-
- <field name="value" widget="monetary" options="{'currency_field': 'currency_id'}"/>
-
-text (FieldText)
- This is the default field type for fields of type *text*.
-
- - Supported field types: *text*
-
-
-handle (HandleWidget)
- This field's job is to be displayed as a *handle*, and allows reordering the
- various records by drag and dropping them.
-
- .. warning:: It has to be specified on the field by which records are sorted.
- .. warning:: Having more than one field with a handle widget on the same list is not supported.
-
- - Supported field types: *integer*
-
-
-email (FieldEmail)
- This field displays email address. The main reason to use it is that it
- is rendered as an anchor tag with the proper href, in readonly mode.
-
- - Supported field types: *char*
-
-phone (FieldPhone)
- This field displays a phone number. The main reason to use it is that it
- is rendered as an anchor tag with the proper href, in readonly mode, but
- only in some cases: we only want to make it clickable if the device can
- call this particular number.
-
- - Supported field types: *char*
-
-url (UrlWidget)
- This field displays an url (in readonly mode). The main reason to use it is
- that it is rendered as an anchor tag with the proper css classes and href.
-
- Also, the text of the anchor tag can be customized with the *text* attribute
- (it won't change the href value).
-
- .. code-block:: xml
-
- <field name="foo" widget="url" text="Some URL"/>
-
- Options:
-
- - website_path: (default:false) by default, the widget forces (if not already
- the case) the href value to begin with http:// except if this option is set
- to true, thus allowing redirections to the database's own website.
-
- - Supported field types: *char*
-
-domain (FieldDomain)
- The "Domain" field allows the user to construct a technical-prefix domain
- thanks to a tree-like interface and see the selected records in real time.
- In debug mode, an input is also there to be able to enter the prefix char
- domain directly (or to build advanced domains the tree-like interface does
- not allow to).
-
- Note that this is limited to 'static' domain (no dynamic expression, or access
- to context variable).
-
- - Supported field types: *char*
-
-link_button (LinkButton)
- The LinkButton widget actually simply displays a span with an icon and the
- text value as content. The link is clickable and will open a new browser
- window with its value as url.
-
- - Supported field types: *char*
-
-image (FieldBinaryImage)
- This widget is used to represent a binary value as an image. In some cases,
- the server returns a 'bin_size' instead of the real image (a bin_size is a
- string representing a file size, such as 6.5kb). In that case, the widget
- will make an image with a source attribute corresponding to an image on the
- server.
-
- - Supported field types: *binary*
-
- Options:
-
- - preview_image: if the image is only loaded as a 'bin_size', then this
- option is useful to inform the web client that the default field name is
- not the name of the current field, but the name of another field.
-
- - accepted_file_extensions: the file extension the user can pick from the file input dialog box (default value is `image/\*`)
- (cf: ``accept`` attribute on <input type="file"/>)
-
- .. code-block:: xml
-
- <field name="image" widget='image' options='{"preview_image":"image_128"}'/>
-
-binary (FieldBinaryFile)
- Generic widget to allow saving/downloading a binary file.
-
- - Supported field types: *binary*
-
- Options:
-
- - accepted_file_extensions: the file extension the user can pick from the file input dialog box
- (cf: ``accept`` attribute on <input type="file"/>)
-
- Attribute:
-
- - filename: saving a binary file will lose its file name, since it only
- saves the binary value. The filename can be saved in another field. To do
- that, an attribute filename should be set to a field present in the view.
-
- .. code-block:: xml
-
- <field name="datas" filename="datas_fname"/>
-
-priority (PriorityWidget)
- This widget is rendered as a set of stars, allowing the user to click on it
- to select a value or not. This is useful for example to mark a task as high
- priority.
-
- Note that this widget also works in 'readonly' mode, which is unusual.
-
- - Supported field types: *selection*
-
-attachment_image (AttachmentImage)
- Image widget for many2one fields. If the field is set, this widget will be
- rendered as an image with the proper src url. This widget does not have a
- different behaviour in edit or readonly mode, it is only useful to view an
- image.
-
- - Supported field types: *many2one*
-
- .. code-block:: xml
-
- <field name="displayed_image_id" widget="attachment_image"/>
-
-image_selection (ImageSelection)
- Allow the user to select a value by clicking on an image.
-
- - Supported field types: *selection*
-
- Options: a dictionary with a mapping from a selection value to an object with
- the url for an image (*image_link*) and a preview image (*preview_link*).
-
- Note that this option is not optional!
-
- .. code-block:: xml
-
- <field name="external_report_layout" widget="image_selection" options="{
- 'background': {
- 'image_link': '/base/static/img/preview_background.png',
- 'preview_link': '/base/static/pdf/preview_background.pdf'
- },
- 'standard': {
- 'image_link': '/base/static/img/preview_standard.png',
- 'preview_link': '/base/static/pdf/preview_standard.pdf'
- }
- }"/>
-
-label_selection (LabelSelection)
- This widget renders a simple non-editable label. This is only useful to
- display some information, not to edit it.
-
- - Supported field types: *selection*
-
- Options:
-
- - classes: a mapping from a selection value to a css class
-
- .. code-block:: xml
-
- <field name="state" widget="label_selection" options="{
- 'classes': {'draft': 'default', 'cancel': 'default', 'none': 'danger'}
- }"/>
-
-state_selection (StateSelectionWidget)
- This is a specialized selection widget. It assumes that the record has some
- hardcoded fields, present in the view: *stage_id*, *legend_normal*,
- *legend_blocked*, *legend_done*. This is mostly used to display and change
- the state of a task in a project, with additional information displayed in
- the dropdown.
-
- - Supported field types: *selection*
-
- .. code-block:: xml
-
- <field name="kanban_state" widget="state_selection"/>
-
-kanban_state_selection (StateSelectionWidget)
- This is exactly the same widget as state_selection
-
- - Supported field types: *selection*
-
-boolean_favorite (FavoriteWidget)
- This widget is displayed as an empty (or not) star, depending on a boolean
- value. Note that it also can be edited in readonly mode.
-
- - Supported field types: *boolean*
-
-boolean_button (FieldBooleanButton)
- The Boolean Button widget is meant to be used in a stat button in a form view.
- The goal is to display a nice button with the current state of a boolean
- field (for example, 'Active'), and allow the user to change that field when
- clicking on it.
-
- Note that it also can be edited in readonly mode.
-
- - Supported field types: *boolean*
-
- Options:
-
- - terminology: it can be either 'active', 'archive', 'close' or a customized
- mapping with the keys *string_true*, *string_false*, *hover_true*, *hover_false*
-
- .. code-block:: xml
-
- <field name="active" widget="boolean_button" options='{"terminology": "archive"}'/>
-
-boolean_toggle (BooleanToggle)
- Displays a toggle switch to represent a boolean. This is a subfield of
- FieldBoolean, mostly used to have a different look.
-
-statinfo (StatInfo)
- This widget is meant to represent statistical information in a *stat button*.
- It is basically just a label with a number.
-
- - Supported field types: *integer, float*
-
- Options:
-
- - label_field: if given, the widget will use the value of the label_field as
- text.
-
- .. code-block:: xml
-
- <button name="%(act_payslip_lines)d"
- icon="fa-money"
- type="action">
- <field name="payslip_count" widget="statinfo"
- string="Payslip"
- options="{'label_field': 'label_tasks'}"/>
- </button>
-
-percentpie (FieldPercentPie)
- This widget is meant to represent statistical information in a *stat button*.
- This is similar to a statinfo widget, but the information is represented in
- a *pie* chart (empty to full). Note that the value is interpreted as a
- percentage (a number between 0 and 100).
-
- - Supported field types: *integer, float*
-
- .. code-block:: xml
-
- <field name="replied_ratio" string="Replied" widget="percentpie"/>
-
-progressbar (FieldProgressBar)
- Represent a value as a progress bar (from 0 to some value)
-
- - Supported field types: *integer, float*
-
- Options:
-
- - editable: boolean if value is editable
- - current_value: get the current_value from the field that must be present in the view
- - max_value: get the max_value from the field that must be present in the view
- - edit_max_value: boolean if the max_value is editable
- - title: title of the bar, displayed on top of the bar --> not translated,
- use parameter (not option) "title" instead
-
- .. code-block:: xml
-
- <field name="absence_of_today" widget="progressbar"
- options="{'current_value': 'absence_of_today', 'max_value': 'total_employee', 'editable': false}"/>
-
-toggle_button (FieldToggleBoolean)
- This widget is intended to be used on boolean fields. It toggles a button
- switching between a green bullet / gray bullet. It also set up a tooltip,
- depending on the value and some options.
-
- - Supported field types: *boolean*
-
- Options:
-
- - active: the string for the tooltip that should be set when boolean is true
- - inactive: the tooltip that should be set when boolean is false
-
- .. code-block:: xml
-
- <field name="payslip_status" widget="toggle_button"
- options='{"active": "Reported in last payslips", "inactive": "To Report in Payslip"}'
- />
-
-dashboard_graph (JournalDashboardGraph)
- This is a more specialized widget, useful to display a graph representing a
- set of data. For example, it is used in the accounting dashboard kanban view.
-
- It assumes that the field is a JSON serialization of a set of data.
-
- - Supported field types: *char*
-
- Attribute
-
- - graph_type: string, can be either 'line' or 'bar'
-
- .. code-block:: xml
-
- <field name="dashboard_graph_data"
- widget="dashboard_graph"
- graph_type="line"/>
-
-ace (AceEditor)
- This widget is intended to be used on Text fields. It provides Ace Editor
- for editing XML and Python.
-
- - Supported field types: *char, text*
-
-- badge (FieldBadge)
- Displays the value inside a bootstrap badge pill.
-
- - Supported field types: *char*, *selection*, *many2one*
-
- By default, the badge has a lightgrey background, but it can be customized
- by using the decoration-X mechanism. For instance, to display a red badge
- under a given condition:
-
- .. code-block:: xml
-
- <field name="foo" widget"badge" decoration-danger="state == 'cancel'"/>
-
-Relational fields
------------------
-
-.. class:: web.relational_fields.FieldSelection
-
- Supported field types: *selection*
-
- .. attribute:: placeholder
-
- a string which is used to display some info when no value is selected
-
- .. code-block:: xml
-
- <field name="tax_id" widget="selection" placeholder="Select a tax"/>
-
-radio (FieldRadio)
- This is a subfield of FielSelection, but specialized to display all the
- valid choices as radio buttons.
-
- Note that if used on a many2one records, then more rpcs will be done to fetch
- the name_gets of the related records.
-
- - Supported field types: *selection, many2one*
-
- Options:
-
- - horizontal: if true, radio buttons will be displayed horizontally.
-
- .. code-block:: xml
-
- <field name="recommended_activity_type_id" widget="radio"
- options="{'horizontal':true}"/>
-
-selection_badge (FieldSelectionBadge)
- This is a subfield of FieldSelection, but specialized to display all the
- valid choices as rectangular badges.
-
- - Supported field types: *selection, many2one*
-
- .. code-block:: xml
-
- <field name="recommended_activity_type_id" widget="selection_badge"/>
-
-many2one (FieldMany2One)
- Default widget for many2one fields.
-
- - Supported field types: *many2one*
-
- Attributes:
-
- - can_create: allow the creation of related records (take precedence over no_create
- option)
- - can_write: allow the editing of related records (default: true)
-
- Options:
-
- - no_create: prevent the creation of related records
- - quick_create: allow the quick creation of related records (default: true)
- - no_quick_create: prevent the quick creation of related records (don't ask me)
- - no_create_edit: same as no_create, maybe...
- - create_name_field: when creating a related record, if this option is set, the value of the *create_name_field* will be filled with the value of the input (default: *name*)
- - always_reload: boolean, default to false. If true, the widget will always
- do an additional name_get to fetch its name value. This is used for the
- situations where the name_get method is overridden (please do not do that)
- - no_open: boolean, default to false. If set to true, the many2one will not
- redirect on the record when clicking on it (in readonly mode)
-
- .. code-block:: xml
-
- <field name="currency_id" options="{'no_create': True, 'no_open': True}"/>
-
-list.many2one (ListFieldMany2One)
- Default widget for many2one fields (in list view).
-
- Specialization of many2one field for list views. The main reason is that we
- need to render many2one fields (in readonly mode) as a text, which does not
- allow opening the related records.
-
- - Supported field types: *many2one*
-
-many2one_barcode (FieldMany2OneBarcode)
- Widget for many2one fields allows to open the camera from a mobile device (Android/iOS) to scan a barcode.
-
- Specialization of many2one field where the user is allowed to use the native camera to scan a barcode.
- Then it uses name_search to search this value.
-
- If this widget is set and user is not using the mobile application,
- it will fallback to regular many2one (FieldMany2One)
-
- - Supported field types: *many2one*
-
-many2one_avatar (Many2OneAvatar)
- This widget is only supported on many2one fields pointing to a model which
- inherits from 'image.mixin'. In readonly, it displays the image of the
- related record next to its display_name. Note that the display_name isn't a
- clickable link in this case. In edit, it behaves exactly like the regular
- many2one.
-
- - Supported field types: *many2one*
-
-many2one_avatar_user (Many2OneAvatarUser)
- This widget is a specialization of the Many2OneAvatar. When the avatar is
- clicked, we open a chat window with the corresponding user. This widget can
- only be set on many2one fields pointing to the 'res.users' model.
-
- - Supported field types: *many2one* (pointing to 'res.users')
-
-many2one_avatar_employee (Many2OneAvatarEmployee)
- Same as Many2OneAvatarUser, but for many2one fields pointing to 'hr.employee'.
-
- - Supported field types: *many2one* (pointing to 'hr.employee')
-
-kanban.many2one (KanbanFieldMany2One)
- Default widget for many2one fields (in kanban view). We need to disable all
- editing in kanban views.
-
- - Supported field types: *many2one*
-
-many2many (FieldMany2Many)
- Default widget for many2many fields.
-
- - Supported field types: *many2many*
-
- Attributes:
-
- - mode: string, default view to display
- - domain: restrict the data to a specific domain
-
- Options:
-
- - create_text: allow the customization of the text displayed when adding a
- new record
- - link: domain determining whether or not records can be added to the relation (default: True).
- - unlink: domain determining whether or not records can be removed from the relation (default: True).
-
-many2many_binary (FieldMany2ManyBinaryMultiFiles)
- This widget helps the user to upload or delete one or more files at the same
- time.
-
- Note that this widget is specific to the model 'ir.attachment'.
-
- - Supported field types: *many2many*
-
- Options:
-
- - accepted_file_extensions: the file extension the user can pick from the file input dialog box
- (cf: ``accept`` attribute on <input type="file"/>)
-
-many2many_tags (FieldMany2ManyTags)
- Display many2many as a list of tags.
-
- - Supported field types: *many2many*
-
- Options:
-
- - create: domain determining whether or not new tags can be created (default: True).
-
- .. code-block:: xml
-
- <field name="category_id" widget="many2many_tags" options="{'create': [['some_other_field', '>', 24]]}"/>
-
- - color_field: the name of a numeric field, which should be present in the
- view. A color will be chosen depending on its value.
-
- .. code-block:: xml
-
- <field name="category_id" widget="many2many_tags" options="{'color_field': 'color'}"/>
-
- - no_edit_color: set to True to remove the possibility to change the color of the tags (default: False).
-
- .. code-block:: xml
-
- <field name="category_id" widget="many2many_tags" options="{'color_field': 'color', 'no_edit_color': True}"/>
-
-form.many2many_tags (FormFieldMany2ManyTags)
- Specialization of many2many_tags widget for form views. It has some extra
- code to allow editing the color of a tag.
-
- - Supported field types: *many2many*
-
-kanban.many2many_tags (KanbanFieldMany2ManyTags)
- Specialization of many2many_tags widget for kanban views.
-
- - Supported field types: *many2many*
-
-many2many_checkboxes (FieldMany2ManyCheckBoxes)
- This field displays a list of checkboxes and allows the user to select a
- subset of the choices. Note that the number of displayed values is limited to
- 100. This limit isn't customizable. It simply allows to handle extreme cases
- where this widget is wrongly set on a field with a huge comodel. In those
- cases, a list view is more adequate as it allows pagination and filtering.
-
- - Supported field types: *many2many*
-
-one2many (FieldOne2Many)
- Default widget for one2many fields.
-
- It usually displays data in a sub list view, or a sub kanban view.
-
- - Supported field types: *one2many*
-
- Options:
-
- - create: domain determining whether or not related records can be created (default: True).
-
- - delete: domain determining whether or not related records can be deleted (default: True).
-
- .. code-block:: xml
-
- <field name="turtles" options="{'create': [['some_other_field', '>', 24]]}"/>
-
- - create_text: a string that is used to customize the 'Add' label/text.
-
- .. code-block:: xml
-
- <field name="turtles" options="{\'create_text\': \'Add turtle\'}">
-
-statusbar (FieldStatus)
- This is a really specialized widget for the form views. It is the bar on top
- of many forms which represent a flow, and allow selecting a specific state.
-
- - Supported field types: *selection, many2one*
-
-reference (FieldReference)
- The FieldReference is a combination of a select (for the model) and a
- FieldMany2One (for its value). It allows the selection of a record on an
- arbitrary model.
-
- - Supported field types: *char, reference*
-
-
-Client actions
-==============
-
-The idea of a client action is a customized widget that is integrated in the
-web client interface, just like a *act_window_action*. This is useful when
-you need a component that is not closely linked to an existing view or a
-specific model. For example, the Discuss application is actually a client
-action.
-
-A client action is a term that has various meanings, depending on the context:
-
-- from the perspective of the server, it is a record of the model *ir_action*,
- with a field *tag* of type char
-- from the perspective of the web client, it is a widget, which inherit from
- the class AbstractAction, and is supposed to be registered in the
- action registry under the corresponding key (from the field char)
-
-Whenever a menu item is associated to a client action, opening it will simply
-fetch the action definition from the server, then lookup into its action
-registry to get the Widget definition at the appropriate key, and finally, it
-will instantiate and append the widget to the proper place in the DOM.
-
-Adding a client action
-----------------------
-
-A client action is a widget which will control the part of the screen below the
-menu bar. It can have a control panel, if necessary. Defining a client action
-can be done in two steps: implementing a new widget, and registering the widget
-in the action registry.
-
-Implementing a new client action.
- This is done by creating a widget:
-
- .. code-block:: javascript
-
- var AbstractAction = require('web.AbstractAction');
-
- var ClientAction = AbstractAction.extend({
- hasControlPanel: true,
- ...
- });
-
-Registering the client action:
- As usual, we need to make the web client aware of the mapping between
- client actions and the actual class:
-
- .. code-block:: javascript
-
- var core = require('web.core');
-
- core.action_registry.add('my-custom-action', ClientAction);
-
-
- Then, to use the client action in the web client, we need to create a client
- action record (a record of the model ``ir.actions.client``) with the proper
- ``tag`` attribute:
-
- .. code-block:: xml
-
- <record id="my_client_action" model="ir.actions.client">
- <field name="name">Some Name</field>
- <field name="tag">my-custom-action</field>
- </record>
-
-
-Using the control panel
------------------------
-
-By default, the client action does not display a control panel. In order to
-do that, several steps should be done.
-
-- Set the *hasControlPanel* to *true*.
- In the widget code:
-
- .. code-block:: javascript
-
- var MyClientAction = AbstractAction.extend({
- hasControlPanel: true,
- loadControlPanel: true, // default: false
- ...
- });
-
- .. warning::
- when the ``loadControlPanel`` is set to true, the client action will automatically get the content of a search view or a control panel view.
- In this case, a model name should be specified like this:
-
- .. code-block:: javascript
-
- init: function (parent, action, options) {
- ...
- this.controlPanelParams.modelName = 'model.name';
- ...
- }
-
-- Call the method *updateControlPanel* whenever we need to update the control panel.
- For example:
-
- .. code-block:: javascript
-
- var SomeClientAction = Widget.extend({
- hasControlPanel: true,
- ...
- start: function () {
- this._renderButtons();
- this._update_control_panel();
- ...
- },
- do_show: function () {
- ...
- this._update_control_panel();
- },
- _renderButtons: function () {
- this.$buttons = $(QWeb.render('SomeTemplate.Buttons'));
- this.$buttons.on('click', ...);
- },
- _update_control_panel: function () {
- this.updateControlPanel({
- cp_content: {
- $buttons: this.$buttons,
- },
- });
- }
-
-The ``updateControlPanel`` is the main method to customize the content in controlpanel.
-For more information, look into the `control_panel_renderer.js <https://github.com/odoo/odoo/blob/13.0/addons/web/static/src/js/views/control_panel/control_panel_renderer.js#L130>`_ file.
-
-.. _.appendTo():
- https://api.jquery.com/appendTo/
-
-.. _.prependTo():
- https://api.jquery.com/prependTo/
-
-.. _.insertAfter():
- https://api.jquery.com/insertAfter/
-
-.. _.insertBefore():
- https://api.jquery.com/insertBefore/
-
-.. _event delegation:
- https://api.jquery.com/delegate/
-
-.. _datepicker: https://github.com/Eonasdan/bootstrap-datetimepicker
diff --git a/doc/reference/mixins.rst b/doc/reference/mixins.rst
deleted file mode 100644
index 953b604ffa3..00000000000
--- a/doc/reference/mixins.rst
+++ /dev/null
@@ -1,1076 +0,0 @@
-:banner: banners/mixins.jpg
-
-.. _reference/mixins:
-
-=========================
-Mixins and Useful Classes
-=========================
-
-Odoo implements some useful classes and mixins that make it easy for you to add
-often-used behaviours on your objects. This guide will details most of them, with
-examples and use cases.
-
-.. _reference/mixins/mail:
-
-Messaging features
-==================
-
-.. _reference/mixins/mail/chatter:
-
-Messaging integration
----------------------
-
-Basic messaging system
-''''''''''''''''''''''
-
-Integrating messaging features to your model is extremely easy. Simply inheriting
-the ``mail.thread`` model and adding the messaging fields (and their appropriate
-widgets) to your form view will get you up and running in no time.
-
-.. admonition:: Example
-
- Let's create a simplistic model representing a business trip. Since organizing
- this kind of trip usually involves a lot of people and a lot of discussion, let's
- add support for message exchange on the model.
-
- .. code-block:: python
-
- class BusinessTrip(models.Model):
- _name = 'business.trip'
- _inherit = ['mail.thread']
- _description = 'Business Trip'
-
- name = fields.Char()
- partner_id = fields.Many2one('res.partner', 'Responsible')
- guest_ids = fields.Many2many('res.partner', 'Participants')
-
- In the form view:
-
- .. code-block:: xml
-
- <record id="businness_trip_form" model="ir.ui.view">
- <field name="name">business.trip.form</field>
- <field name="model">business.trip</field>
- <field name="arch" type="xml">
- <form string="Business Trip">
- <!-- Your usual form view goes here
- ...
- Then comes chatter integration -->
- <div class="oe_chatter">
- <field name="message_follower_ids" widget="mail_followers"/>
- <field name="message_ids" widget="mail_thread"/>
- </div>
- </form>
- </field>
- </record>
-
-Once you've added chatter support on your model, users can easily add messages
-or internal notes on any record of your model; every one of those will send a
-notification (to all followers for messages, to employee (*base.group_user*)
-users for internal notes). If your mail gateway and catchall address are correctly
-configured, these notifications will be sent by e-mail and can be replied-to directly
-from your mail client; the automatic routing system will route the answer to the
-correct thread.
-
-Server-side, some helper functions are there to help you easily send messages and
-to manage followers on your record:
-
-.. rubric:: Posting messages
-
-.. method:: message_post(self, body='', subject=None, message_type='notification', subtype=None, parent_id=False, attachments=None, **kwargs)
-
- Post a new message in an existing thread, returning the new
- mail.message ID.
-
- :param str body: body of the message, usually raw HTML that will
- be sanitized
- :param str message_type: see mail_message.message_type field
- :param int parent_id: handle reply to a previous message by adding the
- parent partners to the message in case of private discussion
- :param list(tuple(str,str)) attachments: list of attachment tuples in the form
- ``(name,content)``, where content is NOT base64 encoded
- :param `\**kwargs`: extra keyword arguments will be used as default column values for the
- new mail.message record
- :return: ID of newly created mail.message
- :rtype: int
-
-.. method:: message_post_with_view(views_or_xmlid, **kwargs):
-
- Helper method to send a mail / post a message using a view_id to
- render using the ir.qweb engine. This method is stand alone, because
- there is nothing in template and composer that allows to handle
- views in batch. This method will probably disappear when templates
- handle ir ui views.
-
- :param str or ``ir.ui.view`` record: external id or record of the view that
- should be sent
-
-.. method:: message_post_with_template(template_id, **kwargs)
-
- Helper method to send a mail with a template
-
- :param template_id: the id of the template to render to create the body of the message
- :param `\**kwargs`: parameter to create a mail.compose.message wizzard (which inherit from mail.message)
-
-.. rubric:: Receiving messages
-
-These methods are called when a new e-mail is processed by the mail gateway. These
-e-mails can either be new thread (if they arrive via an :ref:`alias <reference/mixins/mail/alias>`)
-or simply replies from an existing thread. Overriding them allows you to set values
-on the thread's record depending on some values from the email itself (i.e. update
-a date or an e-mail address, add CC's addresses as followers, etc.).
-
-.. method:: message_new(msg_dict, custom_values=None)
-
- Called by ``message_process`` when a new message is received
- for a given thread model, if the message did not belong to
- an existing thread.
-
- The default behavior is to create a new record of the corresponding
- model (based on some very basic info extracted from the message).
- Additional behavior may be implemented by overriding this method.
-
- :param dict msg_dict: a map containing the email details and
- attachments. See ``message_process`` and ``mail.message.parse`` for details
- :param dict custom_values: optional dictionary of additional
- field values to pass to create() when creating the new thread record;
- be careful, these values may override any other values coming from
- the message
- :rtype: int
- :return: the id of the newly created thread object
-
-.. method:: message_update(msg_dict, update_vals=None)
-
- Called by ``message_process`` when a new message is received
- for an existing thread. The default behavior is to update the record
- with ``update_vals`` taken from the incoming email.
-
- Additional behavior may be implemented by overriding this
- method.
-
- :param dict msg_dict: a map containing the email details and attachments;
- see ``message_process`` and ``mail.message.parse()`` for details.
- :param dict update_vals: a dict containing values to update records given
- their ids; if the dict is None or is void, no write operation is performed.
- :return: True
-
-.. rubric:: Followers management
-
-.. method:: message_subscribe(partner_ids=None, channel_ids=None, subtype_ids=None, force=True)
-
- Add partners to the records followers.
-
- :param list(int) partner_ids: IDs of the partners that will be subscribed
- to the record
- :param list(int) channel_ids: IDs of the channels that will be subscribed
- to the record
- :param list(int) subtype_ids: IDs of the subtypes that the channels/partners
- will be subscribed to (defaults to the default subtypes if ``None``)
- :param force: if True, delete existing followers before creating new one
- using the subtypes given in the parameters
- :return: Success/Failure
- :rtype: bool
-
-
-.. method:: message_unsubscribe(partner_ids=None, channel_ids=None)
-
- Remove partners from the record's followers.
-
- :param list(int) partner_ids: IDs of the partners that will be subscribed
- to the record
- :param list(int) channel_ids: IDs of the channels that will be subscribed
- to the record
- :return: True
- :rtype: bool
-
-
-.. method:: message_unsubscribe_users(user_ids=None)
-
- Wrapper on message_subscribe, using users.
-
- :param list(int) user_ids: IDs of the users that will be unsubscribed
- to the record; if None, unsubscribe the current user instead.
- :return: True
- :rtype: bool
-
-
-Logging changes
-'''''''''''''''
-
-The ``mail`` module adds a powerful tracking system on fields, allowing you
-to log changes to specific fields in the record's chatter. To add tracking
-to a field, simple set the tracking attribute to True.
-
-.. admonition:: Example
-
- Let's track changes on the name and responsible of our business trips:
-
- .. code-block:: python
-
- class BusinessTrip(models.Model):
- _name = 'business.trip'
- _inherit = ['mail.thread']
- _description = 'Business Trip'
-
- name = fields.Char(tracking=True)
- partner_id = fields.Many2one('res.partner', 'Responsible',
- tracking=True)
- guest_ids = fields.Many2many('res.partner', 'Participants')
-
- From now on, every change to a trip's name or responsible will log a note
- on the record. The ``name`` field will be displayed in the notification as
- well to give more context about the notification (even if the name did not
- change).
-
-
-Subtypes
-''''''''
-
-Subtypes give you more granular control over messages. Subtypes act as a classification
-system for notifications, allowing subscribers to a document to customize the
-subtype of notifications they wish to receive.
-
-Subtypes are created as data in your module; the model has the following fields:
-
-``name`` (mandatory) - :class:`~odoo.fields.Char`
- name of the subtype, will be displayed in the notification customization
- popup
-``description`` - :class:`~odoo.fields.Char`
- description that will be added in the message posted for this
- subtype. If void, the name will be added instead
-``internal`` - :class:`~odoo.fields.Boolean`
- messages with internal subtypes will be visible only by employees,
- aka members of the ``base.group_user`` group
-``parent_id`` - :class:`~odoo.fields.Many2one`
- link subtypes for automatic subscription; for example project subtypes are
- linked to task subtypes through this link. When someone is subscribed to
- a project, he will be subscribed to all tasks of this project with
- subtypes found using the parent subtype
-``relation_field`` - :class:`~odoo.fields.Char`
- as an example, when linking project and tasks subtypes, the relation
- field is the project_id field of tasks
-``res_model`` - :class:`~odoo.fields.Char`
- model the subtype applies to; if False, this subtype applies to all models
-``default`` - :class:`~odoo.fields.Boolean`
- wether the subtype is activated by default when subscribing
-``sequence`` - :class:`~odoo.fields.Integer`
- used to order subtypes in the notification customization popup
-``hidden`` - :class:`~odoo.fields.Boolean`
- wether the subtype is hidden in the notification customization popup
-
-
-Interfacing subtypes with field tracking allows to subscribe to different kind
-of notifications depending on what might interest users. To do this, you
-can override the ``_track_subtype()`` function:
-
-.. method:: _track_subtype(init_values)
-
- Give the subtype triggered by the changes on the record according
- to values that have been updated.
-
- :param dict init_values: the original values of the record; only modified fields
- are present in the dict
- :returns: a subtype's full external id or False if no subtype is triggered
-
-
-.. admonition:: Example
-
- Let's add a ``state`` field on our example class and trigger a notification
- with a specific subtype when this field change values.
-
- First, let's define our subtype:
-
- .. code-block:: xml
-
- <record id="mt_state_change" model="mail.message.subtype">
- <field name="name">Trip confirmed</field>
- <field name="res_model">business.trip</field>
- <field name="default" eval="True"/>
- <field name="description">Business Trip confirmed!</field>
- </record>
-
-
- Then, we need to override the ``track_subtype()`` function. This function
- is called by the tracking system to know which subtype should be used depending
- on the change currently being applied. In our case, we want to use our shiny new
- subtype when the ``state`` field changes from *draft* to *confirmed*:
-
- .. code-block:: python
-
- class BusinessTrip(models.Model):
- _name = 'business.trip'
- _inherit = ['mail.thread']
- _description = 'Business Trip'
-
- name = fields.Char(tracking=True)
- partner_id = fields.Many2one('res.partner', 'Responsible',
- tracking=True)
- guest_ids = fields.Many2many('res.partner', 'Participants')
- state = fields.Selection([('draft', 'New'), ('confirmed', 'Confirmed')],
- tracking=True)
-
- def _track_subtype(self, init_values):
- # init_values contains the modified fields' values before the changes
- #
- # the applied values can be accessed on the record as they are already
- # in cache
- self.ensure_one()
- if 'state' in init_values and self.state == 'confirmed':
- return self.env.ref('my_module.mt_state_change')
- return super(BusinessTrip, self)._track_subtype(init_values)
-
-
-Customizing notifications
-'''''''''''''''''''''''''
-
-When sending notifications to followers, it can be quite useful to add buttons in
-the template to allow quick actions directly from the e-mail. Even a simple button
-to link directly to the record's form view can be useful; however in most cases
-you don't want to display these buttons to portal users.
-
-The notification system allows customizing notification templates in the following
-ways:
-
-- Display *Access Buttons*: these buttons are visible at the top of the notification
- e-mail and allow the recipient to directly access the form view of the record
-- Display *Follow Buttons*: these buttons allow the recipient to
- directly quickly subscribe from the record
-- Display *Unfollow Buttons*: these buttons allow the recipient to
- directly quickly unsubscribe from the record
-- Display *Custom Action Buttons*: these buttons are calls to specific routes
- and allow you to make some useful actions directly available from the e-mail (i.e.
- converting a lead to an opportunity, validating an expense sheet for an
- Expense Manager, etc.)
-
-These buttons settings can be applied to different groups that you can define
-yourself by overriding the function ``_notification_recipients``.
-
-.. method:: _notification_recipients(message, groups)
-
- Give the subtype triggered by the changes on the record according
- to values that have been updated.
-
- :param ``record`` message: ``mail.message`` record currently being sent
- :param list(tuple) groups: list of tuple of the form (group_name, group_func,group_data) where:
-
- group_name
- is an identifier used only to be able to override and manipulate
- groups. Default groups are ``user`` (recipients linked to an employee user),
- ``portal`` (recipients linked to a portal user) and ``customer`` (recipients not
- linked to any user). An example of override use would be to add a group
- linked to a res.groups like Hr Officers to set specific action buttons to
- them.
- group_func
- is a function pointer taking a partner record as parameter. This
- method will be applied on recipients to know whether they belong to a given
- group or not. Only first matching group is kept. Evaluation order is the
- list order.
- group_data
- is a dict containing parameters for the notification email with the following
- possible keys - values:
-
- - has_button_access
- whether to display Access <Document> in email. True by default for
- new groups, False for portal / customer.
- - button_access
- dict with url and title of the button
- - has_button_follow
- whether to display Follow in email (if recipient is not currently
- following the thread). True by default for new groups, False for
- portal / customer.
- - button_follow
- dict with url adn title of the button
- - has_button_unfollow
- whether to display Unfollow in email (if recipient is currently following the thread).
- True by default for new groups, False for portal / customer.
- - button_unfollow
- dict with url and title of the button
- - actions
- list of action buttons to display in the notification email.
- Each action is a dict containing url and title of the button.
-
- :returns: a subtype's full external id or False if no subtype is triggered
-
-
-The urls in the actions list can be generated automatically by calling the
-``_notification_link_helper()`` function:
-
-
-.. method:: _notification_link_helper(self, link_type, **kwargs)
-
- Generate a link for the given type on the current record (or on a specific
- record if the kwargs ``model`` and ``res_id`` are set).
-
- :param str link_type: link type to be generated; can be any of these values:
-
- ``view``
- link to form view of the record
- ``assign``
- assign the logged user to the ``user_id`` field of
- the record (if it exists)
- ``follow``
- self-explanatory
- ``unfollow``
- self-explanatory
- ``method``
- call a method on the record; the method's name should be
- provided as the kwarg ``method``
- ``new``
- open an empty form view for a new record; you can specify
- a specific action by providing its id (database id or fully resolved
- external id) in the kwarg ``action_id``
-
- :returns: link of the type selected for the record
- :rtype: str
-
-.. admonition:: Example
-
- Let's add a custom button to the Business Trip state change notification;
- this button will reset the state to Draft and will be only visible to a member
- of the (imaginary) group Travel Manager (``business.group_trip_manager``)
-
- .. code-block:: python
-
- class BusinessTrip(models.Model):
- _name = 'business.trip'
- _inherit = ['mail.thread', 'mail.alias.mixin']
- _description = 'Business Trip'
-
- # Pevious code goes here
-
- def action_cancel(self):
- self.write({'state': 'draft'})
-
- def _notification_recipients(self, message, groups):
- """ Handle Trip Manager recipients that can cancel the trip at the last
- minute and kill all the fun. """
- groups = super(BusinessTrip, self)._notification_recipients(message, groups)
-
- self.ensure_one()
- if self.state == 'confirmed':
- app_action = self._notification_link_helper('method',
- method='action_cancel')
- trip_actions = [{'url': app_action, 'title': _('Cancel')}]
-
- new_group = (
- 'group_trip_manager',
- lambda partner: bool(partner.user_ids) and
- any(user.has_group('business.group_trip_manager')
- for user in partner.user_ids),
- {
- 'actions': trip_actions,
- })
-
- return [new_group] + groups
-
-
- Note that that I could have defined my evaluation function outside of this
- method and define a global function to do it instead of a lambda, but for
- the sake of being more brief and less verbose in these documentation files
- that can sometimes be boring, I choose the former instead of the latter.
-
-Overriding defaults
-'''''''''''''''''''
-
-There are several ways you can customize the behaviour of ``mail.thread`` models,
-including (but not limited to):
-
-``_mail_post_access`` - :class:`~odoo.models.Model` attribute
- the required access rights to be able to post a message on the model; by
- default a ``write`` access is needed, can be set to ``read`` as well
-
-Context keys:
- These context keys can be used to somewhat control ``mail.thread`` features
- like auto-subscription or field tracking during calls to ``create()`` or
- ``write()`` (or any other method where it may be useful).
-
- - ``mail_create_nosubscribe``: at create or message_post, do not subscribe
- the current user to the record thread
- - ``mail_create_nolog``: at create, do not log the automatic '<Document>
- created' message
- - ``mail_notrack``: at create and write, do not perform the value tracking
- creating messages
- - ``tracking_disable``: at create and write, perform no MailThread features
- (auto subscription, tracking, post, ...)
- - ``mail_auto_delete``: auto delete mail notifications; True by default
- - ``mail_notify_force_send``: if less than 50 email notifications to send,
- send them directly instead of using the queue; True by default
- - ``mail_notify_user_signature``: add the current user signature in
- email notifications; True by default
-
-
-.. _reference/mixins/mail/alias:
-
-Mail alias
-----------
-
-Aliases are configurable email addresses that are linked to a specific record
-(which usually inherits the ``mail.alias.mixin`` model) that will create new records when
-contacted via e-mail. They are an easy way to make your system accessible from
-the outside, allowing users or customers to quickly create records in your
-database without needing to connect to Odoo directly.
-
-Aliases vs. Incoming Mail Gateway
-'''''''''''''''''''''''''''''''''
-
-Some people use the Incoming Mail Gateway for this same purpose. You still need
-a correctly configured mail gateway to use aliases, however a single
-catchall domain will be sufficient since all routing will be done inside Odoo.
-Aliases have several advantages over Mail Gateways:
-
-* Easier to configure
- * A single incoming gateway can be used by many aliases; this avoids having
- to configure multiple emails on your domain name (all configuration is done
- inside Odoo)
- * No need for System access rights to configure aliases
-* More coherent
- * Configurable on the related record, not in a Settings submenu
-* Easier to override server-side
- * Mixin model is built to be extended from the start, allowing you to
- extract useful data from incoming e-mails more easily than with a mail
- gateway.
-
-
-Alias support integration
-'''''''''''''''''''''''''
-
-Aliases are usually configured on a parent model which will then create specific
-record when contacted by e-mail. For example, Project have aliases to create tasks
-or issues, Sales Team have aliases to generate Leads.
-
-.. note:: The model that will be created by the alias **must** inherit the
- ``mail_thread`` model.
-
-Alias support is added by inheriting ``mail.alias.mixin``; this mixin will
-generate a new ``mail.alias`` record for each record of the parent class that
-gets created (for example, every ``project.project`` record having its ``mail.alias``
-record initialized on creation).
-
-.. note:: Aliases can also be created manually and supported by a simple
- :class:`~odoo.fields.Many2one` field. This guide assumes you wish a
- more complete integration with automatic creation of the alias, record-specific
- default values, etc.
-
-Unlike ``mail.thread`` inheritance, the ``mail.alias.mixin`` **requires** some
-specific overrides to work correctly. These overrides will specify the values
-of the created alias, like the kind of record it must create and possibly
-some default values these records may have depending on the parent object:
-
-.. method:: _get_alias_model_name(vals)
-
- Return the model name for the alias. Incoming emails that are not
- replies to existing records will cause the creation of a new record
- of this alias model. The value may depend on ``vals``, the dict of
- values passed to ``create`` when a record of this model is created.
-
- :param vals dict: values of the newly created record that will holding
- the alias
- :return: model name
- :rtype: str
-
-.. method:: _get_alias_values()
-
- Return values to create an alias, or to write on the alias after its
- creation. While not completely mandatory, it is usually required to make
- sure that newly created records will be linked to the alias' parent (i.e.
- tasks getting created in the right project) by setting a dictionary of
- default values in the alias' ``alias_defaults`` field.
-
- :return: dictionnary of values that will be written to the new alias
- :rtype: dict
-
-The ``_get_alias_values()`` override is particularly interesting as it allows you
-to modify the behaviour of your aliases easily. Among the fields that can be set
-on the alias, the following are of particular interest:
-
-``alias_name`` - :class:`~odoo.fields.Char`
- name of the email alias, e.g. 'jobs' if you want to catch emails for
- <jobs@example.odoo.com>
-``alias_user_id`` - :class:`~odoo.fields.Many2one` (``res.users``)
- owner of records created upon receiving emails on this alias;
- if this field is not set the system will attempt to find the right owner
- based on the sender (From) address, or will use the Administrator account
- if no system user is found for that address
-``alias_defaults`` - :class:`~odoo.fields.Text`
- Python dictionary that will be evaluated to provide
- default values when creating new records for this alias
-``alias_force_thread_id`` - :class:`~odoo.fields.Integer`
- optional ID of a thread (record) to which all incoming messages will be
- attached, even if they did not reply to it; if set, this will disable the
- creation of new records completely
-``alias_contact`` - :class:`~odoo.fields.Selection`
- Policy to post a message on the document using the mailgateway
-
- - *everyone*: everyone can post
- - *partners*: only authenticated partners
- - *followers*: only followers of the related document or members of following channels
-
-Note that aliases make use of :ref:`delegation inheritance <reference/orm/inheritance>`,
-which means that while the alias is stored in another table, you have
-access to all these fields directly from your parent object. This allows
-you to make your alias easily configurable from the record's form view.
-
-.. admonition:: Example
-
- Let's add aliases on our business trip class to create expenses on the fly via
- e-mail.
-
- .. code-block:: python
-
- class BusinessTrip(models.Model):
- _name = 'business.trip'
- _inherit = ['mail.thread', 'mail.alias.mixin']
- _description = 'Business Trip'
-
- name = fields.Char(tracking=True)
- partner_id = fields.Many2one('res.partner', 'Responsible',
- tracking=True)
- guest_ids = fields.Many2many('res.partner', 'Participants')
- state = fields.Selection([('draft', 'New'), ('confirmed', 'Confirmed')],
- tracking=True)
- expense_ids = fields.One2many('business.expense', 'trip_id', 'Expenses')
- alias_id = fields.Many2one('mail.alias', string='Alias', ondelete="restrict",
- required=True)
-
- def _get_alias_model_name(self, vals):
- """ Specify the model that will get created when the alias receives a message """
- return 'business.expense'
-
- def _get_alias_values(self):
- """ Specify some default values that will be set in the alias at its creation """
- values = super(BusinessTrip, self)._get_alias_values()
- # alias_defaults holds a dictionnary that will be written
- # to all records created by this alias
- #
- # in this case, we want all expense records sent to a trip alias
- # to be linked to the corresponding business trip
- values['alias_defaults'] = {'trip_id': self.id}
- # we only want followers of the trip to be able to post expenses
- # by default
- values['alias_contact'] = 'followers'
- return values
-
- class BusinessExpense(models.Model):
- _name = 'business.expense'
- _inherit = ['mail.thread']
- _description = 'Business Expense'
-
- name = fields.Char()
- amount = fields.Float('Amount')
- trip_id = fields.Many2one('business.trip', 'Business Trip')
- partner_id = fields.Many2one('res.partner', 'Created by')
-
- We would like our alias to be easily configurable from the form view of our
- business trips, so let's add the following to our form view:
-
- .. code-block:: xml
-
- <page string="Emails">
- <group name="group_alias">
- <label for="alias_name" string="Email Alias"/>
- <div name="alias_def">
- <!-- display a link while in view mode and a configurable field
- while in edit mode -->
- <field name="alias_id" class="oe_read_only oe_inline"
- string="Email Alias" required="0"/>
- <div class="oe_edit_only oe_inline" name="edit_alias"
- style="display: inline;" >
- <field name="alias_name" class="oe_inline"/>
- @
- <field name="alias_domain" class="oe_inline" readonly="1"/>
- </div>
- </div>
- <field name="alias_contact" class="oe_inline"
- string="Accept Emails From"/>
- </group>
- </page>
-
- Now we can change the alias address directly from the form view and change
- who can send e-mails to the alias.
-
- We can then override ``message_new()`` on our expense model to fetch the values
- from our email when the expense will be created:
-
- .. code-block:: python
-
- class BusinessExpense(models.Model):
- # Previous code goes here
- # ...
-
- def message_new(self, msg, custom_values=None):
- """ Override to set values according to the email.
-
- In this simple example, we simply use the email title as the name
- of the expense, try to find a partner with this email address and
- do a regex match to find the amount of the expense."""
- name = msg_dict.get('subject', 'New Expense')
- # Match the last occurence of a float in the string
- # Example: '50.3 bar 34.5' becomes '34.5'. This is potentially the price
- # to encode on the expense. If not, take 1.0 instead
- amount_pattern = '(\d+(\.\d*)?|\.\d+)'
- expense_price = re.findall(amount_pattern, name)
- price = expense_price and float(expense_price[-1][0]) or 1.0
- # find the partner by looking for it's email
- partner = self.env['res.partner'].search([('email', 'ilike', email_address)],
- limit=1)
- defaults = {
- 'name': name,
- 'amount': price,
- 'partner_id': partner.id
- }
- defaults.update(custom_values or {})
- res = super(BusinessExpense, self).message_new(msg, custom_values=defaults)
- return res
-
-.. _reference/mixins/mail/activities:
-
-Activities tracking
--------------------
-
-Activities are actions users have to take on a document like making a phone call
-or organizing a meeting. Activities come with the mail module as they are
-integrated in the Chatter but are *not bundled with mail.thread*. Activities
-are records of the ``mail.activity`` class, which have a type (``mail.activity.type``),
-name, description, scheduled time (among others). Pending activities are visible
-above the message history in the chatter widget.
-
-You can integrate activities using the ``mail.activity.mixin`` class on your object
-and the specific widgets to display them (via the field ``activity_ids``) in the form
-view and kanban view of your records (``mail_activity`` and ``kanban_activity``
-widgets, respectively).
-
-.. admonition:: Example
-
- Organizing a business trip is a tedious process and tracking needed activities
- like ordering plane tickets or a cab for the airport could be useful. To do so,
- we will add the activities mixin on our model and display the next planned activities
- in the message history of our trip.
-
- .. code-block:: python
-
- class BusinessTrip(models.Model):
- _name = 'business.trip'
- _inherit = ['mail.thread', 'mail.activity.mixin']
- _description = 'Business Trip'
-
- name = fields.Char()
- # [...]
-
- We modify the form view of our trips to display their next activites:
-
- .. code-block:: xml
-
- <record id="businness_trip_form" model="ir.ui.view">
- <field name="name">business.trip.form</field>
- <field name="model">business.trip</field>
- <field name="arch" type="xml">
- <form string="Business Trip">
- <!-- Your usual form view goes here -->
- <div class="oe_chatter">
- <field name="message_follower_ids" widget="mail_followers"/>
- <field name="activity_ids" widget="mail_activity"/>
- <field name="message_ids" widget="mail_thread"/>
- </div>
- </form>
- </field>
- </record>
-
-You can find concrete examples of integration in the following models:
-
-* ``crm.lead`` in the CRM (*crm*) Application
-* ``sale.order`` in the Sales (*sale*) Application
-* ``project.task`` in the Project (*poject*) Application
-
-
-.. _reference/mixins/website:
-
-Website features
-================
-
-.. _reference/mixins/website/utm:
-
-Visitor tracking
-----------------
-
-The ``utm.mixin`` class can be used to track online marketing/communication
-campaigns through arguments in links to specified resources. The mixin adds
-3 fields to your model:
-
-* ``campaign_id``: :class:`~odoo.fields.Many2one` field to a ``utm.campaign``
- object (i.e. Christmas_Special, Fall_Collection, etc.)
-* ``source_id``: :class:`~odoo.fields.Many2one` field to a ``utm.source``
- object (i.e. Search Engine, mailing list, etc.)
-* ``medium_id``: :class:`~odoo.fields.Many2one` field to a ``utm.medium``
- object (i.e. Snail Mail, e-Mail, social network update, etc.)
-
-These models have a single field ``name`` (i.e. they are simply there to
-distinguish campaigns but don't have any specific behaviour).
-
-Once a customer visits your website with these parameters set in the url
-(i.e. https://www.odoo.com/?campaign_id=mixin_talk&source_id=www.odoo.com&medium_id=website),
-three cookies are set in the visitor's website for these parameters.
-Once a object that inherits the utm.mixin is created from the website (i.e. lead
-form, job application, etc.), the utm.mixin code kicks in and fetches the values
-from the cookies to set them in the new record. Once this is done, you can then
-use the campaign/source/medium fields as any other field when defining reports
-and views (group by, etc.).
-
-To extend this behaviour, simply add a relational field to a simple model (the
-model should support the *quick create* (i.e. call to ``create()`` with a single
-``name`` value) and extend the function ``tracking_fields()``:
-
-.. code-block:: python
-
- class UtmMyTrack(models.Model):
- _name = 'my_module.my_track'
- _description = 'My Tracking Object'
-
- name = fields.Char(string='Name', required=True)
-
-
- class MyModel(models.Models):
- _name = 'my_module.my_model'
- _inherit = ['utm.mixin']
- _description = 'My Tracked Object'
-
- my_field = fields.Many2one('my_module.my_track', 'My Field')
-
- @api.model
- def tracking_fields(self):
- result = super(MyModel, self).tracking_fields()
- result.append([
- # ("URL_PARAMETER", "FIELD_NAME_MIXIN", "NAME_IN_COOKIES")
- ('my_field', 'my_field', 'odoo_utm_my_field')
- ])
- return result
-
-This will tell the system to create a cookie named *odoo_utm_my_field* with the
-value found in the url parameter ``my_field``; once a new record of this model is
-created by a call from a website form, the generic override of the ``create()``
-method of ``utm.mixin`` will fetch the default values for this field from the
-cookie (and the ``my_module.my_track`` record will be creatwed on the fly if it
-does not exist yet).
-
-You can find concrete examples of integration in the following models:
-
-* ``crm.lead`` in the CRM (*crm*) Application
-* ``hr.applicant`` in the Recruitment Process (*hr_recruitment*) Application
-* ``helpdesk.ticket`` in the Helpdesk (*helpdesk* - Odoo Enterprise only) Application
-
-.. _reference/mixins/website/published:
-
-Website visibility
-------------------
-
-You can quite easily add a website visibility toggle on any of your record. While
-this mixin is quite easy to implement manually, it is the most often-used after
-the ``mail.thread`` inheritance; a testament to its usefulness. The typical use
-case for this mixin is any object that has a frontend-page; being able to control
-the visibility of the page allows you to take your time while editing the page
-and only publish it when you're satisfied.
-
-To include the functionnality, you only need to inherit ``website.published.mixin``:
-
-.. code-block:: python
-
- class BlogPost(models.Model):
- _name = "blog.post"
- _description = "Blog Post"
- _inherit = ['website.published.mixin']
-
-This mixin adds 2 fields on your model:
-
-* ``website_published``: :class:`~odoo.fields.Boolean` field which represents
- the status of the publication
-* ``website_url``: :class:`~odoo.fields.Char` field which represents
- the URL through which the object is accessed
-
-Note that this last field is a computed field and must be implemented for your class:
-
-.. code-block:: python
-
- def _compute_website_url(self):
- for blog_post in self:
- blog_post.website_url = "/blog/%s" % (log_post.blog_id)
-
-Once the mechanism is in place, you just have to adapt your frontend and backend
-views to make it accessible. In the backend, adding a button in the button box is
-usually the way to go:
-
-.. code-block:: xml
-
- <button class="oe_stat_button" name="website_publish_button"
- type="object" icon="fa-globe">
- <field name="website_published" widget="website_button"/>
- </button>
-
-In the frontend, some security checks are needed to avoid showing 'Editing'
-buttons to website visitors:
-
-.. code-block:: xml
-
- <div id="website_published_button" class="float-right"
- groups="base.group_website_publisher"> <!-- or any other meaningful group -->
- <t t-call="website.publish_management">
- <t t-set="object" t-value="blog_post"/>
- <t t-set="publish_edit" t-value="True"/>
- <t t-set="action" t-value="'blog.blog_post_action'"/>
- </t>
- </div>
-
-Note that you must pass your object as the variable ``object`` to the template;
-in this example, the ``blog.post`` record was passed as the ``blog_post`` variable
-to the ``qweb`` rendering engine, it is necessary to specify this to the publish
-management template. The ``publish_edit`` variable allow the frontend
-button to link to the backend (allowing you to switch from frontend to backend
-and vice-versa easily); if set, you must specify the full external id of the action
-you want to call in the backend in the ``action`` variable (note that a Form View
-must exist for the model).
-
-The action ``website_publish_button`` is defined in the mixin and adapts its
-behaviour to your object: if the class has a valid ``website_url`` compute function,
-the user is redirected to the frontend when he clicks on the button; the user
-can then publish the page directly from the frontend. This ensures
-that no online publication can happen by accident. If there is not compute function,
-the boolean ``website_published`` is simply triggered.
-
-.. _reference/mixins/website/seo:
-
-Website metadata
-----------------
-
-This simple mixin simply allows you to easily inject metadata in your frontend
-pages.
-
-.. code-block:: python
-
- class BlogPost(models.Model):
- _name = "blog.post"
- _description = "Blog Post"
- _inherit = ['website.seo.metadata', 'website.published.mixin']
-
-This mixin adds 3 fields on your model:
-
-* ``website_meta_title``: :class:`~odoo.fields.Char` field that allow you to set
- an additional title to your page
-* ``website_meta_description``: :class:`~odoo.fields.Char` field that contains a
- short description of the page (sometimes used in search engines results)
-* ``website_meta_keywords``: :class:`~odoo.fields.Char` field that contains some
- keywords to help your page to be classified more precisely by search engines; the
- "Promote" tool will help you select lexically-related keywords easily
-
-These fields are editable in the frontend using the "Promote" tool from the Editor
-toolbar. Setting these fields can help search engines to better index your pages.
-Note that search engines do not base their results only on these metadata; the
-best SEO practice should still be to get referenced by reliable sources.
-
-.. _reference/mixins/misc:
-
-Others
-======
-
-.. _reference/mixins/misc/rating:
-
-Customer Rating
----------------
-
-The rating mixin allows sending email to ask for customer rating, automatic
-transitioning in a kanban processes and aggregating statistics on your ratings.
-
-Adding rating on your model
-'''''''''''''''''''''''''''
-
-To add rating support, simply inherit the ``rating.mixin`` model:
-
-.. code-block:: python
-
- class MyModel(models.Models):
- _name = 'my_module.my_model'
- _inherit = ['rating.mixin', 'mail.thread']
-
- user_id = fields.Many2one('res.users', 'Responsible')
- partner_id = fields.Many2one('res.partner', 'Customer')
-
-The behaviour of the mixin adapts to your model:
-
-* The ``rating.rating`` record will be linked to the ``partner_id`` field of your
- model (if the field is present).
-
- - this behaviour can be overridden with the function ``rating_get_partner_id()``
- if you use another field than ``partner_id``
-
-* The ``rating.rating`` record will be linked to the partner of the ``user_id``
- field of your model (if the field is present) (i.e. the partner who is rated)
-
- - this behaviour can be overridden with the function ``rating_get_rated_partner_id()``
- if you use another field than ``user_id`` (note that the function must return a
- ``res.partner``, for ``user_id`` the system automatically fetches the partner
- of the user)
-
-* The chatter history will display the rating event (if your model inherits from
- ``mail.thread``)
-
-Send rating requests by e-mail
-''''''''''''''''''''''''''''''
-
-If you wish to send emails to request a rating, simply generate an e-mail with
-links to the rating object. A very basic email template could look like this:
-
-.. code-block:: xml
-
- <record id="rating_my_model_email_template" model="mail.template">
- <field name="name">My Model: Rating Request</field>
- <field name="email_from">${object.rating_get_rated_partner_id().email or '' | safe}</field>
- <field name="subject">Service Rating Request</field>
- <field name="model_id" ref="my_module.model_my_model"/>
- <field name="partner_to" >${object.rating_get_partner_id().id}</field>
- <field name="auto_delete" eval="True"/>
- <field name="body_html"><![CDATA[
- % set access_token = object.rating_get_access_token()
- <p>Hi,</p>
- <p>How satsified are you?</p>
- <ul>
- <li><a href="/rate/${access_token}/5">Satisfied</a></li>
- <li><a href="/rate/${access_token}/3">Not satisfied</a></li>
- <li><a href="/rate/${access_token}/1">Very unsatisfied</a></li>
- </ul>
- ]]></field>
- </record>
-
-Your customer will then receive an e-mail with links to a simple webpage allowing
-them to provide a feedback on their interaction with your users (including a free-text
-feedback message).
-
-You can then quite easily integrate your ratings with your form view by defining
-an action for the ratings:
-
-.. code-block:: xml
-
- <record id="rating_rating_action_my_model" model="ir.actions.act_window">
- <field name="name">Customer Ratings</field>
- <field name="res_model">rating.rating</field>
- <field name="view_mode">kanban,pivot,graph</field>
- <field name="domain">[('res_model', '=', 'my_module.my_model'), ('res_id', '=', active_id), ('consumed', '=', True)]</field>
- </record>
-
- <record id="my_module_my_model_view_form_inherit_rating" model="ir.ui.view">
- <field name="name">my_module.my_model.view.form.inherit.rating</field>
- <field name="model">my_module.my_model</field>
- <field name="inherit_id" ref="my_module.my_model_view_form"/>
- <field name="arch" type="xml">
- <xpath expr="//div[@name='button_box']" position="inside">
- <button name="%(rating_rating_action_my_model)d" type="action"
- class="oe_stat_button" icon="fa-smile-o">
- <field name="rating_count" string="Rating" widget="statinfo"/>
- </button>
- </xpath>
- </field>
- </record>
-
-Note that there are default views (kanban,pivot,graph) for ratings which allow
-you a quick bird's eye view of your customer ratings.
-
-You can find concrete examples of integration in the following models:
-
-* ``project.task`` in the Project (*rating_project*) Application
-* ``helpdesk.ticket`` in the Helpdesk (*helpdesk* - Odoo Enterprise only) Application
diff --git a/doc/reference/mobile.rst b/doc/reference/mobile.rst
deleted file mode 100644
index 355164e82c9..00000000000
--- a/doc/reference/mobile.rst
+++ /dev/null
@@ -1,213 +0,0 @@
-:banner: banners/mobile.jpg
-:types: api
-
-.. _reference/mobile:
-
-==================
-Mobile JavaScript
-==================
-
-Introduction
-============
-
-In Odoo 10.0 we released a mobile app which allows you to access all **Odoo apps**
-(even your customized modules).
-
-The application is a combination of **Odoo Web** and **Native Mobile
-components**. In other words it is a Odoo Web instance loaded inside a native, mobile, WebView container.
-
-This page documents how you can access mobile native components like Camera,
-Vibration, Notification and Toast through Odoo Web (via JavaScript). For this, you
-do not need to be a mobile developer, if you know Odoo JavaScript API you can
-access all available mobile features.
-
-.. warning:: These features work with **Odoo Enterprise 10.0+** only
-
-How does it work?
-=================
-
-Internal workings of the mobile application:
-
-.. image:: images/mobile_working.jpg
-
-Of course, it is a web page that loads on a Mobile Native Web container. But it
-is integrated in such a way that you can access native resources from your web
-JavaScript.
-
-WebPages (Odoo Web) is on the top of each layer, where the second layer is a Bridge
-between Odoo Web (JS) and the native mobile components.
-
-When any call from JavaScript is triggered it passes through Bridge and Bridge
-passes it to the native invoker to perform that action.
-
-When the native component has done its work, it is passed to the Bridge again and
-you get the output in JavaScript.
-
-Process time taken by the Native component depends on what you are requesting
-from the Native resources. For example the Camera or GPS Location.
-
-How to use it?
-==============
-
-Just like the Odoo Web Framework, the Mobile API can be used anywhere by getting the object from
-**web_mobile.rpc**
-
-.. image:: images/odoo_mobile_api.png
-
-The mobile RPC object provides a list of methods that are available (this only works with the mobile
-app).
-
-Check if the method is available and then execute it.
-
-Methods
--------
-
-.. note:: Each of the methods returns a JQuery Deffered object which returns
- a data JSON dictionary
-
-Show Toast in device
-.....................
-
-.. js:function:: showToast
-
- :param object args: **message** text to display
-
-A toast provides simple feedback about an operation in a small popup. It only
-fills the amount of space required for the message and the current activity
-remains visible and interactive.
-
-.. code-block:: javascript
-
- mobile.methods.showToast({'message': 'Message sent'});
-
-.. image:: images/toast.png
-
-
-Vibrating device
-................
-
-
-.. js:function:: vibrate
-
- :param object args: Vibrates constantly for the specified period of time
- (in milliseconds).
-
-Vibrate mobile device with given duration.
-
-.. code-block:: javascript
-
- mobile.methods.vibrate({'duration': 100});
-
-Show snackbar with action
-.........................
-
-.. js:function:: showSnackBar
-
- :param object args: (*required*) **Message** to show in snackbar and action **button label** in Snackbar (optional)
- :returns: ``True`` if the user clicks on the Action button, ``False`` if SnackBar auto dismissed after some time.
-
-Snackbars provide lightweight feedback about an operation. They show a brief
-message at the bottom of the screen on mobile or in the lower left corner on larger devices.
-Snackbars appear above all the other elements on the screen and only one can be
-displayed at a time.
-
-.. code-block:: javascript
-
- mobile.methods.showSnackBar({'message': 'Message is deleted', 'btn_text': 'Undo'}).then(function(result){
- if(result){
- // Do undo operation
- }else{
- // Snack Bar dismissed
- }
- });
-
-.. image:: images/snackbar.png
-
-Showing notification
-.....................
-
-.. js:function:: showNotification
-
- :param object args: **title** (first row) of the notification, **message** (second row) of the notification, in a standard notification.
-
-A notification is a message you can display to the user outside of your
-application's normal UI. When you tell the system to issue a notification, it
-first appears as an icon in the notification area. To see the details of the
-notification, the user opens the notification drawer. Both the notification
-area and the notification drawer are system-controlled areas that the user can
-view at any time.
-
-.. code-block:: javascript
-
- mobile.showNotification({'title': 'Simple Notification', 'message': 'This is a test for a simple notification'})
-
-.. image:: images/mobile_notification.png
-
-
-Create contact in device
-.........................
-
-.. js:function:: addContact
-
- :param object args: Dictionary with contact details. Possible keys (name, mobile, phone, fax, email, website, street, street2, country_id, state_id, city, zip, parent_id, function and image)
-
-Create a new device contact with the given contact details.
-
-.. code-block:: javascript
-
- var contact = {
- 'name': 'Michel Fletcher',
- 'mobile': '9999999999',
- 'phone': '7954856587',
- 'fax': '765898745',
- 'email': 'michel.fletcher@agrolait.example.com',
- 'website': 'http://www.agrolait.com',
- 'street': '69 rue de Namur',
- 'street2': false,
- 'country_id': [21, 'Belgium'],
- 'state_id': false,
- 'city': 'Wavre',
- 'zip': '1300',
- 'parent_id': [8, 'Agrolait'],
- 'function': 'Analyst',
- 'image': '<<BASE 64 Image Data>>'
- }
-
- mobile.methods.addContact(contact);
-
-.. image:: images/mobile_contact_create.png
-
-Scanning barcodes
-..................
-
-.. js:function:: scanBarcode
-
- :returns: Scanned ``code`` from any barcode
-
-The barcode API detects barcodes in real-time, on the device, in any orientation.
-
-The barcode API can read the following barcode formats:
-
-* 1D barcodes: EAN-13, EAN-8, UPC-A, UPC-E, Code-39, Code-93, Code-128, ITF, Codabar
-* 2D barcodes: QR Code, Data Matrix, PDF-417, AZTEC
-
-.. code-block:: javascript
-
- mobile.methods.scanBarcode().then(function(code){
- if(code){
- // Perform operation with the scanned code
- }
- });
-
-Switching account in device
-...........................
-
-.. js:function:: switchAccount
-
-Use switchAccount to switch from one account to another on the device.
-
-.. code-block:: javascript
-
- mobile.methods.switchAccount();
-
-.. image:: images/mobile_switch_account.png
diff --git a/doc/reference/module.rst b/doc/reference/module.rst
deleted file mode 100644
index 2c91e4f6d6e..00000000000
--- a/doc/reference/module.rst
+++ /dev/null
@@ -1,148 +0,0 @@
-:banner: banners/module.jpg
-
-================
-Module Manifests
-================
-
-
-
-.. _reference/module/manifest:
-
-Manifest
-========
-
-The manifest file serves to declare a python package as an Odoo module
-and to specify module metadata.
-
-It is a file called ``__manifest__.py`` and contains a single Python
-dictionary, where each key specifies module metadatum.
-
-::
-
- {
- 'name': "A Module",
- 'version': '1.0',
- 'depends': ['base'],
- 'author': "Author Name",
- 'category': 'Category',
- 'description': """
- Description text
- """,
- # data files always loaded at installation
- 'data': [
- 'views/mymodule_view.xml',
- ],
- # data files containing optionally loaded demonstration data
- 'demo': [
- 'demo/demo_data.xml',
- ],
- }
-
-Available manifest fields are:
-
-``name`` (``str``, required)
- the human-readable name of the module
-``version`` (``str``)
- this module's version, should follow `semantic versioning`_ rules
-``description`` (``str``)
- extended description for the module, in reStructuredText
-``author`` (``str``)
- name of the module author
-``website`` (``str``)
- website URL for the module author
-``license`` (``str``, defaults: ``LGPL-3``)
- distribution license for the module.
- Possible values:
-
- * `GPL-2`
- * `GPL-2 or any later version`
- * `GPL-3`
- * `GPL-3 or any later version`
- * `AGPL-3`
- * `LGPL-3`
- * `Other OSI approved licence`
- * `OEEL-1` (Odoo Enterprise Edition License v1.0)
- * `OPL-1` (Odoo Proprietary License v1.0)
- * `Other proprietary`
-
-``category`` (``str``, default: ``Uncategorized``)
- classification category within Odoo, rough business domain for the module.
-
- Although using `existing categories`_ is recommended, the field is
- freeform and unknown categories are created on-the-fly. Category
- hierarchies can be created using the separator ``/`` e.g. ``Foo / Bar``
- will create a category ``Foo``, a category ``Bar`` as child category of
- ``Foo``, and will set ``Bar`` as the module's category.
-``depends`` (``list(str)``)
- Odoo modules which must be loaded before this one, either because this
- module uses features they create or because it alters resources they
- define.
-
- When a module is installed, all of its dependencies are installed before
- it. Likewise dependencies are loaded before a module is loaded.
-``data`` (``list(str)``)
- List of data files which must always be installed or updated with the
- module. A list of paths from the module root directory
-``demo`` (``list(str)``)
- List of data files which are only installed or updated in *demonstration
- mode*
-``auto_install`` (``bool``, default: ``False``)
- If ``True``, this module will automatically be installed if all of its
- dependencies are installed.
-
- It is generally used for "link modules" implementing synergic integration
- between two otherwise independent modules.
-
- For instance ``sale_crm`` depends on both ``sale`` and ``crm`` and is set
- to ``auto_install``. When both ``sale`` and ``crm`` are installed, it
- automatically adds CRM campaigns tracking to sale orders without either
- ``sale`` or ``crm`` being aware of one another
-``external_dependencies`` (``dict(key=list(str))``)
- A dictionary containing python and/or binary dependencies.
-
- For python dependencies, the ``python`` key must be defined for this
- dictionary and a list of python modules to be imported should be assigned
- to it.
-
- For binary dependencies, the ``bin`` key must be defined for this
- dictionary and a list of binary executable names should be assigned to it.
-
- The module won't be installed if either the python module is not installed
- in the host machine or the binary executable is not found within the
- host machine's PATH environment variable.
-``application`` (``bool``, default: ``False``)
- Whether the module should be considered as a fully-fledged application
- (``True``) or is just a technical module (``False``) that provides some
- extra functionality to an existing application module.
-``css`` (``list(str)``)
- Specify css files with custom rules to be imported, these files should be
- located in ``static/src/css`` inside the module.
-``images`` (``list(str)``)
- Specify image files to be used by the module.
-``installable`` (``bool`` default: ``True``)
- Whether a user should be able to install the module from the Web UI or not.
-``maintainer`` (``str``)
- Person or entity in charge of the maintenance of this module, by default
- it is assumed that the author is the maintainer.
-``{pre_init, post_init, uninstall}_hook`` (``str``)
- Hooks for module installation/uninstallation, their value should be a
- string representing the name of a function defined inside the module's
- ``__init__.py``.
-
- ``pre_init_hook`` takes a cursor as its only argument, this function is
- executed prior to the module's installation.
-
- ``post_init_hook`` takes a cursor and a registry as its arguments, this
- function is executed right after the module's installation.
-
- ``uninstall_hook`` takes a cursor and a registry as its arguments, this
- function is executed after the module's uninstallation.
-
- These hooks should only be used when setup/cleanup required for this module
- is either extremely difficult or impossible through the api.
-``active`` (``bool``)
- This indicates whether this module must install automatically or not.
-
-.. _semantic versioning: https://semver.org
-.. _existing categories:
- https://github.com/odoo/odoo/blob/14.0/odoo/addons/base/data/ir_module_category_data.xml
diff --git a/doc/reference/orm.rst b/doc/reference/orm.rst
deleted file mode 100644
index 3ca49846fb6..00000000000
--- a/doc/reference/orm.rst
+++ /dev/null
@@ -1,1092 +0,0 @@
-:banner: banners/orm_api.jpg
-
-.. _reference/orm:
-
-=======
-ORM API
-=======
-
-.. automodule:: odoo.models
-
-.. _reference/orm/models:
-.. _reference/orm/model:
-
-Models
-======
-
-Model fields are defined as attributes on the model itself::
-
- from odoo import models, fields
- class AModel(models.Model):
- _name = 'a.model.name'
-
- field1 = fields.Char()
-
-.. warning:: this means you cannot define a field and a method with the same
- name, the last one will silently overwrite the former ones.
-
-By default, the field's label (user-visible name) is a capitalized version of
-the field name, this can be overridden with the ``string`` parameter. ::
-
- field2 = fields.Integer(string="Field Label")
-
-For the list of field types and parameters, see :ref:`the fields reference
-<reference/fields>`.
-
-Default values are defined as parameters on fields, either as a value::
-
- name = fields.Char(default="a value")
-
-or as a function called to compute the default value, which should return that
-value::
-
- def _default_name(self):
- return self.get_value()
-
- name = fields.Char(default=lambda self: self._default_name())
-
-.. rubric:: API
-
-.. autoclass:: odoo.models.BaseModel()
-
- .. autoattribute:: _auto
- .. attribute:: _log_access
-
- Whether the ORM should automatically generate and update the
- :ref:`reference/fields/automatic/log_access`.
-
- Defaults to whatever value was set for :attr:`~._auto`.
-
- .. autoattribute:: _table
- .. autoattribute:: _sequence
- .. autoattribute:: _sql_constraints
-
- .. autoattribute:: _register
- .. autoattribute:: _abstract
- .. autoattribute:: _transient
-
- .. autoattribute:: _name
- .. autoattribute:: _description
-
- .. autoattribute:: _inherit
- .. autoattribute:: _inherits
-
- .. autoattribute:: _rec_name
- .. autoattribute:: _order
-
- .. autoattribute:: _check_company_auto
-
- .. autoattribute:: _parent_name
- .. autoattribute:: _parent_store
-
- .. autoattribute:: _date_name
- .. autoattribute:: _fold_name
-
-AbstractModel
--------------
-
-.. autoclass:: odoo.models.AbstractModel()
-
-Model
------
-
-.. autoclass:: odoo.models.Model()
-
- .. autoattribute:: _auto
- .. autoattribute:: _abstract
- .. autoattribute:: _transient
-
-TransientModel
---------------
-
-.. autoclass:: odoo.models.TransientModel()
-
- .. autoattribute:: _auto
- .. autoattribute:: _abstract
- .. autoattribute:: _transient
-
-.. _reference/fields:
-.. _reference/orm/fields:
-
-Fields
-======
-
-.. currentmodule:: odoo.fields
-
-.. autoclass:: Field()
-
-.. .. autoattribute:: Field._slots
- :annotation:
-
-.. _reference/fields/basic:
-
-Basic Fields
-------------
-
-.. autoclass:: Boolean()
-
-.. autoclass:: Char()
-
-.. autoclass:: Float()
-
-.. autoclass:: Integer()
-
-.. _reference/fields/advanced:
-
-Advanced Fields
----------------
-
-.. autoclass:: Binary()
-
-.. autoclass:: Html()
-
-.. autoclass:: Image()
-
-.. autoclass:: Monetary()
-
-.. autoclass:: Selection()
-
-.. autoclass:: Text()
-
-.. _reference/fields/date:
-
-Date(time) Fields
-'''''''''''''''''
-
-:class:`Dates <odoo.fields.Date>` and :class:`Datetimes <odoo.fields.Datetime>`
-are very important fields in any kind of business application.
-Their misuse can create invisible yet painful bugs, this section
-aims to provide Odoo developers with the knowledge required
-to avoid misusing these fields.
-
-When assigning a value to a Date/Datetime field, the following options are valid:
-
-* A `date` or `datetime` object.
-* A string in the proper server format:
-
- * ``YYYY-MM-DD`` for :class:`~odoo.fields.Date` fields,
- * ``YYYY-MM-DD HH:MM:SS`` for :class:`~odoo.fields.Datetime` fields.
-
-* `False` or `None`.
-
-The Date and Datetime fields class have helper methods to attempt conversion
-into a compatible type:
-
-* :func:`~odoo.fields.Date.to_date` will convert to a :class:`datetime.date`
-* :func:`~odoo.fields.Datetime.to_datetime` will convert to a :class:`datetime.datetime`.
-
-.. admonition:: Example
-
- To parse date/datetimes coming from external sources::
-
- fields.Date.to_date(self._context.get('date_from'))
-
-Date / Datetime comparison best practices:
-
-* Date fields can **only** be compared to date objects.
-* Datetime fields can **only** be compared to datetime objects.
-
-.. warning:: Strings representing dates and datetimes can be compared
- between each other, however the result may not be the expected
- result, as a datetime string will always be greater than a
- date string, therefore this practice is **heavily**
- discouraged.
-
-Common operations with dates and datetimes such as addition, substraction or
-fetching the start/end of a period are exposed through both
-:class:`~odoo.fields.Date` and :class:`~odoo.fields.Datetime`.
-These helpers are also available by importing `odoo.tools.date_utils`.
-
-.. note:: Timezones
-
- Datetime fields are stored as `timestamp without timezone` columns in the database and are stored
- in the UTC timezone. This is by design, as it makes the Odoo database independent from the timezone
- of the hosting server system. Timezone conversion is managed entirely by the client side.
-
-.. autoclass:: Date()
- :members: today, context_today, to_date, to_string, start_of, end_of, add, subtract
-
-.. autoclass:: Datetime()
- :members: now, today, context_timestamp, to_datetime, to_string, start_of, end_of, add, subtract
-
-.. _reference/fields/relational:
-
-Relational Fields
-'''''''''''''''''
-
-.. autoclass:: Many2one()
-
-.. autoclass:: One2many()
-
-.. autoclass:: Many2many()
-
-Pseudo-relational fields
-''''''''''''''''''''''''
-
-.. autoclass:: Reference()
-
-.. autoclass:: Many2oneReference()
-
-.. _reference/fields/compute:
-
-Computed Fields
-'''''''''''''''
-
-Fields can be computed (instead of read straight from the database) using the
-``compute`` parameter. **It must assign the computed value to the field**. If
-it uses the values of other *fields*, it should specify those fields using
-:func:`~odoo.api.depends`. ::
-
- from odoo import api
- total = fields.Float(compute='_compute_total')
-
- @api.depends('value', 'tax')
- def _compute_total(self):
- for record in self:
- record.total = record.value + record.value * record.tax
-
-* dependencies can be dotted paths when using sub-fields::
-
- @api.depends('line_ids.value')
- def _compute_total(self):
- for record in self:
- record.total = sum(line.value for line in record.line_ids)
-
-* computed fields are not stored by default, they are computed and
- returned when requested. Setting ``store=True`` will store them in the
- database and automatically enable searching.
-* searching on a computed field can also be enabled by setting the ``search``
- parameter. The value is a method name returning a
- :ref:`reference/orm/domains`. ::
-
- upper_name = field.Char(compute='_compute_upper', search='_search_upper')
-
- def _search_upper(self, operator, value):
- if operator == 'like':
- operator = 'ilike'
- return [('name', operator, value)]
-
- The search method is invoked when processing domains before doing an
- actual search on the model. It must return a domain equivalent to the
- condition: ``field operator value``.
-
-.. TODO and/or by setting the store to True for search domains ?
-
-* Computed fields are readonly by default. To allow *setting* values on a computed field, use the ``inverse``
- parameter. It is the name of a function reversing the computation and
- setting the relevant fields::
-
- document = fields.Char(compute='_get_document', inverse='_set_document')
-
- def _get_document(self):
- for record in self:
- with open(record.get_document_path) as f:
- record.document = f.read()
- def _set_document(self):
- for record in self:
- if not record.document: continue
- with open(record.get_document_path()) as f:
- f.write(record.document)
-
-* multiple fields can be computed at the same time by the same method, just
- use the same method on all fields and set all of them::
-
- discount_value = fields.Float(compute='_apply_discount')
- total = fields.Float(compute='_apply_discount')
-
- @api.depends('value', 'discount')
- def _apply_discount(self):
- for record in self:
- # compute actual discount from discount percentage
- discount = record.value * record.discount
- record.discount_value = discount
- record.total = record.value - discount
-
-.. warning::
-
- While it is possible to use the same compute method for multiple
- fields, it is not recommended to do the same for the inverse
- method.
-
- During the computation of the inverse, **all** fields that use
- said inverse are protected, meaning that they can't be computed,
- even if their value is not in the cache.
-
- If any of those fields is accessed and its value is not in cache,
- the ORM will simply return a default value of `False` for these fields.
- This means that the value of the inverse fields (other than the one
- triggering the inverse method) may not give their correct value and
- this will probably break the expected behavior of the inverse method.
-
-.. _reference/fields/related:
-
-Related fields
-''''''''''''''
-
-A special case of computed fields are *related* (proxy) fields, which provide
-the value of a sub-field on the current record. They are defined by setting
-the ``related`` parameter and like regular computed fields they can be
-stored::
-
- nickname = fields.Char(related='user_id.partner_id.name', store=True)
-
-The value of a related field is given by following a sequence of
-relational fields and reading a field on the reached model. The complete
-sequence of fields to traverse is specified by the ``related`` attribute.
-
-Some field attributes are automatically copied from the source field if
-they are not redefined: ``string``, ``help``, ``readonly``, ``required`` (only
-if all fields in the sequence are required), ``groups``, ``digits``, ``size``,
-``translate``, ``sanitize``, ``selection``, ``comodel_name``, ``domain``,
-``context``. All semantic-free attributes are copied from the source
-field.
-
-By default, the values of related fields are not stored to the database.
-Add the attribute ``store=True`` to make it stored, just like computed
-fields. Related fields are automatically recomputed when their
-dependencies are modified.
-
-.. note:: The related fields are computed in sudo mode.
-
-.. warning::
-
- You cannot chain :class:`~odoo.fields.Many2many` or :class:`~odoo.fields.One2many` fields in ``related`` fields dependencies.
-
- ``related`` can be used to refer to a :class:`~odoo.fields.One2many` or
- :class:`~odoo.fields.Many2many` field on another model on the
- condition that it's done through a ``Many2one`` relation on the current model.
- ``One2many`` and ``Many2many`` are not supported and the results will not be
- aggregated correctly::
-
- m2o_id = fields.Many2one()
- m2m_ids = fields.Many2many()
- o2m_ids = fields.One2many()
-
- # Supported
- d_ids = fields.Many2many(related="m2o_id.m2m_ids")
- e_ids = fields.One2many(related="m2o_id.o2m_ids")
-
- # Won't work: use a custom Many2many computed field instead
- f_ids = fields.Many2many(related="m2m_ids.m2m_ids")
- g_ids = fields.One2many(related="o2m_ids.o2m_ids")
-
-.. _reference/fields/automatic:
-
-Automatic fields
-----------------
-
-.. attribute:: id
-
- Identifier :class:`field <odoo.fields.Field>`
-
- If length of current recordset is 1, return id of unique record in it.
-
- Raise an Error otherwise.
-
-.. _reference/fields/automatic/log_access:
-
-Access Log fields
-'''''''''''''''''
-
-These fields are automatically set and updated if
-:attr:`~odoo.models.BaseModel._log_access` is enabled. It can be
-disabled to avoid creating or updating those fields on tables for which they are
-not useful.
-
-By default, :attr:`~odoo.models.BaseModel._log_access` is set to the same value
-as :attr:`~odoo.models.BaseModel._auto`
-
-.. attribute:: create_date
-
- Stores when the record was created, :class:`~odoo.fields.Datetime`
-
-.. attribute:: create_uid
-
- Stores *who* created the record, :class:`~odoo.fields.Many2one` to a
- ``res.users``.
-
-.. attribute:: write_date
-
- Stores when the record was last updated, :class:`~odoo.fields.Datetime`
-
-.. attribute:: write_uid
-
- Stores who last updated the record, :class:`~odoo.fields.Many2one` to a
- ``res.users``.
-
-.. warning:: :attr:`~odoo.models.BaseModel._log_access` *must* be enabled on
- :class:`~odoo.models.TransientModel`.
-
-.. _reference/orm/fields/reserved:
-
-Reserved Field names
---------------------
-
-A few field names are reserved for pre-defined behaviors beyond that of
-automated fields. They should be defined on a model when the related
-behavior is desired:
-
-.. attribute:: name
-
- default value for :attr:`~odoo.models.BaseModel._rec_name`, used to
- display records in context where a representative "naming" is
- necessary.
-
- :class:`~odoo.fields.Char`
-
-.. attribute:: active
-
- toggles the global visibility of the record, if ``active`` is set to
- ``False`` the record is invisible in most searches and listing.
-
- :class:`~odoo.fields.Boolean`
-
-.. .. attribute:: sequence
-..
-.. Alterable ordering criteria, allows drag-and-drop reordering of models
-.. in list views.
-..
-.. :class:`~odoo.fields.Integer`
-
-.. attribute:: state
-
- lifecycle stages of the object, used by the ``states`` attribute on
- :class:`fields <odoo.fields.Field>`.
-
- :class:`~odoo.fields.Selection`
-
-.. attribute:: parent_id
-
- default_value of :attr:`~._parent_name`, used to organize
- records in a tree structure and enables the ``child_of``
- and ``parent_of`` operators in domains.
-
- :class:`~odoo.fields.Many2one`
-
-.. attribute:: parent_path
-
- When :attr:`~._parent_store` is set to True, used to store a value reflecting
- the tree structure of :attr:`~._parent_name`, and to optimize the operators
- ``child_of`` and ``parent_of`` in search domains.
- It must be declared with ``index=True`` for proper operation.
-
- :class:`~odoo.fields.Char`
-
-.. attribute:: company_id
-
- Main field name used for Odoo multi-company behavior.
-
- Used by `:meth:~odoo.models._check_company` to check multi company consistency.
- Defines whether a record is shared between companies (no value) or only
- accessible by the users of a given company.
-
- :class:`~odoo.fields.Many2one`
- :type: :class:`~odoo.addons.base.models.res_company`
-
-Recordsets
-==========
-
-Interactions with models and records are performed through recordsets, an ordered
-collection of records of the same model.
-
-.. warning:: Contrary to what the name implies, it is currently possible for
- recordsets to contain duplicates. This may change in the future.
-
-Methods defined on a model are executed on a recordset, and their ``self`` is
-a recordset::
-
- class AModel(models.Model):
- _name = 'a.model'
- def a_method(self):
- # self can be anything between 0 records and all records in the
- # database
- self.do_operation()
-
-Iterating on a recordset will yield new sets of *a single record*
-("singletons"), much like iterating on a Python string yields strings of a
-single characters::
-
- def do_operation(self):
- print(self) # => a.model(1, 2, 3, 4, 5)
- for record in self:
- print(record) # => a.model(1), then a.model(2), then a.model(3), ...
-
-Field access
-------------
-
-Recordsets provide an "Active Record" interface: model fields can be read and
-written directly from the record as attributes.
-
-.. note::
-
- When accessing non-relational fields on a recordset of potentially multiple
- records, use :meth:`~odoo.models.BaseModel.mapped`::
-
- total_qty = sum(self.mapped('qty'))
-
-Field values can also be accessed like dict items, which is more elegant and
-safer than ``getattr()`` for dynamic field names.
-Setting a field's value triggers an update to the database::
-
- >>> record.name
- Example Name
- >>> record.company_id.name
- Company Name
- >>> record.name = "Bob"
- >>> field = "name"
- >>> record[field]
- Bob
-
-.. warning::
-
- Trying to read a field on multiple records will raise an error for non relational
- fields.
-
-Accessing a relational field (:class:`~odoo.fields.Many2one`,
-:class:`~odoo.fields.One2many`, :class:`~odoo.fields.Many2many`)
-*always* returns a recordset, empty if the field is not set.
-
-Record cache and prefetching
-----------------------------
-
-Odoo maintains a cache for the fields of the records, so that not every field
-access issues a database request, which would be terrible for performance. The
-following example queries the database only for the first statement::
-
- record.name # first access reads value from database
- record.name # second access gets value from cache
-
-To avoid reading one field on one record at a time, Odoo *prefetches* records
-and fields following some heuristics to get good performance. Once a field must
-be read on a given record, the ORM actually reads that field on a larger
-recordset, and stores the returned values in cache for later use. The prefetched
-recordset is usually the recordset from which the record comes by iteration.
-Moreover, all simple stored fields (boolean, integer, float, char, text, date,
-datetime, selection, many2one) are fetched altogether; they correspond to the
-columns of the model's table, and are fetched efficiently in the same query.
-
-Consider the following example, where ``partners`` is a recordset of 1000
-records. Without prefetching, the loop would make 2000 queries to the database.
-With prefetching, only one query is made::
-
- for partner in partners:
- print partner.name # first pass prefetches 'name' and 'lang'
- # (and other fields) on all 'partners'
- print partner.lang
-
-The prefetching also works on *secondary records*: when relational fields are
-read, their values (which are records) are subscribed for future prefetching.
-Accessing one of those secondary records prefetches all secondary records from
-the same model. This makes the following example generate only two queries, one
-for partners and one for countries::
-
- countries = set()
- for partner in partners:
- country = partner.country_id # first pass prefetches all partners
- countries.add(country.name) # first pass prefetches all countries
-
-
-.. _reference/api/decorators:
-
-Method decorators
-=================
-
-.. automodule:: odoo.api
- :members: depends, depends_context, constrains, onchange, returns, autovacuum, model, model_create_multi
-
-.. .. currentmodule:: odoo.api
-
-.. .. autodata:: model
-.. .. autodata:: depends
-.. .. autodata:: constrains
-.. .. autodata:: onchange
-.. .. autodata:: returns
-.. .. autodata:: autovacuum
-
-.. todo:: With sphinx 2.0 : autodecorator
-
-.. todo:: Add in Views reference
- * It is possible to suppress the trigger from a specific field by adding
- ``on_change="0"`` in a view::
-
- <field name="name" on_change="0"/>
-
- will not trigger any interface update when the field is edited by the user,
- even if there are function fields or explicit onchange depending on that
- field.
-
-.. _reference/orm/environment:
-
-Environment
-===========
-
-The :class:`~odoo.api.Environment` stores various contextual data used by
-the ORM: the database cursor (for database queries), the current user
-(for access rights checking) and the current context (storing arbitrary
-metadata). The environment also stores caches.
-
-All recordsets have an environment, which is immutable, can be accessed
-using :attr:`~odoo.models.Model.env` and gives access to:
-
-* the current user (:attr:`~odoo.api.Environment.user`)
-* the cursor (:attr:`~odoo.api.Environment.cr`)
-* the superuser flag (:attr:`~odoo.api.Environment.su`)
-* or the context (:attr:`~odoo.api.Environment.context`)
-
-.. code-block:: bash
-
- >>> records.env
- <Environment object ...>
- >>> records.env.user
- res.user(3)
- >>> records.env.cr
- <Cursor object ...)
-
-When creating a recordset from an other recordset, the environment is
-inherited. The environment can be used to get an empty recordset in an
-other model, and query that model::
-
- >>> self.env['res.partner']
- res.partner()
- >>> self.env['res.partner'].search([['is_company', '=', True], ['customer', '=', True]])
- res.partner(7, 18, 12, 14, 17, 19, 8, 31, 26, 16, 13, 20, 30, 22, 29, 15, 23, 28, 74)
-
-.. currentmodule:: odoo.api
-
-.. automethod:: Environment.ref
-
-.. autoattribute:: Environment.lang
-
-.. autoattribute:: Environment.user
-
-.. autoattribute:: Environment.company
-
-.. autoattribute:: Environment.companies
-
-.. TODO cr, uid but not @property or methods of Environment class...
-
-Altering the environment
-------------------------
-
-.. currentmodule:: odoo.models
-
-.. automethod:: Model.with_context
-
-.. automethod:: Model.with_user
-
-.. automethod:: Model.with_company
-
-.. automethod:: Model.with_env
-
-.. automethod:: Model.sudo
-
-.. _reference/orm/sql:
-
-SQL Execution
--------------
-
-The :attr:`~odoo.api.Environment.cr` attribute on environments is the
-cursor for the current database transaction and allows executing SQL directly,
-either for queries which are difficult to express using the ORM (e.g. complex
-joins) or for performance reasons::
-
- self.env.cr.execute("some_sql", param1, param2, param3)
-
-Because models use the same cursor and the :class:`~odoo.api.Environment`
-holds various caches, these caches must be invalidated when *altering* the
-database in raw SQL, or further uses of models may become incoherent. It is
-necessary to clear caches when using ``CREATE``, ``UPDATE`` or ``DELETE`` in
-SQL, but not ``SELECT`` (which simply reads the database).
-
-.. note::
- Clearing caches can be performed using the
- :meth:`~odoo.models.Model.invalidate_cache` method.
-
-.. automethod:: Model.invalidate_cache
-
-.. warning::
- Executing raw SQL bypasses the ORM, and by consequent, Odoo security rules.
- Please make sure your queries are sanitized when using user input and prefer using
- ORM utilities if you don't really need to use SQL queries.
-
-
-.. _reference/orm/models/crud:
-
-Common ORM methods
-==================
-
-.. currentmodule:: odoo.models
-
-Create/update
--------------
-
-.. todo:: api.model_create_multi information
-
-.. automethod:: Model.create
-
-.. automethod:: Model.copy
-
-.. automethod:: Model.default_get
-
-.. automethod:: Model.name_create
-
-.. automethod:: Model.write
-
-.. automethod:: Model.flush
-
-Search/Read
------------
-
-.. automethod:: Model.browse
-
-.. automethod:: Model.search
-
-.. automethod:: Model.search_count
-
-.. automethod:: Model.name_search
-
-.. automethod:: Model.read
-
-.. automethod:: Model.read_group
-
-Fields/Views
-''''''''''''
-
-.. automethod:: Model.fields_get
-
-.. automethod:: Model.fields_view_get
-
-.. _reference/orm/domains:
-
-Search domains
-''''''''''''''
-
-A domain is a list of criteria, each criterion being a triple (either a
-``list`` or a ``tuple``) of ``(field_name, operator, value)`` where:
-
-* ``field_name`` (``str``)
- a field name of the current model, or a relationship traversal through
- a :class:`~odoo.fields.Many2one` using dot-notation e.g. ``'street'``
- or ``'partner_id.country'``
-
-* ``operator`` (``str``)
- an operator used to compare the ``field_name`` with the ``value``. Valid
- operators are:
-
- ``=``
- equals to
- ``!=``
- not equals to
- ``>``
- greater than
- ``>=``
- greater than or equal to
- ``<``
- less than
- ``<=``
- less than or equal to
- ``=?``
- unset or equals to (returns true if ``value`` is either ``None`` or
- ``False``, otherwise behaves like ``=``)
- ``=like``
- matches ``field_name`` against the ``value`` pattern. An underscore
- ``_`` in the pattern stands for (matches) any single character; a
- percent sign ``%`` matches any string of zero or more characters.
- ``like``
- matches ``field_name`` against the ``%value%`` pattern. Similar to
- ``=like`` but wraps ``value`` with '%' before matching
- ``not like``
- doesn't match against the ``%value%`` pattern
- ``ilike``
- case insensitive ``like``
- ``not ilike``
- case insensitive ``not like``
- ``=ilike``
- case insensitive ``=like``
- ``in``
- is equal to any of the items from ``value``, ``value`` should be a
- list of items
- ``not in``
- is unequal to all of the items from ``value``
- ``child_of``
- is a child (descendant) of a ``value`` record (value can be either
- one item or a list of items).
-
- Takes the semantics of the model into account (i.e following the
- relationship field named by
- :attr:`~odoo.models.Model._parent_name`).
- ``parent_of``
- is a parent (ascendant) of a ``value`` record (value can be either
- one item or a list of items).
-
- Takes the semantics of the model into account (i.e following the
- relationship field named by
- :attr:`~odoo.models.Model._parent_name`).
-
-* ``value``
- variable type, must be comparable (through ``operator``) to the named
- field.
-
-Domain criteria can be combined using logical operators in *prefix* form:
-
-``'&'``
- logical *AND*, default operation to combine criteria following one
- another. Arity 2 (uses the next 2 criteria or combinations).
-``'|'``
- logical *OR*, arity 2.
-``'!'``
- logical *NOT*, arity 1.
-
- .. note:: Mostly to negate combinations of criteria
- Individual criterion generally have a negative form (e.g. ``=`` ->
- ``!=``, ``<`` -> ``>=``) which is simpler than negating the positive.
-
-.. admonition:: Example
-
- To search for partners named *ABC*, from belgium or germany, whose language
- is not english::
-
- [('name','=','ABC'),
- ('language.code','!=','en_US'),
- '|',('country_id.code','=','be'),
- ('country_id.code','=','de')]
-
- This domain is interpreted as:
-
- .. code-block:: text
-
- (name is 'ABC')
- AND (language is NOT english)
- AND (country is Belgium OR Germany)
-
-Unlink
-------
-
-.. automethod:: Model.unlink
-
-.. _reference/orm/records/info:
-
-Record(set) information
------------------------
-
-.. autoattribute:: Model.ids
-
-.. attribute:: env
-
- Returns the environment of the given recordset.
-
- :type: :class:`~odoo.api.Environment`
-
-.. todo:: Environment documentation
-
-.. automethod:: Model.exists
-
-.. automethod:: Model.ensure_one
-
-.. automethod:: Model.name_get
-
-.. automethod:: Model.get_metadata
-
-.. _reference/orm/records/operations:
-
-Operations
-----------
-
-Recordsets are immutable, but sets of the same model can be combined using
-various set operations, returning new recordsets.
-
-.. addition preserves order but can introduce duplicates
-
-* ``record in set`` returns whether ``record`` (which must be a 1-element
- recordset) is present in ``set``. ``record not in set`` is the inverse
- operation
-* ``set1 <= set2`` and ``set1 < set2`` return whether ``set1`` is a subset
- of ``set2`` (resp. strict)
-* ``set1 >= set2`` and ``set1 > set2`` return whether ``set1`` is a superset
- of ``set2`` (resp. strict)
-* ``set1 | set2`` returns the union of the two recordsets, a new recordset
- containing all records present in either source
-* ``set1 & set2`` returns the intersection of two recordsets, a new recordset
- containing only records present in both sources
-* ``set1 - set2`` returns a new recordset containing only records of ``set1``
- which are *not* in ``set2``
-
-Recordsets are iterable so the usual Python tools are available for
-transformation (:func:`python:map`, :func:`python:sorted`,
-:func:`~python:itertools.ifilter`, ...) however these return either a
-:class:`python:list` or an :term:`python:iterator`, removing the ability to
-call methods on their result, or to use set operations.
-
-Recordsets therefore provide the following operations returning recordsets themselves
-(when possible):
-
-Filter
-''''''
-
-.. automethod:: Model.filtered
-
-.. automethod:: Model.filtered_domain
-
-Map
-'''
-
-.. automethod:: Model.mapped
-
-.. note::
-
- Since V13, multi-relational field access is supported and works like a mapped call:
-
- .. code-block:: python3
-
- records.partner_id # == records.mapped('partner_id')
- records.partner_id.bank_ids # == records.mapped('partner_id.bank_ids')
- records.partner_id.mapped('name') # == records.mapped('partner_id.name')
-
-Sort
-''''
-
-.. automethod:: Model.sorted
-
-.. _reference/orm/inheritance:
-
-Inheritance and extension
-=========================
-
-Odoo provides three different mechanisms to extend models in a modular way:
-
-* creating a new model from an existing one, adding new information to the
- copy but leaving the original module as-is
-* extending models defined in other modules in-place, replacing the previous
- version
-* delegating some of the model's fields to records it contains
-
-.. image:: ../images/inheritance_methods.png
- :align: center
-
-Classical inheritance
----------------------
-
-When using the :attr:`~odoo.models.Model._inherit` and
-:attr:`~odoo.models.Model._name` attributes together, Odoo creates a new
-model using the existing one (provided via
-:attr:`~odoo.models.Model._inherit`) as a base. The new model gets all the
-fields, methods and meta-information (defaults & al) from its base.
-
-.. literalinclude:: ../../odoo/addons/test_documentation_examples/inheritance.py
- :language: python
- :lines: 6-
-
-and using them:
-
-.. literalinclude:: ../../odoo/addons/test_documentation_examples/tests/test_inheritance.py
- :language: python
- :lines: 10,11,14,19
-
-will yield:
-
-.. literalinclude:: ../../odoo/addons/test_documentation_examples/tests/test_inheritance.py
- :language: text
- :lines: 16,21
-
-the second model has inherited from the first model's ``check`` method and its
-``name`` field, but overridden the ``call`` method, as when using standard
-:ref:`Python inheritance <python:tut-inheritance>`.
-
-Extension
----------
-
-When using :attr:`~odoo.models.Model._inherit` but leaving out
-:attr:`~odoo.models.Model._name`, the new model replaces the existing one,
-essentially extending it in-place. This is useful to add new fields or methods
-to existing models (created in other modules), or to customize or reconfigure
-them (e.g. to change their default sort order):
-
-.. literalinclude:: ../../odoo/addons/test_documentation_examples/extension.py
- :language: python
- :lines: 6-
-
-.. literalinclude:: ../../odoo/addons/test_documentation_examples/tests/test_extension.py
- :language: python
- :lines: 10,15
-
-will yield:
-
-.. literalinclude:: ../../odoo/addons/test_documentation_examples/tests/test_extension.py
- :language: text
- :lines: 13
-
-.. note::
-
- It will also yield the various :ref:`automatic fields
- <reference/fields/automatic>` unless they've been disabled
-
-Delegation
-----------
-
-The third inheritance mechanism provides more flexibility (it can be altered
-at runtime) but less power: using the :attr:`~odoo.models.Model._inherits`
-a model *delegates* the lookup of any field not found on the current model
-to "children" models. The delegation is performed via
-:class:`~odoo.fields.Reference` fields automatically set up on the parent
-model.
-
-The main difference is in the meaning. When using Delegation, the model
-**has one** instead of **is one**, turning the relationship in a composition
-instead of inheritance:
-
-.. literalinclude:: ../../odoo/addons/test_documentation_examples/delegation.py
- :language: python
- :lines: 5-
-
-.. literalinclude:: ../../odoo/addons/test_documentation_examples/tests/test_delegation.py
- :language: python
- :lines: 11-14,23,28
-
-will result in:
-
-.. literalinclude:: ../../odoo/addons/test_documentation_examples/tests/test_delegation.py
- :language: text
- :lines: 25,30
-
-and it's possible to write directly on the delegated field:
-
-.. literalinclude:: ../../odoo/addons/test_documentation_examples/tests/test_delegation.py
- :language: python
- :lines: 45
-
-.. warning:: when using delegation inheritance, methods are *not* inherited,
- only fields
-
-.. warning::
-
- * `_inherits` is more or less implemented, avoid it if you can;
- * chained `_inherits` is essentially not implemented, we cannot guarantee anything on the final behavior.
-
-
-Fields Incremental Definition
------------------------------
-
-A field is defined as class attribute on a model class. If the model
-is extended, one can also extend the field definition by redefining
-a field with the same name and same type on the subclass.
-In that case, the attributes of the field are taken from the parent class
-and overridden by the ones given in subclasses.
-
-For instance, the second class below only adds a tooltip on the field
-``state``::
-
- class First(models.Model):
- _name = 'foo'
- state = fields.Selection([...], required=True)
-
- class Second(models.Model):
- _inherit = 'foo'
- state = fields.Selection(help="Blah blah blah")
-
-.. _reference/exceptions:
-
-Error management
-================
-
-.. automodule:: odoo.exceptions
- :members: AccessDenied, AccessError, CacheMiss, MissingError, RedirectWarning, UserError, ValidationError
diff --git a/doc/reference/qweb.rst b/doc/reference/qweb.rst
deleted file mode 100644
index b224f46f2d4..00000000000
--- a/doc/reference/qweb.rst
+++ /dev/null
@@ -1,686 +0,0 @@
-:banner: banners/qweb.jpg
-
-.. highlight:: xml
-
-.. _reference/qweb:
-
-====
-QWeb
-====
-
-QWeb is the primary templating_ engine used by Odoo\ [#othertemplates]_. It
-is an XML templating engine\ [#genshif]_ and used mostly to generate HTML_
-fragments and pages.
-
-Template directives are specified as XML attributes prefixed with ``t-``,
-for instance ``t-if`` for :ref:`reference/qweb/conditionals`, with elements
-and other attributes being rendered directly.
-
-To avoid element rendering, a placeholder element ``<t>`` is also available,
-which executes its directive but doesn't generate any output in and of
-itself::
-
- <t t-if="condition">
- <p>Test</p>
- </t>
-
-will result in::
-
- <p>Test</p>
-
-if ``condition`` is true, but::
-
- <div t-if="condition">
- <p>Test</p>
- </div>
-
-will result in::
-
- <div>
- <p>Test</p>
- </div>
-
-.. _reference/qweb/output:
-
-Data output
-===========
-
-QWeb has a primary output directive which automatically HTML-escape its
-content limiting XSS_ risks when displaying user-provided content: ``esc``.
-
-``esc`` takes an expression, evaluates it and prints the content::
-
- <p><t t-esc="value"/></p>
-
-rendered with the value ``value`` set to ``42`` yields::
-
- <p>42</p>
-
-There is one other output directive ``raw`` which behaves the same as
-respectively ``esc`` but *does not HTML-escape its output*. It can be useful
-to display separately constructed markup (e.g. from functions) or already
-sanitized user-provided markup.
-
-.. _reference/qweb/conditionals:
-
-Conditionals
-============
-
-QWeb has a conditional directive ``if``, which evaluates an expression given
-as attribute value::
-
- <div>
- <t t-if="condition">
- <p>ok</p>
- </t>
- </div>
-
-The element is rendered if the condition is true::
-
- <div>
- <p>ok</p>
- </div>
-
-but if the condition is false it is removed from the result::
-
- <div>
- </div>
-
-The conditional rendering applies to the bearer of the directive, which does
-not have to be ``<t>``::
-
- <div>
- <p t-if="condition">ok</p>
- </div>
-
-will give the same results as the previous example.
-
-Extra conditional branching directives ``t-elif`` and ``t-else`` are also
-available::
-
- <div>
- <p t-if="user.birthday == today()">Happy birthday!</p>
- <p t-elif="user.login == 'root'">Welcome master!</p>
- <p t-else="">Welcome!</p>
- </div>
-
-
-.. _reference/qweb/loops:
-
-Loops
-=====
-
-QWeb has an iteration directive ``foreach`` which take an expression returning
-the collection to iterate on, and a second parameter ``t-as`` providing the
-name to use for the "current item" of the iteration::
-
- <t t-foreach="[1, 2, 3]" t-as="i">
- <p><t t-esc="i"/></p>
- </t>
-
-will be rendered as::
-
- <p>1</p>
- <p>2</p>
- <p>3</p>
-
-Like conditions, ``foreach`` applies to the element bearing the directive's
-attribute, and
-
-::
-
- <p t-foreach="[1, 2, 3]" t-as="i">
- <t t-esc="i"/>
- </p>
-
-is equivalent to the previous example.
-
-``foreach`` can iterate on an array (the current item will be the current
-value) or a mapping (the current item will be the current key). Iterating on an
-integer (equivalent to iterating on an array between 0 inclusive and the
-provided integer exclusive) is still supported but deprecated.
-
-In addition to the name passed via ``t-as``, ``foreach`` provides a few other
-variables for various data points:
-
-.. warning:: ``$as`` will be replaced by the name passed to ``t-as``
-
-:samp:`{$as}_all` (deprecated)
- the object being iterated over
-
- .. note:: This variable is only available on JavaScript QWeb, not Python.
-
-:samp:`{$as}_value`
- the current iteration value, identical to ``$as`` for lists and integers,
- but for mappings it provides the value (where ``$as`` provides the key)
-:samp:`{$as}_index`
- the current iteration index (the first item of the iteration has index 0)
-:samp:`{$as}_size`
- the size of the collection if it is available
-:samp:`{$as}_first`
- whether the current item is the first of the iteration (equivalent to
- :samp:`{$as}_index == 0`)
-:samp:`{$as}_last`
- whether the current item is the last of the iteration (equivalent to
- :samp:`{$as}_index + 1 == {$as}_size`), requires the iteratee's size be
- available
-:samp:`{$as}_parity` (deprecated)
- either ``"even"`` or ``"odd"``, the parity of the current iteration round
-:samp:`{$as}_even` (deprecated)
- a boolean flag indicating that the current iteration round is on an even
- index
-:samp:`{$as}_odd` (deprecated)
- a boolean flag indicating that the current iteration round is on an odd
- index
-
-These extra variables provided and all new variables created into the
-``foreach`` are only available in the scope of the``foreach``. If the
-variable exists outside the context of the ``foreach``, the value is copied
-at the end of the foreach into the global context.
-
-::
-
- <t t-set="existing_variable" t-value="False"/>
- <!-- existing_variable now False -->
-
- <p t-foreach="[1, 2, 3]" t-as="i">
- <t t-set="existing_variable" t-value="True"/>
- <t t-set="new_variable" t-value="True"/>
- <!-- existing_variable and new_variable now True -->
- </p>
-
- <!-- existing_variable always True -->
- <!-- new_variable undefined -->
-
-.. _reference/qweb/attributes:
-
-attributes
-==========
-
-QWeb can compute attributes on-the-fly and set the result of the computation
-on the output node. This is done via the ``t-att`` (attribute) directive which
-exists in 3 different forms:
-
-:samp:`t-att-{$name}`
- an attribute called ``$name`` is created, the attribute value is evaluated
- and the result is set as the attribute's value::
-
- <div t-att-a="42"/>
-
- will be rendered as::
-
- <div a="42"></div>
-:samp:`t-attf-{$name}`
- same as previous, but the parameter is a :term:`format string`
- instead of just an expression, often useful to mix literal and non-literal
- string (e.g. classes)::
-
- <t t-foreach="[1, 2, 3]" t-as="item">
- <li t-attf-class="row {{ (item_index % 2 === 0) ? 'even' : 'odd' }}">
- <t t-esc="item"/>
- </li>
- </t>
-
- will be rendered as::
-
- <li class="row even">1</li>
- <li class="row odd">2</li>
- <li class="row even">3</li>
-:samp:`t-att=mapping`
- if the parameter is a mapping, each (key, value) pair generates a new
- attribute and its value::
-
- <div t-att="{'a': 1, 'b': 2}"/>
-
- will be rendered as::
-
- <div a="1" b="2"></div>
-:samp:`t-att=pair`
- if the parameter is a pair (tuple or array of 2 element), the first
- item of the pair is the name of the attribute and the second item is the
- value::
-
- <div t-att="['a', 'b']"/>
-
- will be rendered as::
-
- <div a="b"></div>
-
-setting variables
-=================
-
-QWeb allows creating variables from within the template, to memoize a
-computation (to use it multiple times), give a piece of data a clearer name,
-...
-
-This is done via the ``set`` directive, which takes the name of the variable
-to create. The value to set can be provided in two ways:
-
-* a ``t-value`` attribute containing an expression, and the result of its
- evaluation will be set::
-
- <t t-set="foo" t-value="2 + 1"/>
- <t t-esc="foo"/>
-
- will print ``3``
-* if there is no ``t-value`` attribute, the node's body is rendered and set
- as the variable's value::
-
- <t t-set="foo">
- <li>ok</li>
- </t>
- <t t-esc="foo"/>
-
- will generate ``&lt;li&gt;ok&lt;/li&gt;`` (the content is escaped as we
- used the ``esc`` directive)
-
- .. note:: using the result of this operation is a significant use-case for
- the ``raw`` directive.
-
-calling sub-templates
-=====================
-
-QWeb templates can be used for top-level rendering, but they can also be used
-from within another template (to avoid duplication or give names to parts of
-templates) using the ``t-call`` directive::
-
- <t t-call="other-template"/>
-
-This calls the named template with the execution context of the parent, if
-``other_template`` is defined as::
-
- <p><t t-value="var"/></p>
-
-the call above will be rendered as ``<p/>`` (no content), but::
-
- <t t-set="var" t-value="1"/>
- <t t-call="other-template"/>
-
-will be rendered as ``<p>1</p>``.
-
-However this has the problem of being visible from outside the ``t-call``.
-Alternatively, content set in the body of the ``call`` directive will be
-evaluated *before* calling the sub-template, and can alter a local context::
-
- <t t-call="other-template">
- <t t-set="var" t-value="1"/>
- </t>
- <!-- "var" does not exist here -->
-
-The body of the ``call`` directive can be arbitrarily complex (not just
-``set`` directives), and its rendered form will be available within the called
-template as a magical ``0`` variable::
-
- <div>
- This template was called with content:
- <t t-raw="0"/>
- </div>
-
-being called thus::
-
- <t t-call="other-template">
- <em>content</em>
- </t>
-
-will result in::
-
- <div>
- This template was called with content:
- <em>content</em>
- </div>
-
-Python
-======
-
-Exclusive directives
---------------------
-
-Asset bundles
-'''''''''''''
-
-.. todo:: have fme write these up because I've no idea how they work
-
-"smart records" fields formatting
-'''''''''''''''''''''''''''''''''
-
-The ``t-field`` directive can only be used when performing field access
-(``a.b``) on a "smart" record (result of the ``browse`` method). It is able
-to automatically format based on field type, and is integrated in the
-website's rich text editing.
-
-``t-options`` can be used to customize fields, the most common option
-is ``widget``, other options are field- or widget-dependent.
-
-Debugging
----------
-
-``t-debug``
- invokes a debugger using PDB's ``set_trace`` API. The parameter should
- be the name of a module, on which a ``set_trace`` method is called::
-
- <t t-debug="pdb"/>
-
- is equivalent to ``importlib.import_module("pdb").set_trace()``
-
-Helpers
--------
-
-Request-based
-'''''''''''''
-
-Most Python-side uses of QWeb are in controllers (and during HTTP requests),
-in which case templates stored in the database (as
-:ref:`views <reference/views/qweb>`) can be trivially rendered by calling
-:meth:`odoo.http.HttpRequest.render`:
-
-.. code-block:: python
-
- response = http.request.render('my-template', {
- 'context_value': 42
- })
-
-This automatically creates a :class:`~odoo.http.Response` object which can
-be returned from the controller (or further customized to suit).
-
-View-based
-''''''''''
-
-At a deeper level than the previous helper is the ``render`` method on
-``ir.ui.view``:
-
-.. py:method:: render(cr, uid, id[, values][, engine='ir.qweb][, context])
-
- Renders a QWeb view/template by database id or :term:`external id`.
- Templates are automatically loaded from ``ir.ui.view`` records.
-
- Sets up a number of default values in the rendering context:
-
- ``request``
- the current :class:`~odoo.http.WebRequest` object, if any
- ``debug``
- whether the current request (if any) is in ``debug`` mode
- :func:`quote_plus <werkzeug.urls.url_quote_plus>`
- url-encoding utility function
- :mod:`json`
- the corresponding standard library module
- :mod:`time`
- the corresponding standard library module
- :mod:`datetime`
- the corresponding standard library module
- `relativedelta <https://labix.org/python-dateutil#head-ba5ffd4df8111d1b83fc194b97ebecf837add454>`_
- see module
- ``keep_query``
- the ``keep_query`` helper function
-
- :param values: context values to pass to QWeb for rendering
- :param str engine: name of the Odoo model to use for rendering, can be
- used to expand or customize QWeb locally (by creating
- a "new" qweb based on ``ir.qweb`` with alterations)
-
-.. _reference/qweb/javascript:
-
-.. todo:: the members below are no longer relevant, section to rewrite
-
-.. API
-.. ---
-
-.. It is also possible to use the ``ir.qweb`` model directly (and extend it, and
-.. inherit from it):
-
-.. .. automodule:: odoo.addons.base.ir.ir_qweb
-.. :members: QWeb, QWebContext, FieldConverter, QwebWidget
-
-Javascript
-==========
-
-Exclusive directives
---------------------
-
-Defining templates
-''''''''''''''''''
-
-The ``t-name`` directive can only be placed at the top-level of a template
-file (direct children to the document root)::
-
- <templates>
- <t t-name="template-name">
- <!-- template code -->
- </t>
- </templates>
-
-It takes no other parameter, but can be used with a ``<t>`` element or any
-other. With a ``<t>`` element, the ``<t>`` should have a single child.
-
-The template name is an arbitrary string, although when multiple templates
-are related (e.g. called sub-templates) it is customary to use dot-separated
-names to indicate hierarchical relationships.
-
-Template inheritance
-''''''''''''''''''''
-
-Template inheritance is used to either:
- - Alter existing templates in-place, e.g. to add information to templates
-created by other modules.
- - Create a new template from a given parent template
-
-Template inheritance is performed via the use of two directives:
- - ``t-inherit`` which is the name of the template to inherit from,
- - ``t-inherit-mode`` which is the behaviour of the inheritance: it can either be
- set to ``primary`` to create a new child template from the parented one or
- to ``extension`` to alter the parent template in place.
-
-An optional ``t-name`` directive can also be specified. It will be the name of
-the newly created template if used in primary mode, else it will be added as a
-comment on the transformed template to help retrace inheritances.
-
-For the inheritance itself, the changes are done using xpaths directives.
-See the XPATH_ documentation for the complete set of available instructions.
-
-Primary inheritance (child template)::
-
- <t t-name="child.template" t-inherit="base.template" t-inherit-mode="primary">
- <xpath expr="//ul" position="inside">
- <li>new element</li>
- </xpath>
- </t>
-
-Extension inheritance (in-place transformation)::
-
- <t t-inherit="base.template" t-inherit-mode="extension">
- <xpath expr="//tr[1]" position="after">
- <tr><td>new cell</td></tr>
- </xpath>
- </t>
-
-Old inheritance mechanism (deprecated)
-''''''''''''''''''''''''''''''''''''''
-
-Template inheritance is performed via the ``t-extend`` directive which takes
-the name of the template to alter as parameter.
-
-The directive ``t-extend`` will act as a primary inheritance when combined with
-``t-name`` and as an extension one when used alone.
-
-In both cases the alteration is then performed with any number of ``t-jquery``
-sub-directives::
-
- <t t-extend="base.template">
- <t t-jquery="ul" t-operation="append">
- <li>new element</li>
- </t>
- </t>
-
-The ``t-jquery`` directives takes a `CSS selector`_. This selector is used
-on the extended template to select *context nodes* to which the specified
-``t-operation`` is applied:
-
-``append``
- the node's body is appended at the end of the context node (after the
- context node's last child)
-``prepend``
- the node's body is prepended to the context node (inserted before the
- context node's first child)
-``before``
- the node's body is inserted right before the context node
-``after``
- the node's body is inserted right after the context node
-``inner``
- the node's body replaces the context node's children
-``replace``
- the node's body is used to replace the context node itself
-``attributes``
- the nodes's body should be any number of ``attribute`` elements,
- each with a ``name`` attribute and some textual content, the named
- attribute of the context node will be set to the specified value
- (either replaced if it already existed or added if not)
-No operation
- if no ``t-operation`` is specified, the template body is interpreted as
- javascript code and executed with the context node as ``this``
-
- .. warning:: while much more powerful than other operations, this mode is
- also much harder to debug and maintain, it is recommended to
- avoid it
-
-debugging
----------
-
-The javascript QWeb implementation provides a few debugging hooks:
-
-``t-log``
- takes an expression parameter, evaluates the expression during rendering
- and logs its result with ``console.log``::
-
- <t t-set="foo" t-value="42"/>
- <t t-log="foo"/>
-
- will print ``42`` to the console
-``t-debug``
- triggers a debugger breakpoint during template rendering::
-
- <t t-if="a_test">
- <t t-debug="">
- </t>
-
- will stop execution if debugging is active (exact condition depend on the
- browser and its development tools)
-``t-js``
- the node's body is javascript code executed during template rendering.
- Takes a ``context`` parameter, which is the name under which the rendering
- context will be available in the ``t-js``'s body::
-
- <t t-set="foo" t-value="42"/>
- <t t-js="ctx">
- console.log("Foo is", ctx.foo);
- </t>
-
-Helpers
--------
-
-.. js:attribute:: core.qweb
-
- (core is the ``web.core`` module) An instance of :js:class:`QWeb2.Engine` with all module-defined template
- files loaded, and references to standard helper objects ``_``
- (underscore), ``_t`` (translation function) and JSON_.
-
- :js:func:`core.qweb.render <QWeb2.Engine.render>` can be used to
- easily render basic module templates
-
-.. _reference/qweb/api:
-
-API
----
-
-.. js:class:: QWeb2.Engine
-
- The QWeb "renderer", handles most of QWeb's logic (loading,
- parsing, compiling and rendering templates).
-
- Odoo Web instantiates one for the user in the core module, and
- exports it to ``core.qweb``. It also loads all the template files
- of the various modules into that QWeb instance.
-
- A :js:class:`QWeb2.Engine` also serves as a "template namespace".
-
- .. js:function:: QWeb2.Engine.render(template[, context])
-
- Renders a previously loaded template to a String, using
- ``context`` (if provided) to find the variables accessed
- during template rendering (e.g. strings to display).
-
- :param String template: the name of the template to render
- :param Object context: the basic namespace to use for template
- rendering
- :returns: String
-
- The engine exposes an other method which may be useful in some
- cases (e.g. if you need a separate template namespace with, in
- Odoo Web, Kanban views get their own :js:class:`QWeb2.Engine`
- instance so their templates don't collide with more general
- "module" templates):
-
- .. js:function:: QWeb2.Engine.add_template(templates)
-
- Loads a template file (a collection of templates) in the QWeb
- instance. The templates can be specified as:
-
- An XML string
- QWeb will attempt to parse it to an XML document then load
- it.
-
- A URL
- QWeb will attempt to download the URL content, then load
- the resulting XML string.
-
- A ``Document`` or ``Node``
- QWeb will traverse the first level of the document (the
- child nodes of the provided root) and load any named
- template or template override.
-
- :type templates: String | Document | Node
-
- A :js:class:`QWeb2.Engine` also exposes various attributes for
- behavior customization:
-
- .. js:attribute:: QWeb2.Engine.prefix
-
- Prefix used to recognize directives during parsing. A string. By
- default, ``t``.
-
- .. js:attribute:: QWeb2.Engine.debug
-
- Boolean flag putting the engine in "debug mode". Normally,
- QWeb intercepts any error raised during template execution. In
- debug mode, it leaves all exceptions go through without
- intercepting them.
-
- .. js:attribute:: QWeb2.Engine.jQuery
-
- The jQuery instance used during template inheritance processing.
- Defaults to ``window.jQuery``.
-
- .. js:attribute:: QWeb2.Engine.preprocess_node
-
- A ``Function``. If present, called before compiling each DOM
- node to template code. In Odoo Web, this is used to
- automatically translate text content and some attributes in
- templates. Defaults to ``null``.
-
-.. [#genshif] it is similar in that to Genshi_, although it does not use (and
- has no support for) `XML namespaces`_
-
-.. [#othertemplates] although it uses a few others, either for historical
- reasons or because they remain better fits for the
- use case. Odoo 9.0 still depends on Jinja_ and Mako_.
-
-.. _templating:
- https://en.wikipedia.org/wiki/Template_processor
-
-.. _Jinja: http://jinja.pocoo.org
-.. _Mako: https://www.makotemplates.org
-.. _Genshi: https://genshi.edgewall.org
-.. _XML namespaces: https://en.wikipedia.org/wiki/XML_namespace
-.. _HTML: https://en.wikipedia.org/wiki/HTML
-.. _XSS: https://en.wikipedia.org/wiki/Cross-site_scripting
-.. _JSON: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON
-.. _CSS selector: https://api.jquery.com/category/selectors/
-.. _XPATH: https://developer.mozilla.org/en-US/docs/Web/XPath
diff --git a/doc/reference/reports.rst b/doc/reference/reports.rst
deleted file mode 100644
index 140f91024c1..00000000000
--- a/doc/reference/reports.rst
+++ /dev/null
@@ -1,326 +0,0 @@
-:banner: banners/reports.jpg
-
-.. highlight:: xml
-
-.. _reference/reports:
-
-.. _reference/reports/report:
-
-============
-QWeb Reports
-============
-
-Reports are written in HTML/QWeb, like website views in Odoo. You can use
-the usual :ref:`QWeb control flow tools <reference/qweb>`. The PDF rendering
-itself is performed by wkhtmltopdf_.
-
-Reports are declared using a :ref:`report action <reference/actions/report>`,
-and a :ref:`reference/reports/templates` for the action to use.
-
-If useful or necessary, it is possible to specify a
-:ref:`reference/reports/paper_formats` for the report report.
-
-.. _reference/reports/templates:
-
-Report template
-===============
-
-Report templates will always provide the following variables:
-
-``time``
- a reference to :mod:`python:time` from the Python standard library
-``user``
- ``res.user`` record for the user printing the report
-``res_company``
- record for the current ``user``'s company
-``website``
- the current website object, if any (this item can be present but ``None``)
-``web_base_url``
- the base url for the webserver
-``context_timestamp``
- a function taking :class:`python:datetime.datetime` in UTC\ [#unzoned]_ and
- converting it to the timezone of the user printing the report
-
-Minimal viable template
------------------------
-
-A minimal template would look like::
-
- <template id="report_invoice">
- <t t-call="web.html_container">
- <t t-foreach="docs" t-as="o">
- <t t-call="web.external_layout">
- <div class="page">
- <h2>Report title</h2>
- <p>This object's name is <span t-field="o.name"/></p>
- </div>
- </t>
- </t>
- </t>
- </template>
-
-Calling ``external_layout`` will add the default header and footer on your
-report. The PDF body will be the content inside the ``<div
-class="page">``. The template's ``id`` must be the name specified in the
-report declaration; for example ``account.report_invoice`` for the above
-report. Since this is a QWeb template, you can access all the fields of the
-``docs`` objects received by the template.
-
-By default, the rendering context will also expose the following items:
-
-``docs``
- records for the current report
-``doc_ids``
- list of ids for the ``docs`` records
-``doc_model``
- model for the ``docs`` records
-
-If you wish to access other records/models in the template, you will need
-:ref:`a custom report <reference/reports/custom_reports>`, however in that case
-you will have to provide the items above if you need them.
-
-Translatable Templates
-----------------------
-
-If you wish to translate reports (to the language of a partner, for example),
-you need to define two templates:
-
-* The main report template
-* The translatable document
-
-You can then call the translatable document from your main template with the attribute
-``t-lang`` set to a language code (for example ``fr`` or ``en_US``) or to a record field.
-You will also need to re-browse the related records with the proper context if you use
-fields that are translatable (like country names, sales conditions, etc.)
-
-.. warning::
-
- If your report template does not use translatable record fields, re-browsing the record
- in another language is *not* necessary and will impact performances.
-
-For example, let's look at the Sale Order report from the Sale module::
-
- <!-- Main template -->
- <template id="report_saleorder">
- <t t-call="web.html_container">
- <t t-foreach="docs" t-as="doc">
- <t t-call="sale.report_saleorder_document" t-lang="doc.partner_id.lang"/>
- </t>
- </t>
- </template>
-
- <!-- Translatable template -->
- <template id="report_saleorder_document">
- <!-- Re-browse of the record with the partner lang -->
- <t t-set="doc" t-value="doc.with_context(lang=doc.partner_id.lang)" />
- <t t-call="web.external_layout">
- <div class="page">
- <div class="oe_structure"/>
- <div class="row">
- <div class="col-6">
- <strong t-if="doc.partner_shipping_id == doc.partner_invoice_id">Invoice and shipping address:</strong>
- <strong t-if="doc.partner_shipping_id != doc.partner_invoice_id">Invoice address:</strong>
- <div t-field="doc.partner_invoice_id" t-options="{&quot;no_marker&quot;: True}"/>
- <...>
- <div class="oe_structure"/>
- </div>
- </t>
- </template>
-
-
-The main template calls the translatable template with ``doc.partner_id.lang`` as a
-``t-lang`` parameter, so it will be rendered in the language of the partner. This way,
-each Sale Order will be printed in the language of the corresponding customer. If you wish
-to translate only the body of the document, but keep the header and footer in a default
-language, you could call the report's external layout this way::
-
- <t t-call="web.external_layout" t-lang="en_US">
-
-.. tip::
-
- Please take note that this works only when calling external templates, you will not be
- able to translate part of a document by setting a ``t-lang`` attribute on an xml node other
- than ``t-call``. If you wish to translate part of a template, you can create an external
- template with this partial template and call it from the main one with the ``t-lang``
- attribute.
-
-
-Barcodes
---------
-
-Barcodes are images returned by a controller and can easily be embedded in
-reports thanks to the QWeb syntax (e.g. see :ref:`reference/qweb/attributes`):
-
-.. code-block:: html
-
- <img t-att-src="'/report/barcode/QR/%s' % 'My text in qr code'"/>
-
-More parameters can be passed as a query string
-
-.. code-block:: html
-
- <img t-att-src="'/report/barcode/?
- type=%s&amp;value=%s&amp;width=%s&amp;height=%s'%('QR', 'text', 200, 200)"/>
-
-
-Useful Remarks
---------------
-* Twitter Bootstrap and FontAwesome classes can be used in your report
- template
-* Local CSS can be put directly in the template
-* Global CSS can be inserted in the main report layout by inheriting its
- template and inserting your CSS::
-
- <template id="report_saleorder_style" inherit_id="report.style">
- <xpath expr=".">
- <t>
- .example-css-class {
- background-color: red;
- }
- </t>
- </xpath>
- </template>
-
-* If it appears that your PDF report is missing the styles, please check
- :ref:`these instructions <reference/backend/reporting/printed-reports/pdf-without-styles>`.
-
-.. _reference/reports/paper_formats:
-
-Paper Format
-============
-
-Paper formats are records of ``report.paperformat`` and can contain the
-following attributes:
-
-``name`` (mandatory)
- only useful as a mnemonic/description of the report when looking for one
- in a list of some sort
-``description``
- a small description of your format
-``format``
- either a predefined format (A0 to A9, B0 to B10, Legal, Letter,
- Tabloid,...) or ``custom``; A4 by default. You cannot use a non-custom
- format if you define the page dimensions.
-``dpi``
- output DPI; 90 by default
-``margin_top``, ``margin_bottom``, ``margin_left``, ``margin_right``
- margin sizes in mm
-``page_height``, ``page_width``
- page dimensions in mm
-``orientation``
- Landscape or Portrait
-``header_line``
- boolean to display a header line
-``header_spacing``
- header spacing in mm
-
-Example::
-
- <record id="paperformat_frenchcheck" model="report.paperformat">
- <field name="name">French Bank Check</field>
- <field name="default" eval="True"/>
- <field name="format">custom</field>
- <field name="page_height">80</field>
- <field name="page_width">175</field>
- <field name="orientation">Portrait</field>
- <field name="margin_top">3</field>
- <field name="margin_bottom">3</field>
- <field name="margin_left">3</field>
- <field name="margin_right">3</field>
- <field name="header_line" eval="False"/>
- <field name="header_spacing">3</field>
- <field name="dpi">80</field>
- </record>
-
-.. _reference/reports/custom_reports:
-
-Custom Reports
-==============
-
-By default, the reporting system builds rendering values based on the target
-model specified through the ``model`` field.
-
-However, it will first look for a model named
-:samp:`report.{module.report_name}` and call that model's
-``_get_report_values(doc_ids, data)`` in order to prepare the rendering data for
-the template.
-
-This can be used to include arbitrary items to use or display while rendering
-the template, such as data from additional models:
-
-.. code-block:: python
-
- from odoo import api, models
-
- class ParticularReport(models.AbstractModel):
- _name = 'report.module.report_name'
-
- def _get_report_values(self, docids, data=None):
- # get the report action back as we will need its data
- report = self.env['ir.actions.report']._get_report_from_name('module.report_name')
- # get the records selected for this rendering of the report
- obj = self.env[report.model].browse(docids)
- # return a custom rendering context
- return {
- 'lines': docids.get_lines()
- }
-
-.. warning::
-
- When using a custom report, the "default" document-related items
- (``doc_ids``, ``doc_model`` and ``docs``) will *not* be included. If you
- want them, you will need to include them yourself.
-
- In the example above, the rendering context will contain the "global" values
- as well as the ``lines`` we put in there but nothing else.
-
-.. _reference/reports/custom_fonts:
-
-Custom fonts
-============
-If you want to use custom fonts you will need to add your custom font and the related less/CSS to the ``web.reports_assets_common`` assets bundle.
-Adding your custom font(s) to ``web.assets_common`` or ``web.assets_backend`` will not make your font available in QWeb reports.
-
-Example::
-
- <template id="report_assets_common_custom_fonts" name="Custom QWeb fonts" inherit_id="web.report_assets_common">
- <xpath expr="." position="inside">
- <link href="/your_module/static/src/less/fonts.less" rel="stylesheet" type="text/less"/>
- </xpath>
- </template>
-
-You will need to define your ``@font-face`` within this less file, even if you've used in another assets bundle (other than ``web.reports_assets_common``).
-
-Example::
-
- @font-face {
- font-family: 'MonixBold';
- src: local('MonixBold'), local('MonixBold'), url(/your_module/static/src/fonts/MonixBold-Regular.otf) format('opentype');
- }
-
- .h1-title-big {
- font-family: MonixBold;
- font-size: 60px;
- color: #3399cc;
- }
-
-After you've added the less into your assets bundle you can use the classes - in this example ``h1-title-big`` - in your custom QWeb report.
-
-Reports are web pages
-=====================
-
-Reports are dynamically generated by the report module and can be accessed
-directly via URL:
-
-For example, you can access a Sale Order report in html mode by going to
-\http://<server-address>/report/html/sale.report_saleorder/38
-
-Or you can access the pdf version at
-\http://<server-address>/report/pdf/sale.report_saleorder/38
-
-.. [#unzoned] it does not matter what timezone the :class:`python:datetime`
- object is actually in (including no timezone), its timezone will
- unconditionally be *set* to UTC before being adjusted to the
- user's
-
-.. _wkhtmltopdf: https://wkhtmltopdf.org
diff --git a/doc/reference/security.rst b/doc/reference/security.rst
deleted file mode 100644
index 7c235b08338..00000000000
--- a/doc/reference/security.rst
+++ /dev/null
@@ -1,389 +0,0 @@
-:banner: banners/security.jpg
-
-.. _reference/security:
-
-================
-Security in Odoo
-================
-
-Aside from manually managing access using custom code, Odoo provides two main
-data-driven mechanisms to manage or restrict access to data.
-
-Both mechanisms are linked to specific users through *groups*: a user belongs
-to any number of groups, and security mechanisms are associated to groups,
-thus applying security mechamisms to users.
-
-.. _reference/security/acl:
-
-Access Control
-==============
-
-Managed by the ``ir.model.access`` records, defines access to a whole model.
-
-Each access control has a model to which it grants permissions, the
-permissions it grants and optionally a group.
-
-Access controls are additive, for a given model a user has access all
-permissions granted to any of its groups: if the user belongs to one group
-which allows writing and another which allows deleting, they can both write
-and delete.
-
-If no group is specified, the access control applies to all users, otherwise
-it only applies to the members of the given group.
-
-Available permissions are creation (``perm_create``), searching and reading
-(``perm_read``), updating existing records (``perm_write``) and deleting
-existing records (``perm_unlink``)
-
-.. _reference/security/rules:
-
-Record Rules
-============
-
-Record rules are conditions that records must satisfy for an operation
-(create, read, update or delete) to be allowed. It is applied record-by-record
-after access control has been applied.
-
-A record rule has:
-
-* a model on which it applies
-* a set of permissions to which it applies (e.g. if ``perm_read`` is set, the
- rule will only be checked when reading a record)
-* a set of user groups to which the rule applies, if no group is specified
- the rule is *global*
-* a :ref:`domain <reference/orm/domains>` used to check whether a given record
- matches the rule (and is accessible) or does not (and is not accessible).
- The domain is evaluated with two variables in context: ``user`` is the
- current user's record and ``time`` is the `time module`_
-
-Global rules and group rules (rules restricted to specific groups versus
-groups applying to all users) are used quite differently:
-
-* Global rules are subtractive, they *must all* be matched for a record to be
- accessible
-* Group rules are additive, if *any* of them matches (and all global rules
- match) then the record is accessible
-
-This means the first *group rule* restricts access, but any further
-*group rule* expands it, while *global rules* can only ever restrict access
-(or have no effect).
-
-.. warning:: record rules do not apply to the Superuser account
- :class: aphorism
-
-.. _reference/security/fields:
-
-Field Access
-============
-
-An ORM :class:`~odoo.fields.Field` can have a ``groups`` attribute
-providing a list of groups (as a comma-separated string of
-:term:`external identifiers`).
-
-If the current user is not in one of the listed groups, he will not have
-access to the field:
-
-* restricted fields are automatically removed from requested views
-* restricted fields are removed from :meth:`~odoo.models.Model.fields_get`
- responses
-* attempts to (explicitly) read from or write to restricted fields results in
- an access error
-
-.. todo::
-
- field access groups apply to the Superuser in fields_get but not in
- read/write...
-
-.. _time module: https://docs.python.org/3/library/time.html
-
-
-.. _reference/security/pitfalls:
-
-Security Pitfalls
-=================
-
-As a developer, it is important to understand the security mechanisms and avoid
-common mistakes leading to insecure code.
-
-Unsafe Public Methods
----------------------
-
-Any public method can be executed via a :ref:`RPC call
-<webservices/odoo/calling_methods>` with the chosen parameters. The methods
-starting with a ``_`` are not callable from an action button or external API.
-
-On public methods, the record on which a method is executed and the parameters
-can not be trusted, ACL being only verified during CRUD operations.
-
-.. code-block:: python
-
- # this method is public and its arguments can not be trusted
- def action_done(self):
- if self.state == "draft" and self.user_has_groups('base.manager'):
- self._set_state("done")
-
- # this method is private and can only be called from other python methods
- def _set_state(self, new_state):
- self.sudo().write({"state": new_state})
-
-Making a method private is obviously not enough and care must be taken to use it
-properly.
-
-Bypassing the ORM
------------------
-You should never use the database cursor directly when the ORM can do the same
-thing! By doing so you are bypassing all the ORM features, possibly the
-automated behaviours like translations, invalidation of fields, ``active``,
-access rights and so on.
-
-And chances are that you are also making the code harder to read and probably
-less secure.
-
-.. code-block:: python
-
- # very very wrong
- self.env.cr.execute('SELECT id FROM auction_lots WHERE auction_id in (' + ','.join(map(str, ids))+') AND state=%s AND obj_price > 0', ('draft',))
- auction_lots_ids = [x[0] for x in self.env.cr.fetchall()]
-
- # no injection, but still wrong
- self.env.cr.execute('SELECT id FROM auction_lots WHERE auction_id in %s '\
- 'AND state=%s AND obj_price > 0', (tuple(ids), 'draft',))
- auction_lots_ids = [x[0] for x in self.env.cr.fetchall()]
-
- # better
- auction_lots_ids = self.search([('auction_id','in',ids), ('state','=','draft'), ('obj_price','>',0)])
-
-
-SQL injections
-~~~~~~~~~~~~~~
-Care must be taken not to introduce SQL injections vulnerabilities when using
-manual SQL queries. The vulnerability is present when user input is either
-incorrectly filtered or badly quoted, allowing an attacker to introduce
-undesirable clauses to a SQL query (such as circumventing filters or
-executing ``UPDATE`` or ``DELETE`` commands).
-
-The best way to be safe is to never, NEVER use Python string concatenation (+)
-or string parameters interpolation (%) to pass variables to a SQL query string.
-
-The second reason, which is almost as important, is that it is the job of the
-database abstraction layer (psycopg2) to decide how to format query parameters,
-not your job! For example psycopg2 knows that when you pass a list of values
-it needs to format them as a comma-separated list, enclosed in parentheses !
-
-.. code-block:: python
-
- # the following is very bad:
- # - it's a SQL injection vulnerability
- # - it's unreadable
- # - it's not your job to format the list of ids
- self.env.cr.execute('SELECT distinct child_id FROM account_account_consol_rel ' +
- 'WHERE parent_id IN ('+','.join(map(str, ids))+')')
-
- # better
- self.env.cr.execute('SELECT DISTINCT child_id '\
- 'FROM account_account_consol_rel '\
- 'WHERE parent_id IN %s',
- (tuple(ids),))
-
-This is very important, so please be careful also when refactoring, and most
-importantly do not copy these patterns!
-
-Here is a memorable example to help you remember what the issue is about (but
-do not copy the code there). Before continuing, please be sure to read the
-online documentation of pyscopg2 to learn of to use it properly:
-
-- `The problem with query parameters <http://initd.org/psycopg/docs/usage.html#the-problem-with-the-query-parameters>`_
-- `How to pass parameters with psycopg2 <http://initd.org/psycopg/docs/usage.html#passing-parameters-to-sql-queries>`_
-- `Advanced parameter types <http://initd.org/psycopg/docs/usage.html#adaptation-of-python-values-to-sql-types>`_
-- `Psycopg documentation <https://www.psycopg.org/docs/sql.html>`_
-
-Unescaped field content
------------------------
-
-When rendering content using JavaScript and XML, one may be tempted to use
-a ``t-raw`` to display rich-text content. This should be avoided as a frequent
-`XSS <https://en.wikipedia.org/wiki/Cross-site_scripting>`_ vector.
-
-It is very hard to control the integrity of the data from the computation until
-the final integration in the browser DOM. A ``t-raw`` that is correctly escaped
-at the time of introduction may no longer be safe at the next bugfix or
-refactoring.
-
-.. code-block:: javascript
-
- QWeb.render('insecure_template', {
- info_message: "You have an <strong>important</strong> notification",
- })
-
-.. code-block:: xml
-
- <div t-name="insecure_template">
- <div id="information-bar"><t t-raw="info_message" /></div>
- </div>
-
-The above code may feel safe as the message content is controlled but is a bad
-practice that may lead to unexpected security vulnerabilities once this code
-evolves in the future.
-
-.. code-block:: javascript
-
- // XSS possible with unescaped user provided content !
- QWeb.render('insecure_template', {
- info_message: "You have an <strong>important</strong> notification on " \
- + "the product <strong>" + product.name + "</strong>",
- })
-
-While formatting the template differently would prevent such vulnerabilities.
-
-.. code-block:: javascript
-
- QWeb.render('secure_template', {
- message: "You have an important notification on the product:",
- subject: product.name
- })
-
-.. code-block:: xml
-
- <div t-name="secure_template">
- <div id="information-bar">
- <div class="info"><t t-esc="message" /></div>
- <div class="subject"><t t-esc="subject" /></div>
- </div>
- </div>
-
-.. code-block:: css
-
- .subject {
- font-weight: bold;
- }
-
-Escaping vs Sanitizing
-----------------------
-
-.. important::
-
- Escaping is always 100% mandatory when you mix data and code, no matter how
- safe the data
-
-**Escaping** converts *TEXT* to *CODE*. It is absolutely mandatory to do it
-every time you mix *DATA/TEXT* with *CODE* (e.g. generating HTML or python code
-to be evaluated inside a `safe_eval`), because *CODE* always requires *TEXT* to
-be encoded. It is critical for security, but it's also a question of
-correctness. Even when there is no security risk (because the text is 100%
-guarantee to be safe or trusted), it is still required (e.g. to avoid breaking
-the layout in generated HTML).
-
-Escaping will never break any feature, as long as the developer identifies which
-variable contains *TEXT* and which contains *CODE*.
-
-.. code-block:: python
-
- >>> from odoo.tools import html_escape, html_sanitize
- >>> data = "<R&D>" # `data` is some TEXT coming from somewhere
-
- # Escaping turns it into CODE, good!
- >>> code = html_escape(data)
- >>> code
- '&lt;R&amp;D&gt;'
-
- # Now you can mix it with other code...
- >>> self.message_post(body="<strong>%s</strong>" % code)
-
-**Sanitizing** converts *CODE* to *SAFER CODE* (but not necessary *safe* code).
-It does not work on *TEXT*. Sanitizing is only necessary when *CODE* is
-untrusted, because it comes in full or in part from some user-provided data. If
-the user-provided data is in the form of *TEXT* (e.g. the content from a form
-filled by a user), and if that data was correctly escaped before putting it in
-*CODE*, then sanitizing is useless (but can still be done). If however, the
-user-provided data was **not escaped**, then sanitizing will **not** work as
-expected.
-
-.. code-block:: python
-
- # Sanitizing without escaping is BROKEN: data is corrupted!
- >>> html_sanitize(data)
- ''
-
- # Sanitizing *after* escaping is OK!
- >>> html_sanitize(code)
- '<p>&lt;R&amp;D&gt;</p>'
-
-Sanitizing can break features, depending on whether the *CODE* is expected to
-contain patterns that are not safe. That's why `fields.Html` and
-`tools.html_sanitize()` have options to fine-tune the level of sanitization for
-styles, etc. Those options have to be carefully considered depending on where
-the data comes from, and the desired features. The sanitization safety is
-balanced against sanitization breakages: the safer the sanitisation the more
-likely it is to break things.
-
-.. code-block:: python
-
- >>code = "<p class='text-warning'>Important Information</p>"
- # this will remove the style, which may break features
- # but is necessary if the source is untrusted
- >> html_sanitize(code, strip_classes=True)
- '<p>Important Information</p>'
-
-Evaluating content
-------------------
-Some may want to ``eval`` to parse user provided content. Using ``eval`` should
-be avoided at all cost. A safer, sandboxed, method :class:`~odoo.tools.safe_eval`
-can be used instead but still gives tremendous capabilities to the user running
-it and must be reserved for trusted privileged users only as it breaks the
-barrier between code and data.
-
-.. code-block:: python
-
- # very bad
- domain = eval(self.filter_domain)
- return self.search(domain)
-
- # better but still not recommended
- from odoo.tools import safe_eval
- domain = safe_eval(self.filter_domain)
- return self.search(domain)
-
- # good
- from ast import literal_eval
- domain = literal_eval(self.filter_domain)
- return self.search(domain)
-
-Parsing content does not need ``eval``
-
-========== ================== ================================
-Language Data type Suitable parser
-========== ================== ================================
-Python int, float, etc. int(), float()
-Javascript int, float, etc. parseInt(), parseFloat()
-Python dict json.loads(), ast.literal_eval()
-Javascript object, list, etc. JSON.parse()
-========== ================== ================================
-
-Accessing object attributes
----------------------------
-
-If the values of a record needs to be retrieved or modified dynamically, one may
-want to use the ``getattr`` and ``setattr`` methods.
-
-.. code-block:: python
-
- # unsafe retrieval of a field value
- def _get_state_value(self, res_id, state_field):
- record = self.sudo().browse(res_id)
- return getattr(record, state_field, False)
-
-This code is however not safe as it allows to access any property of the record,
-including private attributes or methods.
-
-The ``__getitem__`` of a recordset has been defined and accessing a dynamic
-field value can be easily achieved safely:
-
-.. code-block:: python
-
- # better retrieval of a field value
- def _get_state_value(self, res_id, state_field):
- record = self.sudo().browse(res_id)
- return record[state_field]
-
-The above method is obviously still too optimistic and additional verifications
-on the record id and field value must be done.
diff --git a/doc/reference/static/res.country.state.csv b/doc/reference/static/res.country.state.csv
deleted file mode 100644
index b1960d9a4c5..00000000000
--- a/doc/reference/static/res.country.state.csv
+++ /dev/null
@@ -1,15 +0,0 @@
-"id","country_id:id","name","code"
-state_au_1,au,"Australian Capital Territory","ACT"
-state_au_2,au,"New South Wales","NSW"
-state_au_3,au,"Northern Territory","NT"
-state_au_4,au,"Queensland","QLD"
-state_au_5,au,"South Australia","SA"
-state_au_6,au,"Tasmania","TAS"
-state_au_7,au,"Victoria","VIC"
-state_au_8,au,"Western Australia","WA"
-state_us_1,us,"Alabama","AL"
-state_us_2,us,"Alaska","AK"
-state_us_3,us,"Arizona","AZ"
-state_us_4,us,"Arkansas","AR"
-state_us_5,us,"California","CA"
-state_us_6,us,"Colorado","CO"
diff --git a/doc/reference/testing.rst b/doc/reference/testing.rst
deleted file mode 100644
index dc0b9e1823a..00000000000
--- a/doc/reference/testing.rst
+++ /dev/null
@@ -1,638 +0,0 @@
-:banner: banners/testing_modules.jpg
-
-.. _reference/testing:
-
-
-===============
-Testing Odoo
-===============
-
-There are many ways to test an application. In Odoo, we have three kinds of
-tests
-
-- Python unit tests (see `Testing Python code`_): useful for testing model business logic
-- JS unit tests (see `Testing JS code`_): useful to test the javascript code in isolation
-- Tours (see `Integration Testing`_): tours simulate a real situation. They ensures that the
- python and the javascript parts properly talk to each other.
-
-Testing Python code
-===================
-
-Odoo provides support for testing modules using unittest.
-
-To write tests, simply define a ``tests`` sub-package in your module, it will
-be automatically inspected for test modules. Test modules should have a name
-starting with ``test_`` and should be imported from ``tests/__init__.py``,
-e.g.
-
-.. code-block:: text
-
- your_module
- |-- ...
- `-- tests
- |-- __init__.py
- |-- test_bar.py
- `-- test_foo.py
-
-and ``__init__.py`` contains::
-
- from . import test_foo, test_bar
-
-.. warning::
-
- test modules which are not imported from ``tests/__init__.py`` will not be
- run
-
-The test runner will simply run any test case, as described in the official
-`unittest documentation`_, but Odoo provides a number of utilities and helpers
-related to testing Odoo content (modules, mainly):
-
-.. autoclass:: odoo.tests.common.TransactionCase
- :members: browse_ref, ref
-
-.. autoclass:: odoo.tests.common.SingleTransactionCase
- :members: browse_ref, ref
-
-.. autoclass:: odoo.tests.common.SavepointCase
-
-.. autoclass:: odoo.tests.common.HttpCase
- :members: browse_ref, ref, url_open, browser_js
-
-.. autofunction:: odoo.tests.common.tagged
-
-By default, tests are run once right after the corresponding module has been
-installed. Test cases can also be configured to run after all modules have
-been installed, and not run right after the module installation::
-
- # coding: utf-8
- from odoo.tests import HttpCase, tagged
-
- # This test should only be executed after all modules have been installed.
- @tagged('-at_install', 'post_install')
- class WebsiteVisitorTests(HttpCase):
- def test_create_visitor_on_tracked_page(self):
- Page = self.env['website.page']
-
-The most common situation is to use
-:class:`~odoo.tests.common.TransactionCase` and test a property of a model
-in each method::
-
- class TestModelA(common.TransactionCase):
- def test_some_action(self):
- record = self.env['model.a'].create({'field': 'value'})
- record.some_action()
- self.assertEqual(
- record.field,
- expected_field_value)
-
- # other tests...
-
-.. note::
-
- Test methods must start with ``test_``
-
-.. autoclass:: odoo.tests.common.Form
- :members:
-
-.. autoclass:: odoo.tests.common.M2MProxy
- :members: add, remove, clear
-
-.. autoclass:: odoo.tests.common.O2MProxy
- :members: new, edit, remove
-
-Running tests
--------------
-
-Tests are automatically run when installing or updating modules if
-:option:`--test-enable <odoo-bin --test-enable>` was enabled when starting the
-Odoo server.
-
-.. _unittest documentation: https://docs.python.org/3/library/unittest.html
-
-Test selection
---------------
-
-In Odoo, Python tests can be tagged to facilitate the test selection when
-running tests.
-
-Subclasses of :class:`odoo.tests.common.BaseCase` (usually through
-:class:`~odoo.tests.common.TransactionCase`,
-:class:`~odoo.tests.common.SavepointCase` or
-:class:`~odoo.tests.common.HttpCase`) are automatically tagged with
-``standard``, ``at_install`` and their source module's name by default.
-
-Invocation
-^^^^^^^^^^
-
-:option:`--test-tags <odoo-bin --test-tags>` can be used to select/filter tests
-to run on the command-line.
-
-This option defaults to ``+standard`` meaning tests tagged ``standard``
-(explicitly or implicitly) will be run by default when starting Odoo
-with :option:`--test-enable <odoo-bin --test-enable>`.
-
-When writing tests, the :func:`~odoo.tests.common.tagged` decorator can be
-used on **test classes** to add or remove tags.
-
-The decorator's arguments are tag names, as strings.
-
-.. danger:: :func:`~odoo.tests.common.tagged` is a class decorator, it has no
- effect on functions or methods
-
-Tags can be prefixed with the minus (``-``) sign, to *remove* them instead of
-add or select them e.g. if you don't want your test to be executed by
-default you can remove the ``standard`` tag:
-
-.. code-block:: python
-
- from odoo.tests import TransactionCase, tagged
-
- @tagged('-standard', 'nice')
- class NiceTest(TransactionCase):
- ...
-
-This test will not be selected by default, to run it the relevant tag will
-have to be selected explicitely:
-
-.. code-block:: console
-
- $ odoo-bin --test-enable --test-tags nice
-
-Note that only the tests tagged ``nice`` are going to be executed. To run
-*both* ``nice`` and ``standard`` tests, provide multiple values to
-:option:`--test-tags <odoo-bin --test-tags>`: on the command-line, values
-are *additive* (you're selecting all tests with *any* of the specified tags)
-
-.. code-block:: console
-
- $ odoo-bin --test-enable --test-tags nice,standard
-
-The config switch parameter also accepts the ``+`` and ``-`` prefixes. The
-``+`` prefix is implied and therefore, totaly optional. The ``-`` (minus)
-prefix is made to deselect tests tagged with the prefixed tags, even if they
-are selected by other specified tags e.g. if there are ``standard`` tests which
-are also tagged as ``slow`` you can run all standard tests *except* the slow
-ones:
-
-.. code-block:: console
-
- $ odoo-bin --test-enable --test-tags 'standard,-slow'
-
-When you write a test that does not inherit from the
-:class:`~odoo.tests.common.BaseCase`, this test will not have the default tags,
-you have to add them explicitely to have the test included in the default test
-suite. This is a common issue when using a simple ``unittest.TestCase`` as
-they're not going to get run:
-
-.. code-block:: python
-
- import unittest
- from odoo.tests import tagged
-
- @tagged('standard', 'at_install')
- class SmallTest(unittest.TestCase):
- ...
-
-Special tags
-^^^^^^^^^^^^
-
-- ``standard``: All Odoo tests that inherit from
- :class:`~odoo.tests.common.BaseCase` are implicitely tagged standard.
- :option:`--test-tags <odoo-bin --test-tags>` also defaults to ``standard``.
-
- That means untagged test will be executed by default when tests are enabled.
-- ``at_install``: Means that the test will be executed right after the module
- installation and before other modules are installed. This is a default
- implicit tag.
-- ``post_install``: Means that the test will be executed after all the modules
- are installed. This is what you want for HttpCase tests most of the time.
-
- Note that this is *not exclusive* with ``at_install``, however since you
- will generally not want both ``post_install`` is usually paired with
- ``-at_install`` when tagging a test class.
-- *module_name*: Odoo tests classes extending
- :class:`~odoo.tests.common.BaseCase` are implicitely tagged with the
- technical name of their module. This allows easily selecting or excluding
- specific modules when testing e.g. if you want to only run tests from
- ``stock_account``:
-
- .. code-block:: console
-
- $ odoo-bin --test-enable --test-tags stock_account
-
-Examples
-^^^^^^^^
-
-.. important::
-
- Tests will be executed only in the installed or updated modules. So
- modules have to be selected with the :option:`-u <odoo-bin -u>` or
- :option:`-i <odoo-bin -i>` switches. For simplicity, those switches are
- not specified in the examples below.
-
-Run only the tests from the sale module:
-
-.. code-block:: console
-
- $ odoo-bin --test-enable --test-tags sale
-
-Run the tests from the sale module but not the ones tagged as slow:
-
-.. code-block:: console
-
- $ odoo-bin --test-enable --test-tags 'sale,-slow'
-
-Run only the tests from stock or tagged as slow:
-
-.. code-block:: console
-
- $ odoo-bin --test-enable --test-tags '-standard, slow, stock'
-
-.. note:: ``-standard`` is implicit (not required), and present for clarity
-
-Testing JS code
-===============
-
-Testing a complex system is an important safeguard to prevent regressions and to
-guarantee that some basic functionality still works. Since Odoo has a non trivial
-codebase in Javascript, it is necessary to test it. In this section, we will
-discuss the practice of testing JS code in isolation: these tests stay in the
-browser, and are not supposed to reach the server.
-
-Qunit test suite
-----------------
-
-The Odoo framework uses the QUnit_ library testing framework as a test runner.
-QUnit defines the concepts of *tests* and *modules* (a set of related tests),
-and gives us a web based interface to execute the tests.
-
-For example, here is what a pyUtils test could look like:
-
-.. code-block:: javascript
-
- QUnit.module('py_utils');
-
- QUnit.test('simple arithmetic', function (assert) {
- assert.expect(2);
-
- var result = pyUtils.py_eval("1 + 2");
- assert.strictEqual(result, 3, "should properly evaluate sum");
- result = pyUtils.py_eval("42 % 5");
- assert.strictEqual(result, 2, "should properly evaluate modulo operator");
- });
-
-The main way to run the test suite is to have a running Odoo server, then
-navigate a web browser to ``/web/tests``. The test suite will then be executed
-by the web browser Javascript engine.
-
-.. image:: ./images/tests.png
- :align: center
-
-The web UI has many useful features: it can run only some submodules, or
-filter tests that match a string. It can show every assertions, failed or passed,
-rerun specific tests, ...
-
-.. warning::
-
- While the test suite is running, make sure that:
-
- - your browser window is focused,
- - it is not zoomed in/out. It needs to have exactly 100% zoom level.
-
- If this is not the case, some tests will fail, without a proper explanation.
-
-Testing Infrastructure
-----------------------
-
-Here is a high level overview of the most important parts of the testing
-infrastructure:
-
-- there is an asset bundle named `web.qunit_suite`_. This bundle contains
- the main code (assets common + assets backend), some libraries, the QUnit test
- runner and the test bundles listed below.
-
-- a bundle named `web.tests_assets`_ includes most of the assets and utils required
- by the test suite: custom QUnit asserts, test helpers, lazy loaded assets, etc.
-
-- another asset bundle, `web.qunit_suite_tests`_, contains all the test scripts.
- This is typically where the test files are added to the suite.
-
-- there is a `controller`_ in web, mapped to the route */web/tests*. This controller
- simply renders the *web.qunit_suite* template.
-
-- to execute the tests, one can simply point its browser to the route */web/tests*.
- In that case, the browser will download all assets, and QUnit will take over.
-
-- there is some code in `qunit_config.js`_ which logs in the console some
- information when a test passes or fails.
-
-- we want the runbot to also run these tests, so there is a test (in `test_js.py`_)
- which simply spawns a browser and points it to the *web/tests* url. Note that
- the browser_js method spawns a Chrome headless instance.
-
-
-Modularity and testing
-----------------------
-
-With the way Odoo is designed, any addon can modify the behaviour of other parts
-of the system. For example, the *voip* addon can modify the *FieldPhone* widget
-to use extra features. This is not really good from the perspective of the
-testing system, since this means that a test in the addon web will fail whenever
-the voip addon is installed (note that the runbot runs the tests with all addons
-installed).
-
-At the same time, our testing sytem is good, because it can detect whenever
-another module breaks some core functionality. There is no complete solution to
-this issue. For now, we solve this on a case by case basis.
-
-Usually, it is not a good idea to modify some other behaviour. For our voip
-example, it is certainly cleaner to add a new *FieldVOIPPhone* widget and
-modify the few views that needs it. This way, the *FieldPhone* widget is not
-impacted, and both can be tested.
-
-Adding a new test case
-----------------------
-
-Let us assume that we are maintaining an addon *my_addon*, and that we
-want to add a test for some javascript code (for example, some utility function
-myFunction, located in *my_addon.utils*). The process to add a new test case is
-the following:
-
-1. create a new file *my_addon/static/tests/utils_tests.js*. This file contains the basic code to
- add a QUnit module *my_addon > utils*.
-
- .. code-block:: javascript
-
- odoo.define('my_addon.utils_tests', function (require) {
- "use strict";
-
- var utils = require('my_addon.utils');
-
- QUnit.module('my_addon', {}, function () {
-
- QUnit.module('utils');
-
- });
- });
-
-
-2. In *my_addon/assets.xml*, add the file to the main test assets:
-
- .. code-block:: xml
-
- <?xml version="1.0" encoding="utf-8"?>
- <odoo>
- <template id="qunit_suite_tests" name="my addon tests" inherit_id="web.qunit_suite_tests">
- <xpath expr="//script[last()]" position="after">
- <script type="text/javascript" src="/my_addon/static/tests/utils_tests.js"/>
- </xpath>
- </template>
- </odoo>
-
-3. Restart the server and update *my_addon*, or do it from the interface (to
- make sure the new test file is loaded)
-
-4. Add a test case after the definition of the *utils* sub test suite:
-
- .. code-block:: javascript
-
- QUnit.test("some test case that we want to test", function (assert) {
- assert.expect(1);
-
- var result = utils.myFunction(someArgument);
- assert.strictEqual(result, expectedResult);
- });
-
-5. Visit */web/tests/* to make sure the test is executed
-
-Helper functions and specialized assertions
--------------------------------------------
-
-Without help, it is quite difficult to test some parts of Odoo. In particular,
-views are tricky, because they communicate with the server and may perform many
-rpcs, which needs to be mocked. This is why we developed some specialized
-helper functions, located in `test_utils.js`_.
-
-- Mock test functions: these functions help setting up a test environment. The
- most important use case is mocking the answers given by the Odoo server. These
- functions use a `mock server`_. This is a javascript class that simulates
- answers to the most common model methods: read, search_read, nameget, ...
-
-- DOM helpers: useful to simulate events/actions on some specific target. For
- example, testUtils.dom.click performs a click on a target. Note that it is
- safer than doing it manually, because it also checks that the target exists,
- and is visible.
-
-- create helpers: they are probably the most important functions exported by
- `test_utils.js`_. These helpers are useful to create a widget, with a mock
- environment, and a lot of small detail to simulate as much as possible the
- real conditions. The most important is certainly `createView`_.
-
-- `qunit assertions`_: QUnit can be extended with specialized assertions. For
- Odoo, we frequently test some DOM properties. This is why we made some
- assertions to help with that. For example, the *containsOnce* assertion takes
- a widget/jQuery/HtmlElement and a selector, then checks if the target contains
- exactly one match for the css selector.
-
-For example, with these helpers, here is what a simple form test could look like:
-
-.. code-block:: javascript
-
- QUnit.test('simple group rendering', function (assert) {
- assert.expect(1);
-
- var form = testUtils.createView({
- View: FormView,
- model: 'partner',
- data: this.data,
- arch: '<form string="Partners">' +
- '<group>' +
- '<field name="foo"/>' +
- '</group>' +
- '</form>',
- res_id: 1,
- });
-
- assert.containsOnce(form, 'table.o_inner_group');
-
- form.destroy();
- });
-
-Notice the use of the testUtils.createView helper and of the containsOnce
-assertion. Also, the form controller was properly destroyed at the end of
-the test.
-
-Best Practices
---------------
-
-In no particular order:
-
-- all test files should be added in *some_addon/static/tests/*
-- for bug fixes, make sure that the test fails without the bug fix, and passes
- with it. This ensures that it actually works.
-- try to have the minimal amount of code necessary for the test to work.
-- usually, two small tests are better than one large test. A smaller test is
- easier to understand and to fix.
-- always cleanup after a test. For example, if your test instantiates a widget,
- it should destroy it at the end.
-- no need to have full and complete code coverage. But adding a few tests helps
- a lot: it makes sure that your code is not completely broken, and whenever a
- bug is fixed, it is really much easier to add a test to an existing test suite.
-- if you want to check some negative assertion (for example, that a HtmlElement
- does not have a specific css class), then try to add the positive assertion in
- the same test (for example, by doing an action that changes the state). This
- will help avoid the test to become dead in the future (for example, if the css
- class is changed).
-
-Tips
-----
-
-- running only one test: you can (temporarily!) change the *QUnit.test(...)*
- definition into *QUnit.only(...)*. This is useful to make sure that QUnit
- only runs this specific test.
-- debug flag: most create utility functions have a debug mode (activated by the
- debug: true parameter). In that case, the target widget will be put in the DOM
- instead of the hidden qunit specific fixture, and more information will be
- logged. For example, all mocked network communications will be available in the
- console.
-- when working on a failing test, it is common to add the debug flag, then
- comment the end of the test (in particular, the destroy call). With this, it
- is possible to see the state of the widget directly, and even better, to
- manipulate the widget by clicking/interacting with it.
-
-
-Integration Testing
-===================
-
-Testing Python code and JS code separately is very useful, but it does not prove
-that the web client and the server work together. In order to do that, we can
-write another kind of test: tours. A tour is a mini scenario of some interesting
-business flow. It explains a sequence of steps that should be followed. The
-test runner will then create a Chrome headless browser, point it to the proper url
-and simulate the click and inputs, according to the scenario.
-
-Screenshots and screencasts during browser_js tests
----------------------------------------------------
-
-When running tests that use HttpCase.browser_js from the command line, the Chrome
-browser is used in headless mode. By default, if a test fails, a PNG screenshot is
-taken at the moment of the failure and written in
-
-.. code-block:: console
-
- '/tmp/odoo_tests/{db_name}/screenshots/'
-
-Two new command line arguments were added since Odoo 13.0 to control this behavior:
-:option:`--screenshots <odoo-bin --screenshots>` and :option:`--screencasts <odoo-bin --screencasts>`
-
-
-Performance Testing
-===================
-
-Query counts
-------------
-
-One of the ways to test performance is to measure database queries. Manually, this can be tested with the
-`--log-sql` CLI parameter. If you want to establish the maximum number of queries for an operation,
-you can use the :meth:`~odoo.tests.common.BaseCase.assertQueryCount` method, integrated in Odoo test classes.
-
-.. code-block:: python
-
- with self.assertQueryCount(11):
- do_something()
-
-.. _reference/testing/populate:
-
-Database population
--------------------
-
-Odoo CLI offers a :ref:`database population<reference/cmdline/populate>` feature.
-
-.. code-block:: console
-
- odoo-bin populate
-
-Instead of the tedious manual, or programmatic, specification of test data,
-one can use this feature to fill a database on demand with the desired number of test data.
-This can be used to detect diverse bugs or performance issues in tested flows.
-
-.. _reference/testing/populate/methods:
-
-To specify this feature for a given model, the following methods and attributes can be defined.
-
-.. currentmodule:: odoo.models
-
-.. autoattribute:: Model._populate_sizes
-.. autoattribute:: Model._populate_dependencies
-.. automethod:: Model._populate
-.. automethod:: Model._populate_factories
-
-.. note::
-
- You have to define at least :meth:`~odoo.models.Model._populate` or :meth:`~odoo.models.Model._populate_factories`
- on the model to enable database population.
-
-Example model
-^^^^^^^^^^^^^
-
-.. code-block:: python
-
- from odoo.tools import populate
-
- class CustomModel(models.Model)
- _inherit = "custom.some_model"
- _populate_sizes = {"small": 100, "medium": 2000, "large": 10000}
- _populate_dependencies = ["custom.some_other_model"]
-
- def _populate_factories(self):
- # Record ids of previously populated models are accessible in the registry
- some_other_ids = self.env.registry.populated_models["custom.some_other_model"]
-
- def get_some_field(values=None, random=None, **kwargs):
- """ Choose a value for some_field depending on other fields values.
-
- :param dict values:
- :param random: seeded :class:`random.Random` object
- """
- field_1 = values['field_1']
- if field_1 in [value2, value3]:
- return random.choice(some_field_values)
- return False
-
- return [
- ("field_1", populate.randomize([value1, value2, value3])),
- ("field_2", populate.randomize([value_a, value_b], [0.5, 0.5])),
- ("some_other_id", populate.randomize(some_other_ids)),
- ("some_field", populate.compute(get_some_field, seed="some_field")),
- ('active', populate.cartesian([True, False])),
- ]
-
- def _populate(self, size):
- records = super()._populate(size)
-
- # If you want to update the generated records
- # E.g setting the parent-child relationships
- records.do_something()
-
- return records
-
-Population tools
-^^^^^^^^^^^^^^^^
-
-Multiple population tools are available to easily create
-the needed data generators.
-
-.. automodule:: odoo.tools.populate
- :members: cartesian, compute, constant, iterate, randint, randomize
-
-.. _qunit: https://qunitjs.com/
-.. _qunit_config.js: https://github.com/odoo/odoo/blob/51ee0c3cb59810449a60dae0b086b49b1ed6f946/addons/web/static/tests/helpers/qunit_config.js#L49
-.. _web.tests_assets: https://github.com/odoo/odoo/blob/51ee0c3cb59810449a60dae0b086b49b1ed6f946/addons/web/views/webclient_templates.xml#L594
-.. _web.qunit_suite: https://github.com/odoo/odoo/blob/51ee0c3cb59810449a60dae0b086b49b1ed6f946/addons/web/views/webclient_templates.xml#L660
-.. _web.qunit_suite_tests: https://github.com/odoo/odoo/blob/51ee0c3cb59810449a60dae0b086b49b1ed6f946/addons/web/views/webclient_templates.xml#L680
-.. _controller: https://github.com/odoo/odoo/blob/51ee0c3cb59810449a60dae0b086b49b1ed6f946/addons/web/controllers/main.py#L637
-.. _test_js.py: https://github.com/odoo/odoo/blob/51ee0c3cb59810449a60dae0b086b49b1ed6f946/addons/web/tests/test_js.py#L13
-.. _test_utils.js: https://github.com/odoo/odoo/blob/51ee0c3cb59810449a60dae0b086b49b1ed6f946/addons/web/static/tests/helpers/test_utils.js
-.. _mock server: https://github.com/odoo/odoo/blob/51ee0c3cb59810449a60dae0b086b49b1ed6f946/addons/web/static/tests/helpers/mock_server.js
-.. _qunit assertions: https://github.com/odoo/odoo/blob/51ee0c3cb59810449a60dae0b086b49b1ed6f946/addons/web/static/tests/helpers/qunit_asserts.js
-.. _createView: https://github.com/odoo/odoo/blob/51ee0c3cb59810449a60dae0b086b49b1ed6f946/addons/web/static/tests/helpers/test_utils_create.js#L267
diff --git a/doc/reference/translations.rst b/doc/reference/translations.rst
deleted file mode 100644
index cc6c92cbb5d..00000000000
--- a/doc/reference/translations.rst
+++ /dev/null
@@ -1,214 +0,0 @@
-:banner: banners/translate.jpg
-
-.. _reference/translations:
-
-
-===================
-Translating Modules
-===================
-
-This section explains how to provide translation abilities to your module.
-
-.. note:: If you want to contribute to the translation of Odoo itself, please refer to the
- `Odoo Wiki page <https://github.com/odoo/odoo/wiki/Translations>`_.
-
-Exporting translatable term
-===========================
-
-A number of terms in your modules are "implicitly translatable" as a result,
-even if you haven't done any specific work towards translation you can export
-your module's translatable terms and may find content to work with.
-
-.. todo:: needs technical features
-
-Translations export is performed via the administration interface by logging into
-the backend interface and opening :menuselection:`Settings --> Translations
---> Import / Export --> Export Translations`
-
-* leave the language to the default (new language/empty template)
-* select the `PO File`_ format
-* select your module
-* click :guilabel:`Export` and download the file
-
-.. image:: translations/po-export.*
- :align: center
- :width: 75%
-
-This gives you a file called :file:`{yourmodule}.pot` which should be moved to
-the :file:`{yourmodule}/i18n/` directory. The file is a *PO Template* which
-simply lists translatable strings and from which actual translations (PO files)
-can be created. PO files can be created using msginit_, with a dedicated
-translation tool like POEdit_ or by simply copying the template to a new file
-called :file:`{language}.po`. Translation files should be put in
-:file:`{yourmodule}/i18n/`, next to :file:`{yourmodule}.pot`, and will be
-automatically loaded by Odoo when the corresponding language is installed (via
-:menuselection:`Settings --> Translations --> Languages`)
-
-.. note:: translations for all loaded languages are also installed or updated
- when installing or updating a module
-
-Implicit exports
-================
-
-Odoo automatically exports translatable strings from "data"-type content:
-
-* in non-QWeb views, all text nodes are exported as well as the content of
- the ``string``, ``help``, ``sum``, ``confirm`` and ``placeholder``
- attributes
-* QWeb templates (both server-side and client-side), all text nodes are
- exported except inside ``t-translation="off"`` blocks, the content of the
- ``title``, ``alt``, ``label`` and ``placeholder`` attributes are also
- exported
-* for :class:`~odoo.fields.Field`, unless their model is marked with
- ``_translate = False``:
-
- * their ``string`` and ``help`` attributes are exported
- * if ``selection`` is present and a list (or tuple), it's exported
- * if their ``translate`` attribute is set to ``True``, all of their existing
- values (across all records) are exported
-* help/error messages of :attr:`~odoo.models.Model._constraints` and
- :attr:`~odoo.models.Model._sql_constraints` are exported
-
-Explicit exports
-================
-
-When it comes to more "imperative" situations in Python code or Javascript
-code, Odoo cannot automatically export translatable terms so they
-must be marked explicitly for export. This is done by wrapping a literal
-string in a function call.
-
-In Python, the wrapping function is :func:`odoo._`::
-
- title = _("Bank Accounts")
-
-In JavaScript, the wrapping function is generally :js:func:`odoo.web._t`:
-
-.. code-block:: javascript
-
- title = _t("Bank Accounts");
-
-.. warning::
-
- Only literal strings can be marked for exports, not expressions or
- variables. For situations where strings are formatted, this means the
- format string must be marked, not the formatted string
-
-The lazy version of `_` and `_t` is :func:`odoo._lt` in python and
-:js:func:`odoo.web._lt` in javascript. The translation lookup is executed only
-at rendering and can be used to declare translatable properties in class methods
-of global variables.
-
-Variables
-^^^^^^^^^
-**Don't** the extract may work but it will not translate the text correctly::
-
- _("Scheduled meeting with %s" % invitee.name)
-
-**Do** set the dynamic variables as a parameter of the translation lookup (this
-will fallback on source in case of missing placeholder in the translation)::
-
- _("Scheduled meeting with %s", invitee.name)
-
-
-Blocks
-^^^^^^
-**Don't** split your translation in several blocks or multiples lines::
-
- # bad, trailing spaces, blocks out of context
- _("You have ") + len(invoices) + _(" invoices waiting")
- _t("You have ") + invoices.length + _t(" invoices waiting");
-
- # bad, multiple small translations
- _("Reference of the document that generated ") + \
- _("this sales order request.")
-
-**Do** keep in one block, giving the full context to translators::
-
- # good, allow to change position of the number in the translation
- _("You have %s invoices wainting") % len(invoices)
- _.str.sprintf(_t("You have %s invoices wainting"), invoices.length);
-
- # good, full sentence is understandable
- _("Reference of the document that generated " + \
- "this sales order request.")
-
-Plural
-^^^^^^
-**Don't** pluralize terms the English-way::
-
- msg = _("You have %(count)s invoice", count=invoice_count)
- if invoice_count > 1:
- msg += _("s")
-
-**Do** keep in mind every language has different plural forms::
-
- if invoice_count > 1:
- msg = _("You have %(count)s invoices", count=invoice_count)
- else:
- msg = _("You have one invoice")
-
-Read vs Run Time
-^^^^^^^^^^^^^^^^
-
-**Don't** invoke translation lookup at server launch::
-
- ERROR_MESSAGE = {
- # bad, evaluated at server launch with no user language
- 'access_error': _('Access Error'),
- 'missing_error': _('Missing Record'),
- }
-
- class Record(models.Model):
-
- def _raise_error(self, code):
- raise UserError(ERROR_MESSAGE[code])
-
-**Don't** invoke translation lookup when the javascript file is read::
-
- # bad, js _t is evaluated too early
- var core = require('web.core');
- var _t = core._t;
- var map_title = {
- access_error: _t('Access Error'),
- missing_error: _t('Missing Record'),
- };
-
-
-**Do** use lazy translation lookup method::
-
- ERROR_MESSAGE = {
- 'access_error': _lt('Access Error'),
- 'missing_error': _lt('Missing Record'),
- }
-
- class Record(models.Model):
-
- def _raise_error(self, code):
- # translation lookup executed at error rendering
- raise UserError(ERROR_MESSAGE[code])
-
-
-or **do** evaluate dynamically the translatable content::
-
- # good, evaluated at run time
- def _get_error_message(self):
- return {
- access_error: _('Access Error'),
- missing_error: _('Missing Record'),
- }
-
-**Do** in the case where the translation lookup is done when the JS file is
-*read*, use `_lt` instead of `_t` to translate the term when it is *used*::
-
- # good, js _lt is evaluated lazily
- var core = require('web.core');
- var _lt = core._lt;
- var map_title = {
- access_error: _lt('Access Error'),
- missing_error: _lt('Missing Record'),
- };
-
-
-.. _PO File: https://en.wikipedia.org/wiki/Gettext#Translating
-.. _msginit: https://www.gnu.org/software/gettext/manual/gettext.html#Creating
-.. _POEdit: https://poedit.net/
diff --git a/doc/reference/translations/po-export.png b/doc/reference/translations/po-export.png
deleted file mode 100644
index 91574b40ee8..00000000000
--- a/doc/reference/translations/po-export.png
+++ /dev/null
Binary files differ
diff --git a/doc/reference/views.rst b/doc/reference/views.rst
deleted file mode 100644
index a8ad929c6a2..00000000000
--- a/doc/reference/views.rst
+++ /dev/null
@@ -1,2139 +0,0 @@
-:banner: banners/views.jpg
-
-.. _reference/views:
-
-=====
-Views
-=====
-
-Views are what define how records should be displayed to end-users. They are specified in XML which
-means that they can be edited independently from the models that they represent. They are flexible
-and allow a high level of customization of the screens that they control. There exist various types
-of views. Each of them represents a mode of visualization: *form*, *list*, *kanban*, etc.
-
-.. todo:: Build doc of ir_ui_view.py ?
-
-.. _reference/views/structure:
-
-Generic structure
-=================
-
-Basic views generally share the common structure defined below. Placeholders are denoted in all
-caps.
-
-.. code-block:: xml
-
- <record id="MODEL_view_TYPE" model="ir.ui.view">
- <field name="name">NAME</field>
- <field name="model">MODEL</field>
- <field name="arch" type="xml">
- <VIEW_TYPE>
- <VIEW_SPECIFICATIONS/>
- </VIEW_TYPE>
- </field>
- </record>
-
-Fields
-======
-
-View objects expose a number of fields. They are optional unless specified otherwise.
-
-* ``name`` (mandatory) :class:`~odoo.fields.Char`
-
- Only useful as a mnemonic/description of the view when looking for one in a list of some sort.
-
-* ``model`` :class:`~odoo.fields.Char`
-
- The model linked to the view, if applicable.
-
-* ``priority`` :class:`~odoo.fields.Integer`
-
- When a view is requested by ``(model, type)``, the view matching the model and
- the type, with the lowest priority will be returned (it is the default view).
-
- It also defines the order of views application during :ref:`view
- inheritance <reference/views/inheritance>`.
-
-* ``groups_id`` :class:`~odoo.fields.Many2many` -> :class:`odoo.addons.base.models.res_users.Groups`
-
- The groups allowed to use/access the current view.
-
- If the view extends an existing view, the extension will only be applied
- for a given user if the user has access to the provided ``groups_id``.
-
-* ``arch`` :class:`~odoo.fields.Text`
-
- The description of the view layout.
-
-Attributes
-==========
-
-.. todo::
-
- view attributes & view element attributes
- attrs & states attributes are missing generic information
-
-The different view types have a wide variety of attributes allowing customizations of
-the generic behaviors. Some main attributes will be explained here. They do not all have
-an impact on all view types.
-
-.. note:: The current context and user access rights may also impact the view abilities.
-
-.. todo:: info on create/... in the context ?
-
-* ``create``
-
- Disable/enable record creation on the view.
-
-* ``edit`` (``form`` & ``list`` & ``gantt``)
-
- Disable/enable record editing on the view.
-
-* ``delete`` (``form`` & ``list``)
-
- Disable/enable record deletion on the view through the **Action** dropdown.
-
-* ``duplicate`` (``form`` & ``list``)
-
- Disable/enable record duplication on the view through the **Action** dropdown.
-
-* ``decoration-{$name}`` (``list`` & ``gantt``)
-
- Define a conditional display of a record in the style of a row's text based on the corresponding
- record's attributes.
-
- Values are Python expressions. For each record, the expression is evaluated
- with the record's attributes as context values and if ``true``, the
- corresponding style is applied to the row. Here are some of the other values
- available in the context:
-
- * ``uid``: the id of the current user,
- * ``today``: the current local date as a string of the form ``YYYY-MM-DD``,
- * ``now``: same as ``today`` with the addition of the current time.
- This value is formatted as ``YYYY-MM-DD hh:mm:ss``.
-
- .. code-block:: xml
-
- <tree decoration-info="state == 'draft'"
- decoration-danger="state == 'help_needed'"
- decoration-bf="state='busy'">
- <TREE_VIEW_CONTENT>
- </tree>
-
- .. warning::
- Supported values differ for the two view types. The Gantt view only supports ``success``,
- ``info``, ``warning``, ``danger`` and ``secondary`` displays. The list view supports ``bf``,
- ``it``, ``success``, ``info``, ``warning``, ``danger``, ``muted`` and ``primary`` displays.
-
-* ``sample`` (``kanban`` & ``list`` & ``gantt`` & ``graph`` & ``pivot`` & ``cohort`` & ``dashboard``)
-
- Populate the view with a set of sample records if none are found for the current model.
- This attribute is false by default.
-
- These fake records will have heuristics for certain field names/models. For example,
- a field 'display_name' on the model 'res.users' will be populated with sample people names
- while an 'email' field will be in the form 'firstname.lastname@sample.demo'.
-
- The user will not be able to interact with these data and they will be discarded as soon as
- an action is performed (record created, column added, etc.)
-
-* ``banner_route``
- a route address to be fetched and prepended to the view.
-
- If this attribute is set, the
- :ref:`controller route url<reference/controllers>` will be fetched and
- displayed above the view. The json response from the controller should
- contain an "html" key.
-
- If the html contains a stylesheet <link> tag, it will be
- removed and appended to <head>.
-
- To interact with the backend you can use <a type="action"> tags. Please take
- a look at the documentation of the _onActionClicked method of
- AbstractController (*addons/web/static/src/js/views/abstract_controller.js*)
- for more details.
-
- Only views extending AbstractView and AbstractController can use this
- attribute, like :ref:`reference/views/form`, :ref:`reference/views/kanban`,
- :ref:`reference/views/list`, ...
-
- Example:
-
- .. code-block:: xml
-
- <tree banner_route="/module_name/hello" />
-
- .. code-block:: python
-
- class MyController(odoo.http.Controller):
- @http.route('/module_name/hello', auth='user', type='json')
- def hello(self):
- return {
- 'html': """
- <div>
- <link href="/module_name/static/src/css/banner.css"
- rel="stylesheet">
- <h1>hello, world</h1>
- </div> """
- }
-
-.. todo:: Views main content section, with field, group & separator ?
-
-.. _reference/views/inheritance:
-
-Inheritance
-===========
-
-Inheritance fields
-------------------
-
-The two following :class:`~odoo.addons.base.ir_ui_view.View` fields are used to specify
-inherited views.
-
-* ``inherit_id`` :class:`~odoo.fields.Many2one`
-
- the current view's parent view, unset by default. Specify the parent using
- the `ref` attribute:
-
- .. code-block:: xml
-
- <field name="inherit_id" ref="library.view_book_form"/>
-
-* ``mode`` :class:`~odoo.fields.Selection`: `extension / primary`
-
- inheritance mode, ``extension`` by default if ``inherit_id`` is set,
- ``primary`` otherwise.
-
- An example of where you would want to override ``mode`` while using
- ``inherit_id`` is delegation inheritance.
- In that case your derived model will be separate from its parent and views
- matching with one won't match with the other. Suppose you inherit from a view
- associated with the parent model and want to customize the derived view to
- show data from the derived model. The ``mode`` of the derived view needs to
- be set to ``primary``, because it's the base (and maybe only) view for that
- derived model. Otherwise the :ref:`view matching <reference/views/inheritance/view-matching>`
- rules won't apply.
-
-.. _reference/views/inheritance/view-matching:
-
-View matching
--------------
-
-* if a view is requested by ``(model, type)``, the view with the right model
- and type, ``mode=primary`` and the lowest priority is matched.
-* when a view is requested by ``id``, if its mode is not ``primary`` its
- *closest* parent with mode ``primary`` is matched.
-
-View resolution
----------------
-
-Resolution generates the final ``arch`` for a requested/matched ``primary``
-view:
-
-#. if the view has a parent, the parent is fully resolved then the current
- view's inheritance specs are applied
-#. if the view has no parent, its ``arch`` is used as-is
-#. the current view's children with mode ``extension`` are looked up and their
- inheritance specs are applied depth-first (a child view is applied, then
- its children, then its siblings)
-
-The result of applying children views yields the final ``arch``
-
-.. todo:: NOTE on fields_view_get and link to ORM ?
-
-Inheritance specs
------------------
-
-Inheritance specs are comprised of an element locator, to match
-the inherited element in the parent view, and children element that
-will be used to modify the inherited element.
-
-There are three types of element locators for matching a target element:
-
-* An ``xpath`` element with an ``expr`` attribute. ``expr`` is an XPath_
- expression\ [#hasclass]_ applied to the current ``arch``, the first node
- it finds is the match
-* a ``field`` element with a ``name`` attribute, matches the first ``field``
- with the same ``name``. All other attributes are ignored during matching
-* any other element: the first element with the same name and identical
- attributes (ignoring ``position`` and ``version`` attributes) is matched
-
-.. code-block:: xml
-
- <xpath expr="page[@name='pg']/group[@name='gp']/field" position="inside">
- <field name="description"/>
- </xpath>
-
- <field name="res_id" position="after"/>
-
- <div name="name" position="replace">
- <div name="name2">
- <field name="name2"/>
- </div>
- </div>
-
-The inheritance spec may have an optional ``position`` attribute specifying
-how the matched node should be altered:
-
-``inside`` (default)
- the content of the inheritance spec is appended to the matched node
-``replace``
- the content of the inheritance spec replaces the matched node.
- Any text node containing only ``$0`` within the contents of the spec will
- be replaced by a complete copy of the matched node, effectively wrapping
- the matched node.
-``after``
- the content of the inheritance spec is added to the matched node's
- parent, after the matched node
-``before``
- the content of the inheritance spec is added to the matched node's
- parent, before the matched node
-``attributes``
- the content of the inheritance spec should be ``attribute`` elements
- with a ``name`` attribute and an optional body:
-
- * if the ``attribute`` element has a body, a new attributed named
- after its ``name`` is created on the matched node with the
- ``attribute`` element's text as value
- * if the ``attribute`` element has no body, the attribute named after
- its ``name`` is removed from the matched node. If no such attribute
- exists, an error is raised
-
- .. code-block:: xml
-
- <field name="sale_information" position="attributes">
- <attribute name="invisible">0</attribute>
- <attribute name="attrs">
- {'invisible': [('sale_ok', '=', False)], 'readonly': [('editable', '=', False)]}
- </attribute>
- </field>
-
-``move``
- can be used as a direct child of a inheritance spec
- with a ``inside``, ``replace``, ``after`` or ``before`` ``position`` attribute
- to move a node.
-
- .. code-block:: xml
-
- <xpath expr="//@target" position="after">
- <xpath expr="//@node" position="move"/>
- </xpath>
-
- <field name="target_field" position="after">
- <field name="my_field" position="move"/>
- </field>
-
-
-A view's specs are applied sequentially.
-
-.. [#hasclass] an extension function is added for simpler matching in QWeb
- views: ``hasclass(*classes)`` matches if the context node has
- all the specified classes
-
-.. _reference/views/types:
-
-View types
-==========
-
-.. _reference/views/activity:
-
-Activity
---------
-
-The Activity view is used to display the activities linked to the records. The
-data are displayed in a chart with the records forming the rows and the activity
-types the columns. The first cell of each row displays a (customizable, see
-``templates``, quite similarly to :ref:`reference/views/kanban`) card representing
-the corresponding record. When clicking on others cells, a detailed description
-of all activities of the same type for the record is displayed.
-
-.. warning::
-
- The Activity view is only available when the ``mail`` module is installed,
- and for the models that inherit from the ``mail.activity.mixin``.
-
-The root element of the Activity view is ``<activity>``, it accepts the following
-attributes:
-
-- ``string`` (mandatory)
- A title, which should describe the view
-
-Possible children of the view element are:
-
-``field``
- declares fields to use in activity *logic*. If the field is simply displayed
- in the activity view, it does not need to be pre-declared.
-
- Possible attributes are:
-
- ``name`` (required)
- the name of the field to fetch
-
-``templates``
- defines the :ref:`reference/qweb` templates. Cards definition may be
- split into multiple templates for clarity, but activity views *must* define at
- least one root template ``activity-box``, which will be rendered once for each
- record.
-
- The activity view uses mostly-standard :ref:`javascript qweb
- <reference/qweb/javascript>` and provides the following context variables
- (see :ref:`reference/views/kanban` for more details):
-
- ``widget``
- the current :js:class:`ActivityRecord`, can be used to fetch some
- meta-information. These methods are also available directly in the
- template context and don't need to be accessed via ``widget``
- ``record``
- an object with all the requested fields as its attributes. Each field has
- two attributes ``value`` and ``raw_value``
-
-.. _reference/views/calendar:
-
-Calendar
---------
-
-Calendar views display records as events in a daily, weekly, monthly or yearly
-calendar. Their root element is ``<calendar>``. Available attributes on the
-calendar view are:
-
-``date_start`` (required)
- name of the record's field holding the start date for the event
-``date_stop``
- name of the record's field holding the end date for the event, if
- ``date_stop`` is provided records become movable (via drag and drop)
- directly in the calendar
-``date_delay``
- alternative to ``date_stop``, provides the duration of the event instead of
- its end date (unit: day)
-``color``
- name of a record field to use for *color segmentation*. Records in the
- same color segment are allocated the same highlight color in the calendar,
- colors are allocated semi-randomly.
- Displayed the display_name/avatar of the visible record in the sidebar
-``form_view_id``
- view to open when the user create or edit an event. Note that if this attribute
- is not set, the calendar view will fall back to the id of the form view in the
- current action, if any.
-``event_open_popup``
- If the option 'event_open_popup' is set to true, then the calendar view will
- open events (or records) in a FormViewDialog. Otherwise, it will open events
- in a new form view (with a do_action)
-``quick_add``
- enables quick-event creation on click: only asks the user for a ``name``
- and tries to create a new event with just that and the clicked event
- time. Falls back to a full form dialog if the quick creation fails
-``all_day``
- name of a boolean field on the record indicating whether the corresponding
- event is flagged as day-long (and duration is irrelevant)
-``mode``
- Default display mode when loading the calendar.
- Possible attributes are: ``day``, ``week``, ``month``, ``year``
-``scales``
- Comma-separated list of scales to provide. By default, all scales are
- available. See mode for possible scale values.
-
-``<field>``
- declares fields to aggregate or to use in kanban *logic*. If the field is
- simply displayed in the calendar cards.
-
- Fields can have additional attributes:
-
- * ``invisible``
- use "True" to hide the value in the cards
- * ``avatar_field``
- only for x2many field, to display the avatar instead of the display_name
- in the cards
- * ``write_model`` and ``write_field``
-
- you can add a filter and save the result in the defined model, the
- filter is added in the sidebar
- * ``filter`` and ``color``
-
- use "True" to add this field in filter in the sidebar. You can specify
- a ``color`` field used to colorize the checkbox.
-
-.. _reference/views/cohort:
-
-Cohort
-------
-
-.. raw:: html
-
- <span class="badge" style="background-color:#AD5E99">Enterprise feature</span>
-
-The cohort view is used to display and understand the way some data changes over
-a period of time. For example, imagine that for a given business, clients can
-subscribe to some service. The cohort view can then display the total number
-of subscriptions each month, and study the rate at which client leave the service
-(churn). When clicking on a cell, the cohort view will redirect you to a new action
-in which you will only see the records contained in the cell's time interval;
-this action contains a list view and a form view.
-
-.. note:: By default the cohort view will use the same list and form views as those
- defined on the action. You can pass a list view and a form view
- to the context of the action in order to set/override the views that will be
- used (the context keys to use being `form_view_id` and `list_view_id`)
-
-For example, here is a very simple cohort view:
-
-.. code-block:: xml
-
- <cohort string="Subscription" date_start="date_start" date_stop="date" interval="month"/>
-
-The root element of the Cohort view is <cohort>, it accepts the following
-attributes:
-
-
-- ``string`` (mandatory)
- A title, which should describe the view
-
-- ``date_start`` (mandatory)
- A valid date or datetime field. This field is understood by the view as the
- beginning date of a record
-
-- ``date_stop`` (mandatory)
- A valid date or datetime field. This field is understood by the view as the
- end date of a record. This is the field that will determine the churn.
-
-- ``mode`` (optional)
- A string to describe the mode. It should be either 'churn' or
- 'retention' (default). Churn mode will start at 0% and accumulate over time
- whereas retention will start at 100% and decrease over time.
-
-- ``timeline`` (optional)
- A string to describe the timeline. It should be either 'backward' or 'forward' (default).
- Forward timeline will display data from date_start to date_stop, whereas backward timeline
- will display data from date_stop to date_start (when the date_start is in future / greater
- than date_stop).
-
-- ``interval`` (optional)
- A string to describe a time interval. It should be 'day', 'week', 'month''
- (default) or 'year'.
-
-- ``measure`` (optional)
- A field that can be aggregated. This field will be used to compute the values
- for each cell. If not set, the cohort view will count the number of occurrences.
-
-``<field>`` (optional)
- allows to specify a particular field in order to manage it from the available measures, it's
- main use is for hiding a field from the selectable measures:
-
-- ``name`` (required)
- the name of the field to use in the view.
-- ``string`` (optional)
- the name that would be used to display the field in the cohort view, overrides the
- default python String attribute of the field.
-- ``invisible`` (optional)
- if true, the field will not appear either in the active measures nor in the selectable
- measures (useful for fields that do not make sense aggregated, such as fields in different
- units, e.g. € and $).
-
-.. _reference/views/dashboard:
-
-Dashboard
----------
-
-.. raw:: html
-
- <span class="badge" style="background-color:#AD5E99">Enterprise feature</span>
-
-Like pivot and graph view, The dashboard view is used to display aggregate data.
-However, the dashboard can embed sub views, which makes it possible to have a
-more complete and interesting look on a given dataset.
-
-The dashboard view can display sub views, aggregates for some fields (over a
-domain), or even *formulas* (expressions which involves one or more aggregates).
-For example, here is a very simple dashboard:
-
-.. code-block:: xml
-
- <dashboard>
- <view type="graph" ref="sale_report.view_order_product_graph"/>
- <group string="Sale">
- <aggregate name="price_total" field="price_total" widget="monetary"/>
- <aggregate name="order_id" field="order_id" string="Orders"/>
- <formula name="price_average" string="Price Average"
- value="record.price_total / record.order_id" widget="percentage"/>
- </group>
- <view type="pivot" ref="sale_report.view_order_product_pivot"/>
- </dashboard>
-
-The root element of the Dashboard view is <dashboard>, it does not accept any
-attributes.
-
-There are 5 possible type of tags in a dashboard view:
-
-``view``
- declares a sub view.
-
- Admissible attributes are:
-
- - ``type`` (mandatory)
- The type of the sub view. For example, *graph* or *pivot*.
-
- - ``ref`` (optional)
- An xml id for a view. If not given, the default view for the model will
- be used.
-
- - ``name`` (optional)
- A string which identifies this element. It is mostly
- useful to be used as a target for an xpath.
-
-``group``
- defines a column layout. This is actually very similar to the group element
- in a form view.
-
- Admissible attributes are:
-
- - ``string`` (optional)
- A description which will be displayed as a group title.
-
- - ``colspan`` (optional)
- The number of subcolumns in this group tag. By default, 6.
-
- - ``col`` (optional)
- The number of columns spanned by this group tag (only makes sense inside
- another group). By default, 6.
-
-
-``aggregate``
- declares an aggregate. This is the value of an aggregate for a given field
- over the current domain.
-
- Note that aggregates are supposed to be used inside a group tag (otherwise
- the style will not be properly applied).
-
- Admissible attributes are:
-
- - ``field`` (mandatory)
- The field name to use for computing the aggregate. Possible field types
- are:
-
- - ``integer`` (default group operator is sum)
- - ``float`` (default group operator is sum)
- - ``many2one`` (default group operator is count distinct)
-
- - ``name`` (mandatory)
- A string to identify this aggregate (useful for formulas)
-
- - ``string`` (optional)
- A short description that will be displayed above the value. If not
- given, it will fall back to the field string.
-
- - ``domain`` (optional)
- An additional restriction on the set of records that we want to aggregate.
- This domain will be combined with the current domain.
-
- - ``domain_label`` (optional)
- When the user clicks on an aggregate with a domain, it will be added to
- the search view as a facet. The string displayed for this facet can
- be customized with this attribute.
-
- - ``group_operator`` (optional)
- A valid postgreSQL aggregate function identifier to use when aggregating
- values (see https://www.postgresql.org/docs/9.5/static/functions-aggregate.html).
- If not provided, By default, the group_operator from the field definition is used.
- Note that no aggregation of field values is achieved if the group_operator value is "".
-
- .. note:: The special aggregate function ``count_distinct`` (defined in odoo) can also be used here
-
- .. code-block:: xml
-
- <aggregate name="price_total_max" field="price_total" group_operator="max"/>
-
-
-
- - ``col`` (optional)
- The number of columns spanned by this tag (only makes sense inside a
- group). By default, 1.
-
- - ``widget`` (optional)
- A widget to format the value (like the widget attribute for fields).
- For example, monetary.
-
- - ``help`` (optional)
- A help message to dipslay in a tooltip (equivalent of help for a field in python)
-
- - ``measure`` (optional)
- This attribute is the name of a field describing the measure that has to be used
- in the graph and pivot views when clicking on the aggregate.
- The special value __count__ can be used to use the count measure.
-
- .. code-block:: xml
-
- <aggregate name="total_ojects" string="Total Objects" field="id" group_operator="count" measure="__count__"/>
-
- - ``clickable`` (optional)
- A boolean indicating if this aggregate should be clickable or not (default to true).
- Clicking on a clickable aggregate will change the measures used by the subviews
- and add the value of the domain attribute (if any) to the search view.
-
- - ``value_label`` (optional)
- A string put on the right of the aggregate value.
- For example, it can be useful to indicate the unit of measure
- of the aggregate value.
-
-``formula``
- declares a derived value. Formulas are values computed from aggregates.
-
- Note that like aggregates, formulas are supposed to be used inside a group
- tag (otherwise the style will not be properly applied).
-
- Admissible attributes are:
-
- - ``value`` (mandatory)
- A string expression that will be evaluated, with the builtin python
- evaluator (in the web client). Every aggregate can be used in the
- context, in the ``record`` variable. For example,
- ``record.price_total / record.order_id``.
-
- - ``name`` (optional)
- A string to identify this formula
-
- - ``string`` (optional)
- A short description that will be displayed above the formula.
-
- - ``col`` (optional)
- The number of columns spanned by this tag (only makes sense inside a
- group). By default, 1.
-
- - ``widget`` (optional)
- A widget to format the value (like the widget attribute for fields).
- For example, monetary. By default, it is 'float'.
-
- - ``help`` (optional)
- A help message to dipslay in a tooltip (equivalent of help for a field in python)
-
- - ``value_label`` (optional)
- A string put on the right of the formula value.
- For example, it can be useful to indicate the unit of measure
- of the formula value.
-
-``widget``
- Declares a specialized widget to be used to display the information. This is
- a mechanism similar to the widgets in the form view.
-
- Admissible attributes are:
-
- - ``name`` (mandatory)
- A string to identify which widget should be instantiated. The view will
- look into the ``widget_registry`` to get the proper class.
-
- - ``col`` (optional)
- The number of columns spanned by this tag (only makes sense inside a
- group). By default, 1.
-
-.. _reference/views/form:
-
-Form
-----
-
-Form views are used to display the data from a single record. Their root
-element is ``<form>``. They are composed of regular HTML_ with additional
-structural and semantic components.
-
-Structural components
-~~~~~~~~~~~~~~~~~~~~~
-
-Structural components provide structure or "visual" features with little
-logic. They are used as elements or sets of elements in form views.
-
-``notebook``
- defines a tabbed section. Each tab is defined through a ``page`` child
- element. Pages can have the following attributes:
-
- * ``string`` (required)
- the title of the tab
- * ``accesskey``
- an HTML accesskey_
- * ``attrs``
- standard dynamic attributes based on record values
-
- .. note:: Note that ``notebook`` should not be placed within ``group``
-
-``group``
- used to define column layouts in forms. By default, groups define 2 columns
- and most direct children of groups take a single column. ``field`` direct
- children of groups display a label by default, and the label and the field
- itself have a colspan of 1 each.
-
- The number of columns in a ``group`` can be customized using the ``col``
- attribute, the number of columns taken by an element can be customized using
- ``colspan``.
-
- Children are laid out horizontally (tries to fill the next column before
- changing row).
-
- Groups can have a ``string`` attribute, which is displayed as the group's
- title
-``newline``
- only useful within ``group`` elements, ends the current row early and
- immediately switches to a new row (without filling any remaining column
- beforehand)
-``separator``
- small horizontal spacing, with a ``string`` attribute behaves as a section
- title
-``sheet``
- can be used as a direct child to ``form`` for a narrower and more responsive
- form layout
-``header``
- combined with ``sheet``, provides a full-width location above the sheet
- itself, generally used to display workflow buttons and status widgets
-
-Semantic components
-~~~~~~~~~~~~~~~~~~~
-
-Semantic components tie into and allow interaction with the Odoo
-system. Available semantic components are:
-
-``button``
- call into the Odoo system, similar to :ref:`list view buttons
- <reference/views/list/button>`. In addition, the following attribute can be
- specified:
-
- ``special``
- for form views opened in dialogs: ``save`` to save the record and close the
- dialog, ``cancel`` to close the dialog without saving.
- ``confirm``
- confirmation message to display (and for the user to accept) before
- performing the button's Odoo call (also works in Kanban views).
-
-``field``
- renders (and allow editing of, possibly) a single field of the current
- record. Using several times a field in a form view is supported and the fields
- can receive different values for modifiers 'invisible' and 'readonly'. However,
- the behavior is not guaranteed when several fields exist with different values
- for modifier 'required'. Possible attributes of the field node are:
-
- ``name`` (mandatory)
- the name of the field to render
- ``id``
- the node id. Useful when there are several occurrences of the same field in
- the view (see ``label`` component below). Default is the field name.
- ``widget``
- fields have a default rendering based on their type
- (e.g. :class:`~odoo.fields.Char`,
- :class:`~odoo.fields.Many2one`). The ``widget`` attributes allows using
- a different rendering method and context.
-
- .. todo:: list of widgets
-
- & options & specific attributes (e.g. widget=statusbar
- statusbar_visible clickable)
- ``options``
- JSON object specifying configuration option for the field's widget
- (including default widgets)
- ``class``
- HTML class to set on the generated element, common field classes are:
-
- ``oe_inline``
- prevent the usual line break following fields
- ``oe_left``, ``oe_right``
- floats_ the field to the corresponding direction
- ``oe_read_only``, ``oe_edit_only``
- only displays the field in the corresponding form mode
- ``oe_avatar``
- for image fields, displays images as "avatar" (square, 90x90 maximum
- size, some image decorations)
- ``groups``
- only displays the field for specific users
- ``on_change``
- calls the specified method when this field's value is edited, can generate
- update other fields or display warnings for the user
-
- .. deprecated:: 8.0
-
- Use :func:`odoo.api.onchange` on the model
-
- ``attrs``
- dynamic meta-parameters based on record values
- ``domain``
- for relational fields only, filters to apply when displaying existing
- records for selection
- ``context``
- for relational fields only, context to pass when fetching possible values
- ``readonly``
- display the field in both readonly and edit mode, but never make it
- editable
- ``required``
- generates an error and prevents saving the record if the field doesn't
- have a value
- ``nolabel``
- don't automatically display the field's label, only makes sense if the
- field is a direct child of a ``group`` element
- ``placeholder``
- help message to display in *empty* fields. Can replace field labels in
- complex forms. *Should not* be an example of data as users are liable to
- confuse placeholder text with filled fields
- ``mode``
- for :class:`~odoo.fields.One2many`, display mode (view type) to use for
- the field's linked records. One of ``tree``, ``form``, ``kanban`` or
- ``graph``. The default is ``tree`` (a list display)
- ``help``
- tooltip displayed for users when hovering the field or its label
- ``filename``
- for binary fields, name of the related field providing the name of the
- file
- ``password``
- indicates that a :class:`~odoo.fields.Char` field stores a password and
- that its data shouldn't be displayed
- ``kanban_view_ref``
- for opening specific kanban view when selecting records from m2o/m2m in mobile
- environment
-
-``label``
- when a ``field`` component isn't placed directly inside a ``group``, or when
- its ``nolabel`` attribute is set, the field's label isn't automatically
- displayed alongside its value. The ``label`` component is the manual alternative
- of displaying the label of a field. Possible attributes are:
-
- ``for`` (mandatory)
- the reference to the field associated with the label. Can be either the name
- of a field, or its id (``id`` attribute set on the ``field``). When there are
- several occurrences of the same field in the view, and there are several
- ``label`` components associated with these ``field`` nodes, those labels
- must have unique ``for`` attributes (in this case referencing the ``id``
- attribute of the corresponding ``field`` nodes).
- ``string``
- the label to display. Display the field's label (coming from the field
- definition in the model) by default.
- ``class``
- same as for ``field`` component.
- ``attrs``
- same as for ``field`` component.
-
-
-Generic structure
-~~~~~~~~~~~~~~~~~
-
-.. code-block:: xml
-
- <form>
- <header>
- <field name="state" widget="statusbar"/>
- </header>
- <sheet>
- <div class="oe_button_box">
- <BUTTONS/>
- </div>
- <group>
- <group>
- <field name="fname"/>
- </group>
- </group>
- <notebook>
- <page string="Page1">
- <group>
- <CONTENT/>
- </group>
- </page>
- <page string="Page2">
- <group>
- <CONTENT/>
- </group>
- </page>
- </notebook>
- </sheet>
- </form>
-
-.. todo:: classes for forms
-
-.. todo:: widgets?
-
-.. _reference/views/gantt:
-
-Gantt
------
-
-.. raw:: html
-
- <span class="badge" style="background-color:#AD5E99">Enterprise feature</span>
-
-Gantt views appropriately display Gantt charts (for scheduling).
-
-The root element of gantt views is ``<gantt/>``, it has no children but can
-take the following attributes:
-
-``date_start`` (required)
- name of the field providing the start datetime of the event for each
- record.
-``date_stop`` (required)
- name of the field providing the end duration of the event for each
- record.
-``color``
- name of the field used to color the pills according to its value
-``decoration-{$name}``
- allow changing the style of a row's text based on the corresponding
- record's attributes.
-
- Values are Python expressions. For each record, the expression is evaluated
- with the record's attributes as context values and if ``true``, the
- corresponding style is applied to the row. Here are some of the other values
- available in the context:
-
- * ``uid``: the id of the current user,
- * ``today``: the current local date as a string of the form ``YYYY-MM-DD``,
- * ``now``: same as ``today`` with the addition of the current time.
- This value is formatted as ``YYYY-MM-DD hh:mm:ss``.
-
- ``{$name}`` can be one of the following `bootstrap contextual color`_ (``danger``,
- ``info``, ``secondary``, ``success`` or ``warning``).
-``default_group_by``
- name of a field to group tasks by
-``consolidation``
- field name to display consolidation value in record cell
-``consolidation_max``
- dictionnary with the "group by" field as key and the maximum consolidation
- value that can be reached before displaying the cell in red
- (e.g. ``{"user_id": 100}``)
-``consolidation_exclude``
- name of the field that describes if the task has to be excluded
- from the consolidation
- if set to true it displays a striped zone in the consolidation line
-``create``, ``cell_create``, ``edit``, ``delete``, ``plan``
- allows *dis*\ abling the corresponding action in the view by setting the
- corresponding attribute to ``false`` (default: ``true``).
-
- * ``create``: If enabled, an ``Add`` button will be available in the control
- panel to create records.
- * ``cell_create``: If enabled and ``create`` enabled, a "**+**" button will be
- displayed while hovering on a time slot cell to create a new record on that slot.
- * ``edit``: If enabled, the opened records will be in edit mode (thus editable).
- * ``plan``: If enabled and ``edit`` enabled, a "magnifying glass" button will be displayed
- on time slots to plan unassigned records into that time slot.
-
- .. admonition:: Example
-
- When you do not want to create records on the gantt view and the beginning and end
- dates are required on the model, the planning feature should be disabled
- because no record will ever be found.
-``offset``
- Depending on the scale, the number of units to add to today to compute the
- default period. Examples: An offset of +1 in default_scale week will open the
- gantt view for next week, and an offset of -2 in default_scale month will open
- the gantt view of 2 months ago.
-``progress``
- name of a field providing the completion percentage for the record's event,
- between 0 and 100
-``string``
- title of the gantt view
-``precision``
- JSON object specifying snapping precisions for the pills in each scale.
-
- * Possible values for scale ``day`` are (default: ``hour``):
-
- ``hour``: records times snap to full hours (ex: 7:12 becomes 8:00)
-
- ``hour:half``: records times snap to half hours (ex: 7:12 becomes 7:30)
-
- ``hour:quarter``: records times snap to half hours (ex: 7:12 becomes 7:15)
-
- * Possible values for scale ``week`` are (default: ``day:half``):
-
- ``day``: records times snap to full days (ex: 7:28 AM becomes 11:59:59 PM of the previous day, 10:32 PM becomes 12:00 PM of the current day)
-
- ``day:half``: records times snap to half hours (ex: 7:28 AM becomes 12:00 PM)
-
- * Possible values for scale ``month`` are (default: ``day:half``):
-
- ``day``: records times snap to full days (ex: 7:28 AM becomes 11:59:59 PM of the previous day, 10:32 PM becomes 12:00 PM of the current day)
-
- ``day:half``: records times snap to half hours (ex: 7:28 AM becomes 12:00 PM)
-
- * Scale ``year`` always snap to full day.
-
- Example of precision attribute: ``{"day": "hour:quarter", "week": "day:half", "month": "day"}``
-``total_row``
- boolean to control whether the row containing the total count of records should
- be displayed. (default: ``false``)
-``collapse_first_level``
- boolean to control whether it is possible to collapse each row if grouped by
- one field. (default: ``false``, the collapse starts when grouping by two fields)
-``display_unavailability``
- boolean to mark the dates returned by the ``gantt_unavailability`` function of
- the model as available inside the gantt view. Records can still be scheduled
- in them, but their unavailability is visually displayed. (default: ``false``)
-``default_scale``
- default scale when rendering the view. Possible values are (default: ``month``):
-
- * ``day``
- * ``week``
- * ``month``
- * ``year``
-
-``scales``
- comma-separated list of allowed scales for this view. By default, all scales
- are allowed. For possible scale values to use in this list, see ``default_scale``.
-
-``templates``
- defines the :ref:`reference/qweb` template ``gantt-popover`` which is used
- when the user hovers over one of the records in the gantt view.
-
- The gantt view uses mostly-standard :ref:`javascript qweb
- <reference/qweb/javascript>` and provides the following context variables:
-
- ``widget``
- the current :js:class:`GanttRow`, can be used to fetch some
- meta-information. The ``getColor`` method to convert in a color integer is
- also available directly in the template context without using ``widget``.
-
- ``on_create``
- If specified when clicking the add button on the view, instead of opening a generic dialog, launch a client action.
- this should hold the xmlid of the action (eg: ``on_create="%(my_module.my_wizard)d"``
-
-``form_view_id``
- view to open when the user create or edit a record. Note that if this attribute
- is not set, the gantt view will fall back to the id of the form view in the
- current action, if any.
-
-``dynamic_range``
- if set to true, the gantt view will start at the first record,
- instead of starting at the beginning of the year/month/day.
-
-``thumbnails``
- This allows to display a thumbnail next to groups name if the group is a relationnal field.
- This expects a python dict which keys are the name of the field on the active model.
- Values are the names of the field holding the thumbnail on the related model.
-
- Example: tasks have a field user_id that reference res.users. The res.users model has a field image that holds the avatar,
- then:
-
- .. code-block:: xml
-
- <gantt
- date_start="date_start"
- date_stop="date_stop"
- thumbnails="{'user_id': 'image_128'}"
- >
- </gantt>
-
- will display the users avatars next to their names when grouped by user_id.
-
-.. _reference/views/graph:
-
-Graph
------
-
-The graph view is used to visualize aggregations over a number of records or
-record groups. Its root element is ``<graph>`` which can take the following
-attributes:
-
-``type``
- one of ``bar`` (default), ``pie`` and ``line``, the type of graph to use
-``stacked``
- only used for ``bar`` charts. If present and set to ``True``, stacks bars
- within a group
-``disable_linking``
- set to ``True`` to prevent from redirecting clicks on graph to list view
-``order``
- if set, x-axis values will be sorted by default according their measure with
- respect to the given order (``asc`` or ``desc``). Only used for ``bar`` and
- ``pie`` charts.
-
-The only allowed element within a graph view is ``field`` which can have the
-following attributes:
-
-``name`` (required)
- the name of a field to use in the view. If used for grouping (rather
- than aggregating)
-
-``title`` (optional)
- string displayed on the top of the graph.
-
-``invisible`` (optional)
- if true, the field will not appear either in the active measures nor in the
- selectable measures.
-
-``type``
- indicates whether the field should be used as a grouping criteria or as an
- aggregated value within a group. Possible values are:
-
- ``row`` (default)
- groups by the specified field. All graph types support at least one level
- of grouping, some may support more.
- ``col``
- authorized in graph views but only used by pivot tables
- ``measure``
- field to aggregate within a group
-
-``interval``
- on date and datetime fields, groups by the specified interval (``day``,
- ``week``, ``month``, ``quarter`` or ``year``) instead of grouping on the
- specific datetime (fixed second resolution) or date (fixed day resolution).
-
-The measures are automatically generated from the model fields; only the
-aggregatable fields are used. Those measures are also alphabetically
-sorted on the string of the field.
-
-.. warning::
-
- graph view aggregations are performed on database content, non-stored
- function fields can not be used in graph views
-
-.. _reference/views/kanban:
-
-Kanban
-------
-
-The kanban view is a `kanban board`_ visualisation: it displays records as
-"cards", halfway between a :ref:`list view <reference/views/list>` and a
-non-editable :ref:`form view <reference/views/form>`. Records may be grouped
-in columns for use in workflow visualisation or manipulation (e.g. tasks or
-work-progress management), or ungrouped (used simply to visualize records).
-
-.. note:: The kanban view will load and display a maximum of ten columns.
- Any column after that will be closed (but can still be opened by
- the user).
-
-The root element of the Kanban view is ``<kanban>``, it can use the following
-attributes:
-
-``default_group_by``
- whether the kanban view should be grouped if no grouping is specified via
- the action or the current search. Should be the name of the field to group
- by when no grouping is otherwise specified
-``default_order``
- cards sorting order used if the user has not already sorted the records (via
- the list view)
-``class``
- adds HTML classes to the root HTML element of the Kanban view
-``examples``
- if set to a key in the `KanbanExamplesRegistry`_, examples on column setups will be available in the grouped kanban view. `Here <https://github.com/odoo/odoo/blob/99821fdcf89aa66ac9561a972c6823135ebf65c0/addons/project/static/src/js/project_task_kanban_examples.js#L27>`_ is an example of how to define those setups.
-``group_create``
- whether the "Add a new column" bar is visible or not. Default: true.
-``group_delete``
- whether groups can be deleted via the context menu. Default: true.
-``group_edit``
- whether groups can be edited via the context menu. Default: true.
-``archivable``
- whether records belonging to a column can be archived / restored if an
- ``active`` field is defined on the model. Default: true.
-``quick_create``
- whether it should be possible to create records without switching to the
- form view. By default, ``quick_create`` is enabled when the Kanban view is
- grouped by many2one, selection, char or boolean fields, and disabled when not.
-``quick_create_view``
- ``form`` view reference, specifying the view used for records quick creation.
-``records_draggable``
- whether it should be possible to drag records when kanban is grouped. Default: true.
-
- Set to ``true`` to always enable it, and to ``false`` to always disable it.
-
-.. todo:: VFE missing information on on_create attribute of kanban views.
-
-Possible children of the view element are:
-
-``field``
- declares fields to use in kanban *logic*. If the field is simply displayed in
- the kanban view, it does not need to be pre-declared.
-
- Possible attributes are:
-
- ``name`` (required)
- the name of the field to fetch
-
-``progressbar``
- declares a progressbar element to put on top of kanban columns.
-
- Possible attributes are:
-
- ``field`` (required)
- the name of the field whose values are used to subgroup column's records in
- the progressbar
-
- ``colors`` (required)
- JSON mapping the above field values to either "danger", "warning", "success"
- or "muted" colors
-
- ``sum_field`` (optional)
- the name of the field whose column's records' values will be summed and
- displayed next to the progressbar (if omitted, displays the total number of
- records)
-
-``templates``
- defines a list of :ref:`reference/qweb` templates. Cards definition may be
- split into multiple templates for clarity, but kanban views *must* define at
- least one root template ``kanban-box``, which will be rendered once for each
- record.
-
- The kanban view uses mostly-standard :ref:`javascript qweb
- <reference/qweb/javascript>` and provides the following context variables:
-
- ``widget``
- the current :js:class:`KanbanRecord`, can be used to fetch some
- meta-information. These methods are also available directly in the
- template context and don't need to be accessed via ``widget``
- ``record``
- an object with all the requested fields as its attributes. Each field has
- two attributes ``value`` and ``raw_value``, the former is formatted
- according to current user parameters, the latter is the direct value from
- a :meth:`~odoo.models.Model.read` (except for date and datetime fields
- that are `formatted according to user's locale
- <https://github.com/odoo/odoo/blob/a678bd4e/addons/web_kanban/static/src/js/kanban_record.js#L102>`_)
- ``context``
- the current context, coming from the action, and the one2many or many2many
- field in the case of a Kanban view embedded in a Form view
- ``user_context``
- self-explanatory
- ``read_only_mode``
- self-explanatory
- ``selection_mode``
- set to true when kanban view is opened in mobile environment from m2o/m2m field
- for selecting records.
-
- .. note:: clicking on m2o/m2m field in mobile environment opens kanban view
-
-
- .. rubric:: buttons and fields
-
- While most of the Kanban templates are standard :ref:`reference/qweb`, the
- Kanban view processes ``field``, ``button`` and ``a`` elements specially:
-
- * by default fields are replaced by their formatted value, unless the
- ``widget`` attribute is specified, in which case their rendering and
- behavior depends on the corresponding widget. Possible values are (among
- others):
-
- ``handle``
- for ``sequence`` (or ``integer``) fields by which records are
- sorted, allows to drag&drop records to reorder them.
-
- .. todo:: list widgets?
-
- * buttons and links with a ``type`` attribute become perform Odoo-related
- operations rather than their standard HTML function. Possible types are:
-
- ``action``, ``object``
- standard behavior for :ref:`Odoo buttons
- <reference/views/list/button>`, most attributes relevant to standard
- Odoo buttons can be used.
- ``open``
- opens the card's record in the form view in read-only mode
- ``edit``
- opens the card's record in the form view in editable mode
- ``delete``
- deletes the card's record and removes the card
-
- .. todo::
-
- * kanban-specific CSS
- * kanban structures/widgets (vignette, details, ...)
-
-If you need to extend the Kanban view, see :js:class::`the JS API <KanbanRecord>`.
-
-Calendar
-~~~~~~~~
-
-Calendar views display records as events in a daily, weekly or monthly
-calendar. Their root element is ``<calendar>``. Available attributes on the
-calendar view are:
-
-``date_start`` (required)
- name of the record's field holding the start date for the event
-``date_stop``
- name of the record's field holding the end date for the event, if
- ``date_stop`` is provided records become movable (via drag and drop)
- directly in the calendar
-``date_delay``
- alternative to ``date_stop``, provides the duration of the event instead of
- its end date (unit: day)
-``color``
- name of a record field to use for *color segmentation*. Records in the
- same color segment are allocated the same highlight color in the calendar,
- colors are allocated semi-randomly.
- Displayed the display_name/avatar of the visible record in the sidebar
-``form_view_id``
- view to open when the user create or edit an event. Note that if this attribute
- is not set, the calendar view will fall back to the id of the form view in the
- current action, if any.
-``event_open_popup``
- If the option 'event_open_popup' is set to true, then the calendar view will
- open events (or records) in a FormViewDialog. Otherwise, it will open events
- in a new form view (with a do_action)
-``quick_add``
- enables quick-event creation on click: only asks the user for a ``name``
- and tries to create a new event with just that and the clicked event
- time. Falls back to a full form dialog if the quick creation fails
-``all_day``
- name of a boolean field on the record indicating whether the corresponding
- event is flagged as day-long (and duration is irrelevant)
-``mode``
- Default display mode when loading the calendar.
- Possible attributes are: ``day``, ``week``, ``month``
-``create``, ``delete``
- allows *dis*\ abling the corresponding action in the view by setting the
- corresponding attribute to ``false``
-``<field>``
- declares fields to aggregate or to use in kanban *logic*. If the field is
- simply displayed in the calendar cards.
-
-.. _reference/views/list:
-
-List
-----
-
-The root element of list views is ``<tree>``\ [#treehistory]_. The list view's
-root can have the following attributes:
-
-``editable``
- by default, selecting a list view's row opens the corresponding
- :ref:`form view <reference/views/form>`. The ``editable`` attributes makes
- the list view itself editable in-place.
-
- Valid values are ``top`` and ``bottom``, making *new* records appear
- respectively at the top or bottom of the list.
-
- The architecture for the inline :ref:`form view <reference/views/form>` is
- derived from the list view. Most attributes valid on a :ref:`form view
- <reference/views/form>`'s fields and buttons are thus accepted by list
- views although they may not have any meaning if the list view is
- non-editable
-
- .. note:: if the ``edit`` attribute is set to ``false``, the ``editable`` option will be ignored.
-
-``multi_edit``
- editable or not editable list can activate the multi-editing feature by defining
- the `multi_edit=1`
-
-``default_order``
- overrides the ordering of the view, replacing the model's order (:attr:`~odoo.models.BaseModel._order` model attribute).
- The value is a comma-separated list of fields, postfixed by ``desc`` to
- sort in reverse order:
-
- .. code-block:: xml
-
- <tree default_order="sequence,name desc">
-
-``decoration-{$name}``
- allow changing the style of a row's text based on the corresponding
- record's attributes.
-
- ``{$name}`` can be ``bf`` (``font-weight: bold``), ``it``
- (``font-style: italic``), or any `bootstrap contextual color`_ (``danger``,
- ``info``, ``muted``, ``primary``, ``success`` or ``warning``).
-``create``, ``edit``, ``delete``, ``duplicate``, ``import``, ``export_xlsx``
- allows *dis*\ abling the corresponding action in the view by setting the
- corresponding attribute to ``false``
-``limit``
- the default size of a page. It must be a positive integer
-``groups_limit``
- when the list view is grouped, the default number of groups of a page. It
- must be a position integer
-``expand``
- when the list view is grouped, automatically open the first level of groups
- if set to true (default: false)
-
-Possible children elements of the list view are:
-
-.. _reference/views/list/button:
-
-``button``
- displays a button in a list cell
-
- ``icon``
- icon to use to display the button
- ``string``
- * if there is no ``icon``, the button's text
- * if there is an ``icon``, ``alt`` text for the icon
- ``type``
- type of button, indicates how it clicking it affects Odoo:
-
- ``object``
- call a method on the list's model. The button's ``name`` is the
- method, which is called with the current row's record id and the
- current context.
-
- .. web client also supports a @args, which allows providing
- additional arguments as JSON. Should that be documented? Does
- not seem to be used anywhere
-
- ``action``
- load an execute an ``ir.actions``, the button's ``name`` is the
- database id of the action. The context is expanded with the list's
- model (as ``active_model``), the current row's record
- (``active_id``) and all the records currently loaded in the list
- (``active_ids``, may be just a subset of the database records
- matching the current search)
- ``name``
- see ``type``
- ``args``
- see ``type``
- ``attrs``
- dynamic attributes based on record values.
-
- A mapping of attributes to domains, domains are evaluated in the
- context of the current row's record, if ``True`` the corresponding
- attribute is set on the cell.
-
- Possible attribute is ``invisible`` (hides the button).
- ``states``
- shorthand for ``invisible`` ``attrs``: a list of states, comma separated,
- requires that the model has a ``state`` field and that it is
- used in the view.
-
- Makes the button ``invisible`` if the record is *not* in one of the
- listed states
-
- .. danger::
-
- Using ``states`` in combination with ``attrs`` may lead to
- unexpected results as domains are combined with a logical AND.
- ``context``
- merged into the view's context when performing the button's Odoo call
-
- .. todo:: declared but unused: help
-
-``field``
- defines a column where the corresponding field should be displayed for
- each record. Can use the following attributes:
-
- ``name``
- the name of the field to display in the current model. A given name
- can only be used once per view
- ``string``
- the title of the field's column (by default, uses the ``string`` of
- the model's field)
- ``invisible``
- fetches and stores the field, but doesn't display the column in the
- table. Necessary for fields which shouldn't be displayed but are
- used by e.g. ``@colors``
- ``groups``
- lists the groups which should be able to see the field
- ``widget``
- alternate representations for a field's display. Possible list view
- values are (among others):
-
- ``progressbar``
- displays ``float`` fields as a progress bar.
- ``handle``
- for ``sequence`` (or ``integer``) fields by which records are
- sorted, instead of displaying the field's value just displays a
- drag&drop icon to reorder records.
- ``sum``, ``avg``
- displays the corresponding aggregate at the bottom of the column. The
- aggregation is only computed on *currently displayed* records. The
- aggregation operation must match the corresponding field's
- ``group_operator``
- ``attrs``
- dynamic attributes based on record values. Only effects the current
- field, so e.g. ``invisible`` will hide the field but leave the same
- field of other records visible, it will not hide the column itself
- ``width`` (for ``editable``)
- when there is no data in the list, the width of a column can be forced
- by setting this attribute. The value can be an absolute width (e.g.
- '100px'), or a relative weight (e.g. '3', meaning that this column will
- be 3 times larger than the others). Note that when there are records in
- the list, we let the browser automatically adapt the column's widths
- according to their content, and this attribute is thus ignored.
- ``decoration-{$name}``
- allow changing the style of a cell's text based on the corresponding
- record's attributes.
-
- ``{$name}`` can be ``bf`` (``font-weight: bold``), ``it``
- (``font-style: italic``), or any `bootstrap contextual color`_ (``danger``,
- ``info``, ``muted``, ``primary``, ``success`` or ``warning``).
- ``nolabel``
- if set to "1", the column header will remain empty. Also, the column
- won't be sortable.
-
- .. note::
-
- if the list view is ``editable``, any field attribute from the
- :ref:`form view <reference/views/form>` is also valid and will
- be used when setting up the inline form view.
-
- .. note::
-
- In case of list sub-views (One2many/Many2many display in a form view),
- The attribute ``column_invisible`` can be useful to hide a column
- depending on the parent object.
-
- .. code-block:: xml
-
- <field name="product_is_late" attrs="{'column_invisible': [('parent.has_late_products', '=', False)]}"/>
-
- .. note:: When a list view is grouped, numeric fields are aggregated and
- displayed for each group. Also, if there are too many records in
- a group, a pager will appear on the right of the group row. For
- this reason, it is not a good practice to have a numeric field in
- the last column, when the list view is in a situation where it can
- be grouped (it is however fine for x2manys field in a form view:
- they cannot be grouped).
-
-``groupby``
- defines custom headers (with buttons) for the current view when grouping
- records on many2one fields. It is also possible to add `field`, inside the
- `groupby` which can be used for modifiers. These fields thus belong on the
- many2one comodel. These extra fields will be fetched in batch.
-
- ``name``
- the name of a many2one field (on the current model). Custom header will be
- displayed when grouping the view on this field name.
-
- .. code-block:: xml
-
- <groupby name="partner_id">
- <field name="name"/> <!-- name of partner_id -->
- <button type="edit" name"edit" string="Edit/>
- <button type="object" name="my_method" string="Button1"
- attrs="{'invisible': [('name', '=', 'Georges')]}"/>
- </groupby>
-
- A special button (`type="edit"`) can be defined to open the many2one form view.
-
-``control``
- defines custom controls for the current view.
-
- This makes sense if the parent ``tree`` view is inside a One2many field.
-
- Does not support any attribute, but can have children:
-
- ``create``
- adds a button to create a new element on the current list.
-
- .. note:: If any ``create`` is defined, it will overwrite the default
- "add a line" button.
-
- The following attributes are supported:
-
- ``string`` (required)
- The text displayed on the button.
-
- ``context``
- This context will be merged into the existing context
- when retrieving the default value of the new record.
-
- For example it can be used to override default values.
-
-
- The following example will override the default "add a line" button
- by replacing it with 3 new buttons:
- "Add a product", "Add a section" and "Add a note".
-
- "Add a product" will set the field 'display_type' to its default value.
-
- The two other buttons will set the field 'display_type'
- to be respectively 'line_section' and 'line_note'.
-
- .. code-block:: xml
-
- <control>
- <create
- string="Add a product"
- />
- <create
- string="Add a section"
- context="{'default_display_type': 'line_section'}"
- />
- <create
- string="Add a note"
- context="{'default_display_type': 'line_note'}"
- />
- </control>
-
-.. [#treehistory] for historical reasons, it has its origin in tree-type views
- later repurposed to a more table/list-type display
-
-.. _reference/views/map:
-
-Map
----
-
-.. raw:: html
-
- <span class="badge" style="background-color:#AD5E99">Enterprise feature</span>
-
-This view is able to display records on a map and the routes between them. The record are represented by pins. It also allows the visualization of fields from the model in a popup tied to the record's pin.
-
-.. note::
-
- The model on which the view is applied should contains a res.partner many2one since the view relies on the res.partner's address and coordinates fields to localize the records.
-
-.. _reference/views/map/api:
-
-Api
-~~~
-
-The view uses location data platforms' api to fetch the tiles (the map's background), do the geoforwarding (converting addresses to a set of coordinates) and fetch the routes.
-The view implements two api, the default one, openstreet map is able to fetch `tiles`_ and do `geoforwarding`_. This api does not require a token.
-As soon as a valid `MapBox`_ token is provided in the general settings the view switches to the Mapbox api. This api is faster and allows the computation of routes. The token are available by `signing up`_ to MapBox
-
-.. _reference/views/structural components:
-
-Structural components
-~~~~~~~~~~~~~~~~~~~~~
-
-The view's root element is ``<map>`` multiple attributes are allowed
-
-``res_partner``
- Contains the res.partner many2one. If not provided the view will resort to create an empty map.
-``default_order``
- If a field is provided the view will override the model's default order. The field must be part of the model on which the view is applied not from res.partner
-``routing``
- if ``true`` the routes between the records will be shown. The view still needs a valid MapBox token and at least two located records. (i.e the records has a res.partner many2one and the partner has a address or valid coordinates)
-``hide_name``
- if ``true`` hide a name from the marker's popup (default: false)
-``hide_address``
- if ``true`` hide a address from the marker's popup (default: false)
-
-The ``<map>`` element can contain multiple ``<field>`` elements. Each ``<field>`` element will be interpreted as a line in the marker's popup. The field's attributes are the following:
-
-``name``
- The field to display.
-``string``
- This string will be displayed before the field's content. It Can be used as a description.
-``limit``
- The size of a page (default: 80). It must be a positive integer.
-
-No attribute or element is mandatory but as stated above if no res.partner many2one is provided the view won't be able to locate records.
-
-For example here is a map:
- .. code-block:: xml
-
- <map res_partner="partner_id" default_order="date_begin" routing="true" hide_name="true">
- <field name="partner_id" string="Customer Name"/>
- </map>
-
-.. _reference/views/pivot:
-
-Pivot
------
-
-The pivot view is used to visualize aggregations as a `pivot table`_. Its root
-element is ``<pivot>`` which can take the following attributes:
-
-``disable_linking``
- Set to ``True`` to remove table cell's links to list view.
-``display_quantity``
- Set to ``true`` to display the Quantity column by default.
-``default_order``
- The name of the measure and the order (asc or desc) to use as default order
- in the view.
-
- .. code-block:: xml
-
- <pivot default_order="foo asc">
- <field name="foo" type="measure"/>
- </pivot>
-
-The only allowed element within a pivot view is ``field`` which can have the
-following attributes:
-
-``name`` (required)
- the name of a field to use in the view. If used for grouping (rather
- than aggregating)
-
-``string``
- the name that will be used to display the field in the pivot view,
- overrides the default python String attribute of the field.
-
-``type``
- indicates whether the field should be used as a grouping criteria or as an
- aggregated value within a group. Possible values are:
-
- ``row`` (default)
- groups by the specified field, each group gets its own row.
- ``col``
- creates column-wise groups
- ``measure``
- field to aggregate within a group
- ``interval``
- on date and datetime fields, groups by the specified interval (``day``,
- ``week``, ``month``, ``quarter`` or ``year``) instead of grouping on the
- specific datetime (fixed second resolution) or date (fixed day resolution).
-
-``invisible``
- if true, the field will not appear either in the active measures nor in the
- selectable measures (useful for fields that do not make sense aggregated,
- such as fields in different units, e.g. € and $).
-
-The measures are automatically generated from the model fields; only the
-aggregatable fields are used. Those measures are also alphabetically
-sorted on the string of the field.
-
-.. warning::
-
- like the graph view, the pivot aggregates data on database content
- which means that non-stored function fields can not be used in pivot views
-
-
-In Pivot view a ``field`` can have a ``widget`` attribute to dictate its format.
-The widget should be a field formatter, of which the most interesting are
-``date``, ``datetime``, ``float_time``, and ``monetary``.
-
-For instance a timesheet pivot view could be defined as::
-
- <pivot string="Timesheet">
- <field name="employee_id" type="row"/>
- <field name="date" interval="month" type="col"/>
- <field name="unit_amount" type="measure" widget="float_time"/>
- </pivot>
-
-.. _reference/views/qweb:
-
-QWeb
-----
-
-QWeb views are standard :ref:`reference/qweb` templates inside a view's
-``arch``. They don't have a specific root element. Because QWeb views don't
-have a specific root element, their type must be specified explicitly (it can
-not be inferred from the root element of the ``arch`` field).
-
-QWeb views have two use cases:
-
-* they can be used as frontend templates, in which case
- :ref:`reference/data/template` should be used as a shortcut.
-* they can be used as actual qweb views (opened inside an action), in which
- case they should be defined as regular view with an explicit ``type`` (it
- can not be inferred) and a model.
-
-The main additions of qweb-as-view to the basic qweb-as-template are:
-
-* qweb-as-view has a special case for a ``<nav>`` element bearing the CSS
- class ``o_qweb_cp_buttons``: its contents should be buttons and will be
- extracted and moved to the control panel's button area, the ``<nav>`` itself
- will be removed, this is a work-around to control panel views not existing
- yet
-* qweb-as-view rendering adds several items to the standard qweb rendering
- context:
-
- ``model``
- the model to which the qweb view is bound
- ``domain``
- the domain provided by the search view
- ``context``
- the context provided by the search view
- ``records``
- a lazy proxy to ``model.search(domain)``, this can be used if you just
- want to iterate the records and not perform more complex operations
- (e.g. grouping)
-* qweb-as-view also provides additional rendering hooks:
-
- - ``_qweb_prepare_context(view_id, domain)`` prepares the rendering context
- specific to qweb-as-view
- - ``qweb_render_view(view_id, domain)`` is the method called by the client
- and will call the context-preparation methods and ultimately
- ``env['ir.qweb'].render()``.
-
-.. _reference/views/search:
-
-Search
-------
-
-Search views are a break from previous view types in that they don't display
-*content*: although they apply to a specific model, they are used to filter
-other view's content (generally aggregated views
-e.g. :ref:`reference/views/list` or :ref:`reference/views/graph`). Beyond that
-difference in use case, they are defined the same way.
-
-The root element of search views is ``<search>``. It takes no attributes.
-
-.. @string is not displayed anywhere, should be removed
-
-Possible children elements of the search view are:
-
-``field``
- fields define domains or contexts with user-provided values. When search
- domains are generated, field domains are composed with one another and
- with filters using **AND**.
-
- Fields can have the following attributes:
-
- ``name``
- the name of the field to filter on
- ``string``
- the field's label
- ``operator``
- by default, fields generate domains of the form :samp:`[({name},
- {operator}, {provided_value})]` where ``name`` is the field's name and
- ``provided_value`` is the value provided by the user, possibly
- filtered or transformed (e.g. a user is expected to provide the
- *label* of a selection field's value, not the value itself).
-
- The ``operator`` attribute allows overriding the default operator,
- which depends on the field's type (e.g. ``=`` for float fields but
- ``ilike`` for char fields)
- ``filter_domain``
- complete domain to use as the field's search domain, can use a
- ``self`` variable to inject the provided value in the custom
- domain. Can be used to generate significantly more flexible domains
- than ``operator`` alone (e.g. searches on multiple fields at once)
-
- If both ``operator`` and ``filter_domain`` are provided,
- ``filter_domain`` takes precedence.
- ``context``
- allows adding context keys, including the user-provided values (which
- as for ``domain`` are available as a ``self`` variable, an array of
- values e.g. ``[id_1, id_2]`` for a :class:`~odoo.fields.Many2one` field).
- By default, fields don't generate domains.
-
- .. note:: the domain and context are inclusive and both are generated
- if a ``context`` is specified. To only generate context
- values, set ``filter_domain`` to an empty list:
- ``filter_domain="[]"``
- ``groups``
- make the field only available to specific users
- ``domain``
- if the field can provide an auto-completion
- (e.g. :class:`~odoo.fields.Many2one`), filters the possible
- completion results.
-
-``filter``
- a filter is a predefined toggle in the search view, it can only be enabled
- or disabled. Its main purposes are to add data to the search context (the
- context passed to the data view for searching/filtering), or to append new
- sections to the search filter.
-
- Filters can have the following attributes:
-
- ``string`` (required)
- the label of the filter
- ``domain`` (optional)
- an Odoo :ref:`domain <reference/orm/domains>`, will be appended to the
- action's domain as part of the search domain.
- ``date`` (optional)
- the name of a field of type ``date`` or ``datetime``.
- Using this attribute has the effect to create
- a set of filters available in a submenu
- of the filters menu. The filters proposed are time dependent
- but not dynamic in the sense that their domains are evaluated
- at the time of the control panel instantiation.
-
- Example:
-
- .. code-block:: xml
-
- <filter name="filter_create_date" date="create_date" string="Creation Date"/>
-
- The example above allows to easily search for records with creation date field
- values in one of the periods below (if the current month is August 2019).
-
- .. code-block:: text
-
- Create Date >
- August
- July
- June
- Q4
- Q3
- Q2
- Q1
- --------------
- 2019
- 2018
- 2017
-
- Muti selection of options is allowed.
-
- ``default_period`` (optional)
- only makes sense for a filter with non empty ``date`` attribute.
- determines which period is activated if the filter is in the
- default set of filters activated at the view initialization. If not provided,
- 'this_month' is used by default.
-
- To choose among the following options:
- today, this_week, this_month, last_month, antepenultimate_month,
- fourth_quarter, third_quarter, second_quarter, first_quarter,
- this_year, last_year, antepenultimate_year.
-
- Example:
-
- .. code-block:: xml
-
- <filter name="filter_create_date" date="create_date" string="Creation Date" default_period="this_week"/>
-
- ``context``
- a Python dictionary, merged into the action's domain to generate the
- search domain
-
- The key ``group_by`` can be used to define a groupby available in the
- 'Group By' menu. The 'group_by' value can be a valid field name.
-
- .. code-block:: xml
-
- <filter name="groupby_category" string="Category" context = {'group_by': 'category_id'}/>
-
- The groupby defined above allows to group data by category.
-
- When the field is of type ``date`` or ``datetime``, the filter generates a submenu of the Group By
- menu in which the following interval options are available: day, week, month, quarter, year.
-
- In case the filter is in the default set of filters activated at the view initialization,
- the records are grouped by month by default. This can be changed by using the syntax
- 'date_field:interval' as in the following example.
-
- Example:
-
- .. code-block:: xml
-
- <filter name="groupby_create_date" string="Creation Date" context = {'group_by': 'create_date:week'}/>
-
- .. note::
- The results of read_groups grouped on a field may be influenced by its group_expand attribute,
- allowing to display empty groups when needed. For more information, please refer to
- :class:`~odoo.fields.Field` attributes documentation.
-
- ``name``
- logical name for the filter, can be used to :ref:`enable it by default
- <reference/views/search/defaults>`, can also be used as
- :ref:`inheritance hook <reference/views/inheritance>`
- ``help``
- a longer explanatory text for the filter, may be displayed as a
- tooltip
- ``groups``
- makes a filter only available to specific users
-
- .. tip::
-
- .. versionadded:: 7.0
-
- Sequences of filters (without non-filters separating them) are treated
- as inclusively composited: they will be composed with ``OR`` rather
- than the usual ``AND``, e.g.
-
- ::
-
- <filter domain="[('state', '=', 'draft')]"/>
- <filter domain="[('state', '=', 'done')]"/>
-
- if both filters are selected, will select the records whose ``state``
- is ``draft`` or ``done``, but
-
- ::
-
- <filter domain="[('state', '=', 'draft')]"/>
- <separator/>
- <filter domain="[('delay', '<', 15)]"/>
-
- if both filters are selected, will select the records whose ``state``
- is ``draft`` **and** ``delay`` is below 15.
-
-``separator``
- can be used to separates groups of filters in simple search views
-
-``group``
- can be used to separate groups of filters, more readable than
- ``separator`` in complex search views
-
-``searchpanel``
- allows to display a search panel on the left of any multi records view.
- By default, the list and kanban views have the searchpanel enabled.
- The search panel can be activated on other views with the attribute:
-
- * ``view_types`` a comma separated list of view types on which to enable the search panel
- default: 'tree,kanban'
-
- This tool allows to quickly filter data on the basis of given fields. The fields
- are specified as direct children of the ``searchpanel`` with tag name ``field``,
- and the following attributes:
-
- * ``name`` (mandatory) the name of the field to filter on
-
- * ``select`` determines the behavior and display. Possible values are
-
- * ``one`` (default) at most one value can be selected. Supported field types are
- many2one and selection.
-
- * ``multi`` several values can be selected (checkboxes). Supported field
- types are many2one, many2many and selection.
-
- * ``groups``: restricts to specific users
-
- * ``string``: determines the label to display
-
- * ``icon``: specifies which icon is used
-
- * ``color``: determines the icon color
-
- * ``enable_counters``: default is false. If set to true the record counters will be computed and
- displayed if non-zero.
-
- This feature has been implemented in case performances would be too bad.
-
- Another way to solve performance issues is to properly override the
- ``search_panel_select_range`` and ``search_panel_select_multi_range`` methods.
-
- * ``expand``: default is false. If set to false categories or filters with 0 records will be hidden.
-
- * ``limit``: default is 200. Integer determining the maximal number of values to fetch for the field.
- If the limit is reached, no values will be displayed in the search panel and an error message will
- appear instead because we consider that is useless / bad performance-wise. All values will be
- fetched if set to 0.
-
- Additional optional attributes are available according to the chosen case:
-
- For the ``one`` case:
-
- * ``hierarchize``: (only available for many2one fields) default is true. Handles the display style of categories :
-
- If set to true child categories will appear under their related parent.
- If not, all categories will be displayed on the same level.
-
- For the ``multi`` case:
-
- * ``domain``: determines conditions that the comodel records have to satisfy.
-
- A domain might be used to express a dependency on another field (with select="one")
- of the search panel. Consider
- /!\ This attribute is incompatible with a select="one" with enabled counters; if a select="multi"
- has a `domain` attribute, all select="one" will have their counters disabled.
-
- .. code-block:: xml
-
- <searchpanel>
- <field name="department_id"/>
- <field name="manager_id" select="multi" domain="[('department_id', '=', department_id)]"/>
- <searchpanel/>
-
- In the above example, the range of values for manager_id (manager names) available at screen
- will depend on the value currently selected for the field ``department_id``.
-
- * ``groupby``: field name of the comodel (only available for many2one and many2many fields). Values will be grouped by that field.
-
-
-.. _reference/views/search/defaults:
-
-Search defaults
-~~~~~~~~~~~~~~~
-
-Search fields and filters can be configured through the action's ``context``
-using :samp:`search_default_{name}` keys. For fields, the value should be the
-value to set in the field, for filters it's a boolean value or a number. For instance,
-assuming ``foo`` is a field and ``bar`` is a filter an action context of:
-
-.. code-block:: python
-
- {
- 'search_default_foo': 'acro',
- 'search_default_bar': 1
- }
-
-will automatically enable the ``bar`` filter and search the ``foo`` field for
-*acro*.
-
-A numeric value (between 1 and 99) can be used to describe the order of default groupbys.
-For instance if ``foo`` and ``bar`` refer to two groupbys
-
-.. code-block:: python
-
- {
- 'search_default_foo': 2,
- 'search_default_bar': 1
- }
-
-has the effect to activate first ``bar`` then ``foo``.
-
-.. todo:: View Grid
-
-.. _bootstrap contextual color: https://getbootstrap.com/docs/3.3/components/#available-variations
-.. _geoforwarding: https://nominatim.org/release-docs/develop/
-.. _tiles: https://wiki.openstreetmap.org/wiki/Tile_data_server
-.. _MapBox: https://docs.mapbox.com/api/
-.. _signing up: https://account.mapbox.com/auth/signup/
-.. _accesskey: https://www.w3.org/TR/html5/editing.html#the-accesskey-attribute
-.. _floats: https://developer.mozilla.org/en-US/docs/Web/CSS/float
-.. _HTML: https://en.wikipedia.org/wiki/HTML
-.. _kanban board: https://en.wikipedia.org/wiki/Kanban_board
-.. _pivot table: https://en.wikipedia.org/wiki/Pivot_table
-.. _XPath: https://en.wikipedia.org/wiki/XPath
-.. _KanbanExamplesRegistry: https://github.com/odoo/odoo/blob/99821fdcf89aa66ac9561a972c6823135ebf65c0/addons/web/static/src/js/views/kanban/kanban_examples_registry.js
diff --git a/doc/requirements.txt b/doc/requirements.txt
deleted file mode 100644
index 33836149c6d..00000000000
--- a/doc/requirements.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-sphinx>=1.6.7
-sphinx-patchqueue>=1.0
diff --git a/doc/setup.rst b/doc/setup.rst
deleted file mode 100644
index 7b03c885e77..00000000000
--- a/doc/setup.rst
+++ /dev/null
@@ -1,15 +0,0 @@
-:types: setting_up
-
-==========
-Setting Up
-==========
-
-.. toctree::
- :titlesonly:
-
- setup/install
- setup/deploy
- setup/update
- setup/cdn
- setup/enterprise
- setup/email_gateway
diff --git a/doc/setup/cdn.rst b/doc/setup/cdn.rst
deleted file mode 100644
index c21323b1467..00000000000
--- a/doc/setup/cdn.rst
+++ /dev/null
@@ -1,82 +0,0 @@
-:banner: banners/cdn.jpg
-
-========================================
-Deploying with Content Delivery Networks
-========================================
-
-.. _reference/cdn/keycdn:
-
-Deploying with KeyCDN_
-======================
-
-.. sectionauthor:: Fabien Meghazi
-
-This document will guide you through the setup of a KeyCDN_ account with your
-Odoo powered website.
-
-Step 1: Create a pull zone in the KeyCDN dashboard
---------------------------------------------------
-
-.. image:: cdn/keycdn_create_a_pull_zone.png
- :class: img-responsive
-
-When creating the zone, enable the CORS option in the
-:guilabel:`advanced features` submenu. (more on that later)
-
-.. image:: cdn/keycdn_enable_CORS.png
- :class: img-responsive
-
-Once done, you'll have to wait a bit while KeyCDN_ is crawling your website.
-
-.. image:: cdn/keycdn_progressbar.png
- :class: img-responsive
-
-.. note:: a new URL has been generated for your Zone, in this case it is
- ``http://pulltest-b49.kxcdn.com``
-
-Step 2: Configure the odoo instance with your zone
---------------------------------------------------
-
-In the Odoo back end, go to the :guilabel:`Website Settings`: menu, then
-activate the CDN support and copy/paste your zone URL in the
-:guilabel:`CDN Base URL` field. This field is only visible and configurable if
-you have developer mode activated.
-
-.. image:: cdn/odoo_cdn_base_url.png
- :class: img-responsive
-
-Now your website is using the CDN for the resources matching the
-:guilabel:`CDN filters` regular expressions.
-
-You can have a look to the HTML of your website in order to check if the CDN
-integration is properly working.
-
-.. image:: cdn/odoo_check_your_html.png
- :class: img-responsive
-
-
-Why should I activate CORS?
----------------------------
-
-A security restriction in some browsers (Firefox and Chrome at time of writing)
-prevents a remotely linked CSS file to fetch relative resources on this same
-external server.
-
-If you don't activate the CORS option in the CDN zone, the more obvious
-resulting problem on a default Odoo website will be the lack of font-awesome
-icons because the font file declared in the font-awesome CSS won't be loaded on
-the remote server.
-
-Here's what you would see on your homepage in such a case:
-
-.. image:: cdn/odoo_font_file_not_loaded.png
- :class: img-responsive
-
-A security error message will also appear in the browser's console:
-
-.. image:: cdn/odoo_security_message.png
- :class: img-responsive
-
-Enabling the CORS option in the CDN fixes this issue.
-
-.. _KeyCDN: https://www.keycdn.com
diff --git a/doc/setup/cdn/keycdn_create_a_pull_zone.png b/doc/setup/cdn/keycdn_create_a_pull_zone.png
deleted file mode 100644
index f2f132722aa..00000000000
--- a/doc/setup/cdn/keycdn_create_a_pull_zone.png
+++ /dev/null
Binary files differ
diff --git a/doc/setup/cdn/keycdn_enable_CORS.png b/doc/setup/cdn/keycdn_enable_CORS.png
deleted file mode 100644
index a08e7afa4c4..00000000000
--- a/doc/setup/cdn/keycdn_enable_CORS.png
+++ /dev/null
Binary files differ
diff --git a/doc/setup/cdn/keycdn_progressbar.png b/doc/setup/cdn/keycdn_progressbar.png
deleted file mode 100644
index baae602e128..00000000000
--- a/doc/setup/cdn/keycdn_progressbar.png
+++ /dev/null
Binary files differ
diff --git a/doc/setup/cdn/odoo_cdn_base_url.png b/doc/setup/cdn/odoo_cdn_base_url.png
deleted file mode 100644
index 4eea1fad643..00000000000
--- a/doc/setup/cdn/odoo_cdn_base_url.png
+++ /dev/null
Binary files differ
diff --git a/doc/setup/cdn/odoo_check_your_html.png b/doc/setup/cdn/odoo_check_your_html.png
deleted file mode 100644
index f50c11a1c15..00000000000
--- a/doc/setup/cdn/odoo_check_your_html.png
+++ /dev/null
Binary files differ
diff --git a/doc/setup/cdn/odoo_font_file_not_loaded.png b/doc/setup/cdn/odoo_font_file_not_loaded.png
deleted file mode 100644
index 4f0448a9eb6..00000000000
--- a/doc/setup/cdn/odoo_font_file_not_loaded.png
+++ /dev/null
Binary files differ
diff --git a/doc/setup/cdn/odoo_security_message.png b/doc/setup/cdn/odoo_security_message.png
deleted file mode 100644
index 13d06e8ac0f..00000000000
--- a/doc/setup/cdn/odoo_security_message.png
+++ /dev/null
Binary files differ
diff --git a/doc/setup/deploy.rst b/doc/setup/deploy.rst
deleted file mode 100644
index 944d6dddc91..00000000000
--- a/doc/setup/deploy.rst
+++ /dev/null
@@ -1,662 +0,0 @@
-:banner: banners/deploying_odoo.jpg
-
-==============
-Deploying Odoo
-==============
-
-This document describes basic steps to set up Odoo in production or on an
-internet-facing server. It follows :ref:`installation <setup/install>`, and is
-not generally necessary for a development systems that is not exposed on the
-internet.
-
-.. warning:: If you are setting up a public server, be sure to check our :ref:`security` recommandations!
-
-
-.. _db_filter:
-
-dbfilter
-========
-
-Odoo is a multi-tenant system: a single Odoo system may run and serve a number
-of database instances. It is also highly customizable, with customizations
-(starting from the modules being loaded) depending on the "current database".
-
-This is not an issue when working with the backend (web client) as a logged-in
-company user: the database can be selected when logging in, and customizations
-loaded afterwards.
-
-However it is an issue for non-logged users (portal, website) which aren't
-bound to a database: Odoo needs to know which database should be used to load
-the website page or perform the operation. If multi-tenancy is not used that is not an
-issue, there's only one database to use, but if there are multiple databases
-accessible Odoo needs a rule to know which one it should use.
-
-That is one of the purposes of :option:`--db-filter <odoo-bin --db-filter>`:
-it specifies how the database should be selected based on the hostname (domain)
-that is being requested. The value is a `regular expression`_, possibly
-including the dynamically injected hostname (``%h``) or the first subdomain
-(``%d``) through which the system is being accessed.
-
-For servers hosting multiple databases in production, especially if ``website``
-is used, dbfilter **must** be set, otherwise a number of features will not work
-correctly.
-
-Configuration samples
----------------------
-
-* Show only databases with names beginning with 'mycompany'
-
-in ``/etc/odoo.conf`` set:
-
-.. code-block:: ini
-
- [options]
- dbfilter = ^mycompany.*$
-
-* Show only databases matching the first subdomain after ``www``: for example
- the database "mycompany" will be shown if the incoming request
- was sent to ``www.mycompany.com`` or ``mycompany.co.uk``, but not
- for ``www2.mycompany.com`` or ``helpdesk.mycompany.com``.
-
-in ``/etc/odoo.conf`` set:
-
-.. code-block:: ini
-
- [options]
- dbfilter = ^%d$
-
-.. note::
- Setting a proper :option:`--db-filter <odoo-bin --db-filter>` is an important part
- of securing your deployment.
- Once it is correctly working and only matching a single database per hostname, it
- is strongly recommended to block access to the database manager screens,
- and to use the ``--no-database-list`` startup paramater to prevent listing
- your databases, and to block access to the database management screens.
- See also security_.
-
-
-PostgreSQL
-==========
-
-By default, PostgreSQL only allows connection over UNIX sockets and loopback
-connections (from "localhost", the same machine the PostgreSQL server is
-installed on).
-
-UNIX socket is fine if you want Odoo and PostgreSQL to execute on the same
-machine, and is the default when no host is provided, but if you want Odoo and
-PostgreSQL to execute on different machines [#different-machines]_ it will
-need to `listen to network interfaces`_ [#remote-socket]_, either:
-
-* Only accept loopback connections and `use an SSH tunnel`_ between the
- machine on which Odoo runs and the one on which PostgreSQL runs, then
- configure Odoo to connect to its end of the tunnel
-* Accept connections to the machine on which Odoo is installed, possibly
- over ssl (see `PostgreSQL connection settings`_ for details), then configure
- Odoo to connect over the network
-
-Configuration sample
---------------------
-
-* Allow tcp connection on localhost
-* Allow tcp connection from 192.168.1.x network
-
-in ``/etc/postgresql/9.5/main/pg_hba.conf`` set:
-
-.. code-block:: text
-
- # IPv4 local connections:
- host all all 127.0.0.1/32 md5
- host all all 192.168.1.0/24 md5
-
-in ``/etc/postgresql/9.5/main/postgresql.conf`` set:
-
-.. code-block:: text
-
- listen_addresses = 'localhost,192.168.1.2'
- port = 5432
- max_connections = 80
-
-.. _setup/deploy/odoo:
-
-Configuring Odoo
-----------------
-
-Out of the box, Odoo connects to a local postgres over UNIX socket via port
-5432. This can be overridden using :ref:`the database options
-<reference/cmdline/server/database>` when your Postgres deployment is not
-local and/or does not use the installation defaults.
-
-The :ref:`packaged installers <setup/install/packaged>` will automatically
-create a new user (``odoo``) and set it as the database user.
-
-* The database management screens are protected by the ``admin_passwd``
- setting. This setting can only be set using configuration files, and is
- simply checked before performing database alterations. It should be set to
- a randomly generated value to ensure third parties can not use this
- interface.
-* All database operations use the :ref:`database options
- <reference/cmdline/server/database>`, including the database management
- screen. For the database management screen to work requires that the PostgreSQL user
- have ``createdb`` right.
-* Users can always drop databases they own. For the database management screen
- to be completely non-functional, the PostgreSQL user needs to be created with
- ``no-createdb`` and the database must be owned by a different PostgreSQL user.
-
- .. warning:: the PostgreSQL user *must not* be a superuser
-
-Configuration sample
-~~~~~~~~~~~~~~~~~~~~
-
-* connect to a PostgreSQL server on 192.168.1.2
-* port 5432
-* using an 'odoo' user account,
-* with 'pwd' as a password
-* filtering only db with a name beginning with 'mycompany'
-
-in ``/etc/odoo.conf`` set:
-
-.. code-block:: ini
-
- [options]
- admin_passwd = mysupersecretpassword
- db_host = 192.168.1.2
- db_port = 5432
- db_user = odoo
- db_password = pwd
- dbfilter = ^mycompany.*$
-
-.. _postgresql_ssl_connect:
-
-SSL Between Odoo and PostgreSQL
--------------------------------
-
-Since Odoo 11.0, you can enforce ssl connection between Odoo and PostgreSQL.
-in Odoo the db_sslmode control the ssl security of the connection
-with value choosed out of 'disable', 'allow', 'prefer', 'require', 'verify-ca'
-or 'verify-full'
-
-`PostgreSQL Doc <https://www.postgresql.org/docs/current/static/libpq-ssl.html>`_
-
-.. _builtin_server:
-
-Builtin server
-==============
-
-Odoo includes built-in HTTP servers, using either multithreading or
-multiprocessing.
-
-For production use, it is recommended to use the multiprocessing server as it
-increases stability, makes somewhat better use of computing resources and can
-be better monitored and resource-restricted.
-
-* Multiprocessing is enabled by configuring :option:`a non-zero number of
- worker processes <odoo-bin --workers>`, the number of workers should be based
- on the number of cores in the machine (possibly with some room for cron
- workers depending on how much cron work is predicted)
-* Worker limits can be configured based on the hardware configuration to avoid
- resources exhaustion
-
-.. warning:: multiprocessing mode currently isn't available on Windows
-
-
-Worker number calculation
--------------------------
-
-* Rule of thumb : (#CPU * 2) + 1
-* Cron workers need CPU
-* 1 worker ~= 6 concurrent users
-
-memory size calculation
------------------------
-
-* We consider 20% of the requests are heavy requests, while 80% are simpler ones
-* A heavy worker, when all computed field are well designed, SQL requests are well designed, ... is estimated to consume around 1GB of RAM
-* A lighter worker, in the same scenario, is estimated to consume around 150MB of RAM
-
-Needed RAM = #worker * ( (light_worker_ratio * light_worker_ram_estimation) + (heavy_worker_ratio * heavy_worker_ram_estimation) )
-
-LiveChat
---------
-
-In multiprocessing, a dedicated LiveChat worker is automatically started and
-listening on :option:`the longpolling port <odoo-bin --longpolling-port>` but
-the client will not connect to it.
-
-Instead you must have a proxy redirecting requests whose URL starts with
-``/longpolling/`` to the longpolling port. Other request should be proxied to
-the :option:`normal HTTP port <odoo-bin --http-port>`
-
-To achieve such a thing, you'll need to deploy a reverse proxy in front of Odoo,
-like nginx or apache. When doing so, you'll need to forward some more http Headers
-to Odoo, and activate the proxy_mode in Odoo configuration to have Odoo read those
-headers.
-
-
-
-Configuration sample
---------------------
-
-* Server with 4 CPU, 8 Thread
-* 60 concurrent users
-
-* 60 users / 6 = 10 <- theorical number of worker needed
-* (4 * 2) + 1 = 9 <- theorical maximal number of worker
-* We'll use 8 workers + 1 for cron. We'll also use a monitoring system to measure cpu load, and check if it's between 7 and 7.5 .
-* RAM = 9 * ((0.8*150) + (0.2*1024)) ~= 3Go RAM for Odoo
-
-in ``/etc/odoo.conf``:
-
-.. code-block:: ini
-
- [options]
- limit_memory_hard = 1677721600
- limit_memory_soft = 629145600
- limit_request = 8192
- limit_time_cpu = 600
- limit_time_real = 1200
- max_cron_threads = 1
- workers = 8
-
-.. _https_proxy:
-
-HTTPS
-=====
-
-Whether it's accessed via website/web client or web service, Odoo transmits
-authentication information in cleartext. This means a secure deployment of
-Odoo must use HTTPS\ [#switching]_. SSL termination can be implemented via
-just about any SSL termination proxy, but requires the following setup:
-
-* Enable Odoo's :option:`proxy mode <odoo-bin --proxy-mode>`. This should only be enabled when Odoo is behind a reverse proxy
-* Set up the SSL termination proxy (`Nginx termination example`_)
-* Set up the proxying itself (`Nginx proxying example`_)
-* Your SSL termination proxy should also automatically redirect non-secure
- connections to the secure port
-
-Configuration sample
---------------------
-
-* Redirect http requests to https
-* Proxy requests to odoo
-
-in ``/etc/odoo.conf`` set:
-
-.. code-block:: ini
-
- proxy_mode = True
-
-in ``/etc/nginx/sites-enabled/odoo.conf`` set:
-
-.. code-block:: nginx
-
- #odoo server
- upstream odoo {
- server 127.0.0.1:8069;
- }
- upstream odoochat {
- server 127.0.0.1:8072;
- }
-
- # http -> https
- server {
- listen 80;
- server_name odoo.mycompany.com;
- rewrite ^(.*) https://$host$1 permanent;
- }
-
- server {
- listen 443;
- server_name odoo.mycompany.com;
- proxy_read_timeout 720s;
- proxy_connect_timeout 720s;
- proxy_send_timeout 720s;
-
- # Add Headers for odoo proxy mode
- proxy_set_header X-Forwarded-Host $host;
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- proxy_set_header X-Forwarded-Proto $scheme;
- proxy_set_header X-Real-IP $remote_addr;
-
- # SSL parameters
- ssl on;
- ssl_certificate /etc/ssl/nginx/server.crt;
- ssl_certificate_key /etc/ssl/nginx/server.key;
- ssl_session_timeout 30m;
- ssl_protocols TLSv1.2;
- ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
- ssl_prefer_server_ciphers off;
-
- # log
- access_log /var/log/nginx/odoo.access.log;
- error_log /var/log/nginx/odoo.error.log;
-
- # Redirect longpoll requests to odoo longpolling port
- location /longpolling {
- proxy_pass http://odoochat;
- }
-
- # Redirect requests to odoo backend server
- location / {
- proxy_redirect off;
- proxy_pass http://odoo;
- }
-
- # common gzip
- gzip_types text/css text/scss text/plain text/xml application/xml application/json application/javascript;
- gzip on;
- }
-
-Odoo as a WSGI Application
-==========================
-
-It is also possible to mount Odoo as a standard WSGI_ application. Odoo
-provides the base for a WSGI launcher script as ``odoo-wsgi.example.py``. That
-script should be customized (possibly after copying it from the setup directory) to correctly set the
-configuration directly in :mod:`odoo.tools.config` rather than through the
-command-line or a configuration file.
-
-However the WSGI server will only expose the main HTTP endpoint for the web
-client, website and webservice API. Because Odoo does not control the creation
-of workers anymore it can not setup cron or livechat workers
-
-Cron Workers
-------------
-
-To run cron jobs for an Odoo deployment as a WSGI application requires
-
-* A classical Odoo (run via ``odoo-bin``)
-* Connected to the database in which cron jobs have to be run (via
- :option:`odoo-bin -d`)
-* Which should not be exposed to the network. To ensure cron runners are not
- network-accessible, it is possible to disable the built-in HTTP server
- entirely with :option:`odoo-bin --no-http` or setting ``http_enable = False``
- in the configuration file
-
-LiveChat
---------
-
-The second problematic subsystem for WSGI deployments is the LiveChat: where
-most HTTP connections are relatively short and quickly free up their worker
-process for the next request, LiveChat require a long-lived connection for
-each client in order to implement near-real-time notifications.
-
-This is in conflict with the process-based worker model, as it will tie
-up worker processes and prevent new users from accessing the system. However,
-those long-lived connections do very little and mostly stay parked waiting for
-notifications.
-
-The solutions to support livechat/motifications in a WSGI application are:
-
-* Deploy a threaded version of Odoo (instread of a process-based preforking
- one) and redirect only requests to URLs starting with ``/longpolling/`` to
- that Odoo, this is the simplest and the longpolling URL can double up as
- the cron instance.
-* Deploy an evented Odoo via ``odoo-gevent`` and proxy requests starting
- with ``/longpolling/`` to
- :option:`the longpolling port <odoo-bin --longpolling-port>`.
-
-Serving Static Files
-====================
-
-For development convenience, Odoo directly serves all static files in its
-modules. This may not be ideal when it comes to performances, and static
-files should generally be served by a static HTTP server.
-
-Odoo static files live in each module's ``static/`` folder, so static files
-can be served by intercepting all requests to :samp:`/{MODULE}/static/{FILE}`,
-and looking up the right module (and file) in the various addons paths.
-
-.. todo:: test whether it would be interesting to serve filestored attachments
- via this, and how (e.g. possibility of mapping ir.attachment id to
- filestore hash in the database?)
-
-.. _security:
-
-Security
-========
-
-For starters, keep in mind that securing an information system is a continuous process,
-not a one-shot operation. At any moment, you will only be as secure as the weakest link
-in your environment.
-
-So please do not take this section as the ultimate list of measures that will prevent
-all security problems. It's only intended as a summary of the first important things
-you should be sure to include in your security action plan. The rest will come
-from best security practices for your operating system and distribution,
-best practices in terms of users, passwords, and access control management, etc.
-
-When deploying an internet-facing server, please be sure to consider the following
-security-related topics:
-
-- Always set a strong super-admin admin password, and restrict access to the database
- management pages as soon as the system is set up. See :ref:`db_manager_security`.
-
-- Choose unique logins and strong passwords for all administrator accounts on all databases.
- Do not use 'admin' as the login. Do not use those logins for day-to-day operations,
- only for controlling/managing the installation.
- *Never* use any default passwords like admin/admin, even for test/staging databases.
-
-- Do **not** install demo data on internet-facing servers. Databases with demo data contain
- default logins and passwords that can be used to get into your systems and cause significant
- trouble, even on staging/dev systems.
-
-- Use appropriate database filters ( :option:`--db-filter <odoo-bin --db-filter>`)
- to restrict the visibility of your databases according to the hostname.
- See :ref:`db_filter`.
- You may also use :option:`-d <odoo-bin -d>` to provide your own (comma-separated)
- list of available databases to filter from, instead of letting the system fetch
- them all from the database backend.
-
-- Once your ``db_name`` and ``db_filter`` are configured and only match a single database
- per hostname, you should set ``list_db`` configuration option to ``False``, to prevent
- listing databases entirely, and to block access to the database management screens
- (this is also exposed as the :option:`--no-database-list <odoo-bin --no-database-list>`
- command-line option)
-
-- Make sure the PostgreSQL user (:option:`--db_user <odoo-bin --db_user>`) is *not* a super-user,
- and that your databases are owned by a different user. For example they could be owned by
- the ``postgres`` super-user if you are using a dedicated non-privileged ``db_user``.
- See also :ref:`setup/deploy/odoo`.
-
-- Keep installations updated by regularly installing the latest builds,
- either via GitHub or by downloading the latest version from
- https://www.odoo.com/page/download or http://nightly.odoo.com
-
-- Configure your server in multi-process mode with proper limits matching your typical
- usage (memory/CPU/timeouts). See also :ref:`builtin_server`.
-
-- Run Odoo behind a web server providing HTTPS termination with a valid SSL certificate,
- in order to prevent eavesdropping on cleartext communications. SSL certificates are
- cheap, and many free options exist.
- Configure the web proxy to limit the size of requests, set appropriate timeouts,
- and then enable the :option:`proxy mode <odoo-bin --proxy-mode>` option.
- See also :ref:`https_proxy`.
-
-- If you need to allow remote SSH access to your servers, make sure to set a strong password
- for **all** accounts, not just `root`. It is strongly recommended to entirely disable
- password-based authentication, and only allow public key authentication. Also consider
- restricting access via a VPN, allowing only trusted IPs in the firewall, and/or
- running a brute-force detection system such as `fail2ban` or equivalent.
-
-- Consider installing appropriate rate-limiting on your proxy or firewall, to prevent
- brute-force attacks and denial of service attacks. See also :ref:`login_brute_force`
- for specific measures.
-
- Many network providers provide automatic mitigation for Distributed Denial of
- Service attacks (DDOS), but this is often an optional service, so you should consult
- with them.
-
-- Whenever possible, host your public-facing demo/test/staging instances on different
- machines than the production ones. And apply the same security precautions as for
- production.
-
-- If your public-facing Odoo server has access to sensitive internal network resources
- or services (e.g. via a private VLAN), implement appropriate firewall rules to
- protect those internal resources. This will ensure that the Odoo server cannot
- be used accidentally (or as a result of malicious user actions) to access or disrupt
- those internal resources.
- Typically this can be done by applying an outbound default DENY rule on the firewall,
- then only explicitly authorizing access to internal resources that the Odoo server
- needs to access.
- `Systemd IP traffic access control <http://0pointer.net/blog/ip-accounting-and-access-lists-with-systemd.html>`_
- may also be useful to implement per-process network access control.
-
-- If your public-facing Odoo server is behind a Web Application Firewall, a load-balancer,
- a transparent DDoS protection service (like CloudFlare) or a similar network-level
- device, you may wish to avoid direct access to the Odoo system. It is generally
- difficult to keep the endpoint IP addresses of your Odoo servers secret. For example
- they can appear in web server logs when querying public systems, or in the headers
- of emails posted from Odoo.
- In such a situation you may want to configure your firewall so that the endpoints
- are not accessible publicly except from the specific IP addresses of your WAF,
- load-balancer or proxy service. Service providers like CloudFlare usually maintain
- a public list of their IP address ranges for this purpose.
-
-- If you are hosting multiple customers, isolate customer data and files from each other
- using containers or appropriate "jail" techniques.
-
-- Setup daily backups of your databases and filestore data, and copy them to a remote
- archiving server that is not accessible from the server itself.
-
-
-.. _login_brute_force:
-
-Blocking Brute Force Attacks
-----------------------------
-For internet-facing deployments, brute force attacks on user passwords are very common, and this
-threat should not be neglected for Odoo servers. Odoo emits a log entry whenever a login attempt
-is performed, and reports the result: success or failure, along with the target login and source IP.
-
-The log entries will have the following form.
-
-Failed login::
-
- 2018-07-05 14:56:31,506 24849 INFO db_name odoo.addons.base.res.res_users: Login failed for db:db_name login:admin from 127.0.0.1
-
-Successful login::
-
- 2018-07-05 14:56:31,506 24849 INFO db_name odoo.addons.base.res.res_users: Login successful for db:db_name login:admin from 127.0.0.1
-
-
-These logs can be easily analyzed by an intrusion prevention system such as `fail2ban`.
-
-For example, the following fail2ban filter definition should match a
-failed login::
-
- [Definition]
- failregex = ^ \d+ INFO \S+ \S+ Login failed for db:\S+ login:\S+ from <HOST>
- ignoreregex =
-
-This could be used with a jail definition to block the attacking IP on HTTP(S).
-
-Here is what it could look like for blocking the IP for 15 minutes when
-10 failed login attempts are detected from the same IP within 1 minute::
-
- [odoo-login]
- enabled = true
- port = http,https
- bantime = 900 ; 15 min ban
- maxretry = 10 ; if 10 attempts
- findtime = 60 ; within 1 min /!\ Should be adjusted with the TZ offset
- logpath = /var/log/odoo.log ; set the actual odoo log path here
-
-
-
-
-.. _db_manager_security:
-
-Database Manager Security
--------------------------
-
-:ref:`setup/deploy/odoo` mentioned ``admin_passwd`` in passing.
-
-This setting is used on all database management screens (to create, delete,
-dump or restore databases).
-
-If the management screens must not be accessible at all, you should set ``list_db``
-configuration option to ``False``, to block access to all the database selection and
-management screens.
-
-.. warning::
-
- It is strongly recommended to disable the Database Manager for any internet-facing
- system! It is meant as a development/demo tool, to make it easy to quickly create
- and manage databases. It is not designed for use in production, and may even expose
- dangerous features to attackers. It is also not designed to handle large databases,
- and may trigger memory limits.
-
- On production systems, database management operations should always be performed by
- the system administrator, including provisioning of new databases and automated backups.
-
-Be sure to setup an appropriate ``db_name`` parameter
-(and optionally, ``db_filter`` too) so that the system can determine the target database
-for each request, otherwise users will be blocked as they won't be allowed to choose the
-database themselves.
-
-If the management screens must only be accessible from a selected set of machines,
-use the proxy server's features to block access to all routes starting with ``/web/database``
-except (maybe) ``/web/database/selector`` which displays the database-selection screen.
-
-If the database-management screen should be left accessible, the
-``admin_passwd`` setting must be changed from its ``admin`` default: this
-password is checked before allowing database-alteration operations.
-
-It should be stored securely, and should be generated randomly e.g.
-
-.. code-block:: console
-
- $ python3 -c 'import base64, os; print(base64.b64encode(os.urandom(24)))'
-
-which will generate a 32 characters pseudorandom printable string.
-
-Supported Browsers
-==================
-
-Odoo supports all the major desktop and mobile browsers available on the market,
-as long as they are supported by their publishers.
-
-Here are the supported browsers:
-
-- Google Chrome
-- Mozilla Firefox
-- Microsoft Edge
-- Apple Safari
-
-.. warning:: Please make sure your browser is up-to-date and still supported by
- its publisher before filing a bug report.
-
-
-.. note::
-
- Since Odoo 13.0, ES6 is supported. Therefore, IE support is dropped.
-
-
-.. [#different-machines]
- to have multiple Odoo installations use the same PostgreSQL database,
- or to provide more computing resources to both software.
-.. [#remote-socket]
- technically a tool like socat_ can be used to proxy UNIX sockets across
- networks, but that is mostly for software which can only be used over
- UNIX sockets
-.. [#switching]
- or be accessible only over an internal packet-switched network, but that
- requires secured switches, protections against `ARP spoofing`_ and
- precludes usage of WiFi. Even over secure packet-switched networks,
- deployment over HTTPS is recommended, and possible costs are lowered as
- "self-signed" certificates are easier to deploy on a controlled
- environment than over the internet.
-
-.. _regular expression: https://docs.python.org/3/library/re.html
-.. _ARP spoofing: https://en.wikipedia.org/wiki/ARP_spoofing
-.. _Nginx termination example:
- https://nginx.com/resources/admin-guide/nginx-ssl-termination/
-.. _Nginx proxying example:
- https://nginx.com/resources/admin-guide/reverse-proxy/
-.. _socat: http://www.dest-unreach.org/socat/
-.. _PostgreSQL connection settings:
-.. _listen to network interfaces:
- https://www.postgresql.org/docs/9.6/static/runtime-config-connection.html
-.. _use an SSH tunnel:
- https://www.postgresql.org/docs/9.6/static/ssh-tunnels.html
-.. _WSGI: https://wsgi.readthedocs.org/
-.. _POSBox: https://www.odoo.com/page/point-of-sale-hardware#part_2
diff --git a/doc/setup/email_gateway.rst b/doc/setup/email_gateway.rst
deleted file mode 100644
index e119baa4eb3..00000000000
--- a/doc/setup/email_gateway.rst
+++ /dev/null
@@ -1,49 +0,0 @@
-:banner: banners/email_gateway.jpg
-
-==================
-Odoo email gateway
-==================
-
-The Odoo mail gateway allows you to inject directly all the received emails in Odoo.
-
-Its principle is straightforward: your SMTP server executes the "mailgate" script for every new incoming email.
-
-The script takes care of connecting to your Odoo database through XML-RPC, and send the emails via
-the `MailThread.message_process()` feature.
-
-Prerequisites
--------------
-- Administrator access to the Odoo database.
-- Your own mail server such as Postfix or Exim.
-- Technical knowledge on how to configure an email server.
-
-For Postfix
------------
-In you alias config (:file:`/etc/aliases`):
-
-.. code-block:: text
-
- email@address: "|/odoo-directory/addons/mail/static/scripts/odoo-mailgate.py -d <database-name> -u <userid> -p <password>"
-
-.. note::
- Resources
-
- - `Postfix <http://www.postfix.org/documentation.html>`_
- - `Postfix aliases <http://www.postfix.org/aliases.5.html>`_
- - `Postfix virtual <http://www.postfix.org/virtual.8.html>`_
-
-
-For Exim
---------
-.. code-block:: text
-
- *: |/odoo-directory/addons/mail/static/scripts/odoo-mailgate.py -d <database-name> -u <userid> -p <password>
-
-.. note::
- Resources
-
- - `Exim <https://www.exim.org/docs.html>`_
-
-.. tip::
- If you don't have access/manage your email server, use `inbound messages
- <https://www.odoo.com/documentation/user/14.0/discuss/advanced/email_servers.html#how-to-manage-outbound-messages>`_.
diff --git a/doc/setup/enterprise.rst b/doc/setup/enterprise.rst
deleted file mode 100644
index 0051b1fafc1..00000000000
--- a/doc/setup/enterprise.rst
+++ /dev/null
@@ -1,107 +0,0 @@
-:banner: banners/enterprise.jpg
-
-.. _setup/enterprise:
-
-============================
-From Community to Enterprise
-============================
-
-Depending on your current installation, there are multiple ways to upgrade
-your community version.
-In any case the basic guidelines are:
-
-* Backup your community database
-
- .. image:: enterprise/db_manager.png
- :class: img-responsive
-
-* Shutdown your server
-
-* Install the web_enterprise module
-
-* Restart your server
-
-* Enter your Odoo Enterprise Subscription code
-
-.. image:: enterprise/enterprise_code.png
- :class: img-responsive
-
-On Linux, using an installer
-============================
-
-* Backup your community database
-
-* Stop the odoo service
-
- .. code-block:: console
-
- $ sudo service odoo stop
-
-* Install the enterprise .deb (it should install over the community package)
-
- .. code-block:: console
-
- $ sudo dpkg -i <path_to_enterprise_deb>
-
-* Update your database to the enterprise packages using
-
- .. code-block:: console
-
- $ python3 /usr/bin/odoo-bin -d <database_name> -i web_enterprise --stop-after-init
-
-* You should be able to connect to your Odoo Enterprise instance using your usual mean of identification.
- You can then link your database with your Odoo Enterprise Subscription by entering the code you received
- by e-mail in the form input
-
-
-On Linux, using the source code
-===============================
-
-There are many ways to launch your server when using sources, and you probably
-have your own favourite. You may need to adapt sections to your usual workflow.
-
-* Shutdown your server
-* Backup your community database
-* Update the ``--addons-path`` parameter of your launch command (see :ref:`setup/install/source`)
-* Install the web_enterprise module by using
-
- .. code-block:: console
-
- $ -d <database_name> -i web_enterprise --stop-after-init
-
- Depending on the size of your database, this may take some time.
-
-* Restart your server with the updated addons path of point 3.
- You should be able to connect to your instance. You can then link your database with your
- Odoo Enterprise Subscription by entering the code you received by e-mail in the form input
-
-On Windows
-==========
-
-* Backup your community database
-
-* Uninstall Odoo Community (using the Uninstall executable in the installation folder) -
- PostgreSQL will remain installed
-
- .. image:: enterprise/windows_uninstall.png
- :class: img-responsive
-
-* Launch the Odoo Enterprise Installer and follow the steps normally. When choosing
- the installation path, you can set the folder of the Community installation
- (this folder still contains the PostgreSQL installation).
- Uncheck ``Start Odoo`` at the end of the installation
-
- .. image:: enterprise/windows_setup.png
- :class: img-responsive
-
-* Using a command window, update your Odoo Database using this command (from the Odoo
- installation path, in the server subfolder)
-
- .. code-block:: console
-
- $ odoo.exe -d <database_name> -i web_enterprise --stop-after-init
-
-* No need to manually launch the server, the service is running.
- You should be able to connect to your Odoo Enterprise instance using your usual
- mean of identification. You can then link your database with your Odoo Enterprise
- Subscription by entering the code you received by e-mail in the form input
diff --git a/doc/setup/enterprise/db_manager.png b/doc/setup/enterprise/db_manager.png
deleted file mode 100644
index 9204fd4fd08..00000000000
--- a/doc/setup/enterprise/db_manager.png
+++ /dev/null
Binary files differ
diff --git a/doc/setup/enterprise/enterprise_code.png b/doc/setup/enterprise/enterprise_code.png
deleted file mode 100644
index 0ce3cca90d2..00000000000
--- a/doc/setup/enterprise/enterprise_code.png
+++ /dev/null
Binary files differ
diff --git a/doc/setup/enterprise/windows_setup.png b/doc/setup/enterprise/windows_setup.png
deleted file mode 100644
index a3f47f3f2c7..00000000000
--- a/doc/setup/enterprise/windows_setup.png
+++ /dev/null
Binary files differ
diff --git a/doc/setup/enterprise/windows_uninstall.png b/doc/setup/enterprise/windows_uninstall.png
deleted file mode 100644
index b75f6d84d94..00000000000
--- a/doc/setup/enterprise/windows_uninstall.png
+++ /dev/null
Binary files differ
diff --git a/doc/setup/install.rst b/doc/setup/install.rst
deleted file mode 100644
index 13108e81eac..00000000000
--- a/doc/setup/install.rst
+++ /dev/null
@@ -1,784 +0,0 @@
-:banner: banners/installing_odoo.jpg
-
-
-.. _setup/install:
-
-===============
-Installing Odoo
-===============
-
-There are multiple ways to install Odoo, or not install it at all, depending
-on the intended use case.
-
-This documents attempts to describe most of the installation options.
-
-:ref:`setup/install/online`
- The easiest way to use Odoo in production or to try it.
-
-:ref:`setup/install/packaged`
- Suitable for testing Odoo, developing modules and can be used for
- long-term production use with additional deployment and maintenance work.
-
-:ref:`setup/install/source`
- Provides greater flexibility: e.g. allow multiple running Odoo versions on
- the same system. Good for developing modules, can be used as base for
- production deployment.
-
-:ref:`setup/install/docker`
- If you usually use docker_ for development or deployment, an official
- docker_ base image is available.
-
-
-.. _setup/install/editions:
-
-Editions
-========
-
-There are two different Editions_ of Odoo: the Community and Enterprise versions.
-Using the Enterprise version is possible on our SaaS_ and accessing the code is
-restricted to Enterprise customers and partners. The Community version is freely
-available to anyone.
-
-If you already use the Community version and wish to upgrade to Enterprise, please
-refer to :ref:`setup/enterprise` (except for :ref:`setup/install/source`).
-
-
-.. _setup/install/online:
-
-Online
-======
-
-Demo
-----
-
-To simply get a quick idea of Odoo, demo_ instances are available. They are
-shared instances which only live for a few hours, and can be used to browse
-around and try things out with no commitment.
-
-Demo_ instances require no local installation, just a web browser.
-
-SaaS
-----
-
-Trivial to start with, fully managed and migrated by Odoo S.A., Odoo's SaaS_
-provides private instances and starts out free. It can be used to discover and
-test Odoo and do non-code customizations (i.e. incompatible with custom modules
-or the Odoo Apps Store) without having to install it locally.
-
-Can be used for both testing Odoo and long-term production use.
-
-Like demo_ instances, SaaS_ instances require no local installation, a web
-browser is sufficient.
-
-
-.. _setup/install/packaged:
-
-Packaged installers
-===================
-
-Odoo provides packaged installers for Windows, deb-based distributions
-(Debian, Ubuntu, …) and RPM-based distributions (Fedora, CentOS, RHEL, …) for
-both the Community and Enterprise versions.
-
-These packages automatically set up all dependencies (for the Community version),
-but may be difficult to keep up-to-date.
-
-Official Community packages with all relevant dependency requirements are
-available on our nightly_ server. Both Communtiy and Enterprise packages can
-be downloaded from our download_ page (you must to be logged in as a paying
-customer or partner to download the Enterprise packages).
-
-Windows
--------
-
-#. Download the installer from our nightly_ server (Community only) or the Windows installer from
- the download_ page (any edition).
-#. Execute the downloaded file.
-
- .. warning:: | On Windows 8 and later you may see a warning titled "Windows protected your PC".
- | Click on **More Info** and then on **Run anyway**.
-
-#. Accept the UAC_ prompt.
-#. Go through the various installation steps.
-
-Odoo will automatically be started at the end of the installation.
-
-Linux
------
-
-Debian/Ubuntu
-'''''''''''''
-
-Odoo 13.0 'deb' package currently supports `Debian Buster`_, `Ubuntu 18.04`_ or above.
-
-Prepare
-^^^^^^^
-
-Odoo needs a `PostgreSQL`_ server to run properly. The default configuration for
-the Odoo 'deb' package is to use the PostgreSQL server on the same host as your
-Odoo instance. Execute the following command in order to install the PostgreSQL server:
-
-.. code-block:: console
-
- $ sudo apt install postgresql -y
-
-.. warning:: `wkhtmltopdf` is not installed through **pip** and must be installed manually in
- version `0.12.5 <the wkhtmltopdf download page_>`_ for it to support headers and
- footers. See our `wiki <https://github.com/odoo/odoo/wiki/Wkhtmltopdf>`_ for more
- details on the various versions.
-
-Repository
-^^^^^^^^^^
-
-Odoo S.A. provides a repository that can be used with Debian and Ubuntu distributions. It can be
-used to install *Odoo Community Edition* by executing the following commands **as root**:
-
-.. code-block:: console
-
- # wget -O - https://nightly.odoo.com/odoo.key | apt-key add -
- # echo "deb http://nightly.odoo.com/14.0/nightly/deb/ ./" >> /etc/apt/sources.list.d/odoo.list
- # apt-get update && apt-get install odoo
-
-You can then use the usual `apt-get upgrade` command to keep your installation up-to-date.
-
-At this moment, there is no nightly repository for the Enterprise Edition.
-
-Deb Package
-^^^^^^^^^^^
-
-Instead of using the repository as described above, the 'deb' packages for both the *Community* and
-*Enterprise* editions can be downloaded from the `official download page <download_>`_.
-
-Next, execute the following commands **as root**:
-
-.. code-block:: console
-
- # dpkg -i <path_to_installation_package> # this probably fails with missing dependencies
- # apt-get install -f # should install the missing dependencies
- # dpkg -i <path_to_installation_package>
-
-This will install Odoo as a service, create the necessary PostgreSQL_ user
-and automatically start the server.
-
-.. warning:: The `python3-xlwt` Debian package does not exists in Debian Buster nor Ubuntu 18.04.
- This python module is needed to export into xls format.
-
- If you need the feature, you can install it manually with:
-
- .. code-block:: console
-
- $ sudo pip3 install xlwt
-
-.. warning:: The `num2words` python package does not exists in Debian Buster nor Ubuntu 18.04.
- Textual amounts will not be rendered by Odoo and this could cause problems with the
- `l10n_mx_edi` module.
-
- If you need this feature, you can install manually with:
-
- .. code-block:: console
-
- $ sudo pip3 install num2words
-
-Fedora
-''''''
-
-Odoo 13.0 'rpm' package supports Fedora 30.
-
-Prepare
-^^^^^^^
-Odoo needs a `PostgreSQL`_ server to run properly. Make sure that the `sudo` command is available
-and well configured and, only then, execute the following command in order to install the PostgreSQL
-server:
-
-.. code-block:: console
-
- $ sudo dnf install -y postgresql-server
- $ sudo postgresql-setup --initdb --unit postgresql
- $ sudo systemctl enable postgresql
- $ sudo systemctl start postgresql
-
-.. warning:: `wkhtmltopdf` is not installed through **pip** and must be installed manually in
- version `0.12.5 <the wkhtmltopdf download page_>`_ for it to support headers and
- footers. See our `wiki <https://github.com/odoo/odoo/wiki/Wkhtmltopdf>`_ for more
- details on the various versions.
-
-Repository
-^^^^^^^^^^
-
-Odoo S.A. provides a repository that can be used with the Fedora distributions.
-It can be used to install *Odoo Community Edition* by executing the following
-commands:
-
-.. code-block:: console
-
- $ sudo dnf config-manager --add-repo=https://nightly.odoo.com/14.0/nightly/rpm/odoo.repo
- $ sudo dnf install -y odoo
- $ sudo systemctl enable odoo
- $ sudo systemctl start odoo
-
-RPM package
-^^^^^^^^^^^
-
-Instead of using the repository as described above, the 'rpm' packages for both the *Community* and
-*Enterprise* editions can be downloaded from the `official download page <download_>`_.
-
-Once downloaded, the package can be installed using the 'dnf' package manager:
-
-.. code-block:: console
-
- $ sudo dnf localinstall odoo_13.0.latest.noarch.rpm
- $ sudo systemctl enable odoo
- $ sudo systemctl start odoo
-
-
-.. _setup/install/source:
-
-Source Install
-==============
-
-The source "installation" is really about not installing Odoo, and running it directly from source
-instead.
-
-This can be more convenient for module developers as the Odoo source is more easily accessible
-than using packaged installation (for information or to build this documentation and have it
-available offline).
-
-It also makes starting and stopping Odoo more flexible and explicit than the services set up by the
-packaged installations, and allows overriding settings using
-:ref:`command-line parameters <reference/cmdline>` without needing to edit a configuration file.
-
-Finally it provides greater control over the system's set up, and allows to more easily keep
-(and run) multiple versions of Odoo side-by-side.
-
-Windows
--------
-
-Fetch the sources
-'''''''''''''''''
-
-There are two ways to obtain the source code of Odoo: as a zip **archive** or through **git**.
-
-Archive
-^^^^^^^
-
-Community Edition:
-
-* `Official download page <download_>`_
-* `GitHub repository <community-repository_>`_
-* `Nightly server <nightly_>`_
-
-Enterprise Edition:
-
-* `Official download page <download_>`_
-* `GitHub repository <enterprise-repository_>`_
-
-Git
-^^^
-
-The following requires git_ to be installed on your machine and that you have basic knowledge of
-git commands.
-
-Community Edition:
-
-.. code-block:: doscon
-
- C:\> git clone https://github.com/odoo/odoo.git
-
-
-Enterprise Edition: (see :ref:`setup/install/editions` to get access)
-
-.. code-block:: doscon
-
- C:\> git clone https://github.com/odoo/enterprise.git
-
-.. note:: **The Enterprise git repository does not contain the full Odoo source code**. It is only
- a collection of extra add-ons. The main server code is in the Community version. Running
- the Enterprise version actually means running the server from the Community version with
- the addons-path option set to the folder with the Enterprise version. You need to clone
- both the Community and Enterprise repository to have a working Odoo Enterprise
- installation.
-
-Prepare
-'''''''
-
-Python
-^^^^^^
-
-Odoo requires Python 3.6 or later to run. Visit `Python's download page <https://www.python.org/downloads/windows/>`_
-to download and install the latest version of Python 3 on your machine.
-
-During installation, check **Add Python 3 to PATH**, then click **Customize Installation** and make
-sure that **pip** is checked.
-
-.. note:: If Python 3 is already installed, make sure that the version is 3.6 or above, as previous
- versions are not compatible with Odoo.
-
- .. code-block:: doscon
-
- C:\> python --version
-
- Verify also that pip_ is installed for this version.
-
- .. code-block:: doscon
-
- C:\> pip --version
-
-PostgreSQL
-^^^^^^^^^^
-
-Odoo uses PostgreSQL as database management system. `Download and install PostgreSQL <https://www.postgresql.org/download/windows/>`_
-(supported version: 10.0 and later).
-
-By default, the only user is `postgres` but Odoo forbids connecting as `postgres`, so you need to
-create a new PostgreSQL user:
-
-#. Add PostgreSQL's `bin` directory (by default: `C:\\Program Files\\PostgreSQL\\<version>\\bin`) to
- your `PATH`.
-#. Create a postgres user with a password using the pg admin gui:
-
- 1. Open **pgAdmin**.
- 2. Double-click the server to create a connection.
- 3. Select :menuselection:`Object --> Create --> Login/Group Role`.
- 4. Enter the username in the **Role Name** field (e.g. `odoo`).
- 5. Open the **Definition** tab and enter the password (e.g. ``odoo``), then click **Save**.
- 6. Open the **Privileges** tab and switch **Can login?** to `Yes` and **Create database?** to
- `Yes`.
-
-Dependencies
-^^^^^^^^^^^^
-
-Before installing the dependencies, you must download and install the
-`Build Tools for Visual Studio <https://visualstudio.microsoft.com/downloads/#build-tools-for-visual-studio-2019>`_.
-When prompted, select **C++ build tools** in the **Workloads** tab and install them.
-
-Odoo dependencies are listed in the `requirements.txt` file located at the root of the Odoo
-community directory.
-
-.. tip:: It can be preferable to not mix python modules packages between different instances of Odoo
- or with your system. You can use virtualenv_ to create isolated Python environments.
-
-Navigate to the path of your Odoo Community installation (`CommunityPath`) and run **pip**
-on the requirements file in a terminal **with Administrator privileges**:
-
-.. code-block:: doscon
-
- C:\> cd \CommunityPath
- C:\> pip install setuptools wheel
- C:\> pip install -r requirements.txt
-
-.. warning:: `wkhtmltopdf` is not installed through **pip** and must be installed manually in
- version `0.12.5 <the wkhtmltopdf download page_>`_ for it to support headers and
- footers. See our `wiki <https://github.com/odoo/odoo/wiki/Wkhtmltopdf>`_ for more
- details on the various versions.
-
-For languages with right-to-left interface (such as Arabic or Hebrew), the package `rtlcss` is
-needed:
-
-#. Download and install `nodejs <https://nodejs.org/en/download/>`_.
-#. Install `rtlcss`:
-
- .. code-block:: doscon
-
- C:\> npm install -g rtlcss
-
-#. Edit the System Environment's variable `PATH` to add the folder where `rtlcss.cmd` is located
- (typically: `C:\\Users\\<user>\\AppData\\Roaming\\npm\\`).
-
-Running Odoo
-''''''''''''
-
-Once all dependencies are set up, Odoo can be launched by running `odoo-bin`, the
-command-line interface of the server. It is located at the root of the Odoo Community directory.
-
-To configure the server, you can either specify :ref:`command-line arguments <reference/cmdline/server>` or a
-:ref:`configuration file <reference/cmdline/config>`.
-
-.. tip:: For the Enterprise edition, you must add the path to the `enterprise` addons to the
- `addons-path` argument. Note that it must come before the other paths in `addons-path` for
- addons to be loaded correctly.
-
-Common necessary configurations are:
-
-* PostgreSQL user and password.
-* Custom addon paths beyond the defaults, to load your own modules.
-
-A typical way to run the server would be:
-
-.. code-block:: doscon
-
- C:\> cd CommunityPath/
- C:\> python odoo-bin -r dbuser -w dbpassword --addons-path=addons -d mydb
-
-Where `CommunityPath` is the path of the Odoo Community installation, `dbuser` is the
-PostgreSQL login, `dbpassword` is the PostgreSQL password
-and `mydb` is the default database to serve on `localhost:8069`. You can add other
-directory paths separated by a comma to ``addons`` at the end of the addons-path option.
-
-Linux
------
-
-Fetch the sources
-'''''''''''''''''
-
-There are two ways to obtain the source code of Odoo: as a zip **archive** or through **git**.
-
-Archive
-^^^^^^^
-
-Community Edition:
-
-* `Official download page <download_>`_
-* `GitHub repository <community-repository_>`_
-* `Nightly server <nightly_>`_
-
-Enterprise Edition:
-
-* `Official download page <download_>`_
-* `GitHub repository <enterprise-repository_>`_
-
-Git
-^^^
-
-The following requires git_ to be installed on your machine and that you have basic knowledge of
-git commands.
-
-Community Edition:
-
-.. code-block:: console
-
- $ git clone https://github.com/odoo/odoo.git
-
-
-Enterprise Edition: (see :ref:`setup/install/editions` to get access)
-
-.. code-block:: console
-
- $ git clone https://github.com/odoo/enterprise.git
-
-.. note:: **The Enterprise git repository does not contain the full Odoo source code**. It is only
- a collection of extra add-ons. The main server code is in the Community version. Running
- the Enterprise version actually means running the server from the Community version with
- the addons-path option set to the folder with the Enterprise version. You need to clone
- both the Community and Enterprise repository to have a working Odoo Enterprise
- installation.
-
-Prepare
-'''''''
-
-Python
-^^^^^^
-
-Odoo requires Python 3.6 or later to run. Use your package manager to download and install Python 3
-on your machine if it is not already done.
-
-.. note:: If Python 3 is already installed, make sure that the version is 3.6 or above, as previous
- versions are not compatible with Odoo.
-
- .. code-block:: console
-
- $ python3 --version
-
- Verify also that pip_ is installed for this version.
-
- .. code-block:: console
-
- $ pip3 --version
-
-PostgreSQL
-^^^^^^^^^^
-
-Odoo uses PostgreSQL as database management system. Use your package manager to download and install
-PostgreSQL (supported version: 10.0 and later).
-
-On Debian/Unbuntu, it can be achieved by executing the following:
-
-.. code-block:: console
-
- $ sudo apt install postgresql postgresql-client
-
-By default, the only user is `postgres` but Odoo forbids connecting as `postgres`, so you need to
-create a new PostgreSQL user:
-
-.. code-block:: console
-
- $ sudo -u postgres createuser -s $USER
- $ createdb $USER
-
-.. note:: Because your PostgreSQL user has the same name as your Unix login, you will be able to
- connect to the database without password.
-
-Dependencies
-^^^^^^^^^^^^
-
-For libraries using native code, it is necessary to install development tools and native
-dependencies before the Python dependencies of Odoo. They are available in `-dev` or `-devel`
-packages for Python, PostgreSQL, libxml2, libxslt1, libevent, libsasl2 and libldap2.
-
-On Debian/Unbuntu, the following command should install all the required libraries:
-
-.. code-block:: console
-
- $ sudo apt install python3-dev libxml2-dev libxslt1-dev libldap2-dev libsasl2-dev \
- libtiff5-dev libjpeg8-dev libopenjp2-7-dev zlib1g-dev libfreetype6-dev \
- liblcms2-dev libwebp-dev libharfbuzz-dev libfribidi-dev libxcb1-dev libpq-dev
-
-Odoo dependencies are listed in the `requirements.txt` file located at the root of the Odoo
-community directory.
-
-.. tip:: It can be preferable to not mix python modules packages between different instances of Odoo
- or with your system. You can use virtualenv_ to create isolated Python environments.
-
-Navigate to the path of your Odoo Community installation (`CommunityPath`) and run **pip**
-on the requirements file:
-
-.. code-block:: console
-
- $ cd /CommunityPath
- $ pip3 install setuptools wheel
- $ pip3 install -r requirements.txt
-
-.. warning:: `wkhtmltopdf` is not installed through **pip** and must be installed manually in
- version `0.12.5 <the wkhtmltopdf download page_>`_ for it to support headers and
- footers. See our `wiki <https://github.com/odoo/odoo/wiki/Wkhtmltopdf>`_ for more
- details on the various versions.
-
-For languages with right-to-left interface (such as Arabic or Hebrew), the package `rtlcss` is
-needed:
-
-#. Download and install **nodejs** and **npm** with your package manager.
-#. Install `rtlcss`:
-
- .. code-block:: console
-
- $ sudo npm install -g rtlcss
-
-Running Odoo
-''''''''''''
-
-Once all dependencies are set up, Odoo can be launched by running `odoo-bin`, the
-command-line interface of the server. It is located at the root of the Odoo Community directory.
-
-To configure the server, you can either specify :ref:`command-line arguments <reference/cmdline/server>` or a
-:ref:`configuration file <reference/cmdline/config>`.
-
-.. tip:: For the Enterprise edition, you must add the path to the `enterprise` addons to the
- `addons-path` argument. Note that it must come before the other paths in `addons-path` for
- addons to be loaded correctly.
-
-Common necessary configurations are:
-
-* PostgreSQL user and password. Odoo has no defaults beyond
- `psycopg2's defaults <http://initd.org/psycopg/docs/module.html>`_: connects over a UNIX socket on
- port `5432` with the current user and no password.
-* Custom addon paths beyond the defaults, to load your own modules.
-
-A typical way to run the server would be:
-
-.. code-block:: console
-
- $ cd /CommunityPath
- $ python3 odoo-bin --addons-path=addons -d mydb
-
-Where `CommunityPath` is the path of the Odoo Community installation
-and `mydb` is the default database to serve on `localhost:8069`. You can add other
-directory paths separated by a comma to ``addons`` at the end of the addons-path option.
-
-Mac OS
-------
-
-Fetch the sources
-'''''''''''''''''
-
-There are two ways to obtain the source code of Odoo: as a zip **archive** or through **git**.
-
-Archive
-^^^^^^^
-
-Community Edition:
-
-* `Official download page <download_>`_
-* `GitHub repository <community-repository_>`_
-* `Nightly server <nightly_>`_
-
-Enterprise Edition:
-
-* `Official download page <download_>`_
-* `GitHub repository <enterprise-repository_>`_
-
-Git
-^^^
-
-The following requires git_ to be installed on your machine and that you have basic knowledge of
-git commands.
-
-Community Edition:
-
-.. code-block:: console
-
- $ git clone https://github.com/odoo/odoo.git
-
-
-Enterprise Edition: (see :ref:`setup/install/editions` to get access)
-
-.. code-block:: console
-
- $ git clone https://github.com/odoo/enterprise.git
-
-.. note:: **The Enterprise git repository does not contain the full Odoo source code**. It is only
- a collection of extra add-ons. The main server code is in the Community version. Running
- the Enterprise version actually means running the server from the Community version with
- the addons-path option set to the folder with the Enterprise version. You need to clone
- both the Community and Enterprise repository to have a working Odoo Enterprise
- installation.
-
-Prepare
-'''''''
-
-Python
-^^^^^^
-
-Odoo requires Python 3.6 or later to run. Use your preferred package manager (homebrew_, macports_)
-to download and install Python 3 on your machine if it is not already done.
-
-.. note:: If Python 3 is already installed, make sure that the version is 3.6 or above, as previous
- versions are not compatible with Odoo.
-
- .. code-block:: console
-
- $ python3 --version
-
- Verify also that pip_ is installed for this version.
-
- .. code-block:: console
-
- $ pip3 --version
-
-PostgreSQL
-^^^^^^^^^^
-
-Odoo uses PostgreSQL as database management system. Use `postgres.app <https://postgresapp.com>`_
-to download and install PostgreSQL (supported version: 10.0 and later).
-
-By default, the only user is `postgres` but Odoo forbids connecting as `postgres`, so you need to
-create a new PostgreSQL user:
-
-.. code-block:: console
-
- $ sudo -u postgres createuser -s $USER
- $ createdb $USER
-
-.. note:: Because your PostgreSQL user has the same name as your Unix login, you will be able to
- connect to the database without password.
-
-Dependencies
-^^^^^^^^^^^^
-
-Odoo dependencies are listed in the `requirements.txt` file located at the root of the Odoo
-community directory.
-
-.. tip:: It can be preferable to not mix python modules packages between different instances of Odoo
- or with your system. You can use virtualenv_ to create isolated Python environments.
-
-Navigate to the path of your Odoo Community installation (`CommunityPath`) and run **pip**
-on the requirements file:
-
-.. code-block:: console
-
- $ cd /CommunityPath
- $ pip3 install setuptools wheel
- $ pip3 install -r requirements.txt
-
-.. warning:: Non-Python dependencies need to be installed with a package manager:
-
- #. Download and install the **Command Line Tools**:
-
- .. code-block:: console
-
- $ xcode-select --install
-
- #. Download and install the package manager of your choice (homebrew_, macports_).
- #. Install non-python dependencies.
-
-.. warning:: `wkhtmltopdf` is not installed through **pip** and must be installed manually in
- version `0.12.5 <the wkhtmltopdf download page_>`_ for it to support headers and
- footers. See our `wiki <https://github.com/odoo/odoo/wiki/Wkhtmltopdf>`_ for more
- details on the various versions.
-
-For languages with right-to-left interface (such as Arabic or Hebrew), the package `rtlcss` is
-needed:
-
-#. Download and install **nodejs** with your preferred package manager (homebrew_, macports_).
-#. Install `rtlcss`:
-
- .. code-block:: console
-
- $ sudo npm install -g rtlcss
-
-Running Odoo
-''''''''''''
-
-Once all dependencies are set up, Odoo can be launched by running `odoo-bin`, the
-command-line interface of the server. It is located at the root of the Odoo Community directory.
-
-To configure the server, you can either specify :ref:`command-line arguments <reference/cmdline/server>` or a
-:ref:`configuration file <reference/cmdline/config>`.
-
-.. tip:: For the Enterprise edition, you must add the path to the `enterprise` addons to the
- `addons-path` argument. Note that it must come before the other paths in `addons-path` for
- addons to be loaded correctly.
-
-Common necessary configurations are:
-
-* PostgreSQL user and password. Odoo has no defaults beyond
- `psycopg2's defaults <http://initd.org/psycopg/docs/module.html>`_: connects over a UNIX socket on
- port `5432` with the current user and no password.
-* Custom addon paths beyond the defaults, to load your own modules.
-
-A typical way to run the server would be:
-
-.. code-block:: console
-
- $ cd /CommunityPath
- $ python3 odoo-bin --addons-path=addons -d mydb
-
-Where `CommunityPath` is the path of the Odoo Community installation
-and `mydb` is the default database to serve on `localhost:8069`. You can add other
-directory paths separated by a comma to ``addons`` at the end of the addons-path option.
-
-
-.. _setup/install/docker:
-
-Docker
-======
-
-The full documentation on how to use Odoo with Docker can be found on the
-official Odoo `docker image <https://registry.hub.docker.com/_/odoo/>`_ page.
-
-.. _Debian Buster: https://www.debian.org/releases/buster/
-.. _demo: https://demo.odoo.com
-.. _docker: https://www.docker.com
-.. _download: https://www.odoo.com/page/download
-.. _Ubuntu 18.04: http://releases.ubuntu.com/18.04/
-.. _EPEL: https://fedoraproject.org/wiki/EPEL
-.. _PostgreSQL: http://www.postgresql.org
-.. _the official installer:
-.. _install pip:
- https://pip.pypa.io/en/latest/installing.html#install-pip
-.. _Quilt: http://en.wikipedia.org/wiki/Quilt_(software)
-.. _saas: https://www.odoo.com/page/start
-.. _the wkhtmltopdf download page: https://github.com/wkhtmltopdf/wkhtmltopdf/releases/tag/0.12.5
-.. _UAC: http://en.wikipedia.org/wiki/User_Account_Control
-.. _wkhtmltopdf: http://wkhtmltopdf.org
-.. _pip: https://pip.pypa.io
-.. _macports: https://www.macports.org
-.. _homebrew: http://brew.sh
-.. _wheels: https://wheel.readthedocs.org/en/latest/
-.. _virtualenv: https://pypi.python.org/pypi/virtualenv
-.. _virtualenvwrapper: https://virtualenvwrapper.readthedocs.io/en/latest/
-.. _pywin32: http://sourceforge.net/projects/pywin32/files/pywin32/
-.. _community-repository: https://github.com/odoo/odoo
-.. _enterprise-repository: https://github.com/odoo/enterprise
-.. _git: https://git-scm.com/
-.. _Editions: https://www.odoo.com/pricing#pricing_table_features
-.. _nightly: https://nightly.odoo.com/
-.. _extra: https://nightly.odoo.com/extra/
diff --git a/doc/setup/update.rst b/doc/setup/update.rst
deleted file mode 100644
index 9438b1ab884..00000000000
--- a/doc/setup/update.rst
+++ /dev/null
@@ -1,151 +0,0 @@
-:banner: banners/installing_odoo.jpg
-
-.. _setup/update:
-
-=============================
-Updating an Odoo installation
-=============================
-
-Introduction
-============
-
-In order to benefit from the latest improvements, security fixes, bug corrections and
-performance boosts, you may need to update your Odoo installation from time to time.
-
-This guide only applies when are using Odoo on your own hosting infrastructure.
-If you are using one of the Odoo Cloud solutions, updates are automatically performed for you.
-
-The terminology surrounding software updates is often confusing, so here are some preliminary
-definitions:
-
-Updating (an Odoo installation)
- Refers to the process of obtaining the latest revision of the source code for
- your current Odoo Edition. For example, updating your Odoo Enterprise 13.0 to the
- latest revision.
- This does not directly cause any change to the contents of your Odoo database, and
- can be undone by reinstalling the previous revision of the source code.
-
-Upgrading (an Odoo database)
- Refers to a complex data processing operation where the structure and contents of your
- database is permanently altered to make it compatible with a new release of Odoo.
- This operation is irreversible and typically accomplished via Odoo's
- `database upgrade service <https://upgrade.odoo.com>`_, when you decide to
- switch to a newer release of Odoo.
- Historically, this process has also been known as a "migration" because it involves moving data
- around inside the database, even though the database may end up at the same physical location
- after the upgrade.
-
-This page describes the typical steps needed to *update* an Odoo installation to the latest
-version. If you'd like more information about upgrading a database, please visit the
-`Odoo Upgrade page <https://upgrade.odoo.com>`_ instead.
-
-
-In a nutshell
-=============
-
-Updating Odoo is accomplished by simply reinstalling the latest version of your Odoo
-Edition on top of your current installation. This will preserve your data without any alteration,
-as long as you do not uninstall PostgreSQL (the database engine that comes with Odoo).
-
-The main reference for updating is logically our :ref:`installation guide <setup/install>`,
-which explains the common installation methods.
-
-Updating is also most appropriately accomplished by the person who deployed Odoo initially,
-because the procedure is very similar.
-
-.. note:: We always recommend to download a complete new up-to-date Odoo version, rather than
- manually applying patches, such as the security patches that come with Security
- Advisories.
- The patches are mainly provided for installations that are heavily customized, or for
- technical personnel who prefer to apply minimal changes temporarily while testing a
- complete update.
-
-
-Step 1: Download an updated Odoo version
-========================================
-
-The central download page is https://www.odoo.com/page/download. If you see a "Buy" link for the
-Odoo Enterprise download, make sure you are logged into Odoo.com with the same login that is
-linked to your Odoo Enterprise subscription.
-
-Alternatively, you can use the unique download link that was included with your Odoo Enterprise
-purchase confirmation email.
-
-.. note:: Downloading an updated version is not necessary if you installed via Github (see below)
-
-
-Step 2: Make a backup of your database
-======================================
-
-The update procedure is quite safe and should not alter you data. However it's always best to take
-a full database backup before performing any change on your installation, and to store it somewhere
-safe, on a different computer.
-
-If you have not disabled the database manager screen (see :ref:`here <security>` why you should), you
-can use it (link at bottom of your database selection screen) to download a backup of your
-database(s). If you disabled it, use the same procedure than for your usual backups.
-
-
-Step 3: Install the updated version
-===================================
-
-Choose the method that matches your current installation:
-
-
-Packaged Installers
--------------------
-
-If you installed Odoo with an installation package downloaded on our website (the recommended method),
-updating is very simple.
-All you have to do is download the installation package corresponding to your system (see step #1)
-and install it on your server. They are updated daily and include the latest security fixes.
-Usually, you can simply double-click the package to install it on top of the current installation.
-After installing the package, be sure to restart the Odoo service or reboot your server,
-and you're all set.
-
-Source Install (Tarball)
-------------------------
-If you have originally installed Odoo with the "tarball" version (source code archive), you have
-to replace the installation directory with a newer version. First download the latest tarball
-from Odoo.com. They are updated daily and include the latest security fixes (see step #1)
-After downloading the package, extract it to a temporary location on your server.
-
-You will get a folder labelled with the version of the source code, for example "odoo-13.0+e.20190719",
-that contains a folder "odoo.egg-info" and the actual source code folder named "odoo" (for Odoo 10
-and later) or "openerp" for older versions.
-You can ignore the odoo.egg-info folder. Locate the folder where your current installation is deployed,
-and replace it with the newer "odoo" or "openerp" folder that was in the archive you just extracted.
-
-Be sure to match the folder layout, for example the new "addons" folder included in the source code
-should end up exactly at the same path it was before. Next, watch out for any specific configuration
-files that you may have manually copied or modified in the old folder, and copy them over to the
-new folder.
-Finally, restart the Odoo service or reboot the machine, and you are all set.
-
-Source Install (Github)
------------------------
-If you have originally installed Odoo with a full Github clone of the official repositories, the
-update procedure requires you to pull the latest source code via git.
-Change into the directory for each repository (the main Odoo repository, and the Enterprise
-repository), and run the following commands::
-
- git fetch
- git rebase --autostash
-
-The last command may encounter source code conflicts if you had edited the Odoo source code locally.
-The error message will give you the list of files with conflicts, and you will need to resolve
-the conflicts manually, by editing them and deciding which part of the code to keep.
-
-Alternatively, if you prefer to simply discard the conflicting changes and restore the official
-version, you can use the following command::
-
- git reset --hard
-
-Finally, restart the Odoo service or reboot the machine, and you should be done.
-
-
-Docker
-------
-
-Please refer to our `Docker image documentation <https://hub.docker.com/_/odoo/>`_ for
-specific update instructions. \ No newline at end of file
diff --git a/doc/tutorials.rst b/doc/tutorials.rst
deleted file mode 100644
index 9cb865cf503..00000000000
--- a/doc/tutorials.rst
+++ /dev/null
@@ -1,13 +0,0 @@
-=========
-Tutorials
-=========
-
-.. toctree::
- :titlesonly:
-
- howtos/themes
- howtos/website
- howtos/backend
- howtos/web
- howtos/profilecode
- howtos/company
diff --git a/doc/webservices.rst b/doc/webservices.rst
deleted file mode 100644
index 3dac7fa947d..00000000000
--- a/doc/webservices.rst
+++ /dev/null
@@ -1,15 +0,0 @@
-:banner: banners/web_service_api.jpg
-:types: api
-
-============
-Web Services
-============
-
-.. toctree::
- :titlesonly:
-
- webservices/odoo
- webservices/iap
- webservices/upgrade
- webservices/localization
- webservices/extract_api \ No newline at end of file
diff --git a/doc/webservices/extract_api.rst b/doc/webservices/extract_api.rst
deleted file mode 100644
index f79a3ff2484..00000000000
--- a/doc/webservices/extract_api.rst
+++ /dev/null
@@ -1,558 +0,0 @@
-:banner: banners/extract_api.jpg
-:types: api
-
-:code-column:
-
-===============
-Extract API
-===============
-
-Odoo provides a service allowing you to automate the processing of your invoices. The service scans your document using an Optical
-Character Recognition (OCR) engine and then uses AI-based algorithms to extract the fields of interest such as the total, the due date, or
-the invoice lines. More functional information can be found on the `demo page <https://www.odoo.com/page/invoice-automation>`_.
-
-This service is a paid service. Each invoice processing will cost you one credit. Three different sized packs can be bought on `iap.odoo.com <https://iap.odoo.com/iap/in-app-services/259?sortby=date>`_.
-
-You can either use this service directly in the Odoo Accounting App or through the API. The Extract API which is detailed in the next section
-allows you to integrate our service directly into your own projects.
-
-Invoices
-========
-The extract API use the JSON-RPC2_ protocol. The diffent routes are located at the following address: **https://iap-extract.odoo.com**.
-
-Expected successful flow
-------------------------
-
-1. Call :ref:`webservices/extract_api/invoice_parse` to submit your invoices (one call for each invoice). On success, you receive a `document_id` in the response.
-2. You then have to regularly poll :ref:`webservices/extract_api/invoice_get_results` to get the document's parsing status.
-3. Once the result received, you can validate it by calling :ref:`webservices/extract_api/invoice_validate` and sending the expected values.
- This step is optional but greatly helps the system to improve.
-
-These 3 routes are detailed in this :ref:`section <webservices/extract_api/routes>`. The HTTP POST method should be used for all of them. A python implementation of the full flow
-can be found :download:`here </_static/extract_api_implementation.py>` and a token for integration testing is provided in the :ref:`integration testing section <webservices/extract_api/integration_testing>`.
-
-.. _webservices/extract_api/routes:
-
-Routes
-------
-
-.. _webservices/extract_api/invoice_parse:
-
-``/iap/invoice_extract/parse``
-''''''''''''''''''''''''''''''
-
-Description
-^^^^^^^^^^^
-Request a processing of the document from the OCR. The route will return a `document_id` you can use to obtain the result of your request.
-
-Request Body
-^^^^^^^^^^^^
-
-``jsonrpc`` (required)
- Must be exactly “2.0”.
-``method`` (required)
- Must be “call”.
-``id`` (required)
- An identifier established by the client. It allows the client to keep track of which response goes with which request. This makes asynchronous calls easier.
-``params``
- ``account_token`` (required)
- The token of the account from which credits will be taken. Each successful call costs one token.
- ``version`` (optional)
- The version will determine the format of your requests and the format of the server response. Some results can be unavailable in older versions. For the current
- version 1.2.0, send ‘120’. If not specified, the latest version will be used.
- ``documents`` (required)
- The invoice must be provided as a string in the ASCII encoding. The list should contain only one string. If multiple strings are provided only the first string
- corresponding to a pdf will be processed. If no pdf is found, the first string will be processed. This field is a list only for legacy reasons. The supported extensions
- are *pdf*, *png*, *jpg* and *bmp*.
- ``user_infos`` (required)
- Information concerning the person to whom the invoice is intended. This informations is not required in order for the service to work but it greatly improves the quality of the result.
-
- ``user_company_vat`` (optional)
- VAT number of the client.
- ``user_company_name`` (optional)
- Name of the client’s company.
- ``user_company_country_code`` (optional)
- Country code of the client. Format: `ISO3166 alpha-2 <https://www.iban.com/country-codes>`_.
- ``user_lang`` (optional)
- The client language. Format: *language_code + _ + locale* (ex: fr_FR, en_US).
- ``user_email`` (optional)
- The client email.
-
-.. rst-class:: setup doc-aside
-
-.. switcher::
-
- .. code-block:: json
-
- {
- "jsonrpc": string,
- "method": string,
- "params": {
- "account_token": string (hex),
- "version": int,
- "documents": [string],
- "user_infos": {
- "user_company_vat": string,
- "user_company_name": string,
- "user_company_country_code": string,
- "user_lang": string,
- "user_email": string,
- },
- },
- "id": string (hex),
- }
-
-Response
-^^^^^^^^
-
-``jsonrpc``
- A string specifying the version of the JSON-RPC protocol. It will be “2.0”.
-``id``
- The identifier you set in the request body.
-``result``
- ``status_code``
- |STATUS_CODE|
- ``status_msg``
- |STATUS_MSG|
- ``document_id``
- Only present if the request is successful.
-
-.. note:: The API does not actually use the JSON-RPC error scheme. Instead the API has its own error scheme bundled inside a successful JSON-RPC result.
-
-============= ==============================================================
- status_code status_msg
-============= ==============================================================
-0 Success
-2 An error occured
-3 You don't have enough credit
-6 Unsupported file format
-9 Server is currently under maintenance. Please try again later.
-============= ==============================================================
-
-.. rst-class:: setup doc-aside
-
-.. switcher::
-
- .. code-block:: json
-
- {
- "jsonrpc": string,
- "id": string,
- "result": {
- "status_code": int,
- "status_msg": string,
- "document_id": int,
- }
- }
-
-
-.. _webservices/extract_api/invoice_get_results:
-
-``/iap/invoice_extract/get_results``
-''''''''''''''''''''''''''''''''''''
-
-Description
-^^^^^^^^^^^
-Request the results of the documents ids obtained with the :ref:`/parse <webservices/extract_api/invoice_parse>` route. Can either return the results or a "request pending" message.
-
-Request Body
-^^^^^^^^^^^^
-
-``jsonrpc`` (required)
- |SAME_AS_PARSE|
-``method`` (required)
- |SAME_AS_PARSE|
-``id`` (required)
- |SAME_AS_PARSE|
-``params``:
- ``version`` (required)
- |SAME_AS_PARSE|
- ``documents_ids`` (required)
- The list of ``document_id`` for which you want to get the current parsing status.
-
-.. rst-class:: setup doc-aside
-
-.. switcher::
-
- .. code-block:: json
-
- {
- "jsonrpc": string,
- "method": string,
- "params": {
- "version": int,
- "documents_ids": [int]
- },
- "id": string (hex),
- }
-
-
-Response
-^^^^^^^^
-
-``jsonrpc``
- |SAME_AS_PARSE|
-``id``
- |SAME_AS_PARSE|
-``result``
- Dictionary where each key is a document_id. For each ``document_id``:
-
- ``status_code``
- |STATUS_CODE|
- ``status_msg``
- |STATUS_MSG|
- ``results``
- Only present if the request is successful.
-
-.. warning:: result keys are strings despite the fact that the document_ids given in the request body are integers.
-
-============= ==============================================================
- status_code status_msg
-============= ==============================================================
-0 Success
-1 Not ready
-2 An error occured
-9 Server is currently under maintenance. Please try again later.
-============= ==============================================================
-
-.. rst-class:: setup doc-aside
-
-.. switcher::
-
- .. code-block:: json
-
- {
- "jsonrpc": string,
- "id": string,
- "result": {
- "document_id_1": {
- "status_code": int,
- "status_msg": str,
- "results": [{"feature_1_name": feature_1_result,
- "feature_2_name": feature_2_result,
- …
- }]
- },
- "document_id_2": {
- "status_code": int,
- "status_msg": str,
- "results": [{"feature_1_name": feature_1_result,
- "feature_2_name": feature_2_result,
- …
- }]
- },
- ...
- }
- }
-
-.. _webservices/extract_api/invoice_get_results/feature_result:
-
-``feature_result``
-''''''''''''''''''
-
-Each field of interest we want to extract from the invoice such as the total or the due date are also called features. An exhaustive list of all the extracted features can be found in the table below.
-
-For each feature, we return a list of candidates and we spotlight the candidate our model predicts to be the best fit for the feature.
-
-``selected_value``
- The best candidate for this feature.
-``words``
- List of all the candidates for this feature ordered by decreasing score.
-
-.. container:: doc-aside
-
- .. switcher::
-
- .. code-block:: json
-
- {
- "selected_value": candidate_12,
- "words": [candidate_12, candidate_3, candidate_4,...]
- }
-
-
-``candidate``
-'''''''''''''
-
-For each candidate we give its representation and position in the document. Candidates are sorted by decreasing order of suitability.
-
-``content``
- Representation of the candidate.
-``coords``
- ``[center_x, center_y, width, height, rotation_angle]``. The position and dimensions are relative to the size of the page and are therefore between 0 and 1.
- The angle is a clockwise rotation measured in degrees.
-``page``
- Page of the original document on which the candidate is located (starts at 0).
-
-.. container:: doc-aside
-
- .. switcher::
-
- .. code-block:: json
-
- {
- "content": string|float,
- "coords": [float, float, float, float, float],
- "page": int
- }
-
-+-------------------------+------------------------------------------------------------------------------------+
-| Feature name | Specifities |
-+=========================+====================================================================================+
-| ``SWIFT_code`` | **content** is a dictionary encoded as a string. |
-| | |
-| | It contains information about the detected SWIFT code |
-| | (or `BIC <https://www.iso9362.org/isobic/overview.html>`_). |
-| | |
-| | Keys: |
-| | |
-| | ``bic`` |
-| | detected BIC (string). |
-| | ``name`` (optional) |
-| | bank name (string). |
-| | ``country_code`` |
-| | ISO3166 alpha-2 country code of the bank (string). |
-| | ``city`` (optional) |
-| | city of the bank (string). |
-| | ``verified_bic`` |
-| | True if the BIC has been found in our DB (bool). |
-| | |
-| | Name and city are present only if verified_bic is true. |
-+-------------------------+------------------------------------------------------------------------------------+
-| ``VAT_Number`` | **content** is a string |
-+-------------------------+------------------------------------------------------------------------------------+
-| ``country`` | **content** is a string |
-+-------------------------+------------------------------------------------------------------------------------+
-| ``currency`` | **content** is a string |
-+-------------------------+------------------------------------------------------------------------------------+
-| ``date`` | **content** is a string |
-| | |
-| | Format : *YYYY-MM-DD HH:MM:SS* |
-+-------------------------+------------------------------------------------------------------------------------+
-| ``due_date`` | Same as for ``date`` |
-+-------------------------+------------------------------------------------------------------------------------+
-| ``global_taxes`` | **content** is a float |
-| | |
-| | **candidate** has an additional field ``amount_type``. Its value is always percent.|
-| | |
-| | **selected_values** is a list of candidates. |
-+-------------------------+------------------------------------------------------------------------------------+
-| ``global_taxes_amount`` | **content** is a float |
-+-------------------------+------------------------------------------------------------------------------------+
-| ``invoice_id`` | **content** is a string |
-+-------------------------+------------------------------------------------------------------------------------+
-| ``subtotal`` | **content** is a float |
-+-------------------------+------------------------------------------------------------------------------------+
-| ``total`` | **content** is a float |
-+-------------------------+------------------------------------------------------------------------------------+
-| ``supplier`` | **content** is a string |
-+-------------------------+------------------------------------------------------------------------------------+
-
-``feature_result`` for the ``invoice_lines`` feature
-''''''''''''''''''''''''''''''''''''''''''''''''''''
-
-It follows a more specific structure. It is basically a list of dictionaries where each dictionary represents an invoice line. Each value follows
-a :ref:`webservices/extract_api/invoice_get_results/feature_result` structure.
-
-.. container:: doc-aside
-
- .. switcher::
-
- .. code-block:: json
-
- [
- {
- "description": feature_result,
- "discount": feature_result,
- "product": feature_result,
- "quantity": feature_result,
- "subtotal": feature_result,
- "total": feature_result,
- "taxes": feature_result,
- "total": feature_result,
- "unit": feature_result,
- "unit_price": feature_result
- },
- ...
- ]
-
-.. _webservices/extract_api/invoice_validate:
-
-``/iap/invoice_extract/validate``
-'''''''''''''''''''''''''''''''''
-
-Description
-^^^^^^^^^^^
-Route that validates the different features of an invoice. The validation step is an optional step but is strongly recommended. By telling the system if it were right or wrong for each
-feature you give an important feedback. It has no direct impact but it helps the system to greatly improve its prediction accuracy for the invoices you will send in the future.
-
-Request Body
-^^^^^^^^^^^^
-
-``jsonrpc`` (required)
- |SAME_AS_PARSE|
-``method`` (required)
- |SAME_AS_PARSE|
-``params``
- ``documents_id`` (required)
- Id of the document for which you want to validate the result.
- ``values``
- Contains the validation for each feature. The field ``merged_line`` indicates if the ``invoice_lines`` have been merged or not.
-
-.. note:: You don't have to validate all the features in order for the validation to succeed. However :ref:`/validate <webservices/extract_api/invoice_validate>` can't be called multiple times for a same invoice.
- Therefore you should validate all the features you want to validate at once.
-
-.. rst-class:: setup doc-aside
-
-.. switcher::
-
- .. code-block:: json
-
- {
- "jsonrpc": string,
- "method": string,
- "params": {
- "document_id": int,
- "values": {
- "merged_lines": bool
- "feature_name_1": validation_1,
- "feature_name_2": validation_2,
- ...
- }
- },
- "id": string (hex),
- }
-
-``validation``
-''''''''''''''
-
-A **validation** for a given feature is a dictionary containing the textual representation of the expected value for this given feature.
-This format apply for all the features except for ``global_taxes`` and ``invoice_lines`` which have more complex validation format.
-
-.. rst-class:: setup doc-aside
-
-.. switcher::
-
- .. code-block:: json
-
- { "content": string|float }
-
-validation for ``global_taxes``
-'''''''''''''''''''''''''''''''
-
-**content** is a list of dictionaries. Each dictionary represents a tax:
-
-``amount``
- Amount on which the tax is applied.
-``tax_amount``
- Amount of the tax.
-``tax_amount_type``
- Indicates if the ``tax_amount`` is a percentage or a fixed value. The type must be specified using the literal string "fixed" or "percent".
-``tax_price_include``
- Indicates if ``amount`` already contains the tax or not.
-
-.. rst-class:: setup doc-aside
-
-.. switcher::
-
- .. code-block:: json
-
- {"content": [
- {
- "amount": float,
- "tax_amount": float,
- "tax_amount_type": "fixed"|"percent",
- "tax_price_include": bool
- },
- ...
- ]}
-
-validation for ``invoice_lines``
-''''''''''''''''''''''''''''''''
-
-**lines** is a list of dictionaries. Each dictionary represents an invoice line. The dictionary keys speak for themselves.
-
-.. rst-class:: setup doc-aside
-
-.. switcher::
-
- .. code-block:: json
-
- {"lines": [
- {
- "description": string,
- "quantity": float,
- "unit_price": float,
- "product": string,
- "taxes_amount": float,
- "taxes": [
- {
- "amount": float,
- "type": "fixed"|"percent",
- "price_include": bool
- },
- ...
- ],
- "subtotal": float,
- "total": float
- },
- ...
- ]}
-
-Response
---------
-
-``jsonrpc``
- |SAME_AS_PARSE|
-``id``
- |SAME_AS_PARSE|
-``result``
- ``status_code``
- |STATUS_CODE|
- ``status_msg``
- |STATUS_MSG|
-
-============= ==========================================================
- status_code status_msg
-============= ==========================================================
-0 Success
-12 Validation format is incorrect
-============= ==========================================================
-
-.. rst-class:: setup doc-aside
-
-.. switcher::
-
- .. code-block:: json
-
- {
- "jsonrpc": string,
- "id": string,
- "result": {
- "status_code": int,
- "status_msg": string,
- }
- }
-
-
-.. _webservices/extract_api/integration_testing:
-
-Integration Testing
-===================
-
-You can test your integration by using *integration_token* as ``account_token`` in the :ref:`/parse <webservices/extract_api/invoice_parse>` request.
-
-Using this token put you in test mode and allows you to simulate the entire flow without really parsing a document and without being billed one credit for each successful invoice parsing.
-
-The only technical differences in test mode is that the document you send is not parsed by the system and that the response you get from :ref:`/get_results <webservices/extract_api/invoice_get_results>`
-is a hard-coded one.
-
-A python implementation of the full flow can be found :download:`here </_static/extract_api_implementation.py>`.
-
-.. _JSON-RPC2: https://www.jsonrpc.org/specification
-
-.. |SAME_AS_PARSE| replace:: Same as for :ref:`/parse <webservices/extract_api/invoice_parse>`.
-
-.. |STATUS_CODE| replace:: The code indicating the status of the request. ``status_code`` is 0 in case of success. Other ``status_code`` are detailed in the table below.
-
-.. |STATUS_MSG| replace:: A string giving verbose details about the request status. \ No newline at end of file
diff --git a/doc/webservices/iap.rst b/doc/webservices/iap.rst
deleted file mode 100644
index b78beefc184..00000000000
--- a/doc/webservices/iap.rst
+++ /dev/null
@@ -1,770 +0,0 @@
-:banner: banners/iap.jpg
-:types: api
-
-.. _webservices/iap:
-
-.. using sphinx-patchqueue:
- * the "queue" directive selects a *series* file which lists the patches in
- the patch queue, in order of application (from top to bottom). The
- corresponding patch files should be in the same directory.
- * the "patch" directive steps to the next patch in the queue, applies it
- and reifies its content (depending on the extension's configuration, by
- default it shows the changed files post-diff application, slicing to
- only display sections affecte by the file)
-
-.. while it's technically possible to apply and update patches by hand, it's
- finnicky work and easy to break.
-
-.. the easiest way is to install quilt (http://savannah.nongnu.org/projects/quilt),
- go to the directory where you want to reify the addon, then create a
- "patches" symlink to the patches directory (the iap/ folder next to this
- file) or set QUILT_PATCHES to that folder.
-
-.. at that point you have a "primed" queue with no patch applied, and you can
- move within the queue with "quilt push" and "quilt pop".
- * "quilt new" creates a new empty patch at the top of the stack
- * "quilt add" tells quilt to start tracking the file, quilt add *works per
- patch*, it must be called *every time you want to alter a file within a
- patch*: quilt is not a full VCS (since it's intended to sit on top of
- an existing source) and does not do permanent tracking of files
- * "quilt edit" is a shorthand to "quilt add" then open the file in your
- editor, I suggest you use that rather than open the edited module
- normally, it avoids forgetting to "quilt add" before doing your
- modifications (at which point your modifications are untracked,
- invisible and depending on your editor may be a PITA to revert & redo)
- * "quilt refresh" updates the current patch to include pending changes
-
-.. see "man quilt" for the rest of the subcommands. FWIW I could not get
- "quilt setup" to do anything useful.
-
-===============
-In-App Purchase
-===============
-
-In-App Purchase (IAP) allows providers of ongoing services through Odoo apps to
-be compensated for ongoing service use rather than — and possibly instead of
-— a sole initial purchase.
-
-In that context, Odoo acts mostly as a *broker* between a client and an Odoo
-App Developer:
-
-* Users purchase service tokens from Odoo.
-* Service providers draw tokens from the user's Odoo account when service
- is requested.
-
-.. attention::
-
- This document is intended for *service providers* and presents the latter,
- which can be done either via direct JSON-RPC2_ or if you are using Odoo
- using the convenience helpers it provides.
-
-Overview
-========
-
-.. figure:: images/players.png
- :align: center
-
- The Players
-
- * The Service Provider is (probably) you the reader, you will be providing
- value to the client in the form of a service paid per-use.
- * The Client installed your Odoo App, and from there will request services.
- * Odoo brokers crediting, the Client adds credit to their account, and you
- can draw credits from there to provide services.
- * The External Service is an optional player: *you* can either provide a
- service directly, or you can delegate the actual service acting as a
- bridge/translator between an Odoo system and the actual service.
-
-
-.. figure:: images/credits.jpg
- :align: center
-
- The Credits
-
-.. note:: The credits went from integer to float value starting **October 2018**.
- Integer values are still supported.
-
- Every service provided through the IAP platform can be used by the
- clients with tokens or *credits*. The credits are an float unit and
- their monetary value depends on the service and is decided by the
- provider. This could be:
-
- * for an sms service: 1 credit = 1 sms;
- * for an ad service: 1 credit = 1 ad; or
- * for a postage service: 1 credit = 1 post stamp.
-
- A credit can also simply be associated with a fixed amount of money
- to palliate the variations of price (e.g. the prices of sms and stamps
- may vary following the countries).
-
- The value of the credits is fixed with the help of prepaid credit packs
- that the clients can buy on https://iap.odoo.com (see :ref:`Packs <iap-packages>`).
-
-.. note:: In the following explanations we will ignore the External Service,
- they are just a detail of the service you provide.
-
-.. figure:: images/normal.png
- :align: center
-
- 'Normal' service flow
-
- If everything goes well, the normal flow is the following:
-
- 1. The Client requests a service of some sort.
- 2. The Service Provider asks Odoo if there are enough credits for the
- service in the Client's account, and creates a transaction over that
- amount.
- 3. The Service Provider provides the service (either on their own or
- calling to External Services).
- 4. The Service Provider goes back to Odoo to capture (if the service could
- be provided) or cancel (if the service could not be provided) the
- transaction created at step 2.
- 5. Finally, the Service Provider notifies the Client that the service has
- been rendered, possibly (depending on the service) displaying or
- storing its results in the client's system.
-
-.. figure:: images/no-credit.png
- :align: center
-
- Insufficient credits
-
- However, if the Client's account lacks credits for the service, the flow will be as follows:
-
- 1. The Client requests a service as previously.
- 2. The Service Provider asks Odoo if there are enough credits on the
- Client's account and gets a negative reply.
- 3. This is signaled back to the Client.
- 4. Who is redirected to their Odoo account to credit it and re-try.
-
-
-Building your service
-=====================
-
-For this example, the service we will provide is ~~mining dogecoins~~ burning
-10 seconds of CPU for a credit. For your own services, you could, for example:
-
-* provide an online service yourself (e.g. convert quotations to faxes for
- business in Japan);
-* provide an *offline* service yourself (e.g. provide accountancy service); or
-* act as intermediary to an other service provider (e.g. bridge to an MMS
- gateway).
-
-.. _register-service:
-
-Register the service on Odoo
-----------------------------
-
-.. queue:: iap_service/series
-
-.. todo:: complete this part with screenshots
-
-The first step is to register your service on the IAP endpoint (production
-and/or test) before you can actually query user accounts. To create a service,
-go to your *Portal Account* on the IAP endpoint (https://iap.odoo.com for
-production, https://iap-sandbox.odoo.com for testing, the endpoints are
-*independent* and *not synchronized*). Alternatively, you can go to your portal
-on Odoo (https://iap.odoo.com/my/home) and select *In-App Services*.
-
-.. note::
-
- On production, there is a manual validation step before the service
- can be used to manage real transactions. This step is automatically passed when
- on sandbox to ease the tests.
-
-Log in then go to :menuselection:`My Account --> Your In-App Services`, click
-Create and provide the informations of your service.
-
-
-The service has *seven* important fields:
-
-* :samp:`name` - :class:`ServiceName`: This is the string you will need to provide inside
- the client's :ref:`app <iap-odoo-app>` when requesting a transaction from Odoo. (e.g.
- :class:`self.env['iap.account].get(name)`). As good practice, this should match the
- technical name of your app.
-
-* :samp:`label` - :class:`Label`: The name displayed on the shopping portal for the
- client.
-
-
-.. warning::
- Both the :class:`ServiceName` and :class:`Label` are unique. As good practice, the
- :class:`ServiceName` should usually match the name of your Odoo Client App.
-
-* :samp:`icon` - :class:`Icon`: A generic icon that will serve as default for your
- :ref:`packs <iap-packages>`.
-
-* :samp:`key` - :class:`ServiceKey`: The developer key that identifies you in
- IAP (see :ref:`your service <iap-service>`) and allows to draw credits from
- the client's account. It will be shown only once upon creation of the service
- and can be regenerated at will.
-
-.. danger::
- Your :class:`ServiceKey` *is a secret*, leaking your service key
- allows other application developers to draw credits bought for
- your service(s).
-
-* :samp:`trial credits` - :class:`Float`: This corresponds to the credits you are ready to offer
- upon first use to your app users. Note that such service will only be available to clients that
- have an active enterprise contract.
-
-* :samp:`privacy policy` - :class:`PrivacyPolicy`: This is an url to the privacy
- policy of your service. This should explicitly mention the **information you collect**,
- how you **use it, its relevance** to make your service work and inform the
- client on how they can **access, update or delete their personal information**.
-
-.. image:: images/menu.png
- :align: center
-
-.. image:: images/service_list.png
- :align: center
-
-.. image:: images/creating_service.png
- :align: center
-
-.. image:: images/service_created.png
- :align: center
-
-You can then create *credit packs* which clients can purchase in order to
-use your service.
-
-.. _iap-packages:
-
-Packs
------
-
-A credit pack is essentially a product with five characteristics:
-
-* Name: name of the pack,
-* Icon: specific icon for the pack (if not provided, it will fallback on the service icon),
-* Description: details on the pack that will appear on the shop page as
- well as the invoice,
-* Amount: amount of credits the client is entitled to when buying the pack,
-* Price: price in EUR (for the time being, USD support is planned).
-
-.. note::
-
- Odoo takes a 25% commission on all pack sales. Adjust your selling price accordingly.
-
-
-.. note::
-
- Depending on the strategy, the price per credit may vary from one
- pack to another.
-
-
-.. image:: images/package.png
- :align: center
-
-.. _iap-odoo-app:
-
-Odoo App
---------
-
-.. queue:: iap/series
-
-.. todo:: does this actually require apps?
-
-The second step is to develop an `Odoo App`_ which clients can install in their
-Odoo instance and through which they can *request* the services you provide.
-Our app will just add a button to the Partners form which lets a user request
-burning some CPU time on the server.
-
-First, we will create an *odoo module* depending on ``iap``. IAP is a standard
-V11 module and the dependency ensures a local account is properly set up and
-we will have access to some necessary views and useful helpers.
-
-.. patch::
-
-Second, the "local" side of the integration. Here we will only be adding an
-action button to the partners view, but you can of course provide significant
-local value via your application and additional parts via a remote service.
-
-.. patch::
-
-.. image:: images/button.png
- :align: center
-
-We can now implement the action method/callback. This will *call our own
-server*.
-
-There are no requirements when it comes to the server or the communication
-protocol between the app and our server, but ``iap`` provides a
-:func:`~odoo.addons.iap.tools.iap_tools.iap_jsonrpc` helper to call a JSON-RPC2_ endpoint on an
-other Odoo instance and transparently re-raise relevant Odoo exceptions
-(:class:`~odoo.addons.iap.tools.iap_tools.InsufficientCreditError`,
-:class:`odoo.exceptions.AccessError` and :class:`odoo.exceptions.UserError`).
-
-In that call, we will need to provide:
-
-* any relevant client parameter (none here),
-* the :class:`token <UserToken>` of the current client that is provided by
- the ``iap.account`` model's ``account_token`` field. You can retrieve the
- account for your service by calling :samp:`env['iap.account'].get({service_name})`
- where :class:`service_name <ServiceName>` is the name of the service registered
- on IAP endpoint.
-
-.. patch::
-
-.. note::
-
- ``iap`` automatically handles
- :class:`~odoo.addons.iap.tools.iap_tools.InsufficientCreditError` coming from the action
- and prompts the user to add credits to their account.
-
- :func:`~odoo.addons.iap.tools.iap_tools.iap_jsonrpc` takes care of re-raising
- :class:`~odoo.addons.iap.models.iap.InsufficientCreditError` for you.
-
-.. danger::
-
- If you are not using :func:`~odoo.addons.iap.tools.iap_tools.iap_jsonrpc` you *must* be
- careful to re-raise
- :class:`~odoo.addons.iap.tools.iap_tools.InsufficientCreditError` in your handler
- otherwise the user will not be prompted to credit their account, and the
- next call will fail the same way.
-
-.. _iap-service:
-
-Service
--------
-
-.. queue:: iap_service/series
-
-Though that is not *required*, since ``iap`` provides both a client helper
-for JSON-RPC2_ calls (:func:`~odoo.addons.iap.tools.iap_tools.iap_jsonrpc`) and a service helper
-for transactions (:class:`~odoo.addons.iap.tools.iap_tools.iap_charge`) we will also be
-implementing the service side as an Odoo module:
-
-.. patch::
-
-Since the query from the client comes as JSON-RPC2_ we will need the
-corresponding controller which can call :class:`~odoo.addons.iap.tools.iap_tools.iap_charge` and
-perform the service within:
-
-.. patch::
-
-.. todo:: for the actual IAP will the "portal" page be on odoo.com or iap.odoo.com?
-
-.. todo:: "My Account" > "Your InApp Services"?
-
-
-The :class:`~odoo.addons.iap.tools.iap_tools.iap_charge` helper will:
-
-1. authorize (create) a transaction with the specified number of credits,
- if the account does not have enough credits it will raise the relevant
- error
-2. execute the body of the ``with`` statement
-3. if the body of the ``with`` executes successfully, update the price
- of the transaction if needed
-4. capture (confirm) the transaction
-5. otherwise, if an error is raised from the body of the ``with``, cancel the
- transaction (and release the hold on the credits)
-
-.. danger::
-
- By default, :class:`~odoo.addons.iap.tools.iap_tools.iap_charge` contacts the *production*
- IAP endpoint, https://iap.odoo.com. While developing and testing your
- service you may want to point it towards the *development* IAP endpoint
- https://iap-sandbox.odoo.com.
-
- To do so, set the ``iap.endpoint`` config parameter in your service
- Odoo: in debug/developer mode, :menuselection:`Setting --> Technical -->
- Parameters --> System Parameters`, just define an entry for the key
- ``iap.endpoint`` if none already exists).
-
-The :class:`~odoo.addons.iap.tools.iap_tools.iap_charge` helper has two additional optional
-parameters we can use to make things clearer to the end-user.
-
-``description``
- is a message which will be associated with the transaction and will be
- displayed in the user's dashboard, it is useful to remind the user why
- the charge exists.
-``credit_template``
- is the name of a :ref:`reference/qweb` template which will be rendered
- and shown to the user if their account has less credit available than the
- service provider is requesting, its purpose is to tell your users why
- they should be interested in your IAP offers.
-
-.. patch::
-
-
-.. TODO:: how do you test your service?
-
-JSON-RPC2_ Transaction API
-==========================
-
-.. image:: images/flow.png
- :align: center
-
-* The IAP transaction API does not require using Odoo when implementing your
- server gateway, calls are standard JSON-RPC2_.
-* Calls use different *endpoints* but the same *method* on all endpoints
- (``call``).
-* Exceptions are returned as JSON-RPC2_ errors, the formal exception name is
- available on ``data.name`` for programmatic manipulation.
-
-.. seealso:: `iap.odoo.com documentation`_ for additional information.
-
-Authorize
----------
-
-.. function:: /iap/1/authorize
-
- Verifies that the user's account has at least as ``credit`` available
- *and creates a hold (pending transaction) on that amount*.
-
- Any amount currently on hold by a pending transaction is considered
- unavailable to further authorize calls.
-
- Returns a :class:`TransactionToken` identifying the pending transaction
- which can be used to capture (confirm) or cancel said transaction (`iap.odoo.com documentation`_).
-
- :param ServiceKey key:
- :param UserToken account_token:
- :param float credit:
- :param str description: optional, helps users identify the reason for
- charges on their account
- :param str dbuuid: optional, allows the user to benefit from trial
- credits if his database is eligible (see :ref:`Service registration <register-service>`)
- :returns: :class:`TransactionToken` if the authorization succeeded
- :raises: :class:`~odoo.exceptions.AccessError` if the service token is invalid
- :raises: :class:`~odoo.addons.iap.models.iap.InsufficientCreditError` if the account does not have enough credits
- :raises: ``TypeError`` if the ``credit`` value is not an integer or a float
-
-.. code-block:: python
-
- r = requests.post(ODOO + '/iap/1/authorize', json={
- 'jsonrpc': '2.0',
- 'id': None,
- 'method': 'call',
- 'params': {
- 'account_token': user_account,
- 'key': SERVICE_KEY,
- 'credit': 25,
- 'description': "Why this is being charged",
- }
- }).json()
- if 'error' in r:
- # handle authorize error
- tx = r['result']
-
- # provide your service here
-
-Capture
--------
-
-.. function:: /iap/1/capture
-
- Confirms the specified transaction, transferring the reserved credits from
- the user's account to the service provider's.
-
- Capture calls are idempotent: performing capture calls on an already
- captured transaction has no further effect.
-
- :param TransactionToken token:
- :param ServiceKey key:
- :param float credit_to_capture: optional parameter to capture a smaller amount of credits than authorized
- :raises: :class:`~odoo.exceptions.AccessError`
-
-.. code-block:: python
- :emphasize-lines: 8
-
- r2 = requests.post(ODOO + '/iap/1/capture', json={
- 'jsonrpc': '2.0',
- 'id': None,
- 'method': 'call',
- 'params': {
- 'token': tx,
- 'key': SERVICE_KEY,
- 'credit_to_capture': credit or False,
- }
- }).json()
- if 'error' in r:
- # handle capture error
- # otherwise transaction is captured
-
-Cancel
-------
-
-.. function:: /iap/1/cancel
-
- Cancels the specified transaction, releasing the hold on the user's
- credits.
-
- Cancel calls are idempotent: performing capture calls on an already
- cancelled transaction has no further effect.
-
- :param TransactionToken token:
- :param ServiceKey key:
- :raises: :class:`~odoo.exceptions.AccessError`
-
-.. code-block:: python
-
- r2 = requests.post(ODOO + '/iap/1/cancel', json={
- 'jsonrpc': '2.0',
- 'id': None,
- 'method': 'call',
- 'params': {
- 'token': tx,
- 'key': SERVICE_KEY,
- }
- }).json()
- if 'error' in r:
- # handle cancel error
- # otherwise transaction is cancelled
-
-Types
------
-
-Exceptions aside, these are *abstract types* used for clarity, you should not
-care how they are implemented.
-
-.. class:: ServiceName
-
- String identifying your service on https://iap.odoo.com (production) as well
- as the account related to your service in the client's database.
-
-.. class:: ServiceKey
-
- Identifier generated for the provider's service. Each key (and service)
- matches a token of a fixed value, as generated by the service provide.
-
- Multiple types of tokens correspond to multiple services. As an exampe, SMS and MMS
- could either be the same service (with an MMS being 'worth' multiple SMS)
- or could be separate services at separate price points.
-
- .. danger:: Your service key *is a secret*, leaking your service key
- allows other application developers to draw credits bought for
- your service(s).
-
-.. class:: UserToken
-
- Identifier for a user account.
-
-.. class:: TransactionToken
-
- Transaction identifier, returned by the authorization process and consumed
- by either capturing or cancelling the transaction.
-
-.. exception:: odoo.addons.iap.tools.iap_tools.InsufficientCreditError
-
- Raised during transaction authorization if the credits requested are not
- currently available on the account (either not enough credits or too many
- pending transactions/existing holds).
-
-.. exception:: odoo.exceptions.AccessError
- :noindex:
-
- Raised by:
-
- * any operation to which a service token is required, if the service token is invalid; or
- * any failure in an inter-server call. (typically, in :func:`~odoo.addons.iap.tools.iap_tools.iap_jsonrpc`).
-
-.. exception:: odoo.exceptions.UserError
- :noindex:
-
- Raised by any unexpected behaviour at the discretion of the App developer (*you*).
-
-
-Test the API
-------------
-
-In order to test the developped app, we propose a sandbox platform that allows you to:
-
-1. Test the whole flow from the client's point of view - Actual services and transactions
- that can be consulted. (again this requires to change the endpoint, see the danger note
- in :ref:`Service <iap-service>`).
-2. Test the API.
-
-The latter consists in specific tokens that will work on **IAP-Sandbox only**.
-
-* Token ``000000``: Represents a non-existing account. Returns
- an :class:`~odoo.addons.iap.tools.iap_tools.InsufficientCreditError` on authorize attempt.
-* Token ``000111``: Represents an account without sufficient credits to perform any service.
- Returns an :class:`~odoo.addons.iap.tools.iap_tools.InsufficientCreditError` on authorize attempt.
-* Token ``111111``: Represents an account with enough credits to perform any service.
- An authorize attempt will return a dummy transacion token that is processed by the capture
- and cancel routes.
-
-.. note::
-
- * Those tokens are only active on the IAP-Sanbox server.
- * The service key is completely ignored with this flow, If you want to run a robust test
- of your service, you should ignore these tokens.
-
-Odoo Helpers
-============
-
-For convenience, if you are implementing your service using Odoo the ``iap``
-module provides a few helpers to make IAP flow even simpler.
-
-.. _iap-charging:
-
-Charging
---------
-
-.. class:: odoo.addons.iap.tools.iap_tools.iap_charge(env, key, account_token, credit[, dbuuid, description, credit_template])
-
- A *context manager* for authorizing and automatically capturing or
- cancelling transactions for use in the backend/proxy.
-
- Works much like e.g. a cursor context manager:
-
- * immediately authorizes a transaction with the specified parameters;
- * executes the ``with`` body;
- * if the body executes in full without error, captures the transaction;
- * otherwise cancels it.
-
- :param odoo.api.Environment env: used to retrieve the ``iap.endpoint``
- configuration key
- :param ServiceKey key:
- :param UserToken token:
- :param float credit:
- :param str description:
- :param Qweb template credit_template:
-
-.. code-block:: python
- :emphasize-lines: 11,13,14,15
-
- @route('/deathstar/superlaser', type='json')
- def superlaser(self, user_account,
- coordinates, target,
- factor=1.0):
- """
- :param factor: superlaser power factor,
- 0.0 is none, 1.0 is full power
- """
- credits = int(MAXIMUM_POWER * factor)
- description = "We will demonstrate the power of this station on your home planet of Alderaan."
- with iap_charge(request.env, SERVICE_KEY, user_account, credits, description) as transaction:
- # TODO: allow other targets
- transaction.credit = max(credits, 2)
- # Sales ongoing one the energy price,
- # a maximum of 2 credits will be charged/captured.
- self.env['systems.planets'].search([
- ('grid', '=', 'M-10'),
- ('name', '=', 'Alderaan'),
- ]).unlink()
-
-
-Authorize
----------
-
-.. class:: odoo.addons.iap.tools.iap_tools.iap_authorize(env, key, account_token, credit[, dbuuid, description, credit_template])
-
- Will authorize everything.
-
- :param odoo.api.Environment env: used to retrieve the ``iap.endpoint``
- configuration key
- :param ServiceKey key:
- :param UserToken token:
- :param float credit:
- :param str description:
- :param Qweb template credit_template:
-
-.. code-block:: python
- :emphasize-lines: 12
-
- @route('/deathstar/superlaser', type='json')
- def superlaser(self, user_account,
- coordinates, target,
- factor=1.0):
- """
- :param factor: superlaser power factor,
- 0.0 is none, 1.0 is full power
- """
- credits = int(MAXIMUM_POWER * factor)
- description = "We will demonstrate the power of this station on your home planet of Alderaan."
- #actual IAP stuff
- transaction_token = authorize(request.env, SERVICE_KEY, user_account, credits, description=description)
- try:
- # Beware the power of this laser
- self.put_galactical_princess_in_sorrow()
- except Exception as e:
- # Nevermind ...
- r = cancel(env,transaction_token, key)
- raise e
- else:
- # We shall rule over the galaxy!
- capture(env,transaction_token, key, min(credits, 2))
-
-Cancel
-------
-
-.. class:: odoo.addons.iap.tools.iap_tools.iap_cancel(env, transaction_token, key)
-
- Will cancel an authorized transaction.
-
- :param odoo.api.Environment env: used to retrieve the ``iap.endpoint``
- configuration key
- :param str transaction_token:
- :param ServiceKey key:
-
-.. code-block:: python
- :emphasize-lines: 16,17,18,19
-
- @route('/deathstar/superlaser', type='json')
- def superlaser(self, user_account,
- coordinates, target,
- factor=1.0):
- """
- :param factor: superlaser power factor,
- 0.0 is none, 1.0 is full power
- """
- credits = int(MAXIMUM_POWER * factor)
- description = "We will demonstrate the power of this station on your home planet of Alderaan."
- #actual IAP stuff
- transaction_token = authorize(request.env, SERVICE_KEY, user_account, credits, description=description)
- try:
- # Beware the power of this laser
- self.put_galactical_princess_in_sorrow()
- except Exception as e:
- # Nevermind ...
- r = cancel(env,transaction_token, key)
- raise e
- else:
- # We shall rule over the galaxy!
- capture(env,transaction_token, key, min(credits, 2))
-
-Capture
--------
-
-.. class:: odoo.addons.iap.tools.iap_tools.iap_capture(env, transaction_token, key, credit)
-
- Will capture the amount ``credit`` on the given transaction.
-
- :param odoo.api.Environment env: used to retrieve the ``iap.endpoint``
- configuration key
- :param str transaction_token:
- :param ServiceKey key:
- :param credit:
-
-.. code-block:: python
- :emphasize-lines: 20,21,22
-
- @route('/deathstar/superlaser', type='json')
- def superlaser(self, user_account,
- coordinates, target,
- factor=1.0):
- """
- :param factor: superlaser power factor,
- 0.0 is none, 1.0 is full power
- """
- credits = int(MAXIMUM_POWER * factor)
- description = "We will demonstrate the power of this station on your home planet of Alderaan."
- #actual IAP stuff
- transaction_token = authorize(request.env, SERVICE_KEY, user_account, credits, description=description)
- try:
- # Beware the power of this laser
- self.put_galactical_princess_in_sorrow()
- except Exception as e:
- # Nevermind ...
- r = cancel(env,transaction_token, key)
- raise e
- else:
- # We shall rule over the galaxy!
- capture(env,transaction_token, key, min(credits, 2))
-
-
-.. _JSON-RPC2: https://www.jsonrpc.org/specification
-.. _Odoo App: https://www.odoo.com/apps
-.. _iap.odoo.com documentation: https://iap.odoo.com/iap/1/documentation
diff --git a/doc/webservices/iap/01-init b/doc/webservices/iap/01-init
deleted file mode 100644
index 243dd911e97..00000000000
--- a/doc/webservices/iap/01-init
+++ /dev/null
@@ -1,16 +0,0 @@
-Index: coalroller/coalroller/__manifest__.py
-===================================================================
---- /dev/null
-+++ coalroller/coalroller/__manifest__.py
-@@ -0,0 +1,5 @@
-+{
-+ 'name': "Coal Roller",
-+ 'category': 'Tools',
-+ 'depends': ['iap'],
-+}
-Index: coalroller/coalroller/__init__.py
-===================================================================
---- /dev/null
-+++ coalroller/coalroller/__init__.py
-@@ -0,0 +1 @@
-+# -*- coding: utf-8 -*-
diff --git a/doc/webservices/iap/02-button b/doc/webservices/iap/02-button
deleted file mode 100644
index c5e73606e85..00000000000
--- a/doc/webservices/iap/02-button
+++ /dev/null
@@ -1,34 +0,0 @@
-Index: coalroller/coalroller/__manifest__.py
-===================================================================
---- coalroller.orig/coalroller/__manifest__.py
-+++ coalroller/coalroller/__manifest__.py
-@@ -2,4 +2,7 @@
- 'name': "Coal Roller",
- 'category': 'Tools',
- 'depends': ['iap'],
-+ 'data': [
-+ 'views/views.xml',
-+ ],
- }
-Index: coalroller/coalroller/views/views.xml
-===================================================================
---- /dev/null
-+++ coalroller/coalroller/views/views.xml
-@@ -0,0 +1,17 @@
-+<odoo>
-+ <record model="ir.ui.view" id="partner_form_coalroll">
-+ <field name="name">partner.form.coalroll</field>
-+ <field name="model">res.partner</field>
-+ <field name="inherit_id" ref="base.view_partner_form" />
-+ <field name="arch" type="xml">
-+ <xpath expr="//div[@name='button_box']">
-+ <button type="object" name="action_partner_coalroll"
-+ class="oe_stat_button" icon="fa-gears">
-+ <div class="o_form_field o_stat_info">
-+ <span class="o_stat_text">Roll Coal</span>
-+ </div>
-+ </button>
-+ </xpath>
-+ </field>
-+ </record>
-+</odoo>
diff --git a/doc/webservices/iap/03-callback b/doc/webservices/iap/03-callback
deleted file mode 100644
index af083f4e00e..00000000000
--- a/doc/webservices/iap/03-callback
+++ /dev/null
@@ -1,39 +0,0 @@
-Index: coalroller/coalroller/__init__.py
-===================================================================
---- coalroller.orig/coalroller/__init__.py
-+++ coalroller/coalroller/__init__.py
-@@ -1 +1,2 @@
- # -*- coding: utf-8 -*-
-+from . import models
-Index: coalroller/coalroller/models/__init__.py
-===================================================================
---- /dev/null
-+++ coalroller/coalroller/models/__init__.py
-@@ -0,0 +1 @@
-+from . import res_partner
-Index: coalroller/coalroller/models/res_partner.py
-===================================================================
---- /dev/null
-+++ coalroller/coalroller/models/res_partner.py
-@@ -0,0 +1,21 @@
-+# -*- coding: utf-8 -*-
-+from odoo import api, models
-+from odoo.addons.iap import jsonrpc, InsufficientCreditError
-+
-+# whichever URL you deploy the service at, here we will run the remote
-+# service in a local Odoo bound to the port 8070
-+DEFAULT_ENDPOINT = 'http://localhost:8070'
-+class Partner(models.Model):
-+ _inherit = 'res.partner'
-+ def action_partner_coalroll(self):
-+ # fetch the user's token for our service
-+ user_token = self.env['iap.account'].get('coalroller')
-+ params = {
-+ # we don't have any parameter to provide
-+ 'account_token': user_token.account_token
-+ }
-+ # ir.config_parameter allows locally overriding the endpoint
-+ # for testing & al
-+ endpoint = self.env['ir.config_parameter'].sudo().get_param('coalroller.endpoint', DEFAULT_ENDPOINT)
-+ jsonrpc(endpoint + '/roll', params=params)
-+ return True
diff --git a/doc/webservices/iap/series b/doc/webservices/iap/series
deleted file mode 100644
index d44682b30f0..00000000000
--- a/doc/webservices/iap/series
+++ /dev/null
@@ -1,3 +0,0 @@
-01-init
-02-button
-03-callback
diff --git a/doc/webservices/iap_service/01-init b/doc/webservices/iap_service/01-init
deleted file mode 100644
index 0ffc92159ad..00000000000
--- a/doc/webservices/iap_service/01-init
+++ /dev/null
@@ -1,16 +0,0 @@
-Index: coalroller_service/coalroller_service/__init__.py
-===================================================================
---- /dev/null
-+++ coalroller_service/coalroller_service/__init__.py
-@@ -0,0 +1 @@
-+# -*- encoding: utf-8 -*-
-Index: coalroller_service/coalroller_service/__manifest__.py
-===================================================================
---- /dev/null
-+++ coalroller_service/coalroller_service/__manifest__.py
-@@ -0,0 +1,5 @@
-+{
-+ 'name': "Coal Roller Service",
-+ 'category': 'Tools',
-+ 'depends': ['iap'],
-+}
diff --git a/doc/webservices/iap_service/02-tnx b/doc/webservices/iap_service/02-tnx
deleted file mode 100644
index 68cfbdc82e3..00000000000
--- a/doc/webservices/iap_service/02-tnx
+++ /dev/null
@@ -1,48 +0,0 @@
-Index: coalroller_service/coalroller_service/controllers/main.py
-===================================================================
---- /dev/null
-+++ coalroller_service/coalroller_service/controllers/main.py
-@@ -0,0 +1,29 @@
-+import time
-+
-+from passlib import pwd, hash
-+
-+from odoo import http
-+from odoo.addons.iap import charge
-+
-+class CoalBurnerController(http.Controller):
-+ @http.route('/roll', type='json', auth='none', csrf='false')
-+ def roll(self, account_token):
-+ # the service key *is a secret*, it should not be committed in
-+ # the source
-+ service_key = self.env['ir.config_parameter'].sudo().get_param('coalroller.service_key')
-+
-+ # we charge 1 credit for 10 seconds of CPU
-+ cost = 1
-+ # TODO: allow the user to specify how many (tens of seconds) of CPU they want to use
-+ with charge(http.request.env, service_key, account_token, cost):
-+
-+ # 10 seconds of CPU per credit
-+ end = time.time() + (10 * cost)
-+ while time.time() < end:
-+ # we will use CPU doing useful things: generating and
-+ # hashing passphrases
-+ p = pwd.genphrase()
-+ h = hash.pbkdf2_sha512.hash(p)
-+ # here we don't have anything useful to the client, an error
-+ # will be raised & transmitted in case of issue, if no error
-+ # is raised we did the job
-Index: coalroller_service/coalroller_service/controllers/__init__.py
-===================================================================
---- /dev/null
-+++ coalroller_service/coalroller_service/controllers/__init__.py
-@@ -0,0 +1,2 @@
-+# -*- encoding: utf-8 -*-
-+from . import main
-Index: coalroller_service/coalroller_service/__init__.py
-===================================================================
---- coalroller_service.orig/coalroller_service/__init__.py
-+++ coalroller_service/coalroller_service/__init__.py
-@@ -1 +1,2 @@
- # -*- encoding: utf-8 -*-
-+from . import controllers
diff --git a/doc/webservices/iap_service/03-template b/doc/webservices/iap_service/03-template
deleted file mode 100644
index de79726e1f8..00000000000
--- a/doc/webservices/iap_service/03-template
+++ /dev/null
@@ -1,56 +0,0 @@
-Index: coalroller_service/coalroller_service/controllers/main.py
-===================================================================
---- coalroller_service.orig/coalroller_service/controllers/main.py
-+++ coalroller_service/coalroller_service/controllers/main.py
-@@ -10,12 +10,14 @@ class CoalBurnerController(http.Controll
- def roll(self, account_token):
- # the service key *is a secret*, it should not be committed in
- # the source
-- service_key = self.env['ir.config_parameter'].sudo().get_param('coalroller.service_key')
-+ service_key = http.request.env['ir.config_parameter'].sudo().get_param('coalroller.service_key')
-
- # we charge 1 credit for 10 seconds of CPU
- cost = 1
- # TODO: allow the user to specify how many (tens of seconds) of CPU they want to use
-- with charge(http.request.env, service_key, account_token, cost):
-+ with charge(http.request.env, service_key, account_token, cost,
-+ description="We're just obeying orders",
-+ credit_template='coalroller_service.no_credit'):
-
- # 10 seconds of CPU per credit
- end = time.time() + (10 * cost)
-Index: coalroller_service/coalroller_service/views/no-credit.xml
-===================================================================
---- /dev/null
-+++ coalroller_service/coalroller_service/views/no-credit.xml
-@@ -0,0 +1,18 @@
-+<odoo>
-+ <template id="no_credit" name="No credit warning">
-+ <div>
-+ <div class="container-fluid">
-+ <div class="row">
-+ <div class="col-md-7 offset-lg-1 mt32 mb32">
-+ <h2>Consume electricity doing nothing useful!</h2>
-+ <ul>
-+ <li>Heat our state of the art data center for no reason</li>
-+ <li>Use multiple watts for only 0.1€</li>
-+ <li>Roll coal without going outside</li>
-+ </ul>
-+ </div>
-+ </div>
-+ </div>
-+ </div>
-+ </template>
-+</odoo>
-Index: coalroller_service/coalroller_service/__manifest__.py
-===================================================================
---- coalroller_service.orig/coalroller_service/__manifest__.py
-+++ coalroller_service/coalroller_service/__manifest__.py
-@@ -2,4 +2,7 @@
- 'name': "Coal Roller Service",
- 'category': 'Tools',
- 'depends': ['iap'],
-+ 'data': [
-+ 'views/no-credit.xml',
-+ ],
- }
diff --git a/doc/webservices/iap_service/series b/doc/webservices/iap_service/series
deleted file mode 100644
index 68544a42924..00000000000
--- a/doc/webservices/iap_service/series
+++ /dev/null
@@ -1,3 +0,0 @@
-01-init
-02-tnx
-03-template
diff --git a/doc/webservices/images/account-security.png b/doc/webservices/images/account-security.png
deleted file mode 100644
index cf91646dd64..00000000000
--- a/doc/webservices/images/account-security.png
+++ /dev/null
Binary files differ
diff --git a/doc/webservices/images/button.png b/doc/webservices/images/button.png
deleted file mode 100644
index 36283cb7467..00000000000
--- a/doc/webservices/images/button.png
+++ /dev/null
Binary files differ
diff --git a/doc/webservices/images/creating_service.png b/doc/webservices/images/creating_service.png
deleted file mode 100644
index 7cf7b247a61..00000000000
--- a/doc/webservices/images/creating_service.png
+++ /dev/null
Binary files differ
diff --git a/doc/webservices/images/credits.jpg b/doc/webservices/images/credits.jpg
deleted file mode 100644
index 734f10e83ad..00000000000
--- a/doc/webservices/images/credits.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/webservices/images/credits2.jpg b/doc/webservices/images/credits2.jpg
deleted file mode 100644
index 037bcb1c910..00000000000
--- a/doc/webservices/images/credits2.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/webservices/images/delete-key.png b/doc/webservices/images/delete-key.png
deleted file mode 100644
index df14cb35dfc..00000000000
--- a/doc/webservices/images/delete-key.png
+++ /dev/null
Binary files differ
diff --git a/doc/webservices/images/flow.png b/doc/webservices/images/flow.png
deleted file mode 100644
index 3fc74a63be5..00000000000
--- a/doc/webservices/images/flow.png
+++ /dev/null
Binary files differ
diff --git a/doc/webservices/images/menu.png b/doc/webservices/images/menu.png
deleted file mode 100644
index 50e1ed0267a..00000000000
--- a/doc/webservices/images/menu.png
+++ /dev/null
Binary files differ
diff --git a/doc/webservices/images/no-credit.png b/doc/webservices/images/no-credit.png
deleted file mode 100644
index dc331280031..00000000000
--- a/doc/webservices/images/no-credit.png
+++ /dev/null
Binary files differ
diff --git a/doc/webservices/images/normal.png b/doc/webservices/images/normal.png
deleted file mode 100644
index 39ce9ee06a7..00000000000
--- a/doc/webservices/images/normal.png
+++ /dev/null
Binary files differ
diff --git a/doc/webservices/images/package.png b/doc/webservices/images/package.png
deleted file mode 100644
index c78fd67f8c6..00000000000
--- a/doc/webservices/images/package.png
+++ /dev/null
Binary files differ
diff --git a/doc/webservices/images/players.png b/doc/webservices/images/players.png
deleted file mode 100644
index 57022ac1312..00000000000
--- a/doc/webservices/images/players.png
+++ /dev/null
Binary files differ
diff --git a/doc/webservices/images/preferences.png b/doc/webservices/images/preferences.png
deleted file mode 100644
index 1ce36717e32..00000000000
--- a/doc/webservices/images/preferences.png
+++ /dev/null
Binary files differ
diff --git a/doc/webservices/images/service_created.png b/doc/webservices/images/service_created.png
deleted file mode 100644
index fea8c2b4571..00000000000
--- a/doc/webservices/images/service_created.png
+++ /dev/null
Binary files differ
diff --git a/doc/webservices/images/service_list.png b/doc/webservices/images/service_list.png
deleted file mode 100644
index cb241d6723e..00000000000
--- a/doc/webservices/images/service_list.png
+++ /dev/null
Binary files differ
diff --git a/doc/webservices/images/template.png b/doc/webservices/images/template.png
deleted file mode 100644
index 6256c01151e..00000000000
--- a/doc/webservices/images/template.png
+++ /dev/null
Binary files differ
diff --git a/doc/webservices/localization.rst b/doc/webservices/localization.rst
deleted file mode 100644
index 9eec234c843..00000000000
--- a/doc/webservices/localization.rst
+++ /dev/null
@@ -1,423 +0,0 @@
-:banner: banners/localization.jpg
-
-=======================
-Creating a Localization
-=======================
-
-.. warning::
-
- This tutorial requires knowledges about how to build a module in Odoo (see
- :doc:`../../howtos/backend`).
-
-Building a localization module
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-When installing the ``accounting`` module, the localization module corresponding to the country code of the company is installed automatically.
-In case of no country code set or no localization module found, the ``l10n_generic_coa`` (US) localization module is installed by default.
-
-For example, ``l10n_be`` will be installed if the company has ``Belgium`` as country.
-
-This behavior is allowed by the presence of a *.xml* file containing the following code:
-
-.. code-block:: xml
-
- <function model="account.chart.template" name="try_loading_for_current_company">
- <value eval="[ref(module.template_xmlid)]"/>
- </function>
-
-Where ``module.template_xmlid`` is the **fully-qualified** xmlid of the corresponding template.
-
-Usually located in the ``data`` folder, it must be loaded at the very last in the ``__manifest__.py`` file.
-
-.. danger::
-
- If the *.xml* file is missing, the right chart of accounts won't be loaded on time!
-
-
-Configuring my own Chart of Accounts?
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-First of all, before I proceed, we need to talk about the templates. A template is a record that allows replica of itself.
-This mechanism is needed when working in multi-companies. For example, the creation of a new account is done using the ``account.account.template`` model.
-However, each company using this chart of accounts will be linked to a replica having ``account.account`` as model.
-So, the templates are never used directly by the company.
-
-Then, when a chart of accounts needs to be installed, all templates dependent of this one will create a replica and link this newly generated record to the company's user.
-It means all such templates must be linked to the chart of accounts in some way. To do so, each one must reference the desired chart of accounts using the ``chart_template_id`` field.
-For this reason, we need to define an instance of the ``account.chart.template`` model before creating its templates.
-
-.. code-block:: xml
-
- <record id="..." model="account.chart.template">
- <!-- [Required] Specify the name to display for this CoA. -->
- <field name="name">...</field>
-
- <!-- [Required] Specify the currency. E.g. "base.USD". -->
- <field name="currency_id" ref="..."/>
-
- <!-- [Required] Specify a prefix of the bank accounts. -->
- <field name="bank_account_code_prefix">...</field>
-
- <!-- [Required] Specify a prefix of the cash accounts. -->
- <field name="cash_account_code_prefix">...</field>
-
- <!-- [Optional] Define a parent chart of accounts that will be installed just before this one. -->
- <field name="parent_id" ref="..."/>
-
- <!-- [Optional] Define the number of digits of account codes. By default, the value is 6. -->
- <field name="code_digits">...</field>
-
- <!-- [Optional] Boolean to show or not this CoA on the list. By default, the CoA is visible.
- This field is mostly used when this CoA has some children (see parent_id field). -->
- <field name="visible" eval="..."/>
-
- <!-- [Optional] Boolean to enable the Anglo-Saxon accounting. By default, this field is False. -->
- <field name="use_anglo_saxon" eval="..."/>
-
- <!-- [Optional] Boolean to enable the complete set of taxes. By default, this field is True.
- This boolean helps you to choose if you want to propose to the user to encode the sale and purchase rates or choose from list of taxes.
- This last choice assumes that the set of tax defined on this template is complete. -->
- <field name="complete_tax_set" eval="..."/>
-
- <!-- [Optional] Specify the spoken languages.
- /!\ This option is only available if your module depends of l10n_multilang.
- You must provide the language codes separated by ';', e.g. eval="'en_US;ar_EG;ar_SY'". -->
- <field name="spoken_languages" eval="..."/>
- </record>
-
-For example, let's take a look to the Belgium chart of accounts.
-
-.. code-block:: xml
-
- <record id="l10nbe_chart_template" model="account.chart.template">
- <field name="name">Belgian PCMN</field>
- <field name="currency_id" ref="base.EUR"/>
- <field name="bank_account_code_prefix">550</field>
- <field name="cash_account_code_prefix">570</field>
- <field name="spoken_languages" eval="'nl_BE'"/>
- </record>
-
-Now that the chart of accounts is created, we can focus on the creation of the templates.
-As said previously, each record must reference this record through the ``chart_template_id`` field.
-If not, the template will be ignored. The following sections show in details how to create these templates.
-
-Adding a new account to my Chart of Accounts
-############################################
-
-It's time to create our accounts. It consists to creating records of ``account.account.template`` type.
-Each ``account.account.template`` is able to create an ``account.account`` for each company.
-
-.. code-block:: xml
-
- <record id="..." model="account.account.template">
- <!-- [Required] Specify the name to display for this account. -->
- <field name="name">...</field>
-
- <!-- [Required] Specify a code. -->
- <field name="code">...</field>
-
- <!-- [Required] Specify a type. -->
- <field name="user_type_id">...</field>
-
- <!-- [Required] Set the CoA owning this account. -->
- <field name="chart_template_id" ref="..."/>
-
- <!-- [Optional] Specify a secondary currency for each account.move.line linked to this account. -->
- <field name="currency_id" ref="..."/>
-
- <!-- [Optional] Boolean to allow the user to reconcile entries in this account. True by default. -->
- <field name="reconcile" eval="..."/>
-
- <!-- [Optional] Specify a group for this account. -->
- <field name="group_id" ref="...">
-
- <!-- [Optional] Specify some tags. -->
- <field name="tag_ids" eval="...">
- </record>
-
-Some of the described fields above deserve a bit more explanation.
-
-The ``user_type_id`` field requires a value of type ``account.account.type``.
-Although some additional types could be created in a localization module, we encourage the usage of the existing types in the `account/data/data_account_type.xml <https://github.com/odoo/odoo/blob/14.0/addons/account/data/data_account_type.xml>`_ file.
-The usage of these generic types ensures the generic reports working correctly in addition to those that you could create in your localization module.
-
-.. warning::
-
- Avoid the usage of liquidity ``account.account.type``!
- Indeed, the bank & cash accounts are created directly at the installation of the localization module and then, are linked to an ``account.journal``.
-
-.. warning::
-
- Only one account of type payable/receivable is enough.
-
-Although the ``tag_ids`` field is optional, this one remains a very powerful feature.
-Indeed, this one allows you to define some tags for your accounts to spread them correctly on your reports.
-For example, suppose you want to create a financial report having multiple lines but you have no way to find a rule to dispatch the accounts according their ``code`` or ``name``.
-The solution is the usage of tags, one for each report line, to spread and aggregate your accounts like you want.
-
-Like any other record, a tag can be created with the following xml structure:
-
-.. code-block:: xml
-
- <record id="..." model="account.account.tag">
- <!-- [Required] Specify the name to display for this tag. -->
- <field name="name">...</field>
-
- <!-- [Optional] Define a scope for this applicability.
- The available keys are 'accounts' and 'taxes' but 'accounts' is the default value. -->
- <field name="applicability">...</field>
- </record>
-
-As you can well imagine with the usage of tags, this feature can also be used with taxes.
-
-An examples coming from the ``l10n_be`` module:
-
-.. code-block:: xml
-
- <record id="a4000" model="account.account.template">
- <field name="name">Clients</field>
- <field name="code">4000</field>
- <field name="user_type_id" ref="account.data_account_type_receivable"/>
- <field name="chart_template_id" ref="l10nbe_chart_template"/>
- </record>
-
-.. warning::
-
- Don't create too much accounts: 200-300 is enough.
-
-Adding a new tax to my Chart of Accounts
-########################################
-
-To create a new tax record, you just need to follow the same process as the creation of accounts.
-The only difference being that you must use the ``account.tax.template`` model.
-
-.. code-block:: xml
-
- <record id="..." model="account.tax.template">
- <!-- [Required] Specify the name to display for this tax. -->
- <field name="name">...</field>
-
- <!-- [Required] Specify the amount.
- E.g. 7 with fixed amount_type means v + 7 if v is the amount on which the tax is applied.
- If amount_type is 'percent', the tax amount is v * 0.07. -->
- <field name="amount" eval="..."/>
-
- <!-- [Required] Set the CoA owning this tax. -->
- <field name="chart_template_id" ref="..."/>
-
- <!-- [Required/Optional] Define an account if the tax is not a group of taxes. -->
- <field name="account_id" ref="..."/>
-
- <!-- [Required/Optional] Define an refund account if the tax is not a group of taxes. -->
- <field name="refund_account_id" ref="..."/>
-
- <!-- [Optional] Define the tax's type.
- 'sale', 'purchase' or 'none' are the allowed values. 'sale' is the default value.
- Note: 'none' means a tax can't be used by itself, however it can still be used in a group. -->
- <field name="type_tax_use">...</field>
-
- <!-- [Optional] Define the type of amount:
- 'group' for a group of taxes, 'fixed' for a tax with a fixed amount or 'percent' for a classic percentage of price.
- By default, the type of amount is percentage. -->
- <field name="amount_type" eval="..."/>
-
- <!-- [Optional] Define some children taxes.
- /!\ Should be used only with an amount_type with 'group' set. -->
- <field name="children_tax_ids" eval="..."/>
-
- <!-- [Optional] The sequence field is used to define order in which the tax lines are applied.
- By default, sequence = 1. -->
- <field name="sequence" eval="..."/>
-
- <!-- [Optional] Specify a short text to be displayed on invoices.
- For example, a tax named "15% on Services" can have the following label on invoice "15%". -->
- <field name="description">...</field>
-
- <!-- [Optional] Boolean that indicates if the amount should be considered as included in price. False by default.
- E.g. Suppose v = 132 and a tax amount of 20.
- If price_include = False, the computed amount will be 132 * 0.2 = 26.4.
- If price_include = True, the computed amount will be 132 - (132 / 1.2) = 132 - 110 = 22. -->
- <field name="price_include" eval="..."/>
-
- <!-- [Optional] Boolean to set to include the amount to the base. False by default.
- If True, the subsequent taxes will be computed based on the base tax amount plus the amount of this tax.
- E.g. suppose v = 100, t1, a tax of 10% and another tax t2 with 20%.
- If t1 doesn't affects the base,
- t1 amount = 100 * 0.1 = 10 and t2 amount = 100 * 0.2 = 20.
- If t1 affects the base,
- t1 amount = 100 * 0.1 = 10 and t2 amount = 110 * 0.2 = 22. -->
- <field name="include_base_amount" eval="..."/>
-
- <!-- [Optional] Boolean false by default.
- If set, the amount computed by this tax will be assigned to the same analytic account as the invoice line (if any). -->
- <field name="analytic" eval="..."/>
-
- <!-- [Optional] Specify some tags.
- These tags must have 'taxes' as applicability.
- See the previous section for more details. -->
- <field name="tag_ids" eval="...">
-
- <!-- [Optional] Define a tax group used to display the sums of taxes in the invoices. -->
- <field name="tax_group_id" ref="..."/>
-
- <!-- [Optional] Define the tax exigibility either based on invoice ('on_invoice' value) or
- either based on payment using the 'on_payment' key.
- The default value is 'on_invoice'. -->
- <field name="tax_exigibility">...</field>
-
- <!-- [Optional] Define a cash basis account in case of tax exigibility 'on_payment'. -->
- <field name="cash_basis_account" red="..."/>
- </record>
-
-An example found in the ``l10n_pl`` module:
-
-.. code-block:: xml
-
- <record id="vp_leas_sale" model="account.tax.template">
- <field name="chart_template_id" ref="pl_chart_template"/>
- <field name="name">VAT - leasing pojazdu(sale)</field>
- <field name="description">VLP</field>
- <field name="amount">1.00</field>
- <field name="sequence" eval="1"/>
- <field name="amount_type">group</field>
- <field name="type_tax_use">sale</field>
- <field name="children_tax_ids" eval="[(6, 0, [ref('vp_leas_sale_1'), ref('vp_leas_sale_2')])]"/>
- <field name="tag_ids" eval="[(6,0,[ref('l10n_pl.tag_pl_21')])]"/>
- <field name="tax_group_id" ref="tax_group_vat_23"/>
- </record>
-
-
-Adding a new fiscal position to my Chart of Accounts
-####################################################
-
-.. note::
- If you need more information about what is a fiscal position and how it works in Odoo, please refer to `How to adapt taxes to my customer status or localization <https://www.odoo.com/documentation/user/online/accounting/others/taxes/application.html>`_.
-
-To create a new fiscal position, simply use the ``account.fiscal.position.template`` model:
-
-.. code-block:: xml
-
- <record id="..." model="account.fiscal.position.template">
- <!-- [Required] Specify the name to display for this fiscal position. -->
- <field name="name">...</field>
-
- <!-- [Required] Set the CoA owning this fiscal position. -->
- <field name="chart_template_id" ref="..."/>
-
- <!-- [Optional] Add some additional notes. -->
- <field name="note">...</field>
- </record>
-
-Adding the properties to my Chart of Accounts
-#############################################
-
-When the whole accounts are generated, you have the possibility to override the newly generated chart of accounts by adding some properties that correspond to default accounts used in certain situations.
-This must be done after the creation of accounts before each one must be linked to the chart of accounts.
-
-.. code-block:: xml
-
- <?xml version="1.0" encoding="utf-8"?>
- <odoo>
- <record id="l10n_xx_chart_template" model="account.chart.template">
-
- <!-- Define receivable/payable accounts. -->
- <field name="property_account_receivable_id" ref="..."/>
- <field name="property_account_payable_id" ref="..."/>
-
- <!-- Define categories of expense/income account. -->
- <field name="property_account_expense_categ_id" ref="..."/>
- <field name="property_account_income_categ_id" ref="..."/>
-
- <!-- Define input/output accounts for stock valuation. -->
- <field name="property_stock_account_input_categ_id" ref="..."/>
- <field name="property_stock_account_output_categ_id" ref="..."/>
-
- <!-- Define an account template for stock valuation. -->
- <field name="property_stock_valuation_account_id" ref="..."/>
-
- <!-- Define loss/gain exchange rate accounts. -->
- <field name="expense_currency_exchange_account_id" ref="..."/>
- <field name="income_currency_exchange_account_id" ref="..."/>
-
- <!-- Define a transfer account. -->
- <field name="transfer_account_id" ref="..."/>
- </record>
- </odoo>
-
-For example, let's come back to the Belgium PCMN. This chart of accounts is override in this way to add some properties.
-
-.. code-block:: xml
-
- <record id="l10nbe_chart_template" model="account.chart.template">
- <field name="property_account_receivable_id" ref="a4000"/>
- <field name="property_account_payable_id" ref="a440"/>
- <field name="property_account_expense_categ_id" ref="a600"/>
- <field name="property_account_income_categ_id" ref="a7010"/>
- <field name="expense_currency_exchange_account_id" ref="a654"/>
- <field name="income_currency_exchange_account_id" ref="a754"/>
- <field name="transfer_account_id" ref="trans"/>
- </record>
-
-How to create a new bank operation model?
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-.. note::
- How a bank operation model works exactly in Odoo? See `Configure model of entries <https://www.odoo.com/documentation/user/online/accounting/bank/reconciliation/configure.html>`_.
-
-Since ``V10``, a new feature is available in the bank statement reconciliation widget: the bank operation model.
-This allows the user to pre-fill some accounting entries with a single click.
-The creation of an ``account.reconcile.model.template`` record is quite easy:
-
-.. code-block:: xml
-
- <record id="..." model="account.reconcile.model.template">
- <!-- [Required] Specify the name to display. -->
- <field name="name">...</field>
-
- <!-- [Required] Set the CoA owning this. -->
- <field name="chart_template_id" ref="..."/>
-
- <!-- [Optional] Set a sequence number defining the order in which it will be displayed.
- By default, the sequence is 10. -->
- <field name="sequence" eval="..."/>
-
- <!-- [Optional] Define an account. -->
- <field name="account_id" ref="..."/>
-
- <!-- [Optional] Define a label to be added to the journal item. -->
- <field name="label">...</field>
-
- <!-- [Optional] Define the type of amount_type, either 'fixed' or 'percentage'.
- The last one is the default value. -->
- <field name="amount_type">...</field>
-
- <!-- [Optional] Define the balance amount on which this model will be applied to (100 by default).
- Fixed amount will count as a debit if it is negative, as a credit if it is positive. -->
- <field name="amount">...</field>
-
- <!-- [Optional] Define eventually a tax. -->
- <field name="tax_id" ref="..."/>
-
- <!-- [Optional] The sames fields are available twice.
- To enable a second journal line, you can set this field to true and
- fill the fields accordingly. -->
- <field name="has_second_line" eval="..."/>
- <field name="second_account_id" ref="..."/>
- <field name="second_label">...</field>
- <field name="second_amount_type">...</field>
- <field name="second_amount">...</field>
- <field name="second_tax_id" ref="..."/>
- </record>
-
-How to create a new dynamic report?
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-If you need to add some reports on your localization, you need to create a new module named **l10n_xx_reports**.
-Furthermore, this additional module must be present in the ``enterprise`` repository and must have at least two dependencies,
-one to bring all the stuff for your localization module and one more, ``account_reports``, to design dynamic reports.
-
-.. code-block:: py
-
- 'depends': ['l10n_xx', 'account_reports'],
-
-Once it's done, you can start the creation of your report statements. The documentation is available in the following `slides <https://www.odoo.com/slides/slide/how-to-create-custom-accounting-report-415>`_.
diff --git a/doc/webservices/odoo.rst b/doc/webservices/odoo.rst
deleted file mode 100644
index cdbbd036e46..00000000000
--- a/doc/webservices/odoo.rst
+++ /dev/null
@@ -1,1337 +0,0 @@
-:banner: banners/web_service_api.jpg
-:types: api
-
-
-:code-column:
-
-============
-External API
-============
-
-Odoo is usually extended internally via modules, but many of its features and
-all of its data are also available from the outside for external analysis or
-integration with various tools. Part of the :ref:`reference/orm/model` API is
-easily available over XML-RPC_ and accessible from a variety of languages.
-
-.. Odoo XML-RPC idiosyncracies:
- * uses multiple endpoint and a nested call syntax instead of a
- "hierarchical" server structure (e.g. ``odoo.res.partner.read()``)
- * uses its own own manual auth system instead of basic auth or sessions
- (basic is directly supported the Python and Ruby stdlibs as well as
- ws-xmlrpc, not sure about ripcord)
- * own auth is inconvenient as (uid, password) have to be explicitly passed
- into every call. Session would allow db to be stored as well
- These issues are especially visible in Java, somewhat less so in PHP
-
-Connection
-==========
-
-.. kinda gross because it duplicates existing bits
-
-.. only:: html
-
- .. rst-class:: setupcode hidden
-
- .. code-block:: python3
-
- import xmlrpc.client
- info = xmlrpc.client.ServerProxy('https://demo.odoo.com/start').start()
- url, db, username, password = \
- info['host'], info['database'], info['user'], info['password']
- common = xmlrpc.client.ServerProxy('{}/xmlrpc/2/common'.format(url))
- uid = common.authenticate(db, username, password, {})
- models = xmlrpc.client.ServerProxy('{}/xmlrpc/2/object'.format(url))
-
- .. code-block:: ruby
-
- require "xmlrpc/client"
- info = XMLRPC::Client.new2('https://demo.odoo.com/start').call('start')
- url, db, username, password = \
- info['host'], info['database'], info['user'], info['password']
- common = XMLRPC::Client.new2("#{url}/xmlrpc/2/common")
- uid = common.call('authenticate', db, username, password, {})
- models = XMLRPC::Client.new2("#{url}/xmlrpc/2/object").proxy
-
- .. code-block:: php
-
- require_once('ripcord.php');
- $info = ripcord::client('https://demo.odoo.com/start')->start();
- list($url, $db, $username, $password) =
- array($info['host'], $info['database'], $info['user'], $info['password']);
- $common = ripcord::client("$url/xmlrpc/2/common");
- $uid = $common->authenticate($db, $username, $password, array());
- $models = ripcord::client("$url/xmlrpc/2/object");
-
- .. code-block:: java
-
- final XmlRpcClient client = new XmlRpcClient();
- final XmlRpcClientConfigImpl start_config = new XmlRpcClientConfigImpl();
- start_config.setServerURL(new URL("https://demo.odoo.com/start"));
- final Map<String, String> info = (Map<String, String>)client.execute(
- start_config, "start", emptyList());
-
- final String url = info.get("host"),
- db = info.get("database"),
- username = info.get("user"),
- password = info.get("password");
-
- final XmlRpcClientConfigImpl common_config = new XmlRpcClientConfigImpl();
- common_config.setServerURL(new URL(String.format("%s/xmlrpc/2/common", url)));
-
- int uid = (int)client.execute(
- common_config, "authenticate", Arrays.asList(
- db, username, password, emptyMap()));
-
- final XmlRpcClient models = new XmlRpcClient() {{
- setConfig(new XmlRpcClientConfigImpl() {{
- setServerURL(new URL(String.format("%s/xmlrpc/2/object", url)));
- }});
- }};
-
-Configuration
--------------
-
-If you already have an Odoo server installed, you can just use its
-parameters
-
-.. warning::
-
- For Odoo Online instances (<domain>.odoo.com), users are created without a
- *local* password (as a person you are logged in via the Odoo Online
- authentication system, not by the instance itself). To use XML-RPC on Odoo
- Online instances, you will need to set a password on the user account you
- want to use:
-
- * Log in your instance with an administrator account
- * Go to :menuselection:`Settings --> Users --> Users`
- * Click on the user you want to use for XML-RPC access
- * Click the :guilabel:`Change Password` button
- * Set a :guilabel:`New Password` value then click
- :guilabel:`Change Password`.
-
- The *server url* is the instance's domain (e.g.
- *https://mycompany.odoo.com*), the *database name* is the name of the
- instance (e.g. *mycompany*). The *username* is the configured user's login
- as shown by the *Change Password* screen.
-
-.. rst-class:: setup doc-aside
-
-.. switcher::
-
- .. code-block:: python3
-
- url = <insert server URL>
- db = <insert database name>
- username = 'admin'
- password = <insert password for your admin user (default: admin)>
-
- .. code-block:: ruby
-
- url = <insert server URL>
- db = <insert database name>
- username = "admin"
- password = <insert password for your admin user (default: admin)>
-
- .. code-block:: php
-
- $url = <insert server URL>;
- $db = <insert database name>;
- $username = "admin";
- $password = <insert password for your admin user (default: admin)>;
-
- .. code-block:: java
-
- final String url = <insert server URL>,
- db = <insert database name>,
- username = "admin",
- password = <insert password for your admin user (default: admin)>;
-
-API Keys
-''''''''
-
-.. versionadded:: 14.0
-
-Odoo has support for **api keys** and (depending on modules or settings) may
-**require** these keys to perform webservice operations.
-
-The way to use API Keys in your scripts is to simply replace your **password**
-by the key. The login remains in-use. You should store the API Key as carefully
-as the password as they essentially provide the same access to your user
-account (although they can not be used to log-in via the interface).
-
-In order to add a key to your account, simply go to your
-:guilabel:`Preferences` (or :guilabel:`My Profile`):
-
-.. figure:: images/preferences.png
- :align: center
-
-then open the :guilabel:`Account Security` tab, and click
-:guilabel:`New API Key`:
-
-.. figure:: images/account-security.png
- :align: center
-
-Input a description for the key, **this description should be as clear and
-complete as possible**: it is the only way you will have to identify your keys
-later and know whether you should remove them or keep them around.
-
-Click :guilabel:`Generate Key`, then copy the key provided. **Store this key
-carefully**: it is equivalent to your password, and just like your password
-the system will not be able to retrieve or show the key again later on. If you lose
-this key, you will have to create a new one (and probably delete the one you
-lost).
-
-Once you have keys configured on your account, they will appear above the
-:guilabel:`New API Key` button, and you will be able to delete them:
-
-.. figure:: images/delete-key.png
- :align: center
-
-**A deleted API key can not be undeleted or re-set**. You will have to generate
-a new key and update all the places where you used the old one.
-
-demo
-''''
-
-To make exploration simpler, you can also ask https://demo.odoo.com for a test
-database:
-
-.. rst-class:: setup doc-aside
-
-.. switcher::
-
- .. code-block:: python3
-
- import xmlrpc.client
- info = xmlrpc.client.ServerProxy('https://demo.odoo.com/start').start()
- url, db, username, password = \
- info['host'], info['database'], info['user'], info['password']
-
- .. code-block:: ruby
-
- require "xmlrpc/client"
- info = XMLRPC::Client.new2('https://demo.odoo.com/start').call('start')
- url, db, username, password = \
- info['host'], info['database'], info['user'], info['password']
-
- .. case:: PHP
-
- .. code-block:: php
-
- require_once('ripcord.php');
- $info = ripcord::client('https://demo.odoo.com/start')->start();
- list($url, $db, $username, $password) =
- array($info['host'], $info['database'], $info['user'], $info['password']);
-
- .. note::
-
- These examples use the `Ripcord <https://code.google.com/p/ripcord/>`_
- library, which provides a simple XML-RPC API. Ripcord requires that
- `XML-RPC support be enabled
- <https://php.net/manual/en/xmlrpc.installation.php>`_ in your PHP
- installation.
-
- Since calls are performed over
- `HTTPS <https://en.wikipedia.org/wiki/HTTP_Secure>`_, it also requires that
- the `OpenSSL extension
- <https://php.net/manual/en/openssl.installation.php>`_ be enabled.
-
- .. case:: Java
-
- .. code-block:: java
-
- final XmlRpcClient client = new XmlRpcClient();
-
- final XmlRpcClientConfigImpl start_config = new XmlRpcClientConfigImpl();
- start_config.setServerURL(new URL("https://demo.odoo.com/start"));
- final Map<String, String> info = (Map<String, String>)client.execute(
- start_config, "start", emptyList());
-
- final String url = info.get("host"),
- db = info.get("database"),
- username = info.get("user"),
- password = info.get("password");
-
- .. note::
-
- These examples use the `Apache XML-RPC library
- <https://ws.apache.org/xmlrpc/>`_
-
- The examples do not include imports as these imports couldn't be
- pasted in the code.
-
-Logging in
-----------
-
-Odoo requires users of the API to be authenticated before they can query most
-data.
-
-The ``xmlrpc/2/common`` endpoint provides meta-calls which don't require
-authentication, such as the authentication itself or fetching version
-information. To verify if the connection information is correct before trying
-to authenticate, the simplest call is to ask for the server's version. The
-authentication itself is done through the ``authenticate`` function and
-returns a user identifier (``uid``) used in authenticated calls instead of
-the login.
-
-.. rst-class:: setup doc-aside
-
-.. switcher::
-
- .. code-block:: python3
-
- common = xmlrpc.client.ServerProxy('{}/xmlrpc/2/common'.format(url))
- common.version()
-
- .. code-block:: ruby
-
- common = XMLRPC::Client.new2("#{url}/xmlrpc/2/common")
- common.call('version')
-
- .. code-block:: php
-
- $common = ripcord::client("$url/xmlrpc/2/common");
- $common->version();
-
- .. code-block:: java
-
- final XmlRpcClientConfigImpl common_config = new XmlRpcClientConfigImpl();
- common_config.setServerURL(
- new URL(String.format("%s/xmlrpc/2/common", url)));
- client.execute(common_config, "version", emptyList());
-
-.. rst-class:: doc-aside
-
-.. code-block:: json
-
- {
- "server_version": "13.0",
- "server_version_info": [13, 0, 0, "final", 0],
- "server_serie": "13.0",
- "protocol_version": 1,
- }
-
-.. rst-class:: setup doc-aside
-
-.. switcher::
-
- .. code-block:: python3
-
- uid = common.authenticate(db, username, password, {})
-
- .. code-block:: ruby
-
- uid = common.call('authenticate', db, username, password, {})
-
- .. code-block:: php
-
- $uid = $common->authenticate($db, $username, $password, array());
-
- .. code-block:: java
-
- int uid = (int)client.execute(
- common_config, "authenticate", asList(
- db, username, password, emptyMap()));
-
-.. _webservices/odoo/calling_methods:
-
-Calling methods
-===============
-
-The second endpoint is ``xmlrpc/2/object``, is used to call methods of odoo
-models via the ``execute_kw`` RPC function.
-
-Each call to ``execute_kw`` takes the following parameters:
-
-* the database to use, a string
-* the user id (retrieved through ``authenticate``), an integer
-* the user's password, a string
-* the model name, a string
-* the method name, a string
-* an array/list of parameters passed by position
-* a mapping/dict of parameters to pass by keyword (optional)
-
-.. container:: doc-aside
-
- For instance to see if we can read the ``res.partner`` model we can call
- ``check_access_rights`` with ``operation`` passed by position and
- ``raise_exception`` passed by keyword (in order to get a true/false result
- rather than true/error):
-
- .. rst-class:: setup
-
- .. switcher::
-
- .. code-block:: python3
-
- models = xmlrpc.client.ServerProxy('{}/xmlrpc/2/object'.format(url))
- models.execute_kw(db, uid, password,
- 'res.partner', 'check_access_rights',
- ['read'], {'raise_exception': False})
-
- .. code-block:: ruby
-
- models = XMLRPC::Client.new2("#{url}/xmlrpc/2/object").proxy
- models.execute_kw(db, uid, password,
- 'res.partner', 'check_access_rights',
- ['read'], {raise_exception: false})
-
- .. code-block:: php
-
- $models = ripcord::client("$url/xmlrpc/2/object");
- $models->execute_kw($db, $uid, $password,
- 'res.partner', 'check_access_rights',
- array('read'), array('raise_exception' => false));
-
- .. code-block:: java
-
- final XmlRpcClient models = new XmlRpcClient() {{
- setConfig(new XmlRpcClientConfigImpl() {{
- setServerURL(new URL(String.format("%s/xmlrpc/2/object", url)));
- }});
- }};
- models.execute("execute_kw", asList(
- db, uid, password,
- "res.partner", "check_access_rights",
- asList("read"),
- new HashMap() {{ put("raise_exception", false); }}
- ));
-
- .. code-block:: json
-
- true
-
- .. todo:: this should be runnable and checked
-
-List records
-------------
-
-Records can be listed and filtered via :meth:`~odoo.models.Model.search`.
-
-:meth:`~odoo.models.Model.search` takes a mandatory
-:ref:`domain <reference/orm/domains>` filter (possibly empty), and returns the
-database identifiers of all records matching the filter. To list customer
-companies for instance:
-
-.. container:: doc-aside
-
- .. switcher::
-
- .. code-block:: python3
-
- models.execute_kw(db, uid, password,
- 'res.partner', 'search',
- [[['is_company', '=', True]]])
-
- .. code-block:: ruby
-
- models.execute_kw(db, uid, password,
- 'res.partner', 'search',
- [[['is_company', '=', true]]])
-
- .. code-block:: php
-
- $models->execute_kw($db, $uid, $password,
- 'res.partner', 'search', array(
- array(array('is_company', '=', true))));
-
- .. code-block:: java
-
- asList((Object[])models.execute("execute_kw", asList(
- db, uid, password,
- "res.partner", "search",
- asList(asList(
- asList("is_company", "=", true)))
- )));
-
- .. code-block:: json
-
- [7, 18, 12, 14, 17, 19, 8, 31, 26, 16, 13, 20, 30, 22, 29, 15, 23, 28, 74]
-
-Pagination
-''''''''''
-
-By default a search will return the ids of all records matching the
-condition, which may be a huge number. ``offset`` and ``limit`` parameters are
-available to only retrieve a subset of all matched records.
-
-.. container:: doc-aside
-
- .. switcher::
-
- .. code-block:: python3
-
- models.execute_kw(db, uid, password,
- 'res.partner', 'search',
- [[['is_company', '=', True]]],
- {'offset': 10, 'limit': 5})
-
- .. code-block:: ruby
-
- models.execute_kw(db, uid, password,
- 'res.partner', 'search',
- [[['is_company', '=', true]]],
- {offset: 10, limit: 5})
-
- .. code-block:: php
-
- $models->execute_kw($db, $uid, $password,
- 'res.partner', 'search',
- array(array(array('is_company', '=', true))),
- array('offset'=>10, 'limit'=>5));
-
- .. code-block:: java
-
- asList((Object[])models.execute("execute_kw", asList(
- db, uid, password,
- "res.partner", "search",
- asList(asList(
- asList("is_company", "=", true))),
- new HashMap() {{ put("offset", 10); put("limit", 5); }}
- )));
-
- .. code-block:: json
-
- [13, 20, 30, 22, 29]
-
-Count records
--------------
-
-Rather than retrieve a possibly gigantic list of records and count them,
-:meth:`~odoo.models.Model.search_count` can be used to retrieve
-only the number of records matching the query. It takes the same
-:ref:`domain <reference/orm/domains>` filter as
-:meth:`~odoo.models.Model.search` and no other parameter.
-
-.. container:: doc-aside
-
- .. switcher::
-
- .. code-block:: python3
-
- models.execute_kw(db, uid, password,
- 'res.partner', 'search_count',
- [[['is_company', '=', True]]])
-
- .. code-block:: ruby
-
- models.execute_kw(db, uid, password,
- 'res.partner', 'search_count',
- [[['is_company', '=', true]]])
-
- .. code-block:: php
-
- $models->execute_kw($db, $uid, $password,
- 'res.partner', 'search_count',
- array(array(array('is_company', '=', true))));
-
- .. code-block:: java
-
- (Integer)models.execute("execute_kw", asList(
- db, uid, password,
- "res.partner", "search_count",
- asList(asList(
- asList("is_company", "=", true)))
- ));
-
- .. code-block:: json
-
- 19
-
-.. warning::
-
- calling ``search`` then ``search_count`` (or the other way around) may not
- yield coherent results if other users are using the server: stored data
- could have changed between the calls
-
-Read records
-------------
-
-Record data is accessible via the :meth:`~odoo.models.Model.read` method,
-which takes a list of ids (as returned by
-:meth:`~odoo.models.Model.search`) and optionally a list of fields to
-fetch. By default, it will fetch all the fields the current user can read,
-which tends to be a huge amount.
-
-.. container:: doc-aside
-
- .. switcher::
-
- .. code-block:: python3
-
- ids = models.execute_kw(db, uid, password,
- 'res.partner', 'search',
- [[['is_company', '=', True]]],
- {'limit': 1})
- [record] = models.execute_kw(db, uid, password,
- 'res.partner', 'read', [ids])
- # count the number of fields fetched by default
- len(record)
-
- .. code-block:: ruby
-
- ids = models.execute_kw(db, uid, password,
- 'res.partner', 'search',
- [[['is_company', '=', true]]],
- {limit: 1})
- record = models.execute_kw(db, uid, password,
- 'res.partner', 'read', [ids]).first
- # count the number of fields fetched by default
- record.length
-
- .. code-block:: php
-
- $ids = $models->execute_kw($db, $uid, $password,
- 'res.partner', 'search',
- array(array(array('is_company', '=', true))),
- array('limit'=>1));
- $records = $models->execute_kw($db, $uid, $password,
- 'res.partner', 'read', array($ids));
- // count the number of fields fetched by default
- count($records[0]);
-
- .. code-block:: java
-
- final List ids = asList((Object[])models.execute(
- "execute_kw", asList(
- db, uid, password,
- "res.partner", "search",
- asList(asList(
- asList("is_company", "=", true))),
- new HashMap() {{ put("limit", 1); }})));
- final Map record = (Map)((Object[])models.execute(
- "execute_kw", asList(
- db, uid, password,
- "res.partner", "read",
- asList(ids)
- )
- ))[0];
- // count the number of fields fetched by default
- record.size();
-
- .. code-block:: json
-
- 121
-
-Conversedly, picking only three fields deemed interesting.
-
-.. container:: doc-aside
-
- .. switcher::
-
- .. code-block:: python3
-
- models.execute_kw(db, uid, password,
- 'res.partner', 'read',
- [ids], {'fields': ['name', 'country_id', 'comment']})
-
- .. code-block:: ruby
-
- models.execute_kw(db, uid, password,
- 'res.partner', 'read',
- [ids], {fields: %w(name country_id comment)})
-
- .. code-block:: php
-
- $models->execute_kw($db, $uid, $password,
- 'res.partner', 'read',
- array($ids),
- array('fields'=>array('name', 'country_id', 'comment')));
-
- .. code-block:: java
-
- asList((Object[])models.execute("execute_kw", asList(
- db, uid, password,
- "res.partner", "read",
- asList(ids),
- new HashMap() {{
- put("fields", asList("name", "country_id", "comment"));
- }}
- )));
-
- .. code-block:: json
-
- [{"comment": false, "country_id": [21, "Belgium"], "id": 7, "name": "Agrolait"}]
-
-.. note:: even if the ``id`` field is not requested, it is always returned
-
-Listing record fields
----------------------
-
-:meth:`~odoo.models.Model.fields_get` can be used to inspect
-a model's fields and check which ones seem to be of interest.
-
-Because it returns a large amount of meta-information (it is also used by client
-programs) it should be filtered before printing, the most interesting items
-for a human user are ``string`` (the field's label), ``help`` (a help text if
-available) and ``type`` (to know which values to expect, or to send when
-updating a record):
-
-.. container:: doc-aside
-
- .. switcher::
-
- .. code-block:: python3
-
- models.execute_kw(
- db, uid, password, 'res.partner', 'fields_get',
- [], {'attributes': ['string', 'help', 'type']})
-
- .. code-block:: ruby
-
- models.execute_kw(
- db, uid, password, 'res.partner', 'fields_get',
- [], {attributes: %w(string help type)})
-
- .. code-block:: php
-
- $models->execute_kw($db, $uid, $password,
- 'res.partner', 'fields_get',
- array(), array('attributes' => array('string', 'help', 'type')));
-
- .. code-block:: java
-
- (Map<String, Map<String, Object>>)models.execute("execute_kw", asList(
- db, uid, password,
- "res.partner", "fields_get",
- emptyList(),
- new HashMap() {{
- put("attributes", asList("string", "help", "type"));
- }}
- ));
-
- .. code-block:: json
-
- {
- "ean13": {
- "type": "char",
- "help": "BarCode",
- "string": "EAN13"
- },
- "property_account_position_id": {
- "type": "many2one",
- "help": "The fiscal position will determine taxes and accounts used for the partner.",
- "string": "Fiscal Position"
- },
- "signup_valid": {
- "type": "boolean",
- "help": "",
- "string": "Signup Token is Valid"
- },
- "date_localization": {
- "type": "date",
- "help": "",
- "string": "Geo Localization Date"
- },
- "ref_company_ids": {
- "type": "one2many",
- "help": "",
- "string": "Companies that refers to partner"
- },
- "sale_order_count": {
- "type": "integer",
- "help": "",
- "string": "# of Sales Order"
- },
- "purchase_order_count": {
- "type": "integer",
- "help": "",
- "string": "# of Purchase Order"
- },
-
-Search and read
----------------
-
-Because it is a very common task, Odoo provides a
-:meth:`~odoo.models.Model.search_read` shortcut which as its name suggests is
-equivalent to a :meth:`~odoo.models.Model.search` followed by a
-:meth:`~odoo.models.Model.read`, but avoids having to perform two requests
-and keep ids around.
-
-Its arguments are similar to :meth:`~odoo.models.Model.search`'s, but it
-can also take a list of ``fields`` (like :meth:`~odoo.models.Model.read`,
-if that list is not provided it will fetch all fields of matched records):
-
-.. container:: doc-aside
-
- .. switcher::
-
- .. code-block:: python3
-
- models.execute_kw(db, uid, password,
- 'res.partner', 'search_read',
- [[['is_company', '=', True]]],
- {'fields': ['name', 'country_id', 'comment'], 'limit': 5})
-
- .. code-block:: ruby
-
- models.execute_kw(db, uid, password,
- 'res.partner', 'search_read',
- [[['is_company', '=', true]]],
- {fields: %w(name country_id comment), limit: 5})
-
- .. code-block:: php
-
- $models->execute_kw($db, $uid, $password,
- 'res.partner', 'search_read',
- array(array(array('is_company', '=', true))),
- array('fields'=>array('name', 'country_id', 'comment'), 'limit'=>5));
-
- .. code-block:: java
-
- asList((Object[])models.execute("execute_kw", asList(
- db, uid, password,
- "res.partner", "search_read",
- asList(asList(
- asList("is_company", "=", true))),
- new HashMap() {{
- put("fields", asList("name", "country_id", "comment"));
- put("limit", 5);
- }}
- )));
-
- .. code-block:: json
-
- [
- {
- "comment": false,
- "country_id": [ 21, "Belgium" ],
- "id": 7,
- "name": "Agrolait"
- },
- {
- "comment": false,
- "country_id": [ 76, "France" ],
- "id": 18,
- "name": "Axelor"
- },
- {
- "comment": false,
- "country_id": [ 233, "United Kingdom" ],
- "id": 12,
- "name": "Bank Wealthy and sons"
- },
- {
- "comment": false,
- "country_id": [ 105, "India" ],
- "id": 14,
- "name": "Best Designers"
- },
- {
- "comment": false,
- "country_id": [ 76, "France" ],
- "id": 17,
- "name": "Camptocamp"
- }
- ]
-
-
-Create records
---------------
-
-Records of a model are created using :meth:`~odoo.models.Model.create`. The
-method will create a single record and return its database identifier.
-
-:meth:`~odoo.models.Model.create` takes a mapping of fields to values, used
-to initialize the record. For any field which has a default value and is not
-set through the mapping argument, the default value will be used.
-
-.. container:: doc-aside
-
- .. switcher::
-
- .. code-block:: python3
-
- id = models.execute_kw(db, uid, password, 'res.partner', 'create', [{
- 'name': "New Partner",
- }])
-
- .. code-block:: ruby
-
- id = models.execute_kw(db, uid, password, 'res.partner', 'create', [{
- name: "New Partner",
- }])
-
- .. code-block:: php
-
- $id = $models->execute_kw($db, $uid, $password,
- 'res.partner', 'create',
- array(array('name'=>"New Partner")));
-
- .. code-block:: java
-
- final Integer id = (Integer)models.execute("execute_kw", asList(
- db, uid, password,
- "res.partner", "create",
- asList(new HashMap() {{ put("name", "New Partner"); }})
- ));
-
- .. code-block:: json
-
- 78
-
-.. warning::
-
- while most value types are what would be expected (integer for
- :class:`~odoo.fields.Integer`, string for :class:`~odoo.fields.Char`
- or :class:`~odoo.fields.Text`),
-
- * :class:`~odoo.fields.Date`, :class:`~odoo.fields.Datetime` and
- :class:`~odoo.fields.Binary` fields use string values
- * :class:`~odoo.fields.One2many` and :class:`~odoo.fields.Many2many`
- use a special command protocol detailed in :meth:`the documentation to
- the write method <odoo.models.Model.write>`.
-
-Update records
---------------
-
-Records can be updated using :meth:`~odoo.models.Model.write`, it takes
-a list of records to update and a mapping of updated fields to values similar
-to :meth:`~odoo.models.Model.create`.
-
-Multiple records can be updated simultanously, but they will all get the same
-values for the fields being set. It is not currently possible to perform
-"computed" updates (where the value being set depends on an existing value of
-a record).
-
-.. container:: doc-aside
-
- .. switcher::
-
- .. code-block:: python3
-
- models.execute_kw(db, uid, password, 'res.partner', 'write', [[id], {
- 'name': "Newer partner"
- }])
- # get record name after having changed it
- models.execute_kw(db, uid, password, 'res.partner', 'name_get', [[id]])
-
- .. code-block:: ruby
-
- models.execute_kw(db, uid, password, 'res.partner', 'write', [[id], {
- name: "Newer partner"
- }])
- # get record name after having changed it
- models.execute_kw(db, uid, password, 'res.partner', 'name_get', [[id]])
-
- .. code-block:: php
-
- $models->execute_kw($db, $uid, $password, 'res.partner', 'write',
- array(array($id), array('name'=>"Newer partner")));
- // get record name after having changed it
- $models->execute_kw($db, $uid, $password,
- 'res.partner', 'name_get', array(array($id)));
-
- .. code-block:: java
-
- models.execute("execute_kw", asList(
- db, uid, password,
- "res.partner", "write",
- asList(
- asList(id),
- new HashMap() {{ put("name", "Newer Partner"); }}
- )
- ));
- // get record name after having changed it
- asList((Object[])models.execute("execute_kw", asList(
- db, uid, password,
- "res.partner", "name_get",
- asList(asList(id))
- )));
-
- .. code-block:: json
-
- [[78, "Newer partner"]]
-
-Delete records
---------------
-
-Records can be deleted in bulk by providing their ids to
-:meth:`~odoo.models.Model.unlink`.
-
-.. container:: doc-aside
-
- .. switcher::
-
- .. code-block:: python3
-
- models.execute_kw(db, uid, password, 'res.partner', 'unlink', [[id]])
- # check if the deleted record is still in the database
- models.execute_kw(db, uid, password,
- 'res.partner', 'search', [[['id', '=', id]]])
-
- .. code-block:: ruby
-
- models.execute_kw(db, uid, password, 'res.partner', 'unlink', [[id]])
- # check if the deleted record is still in the database
- models.execute_kw(db, uid, password,
- 'res.partner', 'search', [[['id', '=', id]]])
-
- .. code-block:: php
-
- $models->execute_kw($db, $uid, $password,
- 'res.partner', 'unlink',
- array(array($id)));
- // check if the deleted record is still in the database
- $models->execute_kw($db, $uid, $password,
- 'res.partner', 'search',
- array(array(array('id', '=', $id))));
-
- .. code-block:: java
-
- models.execute("execute_kw", asList(
- db, uid, password,
- "res.partner", "unlink",
- asList(asList(id))));
- // check if the deleted record is still in the database
- asList((Object[])models.execute("execute_kw", asList(
- db, uid, password,
- "res.partner", "search",
- asList(asList(asList("id", "=", 78)))
- )));
-
- .. code-block:: json
-
- []
-
-Inspection and introspection
-----------------------------
-
-.. todo:: ``get_external_id`` is kinda crap and may not return an id: it just
- gets a random existing xid but won't generate one if there is no
- xid currently associated with the record. And operating with xids
- isn't exactly fun in RPC.
-
-While we previously used :meth:`~odoo.models.Model.fields_get` to query a
-model and have been using an arbitrary model from the start, Odoo stores
-most model metadata inside a few meta-models which allow both querying the
-system and altering models and fields (with some limitations) on the fly over
-XML-RPC.
-
-.. _reference/webservice/inspection/models:
-
-``ir.model``
-''''''''''''
-
-Provides information about Odoo models via its various fields
-
-``name``
- a human-readable description of the model
-``model``
- the name of each model in the system
-``state``
- whether the model was generated in Python code (``base``) or by creating
- an ``ir.model`` record (``manual``)
-``field_id``
- list of the model's fields through a :class:`~odoo.fields.One2many` to
- :ref:`reference/webservice/inspection/fields`
-``view_ids``
- :class:`~odoo.fields.One2many` to the :ref:`reference/views` defined
- for the model
-``access_ids``
- :class:`~odoo.fields.One2many` relation to the
- :ref:`reference/security/acl` set on the model
-
-``ir.model`` can be used to
-
-* query the system for installed models (as a precondition to operations
- on the model or to explore the system's content)
-* get information about a specific model (generally by listing the fields
- associated with it)
-* create new models dynamically over RPC
-
-.. warning::
-
- * "custom" model names must start with ``x_``
- * the ``state`` must be provided and ``manual``, otherwise the model will
- not be loaded
- * it is not possible to add new *methods* to a custom model, only fields
-
-.. container:: doc-aside
-
- a custom model will initially contain only the "built-in" fields available
- on all models:
-
- .. switcher::
-
- .. code-block:: python3
-
- models.execute_kw(db, uid, password, 'ir.model', 'create', [{
- 'name': "Custom Model",
- 'model': "x_custom_model",
- 'state': 'manual',
- }])
- models.execute_kw(
- db, uid, password, 'x_custom_model', 'fields_get',
- [], {'attributes': ['string', 'help', 'type']})
-
- .. code-block:: php
-
- $models->execute_kw(
- $db, $uid, $password,
- 'ir.model', 'create', array(array(
- 'name' => "Custom Model",
- 'model' => 'x_custom_model',
- 'state' => 'manual'
- ))
- );
- $models->execute_kw(
- $db, $uid, $password,
- 'x_custom_model', 'fields_get',
- array(),
- array('attributes' => array('string', 'help', 'type'))
- );
-
- .. code-block:: ruby
-
- models.execute_kw(
- db, uid, password,
- 'ir.model', 'create', [{
- name: "Custom Model",
- model: 'x_custom_model',
- state: 'manual'
- }])
- fields = models.execute_kw(
- db, uid, password, 'x_custom_model', 'fields_get',
- [], {attributes: %w(string help type)})
-
- .. code-block:: java
-
- models.execute(
- "execute_kw", asList(
- db, uid, password,
- "ir.model", "create",
- asList(new HashMap<String, Object>() {{
- put("name", "Custom Model");
- put("model", "x_custom_model");
- put("state", "manual");
- }})
- ));
- final Object fields = models.execute(
- "execute_kw", asList(
- db, uid, password,
- "x_custom_model", "fields_get",
- emptyList(),
- new HashMap<String, Object> () {{
- put("attributes", asList(
- "string",
- "help",
- "type"));
- }}
- ));
-
- .. code-block:: json
-
- {
- "create_uid": {
- "type": "many2one",
- "string": "Created by"
- },
- "create_date": {
- "type": "datetime",
- "string": "Created on"
- },
- "__last_update": {
- "type": "datetime",
- "string": "Last Modified on"
- },
- "write_uid": {
- "type": "many2one",
- "string": "Last Updated by"
- },
- "write_date": {
- "type": "datetime",
- "string": "Last Updated on"
- },
- "display_name": {
- "type": "char",
- "string": "Display Name"
- },
- "id": {
- "type": "integer",
- "string": "Id"
- }
- }
-
-.. _reference/webservice/inspection/fields:
-
-``ir.model.fields``
-'''''''''''''''''''
-
-Provides information about the fields of Odoo models and allows adding
-custom fields without using Python code
-
-``model_id``
- :class:`~odoo.fields.Many2one` to
- :ref:`reference/webservice/inspection/models` to which the field belongs
-``name``
- the field's technical name (used in ``read`` or ``write``)
-``field_description``
- the field's user-readable label (e.g. ``string`` in ``fields_get``)
-``ttype``
- the :ref:`type <reference/orm/fields>` of field to create
-``state``
- whether the field was created via Python code (``base``) or via
- ``ir.model.fields`` (``manual``)
-``required``, ``readonly``, ``translate``
- enables the corresponding flag on the field
-``groups``
- :ref:`field-level access control <reference/security/fields>`, a
- :class:`~odoo.fields.Many2many` to ``res.groups``
-``selection``, ``size``, ``on_delete``, ``relation``, ``relation_field``, ``domain``
- type-specific properties and customizations, see :ref:`the fields
- documentation <reference/orm/fields>` for details
-
-Like custom models, only new fields created with ``state="manual"`` are
-activated as actual fields on the model.
-
-.. warning:: computed fields can not be added via ``ir.model.fields``, some
- field meta-information (defaults, onchange) can not be set either
-
-.. todo:: maybe new-API fields could store constant ``default`` in a new
- column, maybe JSON-encoded?
-
-.. container:: doc-aside
-
- .. switcher::
-
- .. code-block:: python3
-
- id = models.execute_kw(db, uid, password, 'ir.model', 'create', [{
- 'name': "Custom Model",
- 'model': "x_custom",
- 'state': 'manual',
- }])
- models.execute_kw(
- db, uid, password,
- 'ir.model.fields', 'create', [{
- 'model_id': id,
- 'name': 'x_name',
- 'ttype': 'char',
- 'state': 'manual',
- 'required': True,
- }])
- record_id = models.execute_kw(
- db, uid, password,
- 'x_custom', 'create', [{
- 'x_name': "test record",
- }])
- models.execute_kw(db, uid, password, 'x_custom', 'read', [[record_id]])
-
- .. code-block:: php
-
- $id = $models->execute_kw(
- $db, $uid, $password,
- 'ir.model', 'create', array(array(
- 'name' => "Custom Model",
- 'model' => 'x_custom',
- 'state' => 'manual'
- ))
- );
- $models->execute_kw(
- $db, $uid, $password,
- 'ir.model.fields', 'create', array(array(
- 'model_id' => $id,
- 'name' => 'x_name',
- 'ttype' => 'char',
- 'state' => 'manual',
- 'required' => true
- ))
- );
- $record_id = $models->execute_kw(
- $db, $uid, $password,
- 'x_custom', 'create', array(array(
- 'x_name' => "test record"
- ))
- );
- $models->execute_kw(
- $db, $uid, $password,
- 'x_custom', 'read',
- array(array($record_id)));
-
- .. code-block:: ruby
-
- id = models.execute_kw(
- db, uid, password,
- 'ir.model', 'create', [{
- name: "Custom Model",
- model: "x_custom",
- state: 'manual'
- }])
- models.execute_kw(
- db, uid, password,
- 'ir.model.fields', 'create', [{
- model_id: id,
- name: "x_name",
- ttype: "char",
- state: "manual",
- required: true
- }])
- record_id = models.execute_kw(
- db, uid, password,
- 'x_custom', 'create', [{
- x_name: "test record"
- }])
- models.execute_kw(
- db, uid, password,
- 'x_custom', 'read', [[record_id]])
-
- .. code-block:: java
-
- final Integer id = (Integer)models.execute(
- "execute_kw", asList(
- db, uid, password,
- "ir.model", "create",
- asList(new HashMap<String, Object>() {{
- put("name", "Custom Model");
- put("model", "x_custom");
- put("state", "manual");
- }})
- ));
- models.execute(
- "execute_kw", asList(
- db, uid, password,
- "ir.model.fields", "create",
- asList(new HashMap<String, Object>() {{
- put("model_id", id);
- put("name", "x_name");
- put("ttype", "char");
- put("state", "manual");
- put("required", true);
- }})
- ));
- final Integer record_id = (Integer)models.execute(
- "execute_kw", asList(
- db, uid, password,
- "x_custom", "create",
- asList(new HashMap<String, Object>() {{
- put("x_name", "test record");
- }})
- ));
-
- client.execute(
- "execute_kw", asList(
- db, uid, password,
- "x_custom", "read",
- asList(asList(record_id))
- ));
-
- .. code-block:: json
-
- [
- {
- "create_uid": [1, "Administrator"],
- "x_name": "test record",
- "__last_update": "2014-11-12 16:32:13",
- "write_uid": [1, "Administrator"],
- "write_date": "2014-11-12 16:32:13",
- "create_date": "2014-11-12 16:32:13",
- "id": 1,
- "display_name": "test record"
- }
- ]
-
-
-.. _PostgreSQL: https://www.postgresql.org
-.. _XML-RPC: https://en.wikipedia.org/wiki/XML-RPC
-.. _base64: https://en.wikipedia.org/wiki/Base64
diff --git a/doc/webservices/upgrade.rst b/doc/webservices/upgrade.rst
deleted file mode 100644
index 13f7e8472ce..00000000000
--- a/doc/webservices/upgrade.rst
+++ /dev/null
@@ -1,659 +0,0 @@
-:banner: banners/upgrade_api.jpg
-:types: api
-
-
-:code-column:
-
-.. _reference/upgrade-api:
-
-================
-Database Upgrade
-================
-
-Introduction
-~~~~~~~~~~~~
-
-This document describes the API used to upgrade an Odoo database to a
-higher version.
-
-It allows a database to be upgraded without ressorting to the html form at
-https://upgrade.odoo.com
-Although the database will follow the same process described on that form.
-
-
-The required steps are:
-
-* :ref:`creating a request <upgrade-api-create-method>`
-* :ref:`uploading a database dump <upgrade-api-upload-method>`
-* :ref:`running the upgrade process <upgrade-api-process-method>`
-* :ref:`obtaining the status of the database request <upgrade-api-status-method>`
-* :ref:`downloading the upgraded database dump <upgrade-api-download-method>`
-
-The methods
-~~~~~~~~~~~
-
-.. _upgrade-api-create-method:
-
-Creating a database upgrade request
-===================================
-
-This action creates a database request with the following information:
-
-* your contract reference
-* your email address
-* the target version (the Odoo version you want to upgrade to)
-* the purpose of your request (test or production)
-* the database dump name (required but purely informative)
-* optionally the server timezone (for Odoo source version < 6.1)
-
-The ``create`` method
----------------------
-
-.. py:function:: https://upgrade.odoo.com/database/v1/create
-
- Creates a database upgrade request
-
- :param str contract: (required) your enterprise contract reference
- :param str email: (required) your email address
- :param str target: (required) the Odoo version you want to upgrade to. Valid choices: 11.0, 12.0, 13.0
- :param str aim: (required) the purpose of your upgrade database request. Valid choices: test, production.
- :param str filename: (required) a purely informative name for you database dump file
- :param str timezone: (optional) the timezone used by your server. Only for Odoo source version < 6.1
- :return: request result
- :rtype: JSON dictionary
-
-The *create* method returns a JSON dictionary containing the following keys:
-
-.. _upgrade-api-json-failure:
-
-``failures``
-''''''''''''
-
-The list of errors.
-
-A list of dictionaries, each dictionary giving information about one particular
-error. Each dictionary can contain various keys depending of the type of error
-but you will always get the ``reason`` and the ``message`` keys:
-
-* ``reason``: the error type
-* ``message``: a human friendly message
-
-Some possible keys:
-
-* ``code``: a faulty value
-* ``value``: a faulty value
-* ``expected``: a list of valid values
-
-See a sample output aside.
-
-.. rst-class:: setup doc-aside
-
-.. switcher::
-
- .. code-block:: json
-
- {
- "failures": [
- {
- "expected": [
- "11.0",
- "12.0",
- "13.0",
- ],
- "message": "Invalid value \"5.0\"",
- "reason": "TARGET:INVALID",
- "value": "5.0"
- },
- {
- "code": "M123456-abcxyz",
- "message": "Can not find contract M123456-abcxyz",
- "reason": "CONTRACT:NOT_FOUND"
- }
- ]
- }
-
-
-``request``
-'''''''''''
-
-If the *create* method is successful, the value associated to the *request* key
-will be a dictionary containing various information about the created request:
-
-The most important keys are:
-
-* ``id``: the request id
-* ``key``: your private key for this request
-
-These 2 values will be requested by the other methods (upload, process and status)
-
-The other keys will be explained in the section describing the :ref:`status method <upgrade-api-status-method>`.
-
-
-Sample script
-'''''''''''''
-
-Here are 2 examples of database upgrade request creation using:
-
-* one in the python programming language using the requests library
-* one in the bash programming language using `curl <https://curl.haxx.se>`_ (tool
- for transfering data using http) and `jq <https://stedolan.github.io/jq>`_ (JSON processor):
-
-.. rst-class:: setup doc-aside
-
-.. switcher::
-
- .. code-block:: python
-
- import requests
-
- CREATE_URL = "https://upgrade.odoo.com/database/v1/create"
- CONTRACT = "M123456-abcdef"
- AIM = "test"
- TARGET = "12.0"
- EMAIL = "john.doe@example.com"
- FILENAME = "db_name.dump"
-
- fields = dict([
- ('aim', AIM),
- ('email', EMAIL),
- ('filename', DB_SOURCE),
- ('contract', CONTRACT),
- ('target', TARGET),
- ])
-
- r = requests.get(CREATE_URL, data=fields)
- print(r.text)
-
- .. code-block:: bash
-
- CONTRACT=M123456-abcdef
- AIM=test
- TARGET=12.0
- EMAIL=john.doe@example.com
- FILENAME=db_name.dump
- CREATE_URL="https://upgrade.odoo.com/database/v1/create"
- URL_PARAMS="contract=${CONTRACT}&aim=${AIM}&target=${TARGET}&email=${EMAIL}&filename=${FILENAME}"
- curl -sS "${CREATE_URL}?${URL_PARAMS}" > create_result.json
-
- # check for failures
- failures=$(cat create_result.json | jq -r '.failures[]')
- if [ "$failures" != "" ]; then
- echo $failures | jq -r '.'
- exit 1
- fi
-
-.. _upgrade-api-upload-method:
-
-Uploading your database dump
-============================
-
-There are 2 methods to upload your database dump:
-
-* the ``upload`` method using the HTTPS protocol
-* the ``request_sftp_access`` method using the SFTP protocol
-
-The ``upload`` method
----------------------
-
-It's the most simple and most straightforward way of uploading your database dump.
-It uses the HTTPS protocol.
-
-.. py:function:: https://upgrade.odoo.com/database/v1/upload
-
- Uploads a database dump
-
- :param str key: (required) your private key
- :param str request: (required) your request id
- :return: request result
- :rtype: JSON dictionary
-
-The request id and the private key are obtained using the :ref:`create method
-<upgrade-api-create-method>`
-
-The result is a JSON dictionary containing the list of ``failures``, which
-should be empty if everything went fine.
-
-.. rst-class:: setup doc-aside
-
-.. switcher::
-
- .. code-block:: python
-
- import requests
-
- UPLOAD_URL = "https://upgrade.odoo.com/database/v1/upload"
- DUMPFILE = "/tmp/dump.sql"
-
- fields = dict([
- ('request', '10534'),
- ('key', 'Aw7pItGVKFuZ_FOR3U8VFQ=='),
- ])
- headers = {"Content-Type": "application/octet-stream"}
-
- with open(DUMPFILE, 'rb') as f:
- requests.post(UPLOAD_URL, data=f, params=fields, headers=headers)
-
- .. code-block:: bash
-
- UPLOAD_URL="https://upgrade.odoo.com/database/v1/upload"
- DUMPFILE="openchs.70.cdump"
- KEY="Aw7pItGVKFuZ_FOR3U8VFQ=="
- REQUEST_ID="10534"
- URL_PARAMS="key=${KEY}&request=${REQUEST_ID}"
- HEADER="Content-Type: application/octet-stream"
- curl -H $HEADER --data-binary "@${DUMPFILE}" "${UPLOAD_URL}?${URL_PARAMS}"
-
-.. _upgrade-api-request-sftp-access-method:
-
-The ``request_sftp_access`` method
-----------------------------------
-
-This method is recommanded for big database dumps.
-It uses the SFTP protocol and supports resuming.
-
-It will create a temporary SFTP server where you can connect to and allow you
-to upload your database dump using an SFTP client.
-
-.. py:function:: https://upgrade.odoo.com/database/v1/request_sftp_access
-
- Creates an SFTP server
-
- :param str key: (required) your private key
- :param str request: (required) your request id
- :param str ssh_keys: (required) the path to a file listing the ssh public keys you'd like to use
- :return: request result
- :rtype: JSON dictionary
-
-The request id and the private key are obtained using the :ref:`create method
-<upgrade-api-create-method>`
-
-The file listing your ssh public keys should be roughly similar to a standard ``authorized_keys`` file.
-This file should only contains public keys, blank lines or comments (lines starting with the ``#`` character)
-
-Your database upgrade request should be in the ``draft`` state.
-
-The ``request_sftp_access`` method returns a JSON dictionary containing the following keys:
-
-
-.. rst-class:: setup doc-aside
-
-.. switcher::
-
- .. code-block:: python
-
- import requests
-
- UPLOAD_URL = "https://upgrade.odoo.com/database/v1/request_sftp_access"
- SSH_KEY = "$HOME/.ssh/id_rsa.pub"
- SSH_KEY_CONTENT = open(SSH_KEY,'r').read()
-
- fields = dict([
- ('request', '10534'),
- ('key', 'Aw7pItGVKFuZ_FOR3U8VFQ=='),
- ('ssh_keys', SSH_KEY_CONTENT)
- ])
-
- r = requests.post(UPLOAD_URL, params=fields)
- print(r.text)
-
- .. code-block:: bash
-
- REQUEST_SFTP_ACCESS_URL="https://upgrade.odoo.com/database/v1/request_sftp_access"
- SSH_KEYS=/path/to/your/authorized_keys
- KEY="Aw7pItGVKFuZ_FOR3U8VFQ=="
- REQUEST_ID="10534"
- URL_PARAMS="key=${KEY}&request=${REQUEST_ID}"
-
- curl -sS "${REQUEST_SFTP_ACCESS_URL}?${URL_PARAMS}" -F ssh_keys=@${SSH_KEYS} > request_sftp_result.json
-
- # check for failures
- failures=$(cat request_sftp_result.json | jq -r '.failures[]')
- if [ "$failures" != "" ]; then
- echo $failures | jq -r '.'
- exit 1
- fi
-
-
-``failures``
-''''''''''''
-
-The list of errors. See :ref:`failures <upgrade-api-json-failure>` for an
-explanation about the JSON dictionary returned in case of failure.
-
-``request``
-'''''''''''
-
-If the call is successful, the value associated to the *request* key
-will be a dictionary containing your SFTP connexion parameters:
-
-* ``hostname``: the host address to connect to
-* ``sftp_port``: the port to connect to
-* ``sftp_user``: the SFTP user to use for connecting
-* ``shared_file``: the filename you need to use (identical to the ``filename`` value you have used when creating the request in the :ref:`create method <upgrade-api-create-method>`.)
-* ``request_id``: the related upgrade request id (only informative, ,not required for the connection)
-* ``sample_command``: a sample command using the 'sftp' client
-
-You should normally be able to connect using the sample command as is.
-
-You will only have access to the ``shared_file``. No other files will be
-accessible and you will not be able to create new files in your shared
-environment on the SFTP server.
-
-Using the 'sftp' client
-+++++++++++++++++++++++
-
-Once you have successfully connected using your SFTP client, you can upload
-your database dump. Here is a sample session using the 'sftp' client:
-
-::
-
- $ sftp -P 2200 user_10534@upgrade.odoo.com
- Connected to upgrade.odoo.com.
- sftp> put /path/to/openchs.70.cdump openchs.70.cdump
- Uploading /path/to/openchs.70.cdump to /openchs.70.cdump
- sftp> ls -l openchs.70.cdump
- -rw-rw-rw- 0 0 0 849920 Aug 30 15:58 openchs.70.cdump
-
-If your connection is interrupted, you can continue your file transfer using
-the ``-a`` command line switch:
-
-.. code-block:: text
-
- sftp> put -a /path/to/openchs.70.cdump openchs.70.cdump
- Resuming upload of /path/to/openchs.70.cdump to /openchs.70.cdump
-
-If you don't want to manually type the command and need to automate your
-database upgrade using a script, you can use a batch file or pipe your commands to 'sftp':
-
-::
-
- echo "put /path/to/openchs.70.cdump openchs.70.cdump" | sftp -b - -P 2200 user_10534@upgrade.odoo.com
-
-The ``-b`` parameter takes a filename. If the filename is ``-``, it reads the commands from standard input.
-
-
-.. _upgrade-api-process-method:
-
-Asking to process your request
-==============================
-
-This action ask the Upgrade Platform to process your database dump.
-
-The ``process`` method
-----------------------
-
-.. py:function:: https://upgrade.odoo.com/database/v1/process
-
- Process a database dump
-
- :param str key: (required) your private key
- :param str request: (required) your request id
- :return: request result
- :rtype: JSON dictionary
-
-The request id and the private key are obtained using the :ref:`create method
-<upgrade-api-create-method>`
-
-The result is a JSON dictionary containing the list of ``failures``, which
-should be empty if everything went fine.
-
-.. rst-class:: setup doc-aside
-
-.. switcher::
-
- .. code-block:: python
-
- import requests
-
- PROCESS_URL = "https://upgrade.odoo.com/database/v1/process"
-
- fields = dict([
- ('request', '10534'),
- ('key', 'Aw7pItGVKFuZ_FOR3U8VFQ=='),
- ])
-
- r = requests.get(PROCESS_URL, data=fields)
- print(r.text)
-
- .. code-block:: bash
-
- PROCESS_URL="https://upgrade.odoo.com/database/v1/process"
- KEY="Aw7pItGVKFuZ_FOR3U8VFQ=="
- REQUEST_ID="10534"
- URL_PARAMS="key=${KEY}&request=${REQUEST_ID}"
- curl -sS "${PROCESS_URL}?${URL_PARAMS}"
-
-.. _upgrade-api-skip-tests:
-
-
-Asking to skip the tests
-=========================
-
-This action asks the Upgrade Platform to skip the tests for your request.
-If you don't want Odoo to test and validate the migration, you can bypass the testing stage and directly get the migrated dump.
-
-The ``skip_test`` method
-------------------------
-
-.. py:function:: https://upgrade.odoo.com/database/v1/skip_test
-
- Skip the tests, deliver the upgraded dump, and set the state to 'delivered'
-
- :param str key: (required) your private key
- :param str request: (required) your request id
- :return: request result
- :rtype: JSON dictionary
-
-The request id and the private key are obtained using the :ref:`create method
-<upgrade-api-create-method>`
-
-The result is a JSON dictionary containing the list of ``failures``, which
-should be empty if everything went fine.
-
-.. rst-class:: setup doc-aside
-
-.. switcher::
-
- .. code-block:: python
-
- import requests
-
- PROCESS_URL = "https://upgrade.odoo.com/database/v1/skip_test"
-
- fields = dict([
- ('request', '10534'),
- ('key', 'Aw7pItGVKFuZ_FOR3U8VFQ=='),
- ])
-
- r = requests.get(PROCESS_URL, data=fields)
- print(r.text)
-
- .. code-block:: bash
-
- PROCESS_URL="https://upgrade.odoo.com/database/v1/skip_test"
- KEY="Aw7pItGVKFuZ_FOR3U8VFQ=="
- REQUEST_ID="10534"
- URL_PARAMS="key=${KEY}&request=${REQUEST_ID}"
- curl -sS "${PROCESS_URL}?${URL_PARAMS}"
-
-.. _upgrade-api-status-method:
-
-Obtaining your request status
-=============================
-
-This action ask the status of your database upgrade request.
-
-The ``status`` method
----------------------
-
-.. py:function:: https://upgrade.odoo.com/database/v1/status
-
- Ask the status of a database upgrade request
-
- :param str key: (required) your private key
- :param str request: (required) your request id
- :return: request result
- :rtype: JSON dictionary
-
-The request id and the private key are obtained using the :ref:`create method
-<upgrade-api-create-method>`
-
-The result is a JSON dictionary containing various information about your
-database upgrade request.
-
-.. rst-class:: setup doc-aside
-
-.. switcher::
-
- .. code-block:: python
-
- import requests
-
- PROCESS_URL = "https://upgrade.odoo.com/database/v1/status"
-
- fields = dict([
- ('request', '10534'),
- ('key', 'Aw7pItGVKFuZ_FOR3U8VFQ=='),
- ])
-
- r = requests.get(PROCESS_URL, data=fields)
- print(r.text)
-
- .. code-block:: bash
-
- STATUS_URL="https://upgrade.odoo.com/database/v1/status"
- KEY="Aw7pItGVKFuZ_FOR3U8VFQ=="
- REQUEST_ID="10534"
- URL_PARAMS="key=${KEY}&request=${REQUEST_ID}"
- curl -sS "${STATUS_URL}?${URL_PARAMS}"
-
-Sample output
--------------
-
-The ``request`` key contains various useful information about your request:
-
-``id``
- the request id
-``key``
- your private key
-``email``
- the email address you supplied when creating the request
-``target``
- the target Odoo version you supplied when creating the request
-``aim``
- the purpose (test, production) of your database upgrade request you supplied when creating the request
-``filename``
- the filename you supplied when creating the request
-``timezone``
- the timezone you supplied when creating the request
-``state``
- the state of your request
-``issue_stage``
- the stage of the issue we have create on Odoo main server
-``issue``
- the id of the issue we have create on Odoo main server
-``status_url``
- the URL to access your database upgrade request html page
-``notes_url``
- the URL to get the notes about your database upgrade
-``original_sql_url``
- the URL used to get your uploaded (not upgraded) database as an SQL stream
-``original_dump_url``
- the URL used to get your uploaded (not upgraded) database as an archive file
-``upgraded_sql_url``
- the URL used to get your upgraded database as an SQL stream
-``upgraded_dump_url``
- the URL used to get your upgraded database as an archive file
-``modules_url``
- the URL used to get your custom modules
-``filesize``
- the size of your uploaded database file
-``database_uuid``
- the Unique ID of your database
-``created_at``
- the date when you created the request
-``estimated_time``
- an estimation of the time it takes to upgrade your database
-``processed_at``
- time when your database upgrade was started
-``elapsed``
- the time it takes to upgrade your database
-``filestore``
- your attachments were converted to the filestore
-``customer_message``
- an important message related to your request
-``database_version``
- the guessed Odoo version of your uploaded (not upgraded) database
-``postgresql``
- the guessed Postgresql version of your uploaded (not upgraded) database
-``compressions``
- the compression methods used by your uploaded database
-
-.. rst-class:: setup doc-aside
-
-.. switcher::
-
- .. code-block:: json
-
- {
- "failures": [],
- "request": {
- "id": 10534,
- "key": "Aw7pItGVKFuZ_FOR3U8VFQ==",
- "email": "john.doe@example.com",
- "target": "12.0",
- "aim": "test",
- "filename": "db_name.dump",
- "timezone": null,
- "state": "draft",
- "issue_stage": "new",
- "issue": 648398,
- "status_url": "https://upgrade.odoo.com/database/eu1/10534/Aw7pItGVKFuZ_FOR3U8VFQ==/status",
- "notes_url": "https://upgrade.odoo.com/database/eu1/10534/Aw7pItGVKFuZ_FOR3U8VFQ==/upgraded/notes",
- "original_sql_url": "https://upgrade.odoo.com/database/eu1/10534/Aw7pItGVKFuZ_FOR3U8VFQ==/original/sql",
- "original_dump_url": "https://upgrade.odoo.com/database/eu1/10534/Aw7pItGVKFuZ_FOR3U8VFQ==/original/archive",
- "upgraded_sql_url": "https://upgrade.odoo.com/database/eu1/10534/Aw7pItGVKFuZ_FOR3U8VFQ==/upgraded/sql",
- "upgraded_dump_url": "https://upgrade.odoo.com/database/eu1/10534/Aw7pItGVKFuZ_FOR3U8VFQ==/upgraded/archive",
- "modules_url": "https://upgrade.odoo.com/database/eu1/10534/Aw7pItGVKFuZ_FOR3U8VFQ==/modules/archive",
- "filesize": "912.99 Kb",
- "database_uuid": null,
- "created_at": "2018-09-09 07:13:49",
- "estimated_time": null,
- "processed_at": null,
- "elapsed": "00:00",
- "filestore": false,
- "customer_message": null,
- "database_version": null,
- "postgresql": "9.4",
- "compressions": [
- "pgdmp_custom",
- "sql"
- ]
- }
- }
-
-.. _upgrade-api-download-method:
-
-Downloading your database dump
-==============================
-
-Beside downloading your migrated database using the URL provided by the
-:ref:`status method <upgrade-api-status-method>`, you can also use the SFTP
-protocol as described in the :ref:`request_sftp_access method
-<upgrade-api-request-sftp-access-method>`
-
-The diffence is that you'll only be able to download the migrated database. No
-uploading will be possible.
-
-Your database upgrade request should be in the ``done`` state.
-
-Once you have successfully connected using your SFTP client, you can download
-your database dump. Here is a sample session using the 'sftp' client:
-
-::
-
- $ sftp -P 2200 user_10534@upgrade.odoo.com
- Connected to upgrade.odoo.com.
- sftp> get upgraded_openchs.70.cdump /path/to/upgraded_openchs.70.cdump
- Downloading /upgraded_openchs.70.cdump to /path/to/upgraded_openchs.70.cdump
-