from django.conf.urls.defaults import *
urlpatterns = patterns('',
- (r'^lts/link/(?P<flowcell>.+)/(?P<serial>.+)/$', 'htsworkflow.frontend.inventory.views.link_flowcell_and_device'),
+ # DATA
+ (r'^data/items/$', 'htsworkflow.frontend.inventory.views.data_items'),
+ # REMOTE LINKING
+ (r'^lts/link/(?P<flowcell>.+)/(?P<serial>.+)/$', 'htsworkflow.frontend.inventory.views.link_flowcell_and_device'),
+
+ # INDEX
+ (r'^$', 'htsworkflow.frontend.inventory.views.index')
)
from htsworkflow.frontend.inventory.models import Item, LongTermStorage
from htsworkflow.frontend.experiments.models import FlowCell
+from htsworkflow.frontend.bcmagic.forms import BarcodeMagicForm
from django.core.exceptions import ObjectDoesNotExist
-from django.http import HttpResponse
+from django.http import HttpResponse, HttpResponseRedirect
+from django.shortcuts import render_to_response
+from django.template import RequestContext
+from django.template.loader import get_template
+from django.contrib.auth.decorators import login_required
+import json
+
+INVENTORY_CONTEXT_DEFAULTS = {
+ 'app_name': 'Inventory Tracker',
+ 'bcmagic': BarcodeMagicForm()
+}
+
+def data_items(request):
+ """
+ Returns items in json format
+ """
+ item_list = Item.objects.all()
+ d = { 'results': len(item_list) }
+ rows = []
+
+ for item in item_list:
+ item_d = {}
+ item_d['uuid'] = item.uuid
+ item_d['barcode_id'] = item.barcode_id
+ item_d['creation_date'] = item.creation_date.strftime('%Y-%m-%d %H:%M:%S')
+ item_d['modified_date'] = item.modified_date.strftime('%Y-%m-%d %H:%M:%S')
+ item_d['type'] = item.item_type.name
+ rows.append(item_d)
+
+ d['rows'] = rows
+
+ j = json.JSONEncoder()
+ return HttpResponse(j.encode(d), content_type="application/javascript")
+
+def index(request):
+ """
+ Inventory Index View
+ """
+ context_dict = {
+ 'page_name': 'Inventory Index'
+ }
+ context_dict.update(INVENTORY_CONTEXT_DEFAULTS)
+
+ return render_to_response('inventory_index.html',
+ context_dict,
+ context_instance=RequestContext(request))
+
def link_flowcell_and_device(request, flowcell, serial):
"""
--- /dev/null
+
+var getInventoryDataGrid = function(){
+
+ var Item = Ext.data.Record.create([
+ { name: 'uuid' },
+ { name: 'barcode_id'},
+ { name: 'creation_date'/*, type: 'date', dateFormat: 'n/j h:ia'*/},
+ { name: 'modified_date'/*, type: 'date', dateFormat: 'n/j h:ia'*/},
+ { name: 'type'}
+ ]);
+
+ var inventoryReader = new Ext.data.JsonReader(
+ {
+ totalProperty: "results",
+ root: "rows",
+ idProperty: "uuid"
+ },
+ Item
+ );
+
+ /*
+ var inventoryStore = new Ext.data.JsonStore({
+ autoDestory: true,
+ url: '/inventory/data/items/',
+ storeId: 'item_store',
+
+ });
+ */
+
+ var grid = new Ext.grid.GridPanel({
+ store: new Ext.data.GroupingStore({
+ reader: inventoryReader,
+ url: '/inventory/data/items/',
+ storeId: 'item_group_store',
+ groupField: 'type',
+ sortInfo: { field: 'modified_date', direction: "ASC"},
+ autoLoad: true
+ }),
+
+ columns: [
+ {id: 'uuid', header:"UUID", width: 32, sortable: true, dataIndex: 'uuid'},
+ {header: 'Barcode ID', width: 20, sortable: true, dataIndex: 'barcode_id'},
+ {header: 'Creation Date', width: 20, sortable: true, dataIndex: 'creation_date'/*, renderer: Ext.util.Format.dateRenderer('Y/m/d')*/},
+ {header: 'Modified Date', width: 20, sortable: true, dataIndex: 'modified_date'/*, renderer: Ext.util.Format.dateRenderer('Y/m/d')*/},
+ {header: 'Type', width: 20, sortable: true, dataIndex: 'type'}
+ ],
+
+ view: new Ext.grid.GroupingView({
+ forceFit: true,
+ groupTextTpl: '{text} ({[values.rs.length]} {[values.rs.length > 1 ? "Items" : "Item"]})'
+ }),
+
+ frame: true,
+ width: 'auto',
+ height: 500,
+ //autoHeight: true,
+ collapsible: false,
+ title: "Inventory Index",
+ iconCls: 'icon-grid'
+ //renderTo: 'grid_target'
+ });
+
+ return grid;
+}
\ No newline at end of file
height: 30
//margins: '2 0 0 0'
}],
- height: 90
+ height: 90,
+ collapsible: true,
+ collapseMode: 'mini',
+ split: true
},menuPanel,{
//title: 'Body',
region: 'center',
// Focus on barcode magic, because it's awesome and needs attention! ;-)
bcmagic_input.focus();
+
+ // FIXME: grid target temp code.
+ var grid_target = Ext.fly('grid_target');
+ if (grid_target != null){
+ var grid = getInventoryDataGrid();
+ grid.render(grid_target);
+ }
});
\ No newline at end of file
--- /dev/null
+/**\r
+ * jQuery.timers - Timer abstractions for jQuery\r
+ * Written by Blair Mitchelmore (blair DOT mitchelmore AT gmail DOT com)\r
+ * Licensed under the WTFPL (http://sam.zoy.org/wtfpl/).\r
+ * Date: 2008/08/26\r
+ *\r
+ * @author Blair Mitchelmore\r
+ * @version 1.0.0\r
+ *\r
+ **/\r
+\r
+jQuery.fn.extend({\r
+ everyTime: function(interval, label, fn, times, belay) {\r
+ return this.each(function() {\r
+ jQuery.timer.add(this, interval, label, fn, times, belay);\r
+ });\r
+ },\r
+ oneTime: function(interval, label, fn) {\r
+ return this.each(function() {\r
+ jQuery.timer.add(this, interval, label, fn, 1);\r
+ });\r
+ },\r
+ stopTime: function(label, fn) {\r
+ return this.each(function() {\r
+ jQuery.timer.remove(this, label, fn);\r
+ });\r
+ }\r
+});\r
+\r
+jQuery.extend({\r
+ timer: {\r
+ guid: 1,\r
+ global: {},\r
+ regex: /^([0-9]+)\s*(.*s)?$/,\r
+ powers: {\r
+ // Yeah this is major overkill...\r
+ 'ms': 1,\r
+ 'cs': 10,\r
+ 'ds': 100,\r
+ 's': 1000,\r
+ 'das': 10000,\r
+ 'hs': 100000,\r
+ 'ks': 1000000\r
+ },\r
+ timeParse: function(value) {\r
+ if (value == undefined || value == null)\r
+ return null;\r
+ var result = this.regex.exec(jQuery.trim(value.toString()));\r
+ if (result[2]) {\r
+ var num = parseInt(result[1], 10);\r
+ var mult = this.powers[result[2]] || 1;\r
+ return num * mult;\r
+ } else {\r
+ return value;\r
+ }\r
+ },\r
+ add: function(element, interval, label, fn, times, belay) {\r
+ var counter = 0;\r
+ \r
+ if (jQuery.isFunction(label)) {\r
+ if (!times) \r
+ times = fn;\r
+ fn = label;\r
+ label = interval;\r
+ }\r
+ \r
+ interval = jQuery.timer.timeParse(interval);\r
+\r
+ if (typeof interval != 'number' || isNaN(interval) || interval <= 0)\r
+ return;\r
+\r
+ if (times && times.constructor != Number) {\r
+ belay = !!times;\r
+ times = 0;\r
+ }\r
+ \r
+ times = times || 0;\r
+ belay = belay || false;\r
+ \r
+ if (!element.$timers) \r
+ element.$timers = {};\r
+ \r
+ if (!element.$timers[label])\r
+ element.$timers[label] = {};\r
+ \r
+ fn.$timerID = fn.$timerID || this.guid++;\r
+ \r
+ var handler = function() {\r
+ if (belay && this.inProgress) \r
+ return;\r
+ this.inProgress = true;\r
+ if ((++counter > times && times !== 0) || fn.call(element, counter) === false)\r
+ jQuery.timer.remove(element, label, fn);\r
+ this.inProgress = false;\r
+ };\r
+ \r
+ handler.$timerID = fn.$timerID;\r
+ \r
+ if (!element.$timers[label][fn.$timerID]) \r
+ element.$timers[label][fn.$timerID] = window.setInterval(handler,interval);\r
+ \r
+ if ( !this.global[label] )\r
+ this.global[label] = [];\r
+ this.global[label].push( element );\r
+ \r
+ },\r
+ remove: function(element, label, fn) {\r
+ var timers = element.$timers, ret;\r
+ \r
+ if ( timers ) {\r
+ \r
+ if (!label) {\r
+ for ( label in timers )\r
+ this.remove(element, label, fn);\r
+ } else if ( timers[label] ) {\r
+ if ( fn ) {\r
+ if ( fn.$timerID ) {\r
+ window.clearInterval(timers[label][fn.$timerID]);\r
+ delete timers[label][fn.$timerID];\r
+ }\r
+ } else {\r
+ for ( var fn in timers[label] ) {\r
+ window.clearInterval(timers[label][fn]);\r
+ delete timers[label][fn];\r
+ }\r
+ }\r
+ \r
+ for ( ret in timers[label] ) break;\r
+ if ( !ret ) {\r
+ ret = null;\r
+ delete timers[label];\r
+ }\r
+ }\r
+ \r
+ for ( ret in timers ) break;\r
+ if ( !ret ) \r
+ element.$timers = null;\r
+ }\r
+ }\r
+ }\r
+});\r
+\r
+if (jQuery.browser.msie)\r
+ jQuery(window).one("unload", function() {\r
+ var global = jQuery.timer.global;\r
+ for ( var label in global ) {\r
+ var els = global[label], i = els.length;\r
+ while ( --i )\r
+ jQuery.timer.remove(els[i], label);\r
+ }\r
+ });\r
<script type="text/javascript" src="/static/js/ext-3.0-rc2/adapter/jquery/ext-jquery-adapter.js"></script>
<script type="text/javascript" src="/static/js/ext-3.0-rc2/ext-all.js"></script>
<!--<script type="text/javascript" src="/static/js/menu.js"></script>-->
+
+ {% block additional_javascript %}
+ {% endblock %}
+
<script type="text/javascript" src="/static/js/htsw.js"></script>
<!--{{ media }}-->
<!--
<!-- Left side tool bar -->
<div id="left_tbar_data" class="x-hidden">
{% block left_tbar_menu %}
- <div id="Flowcells-Libraries" href="{% url htsworkflow.frontend.samples.views.library %}"></div>
+ <div id="Flowcells-Libraries Tracker" href="{% url htsworkflow.frontend.samples.views.library %}"></div>
+ <div id="Inventory Tracker" href="{% url htsworkflow.frontend.inventory.views.index %}"></div>
{% endblock %}
</div>
--- /dev/null
+{% extends "app_base.html" %}
+
+{% block additional_css %}
+{% endblock %}
+
+{% block additional_javascript %}
+<script type="text/javascript" src="/static/js/htsw-inventory.js"></script>
+{% endblock %}
+
+{% block dynamic_panels %}
+ <ul id="Libraries" class="x-hidden">
+ <li>
+ <img src="/static/img/s.gif" class="icon-show-all" />
+ <a href="{% url htsworkflow.frontend.samples.views.library %}">Index</a><br />
+ </li>
+ </ul>
+{% endblock %}
+
+{% block app_toolbar_west %}
+ <div id="Inventory Index" href="{% url htsworkflow.frontend.inventory.views.index %}"></div>
+{% endblock %}
+
+{% block app_toolbar_east %}
+ <!--<div id="Admin" href="/admin/"></div>-->
+{% endblock %}
+
+{% block content %}
+test
+{% endblock %}
\ No newline at end of file
--- /dev/null
+{% extends "inventory_app.html" %}
+
+{% block content %}
+<div id="grid_target"></div>
+{% endblock %}
+
\ No newline at end of file
(r'^experiments/', include('htsworkflow.frontend.experiments.urls')),
# AnalysTrack:
#(r'^analysis/', include('htsworkflow.frontend.analysis.urls')),
- # Report Views:
+ # Inventory urls
(r'^inventory/', include('htsworkflow.frontend.inventory.urls')),
+ # Report Views:
(r'^reports/', include('htsworkflow.frontend.reports.urls')),
# Library browser
(r'^library/$', 'htsworkflow.frontend.samples.views.library'),