Skip to content

Commit

Permalink
0.4.1
Browse files Browse the repository at this point in the history
  • Loading branch information
SchrodingersGat committed Jul 30, 2021
2 parents 0a73032 + eb883d7 commit 0e59c15
Show file tree
Hide file tree
Showing 42 changed files with 436 additions and 152 deletions.
2 changes: 1 addition & 1 deletion .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@
*.yml text
*.yaml text
*.conf text
*.sh text
*.sh text eol=lf
*.js text
28 changes: 28 additions & 0 deletions .github/workflows/javascript.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Check javascript template files

name: Javascript Templates

on:
push:
branches:
- master

pull_request:
branches-ignore:
- l10*

jobs:

javascript:
runs-on: ubuntu-latest

env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps:
- name: Checkout Code
uses: actions/checkout@v2
- name: Check Files
run: |
cd ci
python check_js_templates.py
17 changes: 15 additions & 2 deletions InvenTree/InvenTree/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"""

import logging

import os
import random
import string
Expand Down Expand Up @@ -202,7 +203,7 @@ def get_setting(environment_var, backup_val, default_value=None):

# Translated Template settings
STATICFILES_I18_PREFIX = 'i18n'
STATICFILES_I18_SRC = os.path.join(BASE_DIR, 'templates', 'js')
STATICFILES_I18_SRC = os.path.join(BASE_DIR, 'templates', 'js', 'translated')
STATICFILES_I18_TRG = STATICFILES_DIRS[0] + '_' + STATICFILES_I18_PREFIX
STATICFILES_DIRS.append(STATICFILES_I18_TRG)
STATICFILES_I18_TRG = os.path.join(STATICFILES_I18_TRG, STATICFILES_I18_PREFIX)
Expand Down Expand Up @@ -347,10 +348,22 @@ def get_setting(environment_var, backup_val, default_value=None):

WSGI_APPLICATION = 'InvenTree.wsgi.application'

background_workers = os.environ.get('INVENTREE_BACKGROUND_WORKERS', None)

if background_workers is not None:
try:
background_workers = int(background_workers)
except ValueError:
background_workers = None

if background_workers is None:
# Sensible default?
background_workers = 4

# django-q configuration
Q_CLUSTER = {
'name': 'InvenTree',
'workers': 4,
'workers': background_workers,
'timeout': 90,
'retry': 120,
'queue_limit': 50,
Expand Down
50 changes: 28 additions & 22 deletions InvenTree/InvenTree/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,28 +93,33 @@
url(r'^.*$', SettingsView.as_view(template_name='InvenTree/settings/settings.html'), name='settings'),
]

# Some javascript files are served 'dynamically', allowing them to pass through the Django translation layer
# These javascript files are served "dynamically" - i.e. rendered on demand
dynamic_javascript_urls = [
url(r'^api.js', DynamicJsView.as_view(template_name='js/api.js'), name='api.js'),
url(r'^attachment.js', DynamicJsView.as_view(template_name='js/attachment.js'), name='attachment.js'),
url(r'^barcode.js', DynamicJsView.as_view(template_name='js/barcode.js'), name='barcode.js'),
url(r'^bom.js', DynamicJsView.as_view(template_name='js/bom.js'), name='bom.js'),
url(r'^build.js', DynamicJsView.as_view(template_name='js/build.js'), name='build.js'),
url(r'^calendar.js', DynamicJsView.as_view(template_name='js/calendar.js'), name='calendar.js'),
url(r'^company.js', DynamicJsView.as_view(template_name='js/company.js'), name='company.js'),
url(r'^filters.js', DynamicJsView.as_view(template_name='js/filters.js'), name='filters.js'),
url(r'^forms.js', DynamicJsView.as_view(template_name='js/forms.js'), name='forms.js'),
url(r'^inventree.js', DynamicJsView.as_view(template_name='js/inventree.js'), name='inventree.js'),
url(r'^label.js', DynamicJsView.as_view(template_name='js/label.js'), name='label.js'),
url(r'^model_renderers.js', DynamicJsView.as_view(template_name='js/model_renderers.js'), name='model_renderers.js'),
url(r'^modals.js', DynamicJsView.as_view(template_name='js/modals.js'), name='modals.js'),
url(r'^nav.js', DynamicJsView.as_view(template_name='js/nav.js'), name='nav.js'),
url(r'^order.js', DynamicJsView.as_view(template_name='js/order.js'), name='order.js'),
url(r'^part.js', DynamicJsView.as_view(template_name='js/part.js'), name='part.js'),
url(r'^report.js', DynamicJsView.as_view(template_name='js/report.js'), name='report.js'),
url(r'^stock.js', DynamicJsView.as_view(template_name='js/stock.js'), name='stock.js'),
url(r'^tables.js', DynamicJsView.as_view(template_name='js/tables.js'), name='tables.js'),
url(r'^table_filters.js', DynamicJsView.as_view(template_name='js/table_filters.js'), name='table_filters.js'),
url(r'^inventree.js', DynamicJsView.as_view(template_name='js/dynamic/inventree.js'), name='inventree.js'),
url(r'^calendar.js', DynamicJsView.as_view(template_name='js/dynamic/calendar.js'), name='calendar.js'),
url(r'^nav.js', DynamicJsView.as_view(template_name='js/dynamic/nav.js'), name='nav.js'),
url(r'^settings.js', DynamicJsView.as_view(template_name='js/dynamic/settings.js'), name='settings.js'),
]

# These javascript files are pased through the Django translation layer
translated_javascript_urls = [
url(r'^api.js', DynamicJsView.as_view(template_name='js/translated/api.js'), name='api.js'),
url(r'^attachment.js', DynamicJsView.as_view(template_name='js/translated/attachment.js'), name='attachment.js'),
url(r'^barcode.js', DynamicJsView.as_view(template_name='js/translated/barcode.js'), name='barcode.js'),
url(r'^bom.js', DynamicJsView.as_view(template_name='js/translated/bom.js'), name='bom.js'),
url(r'^build.js', DynamicJsView.as_view(template_name='js/translated/build.js'), name='build.js'),
url(r'^company.js', DynamicJsView.as_view(template_name='js/translated/company.js'), name='company.js'),
url(r'^filters.js', DynamicJsView.as_view(template_name='js/translated/filters.js'), name='filters.js'),
url(r'^forms.js', DynamicJsView.as_view(template_name='js/translated/forms.js'), name='forms.js'),
url(r'^label.js', DynamicJsView.as_view(template_name='js/translated/label.js'), name='label.js'),
url(r'^model_renderers.js', DynamicJsView.as_view(template_name='js/translated/model_renderers.js'), name='model_renderers.js'),
url(r'^modals.js', DynamicJsView.as_view(template_name='js/translated/modals.js'), name='modals.js'),
url(r'^order.js', DynamicJsView.as_view(template_name='js/translated/order.js'), name='order.js'),
url(r'^part.js', DynamicJsView.as_view(template_name='js/translated/part.js'), name='part.js'),
url(r'^report.js', DynamicJsView.as_view(template_name='js/translated/report.js'), name='report.js'),
url(r'^stock.js', DynamicJsView.as_view(template_name='js/translated/stock.js'), name='stock.js'),
url(r'^tables.js', DynamicJsView.as_view(template_name='js/translated/tables.js'), name='tables.js'),
url(r'^table_filters.js', DynamicJsView.as_view(template_name='js/translated/table_filters.js'), name='table_filters.js'),
]

urlpatterns = [
Expand All @@ -123,7 +128,8 @@
url(r'^supplier-part/', include(supplier_part_urls)),

# "Dynamic" javascript files which are rendered using InvenTree templating.
url(r'^dynamic/', include(dynamic_javascript_urls)),
url(r'^js/dynamic/', include(dynamic_javascript_urls)),
url(r'^js/i18n/', include(translated_javascript_urls)),

url(r'^common/', include(common_urls)),

Expand Down
2 changes: 1 addition & 1 deletion InvenTree/InvenTree/version.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

import common.models

INVENTREE_SW_VERSION = "0.4.0"
INVENTREE_SW_VERSION = "0.4.1"

INVENTREE_API_VERSION = 8

Expand Down
2 changes: 1 addition & 1 deletion InvenTree/build/templates/build/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ <h3>{% trans "Build Orders" %}</h3>
},
{
success: function(response) {
var prefix = '{% settings_value "BUILDORDER_REFERENCE_PREFIX" %}';
var prefix = global_settings.BUILDORDER_REFERENCE_PREFIX;

for (var idx = 0; idx < response.length; idx++) {

Expand Down
87 changes: 80 additions & 7 deletions InvenTree/common/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,67 @@ class BaseInvenTreeSetting(models.Model):
class Meta:
abstract = True

@classmethod
def allValues(cls, user=None):
"""
Return a dict of "all" defined global settings.
This performs a single database lookup,
and then any settings which are not *in* the database
are assigned their default values
"""

keys = set()
settings = []

results = cls.objects.all()

if user is not None:
results = results.filter(user=user)

# Query the database
for setting in results:
settings.append({
"key": setting.key.upper(),
"value": setting.value
})

keys.add(setting.key.upper())

# Specify any "default" values which are not in the database
for key in cls.GLOBAL_SETTINGS.keys():

if key.upper() not in keys:

settings.append({
"key": key.upper(),
"value": cls.get_setting_default(key)
})

# Enforce javascript formatting
for idx, setting in enumerate(settings):

key = setting['key']
value = setting['value']

validator = cls.get_setting_validator(key)

# Convert to javascript compatible booleans
if cls.validator_is_bool(validator):
value = str(value).lower()

# Numerical values remain the same
elif cls.validator_is_int(validator):
pass

# Wrap strings with quotes
else:
value = f"'{value}'"

setting["value"] = value

return settings

@classmethod
def get_setting_name(cls, key):
"""
Expand Down Expand Up @@ -368,13 +429,7 @@ def is_bool(self):

