Skip to content

Commit

Permalink
LIMS-116: Summary page revamp (#606)
Browse files Browse the repository at this point in the history
* updating .gitignore

* adding frontend files and building backend

* adding front end files and router files

* create sidebar, filter options added, routes added

* add routing to page,search bar and column selector

* adding pagination continutation

* adding csv, all columns, rest of filters

* added descending and ascending

* sidebar dropdown&changed data structure&hide row

* cleaning up fixing jump bug

* refactored backend mapped data

* added expanding row

* refactored favourites

* refactored orderby filter

* cleaned up code, added comments

* added all params to watcher

* added summary db connection

* add routes to summary

* add backend changes summarypage

* changes to expandable sidebar, cleaning up fronte

* clean up, add functions to get data

* front end changes, group concat backend

* remove summarypage code

* fix pagination, timeout

* delete old summary file

* changed pagination in summary.php

* changed backend to not include tot

* fix refined cell c column

* added ifsets to avoid undefined offset error

* delete offset for output

* change order of operands

* change filters, fix operands

* fix csv button

* changed prop to propid

* format beamlinename

* change al,be,gamma

* add selected columns summary

* additional changes for selected columns

* add multiple selections change expandable sidebar

* redo  routing, keep alive summary

* fixes, change routing, results display, orderby

* fixes to selected columns

* format page to allow for customisation

* area for potential formatting and fix to querypara

* changes to regex, combobox multiple,  and fomat

* column select fix, resize pill fix, format inputs

* Update api/src/Database/DatabaseConnectionFactory.php

Co-authored-by: Guilherme Francisco <[email protected]>

* Update client/src/js/modules/types/sp/menu.js

Co-authored-by: Guilherme Francisco <[email protected]>

* Update client/src/js/modules/types/saxs/menu.js

Co-authored-by: Guilherme Francisco <[email protected]>

* Update client/src/js/modules/types/pow/menu.js

Co-authored-by: Guilherme Francisco <[email protected]>

* Update client/src/js/modules/types/mx/menu.js

Co-authored-by: Guilherme Francisco <[email protected]>

* Update client/src/js/modules/types/em/menu.js

Co-authored-by: Guilherme Francisco <[email protected]>

* Update client/src/js/app/components/combo-box.vue

Co-authored-by: Guilherme Francisco <[email protected]>

* Update api/src/Database/DatabaseFactory.php

Co-authored-by: John Holt <[email protected]>

* Update api/src/TemplateParser.php

Co-authored-by: Guilherme Francisco <[email protected]>

* Code review changes: database conns, code tidy

* add get started button

---------

Co-authored-by: Guilherme Francisco <[email protected]>
Co-authored-by: John Holt <[email protected]>
  • Loading branch information
3 people authored Jul 25, 2023
1 parent 1894d74 commit e0c0764
Show file tree
Hide file tree
Showing 22 changed files with 16,352 additions and 17 deletions.
5 changes: 5 additions & 0 deletions api/config_sample.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@
$isb = array('user' => 'user', 'pass' => 'pass', 'db' => 'localhost/ispyb');
$dbtype = 'mysql';

# Summary Database credentials
######### DELETE if not using connection.
$summarydbconfig = array('user' => 'user', 'pass' => 'pass', 'db' => 'localhost/ispyb');
$ifsummary = true;

# Encoded JWT key, used to sign and check validaty of jwt tokens
# - Create one of these using /api/authenticate/key
# This can be changed to invalidate all currently active tokens
Expand Down
12 changes: 10 additions & 2 deletions api/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ function setupApplication($mode): Slim
global $motd, $authentication_type, $cas_url, $cas_sso, $sso_url, $package_description,
$facility_courier_countries, $facility_courier_countries_nde,
$dhl_enable, $dhl_link, $scale_grid, $scale_grid_end_date, $preset_proposal, $timezone,
$valid_components, $enabled_container_types;
$valid_components, $enabled_container_types, $ifsummary;
$app->contentType('application/json');
$app->response()->body(json_encode(array(
'motd' => $motd,
Expand All @@ -87,7 +87,8 @@ function setupApplication($mode): Slim
'preset_proposal' => $preset_proposal,
'timezone' => $timezone,
'valid_components' => $valid_components,
'enabled_container_types' => $enabled_container_types
'enabled_container_types' => $enabled_container_types,
'ifsummary' => $ifsummary
)));
});
return $app;
Expand All @@ -102,6 +103,13 @@ function setupDependencyInjectionContainer($app)
return $db;
});

$app->container->singleton('dbsummary', function () use ($app): DatabaseParent {
$dbFactory = new DatabaseFactory(new DatabaseConnectionFactory());
$db = $dbFactory->get("summary");
$db->set_app($app);
return $db;
});

