From 57174c90806c9c33e05f7df548c67736542a72bc Mon Sep 17 00:00:00 2001 From: Brandon King Date: Thu, 30 Apr 2009 02:05:33 +0000 Subject: [PATCH] Adding barcode magic commands: * updated magicbc.js to support the autofill mode (to fill in fields scanned into the barcode magic field. * added bcmagic/utils.py which contains quick functions for returning the correct dictionary expected by bcmagic.js. * added cmd_move_sample as first proof of concept command * Started a bcmagic/plugin.py which in the future will automatically look for bcm_cmds.py within each registered app and automatically add those commands to the processor. * provided samples/bcm_cmds.py as storage location for custom commands * started cmd_move_sample view and form --- samplebc/bcmagic/forms.py | 3 ++- samplebc/bcmagic/plugin.py | 18 ++++++++++++++ samplebc/bcmagic/utils.py | 22 +++++++++++++++++ samplebc/bcmagic/views.py | 47 ++++++++++++++++++++++++++++-------- samplebc/samples/bcm_cmds.py | 36 +++++++++++++++++++++++++++ samplebc/samples/forms.py | 7 +++--- samplebc/samples/urls.py | 4 ++- samplebc/samples/views.py | 13 +++++++--- www/js/magicbc.js | 35 ++++++++++++++++++++++++++- 9 files changed, 166 insertions(+), 19 deletions(-) create mode 100644 samplebc/bcmagic/plugin.py create mode 100644 samplebc/bcmagic/utils.py create mode 100644 samplebc/samples/bcm_cmds.py diff --git a/samplebc/bcmagic/forms.py b/samplebc/bcmagic/forms.py index 4eb3d83..377cee4 100644 --- a/samplebc/bcmagic/forms.py +++ b/samplebc/bcmagic/forms.py @@ -1,7 +1,8 @@ from django import forms class BarcodeMagicForm(forms.Form): - magic = forms.CharField(label="Barcode Magic") + magic = forms.CharField(label="Barcode Magic", required=False) + bcm_mode = forms.CharField(widget=forms.HiddenInput, initial="default") class Media: js = ('js/jquery.timers-1.0.0.js', diff --git a/samplebc/bcmagic/plugin.py b/samplebc/bcmagic/plugin.py new file mode 100644 index 0000000..759b1fd --- /dev/null +++ b/samplebc/bcmagic/plugin.py @@ -0,0 +1,18 @@ +from samplebc.samples import bcm_cmds + +BCM_PLUGINS = {'cmd_move_sample': bcm_cmds.cmd_move_sample} + + +def bcm_plugin_processor(keyword, text, bcm_mode): + """ + Fixme should be made generic plugable, but am hard coding values for proof + of concept. + """ + d = {} + + if bcm_mode not in BCM_PLUGINS: + d['mode'] = 'Error' + d['status'] = 'bcm_mode plugin called "%s" was not found' % (bcm_mode) + return d + + return BCM_PLUGINS[bcm_mode](keyword, text, bcm_mode) \ No newline at end of file diff --git a/samplebc/bcmagic/utils.py b/samplebc/bcmagic/utils.py new file mode 100644 index 0000000..5ee81a9 --- /dev/null +++ b/samplebc/bcmagic/utils.py @@ -0,0 +1,22 @@ + + +def report_error(message): + """ + Return a dictionary with a command to display 'message' + """ + return {'mode': 'Error', 'status': message} + + +def redirect_to_url(url): + """ + Return a bcm dictionary with a command to redirect to 'url' + """ + return {'mode': 'redirect', 'url': url} + + +def autofill(field, value): + """ + Return a bcm dictionary with a command to automatically fill the + corresponding "field" with "value" + """ + return {'mode': 'autofill', 'field': field, 'value': value} \ No newline at end of file diff --git a/samplebc/bcmagic/views.py b/samplebc/bcmagic/views.py index 21d45a1..0b0a2bc 100644 --- a/samplebc/bcmagic/views.py +++ b/samplebc/bcmagic/views.py @@ -4,6 +4,8 @@ from django.shortcuts import render_to_response from django.core.exceptions import ObjectDoesNotExist from samplebc.bcmagic import models +from samplebc.bcmagic.utils import report_error, redirect_to_url +from samplebc.bcmagic.plugin import bcm_plugin_processor import json import re @@ -30,8 +32,7 @@ def __magic_process(text): # There should always be at least one | in a valid scan. if len(split_text) <= 1: - return {'mode': 'Error', - 'status': 'Invalid text: %s' % (text)} + return report_error('Invalid text: %s' % (text)) # Keyword is the first element in the list keyword = split_text[0] @@ -40,8 +41,7 @@ def __magic_process(text): try: keymap = models.KeywordMap.objects.get(keyword=keyword) except ObjectDoesNotExist, e: - return {'mode': 'Error', - 'status': 'Keyword (%s) is not defined' % (keyword)} + return report_error('Keyword (%s) is not defined' % (keyword)) # Remove keyword and only scan the content content = '|'.join(split_text[1:]) @@ -53,14 +53,12 @@ def __magic_process(text): # if the search was invalid if not mo: - return {'mode': 'Error', - 'status': '(%s) failed to match (%s)' % (keymap.regex, content)} + return report_error('(%s) failed to match (%s)' % (keymap.regex, content)) t = Template(keymap.url_template) c = Context(mo.groupdict()) - return {'mode': 'redirect', - 'url': str(t.render(c)) } + return redirect_to_url(str(t.render(c))) @@ -72,20 +70,49 @@ def magic(request): """ d = {} + #Retrieve posted text from processing if 'text' in request.POST: text = request.POST['text'] else: text = None + + #Retrieve bmc_mode for processing + if 'bcm_mode' in request.POST: + bcm_mode = request.POST['bcm_mode'] + else: + bcm_mode = None + + ################################ + # Handle some errors + ################################ - #return HttpResponse(json.write(request.POST.items()), 'text/plain') + # Did not receive text error if text is None or text.strip() == '': d['mode'] = 'Error' d['status'] = 'Did not recieve text' return HttpResponse(json.write(d), 'text/plain') - if text.split('|')[0] == 'url': + # Did not receive bcm_mode error + if bcm_mode is None or bcm_mode.strip() == '': + d['mode'] = 'Error' + d['status'] = 'Missing bcm_mode information' + + + ################################ + # Figure out which mode to use + ################################ + keyword = text.split('|')[0] + + # Handle URL mode by default + if keyword == 'url': d['mode'] = 'redirect' d['url'] = text.split('|')[1] + + # Pass off processing to plugins + elif bcm_mode != 'default': + d = bcm_plugin_processor(keyword, text, bcm_mode) + + # Try keyword mapper else: d = __magic_process(text) diff --git a/samplebc/samples/bcm_cmds.py b/samplebc/samples/bcm_cmds.py new file mode 100644 index 0000000..e3996a0 --- /dev/null +++ b/samplebc/samples/bcm_cmds.py @@ -0,0 +1,36 @@ +from samplebc.bcmagic.utils import report_error, redirect_to_url, autofill +from samplebc.samples.models import Sample, Container, Freezer + +from django.core.exceptions import ObjectDoesNotExist + +def cmd_move_sample(keyword, text, bcm_mode): + """ + FIXME: should live in samples/bcm_cmds.py when this becomes a generic loader + """ + + # If we received anything other than a sample or container + if keyword not in ['s', 'cntr']: + return report_error('Keyword "%s" not valid in "%s" bcm_mode' % (keyword, bcm_mode)) + + # Sample received + if keyword == 's': + sampleid = text.split('|')[1] + try: + sample = Sample.objects.get(sampleid=sampleid) + except ObjectDoesNotExist: + return report_error('Sample (%s) does not exist!' % (sampleid)) + + return autofill('id_sampleid', sampleid) + + # Container received + elif keyword == 'cntr': + cntr_uuid = text.split('|')[1] + + try: + container = Container.objects.get(uuid=cntr_uuid) + except ObjectDoesNotExist, e: + return report_error('Container (%s) does not exist!' % (cntr_uuid)) + + return autofill('id_container_id', cntr_uuid) + + return report_error('The should not happen error occured from cmd_sample_move') \ No newline at end of file diff --git a/samplebc/samples/forms.py b/samplebc/samples/forms.py index d86effc..77d95fb 100644 --- a/samplebc/samples/forms.py +++ b/samplebc/samples/forms.py @@ -32,6 +32,7 @@ class SampleForm(forms.ModelForm): exclude = ('container', 'sampleid') -#class CmdMoveSampleForm(forms.Form): -# sampleid = form.CharField() -# container_id = form.CharField() \ No newline at end of file +class CmdMoveSampleForm(forms.Form): + sampleid = forms.CharField() + container_id = forms.CharField() + mode = forms.CharField(widget=forms.HiddenInput, initial="cmd_move_sample") \ No newline at end of file diff --git a/samplebc/samples/urls.py b/samplebc/samples/urls.py index a435d29..abe4c63 100644 --- a/samplebc/samples/urls.py +++ b/samplebc/samples/urls.py @@ -32,7 +32,9 @@ urlpatterns = patterns('', (r'^freezer/(?P[a-fA-F0-9]+)/print/$', 'samplebc.samples.views.freezer_print'), (r'^freezer/(?P[a-fA-F0-9]+)/$', - 'samplebc.samples.views.freezer_summary') + 'samplebc.samples.views.freezer_summary'), + # CMD URLs + (r'cmd/move_sample/', 'samplebc.samples.views.cmd_move_sample'), ) diff --git a/samplebc/samples/views.py b/samplebc/samples/views.py index 77a43b2..45d136f 100644 --- a/samplebc/samples/views.py +++ b/samplebc/samples/views.py @@ -8,7 +8,7 @@ from django.contrib.auth.decorators import login_required from django.utils.safestring import mark_safe -from samplebc.samples.forms import FreezerForm, ContainerForm, SampleForm +from samplebc.samples.forms import FreezerForm, ContainerForm, SampleForm, CmdMoveSampleForm from samplebc.samples.models import Freezer, Container, Sample from samplebc.samples.util import get_uuid, get_sampleid, assign_to_container from samplebc.samples.errors import NoSpaceAvaliable @@ -709,12 +709,19 @@ def cmd_move_sample(request): """ Moves a sample to a target container """ + form = CmdMoveSampleForm() + + # Load form template + c = Context({'form': form, + 'action_url': ''}) + t = get_template('generic_form.html') + return render_to_response('app.html', { 'app_name': settings.HTSW_ST_APPNAME, 'page_name': 'CMD: Move Sample', 'media': '', - 'bcmagic': BarcodeMagicForm(), + 'bcmagic': BarcodeMagicForm({'bcm_mode': 'cmd_move_sample'}), 'select': 'samples', - 'body': "" + 'body': t.render(c) }, context_instance=RequestContext(request)) \ No newline at end of file diff --git a/www/js/magicbc.js b/www/js/magicbc.js index 512fc74..b7cdae1 100644 --- a/www/js/magicbc.js +++ b/www/js/magicbc.js @@ -33,6 +33,10 @@ var bcmagic_process_callback = function(data, textStatus) { bcmagic_status('Error', 'No redirect URL provided by server'); } } + else if (data['mode'] == 'autofill') + { + bcmagic_autofill(data['field'], data['value']) + } else { bcmagic_message('Message recieved!'); bcmagic_status(data['mode'], data['status']); @@ -59,9 +63,12 @@ var bcmagic_process = function(){ var text = magic.attr('value'); magic.attr('value', ''); + var bcm_mode = $("#id_bcm_mode"); + var mode = bcm_mode.attr('value'); + // Show what we have captured bcmagic_message('Sent command to server'); - $.post('/bcmagic/magic/', {'text': text}, bcmagic_process_callback, 'json'); + $.post('/bcmagic/magic/', {'text': text, 'bcm_mode': mode}, bcmagic_process_callback, 'json'); } var bcmagic_keyhandler = function(e) { @@ -100,6 +107,32 @@ var bcmagic_redirect = function(url) window.location = url; } +var bcmagic_autofill = function(field, val) +{ + var txtbox = $('#'+field); + txtbox.attr('value', val); + + var input_fields = $('form input').not(':hidden').not('[type=submit]'); + + // Count the number of text fields which have been filled in. + var count = 0; + input_fields.each( function(){ + if(this.value.length > 0){ + count = count + 1; + } + }); + + // If the number of text fields filled in is equal to the number of input_fields in the form, submit the form! + if (count == input_fields.length) + { + bcmagic_status('Form Full', 'Form is now full and ready to process'); + } + else + { + bcmagic_status('Form Fill Count', 'Count(' + count +') - Total(' + input_fields.length + ')'); + } +} + //--------------------------------------- // Main Ready Function //--------------------------------------- -- 2.30.2