diff --git a/api/src/Page/Imaging.php b/api/src/Page/Imaging.php index 43c480859..4d09aeb8a 100644 --- a/api/src/Page/Imaging.php +++ b/api/src/Page/Imaging.php @@ -611,7 +611,7 @@ function _get_inspection_images() array_push($args, $this->arg('sid')); } - $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 + $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 FROM blsampleimage si LEFT OUTER JOIN blsampleimagescore sc ON sc.blsampleimagescoreid = si.blsampleimagescoreid INNER JOIN containerinspection i ON i.containerinspectionid = si.containerinspectionid @@ -621,6 +621,7 @@ function _get_inspection_images() INNER JOIN dewar d ON d.dewarid = c.dewarid INNER JOIN shipping s ON s.shippingid = d.shippingid INNER JOIN proposal p ON p.proposalid = s.proposalid + INNER JOIN blsample b ON b.blsampleid = si.blsampleid LEFT OUTER JOIN (SELECT blsampleid, max(score) as maxscore FROM BLSampleImageScore sc diff --git a/api/src/Page/Sample.php b/api/src/Page/Sample.php index eb8850184..0b06ccd6d 100644 --- a/api/src/Page/Sample.php +++ b/api/src/Page/Sample.php @@ -634,6 +634,22 @@ function _sub_samples() $third_inner_select_where = ''; $args = array($this->proposalid); + if ($this->has_arg('s')) { + $st = sizeof($args) + 1; + $where .= " AND s.name LIKE CONCAT('%',:" . $st . ",'%')"; + array_push($args, $this->arg('s')); + } + + if ($this->has_arg('filter')) { + $filters = array( + 'manual' => " AND ss.source='manual'", + 'auto' => " AND ss.source='auto'", + 'point' => " AND dp.experimentkind='SAD'", + 'region' => " AND dp.experimentkind='MESH'", + ); + $where .= $filters[$this->arg('filter')]; + } + if ($this->has_arg('sid')) { $where .= ' AND s.blsampleid=:' . (sizeof($args) + 1); $first_inner_select_where .= ' AND s.blsampleid=:' . (sizeof($args) + 2); diff --git a/client/src/css/partials/_imaging.scss b/client/src/css/partials/_imaging.scss index 0fc3ade5b..96f0a5db0 100644 --- a/client/src/css/partials/_imaging.scss +++ b/client/src/css/partials/_imaging.scss @@ -226,3 +226,7 @@ input[name=gap] { text-align: center; box-sizing: content-box; } + +.plate-max-width { + max-width: 700px; +} diff --git a/client/src/js/modules/imaging/views/queuecontainer.js b/client/src/js/modules/imaging/views/queuecontainer.js index 2ec12d35d..4369c4448 100644 --- a/client/src/js/modules/imaging/views/queuecontainer.js +++ b/client/src/js/modules/imaging/views/queuecontainer.js @@ -12,6 +12,7 @@ define(['marionette', 'modules/imaging/models/plan', 'modules/imaging/collections/plans', + 'modules/shipment/views/plate', 'collections/beamlinesetups', @@ -27,6 +28,7 @@ define(['marionette', SubSamples, TableView, table, FilterView, utils, DiffractionPlan, DiffractionPlans, + PlateView, BeamlineSetups, template, pointemplate, gridtemplate, xfetemplate, VMXiPoint, VMXiGrid, VMXiXFE, @@ -361,53 +363,6 @@ define(['marionette', {id: 'manual', name: 'Manual' }, ], - initialize: function(options) { - ClientFilterView.__super__.initialize.call(this, options) - - this.filterablecollection = options.collection.fullCollection// || options.collection - this.shadowCollection = this.filterablecollection.clone() - - this.listenTo(this.filterablecollection, 'add', function (model, collection, options) { - this.shadowCollection.add(model, options) - }) - this.listenTo(this.filterablecollection, 'remove', function (model, collection, options) { - this.shadowCollection.remove(model, options) - }) - this.listenTo(this.filterablecollection, 'sort', function (col) { - if (!this.query()) this.shadowCollection.reset(col.models) - }) - this.listenTo(this.filterablecollection, 'reset', function (col, options) { - options = _.extend({reindex: true}, options || {}) - if (options.reindex && options.from == null && options.to == null) { - this.shadowCollection.reset(col.models) - if (this.selected()) this._filter() - } - }) - }, - - _filter: function() { - var id = this.selected() - this.trigger('selected:change', id, this.selectedName()) - if (id) { - this.filterablecollection.reset(this.shadowCollection.filter(function(m) { - if (id === 'region') { - return m.get('X2') && m.get('Y2') - - } else if (id === 'point') { - return m.get('X') && m.get('Y') && !m.get('X2') - } - else if (id === 'auto') { - return m.get('SOURCE') == 'auto' - - } else if (id === 'manual') { - return m.get('SOURCE') == 'manual' - } - }), {reindex: false}) - } else { - console.log('reset', this.shadowCollection) - this.filterablecollection.reset(this.shadowCollection.models, {reindex: false}) - } - } }) @@ -518,6 +473,7 @@ define(['marionette', qfilt: '.qfilt', afilt: '.afilt', rimg: '.image', + plate: '.plate', }, events: { @@ -762,27 +718,40 @@ define(['marionette', return this.ui.notcompleted.is(':checked') ? 1 : null }, + getSearch: function() { + return this.table.filter.query() || null + }, + + getFilter: function() { + return this.afilt.$el.find('.current').attr('id') || null + }, + refreshSubSamples: function() { this.subsamples.fetch() }, - initialize: function() { + initialize: function(options) { + this.params = options.params this._lastSample = null + this._subsamples_ready = [] this.platetypes = new PlateTypes() this.type = this.platetypes.findWhere({ name: this.model.get('CONTAINERTYPE') }) this.subsamples = new SubSamples() this.subsamples.queryParams.cid = this.model.get('CONTAINERID') + if (this.params.s) this.subsamples.queryParams.s = this.params.s + this.subsamples.state.pageSize = 10 - this.listenTo(this.subsamples, 'change:isSelected', this.selectSubSample, this) - this.listenTo(this.subsamples, 'sync add remove change:READYFORQUEUE', this.refreshQSubSamples, this) - this.subsamples.fetch() + this._subsamples_ready.push(this.subsamples.fetch()) this.inspections = new ContainerInspections() this.inspections.queryParams.cid = this.model.get('CONTAINERID') this.inspections.setSorting('BLTIMESTAMP', 1) - this.inspections.fetch().done(this.getInspectionImages.bind(this)) + + this._subsamples_ready.push(this.inspections.fetch()) + + $.when.apply($, this._subsamples_ready).done(this.onSubsamplesReady.bind(this)) this.inspectionimages = new InspectionImages() @@ -827,6 +796,12 @@ define(['marionette', } }, + onSubsamplesReady: function() { + this.getInspectionImages() + this.refreshQSubSamples() + this.listenTo(this.subsamples, 'change:isSelected', this.selectSubSample, this) + this.listenTo(this.subsamples, 'sync add remove change:READYFORQUEUE', this.refreshQSubSamples, this) + }, populatePresets: function() { this.ui.preset.html(this.plans.opts()) @@ -838,7 +813,7 @@ define(['marionette', }, selectSample: function() { - this.subsamples.at(0).set({ isSelected: true }) + if (this.subsamples.at(0)) this.subsamples.at(0).set({ isSelected: true }) }, refreshQSubSamples: function() { @@ -861,6 +836,8 @@ define(['marionette', onRender: function() { this.subsamples.queryParams.nodata = this.getNoData.bind(this) this.subsamples.queryParams.notcompleted = this.getNotCompleted.bind(this) + this.subsamples.queryParams.s = this.getSearch.bind(this) + this.subsamples.queryParams.filter = this.getFilter.bind(this) this._ready.done(this.doOnRender.bind(this)) }, @@ -886,6 +863,8 @@ define(['marionette', collection: this.subsamples, columns: subSamplesColumns, tableClass: 'subsamples', + filter: 's', + search: this.params.s, loading: true, backgrid: { row: ClickableRow, emptyText: 'No sub samples found' }, noPageUrl: true, @@ -945,11 +924,29 @@ define(['marionette', }) this.qsmps.show(this.table2) + + this.plateView = new PlateView({ collection: this.subsamples.fullCollection, type: this.type, inspectionimages: this.inspectionimages, showMaxScore: true }) + this.listenTo(this.plateView, 'dropClicked', this.filterByLocation, this) + this.plate.show(this.plateView) }, onShow: function() { this.rimg.show(this.image) }, + + filterByLocation: function(pos) { + if (!pos) return; + var namedrop = this.type.getName(pos)+'d'+this.type.getDrop(pos) + if (this.table.filter.query() === namedrop) { + this.table.filter.clearSearchBox() + } else { + this.table.filter.searchBox().val(namedrop) + } + this.table.filter._updateUrl() + this.subsamples.fetch().done(this.selectSample.bind(this)) + var i = this.inspectionimages.findWhere({ LOCATION: pos.toString() }) + this.image.setModel(i) + }, }) diff --git a/client/src/js/modules/shipment/components/container-queue-wrapper.vue b/client/src/js/modules/shipment/components/container-queue-wrapper.vue index 62b8c7b1a..1e7d1de24 100644 --- a/client/src/js/modules/shipment/components/container-queue-wrapper.vue +++ b/client/src/js/modules/shipment/components/container-queue-wrapper.vue @@ -43,6 +43,7 @@ export default { }, props: { 'cid': Number, + 'search': String, }, data: function() { return { @@ -59,6 +60,7 @@ export default { options: function() { return { model: this.model, + params: { s: this.search } } }, proposalType : function() { @@ -106,4 +108,4 @@ export default { } } - \ No newline at end of file + diff --git a/client/src/js/modules/shipment/router.js b/client/src/js/modules/shipment/router.js index 99fc5c71c..ae2c3de58 100644 --- a/client/src/js/modules/shipment/router.js +++ b/client/src/js/modules/shipment/router.js @@ -10,7 +10,7 @@ define(['utils/lazyrouter'], function(LazyRouter) { 'shipments/pickup/sid/:sid': 'rebook_pickup', 'containers/cid/:cid(/iid/:iid)(/sid/:sid)': 'view_container', - 'containers/queue/:cid': 'queue_container', + 'containers/queue/:cid(/s/:s)': 'queue_container', 'containers/add/did/:did': 'add_container', 'containers/add/visit/:visit': 'add_container_visit', 'containers(/s/:s)(/ty/:ty)(/page/:page)': 'container_list', @@ -46,4 +46,4 @@ define(['utils/lazyrouter'], function(LazyRouter) { // controller: c rjsController: 'modules/shipment/controller', }) -}) \ No newline at end of file +}) diff --git a/client/src/js/modules/shipment/routes.js b/client/src/js/modules/shipment/routes.js index 673cd6531..659a1a5a0 100644 --- a/client/src/js/modules/shipment/routes.js +++ b/client/src/js/modules/shipment/routes.js @@ -353,11 +353,12 @@ const routes = [ } }, { - path: '/containers/queue/:cid([0-9]+)', + path: '/containers/queue/:cid([0-9]+)(/s/)?:s([a-zA-Z0-9_-]+)?', name: 'container-queue', component: ContainerQueueWrapper, props: route => ({ cid: +route.params.cid, + search: route.params.s || '', }), }, { @@ -537,4 +538,4 @@ const routes = [ }, ] -export default routes \ No newline at end of file +export default routes diff --git a/client/src/js/modules/shipment/views/plate.js b/client/src/js/modules/shipment/views/plate.js index 62d6b0a90..39d88b2b9 100644 --- a/client/src/js/modules/shipment/views/plate.js +++ b/client/src/js/modules/shipment/views/plate.js @@ -29,9 +29,11 @@ define(['marionette', 'backbone', 'utils', 'backbone-validation'], function(Mari e.preventDefault() var pos = this._xy_to_drop(utils.get_xy(e,this.$el)) if (pos) { + this.lastClickedDrop = pos var drop = this.collection.findWhere({ LOCATION: pos.toString() }) this.trigger('plate:select') + this.trigger('dropClicked', pos) if (drop) drop.set('isSelected', true) this.drawPlate() } @@ -39,13 +41,14 @@ define(['marionette', 'backbone', 'utils', 'backbone-validation'], function(Mari initialize: function(options) { this.pt = this.getOption('type') + this.lastClickedDrop = null this.inspectionimages = options && options.inspectionimages if (this.inspectionimages) this.listenTo(this.inspectionimages, 'sync', this.render, this) this.hover = {} this.showImageStatus = this.getOption('showImageStatus') this.showSampleStatus = this.getOption('showSampleStatus') - this.showMaxScore = false + this.showMaxScore = this.getOption('showMaxScore') Backbone.Validation.bind(this, { collection: this.collection @@ -187,7 +190,7 @@ define(['marionette', 'backbone', 'utils', 'backbone-validation'], function(Mari var did = (k*this.pt.get('drop_per_well_x'))+j if (this.pt.get('well_drop') > -1) { if (did == this.pt.get('well_drop')) continue - if (did > this.pt.get('well_drop')) did--; + if (did > this.pt.get('well_drop')) did--; } var sampleid = i*this.pt.dropTotal()+did+1 @@ -198,6 +201,7 @@ define(['marionette', 'backbone', 'utils', 'backbone-validation'], function(Mari this.ctx.beginPath() this.ctx.lineWidth = 1; + if (sample && sample.get('isSelected')) { this.ctx.strokeStyle = 'cyan' @@ -213,7 +217,12 @@ define(['marionette', 'backbone', 'utils', 'backbone-validation'], function(Mari } else this.ctx.strokeStyle = '#ddd' 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')) - + + // Highlight last clicked drop + if (sampleid == this.lastClickedDrop) { + this.ctx.fillStyle = '#dddddd' + this.ctx.fill() + } // Highlight Hovered Sample if (this.hover == sampleid) { @@ -234,7 +243,7 @@ define(['marionette', 'backbone', 'utils', 'backbone-validation'], function(Mari this.ctx.fill() } } - + // Show status if (sample && this.showSampleStatus) { if (this.rankOption) { diff --git a/client/src/js/templates/imaging/queuecontainer.html b/client/src/js/templates/imaging/queuecontainer.html index cff3c820b..9d219c67f 100644 --- a/client/src/js/templates/imaging/queuecontainer.html +++ b/client/src/js/templates/imaging/queuecontainer.html @@ -20,7 +20,7 @@

Prepare Container for Data Collection

+
+

Available Samples

@@ -40,9 +42,7 @@

Available Samples

  • -
    -
    -
    +
    diff --git a/client/src/js/views/search.js b/client/src/js/views/search.js index db89d1453..64f5ae455 100644 --- a/client/src/js/views/search.js +++ b/client/src/js/views/search.js @@ -3,7 +3,7 @@ define(['backbone'], function(Backbone) { var Search = Backbone.View.extend({ /** @property */ events: { - "keyup input[type=search]": "search", + "input input[type=search]": "search", "click a[data-backgrid-action=clear]": "clear", "submit": "search" }, @@ -131,12 +131,17 @@ define(['backbone'], function(Backbone) { collection.getFirstPage({data: data, reset: true, fetch: true}); } else collection.fetch({data: data, reset: true}); - if (this.url) { - var url = this.urlFragment ? - window.location.pathname.replace(new RegExp('\\/'+this.urlFragment+'\\/(\\w|-)+'), '')+(this.value ? '/'+this.urlFragment+'/'+this.value : '') : - window.location.pathname.replace(/\/\w+$/, '')+(this.value ? '/'+this.value : '') - window.history.pushState({}, '', url) - } + this._updateUrl() + }, + + _updateUrl: function() { + this.value = this.query() + if (this.url) { + var url = this.urlFragment ? + window.location.pathname.replace(new RegExp('\\/'+this.urlFragment+'\\/(\\w|-)+'), '')+(this.value ? '/'+this.urlFragment+'/'+this.value : '') : + window.location.pathname.replace(/\/\w+$/, '')+(this.value ? '/'+this.value : '') + window.history.pushState({}, '', url) + } }, /**