$app->container->singleton('authData', function () use ($app) {
return new AuthenticationData($app->container['db']);
});
Expand Down
11 changes: 11 additions & 0 deletions api/src/Database/DatabaseConnectionFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ class DatabaseConnectionFactory
public function get($databaseType)
{
global $isb;
global $summarydbconfig;

if (!$databaseType) {
error_log('Database type variable, dbtype, is not specified in config.php - defaulting to MySql.');
Expand All @@ -24,6 +25,16 @@ public function get($databaseType)
$conn = new \mysqli($host, $isb['user'], $isb['pass'], $dbn, $port);
$conn->set_charset("utf8mb4");
}
elseif ($databaseType == 'PureMySQL') {
$port = array_key_exists('port', $summarydbconfig) ? $summarydbconfig['port'] : null;
if (!$port) {
$port = ini_get("mysqli.default_port");
}
list($host, $dbn) = explode('/', $summarydbconfig['db']);
$conn = new \mysqli($host, $summarydbconfig['user'], $summarydbconfig['pass'], $dbn, $port);
$conn->set_charset("utf8mb4");
}


if ($conn == null) {
Utils::returnError("Database Configuration Error", "Database connection for type '$databaseType' does not exist.");
Expand Down
27 changes: 15 additions & 12 deletions api/src/Database/DatabaseFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ class DatabaseFactory
// Value is class name in SynchWeb\Database\Type namespace.
// Key is lower case representation of class name.
public $database_types = array(
'mysql' => 'MySQL'
'mysql' => ["dbClassName" =>'MySQL', "dataConnectionName" => 'MySQL'],
'summary' => ["dbClassName" =>'PureMySQL', "dataConnectionName" => 'PureMySQL']
);

function __construct($databaseConnectionFactory)
Expand All @@ -19,25 +20,27 @@ function __construct($databaseConnectionFactory)

private $databaseConnectionFactory;

public function get()
{
// Global variable is named $dbtype in config.php.
global $dbtype;
$database_type = $dbtype;
public function get($databaseType = null)
{
if ( $databaseType == null) {
// Global variable is named $dbtype in config.php.
global $dbtype;
$databaseType = $dbtype;
}

if (!$database_type) {
if (!$databaseType) {
error_log('Database type variable, dbtype, is not specified in config.php - defaulting to MySql.');
$database_type = 'MySQL';
}

// Determine fully-qualified class name of database class corresponding to $database_type.
if (key_exists(strtolower($database_type), $this->database_types)) {
$dbClassName = $this->database_types[strtolower($database_type)];
if (key_exists(strtolower($databaseType), $this->database_types)) {
$dbType = $this->database_types[strtolower($databaseType)];

$full_class_name = 'SynchWeb\\Database\\Type\\' . $dbClassName;
$full_class_name = 'SynchWeb\\Database\\Type\\' . $dbType["dbClassName"];;

if (class_exists($full_class_name)) {
$conn = $this->databaseConnectionFactory->get($dbClassName);
$conn = $this->databaseConnectionFactory->get($dbType["dataConnectionName"]);
return new $full_class_name($conn);
}
else {
Expand All @@ -46,7 +49,7 @@ public function get()

}
else {
error_log("Database type '$database_type' not configured.");
error_log("Database type '$databaseType' not configured.");
}
return null;
}
Expand Down
262 changes: 262 additions & 0 deletions api/src/Database/Type/PureMySQL.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,262 @@
<?php

namespace SynchWeb\Database\Type;

use SqlFormatter;
use SynchWeb\Database\DatabaseParent;

class PureMySQL extends DatabaseParent {
/** @var string */
protected $type = 'mysql';
/** @var string */
private $lastQuery = ''; // provide a way of retrieving the last query run - by storing the data - can then call getLastQuery() - primarily for testing
/** @var array */
private $lastArgs = array();
/** @var bool */
private $transaction = False;
/** @var int */
private $errors = 0;


function __construct($conn)
{
parent::__construct($conn);

mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT); // throw exceptions.

if (mysqli_connect_errno())
{
$this->error('There was an error connecting to MySQL: ', htmlentities(mysqli_connect_errno()));
}
}

// wsrep_sync_wait waits for cluster replication on a mariadb cluster
function wait_rep_sync($state = false)
{
# Empty - DatabaseFactory checks this exists
}

function start_transaction()
{
$this->transaction = True;
$this->conn->autocommit(False);
}

function end_transaction()
{
if ($this->errors > 0)
$this->conn->rollback();
else
$this->conn->commit();

$this->conn->autocommit(True);
$this->transaction = False;

if ($this->errors > 0)
$this->error('There was an error with MySQL', $this->conn->error . __LINE__);
$this->errors = 0;
}

function paginate($query, $args = array())
{
// MySQL is Limit Start Row, Number
// Oracle subselect is Start Row, End Row
if (sizeof($args))
$args[sizeof($args) - 1] = $args[sizeof($args) - 1] - $args[sizeof($args) - 2];
return $this->pq("$query LIMIT ?,?", $args);
}



// return the last SQL query executed in fully expanded form (i.e. including binded params) - this is mainly for testing purposes (so ideally would not be part of the actual class...)
function getLastQuery()
{
echo '<br/>';
$sql = $this->lastQuery;
for ($i = 1; $i < count($this->lastArgs); $i++)
{
$val = $this->lastArgs[$i];
if (is_string($val))
{
$val = "'" . $val . "'";
}
else if (is_null($val))
{
$val = 'null';
}
$sql = preg_replace('/\?/', $val, $sql, 1);
}
$sql = preg_replace('/\\n/', '', $sql); // replace newlines
return preg_replace('/\s\s+/', ' ', $sql); // remove excess spaces
}

function pq($query, $args = array(), $upperCaseKeys = true)
{

if ($this->debug)
{
print '<h1 class="debug">MySQL Debug</h1>';
print SqlFormatter::format($query);
echo '<br/>';
}

$stmt = $this->conn->prepare($query);

if (!$stmt)
{
if ($this->transaction)
$this->errors++;
else
{
$err = mysqli_error($this->conn);
$this->error('There was an error with MySQL', $err);
return;
}
}

if (sizeof($args))
{
$vtypes = array('NULL' => 'i', 'integer' => 'i', 'double' => 'd', 'string' => 's');

$strfs = '';
foreach ($args as $a)
{
$t = gettype($a);
$strfs .= $vtypes[$t];
}

array_unshift($args, $strfs);
call_user_func_array(array(&$stmt, 'bind_param'), $this->refs($args));
}

$this->lastQuery = $query;
$this->lastArgs = $args;
if ($this->debug)
{
print_r("Full SQL query: " . $this->getLastQuery());
}

if (!$stmt->execute())
{
if ($this->transaction)
$this->errors++;
else
{
$err = mysqli_error($this->conn);
$this->error('There was an error with MySQL', $err);
return;
}
}

$data = array();
if (strpos($query, 'SELECT') !== false)
{
$result = $stmt->get_result();
if ($result)
{
if ($result->num_rows > 0)
{
while ($row = $result->fetch_assoc())
{
$c = array();
// oracle inheritance ;(
foreach ($row as $key => $val)
{
if ($val !== null)
{
if (gettype($val) == gettype(0.1))
$val = round($val, 5);
$val = strval($val);
}
if ($upperCaseKeys)
{
$key = strtoupper($key);
}
$c[$key] = $val;
}
array_push($data, $c);
}
}
}
}

if ($this->debug)
{
echo '<br/>';
print_r('row count: ' . sizeof($data));
echo '<br/>';
}

// Need mysqlnd for this :(
// $result = $stmt->get_result();

// $data = array();

// if ($result) {
// if($result->num_rows > 0) {
// while($row = $result->fetch_assoc()) {
// array_push($data, array_change_key_case($row, CASE_UPPER));
// }
// }
// }

$stmt->close();

return $data;
}

// Union multiple queries that take the same arguments and return the same columns
// Query can optionally be wrapped, where :QUERY will be replaced with the inner query:
// $wrapper = 'SELECT * FROM (:QUERY) GROUP BY id';
function union($queries, $args, $all = false, $wrapper = null)
{
$nargs = sizeof($args);
$all_args = array();
$union_kw = $all ? 'UNION ALL' : 'UNION';
foreach ($queries as $i => &$query)
{
$offset = $i * $nargs;
$query = preg_replace_callback('/\:(\d+)/',
function ($mat) use ($offset)
{
return ':' . (intval($mat[1]) + $offset);
},
$query);
$all_args = array_merge($all_args, $args);
}

$union = implode("\n$union_kw\n", $queries);
if ($wrapper)
{
$union = preg_replace('/:QUERY/', $union, $wrapper);
}

return $this->pq($union, $all_args);
}

private function refs($arr)
{
$refs = array();
foreach ($arr as $key => $value)
{
$refs[$key] = & $arr[$key];
}
return $refs;
}

function read($field)
{
return $field;
}

function id()
{
return mysqli_insert_id($this->conn);
}

function close()
{
if ($this->conn)
$this->conn->close();
}
}
Loading

0 comments on commit e0c0764

Please sign in to comment.