Skip to content

Commit 92289a0

Browse files
ndg63276Mark Williams
andauthored
LIMS-128: Add plate view to queue page (#839)
Co-authored-by: Mark Williams <mark.williams@diamond.ac.uk>
1 parent 5116772 commit 92289a0

File tree

10 files changed

+103
-71
lines changed

10 files changed

+103
-71
lines changed

api/src/Page/Imaging.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -610,7 +610,7 @@ function _get_inspection_images()
610610
array_push($args, $this->arg('sid'));
611611
}
612612

613-
$images = $this->db->pq("SELECT i.containerid, si.containerinspectionid, ROUND(TIMESTAMPDIFF('HOUR', min(i2.bltimestamp), i.bltimestamp)/24,1) as delta, si.blsampleimageid, si.blsampleid, si.micronsperpixelx, si.micronsperpixely, si.blsampleimagescoreid, si.comments, TO_CHAR(si.bltimestamp, 'DD-MM-YYYY HH24:MI') as bltimestamp, sc.name as scorename, sc.score, sc.colour as scorecolour, max.maxscore, scorecolours.colour as maxscorecolour
613+
$images = $this->db->pq("SELECT i.containerid, si.containerinspectionid, ROUND(TIMESTAMPDIFF('HOUR', min(i2.bltimestamp), i.bltimestamp)/24,1) as delta, si.blsampleimageid, si.blsampleid, si.micronsperpixelx, si.micronsperpixely, si.blsampleimagescoreid, si.comments, TO_CHAR(si.bltimestamp, 'DD-MM-YYYY HH24:MI') as bltimestamp, sc.name as scorename, sc.score, sc.colour as scorecolour, max.maxscore, scorecolours.colour as maxscorecolour, b.location
614614
FROM blsampleimage si
615615
LEFT OUTER JOIN blsampleimagescore sc ON sc.blsampleimagescoreid = si.blsampleimagescoreid
616616
INNER JOIN containerinspection i ON i.containerinspectionid = si.containerinspectionid
@@ -620,6 +620,7 @@ function _get_inspection_images()
620620
INNER JOIN dewar d ON d.dewarid = c.dewarid
621621
INNER JOIN shipping s ON s.shippingid = d.shippingid
622622
INNER JOIN proposal p ON p.proposalid = s.proposalid
623+
INNER JOIN blsample b ON b.blsampleid = si.blsampleid
623624
624625
LEFT OUTER JOIN (SELECT blsampleid, max(score) as maxscore
625626
FROM BLSampleImageScore sc

api/src/Page/Sample.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -635,6 +635,22 @@ function _sub_samples()
635635
$third_inner_select_where = '';
636636
$args = array($this->proposalid);
637637

638+
if ($this->has_arg('s')) {
639+
$st = sizeof($args) + 1;
640+
$where .= " AND s.name LIKE CONCAT('%',:" . $st . ",'%')";
641+
array_push($args, $this->arg('s'));
642+
}
643+
644+
if ($this->has_arg('filter')) {
645+
$filters = array(
646+
'manual' => " AND ss.source='manual'",
647+
'auto' => " AND ss.source='auto'",
648+
'point' => " AND dp.experimentkind='SAD'",
649+
'region' => " AND dp.experimentkind='MESH'",
650+
);
651+
$where .= $filters[$this->arg('filter')];
652+
}
653+
638654
if ($this->has_arg('sid')) {
639655
$where .= ' AND s.blsampleid=:' . (sizeof($args) + 1);
640656
$first_inner_select_where .= ' AND s.blsampleid=:' . (sizeof($args) + 2);

client/src/css/partials/_imaging.scss

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,3 +226,7 @@ input[name=gap] {
226226
text-align: center;
227227
box-sizing: content-box;
228228
}
229+
230+
.plate-max-width {
231+
max-width: 700px;
232+
}

client/src/js/modules/imaging/views/queuecontainer.js

Lines changed: 44 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ define(['marionette',
1212

1313
'modules/imaging/models/plan',
1414
'modules/imaging/collections/plans',
15+
'modules/shipment/views/plate',
1516

1617
'collections/beamlinesetups',
1718

@@ -27,6 +28,7 @@ define(['marionette',
2728
SubSamples,
2829
TableView, table, FilterView, utils,
2930
DiffractionPlan, DiffractionPlans,
31+
PlateView,
3032
BeamlineSetups,
3133
template, pointemplate, gridtemplate, xfetemplate,
3234
VMXiPoint, VMXiGrid, VMXiXFE,
@@ -360,53 +362,6 @@ define(['marionette',
360362
{id: 'manual', name: 'Manual' },
361363
],
362364

363-
initialize: function(options) {
364-
ClientFilterView.__super__.initialize.call(this, options)
365-
366-
this.filterablecollection = options.collection.fullCollection// || options.collection
367-
this.shadowCollection = this.filterablecollection.clone()
368-
369-
this.listenTo(this.filterablecollection, 'add', function (model, collection, options) {
370-
this.shadowCollection.add(model, options)
371-
})
372-
this.listenTo(this.filterablecollection, 'remove', function (model, collection, options) {
373-
this.shadowCollection.remove(model, options)
374-
})
375-
this.listenTo(this.filterablecollection, 'sort', function (col) {
376-
if (!this.query()) this.shadowCollection.reset(col.models)
377-
})
378-
this.listenTo(this.filterablecollection, 'reset', function (col, options) {
379-
options = _.extend({reindex: true}, options || {})
380-
if (options.reindex && options.from == null && options.to == null) {
381-
this.shadowCollection.reset(col.models)
382-
if (this.selected()) this._filter()
383-
}
384-
})
385-
},
386-
387-
_filter: function() {
388-
var id = this.selected()
389-
this.trigger('selected:change', id, this.selectedName())
390-
if (id) {
391-
this.filterablecollection.reset(this.shadowCollection.filter(function(m) {
392-
if (id === 'region') {
393-
return m.get('X2') && m.get('Y2')
394-
395-
} else if (id === 'point') {
396-
return m.get('X') && m.get('Y') && !m.get('X2')
397-
}
398-
else if (id === 'auto') {
399-
return m.get('SOURCE') == 'auto'
400-
401-
} else if (id === 'manual') {
402-
return m.get('SOURCE') == 'manual'
403-
}
404-
}), {reindex: false})
405-
} else {
406-
console.log('reset', this.shadowCollection)
407-
this.filterablecollection.reset(this.shadowCollection.models, {reindex: false})
408-
}
409-
}
410365
})
411366

412367

@@ -517,6 +472,7 @@ define(['marionette',
517472
qfilt: '.qfilt',
518473
afilt: '.afilt',
519474
rimg: '.image',
475+
plate: '.plate',
520476
},
521477

522478
events: {
@@ -773,11 +729,20 @@ define(['marionette',
773729
return this.ui.notcompleted.is(':checked') ? 1 : null
774730
},
775731

732+
getSearch: function() {
733+
return this.table.filter.query() || null
734+
},
735+
736+
getFilter: function() {
737+
return this.afilt.$el.find('.current').attr('id') || null
738+
},
739+
776740
refreshSubSamples: function() {
777741
this.subsamples.fetch().done(this.onSubsamplesReady.bind(this))
778742
},
779743

780-
initialize: function() {
744+
initialize: function(options) {
745+
this.params = options.params
781746
this._lastSample = null
782747
this._subsamples_ready = []
783748

@@ -787,8 +752,9 @@ define(['marionette',
787752
this.unfilteredSubsamples = null
788753
this.subsamples = new SubSamples()
789754
this.subsamples.queryParams.cid = this.model.get('CONTAINERID')
790-
this.subsamples.state.pageSize = 10
755+
if (this.params.s) this.subsamples.queryParams.s = this.params.s
791756

757+
this.subsamples.state.pageSize = 10
792758
this._subsamples_ready.push(this.subsamples.fetch())
793759

794760
this.inspections = new ContainerInspections()
@@ -842,6 +808,12 @@ define(['marionette',
842808
}
843809
},
844810

811+
onSubsamplesReady: function() {
812+
this.getInspectionImages()
813+
this.refreshQSubSamples()
814+
this.listenTo(this.subsamples, 'change:isSelected', this.selectSubSample, this)
815+
this.listenTo(this.subsamples, 'sync add remove change:READYFORQUEUE', this.refreshQSubSamples, this)
816+
},
845817

846818
populatePresets: function() {
847819
this.ui.preset.html(this.plans.opts())
@@ -878,7 +850,7 @@ define(['marionette',
878850
},
879851

880852
selectSample: function() {
881-
this.subsamples.at(0).set({ isSelected: true })
853+
if (this.subsamples.at(0)) this.subsamples.at(0).set({ isSelected: true })
882854
},
883855

884856
refreshQSubSamples: function() {
@@ -902,6 +874,8 @@ define(['marionette',
902874
this.ui.unqueuebutton.hide()
903875
this.subsamples.queryParams.nodata = this.getNoData.bind(this)
904876
this.subsamples.queryParams.notcompleted = this.getNotCompleted.bind(this)
877+
this.subsamples.queryParams.s = this.getSearch.bind(this)
878+
this.subsamples.queryParams.filter = this.getFilter.bind(this)
905879
this._ready.done(this.doOnRender.bind(this))
906880
},
907881

@@ -927,6 +901,8 @@ define(['marionette',
927901
collection: this.subsamples,
928902
columns: subSamplesColumns,
929903
tableClass: 'subsamples',
904+
filter: 's',
905+
search: this.params.s,
930906
loading: true,
931907
backgrid: { row: ClickableRow, emptyText: 'No sub samples found' },
932908
noPageUrl: true,
@@ -992,11 +968,29 @@ define(['marionette',
992968
})
993969

994970
this.qsmps.show(this.table2)
971+
972+
this.plateView = new PlateView({ collection: this.subsamples.fullCollection, type: this.type, inspectionimages: this.inspectionimages, showMaxScore: true })
973+
this.listenTo(this.plateView, 'dropClicked', this.filterByLocation, this)
974+
this.plate.show(this.plateView)
995975
},
996976

997977
onShow: function() {
998978
this.rimg.show(this.image)
999979
},
980+
981+
filterByLocation: function(pos) {
982+
if (!pos) return;
983+
var namedrop = this.type.getName(pos)+'d'+this.type.getDrop(pos)
984+
if (this.table.filter.query() === namedrop) {
985+
this.table.filter.clearSearchBox()
986+
} else {
987+
this.table.filter.searchBox().val(namedrop)
988+
}
989+
this.table.filter._updateUrl()
990+
this.subsamples.fetch().done(this.selectSample.bind(this))
991+
var i = this.inspectionimages.findWhere({ LOCATION: pos.toString() })
992+
this.image.setModel(i)
993+
},
1000994

1001995
})
1002996

client/src/js/modules/shipment/components/container-queue-wrapper.vue

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ export default {
4343
},
4444
props: {
4545
'cid': Number,
46+
'search': String,
4647
},
4748
data: function() {
4849
return {
@@ -59,6 +60,7 @@ export default {
5960
options: function() {
6061
return {
6162
model: this.model,
63+
params: { s: this.search }
6264
}
6365
},
6466
proposalType : function() {
@@ -106,4 +108,4 @@ export default {
106108
}
107109
108110
}
109-
</script>
111+
</script>

client/src/js/modules/shipment/router.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ define(['utils/lazyrouter'], function(LazyRouter) {
1010
'shipments/pickup/sid/:sid': 'rebook_pickup',
1111

1212
'containers/cid/:cid(/iid/:iid)(/sid/:sid)': 'view_container',
13-
'containers/queue/:cid': 'queue_container',
13+
'containers/queue/:cid(/s/:s)': 'queue_container',
1414
'containers/add/did/:did': 'add_container',
1515
'containers/add/visit/:visit': 'add_container_visit',
1616
'containers(/s/:s)(/ty/:ty)(/page/:page)': 'container_list',
@@ -46,4 +46,4 @@ define(['utils/lazyrouter'], function(LazyRouter) {
4646
// controller: c
4747
rjsController: 'modules/shipment/controller',
4848
})
49-
})
49+
})

client/src/js/modules/shipment/routes.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -353,11 +353,12 @@ const routes = [
353353
}
354354
},
355355
{
356-
path: '/containers/queue/:cid([0-9]+)',
356+
path: '/containers/queue/:cid([0-9]+)(/s/)?:s([a-zA-Z0-9_-]+)?',
357357
name: 'container-queue',
358358
component: ContainerQueueWrapper,
359359
props: route => ({
360360
cid: +route.params.cid,
361+
search: route.params.s || '',
361362
}),
362363
},
363364
{
@@ -537,4 +538,4 @@ const routes = [
537538
},
538539
]
539540

540-
export default routes
541+
export default routes

client/src/js/modules/shipment/views/plate.js

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,23 +29,26 @@ define(['marionette', 'backbone', 'utils', 'backbone-validation'], function(Mari
2929
e.preventDefault()
3030
var pos = this._xy_to_drop(utils.get_xy(e,this.$el))
3131
if (pos) {
32+
this.lastClickedDrop = pos
3233
var drop = this.collection.findWhere({ LOCATION: pos.toString() })
3334

3435
this.trigger('plate:select')
36+
this.trigger('dropClicked', pos)
3537
if (drop) drop.set('isSelected', true)
3638
this.drawPlate()
3739
}
3840
},
3941

4042
initialize: function(options) {
4143
this.pt = this.getOption('type')
44+
this.lastClickedDrop = null
4245
this.inspectionimages = options && options.inspectionimages
4346
if (this.inspectionimages) this.listenTo(this.inspectionimages, 'sync', this.render, this)
4447

4548
this.hover = {}
4649
this.showImageStatus = this.getOption('showImageStatus')
4750
this.showSampleStatus = this.getOption('showSampleStatus')
48-
this.showMaxScore = false
51+
this.showMaxScore = this.getOption('showMaxScore')
4952

5053
Backbone.Validation.bind(this, {
5154
collection: this.collection
@@ -187,7 +190,7 @@ define(['marionette', 'backbone', 'utils', 'backbone-validation'], function(Mari
187190
var did = (k*this.pt.get('drop_per_well_x'))+j
188191
if (this.pt.get('well_drop') > -1) {
189192
if (did == this.pt.get('well_drop')) continue
190-
if (did > this.pt.get('well_drop')) did--;
193+
if (did > this.pt.get('well_drop')) did--;
191194
}
192195

193196
var sampleid = i*this.pt.dropTotal()+did+1
@@ -198,6 +201,7 @@ define(['marionette', 'backbone', 'utils', 'backbone-validation'], function(Mari
198201

199202
this.ctx.beginPath()
200203
this.ctx.lineWidth = 1;
204+
201205
if (sample && sample.get('isSelected')) {
202206
this.ctx.strokeStyle = 'cyan'
203207

@@ -213,7 +217,12 @@ define(['marionette', 'backbone', 'utils', 'backbone-validation'], function(Mari
213217
} else this.ctx.strokeStyle = '#ddd'
214218

215219
this.ctx.rect(this.pt.get('drop_offset_x')+this.pt.get('offset_x')+row*(this.pt.get('well_width')+this.pt.get('well_pad'))+(j*this.pt.get('drop_widthpx')+this.pt.get('drop_pad')), this.pt.get('drop_offset_y')+this.pt.get('offset_y')+col*(this.pt.get('well_height')+this.pt.get('well_pad'))+(k*this.pt.get('drop_heightpx')+this.pt.get('drop_pad')), this.pt.get('drop_widthpx'), this.pt.get('drop_heightpx'))
216-
220+
221+
// Highlight last clicked drop
222+
if (sampleid == this.lastClickedDrop) {
223+
this.ctx.fillStyle = '#dddddd'
224+
this.ctx.fill()
225+
}
217226

218227
// Highlight Hovered Sample
219228
if (this.hover == sampleid) {
@@ -234,7 +243,7 @@ define(['marionette', 'backbone', 'utils', 'backbone-validation'], function(Mari
234243
this.ctx.fill()
235244
}
236245
}
237-
246+
238247
// Show status
239248
if (sample && this.showSampleStatus) {
240249
if (this.rankOption) {

client/src/js/templates/imaging/queuecontainer.html

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ <h1>Prepare Container for Data Collection</h1>
1818
<ul>
1919
<li>
2020
<span class="label">Container</span>
21-
<span class="NAME"><%-NAME%></span>
21+
<span class="NAME"><a href="/containers/cid/<%-CONTAINERID%>"><%-NAME%></a></span>
2222
</li>
2323

2424
<li>
@@ -28,6 +28,8 @@ <h1>Prepare Container for Data Collection</h1>
2828
</ul>
2929
</div>
3030

31+
<div class="plate plate-max-width"></div>
32+
3133
<h2>Available Samples</h2>
3234
<div class="filter">
3335
<span class="r">
@@ -38,9 +40,7 @@ <h2>Available Samples</h2>
3840
<li><label><input type="checkbox" name="nodata" /> Without Data</label></li>
3941
<li><label><input type="checkbox" name="notcompleted" /> Not Completed</label></li>
4042
</ul>
41-
</div>
42-
<div class="filter">
43-
<div class="filter filter-nohide afilt"></div>
43+
<span class="filter filter-nohide afilt"></span>
4444
</div>
4545
<div class="asamples"></div>
4646
</div>

0 commit comments

Comments
 (0)