validator = self.__class__.get_setting_validator(self.key)

if validator == bool:
return True

if type(validator) in [list, tuple]:
for v in validator:
if v == bool:
return True
return self.__class__.validator_is_bool(validator)

def as_bool(self):
"""
Expand All @@ -385,13 +440,31 @@ def as_bool(self):

return InvenTree.helpers.str2bool(self.value)

@classmethod
def validator_is_bool(cls, validator):

if validator == bool:
return True

if type(validator) in [list, tuple]:
for v in validator:
if v == bool:
return True

return False

def is_int(self):
"""
Check if the setting is required to be an integer value:
"""

validator = self.__class__.get_setting_validator(self.key)

return self.__class__.validator_is_int(validator)

@classmethod
def validator_is_int(cls, validator):

if validator == int:
return True

Expand Down
53 changes: 20 additions & 33 deletions InvenTree/company/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
from __future__ import unicode_literals

from django_filters.rest_framework import DjangoFilterBackend
from django_filters import rest_framework as rest_filters

from rest_framework import filters
from rest_framework import generics

Expand Down Expand Up @@ -84,6 +86,23 @@ def get_queryset(self):
return queryset


class ManufacturerPartFilter(rest_filters.FilterSet):
"""
Custom API filters for the ManufacturerPart list endpoint.
"""

class Meta:
model = ManufacturerPart
fields = [
'manufacturer',
'MPN',
'part',
]

# Filter by 'active' status of linked part
active = rest_filters.BooleanFilter(field_name='part__active')


class ManufacturerPartList(generics.ListCreateAPIView):
""" API endpoint for list view of ManufacturerPart object
Expand All @@ -98,6 +117,7 @@ class ManufacturerPartList(generics.ListCreateAPIView):
)

