mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
Merge remote-tracking branch 'inventree/master'
This commit is contained in:
commit
994124e816
4
.github/workflows/docker.yaml
vendored
4
.github/workflows/docker.yaml
vendored
@ -48,7 +48,7 @@ jobs:
|
||||
- name: Build Docker Image
|
||||
# Build the development docker image (using docker-compose.yml)
|
||||
run: |
|
||||
docker-compose build
|
||||
docker-compose build --no-cache
|
||||
- name: Update Docker Image
|
||||
run: |
|
||||
docker-compose run inventree-dev-server invoke update
|
||||
@ -69,7 +69,7 @@ jobs:
|
||||
test -f data/secret_key.txt
|
||||
- name: Run Unit Tests
|
||||
run: |
|
||||
docker-compose run inventree-dev-server invoke test
|
||||
docker-compose run inventree-dev-server invoke test --disable-pty
|
||||
docker-compose down
|
||||
- name: Set up QEMU
|
||||
if: github.event_name != 'pull_request'
|
||||
|
@ -18,8 +18,7 @@ from django.urls import reverse_lazy
|
||||
from django.utils.timezone import now
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.views import View
|
||||
from django.views.generic import (CreateView, DeleteView, DetailView, ListView,
|
||||
UpdateView)
|
||||
from django.views.generic import DeleteView, DetailView, ListView, UpdateView
|
||||
from django.views.generic.base import RedirectView, TemplateView
|
||||
|
||||
from allauth.account.forms import AddEmailForm
|
||||
@ -185,7 +184,6 @@ class InvenTreeRoleMixin(PermissionRequiredMixin):
|
||||
UpdateView: 'change',
|
||||
DeleteView: 'delete',
|
||||
AjaxUpdateView: 'change',
|
||||
AjaxCreateView: 'add',
|
||||
}
|
||||
|
||||
for view_class in permission_map.keys():
|
||||
@ -360,77 +358,6 @@ class QRCodeView(AjaxView):
|
||||
return context
|
||||
|
||||
|
||||
class AjaxCreateView(AjaxMixin, CreateView):
|
||||
"""An 'AJAXified' CreateView for creating a new object in the db.
|
||||
|
||||
- Returns a form in JSON format (for delivery to a modal window)
|
||||
- Handles form validation via AJAX POST requests
|
||||
"""
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
"""Creates form with initial data, and renders JSON response."""
|
||||
super(CreateView, self).get(request, *args, **kwargs)
|
||||
|
||||
self.request = request
|
||||
form = self.get_form()
|
||||
return self.renderJsonResponse(request, form)
|
||||
|
||||
def save(self, form):
|
||||
"""Method for actually saving the form to the database.
|
||||
|
||||
Default implementation is very simple, but can be overridden if required.
|
||||
"""
|
||||
self.object = form.save()
|
||||
|
||||
return self.object
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
"""Responds to form POST. Validates POST data and returns status info.
|
||||
|
||||
- Validate POST form data
|
||||
- If valid, save form
|
||||
- Return status info (success / failure)
|
||||
"""
|
||||
self.request = request
|
||||
self.form = self.get_form()
|
||||
|
||||
# Perform initial form validation
|
||||
self.form.is_valid()
|
||||
|
||||
# Perform custom validation (no object can be provided yet)
|
||||
self.validate(None, self.form)
|
||||
|
||||
valid = self.form.is_valid()
|
||||
|
||||
# Extra JSON data sent alongside form
|
||||
data = {
|
||||
'form_valid': valid,
|
||||
'form_errors': self.form.errors.as_json(),
|
||||
'non_field_errors': self.form.non_field_errors().as_json(),
|
||||
}
|
||||
|
||||
# Add in any extra class data
|
||||
for value, key in enumerate(self.get_data()):
|
||||
data[key] = value
|
||||
|
||||
if valid:
|
||||
|
||||
# Save the object to the database
|
||||
self.object = self.save(self.form)
|
||||
|
||||
if self.object:
|
||||
# Return the PK of the newly-created object
|
||||
data['pk'] = self.object.pk
|
||||
data['text'] = str(self.object)
|
||||
|
||||
try:
|
||||
data['url'] = self.object.get_absolute_url()
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
return self.renderJsonResponse(request, self.form, data)
|
||||
|
||||
|
||||
class AjaxUpdateView(AjaxMixin, UpdateView):
|
||||
"""An 'AJAXified' UpdateView for updating an object in the db.
|
||||
|
||||
|
@ -5,6 +5,7 @@ from datetime import datetime, timedelta
|
||||
|
||||
from django.conf import settings
|
||||
from django.core.exceptions import AppRegistryNotReady
|
||||
from django.db.utils import IntegrityError, OperationalError
|
||||
|
||||
import feedparser
|
||||
|
||||
@ -57,13 +58,17 @@ def update_news_feed():
|
||||
continue
|
||||
|
||||
# Create entry
|
||||
NewsFeedEntry.objects.create(
|
||||
feed_id=entry.id,
|
||||
title=entry.title,
|
||||
link=entry.link,
|
||||
published=entry.published,
|
||||
author=entry.author,
|
||||
summary=entry.summary,
|
||||
)
|
||||
try:
|
||||
NewsFeedEntry.objects.create(
|
||||
feed_id=entry.id,
|
||||
title=entry.title,
|
||||
link=entry.link,
|
||||
published=entry.published,
|
||||
author=entry.author,
|
||||
summary=entry.summary,
|
||||
)
|
||||
except (IntegrityError, OperationalError):
|
||||
# Sometimes errors-out on database start-up
|
||||
pass
|
||||
|
||||
logger.info('update_news_feed: Sync done')
|
||||
|
@ -10,6 +10,7 @@ from pathlib import Path
|
||||
from django.apps import AppConfig
|
||||
from django.conf import settings
|
||||
from django.core.exceptions import AppRegistryNotReady
|
||||
from django.db.utils import OperationalError
|
||||
|
||||
from InvenTree.ready import canAppAccessDatabase
|
||||
|
||||
@ -35,18 +36,18 @@ class LabelConfig(AppConfig):
|
||||
def ready(self):
|
||||
"""This function is called whenever the label app is loaded."""
|
||||
if canAppAccessDatabase():
|
||||
self.create_labels() # pragma: no cover
|
||||
|
||||
try:
|
||||
self.create_labels() # pragma: no cover
|
||||
except (AppRegistryNotReady, OperationalError):
|
||||
# Database might not yet be ready
|
||||
warnings.warn('Database was not ready for creating labels')
|
||||
|
||||
def create_labels(self):
|
||||
"""Create all default templates."""
|
||||
# Test if models are ready
|
||||
try:
|
||||
from .models import PartLabel, StockItemLabel, StockLocationLabel
|
||||
assert bool(StockLocationLabel is not None)
|
||||
except AppRegistryNotReady: # pragma: no cover
|
||||
# Database might not yet be ready
|
||||
warnings.warn('Database was not ready for creating labels')
|
||||
return
|
||||
from .models import PartLabel, StockItemLabel, StockLocationLabel
|
||||
assert bool(StockLocationLabel is not None)
|
||||
|
||||
# Create the categories
|
||||
self.create_labels_category(
|
||||
@ -62,6 +63,7 @@ class LabelConfig(AppConfig):
|
||||
},
|
||||
],
|
||||
)
|
||||
|
||||
self.create_labels_category(
|
||||
StockLocationLabel,
|
||||
'stocklocation',
|
||||
@ -82,6 +84,7 @@ class LabelConfig(AppConfig):
|
||||
}
|
||||
]
|
||||
)
|
||||
|
||||
self.create_labels_category(
|
||||
PartLabel,
|
||||
'part',
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,5 @@
|
||||
"""JSON API for the plugin app."""
|
||||
"""API for the plugin app."""
|
||||
|
||||
from django.conf import settings
|
||||
from django.urls import include, re_path
|
||||
|
||||
from django_filters.rest_framework import DjangoFilterBackend
|
||||
@ -238,7 +237,6 @@ general_plugin_api_urls = [
|
||||
re_path(r'^.*$', PluginList.as_view(), name='api-plugin-list'),
|
||||
]
|
||||
|
||||
if settings.PLUGINS_ENABLED:
|
||||
plugin_api_urls.append(
|
||||
re_path(r'^plugin/', include(general_plugin_api_urls))
|
||||
)
|
||||
plugin_api_urls.append(
|
||||
re_path(r'^plugin/', include(general_plugin_api_urls))
|
||||
)
|
||||
|
@ -45,6 +45,18 @@ function createNewModal(options={}) {
|
||||
|
||||
var submitClass = options.submitClass || 'primary';
|
||||
|
||||
var buttons = '';
|
||||
|
||||
// Add in a "close" button
|
||||
if (!options.hideCloseButton) {
|
||||
buttons += `<button type='button' class='btn btn-secondary' id='modal-form-close' data-bs-dismiss='modal'>{% trans "Cancel" %}</button>`;
|
||||
}
|
||||
|
||||
// Add in a "submit" button
|
||||
if (!options.hideSubmitButton) {
|
||||
buttons += `<button type='button' class='btn btn-${submitClass}' id='modal-form-submit'>{% trans "Submit" %}</button>`;
|
||||
}
|
||||
|
||||
var html = `
|
||||
<div class='modal fade modal-fixed-footer modal-primary inventree-modal' role='dialog' id='modal-form-${id}' tabindex='-1'>
|
||||
<div class='modal-dialog'>
|
||||
@ -79,8 +91,7 @@ function createNewModal(options={}) {
|
||||
<div id='modal-footer-secondary-buttons'>
|
||||
<!-- Extra secondary buttons can be inserted here -->
|
||||
</div>
|
||||
<button type='button' class='btn btn-secondary' id='modal-form-close' data-bs-dismiss='modal'>{% trans "Cancel" %}</button>
|
||||
<button type='button' class='btn btn-${submitClass}' id='modal-form-submit'>{% trans "Submit" %}</button>
|
||||
${buttons}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -102,11 +113,7 @@ function createNewModal(options={}) {
|
||||
// Steal keyboard focus
|
||||
$(modal_name).focus();
|
||||
|
||||
if (options.hideCloseButton) {
|
||||
$(modal_name).find('#modal-form-close').hide();
|
||||
}
|
||||
|
||||
if (options.preventSubmit || options.hideSubmitButton) {
|
||||
if (options.preventSubmit) {
|
||||
$(modal_name).find('#modal-form-submit').hide();
|
||||
}
|
||||
|
||||
|
@ -1213,7 +1213,7 @@ function orderParts(parts_list, options={}) {
|
||||
constructFormBody({}, {
|
||||
preFormContent: html,
|
||||
title: '{% trans "Order Parts" %}',
|
||||
preventSubmit: true,
|
||||
hideSubmitButton: true,
|
||||
closeText: '{% trans "Close" %}',
|
||||
afterRender: function(fields, opts) {
|
||||
parts.forEach(function(part) {
|
||||
|
@ -4,7 +4,18 @@ import logging
|
||||
import multiprocessing
|
||||
import os
|
||||
|
||||
# Logger configuration
|
||||
logger = logging.getLogger('inventree')
|
||||
accesslog = '-'
|
||||
errorlog = '-'
|
||||
loglevel = os.environ.get('INVENTREE_LOG_LEVEL', 'warning').lower()
|
||||
capture_output = True
|
||||
|
||||
# Worker configuration
|
||||
# TODO: Implement support for gevent
|
||||
# worker_class = 'gevent' # Allow multi-threading support
|
||||
worker_tmp_dir = '/dev/shm' # Write temp file to RAM (faster)
|
||||
threads = 4
|
||||
|
||||
workers = os.environ.get('INVENTREE_GUNICORN_WORKERS', None)
|
||||
|
||||
|
@ -20,7 +20,7 @@ fi
|
||||
|
||||
# Check if "config.yaml" has been copied into the correct location
|
||||
if test -f "$INVENTREE_CONFIG_FILE"; then
|
||||
echo "$INVENTREE_CONFIG_FILE exists - skipping"
|
||||
echo "Loading config file : $INVENTREE_CONFIG_FILE"
|
||||
else
|
||||
echo "Copying config file to $INVENTREE_CONFIG_FILE"
|
||||
cp $INVENTREE_HOME/InvenTree/config_template.yaml $INVENTREE_CONFIG_FILE
|
||||
|
8
tasks.py
8
tasks.py
@ -534,13 +534,15 @@ def test_translations(c):
|
||||
|
||||
|
||||
@task
|
||||
def test(c, database=None):
|
||||
def test(c, disable_pty=False):
|
||||
"""Run unit-tests for InvenTree codebase."""
|
||||
# Run sanity check on the django install
|
||||
manage(c, 'check')
|
||||
|
||||
pty = not disable_pty
|
||||
|
||||
# Run coverage tests
|
||||
manage(c, 'test', pty=True)
|
||||
manage(c, 'test', pty=pty)
|
||||
|
||||
|
||||
@task(help={'dev': 'Set up development environment at the end'})
|
||||
@ -577,7 +579,7 @@ def setup_test(c, ignore_update=False, dev=False, path="inventree-demo-dataset")
|
||||
|
||||
shutil.copytree(src, dst, dirs_exist_ok=True)
|
||||
|
||||
print("Done setting up test enviroment...")
|
||||
print("Done setting up test environment...")
|
||||
print("========================================")
|
||||
|
||||
# Set up development setup if flag is set
|
||||
|
Loading…
Reference in New Issue
Block a user