Adding barcode magic commands:
authorBrandon King <kingb@caltech.edu>
Thu, 30 Apr 2009 02:05:33 +0000 (02:05 +0000)
committerBrandon King <kingb@caltech.edu>
Thu, 30 Apr 2009 02:05:33 +0000 (02:05 +0000)
 * 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
samplebc/bcmagic/plugin.py [new file with mode: 0644]
samplebc/bcmagic/utils.py [new file with mode: 0644]
samplebc/bcmagic/views.py
samplebc/samples/bcm_cmds.py [new file with mode: 0644]
samplebc/samples/forms.py
samplebc/samples/urls.py
samplebc/samples/views.py
www/js/magicbc.js

index 4eb3d8384cd328d89de29d2be3891f54e5ad0ad4..377cee4d15b680656431846321ca8a5c5986cb6a 100644 (file)
@@ -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 (file)
index 0000000..759b1fd
--- /dev/null
@@ -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 (file)
index 0000000..5ee81a9
--- /dev/null
@@ -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
index 21d45a1ec7d31825491e2908f3a1666ef838b8e9..0b0a2bc19d2324cd99d37fb2e70d41bd0adcd775 100644 (file)
@@ -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 (file)
index 0000000..e3996a0
--- /dev/null
@@ -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
index d86effcb6ea3bb192be39c7c95f2b12b3d6300c8..77d95fb0142d488df18a83b2af44e23a1f5c47b8 100644 (file)
@@ -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
index a435d297f4b8c224fd8ad09e56a5c5133e109ce1..abe4c63d0ea548d01559130c6a888764a61a0b06 100644 (file)
@@ -32,7 +32,9 @@ urlpatterns = patterns('',
     (r'^freezer/(?P<freezer_id>[a-fA-F0-9]+)/print/$',
      'samplebc.samples.views.freezer_print'),
     (r'^freezer/(?P<freezer_id>[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'),
     
 )
index 77a43b2e5147d000ce4c309517be44bed6d563c0..45d136fbe40a1494f9d927ef702763e5a36ce005 100644 (file)
@@ -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
index 512fc7456c6841ea084f55ee478b117f7a4f2aaf..b7cdae1b28298b07b1d928632cdf717a79d613b0 100644 (file)
@@ -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
 //---------------------------------------