├── .eslintrc.json ├── .gitignore ├── .travis.yml ├── README.md ├── oca_dependencies.txt ├── requirements.txt ├── roadmap.md ├── scrummer ├── README.rst ├── __init__.py ├── __manifest__.py ├── controllers │ ├── __init__.py │ └── main.py ├── data │ └── project_task.xml ├── doc │ └── index.rst ├── models │ ├── __init__.py │ ├── account.py │ ├── base.py │ ├── mail_message.py │ ├── project_agile_board.py │ ├── project_agile_team.py │ ├── project_project.py │ ├── project_task.py │ ├── res_config_settings.py │ └── res_users.py ├── static │ ├── description │ │ ├── banner.png │ │ ├── changing_team.gif │ │ ├── icon.png │ │ ├── index.html │ │ ├── task_view.gif │ │ └── team_form.png │ ├── img │ │ ├── icon.png │ │ ├── icons │ │ │ ├── apk.png │ │ │ ├── archive.png │ │ │ ├── audio.png │ │ │ ├── css.png │ │ │ ├── doc.png │ │ │ ├── html.png │ │ │ ├── image.png │ │ │ ├── json.png │ │ │ ├── pdf.png │ │ │ ├── ppt.png │ │ │ ├── rar.png │ │ │ ├── sheet.png │ │ │ ├── text.png │ │ │ ├── unknown.png │ │ │ ├── video.png │ │ │ └── zip.png │ │ ├── logo-gray-flat.png │ │ ├── odoo_agile.svg │ │ ├── scrummer.svg │ │ └── unassigned.png │ └── src │ │ ├── css │ │ ├── compiled │ │ │ ├── ion.rangeSlider.css │ │ │ ├── ion.rangeSlider.skinFlat.css │ │ │ └── lity.css │ │ ├── custom-icons │ │ │ ├── moscow-could.svg │ │ │ ├── moscow-must.svg │ │ │ ├── moscow-should.svg │ │ │ └── moscow-would.svg │ │ ├── img │ │ │ └── sprite-skin-flat.png │ │ ├── materialNote.css │ │ ├── materialNote.css.map │ │ ├── materialdesignicons.css │ │ ├── materialdesignicons.css.map │ │ ├── materialize.css │ │ ├── materialize.css.map │ │ ├── scrummer.css │ │ └── scrummer.css.map │ │ ├── fonts │ │ ├── material-design-icons │ │ │ ├── LICENSE.txt │ │ │ ├── Material-Design-Icons.eot │ │ │ ├── Material-Design-Icons.svg │ │ │ ├── Material-Design-Icons.ttf │ │ │ ├── Material-Design-Icons.woff │ │ │ ├── Material-Design-Icons.woff2 │ │ │ ├── materialdesignicons-webfont.eot │ │ │ ├── materialdesignicons-webfont.svg │ │ │ ├── materialdesignicons-webfont.ttf │ │ │ ├── materialdesignicons-webfont.woff │ │ │ └── materialdesignicons-webfont.woff2 │ │ ├── material-icons │ │ │ └── material-icons.woff2 │ │ └── roboto │ │ │ ├── Roboto-Bold.eot │ │ │ ├── Roboto-Bold.ttf │ │ │ ├── Roboto-Bold.woff │ │ │ ├── Roboto-Bold.woff2 │ │ │ ├── Roboto-Light.eot │ │ │ ├── Roboto-Light.ttf │ │ │ ├── Roboto-Light.woff │ │ │ ├── Roboto-Light.woff2 │ │ │ ├── Roboto-Medium.eot │ │ │ ├── Roboto-Medium.ttf │ │ │ ├── Roboto-Medium.woff │ │ │ ├── Roboto-Medium.woff2 │ │ │ ├── Roboto-Regular.eot │ │ │ ├── Roboto-Regular.ttf │ │ │ ├── Roboto-Regular.woff │ │ │ ├── Roboto-Regular.woff2 │ │ │ ├── Roboto-Thin.eot │ │ │ ├── Roboto-Thin.ttf │ │ │ ├── Roboto-Thin.woff │ │ │ └── Roboto-Thin.woff2 │ │ ├── img │ │ ├── android-icon-144x144.png │ │ ├── android-icon-192x192.png │ │ ├── android-icon-36x36.png │ │ ├── android-icon-48x48.png │ │ ├── android-icon-72x72.png │ │ ├── android-icon-96x96.png │ │ ├── apple-icon-114x114.png │ │ ├── apple-icon-120x120.png │ │ ├── apple-icon-144x144.png │ │ ├── apple-icon-152x152.png │ │ ├── apple-icon-180x180.png │ │ ├── apple-icon-57x57.png │ │ ├── apple-icon-60x60.png │ │ ├── apple-icon-72x72.png │ │ ├── apple-icon-76x76.png │ │ ├── apple-icon-precomposed.png │ │ ├── apple-icon.png │ │ ├── favicon-16x16.png │ │ ├── favicon-32x32.png │ │ ├── favicon-96x96.png │ │ ├── favicon.ico │ │ ├── ms-icon-144x144.png │ │ ├── ms-icon-150x150.png │ │ ├── ms-icon-310x310.png │ │ └── ms-icon-70x70.png │ │ ├── js │ │ ├── app_cache.js │ │ ├── demo_data_generator.js │ │ ├── framework │ │ │ ├── config.js │ │ │ ├── core.js │ │ │ ├── data │ │ │ │ ├── data.js │ │ │ │ ├── data_service.js │ │ │ │ ├── data_service_factory.js │ │ │ │ ├── dataset.js │ │ │ │ └── dependency_cache.js │ │ │ ├── dialog.js │ │ │ ├── hash_service.js │ │ │ ├── helper_methods.js │ │ │ ├── mixins.js │ │ │ ├── storage_service.js │ │ │ ├── toast.js │ │ │ └── web_client.js │ │ ├── libs │ │ │ ├── .eslintrc.json │ │ │ ├── Color.js │ │ │ ├── Sortable.js │ │ │ ├── external │ │ │ │ ├── README-materialize-compatibility.txt │ │ │ │ ├── dropify.js │ │ │ │ ├── ion.rangeSlider.js │ │ │ │ ├── jquery-ui.js │ │ │ │ ├── jquery.expander.js │ │ │ │ ├── jquery.validate.js │ │ │ │ ├── lity.js │ │ │ │ ├── materialNote.js │ │ │ │ ├── materialize.js │ │ │ │ ├── moment.js │ │ │ │ └── waypoint.js │ │ │ ├── jquery-validate.js │ │ │ ├── materialNoteOverrides.js │ │ │ ├── my-jquery-extensions.js │ │ │ └── pluralize.js │ │ ├── main.js │ │ ├── views │ │ │ ├── backlog.js │ │ │ ├── kanban_table.js │ │ │ ├── page_manager.js │ │ │ ├── pages │ │ │ │ ├── board.js │ │ │ │ └── dashboard.js │ │ │ ├── task.js │ │ │ └── view_manager.js │ │ └── widgets │ │ │ ├── abstract_model_list.js │ │ │ ├── activity_stream.js │ │ │ ├── attachments.js │ │ │ ├── base_widget.js │ │ │ ├── board_chooser.js │ │ │ ├── header.js │ │ │ ├── layout.js │ │ │ ├── many2many_tags.js │ │ │ ├── many2one.js │ │ │ ├── menu.js │ │ │ ├── modal_widget.js │ │ │ ├── model_list.js │ │ │ ├── subheader.js │ │ │ ├── task_links.js │ │ │ └── task_widget.js │ │ ├── scss │ │ ├── components │ │ │ └── _materialize_overrides.scss │ │ ├── materialNote.scss │ │ ├── materialdesignicons.scss │ │ ├── materialdesignicons │ │ │ ├── _animated.scss │ │ │ ├── _core.scss │ │ │ ├── _extras.scss │ │ │ ├── _functions.scss │ │ │ ├── _icons.scss │ │ │ ├── _path.scss │ │ │ └── _variables.scss │ │ ├── materialize-components │ │ │ ├── _buttons.scss │ │ │ ├── _cards.scss │ │ │ ├── _carousel.scss │ │ │ ├── _chips.scss │ │ │ ├── _collapsible.scss │ │ │ ├── _color.scss │ │ │ ├── _dropdown.scss │ │ │ ├── _global.scss │ │ │ ├── _grid.scss │ │ │ ├── _icons-material-design.scss │ │ │ ├── _materialbox.scss │ │ │ ├── _mixins.scss │ │ │ ├── _modal.scss │ │ │ ├── _navbar.scss │ │ │ ├── _normalize.scss │ │ │ ├── _prefixer.scss │ │ │ ├── _preloader.scss │ │ │ ├── _roboto.scss │ │ │ ├── _sideNav.scss │ │ │ ├── _slider.scss │ │ │ ├── _table_of_contents.scss │ │ │ ├── _tabs.scss │ │ │ ├── _toast.scss │ │ │ ├── _tooltip.scss │ │ │ ├── _typography.scss │ │ │ ├── _variables.scss │ │ │ ├── _waves.scss │ │ │ ├── date_picker │ │ │ │ ├── _default.date.scss │ │ │ │ ├── _default.scss │ │ │ │ └── _default.time.scss │ │ │ └── forms │ │ │ │ ├── _checkboxes.scss │ │ │ │ ├── _file-input.scss │ │ │ │ ├── _forms.scss │ │ │ │ ├── _input-fields.scss │ │ │ │ ├── _radio-buttons.scss │ │ │ │ ├── _range.scss │ │ │ │ ├── _select.scss │ │ │ │ └── _switches.scss │ │ ├── materialize.scss │ │ └── scrummer.scss │ │ └── xml │ │ ├── aside.left.menu.xml │ │ ├── header.xml │ │ ├── layout.xml │ │ ├── page.board.xml │ │ ├── page.dashboard.xml │ │ ├── scrummer.activity_stream.xml │ │ ├── scrummer.board_chooser.xml │ │ ├── scrummer.project_item.xml │ │ ├── scrummer.task.links.xml │ │ ├── scrummer.task.xml │ │ ├── sub-header.xml │ │ ├── view-common.xml │ │ ├── view-manager.xml │ │ ├── view.backlog.xml │ │ ├── view.kanban_table.xml │ │ ├── view.task.xml │ │ ├── widget.attachments.xml │ │ ├── widget.many2one.xml │ │ └── widget.modal.xml └── views │ ├── index.xml │ ├── menu.xml │ ├── project_agile_team_view.xml │ ├── project_project_view.xml │ ├── project_task_priority_view.xml │ ├── project_task_type2_view.xml │ ├── project_task_view.xml │ ├── project_type_view.xml │ ├── res_config_settings_views.xml │ └── scrummer.xml ├── scrummer_git ├── README.rst ├── __init__.py ├── __manifest__.py ├── controllers │ ├── __init__.py │ └── main.py ├── doc │ └── index.rst ├── models │ ├── __init__.py │ └── project_task.py ├── static │ ├── description │ │ ├── banner.png │ │ ├── git_commit.gif │ │ ├── icon.png │ │ └── index.html │ └── src │ │ ├── js │ │ └── scrummer_git.js │ │ └── xml │ │ └── scrummer_git.xml └── views │ └── scrummer_git.xml ├── scrummer_kanban ├── README.rst ├── __init__.py ├── __manifest__.py ├── controllers │ ├── __init__.py │ └── main.py ├── doc │ └── index.rst ├── models │ ├── __init__.py │ ├── project.py │ └── project_agile_board.py ├── static │ ├── description │ │ ├── banner.png │ │ ├── create_task.gif │ │ ├── icon.png │ │ ├── index.html │ │ └── task_kanban_view.gif │ └── src │ │ ├── css │ │ ├── scrummer_kanban.css │ │ └── scrummer_kanban.css.map │ │ ├── js │ │ ├── views │ │ │ ├── kanban.js │ │ │ ├── kanban_board.js │ │ │ └── task.js │ │ └── widgets │ │ │ ├── menu.js │ │ │ ├── modal_widget.js │ │ │ └── task_widget.js │ │ ├── scss │ │ └── scrummer_kanban.scss │ │ └── xml │ │ ├── view.kanban.xml │ │ └── widget.modal.xml └── views │ └── scrummer_kanban.xml ├── scrummer_scrum ├── README.rst ├── __init__.py ├── __manifest__.py ├── controllers │ ├── __init__.py │ └── main.py ├── doc │ └── index.rst ├── models │ ├── __init__.py │ ├── project.py │ ├── project_agile_board.py │ ├── project_agile_scrum_sprint.py │ └── project_agile_team.py ├── static │ ├── description │ │ ├── active_sprint.gif │ │ ├── banner.png │ │ ├── create_sprint.gif │ │ ├── create_task.gif │ │ ├── icon.png │ │ └── index.html │ └── src │ │ ├── css │ │ ├── scrummer_scrum.css │ │ └── scrummer_scrum.css.map │ │ ├── js │ │ ├── views │ │ │ ├── active_sprint.js │ │ │ └── backlog.js │ │ └── widgets │ │ │ ├── menu.js │ │ │ └── task_widget.js │ │ ├── scss │ │ └── scrummer_scrum.scss │ │ └── xml │ │ ├── view.backlog.xml │ │ ├── view.sprint.xml │ │ └── view.task.xml └── views │ ├── project_agile_scrum_sprint_views.xml │ └── scrummer_scrum.xml ├── scrummer_timesheet_category ├── README.rst ├── __init__.py ├── __manifest__.py ├── controllers │ ├── __init__.py │ └── main.py ├── doc │ └── index.rst ├── models │ ├── __init__.py │ ├── account.py │ └── res_users.py ├── static │ ├── description │ │ ├── banner.png │ │ ├── icon.png │ │ ├── index.html │ │ └── timesheet_category.png │ └── src │ │ ├── js │ │ └── scrummer_timesheet_category.js │ │ └── xml │ │ └── scrummer_timesheet.xml └── views │ └── assets.xml ├── scrummer_workflow_security ├── README.rst ├── __init__.py ├── __manifest__.py ├── controllers │ ├── __init__.py │ └── main.py ├── doc │ └── index.rst ├── static │ ├── description │ │ ├── banner.png │ │ ├── icon.png │ │ └── index.html │ └── src │ │ └── js │ │ ├── kanban_table.js │ │ └── workflow_transition_widget.js └── views │ └── scrummer_workflow_security.xml ├── scrummer_workflow_transition_by_project ├── README.rst ├── __init__.py ├── __manifest__.py ├── controllers │ ├── __init__.py │ └── main.py ├── doc │ └── index.rst ├── static │ ├── description │ │ ├── banner.png │ │ ├── icon.png │ │ └── index.html │ └── src │ │ └── js │ │ ├── kanban_table.js │ │ └── workflow_transition_widget.js └── views │ └── scrummer_workflow_transition_by_project.xml └── scrummer_workflow_transitions_by_task_type ├── README.rst ├── __init__.py ├── __manifest__.py ├── controllers ├── __init__.py └── main.py ├── doc └── index.rst ├── static ├── description │ ├── banner.png │ ├── icon.png │ └── index.html └── src │ └── js │ ├── kanban_table.js │ └── workflow_transition_widget.js └── views └── scrummer_workflow_transitions_by_task_type.xml /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | 5 | # C extensions 6 | *.so 7 | 8 | # Distribution / packaging 9 | .Python 10 | env/ 11 | bin/ 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | eggs/ 16 | lib/ 17 | lib64/ 18 | parts/ 19 | sdist/ 20 | var/ 21 | *.egg-info/ 22 | .installed.cfg 23 | *.egg 24 | 25 | # Installer logs 26 | pip-log.txt 27 | pip-delete-this-directory.txt 28 | 29 | # Unit test / coverage reports 30 | htmlcov/ 31 | .tox/ 32 | .coverage 33 | .cache 34 | nosetests.xml 35 | coverage.xml 36 | 37 | # Translations 38 | *.mo 39 | 40 | # Pycharm 41 | .idea 42 | 43 | # Visual Studio cache/options directory 44 | .vs/ 45 | .vscode 46 | 47 | # Mr Developer 48 | .mr.developer.cfg 49 | .project 50 | .pydevproject 51 | 52 | # Rope 53 | .ropeproject 54 | 55 | # Sphinx documentation 56 | docs/_build/ 57 | 58 | # Backup files 59 | *~ 60 | *.swp 61 | 62 | # Sass 63 | */.sass-cache/ 64 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | 3 | python: 4 | - "3.5" 5 | 6 | sudo: false 7 | cache: pip 8 | 9 | git: 10 | depth: 5 11 | quiet: true 12 | 13 | addons: 14 | apt: 15 | packages: 16 | - expect-dev # provides unbuffer utility 17 | - python-lxml # because pip installation is slow 18 | 19 | env: 20 | global: 21 | - VERSION="11.0" TESTS="0" LINT_CHECK="0" PYLINT_ODOO_JSLINTRC=" " 22 | - WKHTMLTOPDF_VERSION="0.12.4" 23 | - SERVER_OPTIONS="--load=web,web_syncer" OPTIONS="--load=web,web_syncer" 24 | matrix: 25 | - LINT_CHECK="1" 26 | - TESTS="1" ODOO_REPO="OCA/OCB" 27 | - TESTS="1" ODOO_REPO="odoo/odoo" 28 | 29 | before_install: 30 | - "export DISPLAY=:99.0" 31 | - "sh -e /etc/init.d/xvfb start" 32 | 33 | install: 34 | - git clone --depth=1 https://github.com/OCA/maintainer-quality-tools.git ${HOME}/maintainer-quality-tools 35 | - export PATH=${HOME}/maintainer-quality-tools/travis:${PATH} 36 | - travis_install_nightly 37 | 38 | script: 39 | - travis_run_tests 40 | 41 | after_success: 42 | - travis_after_tests_success 43 | -------------------------------------------------------------------------------- /oca_dependencies.txt: -------------------------------------------------------------------------------- 1 | modoolar-project-agile https://github.com/modoolar/project-agile 2 | modoolar-project https://github.com/modoolar/project 3 | modoolar-web https://github.com/modoolar/web -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | cryptography 2 | jira==1.0.10 3 | textile==3.0.3 -------------------------------------------------------------------------------- /roadmap.md: -------------------------------------------------------------------------------- 1 | Roadmap 2 | 3 | * Add Scrum reports (ie. sprint burndown chart, team performance) - in progress 4 | * Model list refactoring 5 | * Backlog task item context menu extensions (Send to top, Send to bottom) 6 | * Add field widget for every data type 7 | * Inline task editing: edit task fields directly on the form instead of using edit modal screen. 8 | * Improve swimlane headers in active sprint - in progress 9 | * Implement basic security in odoo-agile based on Odoo ACL settings and business flow 10 | * Add Meeting management (reminders, calendars) 11 | * Add Release planning module 12 | * Extend filter in odoo-agile to be more Odoo like (smart search, filters, etc) 13 | * Add agile board configurator 14 | * UI/UX improvements 15 | * * Layout and UX improvements 16 | * * Upgrade Google Material CSS lib once released (http://materializecss.com/). 17 | * Integrations (Git, Bitbucket, Gitlab) 18 | * * Code repositories (Github, Gitlab, Bitbucket) 19 | * * * Create branches from within odoo-agile 20 | * * * Create pull requests from within odoo-agile 21 | * * * Extend existing webhooks to receive notifications regarding new branches and PRs 22 | * * * External repositories crawler to discover all remote branches and odoo modules and thus allow you to add more metadata to the tasks in Odoo 23 | * * JIRA 24 | * * * Import workflows from JIRA once JIRA fix their API bug 25 | 26 | This is not a final list, we will update it in time. If you are willing to participate in odoo-agile development, please consider following the proposed roadmap or get in touch with us to coordinate development efforts. -------------------------------------------------------------------------------- /scrummer/README.rst: -------------------------------------------------------------------------------- 1 | doc/index.rst -------------------------------------------------------------------------------- /scrummer/__init__.py: -------------------------------------------------------------------------------- 1 | from . import controllers 2 | from . import models 3 | -------------------------------------------------------------------------------- /scrummer/__manifest__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 - 2018 Modoolar 2 | # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl-3.0.en.html). 3 | { 4 | "name": "Scrummer", 5 | "summary": "Scrummer is frontend for project agile framework", 6 | "category": "Project", 7 | "version": "11.0.1.0.0", 8 | "license": "LGPL-3", 9 | "author": "Modoolar", 10 | "website": "https://www.modoolar.com/", 11 | "images": ["static/description/banner.png"], 12 | "depends": [ 13 | "project_agile", 14 | "web_syncer", 15 | ], 16 | 17 | "data": [ 18 | "views/project_project_view.xml", 19 | "views/project_type_view.xml", 20 | "views/project_task_view.xml", 21 | "views/project_task_type2_view.xml", 22 | "views/project_task_priority_view.xml", 23 | "views/project_agile_team_view.xml", 24 | "views/res_config_settings_views.xml", 25 | 26 | "views/scrummer.xml", 27 | "views/index.xml", 28 | 29 | "views/menu.xml", 30 | 31 | "data/project_task.xml", 32 | ], 33 | 34 | "demo": [ 35 | ], 36 | 37 | "qweb": ["static/src/xml/*.xml"], 38 | "application": True, 39 | "installable": True, 40 | } 41 | -------------------------------------------------------------------------------- /scrummer/controllers/__init__.py: -------------------------------------------------------------------------------- 1 | from . import main 2 | -------------------------------------------------------------------------------- /scrummer/models/__init__.py: -------------------------------------------------------------------------------- 1 | from . import base 2 | 3 | from . import project_agile_team 4 | from . import project_agile_board 5 | from . import project_project 6 | from . import project_task 7 | from . import mail_message 8 | from . import res_users 9 | from . import account 10 | from . import res_config_settings 11 | -------------------------------------------------------------------------------- /scrummer/models/account.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 - 2018 Modoolar 2 | # License LGPLv3.0 or later (https://www.gnu.org/licenses/lgpl-3.0.en.html). 3 | 4 | from odoo import models, fields 5 | 6 | 7 | class AccountAnalyticLine(models.Model): 8 | _inherit = 'account.analytic.line' 9 | 10 | name = fields.Char(scrummer=True) 11 | date = fields.Date(scrummer=True) 12 | amount = fields.Monetary(scrummer=True) 13 | unit_amount = fields.Float(scrummer=True) 14 | user_id = fields.Many2one(scrummer=True) 15 | -------------------------------------------------------------------------------- /scrummer/models/base.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 - 2018 Modoolar 2 | # License LGPLv3.0 or later (https://www.gnu.org/licenses/lgpl-3.0.en.html). 3 | 4 | from odoo import models, fields, api 5 | 6 | 7 | class Base(models.AbstractModel): 8 | _inherit = 'base' 9 | 10 | @api.model 11 | def _format_values(self, record, vals, update_related_fields=False): 12 | res = super(Base, self)._format_values( 13 | record, vals, update_related_fields 14 | ) 15 | 16 | for fn in list(res.keys()): 17 | if not record._fields[fn]._attrs.get('scrummer', False): 18 | del res[fn] 19 | return res 20 | 21 | 22 | class AgileSystemCodeItem(models.AbstractModel): 23 | _inherit = 'project.agile.code_item' 24 | 25 | name = fields.Char(scrummer=True) 26 | description = fields.Html(scrummer=True) 27 | system = fields.Boolean(scrummer=True) 28 | active = fields.Boolean(scrummer=True) 29 | sequence = fields.Integer(scrummer=True) 30 | scrummer_icon = fields.Char() 31 | scrummer_icon_color = fields.Char() 32 | -------------------------------------------------------------------------------- /scrummer/models/mail_message.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 - 2018 Modoolar 2 | # License LGPLv3.0 or later (https://www.gnu.org/licenses/lgpl-3.0.en.html). 3 | 4 | from odoo import models, fields, api 5 | 6 | 7 | class MailMessageSubtype(models.Model): 8 | _name = 'mail.message.subtype' 9 | _inherit = ['mail.message.subtype', 'project.agile.mixin.id_search'] 10 | 11 | name = fields.Char(scrummer=True) 12 | default = fields.Boolean(scrummer=True) 13 | sequence = fields.Integer(scrummer=True) 14 | 15 | 16 | class Message(models.Model): 17 | _inherit = "mail.message" 18 | 19 | author_last_update = fields.Datetime( 20 | related='create_uid.__last_update', 21 | scrummer=True 22 | ) 23 | 24 | @api.model 25 | def _message_read_dict_postprocess(self, messages, message_tree): 26 | ret = super(Message, self)._message_read_dict_postprocess( 27 | messages, message_tree 28 | ) 29 | 30 | if self.env.context.get("scrummer", False): 31 | for message_dict in messages: 32 | message = message_tree[message_dict.get('id')] 33 | message_dict.update({ 34 | 'author_last_update': message.author_last_update, 35 | 'write_date': message.write_date, 36 | }) 37 | return ret 38 | -------------------------------------------------------------------------------- /scrummer/models/project_agile_board.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 - 2018 Modoolar 2 | # License LGPLv3.0 or later (https://www.gnu.org/licenses/lgpl-3.0.en.html). 3 | 4 | from odoo import models, fields 5 | 6 | 7 | class Board(models.Model): 8 | _inherit = 'project.agile.board' 9 | 10 | name = fields.Char(scrummer=True) 11 | description = fields.Char(scrummer=True) 12 | type = fields.Selection(scrummer=True) 13 | project_ids = fields.Many2many( 14 | comodel_name="project.project", 15 | scrummer=True, 16 | ) 17 | column_ids = fields.One2many( 18 | comodel_name="project.agile.board.column", 19 | scrummer=True, 20 | ) 21 | unmapped_state_ids = fields.One2many( 22 | comodel_name='project.workflow.state', 23 | scrummer=True, 24 | ) 25 | unmapped_task_stage_ids = fields.One2many( 26 | comodel_name='project.task.type', 27 | scrummer=True, 28 | ) 29 | board_task_type_ids = fields.Many2many( 30 | comodel_name='project.task.type2', 31 | scrummer=True, 32 | ) 33 | backlog_task_type_ids = fields.Many2many( 34 | comodel_name='project.task.type2', 35 | scrummer=True, 36 | ) 37 | -------------------------------------------------------------------------------- /scrummer/models/project_agile_team.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 - 2018 Modoolar 2 | # License LGPLv3.0 or later (https://www.gnu.org/licenses/lgpl-3.0.en.html). 3 | 4 | from odoo import models, fields, api 5 | 6 | 7 | class AgileTeam(models.Model): 8 | _inherit = 'project.agile.team' 9 | 10 | name = fields.Char(scrummer=True) 11 | description = fields.Html(scrummer=True) 12 | type = fields.Selection(scrummer=True) 13 | email = fields.Char(scrummer=True) 14 | default_hrs = fields.Float(scrummer=True) 15 | member_ids = fields.Many2many( 16 | comodel_name='res.users', 17 | scrummer=True 18 | ) 19 | project_ids = fields.Many2many( 20 | comodel_name='project.project', 21 | scrummer=True 22 | ) 23 | product_owner_ids = fields.One2many( 24 | comodel_name='res.users', 25 | scrummer=True 26 | ) 27 | workflow_id = fields.Many2one( 28 | comodel_name='project.workflow', 29 | scrummer=True 30 | ) 31 | 32 | @api.multi 33 | def open_in_scrummer(self): 34 | self.ensure_one() 35 | return { 36 | 'type': 'ir.actions.act_url', 37 | 'target': 'self', 38 | 'url': "/scrummer/web" 39 | } 40 | -------------------------------------------------------------------------------- /scrummer/models/project_project.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 - 2018 Modoolar 2 | # License LGPLv3.0 or later (https://www.gnu.org/licenses/lgpl-3.0.en.html). 3 | 4 | from odoo import models, fields, api 5 | 6 | 7 | class ProjectType(models.Model): 8 | _inherit = "project.type" 9 | _implements_syncer = True 10 | 11 | task_type_ids = fields.Many2many( 12 | comodel_name='project.task.type2', 13 | scrummer=True 14 | ) 15 | 16 | 17 | class Project(models.Model): 18 | _inherit = 'project.project' 19 | 20 | image_key = fields.Char(scrummer=True) 21 | write_date = fields.Datetime(scrummer=True) 22 | todo_estimation = fields.Integer(scrummer=True) 23 | in_progress_estimation = fields.Integer(scrummer=True) 24 | done_estimation = fields.Integer(scrummer=True) 25 | default_task_type_id = fields.Many2one( 26 | comodel_name='project.task.type2', 27 | scrummer=True 28 | ) 29 | 30 | @api.multi 31 | def open_in_scrummer(self): 32 | self.ensure_one() 33 | url = "/scrummer/web#page=board&project=%s&view=%s" 34 | return { 35 | 'type': 'ir.actions.act_url', 36 | 'target': 'self', 37 | 'url': url % (self.id, self.agile_method) 38 | } 39 | 40 | 41 | class AnalyticAccount(models.Model): 42 | _inherit = 'account.analytic.account' 43 | 44 | name = fields.Char(scrummer=True) 45 | -------------------------------------------------------------------------------- /scrummer/models/res_config_settings.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 - 2018 Modoolar 2 | # License LGPLv3.0 or later (https://www.gnu.org/licenses/lgpl-3.0.en.html). 3 | 4 | 5 | from odoo import fields, models 6 | 7 | 8 | class ResConfigSettings(models.TransientModel): 9 | _inherit = 'res.config.settings' 10 | 11 | module_scrummer_scrum = fields.Boolean( 12 | string="Scrum" 13 | ) 14 | 15 | module_scrummer_kanban = fields.Boolean( 16 | string="Kanban" 17 | ) 18 | 19 | module_scrummer_git = fields.Boolean( 20 | string="Git" 21 | ) 22 | 23 | module_scrummer_timesheet_category = fields.Boolean( 24 | string="Timsheet Category" 25 | ) 26 | 27 | module_scrummer_workflow_security = fields.Boolean( 28 | string="Workflow Security" 29 | ) 30 | 31 | module_scrummer_workflow_transitions_by_task_type = fields.Boolean( 32 | string="Workflow Transition By Task Type" 33 | ) 34 | 35 | module_scrummer_workflow_transition_by_project = fields.Boolean( 36 | string="Workflow Transition By Project" 37 | ) 38 | -------------------------------------------------------------------------------- /scrummer/models/res_users.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 - 2018 Modoolar 2 | # License LGPLv3.0 or later (https://www.gnu.org/licenses/lgpl-3.0.en.html). 3 | 4 | from odoo import models, fields 5 | 6 | 7 | class Users(models.Model): 8 | _inherit = "res.users" 9 | 10 | name = fields.Char(scrummer=True) 11 | write_date = fields.Datetime(scrummer=True) 12 | partner_id = fields.Many2one( 13 | comodel_name='res.partner', 14 | scrummer=True 15 | ) 16 | team_ids = fields.Many2many( 17 | comodel_name='project.agile.team', 18 | scrummer=True, 19 | ) 20 | team_id = fields.Many2one( 21 | comodel_name="project.agile.team", 22 | scrummer=True, 23 | ) 24 | -------------------------------------------------------------------------------- /scrummer/static/description/banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer/static/description/banner.png -------------------------------------------------------------------------------- /scrummer/static/description/changing_team.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer/static/description/changing_team.gif -------------------------------------------------------------------------------- /scrummer/static/description/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer/static/description/icon.png -------------------------------------------------------------------------------- /scrummer/static/description/task_view.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer/static/description/task_view.gif -------------------------------------------------------------------------------- /scrummer/static/description/team_form.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer/static/description/team_form.png -------------------------------------------------------------------------------- /scrummer/static/img/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer/static/img/icon.png -------------------------------------------------------------------------------- /scrummer/static/img/icons/apk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer/static/img/icons/apk.png -------------------------------------------------------------------------------- /scrummer/static/img/icons/archive.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer/static/img/icons/archive.png -------------------------------------------------------------------------------- /scrummer/static/img/icons/audio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer/static/img/icons/audio.png -------------------------------------------------------------------------------- /scrummer/static/img/icons/css.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer/static/img/icons/css.png -------------------------------------------------------------------------------- /scrummer/static/img/icons/doc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer/static/img/icons/doc.png -------------------------------------------------------------------------------- /scrummer/static/img/icons/html.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer/static/img/icons/html.png -------------------------------------------------------------------------------- /scrummer/static/img/icons/image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer/static/img/icons/image.png -------------------------------------------------------------------------------- /scrummer/static/img/icons/json.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer/static/img/icons/json.png -------------------------------------------------------------------------------- /scrummer/static/img/icons/pdf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer/static/img/icons/pdf.png -------------------------------------------------------------------------------- /scrummer/static/img/icons/ppt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer/static/img/icons/ppt.png -------------------------------------------------------------------------------- /scrummer/static/img/icons/rar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer/static/img/icons/rar.png -------------------------------------------------------------------------------- /scrummer/static/img/icons/sheet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer/static/img/icons/sheet.png -------------------------------------------------------------------------------- /scrummer/static/img/icons/text.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer/static/img/icons/text.png -------------------------------------------------------------------------------- /scrummer/static/img/icons/unknown.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer/static/img/icons/unknown.png -------------------------------------------------------------------------------- /scrummer/static/img/icons/video.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer/static/img/icons/video.png -------------------------------------------------------------------------------- /scrummer/static/img/icons/zip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer/static/img/icons/zip.png -------------------------------------------------------------------------------- /scrummer/static/img/logo-gray-flat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer/static/img/logo-gray-flat.png -------------------------------------------------------------------------------- /scrummer/static/img/scrummer.svg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer/static/img/scrummer.svg -------------------------------------------------------------------------------- /scrummer/static/img/unassigned.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer/static/img/unassigned.png -------------------------------------------------------------------------------- /scrummer/static/src/css/compiled/ion.rangeSlider.skinFlat.css: -------------------------------------------------------------------------------- 1 | /* Ion.RangeSlider, Flat UI Skin 2 | // css version 2.0.3 3 | // © Denis Ineshin, 2014 https://github.com/IonDen 4 | // ===================================================================================================================*/ 5 | 6 | /* ===================================================================================================================== 7 | // Skin details */ 8 | 9 | .irs-line-mid, 10 | .irs-line-left, 11 | .irs-line-right, 12 | .irs-bar, 13 | .irs-bar-edge, 14 | .irs-slider { 15 | background: url(../img/sprite-skin-flat.png) repeat-x; 16 | } 17 | 18 | .irs { 19 | height: 40px; 20 | } 21 | .irs-with-grid { 22 | height: 60px; 23 | } 24 | .irs-line { 25 | height: 12px; top: 25px; 26 | } 27 | .irs-line-left { 28 | height: 12px; 29 | background-position: 0 -30px; 30 | } 31 | .irs-line-mid { 32 | height: 12px; 33 | background-position: 0 0; 34 | } 35 | .irs-line-right { 36 | height: 12px; 37 | background-position: 100% -30px; 38 | } 39 | 40 | .irs-bar { 41 | height: 12px; top: 25px; 42 | background-position: 0 -60px; 43 | } 44 | .irs-bar-edge { 45 | top: 25px; 46 | height: 12px; width: 9px; 47 | background-position: 0 -90px; 48 | } 49 | 50 | .irs-shadow { 51 | height: 3px; top: 34px; 52 | background: #000; 53 | opacity: 0.25; 54 | } 55 | .lt-ie9 .irs-shadow { 56 | filter: alpha(opacity=25); 57 | } 58 | 59 | .irs-slider { 60 | width: 16px; height: 18px; 61 | top: 22px; 62 | background-position: 0 -120px; 63 | } 64 | .irs-slider.state_hover, .irs-slider:hover { 65 | background-position: 0 -150px; 66 | } 67 | 68 | .irs-min, .irs-max { 69 | color: #999; 70 | font-size: 10px; line-height: 1.333; 71 | text-shadow: none; 72 | top: 0; padding: 1px 3px; 73 | background: #e1e4e9; 74 | -moz-border-radius: 4px; 75 | border-radius: 4px; 76 | } 77 | 78 | .irs-from, .irs-to, .irs-single { 79 | color: #fff; 80 | font-size: 10px; line-height: 1.333; 81 | text-shadow: none; 82 | padding: 1px 5px; 83 | background: #ed5565; 84 | -moz-border-radius: 4px; 85 | border-radius: 4px; 86 | } 87 | .irs-from:after, .irs-to:after, .irs-single:after { 88 | position: absolute; display: block; content: ""; 89 | bottom: -6px; left: 50%; 90 | width: 0; height: 0; 91 | margin-left: -3px; 92 | overflow: hidden; 93 | border: 3px solid transparent; 94 | border-top-color: #ed5565; 95 | } 96 | 97 | 98 | .irs-grid-pol { 99 | background: #e1e4e9; 100 | } 101 | .irs-grid-text { 102 | color: #999; 103 | } 104 | 105 | .irs-disabled { 106 | } 107 | -------------------------------------------------------------------------------- /scrummer/static/src/css/img/sprite-skin-flat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer/static/src/css/img/sprite-skin-flat.png -------------------------------------------------------------------------------- /scrummer/static/src/fonts/material-design-icons/Material-Design-Icons.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer/static/src/fonts/material-design-icons/Material-Design-Icons.eot -------------------------------------------------------------------------------- /scrummer/static/src/fonts/material-design-icons/Material-Design-Icons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer/static/src/fonts/material-design-icons/Material-Design-Icons.ttf -------------------------------------------------------------------------------- /scrummer/static/src/fonts/material-design-icons/Material-Design-Icons.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer/static/src/fonts/material-design-icons/Material-Design-Icons.woff -------------------------------------------------------------------------------- /scrummer/static/src/fonts/material-design-icons/Material-Design-Icons.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer/static/src/fonts/material-design-icons/Material-Design-Icons.woff2 -------------------------------------------------------------------------------- /scrummer/static/src/fonts/material-design-icons/materialdesignicons-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer/static/src/fonts/material-design-icons/materialdesignicons-webfont.eot -------------------------------------------------------------------------------- /scrummer/static/src/fonts/material-design-icons/materialdesignicons-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer/static/src/fonts/material-design-icons/materialdesignicons-webfont.ttf -------------------------------------------------------------------------------- /scrummer/static/src/fonts/material-design-icons/materialdesignicons-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer/static/src/fonts/material-design-icons/materialdesignicons-webfont.woff -------------------------------------------------------------------------------- /scrummer/static/src/fonts/material-design-icons/materialdesignicons-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer/static/src/fonts/material-design-icons/materialdesignicons-webfont.woff2 -------------------------------------------------------------------------------- /scrummer/static/src/fonts/material-icons/material-icons.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer/static/src/fonts/material-icons/material-icons.woff2 -------------------------------------------------------------------------------- /scrummer/static/src/fonts/roboto/Roboto-Bold.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer/static/src/fonts/roboto/Roboto-Bold.eot -------------------------------------------------------------------------------- /scrummer/static/src/fonts/roboto/Roboto-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer/static/src/fonts/roboto/Roboto-Bold.ttf -------------------------------------------------------------------------------- /scrummer/static/src/fonts/roboto/Roboto-Bold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer/static/src/fonts/roboto/Roboto-Bold.woff -------------------------------------------------------------------------------- /scrummer/static/src/fonts/roboto/Roboto-Bold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer/static/src/fonts/roboto/Roboto-Bold.woff2 -------------------------------------------------------------------------------- /scrummer/static/src/fonts/roboto/Roboto-Light.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer/static/src/fonts/roboto/Roboto-Light.eot -------------------------------------------------------------------------------- /scrummer/static/src/fonts/roboto/Roboto-Light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer/static/src/fonts/roboto/Roboto-Light.ttf -------------------------------------------------------------------------------- /scrummer/static/src/fonts/roboto/Roboto-Light.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer/static/src/fonts/roboto/Roboto-Light.woff -------------------------------------------------------------------------------- /scrummer/static/src/fonts/roboto/Roboto-Light.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer/static/src/fonts/roboto/Roboto-Light.woff2 -------------------------------------------------------------------------------- /scrummer/static/src/fonts/roboto/Roboto-Medium.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer/static/src/fonts/roboto/Roboto-Medium.eot -------------------------------------------------------------------------------- /scrummer/static/src/fonts/roboto/Roboto-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer/static/src/fonts/roboto/Roboto-Medium.ttf -------------------------------------------------------------------------------- /scrummer/static/src/fonts/roboto/Roboto-Medium.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer/static/src/fonts/roboto/Roboto-Medium.woff -------------------------------------------------------------------------------- /scrummer/static/src/fonts/roboto/Roboto-Medium.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer/static/src/fonts/roboto/Roboto-Medium.woff2 -------------------------------------------------------------------------------- /scrummer/static/src/fonts/roboto/Roboto-Regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer/static/src/fonts/roboto/Roboto-Regular.eot -------------------------------------------------------------------------------- /scrummer/static/src/fonts/roboto/Roboto-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer/static/src/fonts/roboto/Roboto-Regular.ttf -------------------------------------------------------------------------------- /scrummer/static/src/fonts/roboto/Roboto-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer/static/src/fonts/roboto/Roboto-Regular.woff -------------------------------------------------------------------------------- /scrummer/static/src/fonts/roboto/Roboto-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer/static/src/fonts/roboto/Roboto-Regular.woff2 -------------------------------------------------------------------------------- /scrummer/static/src/fonts/roboto/Roboto-Thin.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer/static/src/fonts/roboto/Roboto-Thin.eot -------------------------------------------------------------------------------- /scrummer/static/src/fonts/roboto/Roboto-Thin.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer/static/src/fonts/roboto/Roboto-Thin.ttf -------------------------------------------------------------------------------- /scrummer/static/src/fonts/roboto/Roboto-Thin.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer/static/src/fonts/roboto/Roboto-Thin.woff -------------------------------------------------------------------------------- /scrummer/static/src/fonts/roboto/Roboto-Thin.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer/static/src/fonts/roboto/Roboto-Thin.woff2 -------------------------------------------------------------------------------- /scrummer/static/src/img/android-icon-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer/static/src/img/android-icon-144x144.png -------------------------------------------------------------------------------- /scrummer/static/src/img/android-icon-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer/static/src/img/android-icon-192x192.png -------------------------------------------------------------------------------- /scrummer/static/src/img/android-icon-36x36.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer/static/src/img/android-icon-36x36.png -------------------------------------------------------------------------------- /scrummer/static/src/img/android-icon-48x48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer/static/src/img/android-icon-48x48.png -------------------------------------------------------------------------------- /scrummer/static/src/img/android-icon-72x72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer/static/src/img/android-icon-72x72.png -------------------------------------------------------------------------------- /scrummer/static/src/img/android-icon-96x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer/static/src/img/android-icon-96x96.png -------------------------------------------------------------------------------- /scrummer/static/src/img/apple-icon-114x114.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer/static/src/img/apple-icon-114x114.png -------------------------------------------------------------------------------- /scrummer/static/src/img/apple-icon-120x120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer/static/src/img/apple-icon-120x120.png -------------------------------------------------------------------------------- /scrummer/static/src/img/apple-icon-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer/static/src/img/apple-icon-144x144.png -------------------------------------------------------------------------------- /scrummer/static/src/img/apple-icon-152x152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer/static/src/img/apple-icon-152x152.png -------------------------------------------------------------------------------- /scrummer/static/src/img/apple-icon-180x180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer/static/src/img/apple-icon-180x180.png -------------------------------------------------------------------------------- /scrummer/static/src/img/apple-icon-57x57.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer/static/src/img/apple-icon-57x57.png -------------------------------------------------------------------------------- /scrummer/static/src/img/apple-icon-60x60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer/static/src/img/apple-icon-60x60.png -------------------------------------------------------------------------------- /scrummer/static/src/img/apple-icon-72x72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer/static/src/img/apple-icon-72x72.png -------------------------------------------------------------------------------- /scrummer/static/src/img/apple-icon-76x76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer/static/src/img/apple-icon-76x76.png -------------------------------------------------------------------------------- /scrummer/static/src/img/apple-icon-precomposed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer/static/src/img/apple-icon-precomposed.png -------------------------------------------------------------------------------- /scrummer/static/src/img/apple-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer/static/src/img/apple-icon.png -------------------------------------------------------------------------------- /scrummer/static/src/img/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer/static/src/img/favicon-16x16.png -------------------------------------------------------------------------------- /scrummer/static/src/img/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer/static/src/img/favicon-32x32.png -------------------------------------------------------------------------------- /scrummer/static/src/img/favicon-96x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer/static/src/img/favicon-96x96.png -------------------------------------------------------------------------------- /scrummer/static/src/img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer/static/src/img/favicon.ico -------------------------------------------------------------------------------- /scrummer/static/src/img/ms-icon-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer/static/src/img/ms-icon-144x144.png -------------------------------------------------------------------------------- /scrummer/static/src/img/ms-icon-150x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer/static/src/img/ms-icon-150x150.png -------------------------------------------------------------------------------- /scrummer/static/src/img/ms-icon-310x310.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer/static/src/img/ms-icon-310x310.png -------------------------------------------------------------------------------- /scrummer/static/src/img/ms-icon-70x70.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer/static/src/img/ms-icon-70x70.png -------------------------------------------------------------------------------- /scrummer/static/src/js/framework/config.js: -------------------------------------------------------------------------------- 1 | // Copyright 2017 - 2018 Modoolar 2 | // License LGPLv3.0 or later (https://www.gnu.org/licenses/lgpl-3.0.en.html). 3 | 4 | odoo.define('scrummer.config', function (require) { 5 | "use strict"; 6 | const bus = require('scrummer.core').bus; 7 | 8 | const medias = [ 9 | window.matchMedia('(max-width: 600px)'), 10 | window.matchMedia('(min-width: 601px) and (max-width: 992px)'), 11 | window.matchMedia('(min-width: 993px)') 12 | ]; 13 | 14 | function size_class() { 15 | for (let i = 0; i < medias.length; i++) { 16 | if (medias[i].matches) { 17 | return i; 18 | } 19 | } 20 | } 21 | 22 | const config = { 23 | debug: $.deparam($.param.querystring()).debug, 24 | device: { 25 | //touch: 'ontouchstart' in window || 'onmsgesturechange' in window, 26 | size_class: size_class(), 27 | SIZES: {S: 0, M: 1, L: 2} 28 | } 29 | }; 30 | 31 | function set_size_class() { 32 | const sc = size_class(); 33 | if (sc !== config.device.size_class) { 34 | config.device.size_class = sc; 35 | bus.trigger('size_class', sc); 36 | } 37 | } 38 | 39 | medias.forEach((m) => m.addListener(set_size_class)); 40 | 41 | return config; 42 | }); 43 | -------------------------------------------------------------------------------- /scrummer/static/src/js/framework/core.js: -------------------------------------------------------------------------------- 1 | // Copyright 2017 - 2018 Modoolar 2 | // License LGPLv3.0 or later (https://www.gnu.org/licenses/lgpl-3.0.en.html). 3 | 4 | odoo.define('scrummer.core', function (require) { 5 | "use strict"; 6 | const Bus = require('web.Bus'); 7 | 8 | const bus = new Bus(); 9 | 10 | return { 11 | bus, 12 | }; 13 | }); 14 | -------------------------------------------------------------------------------- /scrummer/static/src/js/framework/data/data.js: -------------------------------------------------------------------------------- 1 | // Copyright 2017 - 2018 Modoolar 2 | // License LGPLv3.0 or later (https://www.gnu.org/licenses/lgpl-3.0.en.html). 3 | 4 | odoo.define('scrummer.data', function (require) { 5 | "use strict"; 6 | const DataSet = require('scrummer.dataset'); 7 | const bus = require('bus.bus'); 8 | const session = require('web.session'); 9 | const Syncer = require('web.syncer').Syncer; 10 | const DependencyCache = require('scrummer.dependency_cache'); 11 | const cache = new DependencyCache.DependencyCache(); 12 | const getImage = function (model, id, last_update, field = "image_small") { 13 | return session.url('/web/image', { 14 | model, id, field, 15 | unique: (last_update || '').replace(/[^0-9]/g, '') 16 | }); 17 | }; 18 | const getTaskLinks = function (taskId) { 19 | return session.rpc(`/scrummer/web/data/task/${taskId}/get_task_links`, {context: {task_id: taskId}}); 20 | }; 21 | 22 | window.data = { 23 | cache, 24 | getDataSet: DataSet.get, 25 | getImage, 26 | getTaskLinks, 27 | session, 28 | bus, 29 | sync: new Syncer() 30 | }; 31 | return window.data; 32 | }); 33 | -------------------------------------------------------------------------------- /scrummer/static/src/js/framework/data/data_service_factory.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | // Copyright 2017 - 2018 Modoolar 3 | // License LGPLv3.0 or later (https://www.gnu.org/licenses/lgpl-3.0.en.html). 4 | 5 | odoo.define('scrummer.data_service_factory', function (require) { 6 | const DataService = require('scrummer.DataService'); 7 | 8 | // Registry of custom implementations of DataService. If not defined, standard DataService will be generated. 9 | const custom_registry = new Map(); 10 | const cached_data_services = new Map(); 11 | 12 | const DataServiceFactory = { 13 | custom_registry, 14 | get(modelName, readonly) { 15 | if (!cached_data_services.has(modelName)) { 16 | const DataServiceClass = custom_registry.has(modelName) ? custom_registry.get(modelName) : DataService; 17 | const newDataServiceInstance = new DataServiceClass({model: modelName}); 18 | newDataServiceInstance.setReadonly(readonly); 19 | cached_data_services.set(modelName, newDataServiceInstance); 20 | } 21 | return cached_data_services.get(modelName); 22 | } 23 | }; 24 | window.DataServiceFactory = DataServiceFactory; 25 | return DataServiceFactory; 26 | }); 27 | -------------------------------------------------------------------------------- /scrummer/static/src/js/framework/data/dependency_cache.js: -------------------------------------------------------------------------------- 1 | // Copyright 2017 - 2018 Modoolar 2 | // License LGPLv3.0 or later (https://www.gnu.org/licenses/lgpl-3.0.en.html). 3 | 4 | odoo.define('scrummer.dependency_cache', function (require) { 5 | "use strict"; 6 | 7 | const core = require('web.core'); 8 | const AgileMixins = require('scrummer.mixins'); 9 | const DataSet = require('scrummer.dataset'); 10 | 11 | const DependencyCache = core.Class.extend({ 12 | 13 | init() { 14 | this.deps = {}; 15 | }, 16 | 17 | orderedStringify(obj) { 18 | const copy = {}; 19 | if (typeof obj !== "object") { 20 | return ""; 21 | } 22 | Object.keys(obj).sort((a, b) => a > b).forEach((key) => { 23 | copy[key] = obj[key]; 24 | }); 25 | return JSON.stringify(copy); 26 | }, 27 | // TODO: Here we should implement some GC algorithm and maybe cache sharing between tabs. 28 | // Problem id: 60a91bed-b6ed-48cc-80db-69152e31cd12 29 | invokeOnceFactory(Dependency, options) { 30 | const invoked = new Map(); 31 | return (params) => { 32 | const optionsStringified = this.orderedStringify(params); 33 | if (!invoked.get(optionsStringified)) { 34 | const dep = new Dependency(this, options, params); 35 | invoked.set(optionsStringified, dep); 36 | dep.resolve(); 37 | } 38 | return invoked.get(optionsStringified).promise(); 39 | }; 40 | }, 41 | 42 | add(name, dependency, options) { 43 | this.deps[name] = this.invokeOnceFactory(dependency, options); 44 | }, 45 | 46 | get(name, params) { 47 | return this.deps[name](params); 48 | }, 49 | 50 | has(name) { 51 | return name in this.deps; 52 | } 53 | 54 | }); 55 | const AbstractDependency = core.Class.extend(AgileMixins.RequireMixin, { 56 | init(cache, options, params) { 57 | Object.assign(this, options); 58 | this.cache = cache; 59 | this.params = params; 60 | this.deferred = $.Deferred(); 61 | this.getDataSet = DataSet.get; 62 | }, 63 | /** 64 | * This method must be overridden and it should resolve/reject deferred with appropriate data. 65 | */ 66 | resolve() { 67 | throw new Error("Not implemented!"); 68 | }, 69 | promise() { 70 | return this.deferred.promise(); 71 | } 72 | }); 73 | 74 | return { 75 | DependencyCache, 76 | AbstractDependency, 77 | }; 78 | }); 79 | -------------------------------------------------------------------------------- /scrummer/static/src/js/framework/dialog.js: -------------------------------------------------------------------------------- 1 | // Copyright 2017 - 2018 Modoolar 2 | // License LGPLv3.0 or later (https://www.gnu.org/licenses/lgpl-3.0.en.html). 3 | 4 | 'use strict'; 5 | odoo.define('scrummer.dialog', function () { 6 | return { 7 | /** 8 | * 9 | * @param {String} title 10 | * @param {String} message 11 | * @param {String} [okText=ok] - Positive button text 12 | * @param {String} [cancelText=cancel] - Negative button text 13 | * @returns {jQuery.Promise} 14 | */ 15 | confirm(title, message, okText = "ok", cancelText = "cancel") { 16 | const def = new $.Deferred(); 17 | const modal = $(""); 20 | const modalFooter = $(""); 21 | modalFooter.appendTo(modal); 22 | const ok = $("" + okText + ""); 23 | const cancel = $("" + cancelText + ""); 24 | modalFooter.append(ok).append(cancel); 25 | $("body").append(modal); 26 | modal.materialModal({ 27 | dismissible: false, 28 | complete: function () { 29 | if (!modal.ok) { 30 | def.reject(); 31 | } 32 | modal.remove(); 33 | } 34 | }); 35 | 36 | modal.materialModal("open"); 37 | ok.click(() => { 38 | modal.ok = true; 39 | def.resolve(); 40 | modal.materialModal("close"); 41 | }); 42 | return def.promise(); 43 | 44 | } 45 | }; 46 | }); 47 | -------------------------------------------------------------------------------- /scrummer/static/src/js/framework/storage_service.js: -------------------------------------------------------------------------------- 1 | // Copyright 2017 - 2018 Modoolar 2 | // License LGPLv3.0 or later (https://www.gnu.org/licenses/lgpl-3.0.en.html). 3 | 4 | odoo.define('scrummer.storage_service', function (require) { 5 | "use strict"; 6 | 7 | const core = require('web.core'); 8 | const mixins = require('web.mixins'); 9 | 10 | const StorageService = core.Class.extend(mixins.EventDispatcherMixin, { 11 | init(prefix) { 12 | mixins.EventDispatcherMixin.init.call(this); 13 | this.prefix = prefix + "_"; 14 | }, 15 | /* 16 | * set,get and delete are simulation of Properties mixin, 17 | * but set/delete trigger change event only if value changes, 18 | * and returns object with oldValue & newValue 19 | */ 20 | set(key, val) { 21 | const keyWithPrefix = this.prefix + key; 22 | const currentVal = window.localStorage.getItem(keyWithPrefix); 23 | const value = typeof val === "object" ? JSON.stringify(val) : val; 24 | if (currentVal !== value) { 25 | const tmp = currentVal; 26 | window.localStorage.setItem(keyWithPrefix, value); 27 | if (tmp !== value) { 28 | this.trigger("change:" + key, this, { 29 | oldValue: tmp, 30 | newValue: value 31 | }); 32 | } 33 | } 34 | }, 35 | delete(key) { 36 | const keyWithPrefix = this.prefix + key; 37 | const currentVal = window.localStorage.getItem(keyWithPrefix); 38 | if (currentVal !== null) { 39 | const tmp = this.currentVal; 40 | window.localStorage.removeItem(keyWithPrefix); 41 | if (typeof tmp !== "undefined" && tmp !== null) { 42 | this.trigger("change:" + key, this, { 43 | oldValue: tmp, 44 | newValue: null 45 | }); 46 | } 47 | } 48 | }, 49 | get(key) { 50 | const keyWithPrefix = this.prefix + key; 51 | const currentVal = window.localStorage.getItem(keyWithPrefix); 52 | return this._isJsonString(currentVal) ? JSON.parse(currentVal) : currentVal; 53 | }, 54 | _isJsonString(str) { 55 | try { 56 | JSON.parse(str); 57 | } catch (e) { 58 | return false; 59 | } 60 | return true; 61 | } 62 | 63 | }); 64 | 65 | return new StorageService("scrummer"); 66 | }); 67 | -------------------------------------------------------------------------------- /scrummer/static/src/js/framework/toast.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | // Copyright 2017 - 2018 Modoolar 3 | // License LGPLv3.0 or later (https://www.gnu.org/licenses/lgpl-3.0.en.html). 4 | 5 | 6 | odoo.define('scrummer.toast', function (require) { 7 | const web_core = require('web.core'); 8 | const _t = web_core._t; 9 | const hash_service = require('scrummer.hash_service'); 10 | const ScrummerData = require('scrummer.data'); 11 | const Materialize = window.Materialize; 12 | 13 | return { 14 | duration: 5000, 15 | /** 16 | * 17 | * @param {(String | jQuery)} content 18 | * @param {String} imageUrl 19 | * @param {Object} button - Object with button metadata 20 | * @param {String} button.text - Button name 21 | * @param {function} button.callback - Callback that will be called on button click 22 | * @param {function} callback - Callback that will be called when toast is completed 23 | * @param {Number} duration - Duration in milliseconds 24 | * @param {String} type - Class that will be appended to toast, can be used for customising style 25 | */ 26 | toast(content, imageUrl, button, callback = null, duration = this.duration, type = "") { 27 | const toastContainer = $("
"); 28 | 29 | if (imageUrl) { 30 | const toastUserImage = $('
'); 31 | toastContainer.append(toastUserImage); 32 | } 33 | 34 | const toastContent = $('
'); 35 | toastContent.append(content); 36 | toastContainer.append(toastContent); 37 | if (button) { 38 | const btn = $('
'); 39 | btn.click(button.callback); 40 | toastContainer.append(btn); 41 | } 42 | Materialize.toast(toastContainer, duration, ("agile-toast " + type).trim(), callback); 43 | }, 44 | toastTask(user, task, method) { 45 | const action = { 46 | create: _t("created"), 47 | write: _t("updated"), 48 | unlink: _t("deleted"), 49 | }; 50 | const toastContent = $('

