diff --git a/InvenTree/InvenTree/api.py b/InvenTree/InvenTree/api.py new file mode 100644 index 0000000000..d68ecd67ad --- /dev/null +++ b/InvenTree/InvenTree/api.py @@ -0,0 +1,142 @@ +""" +Main JSON interface views +""" + +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.utils.translation import ugettext as _ +from django.http import JsonResponse + +from rest_framework import permissions +from rest_framework.response import Response +from rest_framework.views import APIView + +from .views import AjaxView +from .version import inventreeVersion, inventreeInstanceName + +from plugins import plugins as inventree_plugins + +# Load barcode plugins +print("INFO: Loading plugins") + +barcode_plugins = inventree_plugins.load_barcode_plugins() +action_plugins = inventree_plugins.load_action_plugins() + + +class InfoView(AjaxView): + """ Simple JSON endpoint for InvenTree information. + Use to confirm that the server is running, etc. + """ + + def get(self, request, *args, **kwargs): + + data = { + 'server': 'InvenTree', + 'version': inventreeVersion(), + 'instance': inventreeInstanceName(), + } + + return JsonResponse(data) + + +class ActionPluginView(APIView): + """ + Endpoint for running custom action plugins. + """ + + permission_classes = [ + permissions.IsAuthenticated, + ] + + def post(self, request, *args, **kwargs): + + action = request.data.get('action', None) + + data = request.data.get('data', None) + + if action is None: + return Response({ + 'error': _("No action specified") + }) + + for plugin_class in action_plugins: + if plugin_class.action_name() == action: + + plugin = plugin_class(request.user, data=data) + + plugin.perform_action() + + return Response(plugin.get_response()) + + # If we got to here, no matching action was found + return Response({ + 'error': _("No matching action found"), + "action": action, + }) + + +class BarcodePluginView(APIView): + """ + Endpoint for handling barcode scan requests. + + Barcode data are decoded by the client application, + and sent to this endpoint (as a JSON object) for validation. + + A barcode could follow the internal InvenTree barcode format, + or it could match to a third-party barcode format (e.g. Digikey). + + """ + + permission_classes = [ + permissions.IsAuthenticated, + ] + + def post(self, request, *args, **kwargs): + + response = {} + + barcode_data = request.data.get('barcode', None) + + print("Barcode data:") + print(barcode_data) + + if barcode_data is None: + response['error'] = _('No barcode data provided') + else: + # Look for a barcode plugin that knows how to handle the data + for plugin_class in barcode_plugins: + + # Instantiate the plugin with the provided plugin data + plugin = plugin_class(barcode_data) + + if plugin.validate(): + + # Plugin should return a dict response + response = plugin.decode() + + if type(response) is dict: + if 'success' not in response.keys() and 'error' not in response.keys(): + response['success'] = _('Barcode successfully decoded') + else: + response = { + 'error': _('Barcode plugin returned incorrect response') + } + + response['plugin'] = plugin.plugin_name() + response['hash'] = plugin.hash() + + break + + if 'error' not in response and 'success' not in response: + response = { + 'error': _('Unknown barcode format'), + } + + # Include the original barcode data + response['barcode_data'] = barcode_data + + print("Response:") + print(response) + + return Response(response) diff --git a/InvenTree/InvenTree/helpers.py b/InvenTree/InvenTree/helpers.py index 6b619b4aa2..b9a4d73740 100644 --- a/InvenTree/InvenTree/helpers.py +++ b/InvenTree/InvenTree/helpers.py @@ -172,7 +172,7 @@ def WrapWithQuotes(text, quote='"'): return text -def MakeBarcode(object_type, object_id, object_url, data={}): +def MakeBarcode(object_name, object_data): """ Generate a string for a barcode. Adds some global InvenTree parameters. Args: @@ -185,13 +185,12 @@ def MakeBarcode(object_type, object_id, object_url, data={}): json string of the supplied data plus some other data """ - # Add in some generic InvenTree data - data['type'] = object_type - data['id'] = object_id - data['url'] = object_url - data['tool'] = 'InvenTree' - data['instance'] = inventreeInstanceName() - data['version'] = inventreeVersion() + data = { + 'tool': 'InvenTree', + 'version': inventreeVersion(), + 'instance': inventreeInstanceName(), + object_name: object_data + } return json.dumps(data, sort_keys=True) diff --git a/InvenTree/InvenTree/static/script/inventree/part.js b/InvenTree/InvenTree/static/script/inventree/part.js index 05b209b9b8..7954caa012 100644 --- a/InvenTree/InvenTree/static/script/inventree/part.js +++ b/InvenTree/InvenTree/static/script/inventree/part.js @@ -81,15 +81,19 @@ function loadPartTable(table, url, options={}) { * - table: HTML reference to the table * - url: Base URL for API query * - options: object containing following (optional) fields - * allowInactive: If true, allow display of inactive parts * checkbox: Show the checkbox column * query: extra query params for API request * buttons: If provided, link buttons to selection status of this table + * disableFilters: If true, disable custom filters */ - var params = options.parms || {}; + var params = options.params || {}; - var filters = loadTableFilters("parts"); + var filters = {}; + + if (!options.disableFilters) { + filters = loadTableFilters("parts"); + } for (var key in params) { filters[key] = params[key]; @@ -147,6 +151,10 @@ function loadPartTable(table, url, options={}) { display += ``; } + if (row.starred) { + display += ``; + } + /* if (row.component) { display = display + ``; diff --git a/InvenTree/InvenTree/static/script/inventree/stock.js b/InvenTree/InvenTree/static/script/inventree/stock.js index bf0ddbef5e..d68d0946a2 100644 --- a/InvenTree/InvenTree/static/script/inventree/stock.js +++ b/InvenTree/InvenTree/static/script/inventree/stock.js @@ -41,6 +41,7 @@ function loadStockTable(table, options) { * groupByField - Column for grouping stock items * buttons - Which buttons to link to stock selection callbacks * filterList -