serializer_class = ManufacturerPartSerializer
filterset_class = ManufacturerPartFilter

def get_serializer(self, *args, **kwargs):

Expand All @@ -115,45 +135,12 @@ def get_serializer(self, *args, **kwargs):

return self.serializer_class(*args, **kwargs)

def filter_queryset(self, queryset):
"""
Custom filtering for the queryset.
"""

queryset = super().filter_queryset(queryset)

params = self.request.query_params

# Filter by manufacturer
manufacturer = params.get('manufacturer', None)

if manufacturer is not None:
queryset = queryset.filter(manufacturer=manufacturer)

# Filter by parent part?
part = params.get('part', None)

if part is not None:
queryset = queryset.filter(part=part)

# Filter by 'active' status of the part?
active = params.get('active', None)

if active is not None:
active = str2bool(active)
queryset = queryset.filter(part__active=active)

return queryset

filter_backends = [
DjangoFilterBackend,
filters.SearchFilter,
filters.OrderingFilter,
]

filter_fields = [
]

search_fields = [
'manufacturer__name',
'description',
Expand Down
21 changes: 10 additions & 11 deletions InvenTree/company/templates/company/company_base.html
Original file line number Diff line number Diff line change
Expand Up @@ -198,17 +198,16 @@ <h4>{% trans "Company Details" %}</h4>
);
});

{% settings_value "INVENTREE_DOWNLOAD_FROM_URL" as allow_download %}
if (global_settings.INVENTREE_DOWNLOAD_FROM_URL) {

{% if allow_download %}
$('#company-image-url').click(function() {
launchModalForm(
'{% url "company-image-download" company.id %}',
{
reload: true,
}
)
});
{% endif %}
$('#company-image-url').click(function() {
launchModalForm(
'{% url "company-image-download" company.id %}',
{
reload: true,
}
)
});
}

{% endblock %}
Loading

0 comments on commit 0e59c15

Please sign in to comment.