' + user.name + ' ' + action[method] + ' ' + task.priority_id[1] + ' ' + task.type_id[1] + ' ' + task.key + ' - ' + task.name + '

'); 51 | this.toast(toastContent, ScrummerData.getImage("res.users", user.id, user.write_date), { 52 | text: "open", callback: () => { 53 | hash_service.set("task", task.id); 54 | hash_service.set("view", "task"); 55 | hash_service.set("page", "board"); 56 | } 57 | }); 58 | } 59 | }; 60 | }); 61 | -------------------------------------------------------------------------------- /scrummer/static/src/js/framework/web_client.js: -------------------------------------------------------------------------------- 1 | // Copyright 2017 - 2018 Modoolar 2 | // License LGPLv3.0 or later (https://www.gnu.org/licenses/lgpl-3.0.en.html). 3 | 4 | "use strict"; 5 | odoo.define('web.web_client', function (require) { 6 | /* eslint-disable no-empty-function*/ 7 | const WebClient = require('web.WebClient'); 8 | const web_client = new WebClient(); 9 | 10 | 11 | web_client._title_changed = function () {}; 12 | web_client.do_push_state = function (state) { 13 | this.trigger('state_pushed', state); 14 | }; 15 | web_client.toggle_fullscreen = function(){}; 16 | web_client.current_action_updated = function(){}; 17 | web_client.show_application = function () { 18 | return web_client.action_manager.do_action("scrummer"); 19 | }; 20 | 21 | $(function () { 22 | web_client.setElement($(document.body)); 23 | web_client.start(); 24 | }); 25 | return web_client; 26 | }); 27 | -------------------------------------------------------------------------------- /scrummer/static/src/js/libs/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "globals": { 3 | "$": false, 4 | "_": false, 5 | "jQuery": false, 6 | "moment": false, 7 | "odoo": false, 8 | "openerp": false, 9 | "self": false 10 | }, 11 | "env": { 12 | "browser": true, 13 | "es6": true 14 | }, 15 | "rules": {}, 16 | "parserOptions": { 17 | "ecmaVersion": 2018 18 | }, 19 | "root": true 20 | } -------------------------------------------------------------------------------- /scrummer/static/src/js/libs/external/README-materialize-compatibility.txt: -------------------------------------------------------------------------------- 1 | 1. $.fn.modal is in conflict with odoo's modal, so here is renamed to $.fn.materialModal 2 | 2. appendOptionWithIcon in select plugin is extended with following code to enable materialdesignicons inside option 3 | var mdi = option.data('mdi'); 4 | var iconColor = option.data('iconColor'); 5 | if (!!mdi) { 6 | var classString = (!!classes) ? ' class="mdi mdi-' + mdi + ' ' + classes + '"' : ' class="mdi mdi-' + mdi + '"'; 7 | var styleString = 'style="' + (mdi.startsWith("custom-") ? 'background-color' : 'color') + ':' + iconColor + '"'; 8 | // Check for multiple type. 9 | if (type === 'multiple') { 10 | options.append($('
  • ' + option.html() + '
  • ')); 11 | } else { 12 | options.append($('
  • ' + option.html() + '
  • ')); 13 | } 14 | return true; 15 | } 16 | 3. Updated Waves to 0.7.5 (Replaced sass _Waves and changed materialize.js) 17 | 4. When closing modal of materialNote, event is propagated to main modal and it's also getting closed, so stopping propagation is added in line 2631: 18 | $(this).on('closeModal', function (e) { 19 | e.stopPropagation(); -------------------------------------------------------------------------------- /scrummer/static/src/js/libs/jquery-validate.js: -------------------------------------------------------------------------------- 1 | // Copyright 2017 - 2018 Modoolar 2 | // License LGPLv3.0 or later (https://www.gnu.org/licenses/lgpl-3.0.en.html). 3 | odoo.define('jquery-validator', function (require) { 4 | var _t = require('web.core')._t; 5 | 6 | jQuery.validator.setDefaults({ 7 | messages: { 8 | required: _t("This field is required."), 9 | remote: _t("Please fix this field."), 10 | email: _t("Please enter a valid email address."), 11 | url: _t("Please enter a valid URL."), 12 | date: _t("Please enter a valid date."), 13 | dateISO: _t("Please enter a valid date (ISO)."), 14 | number: _t("Please enter a valid number."), 15 | digits: _t("Please enter only digits."), 16 | equalTo: _t("Please enter the same value again."), 17 | maxlength: $.validator.format(_t("Please enter no more than {0} characters.")), 18 | minlength: $.validator.format(_t("Please enter at least {0} characters.")), 19 | rangelength: $.validator.format(_t("Please enter a value between {0} and {1} characters long.")), 20 | range: $.validator.format(_t("Please enter a value between {0} and {1}.")), 21 | max: $.validator.format(_t("Please enter a value less than or equal to {0}.")), 22 | min: $.validator.format(_t("Please enter a value greater than or equal to {0}.")), 23 | step: $.validator.format(_t("Please enter a multiple of {0}.")) 24 | }, 25 | ignore:"", 26 | validClass:"", 27 | errorElement: 'div', 28 | errorPlacement: function (error, element) { 29 | var placement = $(element).data('error'); 30 | if (placement) { 31 | $(placement).append(error) 32 | } else { 33 | error.insertAfter(element); 34 | } 35 | } 36 | }); 37 | }); 38 | -------------------------------------------------------------------------------- /scrummer/static/src/js/main.js: -------------------------------------------------------------------------------- 1 | // Copyright 2017 - 2018 Modoolar 2 | // License LGPLv3.0 or later (https://www.gnu.org/licenses/lgpl-3.0.en.html). 3 | 4 | odoo.define('scrummer.main', function (require) { 5 | "use strict"; 6 | const AgileLayout = require('scrummer.layout'); 7 | const core = require('web.core'); 8 | 9 | core.action_registry.add('scrummer', AgileLayout.AgileLayout); 10 | 11 | }); 12 | -------------------------------------------------------------------------------- /scrummer/static/src/js/widgets/subheader.js: -------------------------------------------------------------------------------- 1 | // Copyright 2017 - 2018 Modoolar 2 | // License LGPLv3.0 or later (https://www.gnu.org/licenses/lgpl-3.0.en.html). 3 | 4 | odoo.define('scrummer.subheader', ['scrummer.BaseWidgets'], function (require) { 5 | "use strict"; 6 | const AgileBaseWidgets = require('scrummer.BaseWidgets'); 7 | 8 | const SubheaderWidget = AgileBaseWidgets.AgileBaseWidget.extend({ 9 | _name: "SubheaderWidget", 10 | template: "scrummer.subheader", 11 | setTitle(title){ 12 | if(typeof title === "string"){ 13 | this.$(".view-title").html(`
    ${title}
    `); 14 | } else if(title instanceof jQuery){ 15 | this.$(".view-title").empty().append(title); 16 | } 17 | } 18 | }); 19 | return { 20 | SubheaderWidget 21 | }; 22 | }); 23 | -------------------------------------------------------------------------------- /scrummer/static/src/scss/components/_materialize_overrides.scss: -------------------------------------------------------------------------------- 1 | $button-padding: 0 0.7rem; 2 | @import "../materialize-components/color"; 3 | 4 | /*** Colors ***/ 5 | $primary-color: color("agile-main-color", "base") !default; 6 | $primary-color-light: lighten($primary-color, 15%) !default; 7 | $primary-color-dark: darken($primary-color, 15%) !default; 8 | 9 | $secondary-color: color("green", "base") !default; 10 | $success-color: color("green", "accent-3") !default; 11 | $error-color: color("red", "accent-3") !default; 12 | 13 | /*** Navbar ***/ 14 | $navbar-height: 45px !default; 15 | $navbar-height-mobile: 56px !default; 16 | 17 | /*** Chips ***/ 18 | $chip-selected-color: $secondary-color; -------------------------------------------------------------------------------- /scrummer/static/src/scss/materialdesignicons.scss: -------------------------------------------------------------------------------- 1 | /* MaterialDesignIcons.com */ 2 | $mdi-font-path: "../fonts/material-design-icons"; 3 | @import "materialdesignicons/variables"; 4 | @import "materialdesignicons/functions"; 5 | @import "materialdesignicons/path"; 6 | @import "materialdesignicons/core"; 7 | @import "materialdesignicons/icons"; 8 | @import "materialdesignicons/extras"; 9 | @import "materialdesignicons/animated"; 10 | -------------------------------------------------------------------------------- /scrummer/static/src/scss/materialdesignicons/_animated.scss: -------------------------------------------------------------------------------- 1 | // From Font Awesome 2 | .#{$mdi-css-prefix}-spin:before { 3 | -webkit-animation: #{$mdi-css-prefix}-spin 2s infinite linear; 4 | animation: #{$mdi-css-prefix}-spin 2s infinite linear; 5 | } 6 | 7 | @-webkit-keyframes #{$mdi-css-prefix}-spin { 8 | 0% { 9 | -webkit-transform: rotate(0deg); 10 | transform: rotate(0deg); 11 | } 12 | 100% { 13 | -webkit-transform: rotate(359deg); 14 | transform: rotate(359deg); 15 | } 16 | } 17 | 18 | @keyframes #{$mdi-css-prefix}-spin { 19 | 0% { 20 | -webkit-transform: rotate(0deg); 21 | transform: rotate(0deg); 22 | } 23 | 100% { 24 | -webkit-transform: rotate(359deg); 25 | transform: rotate(359deg); 26 | } 27 | } -------------------------------------------------------------------------------- /scrummer/static/src/scss/materialdesignicons/_core.scss: -------------------------------------------------------------------------------- 1 | .#{$mdi-css-prefix}:before, 2 | .#{$mdi-css-prefix}-set { 3 | display: inline-block; 4 | font: normal normal normal #{$mdi-font-size-base}/1 '#{$mdi-font-name}'; // shortening font declaration 5 | font-size: inherit; // can't have font-size inherit on line above, so need to override 6 | text-rendering: auto; // optimizelegibility throws things off #1094 7 | line-height: inherit; 8 | -webkit-font-smoothing: antialiased; 9 | -moz-osx-font-smoothing: grayscale; 10 | } -------------------------------------------------------------------------------- /scrummer/static/src/scss/materialdesignicons/_extras.scss: -------------------------------------------------------------------------------- 1 | $mdi-sizes: 18 24 36 48; 2 | @each $mdi-size in $mdi-sizes { 3 | .#{$mdi-css-prefix}-#{$mdi-size}px { 4 | &.#{$mdi-css-prefix}-set, 5 | &.#{$mdi-css-prefix}:before { 6 | font-size: $mdi-size * 1px; 7 | } 8 | } 9 | } 10 | 11 | .#{$mdi-css-prefix}-dark { 12 | &:before { 13 | color: rgba(0, 0, 0, 0.54); 14 | } 15 | &.mdi-inactive:before { 16 | color: rgba(0, 0, 0, 0.26); 17 | } 18 | } 19 | .#{$mdi-css-prefix}-light { 20 | &:before { 21 | color: rgba(255, 255, 255, 1); 22 | } 23 | &.mdi-inactive:before { 24 | color: rgba(255, 255, 255, 0.3); 25 | } 26 | } 27 | 28 | $mdi-degrees: 45 90 135 180 225 270 315; 29 | @each $mdi-degree in $mdi-degrees { 30 | .#{$mdi-css-prefix}-rotate-#{$mdi-degree}{ 31 | &:before { 32 | -webkit-transform: rotate(#{$mdi-degree}deg); 33 | -ms-transform: rotate(#{$mdi-degree}deg); 34 | transform: rotate(#{$mdi-degree}deg); 35 | } 36 | /* 37 | // Not included in production 38 | &.#{$mdi-css-prefix}-flip-h:before { 39 | -webkit-transform: scaleX(-1) rotate(#{$mdi-degree}deg); 40 | transform: scaleX(-1) rotate(#{$mdi-degree}deg); 41 | filter: FlipH; 42 | -ms-filter: "FlipH"; 43 | } 44 | &.#{$mdi-css-prefix}-flip-v:before { 45 | -webkit-transform: scaleY(-1) rotate(#{$mdi-degree}deg); 46 | -ms-transform: rotate(#{$mdi-degree}deg); 47 | transform: scaleY(-1) rotate(#{$mdi-degree}deg); 48 | filter: FlipV; 49 | -ms-filter: "FlipV"; 50 | } 51 | */ 52 | } 53 | } 54 | .#{$mdi-css-prefix}-flip-h:before { 55 | -webkit-transform: scaleX(-1); 56 | transform: scaleX(-1); 57 | filter: FlipH; 58 | -ms-filter: "FlipH"; 59 | } 60 | .#{$mdi-css-prefix}-flip-v:before { 61 | -webkit-transform: scaleY(-1); 62 | transform: scaleY(-1); 63 | filter: FlipV; 64 | -ms-filter: "FlipV"; 65 | } -------------------------------------------------------------------------------- /scrummer/static/src/scss/materialdesignicons/_functions.scss: -------------------------------------------------------------------------------- 1 | @function char($character-code) { 2 | @if function-exists("selector-append") { 3 | @return unquote("\"\\#{$character-code}\""); 4 | } 5 | 6 | @if "\\#{'x'}" == "\\x" { 7 | @return str-slice("\x", 1, 1) + $character-code; 8 | } 9 | @else { 10 | @return #{"\"\\"}#{$character-code + "\""}; 11 | } 12 | } 13 | 14 | @function mdi($name) { 15 | @if map-has-key($mdi-icons, $name) == false { 16 | @warn "Icon #{$name} not found."; 17 | @return ""; 18 | } 19 | @return char(map-get($mdi-icons, $name)); 20 | } -------------------------------------------------------------------------------- /scrummer/static/src/scss/materialdesignicons/_icons.scss: -------------------------------------------------------------------------------- 1 | @each $key, $value in $mdi-icons { 2 | .#{$mdi-css-prefix}-#{$key}:before { 3 | content: char($value); 4 | } 5 | } 6 | 7 | .#{$mdi-css-prefix}-blank:before { 8 | content: "\F68C"; 9 | visibility: hidden; 10 | } -------------------------------------------------------------------------------- /scrummer/static/src/scss/materialdesignicons/_path.scss: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: '#{$mdi-font-name}'; 3 | src: url('#{$mdi-font-path}/#{$mdi-filename}-webfont.eot?v=#{$mdi-version}'); 4 | src: url('#{$mdi-font-path}/#{$mdi-filename}-webfont.eot?#iefix&v=#{$mdi-version}') format('embedded-opentype'), 5 | url('#{$mdi-font-path}/#{$mdi-filename}-webfont.woff2?v=#{$mdi-version}') format('woff2'), 6 | url('#{$mdi-font-path}/#{$mdi-filename}-webfont.woff?v=#{$mdi-version}') format('woff'), 7 | url('#{$mdi-font-path}/#{$mdi-filename}-webfont.ttf?v=#{$mdi-version}') format('truetype'), 8 | url('#{$mdi-font-path}/#{$mdi-filename}-webfont.svg?v=#{$mdi-version}##{$mdi-filename}#{$mdi-font-weight}') format('svg'); 9 | font-weight: normal; 10 | font-style: normal; 11 | } 12 | -------------------------------------------------------------------------------- /scrummer/static/src/scss/materialize-components/_carousel.scss: -------------------------------------------------------------------------------- 1 | .carousel { 2 | &.carousel-slider { 3 | top: 0; 4 | left: 0; 5 | height: 0; 6 | 7 | .carousel-fixed-item { 8 | &.with-indicators { 9 | bottom: 68px; 10 | } 11 | 12 | position: absolute; 13 | left: 0; 14 | right: 0; 15 | bottom: 20px; 16 | z-index: 1; 17 | } 18 | 19 | .carousel-item { 20 | width: 100%; 21 | height: 100%; 22 | min-height: 400px; 23 | position: absolute; 24 | top: 0; 25 | left: 0; 26 | 27 | h2 { 28 | font-size: 24px; 29 | font-weight: 500; 30 | line-height: 32px; 31 | } 32 | 33 | p { 34 | font-size: 15px; 35 | } 36 | } 37 | } 38 | 39 | overflow: hidden; 40 | position: relative; 41 | width: 100%; 42 | height: 400px; 43 | perspective: 500px; 44 | transform-style: preserve-3d; 45 | transform-origin: 0% 50%; 46 | 47 | .carousel-item { 48 | display: none; 49 | width: 200px; 50 | height: 400px; 51 | position: absolute; 52 | top: 0; 53 | left: 0; 54 | 55 | img { 56 | width: 100%; 57 | } 58 | } 59 | 60 | .indicators { 61 | position: absolute; 62 | text-align: center; 63 | left: 0; 64 | right: 0; 65 | bottom: 0; 66 | margin: 0; 67 | 68 | .indicator-item { 69 | &.active { 70 | background-color: #fff; 71 | } 72 | 73 | display: inline-block; 74 | position: relative; 75 | cursor: pointer; 76 | height: 8px; 77 | width: 8px; 78 | margin: 24px 4px; 79 | background-color: rgba(255,255,255,.5); 80 | 81 | transition: background-color .3s; 82 | border-radius: 50%; 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /scrummer/static/src/scss/materialize-components/_chips.scss: -------------------------------------------------------------------------------- 1 | .chip { 2 | display: inline-block; 3 | height: 32px; 4 | font-size: 13px; 5 | font-weight: 500; 6 | color: rgba(0,0,0,.6); 7 | line-height: 32px; 8 | padding: 0 12px; 9 | border-radius: 16px; 10 | background-color: $chip-bg-color; 11 | margin-bottom: $chip-margin; 12 | margin-right: $chip-margin; 13 | 14 | img { 15 | float: left; 16 | margin: 0 8px 0 -12px; 17 | height: 32px; 18 | width: 32px; 19 | border-radius: 50%; 20 | } 21 | 22 | .close { 23 | cursor: pointer; 24 | float: right; 25 | font-size: 16px; 26 | line-height: 32px; 27 | padding-left: 8px; 28 | } 29 | } 30 | 31 | .chips { 32 | border: none; 33 | border-bottom: 1px solid $chip-border-color; 34 | box-shadow: none; 35 | margin: $input-margin; 36 | min-height: 45px; 37 | outline: none; 38 | transition: all .3s; 39 | 40 | &.focus { 41 | border-bottom: 1px solid $chip-selected-color; 42 | box-shadow: 0 1px 0 0 $chip-selected-color; 43 | } 44 | 45 | &:hover { 46 | cursor: text; 47 | } 48 | 49 | .chip.selected { 50 | background-color: $chip-selected-color; 51 | color: #fff; 52 | } 53 | 54 | .input { 55 | background: none; 56 | border: 0; 57 | color: rgba(0,0,0,.6); 58 | display: inline-block; 59 | font-size: $input-font-size; 60 | height: $input-height; 61 | line-height: 32px; 62 | outline: 0; 63 | margin: 0; 64 | padding: 0 !important; 65 | width: 120px !important; 66 | } 67 | 68 | .input:focus { 69 | border: 0 !important; 70 | box-shadow: none !important; 71 | } 72 | } 73 | 74 | // Form prefix 75 | .prefix ~ .chips { 76 | margin-left: 3rem; 77 | width: 92%; 78 | width: calc(100% - 3rem); 79 | } 80 | .chips:empty ~ label { 81 | font-size: 0.8rem; 82 | transform: translateY(-140%); 83 | } 84 | -------------------------------------------------------------------------------- /scrummer/static/src/scss/materialize-components/_collapsible.scss: -------------------------------------------------------------------------------- 1 | .collapsible { 2 | border-top: 1px solid $collapsible-border-color; 3 | border-right: 1px solid $collapsible-border-color; 4 | border-left: 1px solid $collapsible-border-color; 5 | margin: $element-top-margin 0 $element-bottom-margin 0; 6 | @extend .z-depth-1; 7 | } 8 | 9 | .collapsible-header { 10 | display: block; 11 | cursor: pointer; 12 | min-height: $collapsible-height; 13 | line-height: $collapsible-height; 14 | padding: 0 1rem; 15 | background-color: $collapsible-header-color; 16 | //border-bottom: 1px solid $collapsible-border-color; 17 | 18 | i { 19 | width: 2rem; 20 | font-size: 1.6rem; 21 | line-height: $collapsible-height; 22 | display: block; 23 | float: left; 24 | text-align: center; 25 | margin-right: 1rem; 26 | } 27 | } 28 | 29 | .collapsible-body { 30 | display: none; 31 | //border-bottom: 1px solid $collapsible-border-color; 32 | box-sizing: border-box; 33 | 34 | p { 35 | margin: 0; 36 | padding: 2rem; 37 | } 38 | } 39 | 40 | // sideNav collapsible styling 41 | .side-nav, 42 | .side-nav.fixed { 43 | 44 | .collapsible { 45 | border: none; 46 | box-shadow: none; 47 | 48 | li { padding: 0; } 49 | } 50 | 51 | .collapsible-header { 52 | background-color: transparent; 53 | border: none; 54 | line-height: inherit; 55 | height: inherit; 56 | padding: 0 $sidenav-padding; 57 | 58 | &:hover { background-color: rgba(0,0,0,.05); } 59 | i { line-height: inherit; } 60 | } 61 | 62 | .collapsible-body { 63 | border: 0; 64 | background-color: $collapsible-header-color; 65 | 66 | li a { 67 | padding: 0 (7.5px + $sidenav-padding) 68 | 0 (15px + $sidenav-padding); 69 | } 70 | } 71 | 72 | } 73 | 74 | // Popout Collapsible 75 | 76 | .collapsible.popout { 77 | border: none; 78 | box-shadow: none; 79 | > li { 80 | box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.16), 0 2px 10px 0 rgba(0, 0, 0, 0.12); 81 | // transform: scaleX(.92); 82 | margin: 0 24px; 83 | transition: margin .35s cubic-bezier(0.250, 0.460, 0.450, 0.940); 84 | } 85 | > li.active { 86 | box-shadow: 0 5px 11px 0 rgba(0, 0, 0, 0.18), 0 4px 15px 0 rgba(0, 0, 0, 0.15); 87 | margin: 16px 0; 88 | // transform: scaleX(1); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /scrummer/static/src/scss/materialize-components/_dropdown.scss: -------------------------------------------------------------------------------- 1 | .dropdown-content { 2 | @extend .z-depth-1; 3 | background-color: $dropdown-bg-color; 4 | margin: 0; 5 | display: none; 6 | min-width: 100px; 7 | max-height: 650px; 8 | overflow-y: auto; 9 | opacity: 0; 10 | position: absolute; 11 | z-index: 999; 12 | will-change: width, height; 13 | 14 | li { 15 | clear: both; 16 | color: $off-black; 17 | cursor: pointer; 18 | min-height: $dropdown-item-height; 19 | line-height: 1.5rem; 20 | width: 100%; 21 | text-align: left; 22 | text-transform: none; 23 | 24 | &:hover, &.active, &.selected { 25 | background-color: $dropdown-hover-bg-color; 26 | } 27 | 28 | &.active.selected { 29 | background-color: darken($dropdown-hover-bg-color, 5%); 30 | } 31 | 32 | &.divider { 33 | min-height: 0; 34 | height: 1px; 35 | } 36 | 37 | & > a, & > span { 38 | font-size: 16px; 39 | color: $dropdown-color; 40 | display: block; 41 | line-height: 22px; 42 | padding: (($dropdown-item-height - 22) / 2) 16px; 43 | } 44 | 45 | & > span > label { 46 | top: 1px; 47 | left: 0; 48 | height: 18px; 49 | } 50 | 51 | // Icon alignment override 52 | & > a > i { 53 | height: inherit; 54 | line-height: inherit; 55 | } 56 | } 57 | } 58 | 59 | // Input field specificity bugfix 60 | .input-field.col .dropdown-content [type="checkbox"] + label { 61 | top: 1px; 62 | left: 0; 63 | height: 18px; 64 | } 65 | 66 | -------------------------------------------------------------------------------- /scrummer/static/src/scss/materialize-components/_icons-material-design.scss: -------------------------------------------------------------------------------- 1 | /* This is needed for some mobile phones to display the Google Icon font properly */ 2 | .material-icons { 3 | text-rendering: optimizeLegibility; 4 | font-feature-settings: 'liga'; 5 | } 6 | -------------------------------------------------------------------------------- /scrummer/static/src/scss/materialize-components/_materialbox.scss: -------------------------------------------------------------------------------- 1 | .materialboxed { 2 | display: block; 3 | cursor: zoom-in; 4 | position: relative; 5 | transition: opacity .4s; 6 | 7 | &:hover { 8 | &:not(.active) { 9 | opacity: .8; 10 | } 11 | will-change: left, top, width, height; 12 | } 13 | } 14 | 15 | .materialboxed.active { 16 | cursor: zoom-out; 17 | } 18 | 19 | #materialbox-overlay { 20 | position:fixed; 21 | top:0; 22 | left:0; 23 | right: 0; 24 | bottom: 0; 25 | background-color: #292929; 26 | z-index: 1000; 27 | 28 | will-change: opacity; 29 | } 30 | .materialbox-caption { 31 | position: fixed; 32 | display: none; 33 | color: #fff; 34 | line-height: 50px; 35 | bottom: 0; 36 | width: 100%; 37 | text-align: center; 38 | padding: 0% 15%; 39 | height: 50px; 40 | z-index: 1000; 41 | -webkit-font-smoothing: antialiased; 42 | } -------------------------------------------------------------------------------- /scrummer/static/src/scss/materialize-components/_mixins.scss: -------------------------------------------------------------------------------- 1 | // @mixin box-shadow-2($args1, $args2) { 2 | // -webkit-box-shadow: $args1, $args2; 3 | // -moz-box-shadow: $args1, $args2; 4 | // box-shadow: $args1, $args2; 5 | // } -------------------------------------------------------------------------------- /scrummer/static/src/scss/materialize-components/_modal.scss: -------------------------------------------------------------------------------- 1 | .modal { 2 | @extend .z-depth-4; 3 | 4 | display: none; 5 | position: fixed; 6 | left: 0; 7 | right: 0; 8 | background-color: #fafafa; 9 | padding: 0; 10 | max-height: 70%; 11 | width: 55%; 12 | margin: auto; 13 | overflow-y: auto; 14 | 15 | border-radius: 2px; 16 | will-change: top, opacity; 17 | 18 | @media #{$medium-and-down} { 19 | width: 80%; 20 | } 21 | 22 | h1,h2,h3,h4 { 23 | margin-top: 0; 24 | } 25 | 26 | .modal-content { 27 | padding: 24px; 28 | } 29 | .modal-close { 30 | cursor: pointer; 31 | } 32 | 33 | .modal-footer { 34 | border-radius: 0 0 2px 2px; 35 | background-color: #fafafa; 36 | padding: 4px 6px; 37 | height: 56px; 38 | width: 100%; 39 | 40 | .btn, .btn-flat { 41 | float: right; 42 | margin: 6px 0; 43 | } 44 | } 45 | } 46 | .modal-overlay { 47 | position: fixed; 48 | z-index: 999; 49 | top: -100px; 50 | left: 0; 51 | bottom: 0; 52 | right: 0; 53 | height: 125%; 54 | width: 100%; 55 | background: #000; 56 | display: none; 57 | 58 | will-change: opacity; 59 | } 60 | 61 | // Modal with fixed action footer 62 | .modal.modal-fixed-footer { 63 | padding: 0; 64 | height: 70%; 65 | 66 | .modal-content { 67 | position: absolute; 68 | height: calc(100% - 56px); 69 | max-height: 100%; 70 | width: 100%; 71 | overflow-y: auto; 72 | } 73 | 74 | .modal-footer { 75 | border-top: 1px solid rgba(0,0,0,.1); 76 | position: absolute; 77 | bottom: 0; 78 | } 79 | } 80 | 81 | // Modal Bottom Sheet Style 82 | .modal.bottom-sheet { 83 | top: auto; 84 | bottom: -100%; 85 | margin: 0; 86 | width: 100%; 87 | max-height: 45%; 88 | border-radius: 0; 89 | will-change: bottom, opacity; 90 | } 91 | -------------------------------------------------------------------------------- /scrummer/static/src/scss/materialize-components/_roboto.scss: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: "Roboto"; 3 | src: local(Roboto Thin), url('#{$roboto-font-path}Roboto-Thin.eot'); 4 | src: url("#{$roboto-font-path}Roboto-Thin.eot?#iefix") format('embedded-opentype'), 5 | url("#{$roboto-font-path}Roboto-Thin.woff2") format("woff2"), 6 | url("#{$roboto-font-path}Roboto-Thin.woff") format("woff"), 7 | url("#{$roboto-font-path}Roboto-Thin.ttf") format("truetype"); 8 | 9 | font-weight: 200; 10 | } 11 | @font-face { 12 | font-family: "Roboto"; 13 | src: local(Roboto Light), url('#{$roboto-font-path}Roboto-Light.eot'); 14 | src: url("#{$roboto-font-path}Roboto-Light.eot?#iefix") format('embedded-opentype'), 15 | url("#{$roboto-font-path}Roboto-Light.woff2") format("woff2"), 16 | url("#{$roboto-font-path}Roboto-Light.woff") format("woff"), 17 | url("#{$roboto-font-path}Roboto-Light.ttf") format("truetype"); 18 | font-weight: 300; 19 | } 20 | 21 | @font-face { 22 | font-family: "Roboto"; 23 | src: local(Roboto Regular), url('#{$roboto-font-path}Roboto-Regular.eot'); 24 | src: url("#{$roboto-font-path}Roboto-Regular.eot?#iefix") format('embedded-opentype'), 25 | url("#{$roboto-font-path}Roboto-Regular.woff2") format("woff2"), 26 | url("#{$roboto-font-path}Roboto-Regular.woff") format("woff"), 27 | url("#{$roboto-font-path}Roboto-Regular.ttf") format("truetype"); 28 | font-weight: 400; 29 | } 30 | 31 | @font-face { 32 | font-family: "Roboto"; 33 | src: url('#{$roboto-font-path}Roboto-Medium.eot'); 34 | src: url("#{$roboto-font-path}Roboto-Medium.eot?#iefix") format('embedded-opentype'), 35 | url("#{$roboto-font-path}Roboto-Medium.woff2") format("woff2"), 36 | url("#{$roboto-font-path}Roboto-Medium.woff") format("woff"), 37 | url("#{$roboto-font-path}Roboto-Medium.ttf") format("truetype"); 38 | font-weight: 500; 39 | } 40 | 41 | @font-face { 42 | font-family: "Roboto"; 43 | src: url('#{$roboto-font-path}Roboto-Bold.eot'); 44 | src: url("#{$roboto-font-path}Roboto-Bold.eot?#iefix") format('embedded-opentype'), 45 | url("#{$roboto-font-path}Roboto-Bold.woff2") format("woff2"), 46 | url("#{$roboto-font-path}Roboto-Bold.woff") format("woff"), 47 | url("#{$roboto-font-path}Roboto-Bold.ttf") format("truetype"); 48 | font-weight: 700; 49 | } 50 | -------------------------------------------------------------------------------- /scrummer/static/src/scss/materialize-components/_slider.scss: -------------------------------------------------------------------------------- 1 | .slider { 2 | position: relative; 3 | height: 400px; 4 | width: 100%; 5 | 6 | // Fullscreen slider 7 | &.fullscreen { 8 | height: 100%; 9 | width: 100%; 10 | position: absolute; 11 | top: 0; 12 | left: 0; 13 | right: 0; 14 | bottom: 0; 15 | 16 | ul.slides { 17 | height: 100%; 18 | } 19 | 20 | ul.indicators { 21 | z-index: 2; 22 | bottom: 30px; 23 | } 24 | } 25 | 26 | .slides { 27 | background-color: $slider-bg-color; 28 | margin: 0; 29 | height: 400px; 30 | 31 | li { 32 | opacity: 0; 33 | position: absolute; 34 | top: 0; 35 | left: 0; 36 | z-index: 1; 37 | width: 100%; 38 | height: inherit; 39 | overflow: hidden; 40 | 41 | img { 42 | height: 100%; 43 | width: 100%; 44 | background-size: cover; 45 | background-position: center; 46 | } 47 | 48 | .caption { 49 | color: #fff; 50 | position: absolute; 51 | top: 15%; 52 | left: 15%; 53 | width: 70%; 54 | opacity: 0; 55 | 56 | p { color: $slider-bg-color-light; } 57 | } 58 | 59 | &.active { 60 | z-index: 2; 61 | } 62 | } 63 | } 64 | 65 | 66 | .indicators { 67 | position: absolute; 68 | text-align: center; 69 | left: 0; 70 | right: 0; 71 | bottom: 0; 72 | margin: 0; 73 | 74 | .indicator-item { 75 | display: inline-block; 76 | position: relative; 77 | cursor: pointer; 78 | height: 16px; 79 | width: 16px; 80 | margin: 0 12px; 81 | background-color: $slider-bg-color-light; 82 | 83 | transition: background-color .3s; 84 | border-radius: 50%; 85 | 86 | &.active { 87 | background-color: $slider-indicator-color; 88 | } 89 | } 90 | } 91 | 92 | } -------------------------------------------------------------------------------- /scrummer/static/src/scss/materialize-components/_table_of_contents.scss: -------------------------------------------------------------------------------- 1 | /*************** 2 | Nav List 3 | ***************/ 4 | .table-of-contents { 5 | &.fixed { 6 | position: fixed; 7 | } 8 | 9 | li { 10 | padding: 2px 0; 11 | } 12 | a { 13 | display: inline-block; 14 | font-weight: 300; 15 | color: #757575; 16 | padding-left: 20px; 17 | height: 1.5rem; 18 | line-height: 1.5rem; 19 | letter-spacing: .4; 20 | display: inline-block; 21 | 22 | &:hover { 23 | color: lighten(#757575, 20%); 24 | padding-left: 19px; 25 | border-left: 1px solid lighten(color("materialize-red", "base"),10%); 26 | } 27 | &.active { 28 | font-weight: 500; 29 | padding-left: 18px; 30 | border-left: 2px solid lighten(color("materialize-red", "base"),10%); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /scrummer/static/src/scss/materialize-components/_tabs.scss: -------------------------------------------------------------------------------- 1 | .tabs { 2 | &.tabs-transparent { 3 | background-color: transparent; 4 | 5 | .tab a, 6 | .tab.disabled a, 7 | .tab.disabled a:hover { 8 | color: rgba(255,255,255,0.7); 9 | } 10 | 11 | .tab a:hover, 12 | .tab a.active { 13 | color: #fff; 14 | } 15 | 16 | .indicator { 17 | background-color: #fff; 18 | } 19 | } 20 | 21 | &.tabs-fixed-width { 22 | display: flex; 23 | 24 | .tab { 25 | -webkit-box-flex: 1; 26 | -webkit-flex-grow: 1; 27 | -ms-flex-positive: 1; 28 | flex-grow: 1; 29 | } 30 | } 31 | 32 | position: relative; 33 | overflow-x: auto; 34 | overflow-y: hidden; 35 | height: 48px; 36 | width: 100%; 37 | background-color: $tabs-bg-color; 38 | margin: 0 auto; 39 | white-space: nowrap; 40 | 41 | .tab { 42 | display: inline-block; 43 | text-align: center; 44 | line-height: 48px; 45 | height: 48px; 46 | padding: 0; 47 | margin: 0; 48 | text-transform: uppercase; 49 | 50 | a { 51 | &:hover, 52 | &.active { 53 | background-color: transparent; 54 | color: $tabs-text-color; 55 | } 56 | 57 | color: rgba($tabs-text-color, .7); 58 | display: block; 59 | width: 100%; 60 | height: 100%; 61 | padding: 0 24px; 62 | font-size: 14px; 63 | text-overflow: ellipsis; 64 | overflow: hidden; 65 | transition: color .28s ease; 66 | } 67 | 68 | &.disabled a, 69 | &.disabled a:hover { 70 | color: rgba($tabs-text-color, .7); 71 | cursor: default; 72 | } 73 | } 74 | .indicator { 75 | position: absolute; 76 | bottom: 0; 77 | height: 2px; 78 | background-color: $tabs-underline-color; 79 | will-change: left, right; 80 | } 81 | } 82 | 83 | // Fixed sideNav hide on smaller 84 | @media #{$medium-and-down} { 85 | .tabs { 86 | display: flex; 87 | 88 | .tab { 89 | -webkit-box-flex: 1; 90 | -webkit-flex-grow: 1; 91 | -ms-flex-positive: 1; 92 | flex-grow: 1; 93 | 94 | a { 95 | padding: 0 12px; 96 | } 97 | } 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /scrummer/static/src/scss/materialize-components/_toast.scss: -------------------------------------------------------------------------------- 1 | #toast-container { 2 | display:block; 3 | position: fixed; 4 | z-index: 10000; 5 | 6 | @media #{$small-and-down} { 7 | min-width: 100%; 8 | bottom: 0%; 9 | } 10 | @media #{$medium-only} { 11 | left: 5%; 12 | bottom: 7%; 13 | max-width: 90%; 14 | } 15 | @media #{$large-and-up} { 16 | top: 10%; 17 | right: 7%; 18 | max-width: 86%; 19 | } 20 | } 21 | 22 | .toast { 23 | @extend .z-depth-1; 24 | border-radius: 2px; 25 | top: 0; 26 | width: auto; 27 | clear: both; 28 | margin-top: 10px; 29 | position: relative; 30 | max-width:100%; 31 | height: auto; 32 | min-height: $toast-height; 33 | line-height: 1.5em; 34 | word-break: break-all; 35 | background-color: $toast-color; 36 | padding: 10px 25px; 37 | font-size: 1.1rem; 38 | font-weight: 300; 39 | color: $toast-text-color; 40 | 41 | display: flex; 42 | align-items: center; 43 | justify-content: space-between; 44 | 45 | .btn, .btn-flat { 46 | margin: 0; 47 | margin-left: 3rem; 48 | } 49 | 50 | &.rounded{ 51 | border-radius: 24px; 52 | } 53 | 54 | @media #{$small-and-down} { 55 | width:100%; 56 | border-radius: 0; 57 | } 58 | @media #{$medium-only} { 59 | float: left; 60 | } 61 | @media #{$large-and-up} { 62 | float: right; 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /scrummer/static/src/scss/materialize-components/_tooltip.scss: -------------------------------------------------------------------------------- 1 | .material-tooltip { 2 | padding: 10px 8px; 3 | font-size: 1rem; 4 | z-index: 2000; 5 | background-color: transparent; 6 | border-radius: 2px; 7 | color: #fff; 8 | min-height: 36px; 9 | line-height: 120%; 10 | opacity: 0; 11 | display: none; 12 | position: absolute; 13 | text-align: center; 14 | max-width: calc(100% - 4px); 15 | overflow: hidden; 16 | left: 0; 17 | top: 0; 18 | pointer-events: none; 19 | } 20 | 21 | .backdrop { 22 | position: absolute; 23 | opacity: 0; 24 | display: none; 25 | height: 7px; 26 | width: 14px; 27 | border-radius: 0 0 50% 50%; 28 | background-color: #323232; 29 | z-index: -1; 30 | transform-origin: 50% 0%; 31 | transform: translate3d(0,0,0); 32 | } 33 | -------------------------------------------------------------------------------- /scrummer/static/src/scss/materialize-components/_typography.scss: -------------------------------------------------------------------------------- 1 | 2 | a { 3 | text-decoration: none; 4 | } 5 | 6 | html{ 7 | line-height: 1.5; 8 | 9 | @media only screen and (min-width: 0) { 10 | font-size: 14px; 11 | } 12 | 13 | @media only screen and (min-width: $medium-screen) { 14 | font-size: 14.5px; 15 | } 16 | 17 | @media only screen and (min-width: $large-screen) { 18 | font-size: 15px; 19 | } 20 | 21 | font-family: "Roboto", sans-serif; 22 | font-weight: normal; 23 | color: $off-black; 24 | } 25 | h1, h2, h3, h4, h5, h6 { 26 | font-weight: 400; 27 | line-height: 1.1; 28 | } 29 | 30 | // Header Styles 31 | h1 a, h2 a, h3 a, h4 a, h5 a, h6 a { font-weight: inherit; } 32 | h1 { font-size: $h1-fontsize; line-height: 110%; margin: ($h1-fontsize / 2) 0 ($h1-fontsize / 2.5) 0;} 33 | h2 { font-size: $h2-fontsize; line-height: 110%; margin: ($h2-fontsize / 2) 0 ($h2-fontsize / 2.5) 0;} 34 | h3 { font-size: $h3-fontsize; line-height: 110%; margin: ($h3-fontsize / 2) 0 ($h3-fontsize / 2.5) 0;} 35 | h4 { font-size: $h4-fontsize; line-height: 110%; margin: ($h4-fontsize / 2) 0 ($h4-fontsize / 2.5) 0;} 36 | h5 { font-size: $h5-fontsize; line-height: 110%; margin: ($h5-fontsize / 2) 0 ($h5-fontsize / 2.5) 0;} 37 | h6 { font-size: $h6-fontsize; line-height: 110%; margin: ($h6-fontsize / 2) 0 ($h6-fontsize / 2.5) 0;} 38 | 39 | // Text Styles 40 | em { font-style: italic; } 41 | strong { font-weight: 500; } 42 | small { font-size: 75%; } 43 | .light { font-weight: 300; } 44 | .thin { font-weight: 200; } 45 | 46 | 47 | .flow-text{ 48 | font-weight: 300; 49 | $i: 0; 50 | @while $i <= $intervals { 51 | @media only screen and (min-width : 360 + ($i * $interval-size)) { 52 | font-size: 1.2rem * (1 + (.02 * $i)); 53 | } 54 | $i: $i + 1; 55 | } 56 | 57 | // Handle below 360px screen 58 | @media only screen and (max-width: 360px) { 59 | font-size: 1.2rem; 60 | } 61 | } -------------------------------------------------------------------------------- /scrummer/static/src/scss/materialize-components/forms/_file-input.scss: -------------------------------------------------------------------------------- 1 | /* File Input 2 | ========================================================================== */ 3 | 4 | .file-field { 5 | position: relative; 6 | 7 | .file-path-wrapper { 8 | overflow: hidden; 9 | padding-left: 10px; 10 | } 11 | 12 | input.file-path { width: 100%; } 13 | 14 | .btn { 15 | float: left; 16 | height: $input-height; 17 | line-height: $input-height; 18 | } 19 | 20 | span { 21 | cursor: pointer; 22 | } 23 | 24 | input[type=file] { 25 | position: absolute; 26 | top: 0; 27 | right: 0; 28 | left: 0; 29 | bottom: 0; 30 | width: 100%; 31 | margin: 0; 32 | padding: 0; 33 | font-size: 20px; 34 | cursor: pointer; 35 | opacity: 0; 36 | filter: alpha(opacity=0); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /scrummer/static/src/scss/materialize-components/forms/_forms.scss: -------------------------------------------------------------------------------- 1 | // Remove Focus Boxes 2 | select:focus { 3 | outline: $select-focus; 4 | } 5 | 6 | button:focus { 7 | outline: none; 8 | background-color: $button-background-focus; 9 | } 10 | 11 | label { 12 | font-size: $label-font-size; 13 | color: $input-border-color; 14 | } 15 | 16 | @import 'input-fields'; 17 | @import 'radio-buttons'; 18 | @import 'checkboxes'; 19 | @import 'switches'; 20 | @import 'select'; 21 | @import 'file-input'; 22 | @import 'range'; 23 | -------------------------------------------------------------------------------- /scrummer/static/src/scss/materialize-components/forms/_select.scss: -------------------------------------------------------------------------------- 1 | /* Select Field 2 | ========================================================================== */ 3 | 4 | select { display: none; } 5 | select.browser-default { display: block; } 6 | 7 | select { 8 | background-color: $select-background; 9 | width: 100%; 10 | padding: $select-padding; 11 | border: $select-border; 12 | border-radius: $select-radius; 13 | height: $input-height; 14 | } 15 | 16 | .select-label { 17 | position: absolute; 18 | } 19 | 20 | .select-wrapper { 21 | position: relative; 22 | 23 | input.select-dropdown { 24 | position: relative; 25 | cursor: pointer; 26 | background-color: transparent; 27 | border: none; 28 | border-bottom: $input-border; 29 | outline: none; 30 | height: $input-height; 31 | line-height: $input-height; 32 | width: 100%; 33 | font-size: $input-font-size; 34 | margin: $input-margin; 35 | padding: 0; 36 | display: block; 37 | } 38 | 39 | span.caret { 40 | color: initial; 41 | position: absolute; 42 | right: 0; 43 | top: 0; 44 | bottom: 0; 45 | height: 10px; 46 | margin: auto 0; 47 | font-size: 10px; 48 | line-height: 10px; 49 | 50 | &.disabled { 51 | color: $input-disabled-color; 52 | } 53 | } 54 | 55 | & + label { 56 | position: absolute; 57 | top: -14px; 58 | font-size: $label-font-size; 59 | } 60 | } 61 | 62 | // Disabled styles 63 | select:disabled { 64 | color: rgba(0,0,0,.3); 65 | } 66 | 67 | .select-wrapper input.select-dropdown:disabled { 68 | color: rgba(0,0,0,.3); 69 | cursor: default; 70 | -webkit-user-select: none; /* webkit (safari, chrome) browsers */ 71 | -moz-user-select: none; /* mozilla browsers */ 72 | -ms-user-select: none; /* IE10+ */ 73 | border-bottom: 1px solid rgba(0,0,0,.3); 74 | } 75 | 76 | .select-wrapper i { 77 | color: $select-disabled-color; 78 | } 79 | 80 | .select-dropdown li.disabled, 81 | .select-dropdown li.disabled > span, 82 | .select-dropdown li.optgroup { 83 | color: $select-disabled-color; 84 | background-color: transparent; 85 | } 86 | 87 | // Prefix Icons 88 | .prefix ~ .select-wrapper { 89 | margin-left: 3rem; 90 | width: 92%; 91 | width: calc(100% - 3rem); 92 | } 93 | 94 | .prefix ~ label { margin-left: 3rem; } 95 | 96 | // Icons 97 | .select-dropdown li { 98 | img { 99 | height: $dropdown-item-height - 10; 100 | width: $dropdown-item-height - 10; 101 | margin: 5px 15px; 102 | float: right; 103 | } 104 | } 105 | 106 | // Optgroup styles 107 | .select-dropdown li.optgroup { 108 | border-top: 1px solid $dropdown-hover-bg-color; 109 | 110 | &.selected > span { 111 | color: rgba(0, 0, 0, .7); 112 | } 113 | 114 | & > span { 115 | color: rgba(0, 0, 0, .4); 116 | } 117 | 118 | & ~ li.optgroup-option { 119 | padding-left: 1rem; 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /scrummer/static/src/scss/materialize-components/forms/_switches.scss: -------------------------------------------------------------------------------- 1 | /* Switch 2 | ========================================================================== */ 3 | 4 | .switch, 5 | .switch * { 6 | -webkit-user-select: none; 7 | -moz-user-select: none; 8 | -khtml-user-select: none; 9 | -ms-user-select: none; 10 | } 11 | 12 | .switch label { 13 | cursor: pointer; 14 | } 15 | 16 | .switch label input[type=checkbox] { 17 | opacity: 0; 18 | width: 0; 19 | height: 0; 20 | 21 | &:checked + .lever { 22 | background-color: $switch-checked-lever-bg; 23 | 24 | &:after { 25 | background-color: $switch-bg-color; 26 | left: 24px; 27 | } 28 | } 29 | } 30 | 31 | .switch label .lever { 32 | content: ""; 33 | display: inline-block; 34 | position: relative; 35 | width: 40px; 36 | height: 15px; 37 | background-color: $switch-unchecked-lever-bg; 38 | border-radius: $switch-radius; 39 | margin-right: 10px; 40 | transition: background 0.3s ease; 41 | vertical-align: middle; 42 | margin: 0 16px; 43 | 44 | &:after { 45 | content: ""; 46 | position: absolute; 47 | display: inline-block; 48 | width: 21px; 49 | height: 21px; 50 | background-color: $switch-unchecked-bg; 51 | border-radius: 21px; 52 | box-shadow: 0 1px 3px 1px rgba(0,0,0,.4); 53 | left: -5px; 54 | top: -3px; 55 | transition: left 0.3s ease, background .3s ease, box-shadow 0.1s ease; 56 | } 57 | } 58 | 59 | // Switch active style 60 | input[type=checkbox]:checked:not(:disabled) ~ .lever:active::after, 61 | input[type=checkbox]:checked:not(:disabled).tabbed:focus ~ .lever::after { 62 | box-shadow: 0 1px 3px 1px rgba(0,0,0,.4), 0 0 0 15px transparentize($switch-bg-color, .9); 63 | } 64 | 65 | input[type=checkbox]:not(:disabled) ~ .lever:active:after, 66 | input[type=checkbox]:not(:disabled).tabbed:focus ~ .lever::after { 67 | box-shadow: 0 1px 3px 1px rgba(0,0,0,.4), 0 0 0 15px rgba(0, 0, 0, .08); 68 | } 69 | 70 | // Disabled Styles 71 | .switch input[type=checkbox][disabled] + .lever { 72 | cursor: default; 73 | } 74 | 75 | .switch label input[type=checkbox][disabled] + .lever:after, 76 | .switch label input[type=checkbox][disabled]:checked + .lever:after { 77 | background-color: $input-disabled-solid-color; 78 | } 79 | -------------------------------------------------------------------------------- /scrummer/static/src/scss/materialize.scss: -------------------------------------------------------------------------------- 1 | @charset "UTF-8"; 2 | 3 | // Overrides 4 | @import "components/materialize_overrides"; 5 | 6 | // Mixins 7 | // @import "materialize-components/prefixer"; 8 | @import "materialize-components/mixins"; 9 | @import "materialize-components/color"; 10 | 11 | // Variables; 12 | @import "materialize-components/variables"; 13 | 14 | // Reset 15 | @import "materialize-components/normalize"; 16 | 17 | // materialize-components 18 | @import "materialize-components/global"; 19 | @import "materialize-components/icons-material-design"; 20 | @import "materialize-components/grid"; 21 | @import "materialize-components/navbar"; 22 | @import "materialize-components/roboto"; 23 | @import "materialize-components/typography"; 24 | @import "materialize-components/cards"; 25 | @import "materialize-components/toast"; 26 | @import "materialize-components/tabs"; 27 | @import "materialize-components/tooltip"; 28 | @import "materialize-components/buttons"; 29 | @import "materialize-components/dropdown"; 30 | @import "materialize-components/waves"; 31 | @import "materialize-components/modal"; 32 | @import "materialize-components/collapsible"; 33 | @import "materialize-components/chips"; 34 | @import "materialize-components/materialbox"; 35 | @import "materialize-components/forms/forms"; 36 | @import "materialize-components/table_of_contents"; 37 | @import "materialize-components/sideNav"; 38 | @import "materialize-components/preloader"; 39 | @import "materialize-components/slider"; 40 | @import "materialize-components/carousel"; 41 | @import "materialize-components/date_picker/default"; 42 | @import "materialize-components/date_picker/default.date"; 43 | @import "materialize-components/date_picker/default.time"; 44 | -------------------------------------------------------------------------------- /scrummer/static/src/xml/aside.left.menu.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 16 | 17 | 18 | 19 | 20 |
  • 21 | 22 | 23 | 24 | 25 |
  • 26 |
    27 | 28 |
  • 29 | 30 | 31 | 32 | 33 |
  • 34 |
    35 | 36 |
  • 37 | 48 |
  • 49 |
    50 | 51 |
  • 52 | 53 |
  • 54 |
    55 |
    56 | -------------------------------------------------------------------------------- /scrummer/static/src/xml/layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 |
    9 | 10 | 11 |
    12 |
    13 | 14 |
    15 |
    16 |
    17 |

    Access denied

    18 | 19 |
    20 |

    21 |
    22 | back to odoo 23 |
    24 |
    25 |
    26 |
    27 |
    28 | -------------------------------------------------------------------------------- /scrummer/static/src/xml/page.board.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 |
    9 | 10 | 11 |
    12 |
    13 |
    14 | -------------------------------------------------------------------------------- /scrummer/static/src/xml/page.dashboard.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 |
    9 |
    10 |
    11 |
    12 |
    13 |
    14 |
    15 |
    16 |

    Projects

    17 |
    18 |
    19 | 20 |
    21 |
    22 |
    23 |
    24 |
    25 |
    26 |
    27 |
    28 |
    29 |
    30 | 31 | 32 |
    33 |
    34 |
    35 |

    Assigned to me

    36 |

    37 |
    38 |
    39 | 44 |
    45 |
    46 |
    47 |
    48 |
    49 |
    50 |
    51 |
    52 |
    53 |
    54 |
    55 |
    56 |
    57 |
    58 |
    59 |
    60 |
    61 | 62 |
    Your team does not have any projects assigned. You can create/assign project in odoo project management module.
    63 |
    64 | 65 | -------------------------------------------------------------------------------- /scrummer/static/src/xml/scrummer.board_chooser.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 |
  • 9 | 10 | 11 | 12 |
  • 13 | 14 |
    15 | 16 |
  • 17 |
    18 | 20 |
    21 |
    22 | All project 23 | 24 | 25 | 26 |
    27 |
  • 28 |
    29 |
    30 | -------------------------------------------------------------------------------- /scrummer/static/src/xml/scrummer.project_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 |
  • 9 |
    10 |
    11 | 12 |
    13 | 14 |
    15 |
    16 |
    17 | 18 | 19 | 20 |
    21 |
    22 |
  • 23 |
    24 |
    25 | -------------------------------------------------------------------------------- /scrummer/static/src/xml/scrummer.task.links.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /scrummer/static/src/xml/sub-header.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 |
    10 |
    11 |
    12 |
    13 |
    14 | 15 | 16 | -------------------------------------------------------------------------------- /scrummer/static/src/xml/view-common.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 |
    11 | 12 | 13 | 14 | 23 |
    24 | 25 |
    26 |
    27 |
    28 | -------------------------------------------------------------------------------- /scrummer/static/src/xml/view-manager.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 |
    10 | 11 |
    12 | 13 |
    14 |
    15 |
    16 | 17 |
    18 | 19 |
    20 |
    21 | -------------------------------------------------------------------------------- /scrummer/static/src/xml/view.backlog.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 |
    10 |
    11 |
    12 |
    13 |
    14 |
      15 |
    16 |
    17 |
    18 | 19 |
    20 |
    21 |
    22 | 23 | 24 | 25 |
    26 | 27 | 28 |
      29 |
    • 30 | Backlog 31 | 32 | 33 | 34 |
      35 |
      36 |
      37 |
      38 |
    • 39 |
      40 |
      41 |
      42 |
      43 |
      44 |
      45 |
      46 |
      47 |
      48 |
      49 |
      50 |
      51 |
      52 |
    53 |
    54 | 55 | -------------------------------------------------------------------------------- /scrummer/static/src/xml/widget.attachments.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 |
    11 | 12 |
    13 |
    Drop files here...
    14 | or Choose files 15 |
    16 |
    17 |
    18 | 19 | 20 | 21 | 22 |
    23 |
    24 |
    25 |
    26 | 28 |
    29 |
    30 | 31 | 32 | 33 |
    34 |
    35 |
    36 |
    37 | 38 |
    39 | 41 | 42 | 43 | 44 |
    45 |
    46 |
    47 |
    48 |
    49 |
    50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /scrummer/static/src/xml/widget.many2one.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 |
    10 |
    11 | 12 | 13 | 14 | 15 |
    17 |
    18 |
    19 | 20 |
    21 | -------------------------------------------------------------------------------- /scrummer/views/menu.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | Scrummer 9 | /scrummer/web 10 | self 11 | 12 | 13 | 14 | 19 | 20 | -------------------------------------------------------------------------------- /scrummer/views/project_agile_team_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | project_agile_team_form 9 | project.agile.team 10 | 11 | 12 |
    13 |
    16 |
    17 |
    18 |
    19 | -------------------------------------------------------------------------------- /scrummer/views/project_project_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | project.project.form 9 | project.project 10 | 11 | 12 | 13 | 14 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /scrummer/views/project_type_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | project.type.form 9 | project.type 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /scrummer_git/README.rst: -------------------------------------------------------------------------------- 1 | doc/index.rst -------------------------------------------------------------------------------- /scrummer_git/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 - 2018 Modoolar 2 | # License LGPLv3.0 or later (https://www.gnu.org/licenses/lgpl-3.0.en.html). 3 | from . import models 4 | from . import controllers 5 | -------------------------------------------------------------------------------- /scrummer_git/__manifest__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 - 2018 Modoolar 2 | # License LGPLv3.0 or later (https://www.gnu.org/licenses/lgpl-3.0.en.html). 3 | 4 | { 5 | "name": "Scrummer Git", 6 | "summary": "Enables you to integrate project_git with Scrummer", 7 | "category": "Project", 8 | "version": "11.0.1.0.0", 9 | "license": "LGPL-3", 10 | "author": "Modoolar", 11 | "website": "https://www.modoolar.com/", 12 | "images": ["static/description/banner.png"], 13 | "depends": [ 14 | "project_git", 15 | "scrummer" 16 | ], 17 | "data": [ 18 | "views/scrummer_git.xml" 19 | ], 20 | 21 | "demo": [], 22 | "qweb": [ 23 | "static/src/xml/scrummer_git.xml", 24 | ], 25 | "application": False 26 | } 27 | -------------------------------------------------------------------------------- /scrummer_git/controllers/__init__.py: -------------------------------------------------------------------------------- 1 | from . import main 2 | -------------------------------------------------------------------------------- /scrummer_git/controllers/main.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 - 2018 Modoolar 2 | # License LGPLv3.0 or later (https://www.gnu.org/licenses/lgpl-3.0.en.html). 3 | 4 | from odoo import http 5 | from odoo.addons.scrummer.controllers import main 6 | 7 | 8 | class ScrummerController(main.ScrummerController): 9 | @http.route([ 10 | '/scrummer/git//commits' 11 | ], type='json', auth='user') 12 | def load_commits(self, task): 13 | return task.commit_ids.format_commits() 14 | -------------------------------------------------------------------------------- /scrummer_git/doc/index.rst: -------------------------------------------------------------------------------- 1 | .. image:: https://www.gnu.org/graphics/lgplv3-147x51.png 2 | :target: https://www.gnu.org/licenses/lgpl-3.0.en.html 3 | :alt: License: LGPL-v3 4 | 5 | ============ 6 | Scrummer Git 7 | ============ 8 | 9 | This module integrates ``project_git`` and ``scrummer`` modules by 10 | displaying commits on task details view under section ``Development`` 11 | 12 | 13 | Usage 14 | ===== 15 | 16 | In order to see registered commits one needs to open a task in Scrummer 17 | and look for "Development" section on the form view. 18 | 19 | 20 | Credits 21 | ======= 22 | 23 | 24 | Contributors 25 | ------------ 26 | 27 | * Sladjan Kantar 28 | * Aleksandar Gajić 29 | * Miroslav Nikolić 30 | 31 | 32 | Maintainer 33 | ---------- 34 | 35 | .. image:: https://www.modoolar.com/modoolar/static/modoolar-logo.png 36 | :alt: Modoolar 37 | :target: https://modoolar.com 38 | 39 | This module is maintained by Modoolar. 40 | 41 | :: 42 | 43 | As Odoo Gold partner, our company is specialized in Odoo ERP customization and business solutions development. 44 | Beside that, we build cool apps on top of Odoo platform. 45 | 46 | To contribute to this module, please visit https://modoolar.com 47 | -------------------------------------------------------------------------------- /scrummer_git/models/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 - 2018 Modoolar 2 | # License LGPLv3.0 or later (https://www.gnu.org/licenses/lgpl-3.0.en.html). 3 | from . import project_task 4 | -------------------------------------------------------------------------------- /scrummer_git/models/project_task.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 - 2018 Modoolar 2 | # License LGPLv3.0 or later (https://www.gnu.org/licenses/lgpl-3.0.en.html). 3 | 4 | from odoo import models, fields, api 5 | 6 | 7 | class ProjectTask(models.Model): 8 | _inherit = "project.task" 9 | 10 | commit_ids = fields.Many2many( 11 | comodel_name="project.git.commit", 12 | scrummer=True, 13 | ) 14 | 15 | 16 | class GitCommit(models.Model): 17 | _inherit = 'project.git.commit' 18 | 19 | @api.multi 20 | def format_commits(self): 21 | commits = [] 22 | 23 | for commit in self: 24 | commits.append(commit.format_commit()) 25 | 26 | return commits 27 | 28 | @api.multi 29 | def format_commit(self): 30 | self.ensure_one() 31 | return { 32 | 'id': self.id, 33 | 'date': self.date, 34 | 'name': self.name, 35 | 'url': self.url, 36 | 'avatar': self.avatar, 37 | 'message': self.message, 38 | 'message_short': self.message_short, 39 | 'author': { 40 | 'id': self.author_id.id, 41 | 'name': self.author_id.name, 42 | 'avatar': self.author_id.avatar, 43 | 'username': self.author_id.username, 44 | }, 45 | 'branch': { 46 | 'id': self.branch_id.id, 47 | 'name': self.branch_id.name, 48 | 'url': self.branch_id.url, 49 | }, 50 | 'repository': { 51 | 'id': self.repository_id.id, 52 | 'name': self.repository_id.name, 53 | 'url': self.repository_id.url, 54 | 'avatar': self.repository_id.image_type, 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /scrummer_git/static/description/banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer_git/static/description/banner.png -------------------------------------------------------------------------------- /scrummer_git/static/description/git_commit.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer_git/static/description/git_commit.gif -------------------------------------------------------------------------------- /scrummer_git/static/description/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/modoolar/scrummer/2ba08662342a120967622ba7b85b6c4718eebaf5/scrummer_git/static/description/icon.png -------------------------------------------------------------------------------- /scrummer_git/static/description/index.html: -------------------------------------------------------------------------------- 1 |
    2 |
    3 |
    4 |

    Scrummer Git

    5 |

    Overview

    6 |

    7 | This module integrates Project Git and Scrummer modules by 8 | displaying commits on task details view under section Development 9 |

    10 |
    11 |
    12 |
    13 |
    14 |
    15 |
    16 |

    Usage

    17 |

    18 | In order to see registered commits one needs to open a task in Scrummer 19 | and look for "Development" section on the form view. 20 |

    21 |
    22 | Scrummer Git commit 23 |
    24 |
    25 |
    26 |
    27 |
    28 |
    29 |
    30 |

    31 | MODOOLAR 32 |

    33 |

    34 | With extensive experience in implementing Odoo based applications, we can offer you a custom-tailored 35 | solution that perfectly meets your needs, and spanning through CRM, Sales management, Accounting, HR 36 | management, Project management, Document management, eCommerce, Webshop, and many more. With our 37 | hands-on expertise, we can help you get exclusive tailor-made apps for your unique business needs. Our 38 | knowledge extends beyond our tech-stack expertise - we follow startup trends, so that we can provide 39 | guidance to our clients regarding the business process, legal issues and marketing strategies. 40 |

    41 |
    42 | 43 | Contact us 44 |
    45 |
    46 |
    47 |
    48 | 49 | 50 | -------------------------------------------------------------------------------- /scrummer_git/static/src/js/scrummer_git.js: -------------------------------------------------------------------------------- 1 | // Copyright 2017 - 2018 Modoolar 2 | // License LGPLv3.0 or later (https://www.gnu.org/licenses/lgpl-3.0.en.html). 3 | 4 | odoo.define("scrummer_git", function (require) { 5 | 6 | const TaskWidget = require('scrummer.widget.task').TaskWidget; 7 | const ModalWidget = require('scrummer.widget.modal').ModalWidget; 8 | const session = require('web.session'); 9 | 10 | const CommitsModal = ModalWidget.extend({ 11 | template: "scrummer.widget.modal.show_commits", 12 | init(parent, options) { 13 | this._super(parent, options); 14 | this._require_prop("commits"); 15 | }, 16 | addedToDOM() { 17 | this._super(); 18 | this.$('.tooltipped').tooltip(); 19 | } 20 | }); 21 | 22 | TaskWidget.include({ 23 | start() { 24 | $("#show_commits").click(() => { 25 | session.rpc(`/scrummer/git/${this.id}/commits`).then((commits) => { 26 | const modal = new CommitsModal(this, {commits}); 27 | modal.appendTo($("body")); 28 | }); 29 | 30 | }); 31 | 32 | return this._super(); 33 | } 34 | }); 35 | 36 | return { 37 | CommitsModal 38 | }; 39 | }); 40 | -------------------------------------------------------------------------------- /scrummer_git/views/scrummer_git.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 |