From 3242f8ffe5565cf0f29db7f1d13c8fdb38ead33f Mon Sep 17 00:00:00 2001 From: Mark Williams Date: Tue, 19 Nov 2024 11:20:00 +0000 Subject: [PATCH 1/2] LIMS-103: Fix various bugs in Screens UI --- api/src/Database/Type/MySQL.php | 1 + api/src/Page/Imaging.php | 13 ++++--- api/src/Page/Shipment.php | 13 ++++++- client/src/js/collections/containertypes.js | 35 ++++++++++++------- client/src/js/models/containertypes.js | 8 +++++ client/src/js/modules/imaging/controller.js | 4 +-- client/src/js/modules/imaging/routes.js | 6 ++-- .../js/modules/imaging/views/screenadmin.js | 4 +-- .../modules/imaging/views/screencompadmin.js | 30 +++++++++++++--- .../src/js/templates/imaging/screencomps.html | 5 +++ 10 files changed, 90 insertions(+), 29 deletions(-) create mode 100644 client/src/js/models/containertypes.js diff --git a/api/src/Database/Type/MySQL.php b/api/src/Database/Type/MySQL.php index a04c8c7da..baffd67c3 100644 --- a/api/src/Database/Type/MySQL.php +++ b/api/src/Database/Type/MySQL.php @@ -130,6 +130,7 @@ class MySQL extends DatabaseParent { // VMXi 'ContainerInspection', + 'ContainerType', 'Imager', 'Screen', 'ScreenComponentGroup', diff --git a/api/src/Page/Imaging.php b/api/src/Page/Imaging.php index fa19544ad..63e8ff48f 100644 --- a/api/src/Page/Imaging.php +++ b/api/src/Page/Imaging.php @@ -45,6 +45,7 @@ class Imaging extends Page 'PROPOSALID' => '\d+', 'COMPONENTID' => '\d+', 'GLOBAL' => '\d', + 'CONTAINERTYPEID' => '\d*', 'SCREENCOMPONENTGROUPID' => '\d+', 'SCREENCOMPONENTID' => '\d+', 'CONCENTRATION' => '\d+(.\d+)?', @@ -865,10 +866,11 @@ function _get_screens() array_push($args, $this->arg('scid')); } - $screens = $this->db->pq("SELECT 96 as capacity, CONCAT(p.proposalcode, p.proposalnumber) as prop, s.global, s.name, s.screenid, s.proposalid, count(distinct sg.screencomponentgroupid) as groups, count(distinct sc.screencomponentid) as components + $screens = $this->db->pq("SELECT ct.name as containertypeid, IFNULL(ct.capacity, 96) as capacity, CONCAT(p.proposalcode, p.proposalnumber) as prop, s.global, s.name, s.screenid, s.proposalid, count(distinct sg.screencomponentgroupid) as groups, count(distinct sc.screencomponentid) as components FROM screen s LEFT OUTER JOIN screencomponentgroup sg ON sg.screenid = s.screenid LEFT OUTER JOIN screencomponent sc ON sc.screencomponentgroupid = sg.screencomponentgroupid + LEFT OUTER JOIN containertype ct ON ct.containertypeid = s.containertypeid INNER JOIN proposal p ON p.proposalid = s.proposalid WHERE $where GROUP BY CONCAT(p.proposalcode, p.proposalnumber), s.global, s.name, s.screenid, s.proposalid", $args); @@ -888,8 +890,8 @@ function _add_screen() if (!$this->has_arg('NAME')) $this->_error('No screen name provided'); - $this->db->pq("INSERT INTO screen (screenid, name, proposalid) - VALUES (s_screen.nextval, :1, :2) RETURNING screenid INTO :id", array($this->arg('NAME'), $this->proposalid)); + $this->db->pq("INSERT INTO screen (screenid, name, global, proposalid) + VALUES (s_screen.nextval, :1, :2, :3) RETURNING screenid INTO :id", array($this->arg('NAME'), $this->arg('GLOBAL'), $this->proposalid)); $this->_output(array('SCREENID' => $this->db->id())); } @@ -907,9 +909,10 @@ function _update_screen() if (!sizeof($sc)) $this->_error('No such screen'); - foreach (array('NAME', 'GLOBAL') as $f) { + foreach (array('NAME', 'GLOBAL', 'CONTAINERTYPEID') as $f) { if ($this->has_arg($f)) { - $this->db->pq('UPDATE screen SET ' . $f . '=:1 WHERE screenid=:2', array($this->arg($f), $this->arg('scid'))); + $argf = $this->arg($f) == '' ? null : $this->arg($f); + $this->db->pq('UPDATE screen SET ' . $f . '=:1 WHERE screenid=:2', array($argf, $this->arg('scid'))); $this->_output(array($f => $this->arg($f))); } } diff --git a/api/src/Page/Shipment.php b/api/src/Page/Shipment.php index fdb44b725..0bcd903a7 100644 --- a/api/src/Page/Shipment.php +++ b/api/src/Page/Shipment.php @@ -146,6 +146,7 @@ class Shipment extends Page 'TOKEN' => '\w+', 'tracking_number' => '\w+', 'AWBURL' => '[\w\:\/\.\-]+', + 'PROPOSALTYPE' => '\w+', 'manifest' => '\d', 'currentuser' => '\d', @@ -2499,6 +2500,7 @@ function _add_container_history() function _get_container_types() { $where = ''; + $args = array(); // By default only return active container types. // If all param set return everything if ($this->has_arg('all')) { @@ -2506,7 +2508,16 @@ function _get_container_types() } else { $where .= 'ct.active = 1'; } - $rows = $this->db->pq("SELECT ct.containerTypeId, name, ct.proposalType, ct.capacity, ct.wellPerRow, ct.dropPerWellX, ct.dropPerWellY, ct.dropHeight, ct.dropWidth, ct.wellDrop FROM ContainerType ct WHERE $where"); + if ($this->has_arg('ty')) { + if ($this->arg('ty') == 'plate') { + $where .= " AND ct.wellperrow is not null"; + } + } + if ($this->has_arg('PROPOSALTYPE')) { + $where .= ' AND ct.proposaltype = :1'; + array_push($args, $this->arg('PROPOSALTYPE')); + } + $rows = $this->db->pq("SELECT ct.containerTypeId, name, ct.proposalType, ct.capacity, ct.wellPerRow, ct.dropPerWellX, ct.dropPerWellY, ct.dropHeight, ct.dropWidth, ct.wellDrop FROM ContainerType ct WHERE $where", $args); $this->_output(array('total' => count($rows), 'data' => $rows)); } diff --git a/client/src/js/collections/containertypes.js b/client/src/js/collections/containertypes.js index d8d4039f0..c9ec1b7ae 100644 --- a/client/src/js/collections/containertypes.js +++ b/client/src/js/collections/containertypes.js @@ -1,13 +1,24 @@ -define(['backbone', 'utils/kvcollection'], function(Backbone, KVCollection) { - - return Backbone.Collection.extend({ - - initialize: function(options) { - this.add({ name: 'Puck' }) - this.add({ name: 'CrystalQuickX', plate: 1 }) +define(['backbone.paginator', 'models/containertypes', 'utils/kvcollection'], function(PageableCollection, ContainerTypes, KVCollection) { + + return PageableCollection.extend(_.extend({}, KVCollection, { + model: ContainerTypes, + mode: 'client', + url: '/shipment/containers/types', + + state: { + pageSize: 9999, }, - - keyAttribute: 'name', - valueAttribute: 'name', - }) -}) \ No newline at end of file + + parseState: function(r, q, state, options) { + return { totalRecords: r.total } + }, + + parseRecords: function(r, options) { + return r.data + }, + + keyAttribute: 'NAME', + valueAttribute: 'CONTAINERTYPEID', + + })) +}) diff --git a/client/src/js/models/containertypes.js b/client/src/js/models/containertypes.js new file mode 100644 index 000000000..93833184d --- /dev/null +++ b/client/src/js/models/containertypes.js @@ -0,0 +1,8 @@ +define(['backbone'], function(Backbone) { + + return Backbone.Model.extend({ + idAttribute: 'CONTAINERTYPEID', + }) + +}) + diff --git a/client/src/js/modules/imaging/controller.js b/client/src/js/modules/imaging/controller.js index 7b655ba82..34e14dac0 100644 --- a/client/src/js/modules/imaging/controller.js +++ b/client/src/js/modules/imaging/controller.js @@ -87,7 +87,7 @@ define(['marionette', screens.fetch({ success: function(r) { app.content.show(new ScreenAdmin({ collection: screens })) - app.bc.reset([{ title: 'Crysallisation Screens', url: '/imaging/screen' }]) + app.bc.reset([{ title: 'Crystallisation Screens', url: '/imaging/screen' }]) }, error: function() { @@ -155,4 +155,4 @@ define(['marionette', }) return controller -}) \ No newline at end of file +}) diff --git a/client/src/js/modules/imaging/routes.js b/client/src/js/modules/imaging/routes.js index 3f184302f..2c347f783 100644 --- a/client/src/js/modules/imaging/routes.js +++ b/client/src/js/modules/imaging/routes.js @@ -165,7 +165,7 @@ const routes = [ options: { collection: new Screens() }, - breadcrumbs: [{ title: 'Crysallisation Screens', url: '/imaging/screen' }], + breadcrumbs: [{ title: 'Crystallisation Screens', url: '/imaging/screen' }], }, }, { @@ -176,7 +176,7 @@ const routes = [ options: { model: new Screen({SCREENID: route.params.sid}) }, - breadcrumbs: [{ title: 'Crysallisation Screens', url: '/imaging/screen' }], + breadcrumbs: [{ title: 'Crystallisation Screens', url: '/imaging/screen' }], breadcrumb_tags: ['NAME'] }), }, @@ -184,4 +184,4 @@ const routes = [ } ] -export default routes \ No newline at end of file +export default routes diff --git a/client/src/js/modules/imaging/views/screenadmin.js b/client/src/js/modules/imaging/views/screenadmin.js index 6d5cde10c..cc98f8727 100644 --- a/client/src/js/modules/imaging/views/screenadmin.js +++ b/client/src/js/modules/imaging/views/screenadmin.js @@ -81,7 +81,7 @@ define(['marionette', 'backbone', addScreen: function(e) { e.preventDefault() if (this.$el.find('.new').length) return - this.collection.add(new Screen({ new: true })) + this.collection.unshift(new Screen({ new: true })) }, @@ -92,4 +92,4 @@ define(['marionette', 'backbone', }, }) -}) \ No newline at end of file +}) diff --git a/client/src/js/modules/imaging/views/screencompadmin.js b/client/src/js/modules/imaging/views/screencompadmin.js index ddfd7f195..507cef5f9 100644 --- a/client/src/js/modules/imaging/views/screencompadmin.js +++ b/client/src/js/modules/imaging/views/screencompadmin.js @@ -8,14 +8,14 @@ define(['marionette', 'backbone', 'backgrid', 'views/table', 'views/filter', 'modules/imaging/collections/screencomponents', 'modules/imaging/views/screencomponentgroup', - 'modules/shipment/collections/platetypes', + 'collections/containertypes', 'modules/shipment/views/plate', 'templates/imaging/screencomps.html', 'backbone-validation', ], function(Marionette, Backbone, Backgrid, TableView, FilterView, Editable, - ComponentGroup, ComponentGroups, Component, Components, GroupView, PlateType, PlateView, + ComponentGroup, ComponentGroups, Component, Components, GroupView, PlateTypes, PlateView, template) { @@ -29,6 +29,10 @@ define(['marionette', 'backbone', 'backgrid', 'views/table', 'views/filter', className: 'content', template: template, + ui: { + containertype: '.containertype', + }, + regions: { group: '.group', plate: '.plate', @@ -40,6 +44,7 @@ define(['marionette', 'backbone', 'backgrid', 'views/table', 'views/filter', modelEvents: { 'change:CAPACITY': 'updatePositions', + 'change:CONTAINERTYPEID': 'updateCapacity', }, initialize: function(options) { @@ -58,6 +63,14 @@ define(['marionette', 'backbone', 'backgrid', 'views/table', 'views/filter', this.updatePositions() }, + updateCapacity: function() { + var newct = this.ctypes.findWhere({ CONTAINERTYPEID: this.model.get('CONTAINERTYPEID') }) + var newcapacity = newct ? newct.get('CAPACITY') : 96 + this.model.set('CAPACITY', newcapacity) + this.$el.find('.CAPACITY').html(newcapacity) + this.onRender() + }, + updatePositions: function(e) { var pos = [] _.each(_.range(this.model.get('CAPACITY')), function(i) { @@ -69,6 +82,7 @@ define(['marionette', 'backbone', 'backgrid', 'views/table', 'views/filter', }, setGroup: function(pos) { + if (!pos) return var s = this.collection.findWhere({ POSITION: pos.toString() }) if (s) this.groupview.setModel(s) else { @@ -87,17 +101,25 @@ define(['marionette', 'backbone', 'backgrid', 'views/table', 'views/filter', edit.create('NAME', 'text') if (app.prop == this.model.get('PROP')) { edit.create('GLOBAL', 'select', { data: { 1: 'Yes', 0: 'No' } }) + var self = this + this.ctypes = new PlateTypes() + this.ctypes.queryParams = { 'PROPOSALTYPE': 'mx', 'ty': 'plate' } + this.ctypes.fetch().done(function() { + edit.create('CONTAINERTYPEID', 'select', { data: self.ctypes.kv({ empty: true }) }) + }) + } else { + this.ui.containertype.hide() } this.groupview = new GroupView({ components: this.components, editable: app.prop == this.model.get('PROP') }) this.group.show(this.groupview) - this.filterview = new FilterView({ filters: this.positions, url: false, className: 'plate-12-wide' }) + this.filterview = new FilterView({ filters: this.positions, url: false, className: 'plate-12-wide', value: 1 }) this.listenTo(this.filterview, 'selected:change', this.setGroup, this) this.plate.show(this.filterview) + this.setGroup(1) }, - saveGroups: function(e) { e.preventDefault() console.log('save groups') diff --git a/client/src/js/templates/imaging/screencomps.html b/client/src/js/templates/imaging/screencomps.html index ea2b253c3..133285f03 100644 --- a/client/src/js/templates/imaging/screencomps.html +++ b/client/src/js/templates/imaging/screencomps.html @@ -15,6 +15,11 @@

Crystallisation Screen

<%-GLOBAL == 1 ? 'Yes' : 'No' %><%-GLOBAL == 1 ? ' (Proposal '+PROP+')' : '' %> +
  • + Container Type + <%-CONTAINERTYPEID%> +
  • +
  • Capacity <%-CAPACITY%> From 50359e202e240da8d8136b44eeac6ce1a2f5259f Mon Sep 17 00:00:00 2001 From: Mark W <24956497+ndg63276@users.noreply.github.com> Date: Wed, 27 Nov 2024 11:38:42 +0000 Subject: [PATCH 2/2] Update api/src/Page/Shipment.php Co-authored-by: Guilherme Francisco --- api/src/Page/Shipment.php | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/api/src/Page/Shipment.php b/api/src/Page/Shipment.php index 0bcd903a7..2ebaafff1 100644 --- a/api/src/Page/Shipment.php +++ b/api/src/Page/Shipment.php @@ -2508,10 +2508,8 @@ function _get_container_types() } else { $where .= 'ct.active = 1'; } - if ($this->has_arg('ty')) { - if ($this->arg('ty') == 'plate') { - $where .= " AND ct.wellperrow is not null"; - } + if ($this->has_arg('ty') && $this->arg('ty') == 'plate') { + $where .= " AND ct.wellperrow is not null"; } if ($this->has_arg('PROPOSALTYPE')) { $where .= ' AND ct.proposaltype = :1';