From dfd500097e8619cc1d24dd4d90a45ffed6853d3e Mon Sep 17 00:00:00 2001 From: Oliver Date: Mon, 13 Sep 2021 20:01:36 +1000 Subject: [PATCH 01/12] Update contributing.md (cherry picked from commit 398842d6e57b79adc650f8c29eadf0142ec08157) --- CONTRIBUTING.md | 96 ++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 88 insertions(+), 8 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4af3fc5386..0677e61de4 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,22 +1,102 @@ -Contributions to InvenTree are welcomed - please follow the guidelines below. +Please read the contribution guidelines below, before submitting your first pull request to the InvenTree codebase. -## Feature Branches +## Branches and Versioning -No pushing to master! New featues must be submitted in a separate branch (one branch per feature). +InvenTree roughly follow the [GitLab flow](https://docs.gitlab.com/ee/topics/gitlab_flow.html) branching style, to allow simple management of multiple tagged releases, short-lived branches, and development on the main branch. -## Include Migration Files +### Version Numbering + +InvenTree version numbering follows the [semantic versioning](https://semver.org/) specification. + +### Master Branch + +The HEAD of the "main" or "master" branch of InvenTree represents the current "latest" state of code development. + +- All feature branches are merged into master +- All bug fixes are merged into master + +**No pushing to master:** New featues must be submitted as a pull request from a separate branch (one branch per feature). + +#### Feature Branches + +Feature branches should be branched *from* the *master* branch. + +- One major feature per branch / pull request +- Feature pull requests are merged back *into* the master branch +- Features *may* also be merged into a release candidate branch + +### Stable Branch + +The HEAD of the "stable" branch represents the latest stable release code. + +- Versioned releases are merged into the "stable" branch +- Bug fix branches are made *from* the "stable" branch + +#### Release Candidate Branches + +- Release candidate branches are made from master, and merged into stable. +- RC branches are targetted at a major/minor version e.g. "0.5" +- When a release candidate branch is merged into *stable*, the release is tagged + +#### Bugfix Branches + +- If a bug is discovered in a tagged release version of InvenTree, a "bugfix" or "hotfix" branch should be made *from* that tagged release +- When approved, the branch is merged back *into* stable, with an incremented PATCH number (e.g. 0.4.1 -> 0.4.2) +- The bugfix *must* also be cherry picked into the *master* branch. + +## Migration Files Any required migration files **must** be included in the commit, or the pull-request will be rejected. If you change the underlying database schema, make sure you run `invoke migrate` and commit the migration files before submitting the PR. +*Note: A github action checks for unstaged migration files and will reject the PR if it finds any!* -## Testing +## Unit Testing -Any new code should be covered by unit tests - a submitted PR may not be accepted if the code coverage is decreased. +Any new code should be covered by unit tests - a submitted PR may not be accepted if the code coverage for any new features is insufficient, or the overall code coverage is decreased. + +The InvenTree code base makes use of [GitHub actions](https://github.com/features/actions) to run a suite of automated tests against the code base every time a new pull request is received. These actions include (but are not limited to): + +- Checking Python and Javascript code against standard style guides +- Running unit test suite +- Automated building and pushing of docker images +- Generating translation files + +The various github actions can be found in the `./github/workflows` directory + +## Code Style + +Sumbitted Python code is automatically checked against PEP style guidelines. Locally you can run `invoke style` to ensure the style checks will pass, before submitting the PR. ## Documentation New features or updates to existing features should be accompanied by user documentation. A PR with associated documentation should link to the matching PR at https://github.com/inventree/inventree-docs/ -## Code Style +## Translations -Sumbitted Python code is automatically checked against PEP style guidelines. Locally you can run `invoke style` to ensure the style checks will pass, before submitting the PR. +Any user-facing strings *must* be passed through the translation engine. + +- InvenTree code is written in English +- User translatable strings are provided in English as the primary language +- Secondary language translations are provided [via Crowdin](https://crowdin.com/project/inventree) + +*Note: Translation files are updated via GitHub actions - you do not need to compile translations files before submitting a pull request!* + +### Python Code + +For strings exposed via Python code, use the following format: + +```python +from django.utils.translation import ugettext_lazy as _ + +user_facing_string = _('This string will be exposed to the translation engine!') +``` + +### Templated Strings + +HTML and javascript files are passed through the django templating engine. Translatable strings are implemented as follows: + +```html +{% load i18n %} + +{% trans "This string will be translated" %} - this string will not! +``` \ No newline at end of file From c890a4a6d00ec5a909bd267e713744533aeb8674 Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 13 Sep 2021 23:18:44 +0200 Subject: [PATCH 02/12] only add button per name once --- InvenTree/templates/js/translated/modals.js | 25 +++++++++++++++------ 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/InvenTree/templates/js/translated/modals.js b/InvenTree/templates/js/translated/modals.js index 5195c67b46..2a90a54324 100644 --- a/InvenTree/templates/js/translated/modals.js +++ b/InvenTree/templates/js/translated/modals.js @@ -793,14 +793,25 @@ function attachSecondaries(modal, secondaries) { function insertActionButton(modal, options) { /* Insert a custom submission button */ - var html = ` - - - `; + var element = $(modal).find('#modal-footer-buttons'); - $(modal).find('#modal-footer-buttons').append(html); + // check if button already present + var already_present = false; + for(var child=element[0].firstElementChild; child; child=child.nextElementSibling){ + if (item.firstElementChild.name == options.name) { + already_present = true; + } + } + + if (already_present == false) { + var html = ` + + + `; + element.append(html); + } } function attachButtons(modal, buttons) { From 847fb62ab55ee0c7b95b52d2f37545930c5df546 Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 13 Sep 2021 23:25:13 +0200 Subject: [PATCH 03/12] js style --- InvenTree/templates/js/translated/modals.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/InvenTree/templates/js/translated/modals.js b/InvenTree/templates/js/translated/modals.js index 2a90a54324..96e41fd6ec 100644 --- a/InvenTree/templates/js/translated/modals.js +++ b/InvenTree/templates/js/translated/modals.js @@ -797,7 +797,7 @@ function insertActionButton(modal, options) { // check if button already present var already_present = false; - for(var child=element[0].firstElementChild; child; child=child.nextElementSibling){ + for (var child=element[0].firstElementChild; child; child=child.nextElementSibling) { if (item.firstElementChild.name == options.name) { already_present = true; } From 5bd5c61b9db99a9017b040c7d7271d65d1cef670 Mon Sep 17 00:00:00 2001 From: Oliver Date: Tue, 14 Sep 2021 10:43:40 +1000 Subject: [PATCH 04/12] Fix callback for test template table --- InvenTree/part/templates/part/detail.html | 42 ++++------------------- InvenTree/templates/js/translated/part.js | 38 +++++++++++++++++++- 2 files changed, 43 insertions(+), 37 deletions(-) diff --git a/InvenTree/part/templates/part/detail.html b/InvenTree/part/templates/part/detail.html index 6bad2bbbdf..d240b53601 100644 --- a/InvenTree/part/templates/part/detail.html +++ b/InvenTree/part/templates/part/detail.html @@ -667,6 +667,8 @@ }); onPanelLoad("test-templates", function() { + + // Load test template table loadPartTestTemplateTable( $("#test-template-table"), { @@ -677,11 +679,8 @@ } ); + // Callback for "add test template" button $("#add-test-template").click(function() { - - function reloadTestTemplateTable() { - $("#test-template-table").bootstrapTable("refresh"); - } constructForm('{% url "api-part-test-template-list" %}', { method: 'POST', @@ -697,39 +696,10 @@ } }, title: '{% trans "Add Test Result Template" %}', - onSuccess: reloadTestTemplateTable + onSuccess: function() { + $("#test-template-table").bootstrapTable("refresh"); + } }); - - $("#test-template-table").on('click', '.button-test-edit', function() { - var pk = $(this).attr('pk'); - - var url = `/api/part/test-template/${pk}/`; - - constructForm(url, { - fields: { - test_name: {}, - description: {}, - required: {}, - requires_value: {}, - requires_attachment: {}, - }, - title: '{% trans "Edit Test Result Template" %}', - onSuccess: reloadTestTemplateTable, - }); - }); - - $("#test-template-table").on('click', '.button-test-delete', function() { - var pk = $(this).attr('pk'); - - var url = `/api/part/test-template/${pk}/`; - - constructForm(url, { - method: 'DELETE', - title: '{% trans "Delete Test Result Template" %}', - onSuccess: reloadTestTemplateTable, - }); - }); - }); }); diff --git a/InvenTree/templates/js/translated/part.js b/InvenTree/templates/js/translated/part.js index 1ccf8157b6..8cae5d249b 100644 --- a/InvenTree/templates/js/translated/part.js +++ b/InvenTree/templates/js/translated/part.js @@ -1252,7 +1252,43 @@ function loadPartTestTemplateTable(table, options) { } } } - ] + ], + onPostBody: function() { + + table.find('.button-test-edit').click(function() { + var pk = $(this).attr('pk'); + + var url = `/api/part/test-template/${pk}/`; + + constructForm(url, { + fields: { + test_name: {}, + description: {}, + required: {}, + requires_value: {}, + requires_attachment: {}, + }, + title: '{% trans "Edit Test Result Template" %}', + onSuccess: function() { + table.bootstrapTable('refresh'); + }, + }); + }); + + table.find('.button-test-delete').click(function() { + var pk = $(this).attr('pk'); + + var url = `/api/part/test-template/${pk}/`; + + constructForm(url, { + method: 'DELETE', + title: '{% trans "Delete Test Result Template" %}', + onSuccess: function() { + table.bootstrapTable('refresh'); + }, + }); + }); + } }); } From 11cc0c7cedb5ecc11517ee504dc2851f08493bfb Mon Sep 17 00:00:00 2001 From: Oliver Date: Fri, 17 Sep 2021 20:53:18 +1000 Subject: [PATCH 05/12] Adds a test for non-standard characters via API --- InvenTree/part/test_api.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/InvenTree/part/test_api.py b/InvenTree/part/test_api.py index ebef21b84b..8150461b38 100644 --- a/InvenTree/part/test_api.py +++ b/InvenTree/part/test_api.py @@ -588,6 +588,21 @@ class PartAPITest(InvenTreeAPITestCase): self.assertEqual(new_part.supplier_parts.count(), 1) self.assertEqual(new_part.manufacturer_parts.count(), 1) + def test_strange_chars(self): + """ + Test that non-standard ASCII chars are accepted + """ + + url = reverse('api-part-list') + + data = { + "name": "Kaltgerätestecker", + "description": "Gerät", + "category": 2 + } + + response = self.post(url, data, expected_code=201) + class PartDetailTests(InvenTreeAPITestCase): """ From e7963f8a851d998791d932b569bf84dcf72fdc8b Mon Sep 17 00:00:00 2001 From: Oliver Date: Fri, 17 Sep 2021 21:06:07 +1000 Subject: [PATCH 06/12] test fixes --- InvenTree/part/test_api.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/InvenTree/part/test_api.py b/InvenTree/part/test_api.py index 8150461b38..660b573e33 100644 --- a/InvenTree/part/test_api.py +++ b/InvenTree/part/test_api.py @@ -595,14 +595,20 @@ class PartAPITest(InvenTreeAPITestCase): url = reverse('api-part-list') + name = "Kaltgerätestecker" + description = "Gerät" + data = { - "name": "Kaltgerätestecker", - "description": "Gerät", + "name": name, + "description": description, "category": 2 } response = self.post(url, data, expected_code=201) + self.assertEqual(response.data['name'], name) + self.assertEqual(response.data['description'], description) + class PartDetailTests(InvenTreeAPITestCase): """ From 8d6d16c07bab19859120723f3395b52931784f26 Mon Sep 17 00:00:00 2001 From: Oliver Date: Fri, 17 Sep 2021 22:13:13 +1000 Subject: [PATCH 07/12] Add template for app issues --- .github/ISSUE_TEMPLATE/app_issue.md | 30 +++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/app_issue.md diff --git a/.github/ISSUE_TEMPLATE/app_issue.md b/.github/ISSUE_TEMPLATE/app_issue.md new file mode 100644 index 0000000000..e71861394c --- /dev/null +++ b/.github/ISSUE_TEMPLATE/app_issue.md @@ -0,0 +1,30 @@ +--- +name: App issue +about: Report a bug or issue with the InvenTree app +title: "[APP] Enter bug description" +labels: bug, app +assignees: '' + +--- + +**Describe the bug** +A clear and concise description of the bug or issue + +**To Reproduce** +Steps to reproduce the behavior: + +1. Go to ... +2. Select ... +3. ... + +**Expected Behavior** +A clear and concise description of what you expected to happen + +**Screenshots** +If applicable, add screenshots to help explain your problem + +**Version Information** + +- App platform: *Select iOS or Android* +- App version: *Enter app version* +- Server version: *Enter server version* From 5443beef65a593d57401e35b6fcac8d9ad079645 Mon Sep 17 00:00:00 2001 From: Oliver Date: Mon, 20 Sep 2021 17:15:31 +1000 Subject: [PATCH 08/12] Improve 'health status' warnings - Don't show error message if only non-critical warnings present --- InvenTree/InvenTree/context.py | 7 ++++++- InvenTree/templates/navbar.html | 10 +--------- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/InvenTree/InvenTree/context.py b/InvenTree/InvenTree/context.py index 3e1f98ffc2..bd68a0182f 100644 --- a/InvenTree/InvenTree/context.py +++ b/InvenTree/InvenTree/context.py @@ -36,9 +36,14 @@ def health_status(request): 'email_configured': InvenTree.status.is_email_configured(), } + # The following keys are required to denote system health + health_keys = [ + 'django_q_running', + ] + all_healthy = True - for k in status.keys(): + for k in health_keys: if status[k] is not True: all_healthy = False diff --git a/InvenTree/templates/navbar.html b/InvenTree/templates/navbar.html index b109bd9daf..6946b69bce 100644 --- a/InvenTree/templates/navbar.html +++ b/InvenTree/templates/navbar.html @@ -71,11 +71,7 @@ {% if user.is_staff %} {% if not system_healthy %} - {% if not django_q_running %} - {% else %} - - {% endif %} {% elif not up_to_date %} {% endif %} @@ -96,11 +92,7 @@ {% if system_healthy or not user.is_staff %} {% else %} - {% if not django_q_running %} - - {% else %} - - {% endif %} + {% endif %} {% trans "System Information" %} From c1a827819c3a10d18383d25041c8eefc74bc65eb Mon Sep 17 00:00:00 2001 From: rocheparadox Date: Mon, 20 Sep 2021 17:00:45 +0530 Subject: [PATCH 09/12] css for part to occupy full height - fix for bug Inventree#1848 --- InvenTree/InvenTree/static/css/inventree.css | 4 ++++ InvenTree/templates/js/translated/part.js | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/InvenTree/InvenTree/static/css/inventree.css b/InvenTree/InvenTree/static/css/inventree.css index 9ed478ea90..585c0b3825 100644 --- a/InvenTree/InvenTree/static/css/inventree.css +++ b/InvenTree/InvenTree/static/css/inventree.css @@ -1061,3 +1061,7 @@ input[type='number']{ .search-menu .ui-menu-item { margin-top: 0.5rem; } + +.product-card-panel{ + height: 100%; +} diff --git a/InvenTree/templates/js/translated/part.js b/InvenTree/templates/js/translated/part.js index 8cae5d249b..9abbd2a0b9 100644 --- a/InvenTree/templates/js/translated/part.js +++ b/InvenTree/templates/js/translated/part.js @@ -768,7 +768,7 @@ function partGridTile(part) { var html = `
-
+
`; } html += partGridTile(row); From 1d85ccd543f917bd21ce106e0e00dee8082a1090 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 22 Sep 2021 17:46:34 +0000 Subject: [PATCH 10/12] Build(deps): Bump django from 3.2.4 to 3.2.5 Bumps [django](https://github.com/django/django) from 3.2.4 to 3.2.5. - [Release notes](https://github.com/django/django/releases) - [Commits](https://github.com/django/django/compare/3.2.4...3.2.5) --- updated-dependencies: - dependency-name: django dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index d7c5a01ee4..68eb6797e5 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ # Django framework -Django==3.2.4 # Django package +Django==3.2.5 # Django package gunicorn>=20.1.0 # Gunicorn web server pillow==8.3.2 # Image manipulation From d2b9993e96eb6658be2060490630033bb89a4404 Mon Sep 17 00:00:00 2001 From: Oliver Date: Fri, 24 Sep 2021 12:04:25 +1000 Subject: [PATCH 11/12] Fix form filters for "default_supplier" --- InvenTree/templates/js/translated/part.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/InvenTree/templates/js/translated/part.js b/InvenTree/templates/js/translated/part.js index 9abbd2a0b9..e74b6fd743 100644 --- a/InvenTree/templates/js/translated/part.js +++ b/InvenTree/templates/js/translated/part.js @@ -94,7 +94,12 @@ function partFields(options={}) { }, default_location: { }, - default_supplier: {}, + default_supplier: { + filters: { + part_detail: true, + supplier_detail: true, + } + }, default_expiry: { icon: 'fa-calendar-alt', }, @@ -315,6 +320,9 @@ function editPart(pk) { edit: true }); + // Filter supplied parts by the Part ID + fields.default_supplier.filters.part = pk; + var groups = partGroups({}); constructForm(url, { From f53aac0784f158ce2508e1810b20262abf09f6f5 Mon Sep 17 00:00:00 2001 From: Oliver Date: Fri, 24 Sep 2021 12:04:36 +1000 Subject: [PATCH 12/12] Remove "default_supplier" field when duplicating a part --- InvenTree/templates/js/translated/part.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/InvenTree/templates/js/translated/part.js b/InvenTree/templates/js/translated/part.js index e74b6fd743..6e8c02c0b1 100644 --- a/InvenTree/templates/js/translated/part.js +++ b/InvenTree/templates/js/translated/part.js @@ -346,6 +346,9 @@ function duplicatePart(pk, options={}) { duplicate: pk, }); + // Remove "default_supplier" field + delete fields['default_supplier']; + // If we are making a "variant" part if (options.variant) {