247 lines
7.0 KiB
PHP
247 lines
7.0 KiB
PHP
<?php
|
|
|
|
namespace view\history\details;
|
|
|
|
use \generic\core\i_view;
|
|
use \api\core\Request;
|
|
use \error\core\Err;
|
|
|
|
|
|
class main extends i_view{
|
|
|
|
public $id_history;
|
|
public $timeline = [];
|
|
public $entry = [];
|
|
|
|
|
|
/* (1) Constructor
|
|
*
|
|
* @id_history<id> UID of the history entry
|
|
*
|
|
---------------------------------------------------------*/
|
|
public function __construct($id_history){
|
|
/* (1) Set attributes
|
|
---------------------------------------------------------*/
|
|
$this->id_history = $id_history;
|
|
|
|
|
|
/* (3) Get entry data
|
|
---------------------------------------------------------*/
|
|
/* (1) Request */
|
|
$entry_req = new Request('historyDefault/getById', [ 'id_entry' => $this->id_history ]);
|
|
|
|
/* (2) Get response */
|
|
$entry_res = $entry_req->dispatch();
|
|
|
|
/* (3) On success, store entry data */
|
|
if( $entry_res->error->get() == Err::Success )
|
|
$this->entry = $entry_res->get('entry');
|
|
|
|
|
|
/* (3) Get machine timeline
|
|
---------------------------------------------------------*/
|
|
/* (1) Request */
|
|
$mac_req = new Request('historyDefault/get_timeline', [ 'id_entry' => $this->id_history ]);
|
|
|
|
/* (2) Get response */
|
|
$mac_res = $mac_req->dispatch();
|
|
|
|
/* (3) On success, store timeline data */
|
|
if( $mac_res->error->get() == Err::Success ){
|
|
$this->timeline = $mac_res->get('timeline');
|
|
|
|
// add date nodes to the timeline
|
|
$this->add_date_nodes();
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* (2) Format timeline data to svg render
|
|
*
|
|
* @return svg<String> SVG raw render
|
|
*
|
|
---------------------------------------------------------*/
|
|
public function svg(){
|
|
|
|
/* (1) Initialize variables
|
|
---------------------------------------------------------*/
|
|
/* (1) Set date() timezone */
|
|
date_default_timezone_set('Europe/Paris');
|
|
debug();
|
|
|
|
/* (2) Init. result raw svg */
|
|
$RAW = '';
|
|
|
|
/* (3) Set global range */
|
|
$c = 0;
|
|
$cl = count($this->timeline);
|
|
|
|
// if no entry -> abort
|
|
if( $cl == 0 )
|
|
return '';
|
|
|
|
/* (4) Useful variables */
|
|
$y_pad = 80; // padding between each node
|
|
$line_pad = 50; // padding on each LINE end
|
|
$line_height = ( $cl + 1 ) * $y_pad; // line height (each node * @y_pad + @y_pad)
|
|
$height = $line_height + 2*$line_pad; // svg height
|
|
$width = 200; // svg width
|
|
$x = 50; // center width
|
|
|
|
/* (5) Svg tag */
|
|
$RAW .= "<svg width='$width' height='$height' viewBox='0 0 $width $height' class='timeline'>";
|
|
|
|
/* (6) Start CIRCLE */ {
|
|
|
|
// {6.1} Date node //
|
|
$y = $line_pad;
|
|
$RAW .= "<circle cx='$x' cy='$y' r='7' fill='#edf0f5' class='tstart'/>";
|
|
$RAW .= "<circle cx='$x' cy='$y' r='4' fill='#555' class='tstart'/>";
|
|
|
|
// {6.2} Date line to text //
|
|
$line_end_x = $x + (30-8);
|
|
$RAW .= "<path d='m".($x+8)." $y L$line_end_x $y' style='stroke-dasharray: 3px;' s stroke='#444'/>";
|
|
|
|
// {6.3} Date text //
|
|
$x_decal = $x + 30;
|
|
$y_decal = $y + 5;
|
|
$RAW .= "<text x='$x_decal' y='$y_decal' class='bold'>".date('d / m / Y', $this->timeline[0]['timestamp'])."</text>";
|
|
|
|
}
|
|
|
|
|
|
/* (2) Build barebone
|
|
---------------------------------------------------------*/
|
|
/* (1) Default TIMELINE */
|
|
$line_end_y = $line_height + $line_pad;
|
|
$RAW .= "<path d='m$x $line_pad L$x $line_end_y' style='stroke-dasharray: 3px;' stroke='#444' class='timeline line'/>";
|
|
|
|
|
|
/* (3) Build each action
|
|
---------------------------------------------------------*/
|
|
for( $c = 0 ; $c < $cl ; $c++ ){
|
|
|
|
/* (1) Calculate X */
|
|
$y = $line_pad + $y_pad + $c*$y_pad;
|
|
|
|
/* (2) Get entry data */
|
|
$entry = $this->timeline[$c];
|
|
|
|
/* (2.1) If DATE NODE -> add it */
|
|
if( isset($entry['date_node']) ){
|
|
|
|
// {2.1.1} Date node //
|
|
$RAW .= "<circle cx='$x' cy='$y' r='7' fill='#edf0f5' class='tstart'/>";
|
|
$RAW .= "<circle cx='$x' cy='$y' r='4' fill='#555' class='tstart'/>";
|
|
|
|
// {2.1.2} Date line to text //
|
|
$line_end_x = $x + (30-8);
|
|
$RAW .= "<path d='m".($x+8)." $y L$line_end_x $y' style='stroke-dasharray: 3px;' stroke='#555'/>";
|
|
|
|
// {2.1.3} Date text //
|
|
$x_decal = $x + 30;
|
|
$y_decal = $y + 5;
|
|
$RAW .= "<text x='$x_decal' y='$y_decal' class='bold'>".$entry['date_node']."</text>";
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
/* (3) Get useful data */
|
|
$action_class = strtolower($entry['action_name']);
|
|
$icon_uri = '/src/static/timeline/'.$action_class.'@ffffff.svg';
|
|
$data_user = "data-user='".$entry['user_name']."'";
|
|
$data_machine = " data-machine='".$entry['machine_name']."'";
|
|
$data_action = " data-action='".$entry['action_name']."'";
|
|
$data_time = " data-time='".date('H:i:s d/m/Y', $entry['timestamp'])."'";
|
|
$data_tags = $data_user.$data_machine.$data_action.$data_time;
|
|
|
|
$y_img = $y - 5.5;
|
|
|
|
/* (4) Draw entry circles */
|
|
$RAW .= "<circle cx='$x' cy='$y' r='15' class='timeline around $action_class' $data_tags />";
|
|
$RAW .= "<circle cx='$x' cy='$y' r='12' class='timeline center $action_class' />";
|
|
|
|
/* (5) Draw entry icon (action) */
|
|
$x_decal = $x - 5.5;
|
|
$RAW .= "\t<image x='$x_decal' y='$y_img' width='12' height='12' xlink:href='$icon_uri' class='icon' />";
|
|
|
|
/* (6) Draw circle below if current user */
|
|
if( $this->entry['id_user'] == $entry['id_user'] ){
|
|
$x_decal = $x - 21;
|
|
$RAW .= "<circle cx='$x_decal' cy='$y' r='2' class='timeline below $action_class' />";
|
|
}
|
|
|
|
/* (6) Hour */
|
|
$x_decal = $x + 25;
|
|
$y_decal = $y + 5;
|
|
$RAW .= "<text x='$x_decal' y='$y_decal' class='$action_class'>".date('H:i:s', $entry['timestamp'])."</text>";
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
/* (4) Close SVG
|
|
---------------------------------------------------------*/
|
|
/* (1) Stop CIRCLE */
|
|
$y = $line_height + $line_pad;
|
|
$RAW .= "<circle cx='$x' cy='$y' r='6' fill='#edf0f5' class='tstop' />";
|
|
$RAW .= "<circle cx='$x' cy='$y' r='4' fill='#555' class='tstop' />";
|
|
|
|
/* (2) Close SVG tag */
|
|
$RAW .= "</svg>";
|
|
|
|
|
|
/* (5) Create invisible infobox (for now)
|
|
---------------------------------------------------------*/
|
|
$RAW .= "<div class='timeline infobox'></div>";
|
|
|
|
|
|
|
|
return $RAW;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* (3) Add events for new day in @this->timeline
|
|
*
|
|
---------------------------------------------------------*/
|
|
private function add_date_nodes(){
|
|
|
|
/* (1) Initialization
|
|
---------------------------------------------------------*/
|
|
/* (1) Initialize variables */
|
|
$last_day = null;
|
|
$new_timeline = []; // will contain the new @timeline data
|
|
|
|
|
|
/* (2) Browse each entry
|
|
---------------------------------------------------------*/
|
|
foreach($this->timeline as $entry){
|
|
|
|
/* (1) If different day (not null) -> add a node + update last_day */
|
|
if( !is_null($last_day) && $last_day != date('d / m / Y', $entry['timestamp']) )
|
|
$new_timeline[] = [ 'date_node' => $last_day ];
|
|
|
|
/* (2) In all cases -> copy the event */
|
|
$new_timeline[] = $entry;
|
|
|
|
/* (3) Update the day */
|
|
$last_day = date('d / m / Y', $entry['timestamp']);
|
|
|
|
}
|
|
|
|
|
|
/* (3) Update the result
|
|
---------------------------------------------------------*/
|
|
$this->timeline = $new_timeline;
|
|
|
|
}
|
|
|
|
} |