diff --git a/api/assets/emails/html/dewar-dispatch-lite.html b/api/assets/emails/html/dewar-dispatch-lite.html
index ad3b16b2b..becda15da 100644
--- a/api/assets/emails/html/dewar-dispatch-lite.html
+++ b/api/assets/emails/html/dewar-dispatch-lite.html
@@ -1,4 +1,4 @@
-
Goods Handling, please arrange dispatch of the following Dewar.
diff --git a/api/config_sample.php b/api/config_sample.php
index f75ece813..a178d48cd 100644
--- a/api/config_sample.php
+++ b/api/config_sample.php
@@ -155,6 +155,9 @@
# Server log location
$server_log = '/dls_sw/<%=BEAMLINENAME%>/logs/gda-server.log';
+ # Path to ccp4 location
+ $ccp4_location = '/dls_sw/apps/ccp4/latest/ccp4-9';
+
# Email addresses, comma separate for multiple recepients
# - Email templates in assets/emails in plain and html/ format
@@ -239,6 +242,8 @@
$facility_courier_countries = array('United Kingdom');
// List of non dom eu free countries
$facility_courier_countries_nde = array('France', 'Italy', 'Spain');
+ // Link to help with international shipments
+ $facility_courier_countries_link = '';
$package_description = 'Dry shipper containing frozen crystals';
$dewar_weight = 18;
diff --git a/api/index.php b/api/index.php
index 4f884d58d..ace25a44c 100644
--- a/api/index.php
+++ b/api/index.php
@@ -68,7 +68,7 @@ function setupApplication($mode): Slim
$app->get('/options', function () use ($app) {
global $motd, $authentication_type, $cas_url, $cas_sso, $sso_url, $package_description,
- $facility_courier_countries, $facility_courier_countries_nde,
+ $facility_courier_countries, $facility_courier_countries_nde, $facility_courier_countries_link,
$dhl_enable, $scale_grid, $scale_grid_end_date, $preset_proposal, $timezone,
$valid_components, $enabled_container_types, $ifsummary, $synchweb_version, $redirects,
$shipping_service_app_url, $use_shipping_service_redirect, $use_shipping_service_redirect_incoming_shipments;
@@ -83,6 +83,7 @@ function setupApplication($mode): Slim
'package_description' => $package_description,
'facility_courier_countries' => $facility_courier_countries,
'facility_courier_countries_nde' => $facility_courier_countries_nde,
+ 'facility_courier_countries_link' => $facility_courier_countries_link,
'dhl_enable' => $dhl_enable,
'scale_grid' => $scale_grid,
'scale_grid_end_date' => $scale_grid_end_date,
diff --git a/api/scripts/mtz2map.sh b/api/scripts/mtz2map.sh
index 04fb213c0..00542447d 100755
--- a/api/scripts/mtz2map.sh
+++ b/api/scripts/mtz2map.sh
@@ -2,19 +2,6 @@
cd /tmp
-# If you are running with the module system, load ccp4
-#. /etc/profile.d/modules.sh
-#module load ccp4
-
-# If not, define the environment variables required below
-#export CCP4_MASTER=/dls_sw/apps/ccp4/
-export CCP4_MASTER=/dls_sw/apps/ccp4/latest/ccp4-8.0
-export CINCL=$CCP4_MASTER/include
-export CLIBD=$CCP4_MASTER/lib/data
-
-export CCP4_SCR=/tmp
-export root=$CCP4_MASTER/bin
-
if [ -f $1 ]; then
mtz=$1
else
@@ -41,6 +28,14 @@ else
fi
fi
+#export CCP4_MASTER=/dls_sw/apps/ccp4/
+export CCP4_MASTER=$5
+export CINCL=$CCP4_MASTER/include
+export CLIBD=$CCP4_MASTER/lib/data
+
+export CCP4_SCR=/tmp
+export root=$CCP4_MASTER/bin
+
if [ $3 == 'dimple' ]; then
if $root/mtzinfo $mtz | grep -q PH2FOFCWT; then
diff --git a/api/src/Authentication/AuthenticationParent.php b/api/src/Authentication/AuthenticationParent.php
index 559051d10..c7262512e 100644
--- a/api/src/Authentication/AuthenticationParent.php
+++ b/api/src/Authentication/AuthenticationParent.php
@@ -16,4 +16,6 @@ public function check();
public function authorise();
public function authenticateByCode($code);
+
+ public function logout();
}
\ No newline at end of file
diff --git a/api/src/Authentication/Type/CAS.php b/api/src/Authentication/Type/CAS.php
index e7b24d2e7..0160dbe63 100644
--- a/api/src/Authentication/Type/CAS.php
+++ b/api/src/Authentication/Type/CAS.php
@@ -122,5 +122,10 @@ function validate($service, $ticket)
return rtrim($resp);
}
+
+ function logout()
+ {
+ return false;
+ }
}
diff --git a/api/src/Authentication/Type/Combined.php b/api/src/Authentication/Type/Combined.php
index 7a0fe7386..0a957a869 100644
--- a/api/src/Authentication/Type/Combined.php
+++ b/api/src/Authentication/Type/Combined.php
@@ -36,4 +36,9 @@ public function authorise() {
public function authenticateByCode($code){
return $this->OIDCAuth->authenticateByCode($code);
}
+
+ public function logout()
+ {
+ return $this->OIDCAuth->logout();
+ }
}
diff --git a/api/src/Authentication/Type/Dummy.php b/api/src/Authentication/Type/Dummy.php
index d5878e9bb..2d53c0520 100644
--- a/api/src/Authentication/Type/Dummy.php
+++ b/api/src/Authentication/Type/Dummy.php
@@ -26,4 +26,9 @@ function authenticate($login, $password)
{
return true;
}
+
+ function logout()
+ {
+ return false;
+ }
}
diff --git a/api/src/Authentication/Type/LDAP.php b/api/src/Authentication/Type/LDAP.php
index 669e92120..a727afc97 100644
--- a/api/src/Authentication/Type/LDAP.php
+++ b/api/src/Authentication/Type/LDAP.php
@@ -66,4 +66,9 @@ function authenticate($login, $password)
}
}
}
+
+ function logout()
+ {
+ return false;
+ }
}
diff --git a/api/src/Authentication/Type/OIDC.php b/api/src/Authentication/Type/OIDC.php
index c4ea2fcba..9b844a2a9 100644
--- a/api/src/Authentication/Type/OIDC.php
+++ b/api/src/Authentication/Type/OIDC.php
@@ -135,4 +135,9 @@ function authenticateByCode($code)
setcookie($cookie_key, $token, $cookieOpts);
return $this->getUser($token);
}
+
+ function logout()
+ {
+ return $this->getProviderConfig()->end_session_endpoint;
+ }
}
diff --git a/api/src/Authentication/Type/Simple.php b/api/src/Authentication/Type/Simple.php
index 6a355946c..c1e73de78 100644
--- a/api/src/Authentication/Type/Simple.php
+++ b/api/src/Authentication/Type/Simple.php
@@ -22,6 +22,11 @@ function check()
return false;
}
+ function logout()
+ {
+ return false;
+ }
+
function authenticate($login, $password)
{
$person = $this->db->pq("SELECT password FROM person WHERE login=:1", array($login));
diff --git a/api/src/Controllers/AuthenticationController.php b/api/src/Controllers/AuthenticationController.php
index 0d9aef954..0db43e3f3 100644
--- a/api/src/Controllers/AuthenticationController.php
+++ b/api/src/Controllers/AuthenticationController.php
@@ -116,7 +116,10 @@ private function checkAuthRequiredForSpecificSituations($parts): bool
($parts[0] == 'shipment' && $parts[1] == 'containers' && $parts[2] == 'notify' && in_array($_SERVER["REMOTE_ADDR"], $auto)) ||
# Allow barcode reader ips unauthorised access to add container history
- ($parts[0] == 'shipment' && $parts[1] == 'containers' && $parts[2] == 'history' && in_array($_SERVER["REMOTE_ADDR"], $bcr))
+ ($parts[0] == 'shipment' && $parts[1] == 'containers' && $parts[2] == 'history' && in_array($_SERVER["REMOTE_ADDR"], $bcr)) ||
+
+ # Allow shipping service to update dewar status
+ ($parts[0] == 'shipment' && $parts[1] == 'dewars' && $parts[2] == 'confirmdispatch')
)
{
$need_auth = false;
@@ -391,17 +394,24 @@ function authenticateByCode()
// Logout
function logout()
{
- global $cookie_key;
- if (isset($_COOKIE[$cookie_key])) {
- $cookieOpts = array (
- 'expires' => time() - 3600,
- 'path' => '/',
- 'secure' => true,
- 'httponly' => true,
- 'samesite' => 'Strict'
- );
-
- setcookie($cookie_key, null, $cookieOpts);
+ global $cookie_key, $cas_sso;
+ if($cas_sso) {
+ if (isset($_COOKIE[$cookie_key])) {
+ $cookieOpts = array (
+ 'expires' => time() - 3600,
+ 'path' => '/',
+ 'secure' => true,
+ 'httponly' => true,
+ 'samesite' => 'Strict'
+ );
+
+ setcookie($cookie_key, null, $cookieOpts);
+ }
+
+ header('Location: ' . $this->authenticateByType()->logout());
+ $this->returnResponse(302, array('status' => "Redirecting to SSO provider"));
+ } else {
+ $this->returnError(501, "SSO not configured");
}
}
diff --git a/api/src/Downstream/DownstreamProcessing.php b/api/src/Downstream/DownstreamProcessing.php
index 325c0a1c1..ca271d91b 100644
--- a/api/src/Downstream/DownstreamProcessing.php
+++ b/api/src/Downstream/DownstreamProcessing.php
@@ -217,15 +217,14 @@ function _lookup_autoproc($aid, $scalingid = null) {
* @param string $pdb The input pdb file to generate the map around
*/
function convert_mtz($mtz, $aid, $program, $pdb, $map = 0) {
+ global $ccp4_location;
exec(
'/bin/bash ./scripts/mtz2map.sh ' .
- $mtz .
- ' ' .
- $aid .
- ' ' .
- $program .
- ' ' .
- $pdb,
+ $mtz . ' ' .
+ $aid . ' ' .
+ $program . ' ' .
+ $pdb . ' ' .
+ $ccp4_location,
$output,
$res
);
diff --git a/api/src/Downstream/Type/Shelxt.php b/api/src/Downstream/Type/Shelxt.php
new file mode 100644
index 000000000..c9422e0a5
--- /dev/null
+++ b/api/src/Downstream/Type/Shelxt.php
@@ -0,0 +1,91 @@
+autoprocprogramid);
+ $filepath = $this->db->pq(
+ "SELECT app.filePath from autoprocprogramattachment app where autoprocprogramid = :1 and filename = 'shelxt_results.json' ",
+ $appid
+ );
+ return $filepath;
+ }
+
+ function _get_shelxt_results_png() {
+ $appid = array($this->autoprocprogramid);
+ $filepath = $this->db->pq(
+ "SELECT app.filepath, app.filename from autoprocprogramattachment app where autoprocprogramid = :1 and filename like '%.png%' ",
+ $appid
+ );
+ return $filepath;
+ }
+
+ function _get_pdb() {
+ $appid = array($this->autoprocprogramid);
+ $filepath = $this->db->pq(
+ "SELECT app.filepath, app.filename from autoprocprogramattachment app where autoprocprogramid = :1 and filename like '%.pdb%' ",
+ $appid
+ );
+ if (sizeof($filepath)) {
+ return $filepath[0]["FILEPATH"] . "/" . $filepath[0]["FILENAME"];
+ } else {
+ return;
+ }
+ }
+
+ function results() {
+ $json_filepath = $this->_get_shelxt_results_json();
+ if (sizeof($json_filepath)) {
+ $json_path = $json_filepath[0]["FILEPATH"] . "/shelxt_results.json" ;
+ $json_data = file_get_contents($json_path);
+ } else {
+ $json_data = "[]";
+ }
+ $dat = array();
+ $dat['BLOBS'] = 1;
+ $dat['SOLUTIONS'] = json_decode($json_data);
+
+ // scaling_id should always be present, but just in case...
+ if (array_key_exists('scaling_id', $this->process['PARAMETERS'])) {
+ $integrator = $this->_lookup_autoproc(
+ null,
+ $this->process['PARAMETERS']['scaling_id']
+ );
+ if ($integrator) {
+ $dat['PARENTAUTOPROCPROGRAM'] = $integrator['PROCESSINGPROGRAMS'];
+ $dat['PARENTAUTOPROCPROGRAMID'] = $integrator['AUTOPROCPROGRAMID'];
+ }
+ }
+ $results = new DownstreamResult($this);
+ $results->data = $dat;
+
+ return $results;
+ }
+
+ function images($n = 0) {
+ $png = $this->_get_shelxt_results_png();
+ if (sizeof($png)) {
+ return $png[0]["FILEPATH"] . "/" . $png[0]["FILENAME"];
+ } else {
+ return;
+ }
+
+ }
+
+ function mapmodel($n = 0, $map = false) {
+ $pdb = $this->_get_pdb();
+ if (!$pdb) {
+ return;
+ } else {
+ return $pdb;
+ }
+ }
+}
diff --git a/api/src/Page/Sample.php b/api/src/Page/Sample.php
index 145a88838..eb8850184 100644
--- a/api/src/Page/Sample.php
+++ b/api/src/Page/Sample.php
@@ -631,13 +631,15 @@ function _sub_samples()
$where = '';
$first_inner_select_where = '';
$second_inner_select_where = '';
+ $third_inner_select_where = '';
$args = array($this->proposalid);
if ($this->has_arg('sid')) {
$where .= ' AND s.blsampleid=:' . (sizeof($args) + 1);
$first_inner_select_where .= ' AND s.blsampleid=:' . (sizeof($args) + 2);
$second_inner_select_where .= ' AND s.blsampleid=:' . (sizeof($args) + 3);
- array_push($args, $this->arg('sid'), $this->arg('sid'), $this->arg('sid'));
+ $third_inner_select_where .= ' AND s.blsampleid=:' . (sizeof($args) + 4);
+ array_push($args, $this->arg('sid'), $this->arg('sid'), $this->arg('sid'), $this->arg('sid'));
}
if ($this->has_arg('cid')) {
@@ -648,7 +650,7 @@ function _sub_samples()
}
$this->db->wait_rep_sync(true);
- $ss_query_string = $this->get_sub_samples_query($where, $first_inner_select_where, $second_inner_select_where);
+ $ss_query_string = $this->get_sub_samples_query($where, $first_inner_select_where, $second_inner_select_where, $third_inner_select_where);
$subs = $this->db->pq($ss_query_string, $args);
$this->db->wait_rep_sync(false);
@@ -683,7 +685,7 @@ function _get_sub_sample()
}
}
- private function get_sub_samples_query($where, $first_inner_select_where = '', $second_inner_select_where = '')
+ private function get_sub_samples_query($where, $first_inner_select_where = '', $second_inner_select_where = '', $third_inner_select_where = '')
{
$group_by = "";
$order_by = "";
@@ -707,7 +709,7 @@ private function get_sub_samples_query($where, $first_inner_select_where = '', $
$from_query = "FROM (
SELECT ss.blsubsampleid
FROM (
- SELECT s.blsampleid, max(si.blsampleimageid) AS blsampleimageid
+ SELECT s.blsampleid, max(si.blsampleimageid) AS blsampleimageid
FROM blsample s
INNER JOIN blsampleimage si ON si.blsampleid = s.blsampleid
WHERE 1=1 $first_inner_select_where
@@ -715,14 +717,26 @@ private function get_sub_samples_query($where, $first_inner_select_where = '', $
) qq
JOIN blsubsample ss ON ss.blsampleimageid = qq.blsampleimageid
WHERE ss.source = 'auto'
-
+
UNION ALL
SELECT ss.blsubsampleid
FROM blsubsample ss
LEFT JOIN blsample s on ss.blsampleid = s.blsampleid
- WHERE ss.source = 'manual' $second_inner_select_where
- ) q JOIN blsubsample ss ON ss.blsubsampleid = q.blsubsampleid";
+ WHERE ss.source = 'manual' $second_inner_select_where";
+
+ // show auto generated subsamples with data collections
+ if ($third_inner_select_where != '') {
+ $from_query .= "
+ UNION ALL
+ SELECT ss.blsubsampleid
+ FROM blsubsample ss
+ LEFT JOIN blsample s on ss.blsampleid = s.blsampleid
+ INNER JOIN datacollection dc ON ss.blsubsampleid = dc.blsubsampleid
+ WHERE ss.source = 'auto' $third_inner_select_where";
+ }
+
+ $from_query .= ") q JOIN blsubsample ss ON ss.blsubsampleid = q.blsubsampleid";
$group_by = "GROUP BY pr.acronym,
s.name,
diff --git a/api/src/Page/Shipment.php b/api/src/Page/Shipment.php
index 4e8ee5d25..6b3f16f4a 100644
--- a/api/src/Page/Shipment.php
+++ b/api/src/Page/Shipment.php
@@ -143,6 +143,9 @@ class Shipment extends Page
'CLOSETIME' => '\d\d:\d\d',
'PRODUCTCODE' => '\w',
'BEAMLINENAME' => '[\w\-]+',
+ 'TOKEN' => '\w+',
+ 'tracking_number' => '\w+',
+ 'AWBURL' => '[\w\:\/\.\-]+',
'manifest' => '\d',
'currentuser' => '\d',
@@ -196,6 +199,7 @@ class Shipment extends Page
array('/dewars/transfer', 'post', '_transfer_dewar'),
array('/dewars/dispatch', 'post', '_dispatch_dewar'),
+ array('/dewars/confirmdispatch/did/:did/token/:TOKEN', 'post', '_dispatch_dewar_confirmation'),
array('/dewars/tracking(/:DEWARID)', 'get', '_get_dewar_tracking'),
@@ -986,7 +990,8 @@ function _create_dewars_shipment_request(
array $dewars,
string $proposal,
int $external_id,
- int $shipping_id
+ int $shipping_id,
+ string $callback_url=""
): int {
$packages = [];
@@ -1035,6 +1040,9 @@ function _create_dewars_shipment_request(
"origin_url" => "{$protocol}://{$_SERVER['SERVER_NAME']}{$server_port}/shipments/sid/{$shipping_id}",
"packages" => $packages
);
+ if ($callback_url) {
+ $shipment_request_info["dispatch_callback_url"] = "{$protocol}://{$_SERVER['SERVER_NAME']}{$server_port}{$callback_url}";
+ }
$response = $this->shipping_service->create_shipment_request($shipment_request_info);
$external_shipping_id = $response['shipmentRequestId'];
return $external_shipping_id;
@@ -1050,7 +1058,14 @@ function _dispatch_dewar_shipment_request($dewar)
$proposal = $dewar['PROPOSAL'];
$external_id = (int) $dewar['DEWARID'];
$shipping_id = (int) $dewar['SHIPPINGID'];
- $external_shipping_id = $this->_create_dewars_shipment_request($dewars, $proposal, $external_id, $shipping_id);
+ $token = md5(uniqid());
+ $this->db->pq(
+ "UPDATE dewar SET extra = JSON_SET(IFNULL(extra, '{}'), '$.token', :1 ) WHERE dewarid=:2",
+ array($token, $external_id)
+ );
+
+ $callback_url = "/api/shipment/dewars/confirmdispatch/did/{$external_id}/token/{$token}";
+ $external_shipping_id = $this->_create_dewars_shipment_request($dewars, $proposal, $external_id, $shipping_id, $callback_url);
$this->db->pq(
"UPDATE dewar SET externalShippingIdFromSynchrotron=:1 WHERE dewarid=:2",
@@ -1200,14 +1215,6 @@ function _dispatch_dewar()
$dispatch_from_location = 'eBIC';
}
- // Update dewar transport history with provided location.
- $this->db->pq(
- "INSERT INTO dewartransporthistory (dewartransporthistoryid,dewarid,dewarstatus,storagelocation,arrivaldate)
- VALUES (s_dewartransporthistory.nextval,:1,'dispatch-requested',:2,CURRENT_TIMESTAMP)
- RETURNING dewartransporthistoryid INTO :id",
- array($dew['DEWARID'], $dewar_location)
- );
-
$terms = $this->db->pq(
"SELECT cta.couriertermsacceptedid FROM couriertermsaccepted cta WHERE cta.shippingid=:1",
array($dew['SHIPPINGID'])
@@ -1255,10 +1262,133 @@ function _dispatch_dewar()
&& $terms_accepted
&& Utils::getValueOrDefault($use_shipping_service_redirect)
);
- $subject_pickup_date = $use_dispatch_lite_template ? '' : ' - Pickup Date: ' . $this->args['DELIVERYAGENT_SHIPPINGDATE'];
- $subject_line = '*** Dispatch requested for Dewar ' . $dew['BARCODE'] . ' from ' . $dispatch_from_location . $subject_pickup_date . ' ***';
- $email_template = $use_dispatch_lite_template ? 'dewar-dispatch-lite' : 'dewar-dispatch';
+
+ if ($use_dispatch_lite_template) {
+ $this->_output(1);
+ } else {
+ $subject_pickup_date = $use_dispatch_lite_template ? '' : ' - Pickup Date: ' . $this->args['DELIVERYAGENT_SHIPPINGDATE'];
+ $subject_line = '*** Dispatch requested for Dewar ' . $dew['BARCODE'] . ' from ' . $dispatch_from_location . $subject_pickup_date . ' ***';
+ $email_template = $use_dispatch_lite_template ? 'dewar-dispatch-lite' : 'dewar-dispatch';
+ $email = new Email($email_template, $subject_line);
+
+ // If a local contact is given, try to find their email address
+ // First try LDAP, if unsuccessful look at the ISPyB person record for a matching staff user
+ $local_contact = $this->has_arg('LOCALCONTACT') ? $this->args['LOCALCONTACT'] : '';
+ if ($local_contact) {
+ $this->args['LCEMAIL'] = $this->_get_email_fn($local_contact);
+ if (!$this->args['LCEMAIL']) {
+ $this->args['LCEMAIL'] = $this->_get_ispyb_email_fn($local_contact);
+ }
+ }
+
+ if (!array_key_exists('FACILITYCODE', $data))
+ $data['FACILITYCODE'] = '';
+ if (!array_key_exists('AWBNUMBER', $data))
+ $data['AWBNUMBER'] = '';
+ if (!array_key_exists('DELIVERYAGENT_AGENTNAME', $data))
+ $data['DELIVERYAGENT_AGENTNAME'] = '';
+ if (!array_key_exists('DELIVERYAGENT_AGENTCODE', $data))
+ $data['DELIVERYAGENT_AGENTCODE'] = '';
+ if (!array_key_exists('LOCATION', $data))
+ $data['LOCATION'] = $dewar_location;
+ if (!array_key_exists('LOCALCONTACT', $data))
+ $data['LOCALCONTACT'] = $local_contact;
+ if (!array_key_exists('LCEMAIL', $data))
+ $data['LCEMAIL'] = '';
+ $data['BARCODE'] = $dew['BARCODE'];
+ $email->data = $data;
+
+ if (
+ $country != $facility_country &&
+ array_key_exists('DELIVERYAGENT_AGENTNAME', $data) &&
+ $data['DELIVERYAGENT_AGENTNAME'] === 'DHL' &&
+ array_key_exists('PROPOSALCODE', $dew) &&
+ in_array($dew['PROPOSALCODE'], array('bi','cm','mx')) &&
+ !is_null($dispatch_email_intl)
+ ) {
+ $recpts = $dispatch_email_intl;
+ } else {
+ $recpts = $dispatch_email;
+ }
+
+ $recpts .= ', ' . $this->arg('EMAILADDRESS');
+ $local_contact_email = $this->has_arg('LCEMAIL') ? $this->args['LCEMAIL'] : '';
+ if ($local_contact_email) $recpts .= ', ' . $local_contact_email;
+
+ $email->send($recpts);
+
+ // Update the dewar status and storage location
+ $this->db->pq(
+ "UPDATE dewar
+ set dewarstatus='dispatch-requested', storagelocation=lower(:2)
+ WHERE dewarid=:1",
+ array($dew['DEWARID'], $dewar_location)
+ );
+
+ $this->db->pq("UPDATE shipping set shippingstatus='dispatch-requested' WHERE shippingid=:1", array($dew['SHIPPINGID']));
+
+ // Update dewar transport history with provided location.
+ $this->db->pq(
+ "INSERT INTO dewartransporthistory (dewartransporthistoryid,dewarid,dewarstatus,storagelocation,arrivaldate)
+ VALUES (s_dewartransporthistory.nextval,:1,'dispatch-requested',:2,CURRENT_TIMESTAMP)
+ RETURNING dewartransporthistoryid INTO :id",
+ array($dew['DEWARID'], $dewar_location)
+ );
+
+ $this->_output(1);
+ }
+ }
+
+
+ function _dispatch_dewar_confirmation()
+ {
+ global $dispatch_email;
+ global $shipping_service_app_url;
+
+ if (!$this->has_arg('did'))
+ $this->_error('No dewar specified');
+
+ # Check token against dewar given
+ $dew = $this->db->pq(
+ "SELECT d.dewarid, d.barcode, d.storagelocation, d.dewarstatus, d.externalShippingIdFromSynchrotron, d.facilitycode, d.trackingNumberFromSynchrotron,
+ s.shippingid,
+ CONCAT(p.proposalcode, p.proposalnumber) as proposal,
+ json_unquote(json_extract(d.extra, '$.token')) as token,
+ pe2.emailaddress
+ FROM dewar d
+ INNER JOIN shipping s ON s.shippingid = d.shippingid
+ INNER JOIN proposal p ON p.proposalid = s.proposalid
+ LEFT OUTER JOIN labcontact c2 ON s.returnlabcontactid = c2.labcontactid
+ LEFT OUTER JOIN person pe2 ON pe2.personid = c2.personid
+ WHERE d.dewarid=:1",
+ array($this->arg('did'))
+ );
+ $dew = $dew[0];
+
+ if (!$this->has_arg('TOKEN') || $this->arg('TOKEN') !== $dew['TOKEN']) {
+ $this->_error('Incorrect token');
+ }
+
+ # Prepare e-mail to stores
+ $data = $this->args;
+ if (!array_key_exists('prop', $data))
+ $data['prop'] = $dew['PROPOSAL'];
+ if (!array_key_exists('FACILITYCODE', $data))
+ $data['FACILITYCODE'] = $dew['FACILITYCODE'];
+ if (!array_key_exists('BARCODE', $data))
+ $data['BARCODE'] = $dew['BARCODE'];
+ if (!array_key_exists('AWBURL', $data))
+ $data['AWBURL'] = "{$shipping_service_app_url}/shipment-requests/{$dew['EXTERNALSHIPPINGIDFROMSYNCHROTRON']}/outgoing";
+ if (!array_key_exists('LOCATION', $data))
+ $data['LOCATION'] = $dew['STORAGELOCATION'];
+ if (!array_key_exists('EMAILADDRESS', $data))
+ $data['EMAILADDRESS'] = $dew['EMAILADDRESS'];;
+ if (!array_key_exists('tracking_number', $data))
+ $data['tracking_number'] = $dew['TRACKINGNUMBERFROMSYNCHROTRON'];
+ $subject_line = '*** Dispatch requested for Dewar ' . $dew['BARCODE'] . ' from ' . $data['LOCATION'] . ' ***';
+ $email_template = 'dewar-dispatch-lite';
$email = new Email($email_template, $subject_line);
+ $email->data = $data;
// If a local contact is given, try to find their email address
// First try LDAP, if unsuccessful look at the ISPyB person record for a matching staff user
@@ -1270,37 +1400,8 @@ function _dispatch_dewar()
}
}
- if (!array_key_exists('FACILITYCODE', $data))
- $data['FACILITYCODE'] = '';
- if (!array_key_exists('AWBNUMBER', $data))
- $data['AWBNUMBER'] = '';
- if (!array_key_exists('DELIVERYAGENT_AGENTNAME', $data))
- $data['DELIVERYAGENT_AGENTNAME'] = '';
- if (!array_key_exists('DELIVERYAGENT_AGENTCODE', $data))
- $data['DELIVERYAGENT_AGENTCODE'] = '';
- if (!array_key_exists('LOCATION', $data))
- $data['LOCATION'] = $dewar_location;
- if (!array_key_exists('LOCALCONTACT', $data))
- $data['LOCALCONTACT'] = $local_contact;
- if (!array_key_exists('LCEMAIL', $data))
- $data['LCEMAIL'] = '';
- $data['BARCODE'] = $dew['BARCODE'];
- $email->data = $data;
-
- if (
- $country != $facility_country &&
- array_key_exists('DELIVERYAGENT_AGENTNAME', $data) &&
- $data['DELIVERYAGENT_AGENTNAME'] === 'DHL' &&
- array_key_exists('PROPOSALCODE', $dew) &&
- in_array($dew['PROPOSALCODE'], array('bi','cm','mx')) &&
- !is_null($dispatch_email_intl)
- ) {
- $recpts = $dispatch_email_intl;
- } else {
- $recpts = $dispatch_email;
- }
-
- $recpts .= ', ' . $this->arg('EMAILADDRESS');
+ $recpts = $dispatch_email;
+ if ($data['EMAILADDRESS']) $recpts .= ', ' . $data['EMAILADDRESS'];
$local_contact_email = $this->has_arg('LCEMAIL') ? $this->args['LCEMAIL'] : '';
if ($local_contact_email) $recpts .= ', ' . $local_contact_email;
@@ -1309,9 +1410,19 @@ function _dispatch_dewar()
// Also update the dewar status and storage location to keep it in sync with history...
$this->db->pq(
"UPDATE dewar
- set dewarstatus='dispatch-requested', storagelocation=lower(:2)
+ set dewarstatus='dispatch-requested', storagelocation=lower(:2), trackingnumberfromsynchrotron=:3
WHERE dewarid=:1",
- array($dew['DEWARID'], $dewar_location)
+ array($dew['DEWARID'], $data['LOCATION'], $data['tracking_number'])
+ );
+
+ $this->db->pq("UPDATE shipping set shippingstatus='dispatch-requested' WHERE shippingid=:1", array($dew['SHIPPINGID']));
+
+ // Update dewar transport history with provided location.
+ $this->db->pq(
+ "INSERT INTO dewartransporthistory (dewartransporthistoryid,dewarid,dewarstatus,storagelocation,arrivaldate)
+ VALUES (s_dewartransporthistory.nextval,:1,'dispatch-requested',:2,CURRENT_TIMESTAMP)
+ RETURNING dewartransporthistoryid INTO :id",
+ array($dew['DEWARID'], $data['LOCATION'])
);
$this->_output(1);
diff --git a/client/src/js/app/components/header.vue b/client/src/js/app/components/header.vue
index c9d91de97..ac2758223 100644
--- a/client/src/js/app/components/header.vue
+++ b/client/src/js/app/components/header.vue
@@ -116,7 +116,7 @@ export default {
this.$store.dispatch('auth/logout')
.then(() => {
if (this.sso) {
- this.$router.push('/logout');
+ window.location.assign(`${this.$store.getters.apiUrl}/authenticate/logout`);
} else {
this.$router.push('/');
}
diff --git a/client/src/js/app/router/router.js b/client/src/js/app/router/router.js
index b47f041cf..33ef36c22 100644
--- a/client/src/js/app/router/router.js
+++ b/client/src/js/app/router/router.js
@@ -15,7 +15,6 @@ import MarionetteApplication from 'app/marionette-application.js'
import Home from 'app/views/home.vue'
import Login from 'app/views/login.vue'
-import Logout from 'app/views/logout.vue'
import NotFound from 'app/views/notfound.vue'
import NotAuthorised from 'app/views/notauthorised.vue'
@@ -62,11 +61,6 @@ let routes = [
props: true, // this will mean redirect query also passed to login as prop
component: Login,
},
- {
- path: '/logout',
- name: 'logout',
- component: Logout,
- },
{
path: '/notfound',
alias: '/404',
@@ -127,7 +121,6 @@ router.beforeEach((to, from, next) => {
if (to.path === '/notfound') { next(); return }
if (to.path === '/') { next(); return }
if (to.path === '/login') { next(); return }
- if (to.path === '/logout') { next(); return }
// Make sure the store is initialised before proceeding further
const init = store.dispatch('initialise')
diff --git a/client/src/js/app/store/modules/store.auth.js b/client/src/js/app/store/modules/store.auth.js
index aa125f8af..8c141106a 100644
--- a/client/src/js/app/store/modules/store.auth.js
+++ b/client/src/js/app/store/modules/store.auth.js
@@ -133,27 +133,13 @@ const auth = {
})
},
- logout({commit, rootState}){
- return new Promise((resolve, reject) => {
- // If sso need to call the logout URL
- Backbone.ajax({
- url: rootState.apiUrl+'/authenticate/logout',
- type: 'GET',
- success: function() {
- console.log("Logout successful")
- commit('logout')
- commit('proposal/setProposal', null, {root: true})
- commit('user/updateUser', {}, {root: true})
- resolve()
- },
- error: function() {
- // Even if an error we can set our local properties to logged out
- console.log("Error returned from logout URL")
- commit('logout')
- commit('proposal/setProposal', null, {root: true})
- commit('user/updateUser', {}, {root: true})
- reject()
- }})
+ logout({commit}){
+ return new Promise((resolve) => {
+ console.log("Logout successful")
+ commit('logout')
+ commit('proposal/setProposal', null, {root: true})
+ commit('user/updateUser', {}, {root: true})
+ resolve()
})
},
},
diff --git a/client/src/js/app/views/login.vue b/client/src/js/app/views/login.vue
index 58f4bf8d5..a30993499 100644
--- a/client/src/js/app/views/login.vue
+++ b/client/src/js/app/views/login.vue
@@ -127,7 +127,7 @@ export default {
return this.$store.getters.apiUrl;
},
logoutUrl: function () {
- return `https://${this.$store.getters.sso_url}/logout`;
+ return `${this.$store.getters.apiUrl}/authenticate/logout`;
},
},
diff --git a/client/src/js/app/views/logout.vue b/client/src/js/app/views/logout.vue
deleted file mode 100644
index f648bb4c6..000000000
--- a/client/src/js/app/views/logout.vue
+++ /dev/null
@@ -1,28 +0,0 @@
-
-
-
Logout
-
- Successfully logged out. You might not be logged out of your SSO provider yet.
- Log out of it too?
-
-
Go to home
-
-
-
-
diff --git a/client/src/js/modules/dc/views/downstream.js b/client/src/js/modules/dc/views/downstream.js
index 5d0faf538..eb8d8e858 100644
--- a/client/src/js/modules/dc/views/downstream.js
+++ b/client/src/js/modules/dc/views/downstream.js
@@ -7,11 +7,12 @@ define(['backbone', 'marionette',
'modules/dc/views/dimple',
'modules/dc/views/mrbump',
'modules/dc/views/bigep',
+ 'modules/dc/views/shelxt',
'templates/dc/downstreamerror.html'
], function(Backbone, Marionette, TabView, DownStreams, DownstreamWrapper,
TableView,
- FastEP, DIMPLE, MrBUMP, BigEP, downstreamerror) {
+ FastEP, DIMPLE, MrBUMP, BigEP, Shelxt, downstreamerror) {
var DownstreamsCollection = Backbone.Collection.extend()
@@ -61,6 +62,7 @@ define(['backbone', 'marionette',
'Autobuild': BigEP,
'Crank2': BigEP,
'AutoSHARP': BigEP,
+ 'Shelxt': Shelxt,
}
if (model.get('PROCESS').PROCESSINGSTATUS != 1) {
diff --git a/client/src/js/modules/dc/views/mapmodelview.js b/client/src/js/modules/dc/views/mapmodelview.js
index 949ff0052..595135562 100644
--- a/client/src/js/modules/dc/views/mapmodelview.js
+++ b/client/src/js/modules/dc/views/mapmodelview.js
@@ -33,7 +33,9 @@ define(['marionette',
loadMaps: function() {
this.mapsToLoad = this.downstream.get('FEATURES').MAPMODEL[1];
this.mapsLoaded = 0
- this.doLoadMaps(1, this.onMapsLoaded.bind(this))
+ if (this.mapsToLoad > 0) {
+ this.doLoadMaps(1, this.onMapsLoaded.bind(this))
+ }
},
@@ -167,4 +169,4 @@ define(['marionette',
-})
\ No newline at end of file
+})
diff --git a/client/src/js/modules/dc/views/shelxt.js b/client/src/js/modules/dc/views/shelxt.js
new file mode 100644
index 000000000..0689acdb8
--- /dev/null
+++ b/client/src/js/modules/dc/views/shelxt.js
@@ -0,0 +1,44 @@
+define([
+ 'marionette', 'templates/dc/dc_shelxt.html', 'utils', 'utils/xhrimage', 'jquery.mp'
+], function(Marionette, template, utils, XHRImage) {
+
+ return Marionette.ItemView.extend({
+ template: template,
+ className: 'clearfix',
+
+ ui: {
+ solutions: '.solutions',
+ blob: '.blobs img',
+ blobs: '.blobs',
+ },
+
+ showBlob: function() {
+ this.ui.blob.attr('src', this.blob.src).show()
+ this.ui.blobs.addClass('loaded').removeClass('pending')
+ },
+
+ onDomRefresh: function() {
+ this.ui.blobs.magnificPopup({
+ delegate: 'a', type: 'image',
+ gallery: {
+ enabled: true,
+ navigateByImgClick: true,
+ }
+ })
+
+ this.ui.blob.hide()
+ if (this.model.get('BLOBS') > 0) {
+ this.blob = new XHRImage()
+ this.blob.onload = this.showBlob.bind(this)
+ this.ui.blobs.addClass('pending')
+ this.blob.load(app.apiurl+'/processing/downstream/images/'+this.model.get('AID'))
+ }
+
+ if (!app.mobile()) {
+ this.ui.solutions.width(0.47*(this.options.holderWidth-14))
+ }
+ },
+
+ })
+
+})
diff --git a/client/src/js/modules/shipment/models/dispatch.js b/client/src/js/modules/shipment/models/dispatch.js
index 779948e33..195045bf3 100644
--- a/client/src/js/modules/shipment/models/dispatch.js
+++ b/client/src/js/modules/shipment/models/dispatch.js
@@ -37,7 +37,7 @@ define(['backbone'], function(Backbone) {
},
EMAILADDRESS: {
- required: true,
+ required: function () {return this.dispatchDetailsRequired},
pattern: 'email',
},
diff --git a/client/src/js/modules/shipment/views/shipment.js b/client/src/js/modules/shipment/views/shipment.js
index 7601d7d0e..6932f8645 100644
--- a/client/src/js/modules/shipment/views/shipment.js
+++ b/client/src/js/modules/shipment/views/shipment.js
@@ -43,6 +43,9 @@ define(['marionette',
APIURL: app.apiurl,
PROP: app.prop,
DHL_ENABLE: app.options.get('dhl_enable'),
+ FACILITY_COURIER_COUNTRIES: app.options.get('facility_courier_countries'),
+ FACILITY_COURIER_COUNTRIES_NDE: app.options.get('facility_courier_countries_nde'),
+ FACILITY_COURIER_COUNTRIES_LINK: app.options.get('facility_courier_countries_link'),
}
},
diff --git a/client/src/js/modules/shipment/views/shipmentadd.js b/client/src/js/modules/shipment/views/shipmentadd.js
index 45d35957c..a5fea270b 100644
--- a/client/src/js/modules/shipment/views/shipmentadd.js
+++ b/client/src/js/modules/shipment/views/shipmentadd.js
@@ -48,6 +48,13 @@ define(['marionette', 'views/form',
return FormView.extend({
template: template,
+ templateHelpers: function() {
+ return {
+ DHL_ENABLE: app.options.get('dhl_enable'),
+ FACILITY_COURIER_COUNTRIES_LINK: app.options.get('facility_courier_countries_link'),
+ }
+ },
+
events: {
'change input[name=DEWARS]': 'updateFCodes',
'change @ui.lcret': 'getlcdetails',
diff --git a/client/src/js/modules/types/sm/dc/views/apstatusitem.js b/client/src/js/modules/types/sm/dc/views/apstatusitem.js
index 9a70f5650..b87f2ebdf 100644
--- a/client/src/js/modules/types/sm/dc/views/apstatusitem.js
+++ b/client/src/js/modules/types/sm/dc/views/apstatusitem.js
@@ -9,14 +9,25 @@ define(['modules/dc/views/apstatusitem'], function(APStatusItem) {
' ',
' ']
- _.each(['autoproc','downstream'], function(ty, id) {
- this.ui.holder.eq(id).empty()
- _.each(res[ty], function(ap, n) {
- if(ap != 0)
- this.ui.holder.eq(id).append(n+' '+val[ap]+' ')
- }, this)
+ _.each({ap: 'autoproc',dp: 'downstream'}, function(ty, id) {
+ this.ui[id].empty()
+ var allResults = []
+ if (res[ty]) {
+ _.each(res[ty], function(ap, n) {
+ var ress = {}
+ _.each(ap, function(a) {
+ if (!(a in ress)) ress[a] = 0
+ ress[a]++
+ })
+ allResults.push(n+': '+_.map(ress, function(c, st) { return c > 1 ? ''+c+'x '+val[st] : val[st]}).join(' '))
+ }, this)
+
+ this.ui[id].append(allResults.join('| '))
+ } else {
+ this.ui[id].append('No processing results')
+ }
}, this)
},
})
-})
\ No newline at end of file
+})
diff --git a/client/src/js/templates/dc/dc_shelxt.html b/client/src/js/templates/dc/dc_shelxt.html
new file mode 100644
index 000000000..a94d5a516
--- /dev/null
+++ b/client/src/js/templates/dc/dc_shelxt.html
@@ -0,0 +1,32 @@
+
+
+
+
+ <% if (SOLUTIONS.length) { %>
+ <% _.each(SOLUTIONS, function(r, i) { %>
+
+ <% _.each(r, function(j) { %>
+ <%-j%>
+ <% }) %>
+
+ <% }) %>
+ <% } else { %>
+
+ Solutions
+
+
+ No Solutions Found
+
+ <% } %>
+
+
+
diff --git a/client/src/js/templates/shipment/dispatch.html b/client/src/js/templates/shipment/dispatch.html
index 74ed6e56f..7bda18046 100644
--- a/client/src/js/templates/shipment/dispatch.html
+++ b/client/src/js/templates/shipment/dispatch.html
@@ -24,11 +24,6 @@ Request Dewar Dispatch
<% } %>
-
- Email AddressThe contact email for the Dewar return
-
-
-
Laboratory Country
The contact's laboratory country
@@ -130,6 +125,11 @@ Request Dewar Dispatch
+
+ Email AddressThe contact email for the Dewar return
+
+
+
Phone Number
diff --git a/client/src/js/templates/shipment/shipment.html b/client/src/js/templates/shipment/shipment.html
index 6ee05bffb..a58058375 100644
--- a/client/src/js/templates/shipment/shipment.html
+++ b/client/src/js/templates/shipment/shipment.html
@@ -6,8 +6,10 @@ Shipment: <%-SHIPPI
<% if (DHL_ENABLE) { %>
<% if (DELIVERYAGENT_HAS_LABEL == '1') { %>
You can print your Air Waybill by clicking "Print Air Waybill" below
- <% } else if (COUNTRY && COUNTRY !="United Kingdom" ) { %>
- International shipping is currently disabled from this application. Please see here
+ <% } else if (COUNTRY && FACILITY_COURIER_COUNTRIES_NDE.includes(COUNTRY) ) { %>
+ International shipping is not available through this application. If you're arranging your own shipping (e.g. industrial users), enter your tracking numbers below after booking and include printed return labels in the dewar case. European academic users, please see here .
+ <% } else if (COUNTRY && !FACILITY_COURIER_COUNTRIES.includes(COUNTRY) ) { %>
+ International shipping is not available through this application. If you're arranging your own shipping, enter your tracking numbers below after booking and include printed return labels in the dewar case.
<% } else { %>
You can now book your shipment with DHL using "Create Air Waybill" below
<% } %>
diff --git a/client/src/js/templates/shipment/shipmentadd.html b/client/src/js/templates/shipment/shipmentadd.html
index 0860a72c9..3866fe012 100644
--- a/client/src/js/templates/shipment/shipmentadd.html
+++ b/client/src/js/templates/shipment/shipmentadd.html
@@ -2,7 +2,9 @@
Add New Shipment
-Please note that international shipping is currently disabled from this application. Please see the link here
+<% if (FACILITY_COURIER_COUNTRIES_LINK) { %>
+ Please note that international shipping is currently disabled from this application. Please see the link here .
+<% } %>