Added module historyDefault/getById to check current user in history.details.view + Refactor css + added info in svg tags + javascript began management (only launch event, implementation TODO)
This commit is contained in:
parent
b0f9cfae1e
commit
43e626d32d
|
@ -199,6 +199,39 @@
|
|||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* (x) Return the entry data for an history id
|
||||
*
|
||||
* @id_entry<id> UID of the history entry
|
||||
*
|
||||
* @return data<array> Entry data
|
||||
*
|
||||
---------------------------------------------------------*/
|
||||
|
||||
public function getById($params){
|
||||
extract($params);
|
||||
|
||||
/* (1) Get history entry data
|
||||
---------------------------------------------------------*/
|
||||
/* (1) Request */
|
||||
$entry = new Repo('history/getById', [$id_entry]);
|
||||
|
||||
/* (2) Get response */
|
||||
$entry = $entry->answer();
|
||||
|
||||
/* (3) Manage error */
|
||||
if( !is_array($entry) )
|
||||
return ['error' => new Error(Err::RepoError)];
|
||||
|
||||
|
||||
/* (2) Return data
|
||||
---------------------------------------------------------*/
|
||||
return [ 'entry' => $entry ];
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
public $id_history;
|
||||
private $timeline = [];
|
||||
private $entry = [];
|
||||
|
||||
|
||||
/* (1) Constructor
|
||||
|
@ -23,7 +24,21 @@
|
|||
---------------------------------------------------------*/
|
||||
$this->id_history = $id_history;
|
||||
|
||||
/* (2) Get machine timeline
|
||||
|
||||
/* (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 ]);
|
||||
|
@ -61,68 +76,95 @@
|
|||
$cl = count($this->timeline);
|
||||
|
||||
/* (4) Create ranges of size 15 */
|
||||
$r_size = 10;
|
||||
$rl = round( $cl / $r_size );
|
||||
$r_size = 10; // set the number of actions by line
|
||||
$rl = floor( $cl / $r_size ); // calculate the number of whole lines
|
||||
$lrl = $cl % $r_size; // calculate the number of actions in the last line
|
||||
$y_range_diff = 100;
|
||||
$total_height = $y_range_diff*$rl;
|
||||
$total_height = ($lrl == 0 ) ? $y_range_diff*$rl : $y_range_diff*($rl+1); // total height (number of entries + last if not empty)
|
||||
|
||||
|
||||
/* (1) Svg tag */
|
||||
$RAW .= "<svg width='1000' height='$total_height' viewBox='0 0 1000 $total_height'>";
|
||||
/* (5) Svg tag */
|
||||
$RAW .= "<svg width='1000' height='$total_height' viewBox='0 0 1000 $total_height' class='timeline'>";
|
||||
|
||||
/* (2) Start CIRCLE */
|
||||
$RAW .= "<circle cx='50' cy='50' r='6' fill='#edf0f5'/>";
|
||||
$RAW .= "<circle cx='50' cy='50' r='4' fill='#555'/>";
|
||||
/* (6) Start CIRCLE */
|
||||
$RAW .= "<circle cx='50' cy='50' r='6' fill='#edf0f5' class='tstart'/>";
|
||||
$RAW .= "<circle cx='50' cy='50' r='4' fill='#555' class='tstart'/>";
|
||||
|
||||
|
||||
for( $r = 0 ; $r < $rl ; $r++ ){
|
||||
for( $r = 0 ; $r <= $rl ; $r++ ){
|
||||
|
||||
// if last line is empty -> stop here
|
||||
if( $r == $rl && $lrl == 0 )
|
||||
break;
|
||||
|
||||
$y = $y_range_diff*$r + 50;
|
||||
|
||||
/* (2) Build barebone
|
||||
---------------------------------------------------------*/
|
||||
/* (1) Timeline LINE */
|
||||
$RAW .= "<path d='m50 $y L900 $y' style='stroke-dasharray: 3px;' stroke='#444'/>";
|
||||
/* (1) Default TIMELINE */
|
||||
if( $r < $rl ){
|
||||
|
||||
$RAW .= "<path d='m50 $y L900 $y' style='stroke-dasharray: 3px;' stroke='#444' class='timeline line'/>";
|
||||
|
||||
/* (2) Last TIMELINE (can be shorter) */
|
||||
}else{ // if last line -> trace timeline until last element +1
|
||||
|
||||
$len = 100 + $lrl*800/$r_size;
|
||||
$RAW .= "<path d='m50 $y L$len $y' style='stroke-dasharray: 3px;' stroke='#444' class='timeline line'/>";
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* (3) Build each action
|
||||
---------------------------------------------------------*/
|
||||
for( $c = 0 ; $c < $r_size ; $c++ ){
|
||||
$el_len = ( $r == $rl ) ? $lrl : $r_size ;// number of elements on the line
|
||||
for( $c = 0 ; $c < $el_len ; $c++ ){
|
||||
|
||||
// exit if no more entry
|
||||
/* (1) Display nothing if last entry and is empty */
|
||||
if( !isset($this->timeline[$r*$r_size+$c]) )
|
||||
break;
|
||||
|
||||
/* (2) Get entry data */
|
||||
$entry = $this->timeline[$r*$r_size+$c];
|
||||
|
||||
/* (3) Get useful data */
|
||||
$action_class = strtolower($entry['action_name']);
|
||||
$icon_uri = '/src/static/timeline/'.$action_class.'@'.$this->get_action_color($action_class).'.svg';
|
||||
$x_offset = 100 + $c*800/$r_size;
|
||||
$x_img_offset = $x_offset - 5.5;
|
||||
$data_user = "data-user='".$entry['id_user']."'";
|
||||
$data_machine = " data-machine='".$entry['id_machine']."'";
|
||||
$data_action = " data-action='".$entry['id_action']."'";
|
||||
$data_time = " data-time='".date('H:i:s d/m/Y', $entry['timestamp'])."'";
|
||||
$data_tags = $data_user.$data_machine.$data_action.$data_time;
|
||||
|
||||
// circle
|
||||
$RAW .= "<circle cx='$x_offset' cy='$y' r='15' class='svg_$action_class op_svg'/>";
|
||||
$RAW .= "<circle cx='$x_offset' cy='$y' r='12' class='svg_$action_class'/>";
|
||||
/* (4) Draw entry circles */
|
||||
$RAW .= "<circle cx='$x_offset' cy='$y' r='15' class='timeline around $action_class' $data_tags />";
|
||||
$RAW .= "<circle cx='$x_offset' cy='$y' r='12' class='timeline center $action_class' />";
|
||||
|
||||
// inside icon
|
||||
/* (5) Draw circle around if not current user */
|
||||
if( $this->entry['id_user'] != $entry['id_user'] )
|
||||
$RAW .= "<circle cx='$x_offset' cy='$y' r='18' class='timeline user' />";
|
||||
|
||||
|
||||
/* (6) Draw entry icon (action) */
|
||||
$y_decal = $y - 5.5;
|
||||
$RAW .= "<image x='$x_img_offset' y='$y_decal' width='12' height='12' xlink:href='$icon_uri'/>";
|
||||
$RAW .= "\t<image x='$x_img_offset' y='$y_decal' width='12' height='12' xlink:href='$icon_uri' class='icon' />";
|
||||
|
||||
}
|
||||
|
||||
// exit if no more entry
|
||||
if( !isset($this->timeline[$r*$r_size]) )
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* (4) Stop CIRCLE */
|
||||
/* (4) Close SVG
|
||||
---------------------------------------------------------*/
|
||||
/* (1) Stop CIRCLE */
|
||||
$x_offset = 100 + $c*800/$r_size;
|
||||
$RAW .= "<circle cx='$x_offset' cy='$y' r='6' fill='#edf0f5'/>";
|
||||
$RAW .= "<circle cx='$x_offset' cy='$y' r='4' fill='#555'/>";
|
||||
$RAW .= "<circle cx='$x_offset' cy='$y' r='6' fill='#edf0f5' class='tstop' />";
|
||||
$RAW .= "<circle cx='$x_offset' cy='$y' r='4' fill='#555' class='tstop' />";
|
||||
|
||||
/* (5) Close SVG tag */
|
||||
/* (2) Close SVG tag */
|
||||
$RAW .= "</svg>";
|
||||
|
||||
|
||||
|
|
|
@ -616,6 +616,17 @@
|
|||
"output": {
|
||||
"timeline": { "description": "Données de la timeline.", "type": "array" }
|
||||
}
|
||||
},
|
||||
|
||||
"getById": {
|
||||
"description": "Retourne les données associées à une entrée historique.",
|
||||
"permissions": [["admin"]],
|
||||
"parameters": {
|
||||
"id_entry": { "description": "UID de l'entrée historique", "type": "id" }
|
||||
},
|
||||
"output": {
|
||||
"entry": { "description": "Données de l'entrée.", "type": "array" }
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
|
|
|
@ -540,43 +540,83 @@ article.check-table{
|
|||
|
||||
/* [4] Timeline SVG
|
||||
=========================================================*/
|
||||
/* (1) svg circles -> set right transform-origin */
|
||||
svg > circle[class^=svg_]{
|
||||
svg.timeline{
|
||||
|
||||
/* (1) svg circles -> set right transform-origin */
|
||||
& circle.timeline{
|
||||
|
||||
-webkit-transform-origin: 50% 50% 0;
|
||||
transform-origin: 50% 50% 0;
|
||||
|
||||
transition: transform .2s ease-in-out;
|
||||
|
||||
}
|
||||
|
||||
/* (2) Set cursor to pointer */
|
||||
svg > circle[class^=svg_]:not(.op_svg){
|
||||
/* (2) Set cursor to pointer */
|
||||
&.around{
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* (3) Middle circles -> scale+ on hover */
|
||||
svg > circle[class^=svg_]:not(.op_svg):hover{
|
||||
/* (3) Dispatch event to next nodes */
|
||||
&:hover + .center{ // center node
|
||||
|
||||
-webkit-transform: scale(1.2);
|
||||
transform: scale(1.2);
|
||||
}
|
||||
|
||||
/* (4) Avoid icons inside middle circles to block :hover */
|
||||
svg > circle[class^=svg_]:not(.op_svg) + image{
|
||||
-webkit-pionter-events: none;
|
||||
}
|
||||
|
||||
&:hover + .center + .user{ // user node
|
||||
|
||||
-webkit-transform: scale(.8);
|
||||
transform: scale(.8);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* (4) Remove center circle event */
|
||||
&.center{
|
||||
|
||||
-webkit-pointer-events: none;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* (5) Make around circles a bit transparent */
|
||||
svg > circle.op_svg{
|
||||
opacity: .6;
|
||||
}
|
||||
}
|
||||
|
||||
/* (6) Set circle colors according to action type */
|
||||
svg > circle.svg_start{ fill: #2cde8b; }
|
||||
svg > circle.svg_stop{ fill: #3a3a3a; }
|
||||
svg > circle.svg_lock{ fill: #e04343; }
|
||||
svg > circle.svg_unlock{ fill: #af1c1c; }
|
||||
svg > circle.svg_signal{ fill: #3258d8; }
|
||||
svg > circle.svg_unsignal{ fill: #2041ab; }
|
||||
/* (5) Set colors according to action type */
|
||||
&.around, &.center{
|
||||
|
||||
&.start{ fill: #2cde8b; }
|
||||
&.stop{ fill: #3a3a3a; }
|
||||
&.lock{ fill: #e04343; }
|
||||
&.unlock{ fill: #af1c1c; }
|
||||
&.signal{ fill: #3258d8; }
|
||||
&.unsignal{ fill: #2041ab; }
|
||||
|
||||
}
|
||||
|
||||
/* (6) Make around circles a bit transparent */
|
||||
&.around{ opacity: .6; }
|
||||
|
||||
/* (7) User circles */
|
||||
&.user{
|
||||
fill: none;
|
||||
stroke-width: 1.5px;
|
||||
stroke: #777;
|
||||
stroke-opacity: .3;
|
||||
}
|
||||
|
||||
/* (8) Set user colors according to action type */
|
||||
&.center.start + .user{ stroke: #2cde8b; }
|
||||
&.center.stop + .user{ stroke: #3a3a3a; }
|
||||
&.center.lock + .user{ stroke: #e04343; }
|
||||
&.center.unlock + .user{ stroke: #af1c1c; }
|
||||
&.center.signal + .user{ stroke: #3258d8; }
|
||||
&.center.unsignal + .user{ stroke: #2041ab; }
|
||||
|
||||
}
|
||||
|
||||
/* (9) Avoid icons inside center circles to block :hover */
|
||||
image{
|
||||
|
||||
-webkit-pointer-events: none;
|
||||
pointer-events: none;
|
||||
|
||||
}
|
||||
}
|
|
@ -698,59 +698,106 @@ article.check-table > div > span input[type='checkbox']:checked + label[for] {
|
|||
|
||||
/* [4] Timeline SVG
|
||||
=========================================================*/
|
||||
/* (1) svg circles -> set right transform-origin */
|
||||
svg > circle[class^=svg_] {
|
||||
svg.timeline {
|
||||
/* (1) svg circles -> set right transform-origin */
|
||||
/* (9) Avoid icons inside center circles to block :hover */
|
||||
}
|
||||
|
||||
svg.timeline circle.timeline {
|
||||
-webkit-transform-origin: 50% 50% 0;
|
||||
transform-origin: 50% 50% 0;
|
||||
transition: transform .2s ease-in-out;
|
||||
/* (2) Set cursor to pointer */
|
||||
/* (4) Remove center circle event */
|
||||
/* (5) Set colors according to action type */
|
||||
/* (6) Make around circles a bit transparent */
|
||||
/* (7) User circles */
|
||||
/* (8) Set user colors according to action type */
|
||||
}
|
||||
|
||||
/* (2) Set cursor to pointer */
|
||||
svg > circle[class^=svg_]:not(.op_svg) {
|
||||
svg.timeline circle.timeline.around {
|
||||
cursor: pointer;
|
||||
/* (3) Dispatch event to next nodes */
|
||||
}
|
||||
|
||||
/* (3) Middle circles -> scale+ on hover */
|
||||
svg > circle[class^=svg_]:not(.op_svg):hover {
|
||||
svg.timeline circle.timeline.around:hover + .center {
|
||||
-webkit-transform: scale(1.2);
|
||||
transform: scale(1.2);
|
||||
}
|
||||
|
||||
/* (4) Avoid icons inside middle circles to block :hover */
|
||||
svg > circle[class^=svg_]:not(.op_svg) + image {
|
||||
-webkit-pionter-events: none;
|
||||
svg.timeline circle.timeline.around:hover + .center + .user {
|
||||
-webkit-transform: scale(0.8);
|
||||
transform: scale(0.8);
|
||||
}
|
||||
|
||||
svg.timeline circle.timeline.center {
|
||||
-webkit-pointer-events: none;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* (5) Make around circles a bit transparent */
|
||||
svg > circle.op_svg {
|
||||
opacity: .6;
|
||||
}
|
||||
|
||||
/* (6) Set circle colors according to action type */
|
||||
svg > circle.svg_start {
|
||||
svg.timeline circle.timeline.around.start, svg.timeline circle.timeline.center.start {
|
||||
fill: #2cde8b;
|
||||
}
|
||||
|
||||
svg > circle.svg_stop {
|
||||
svg.timeline circle.timeline.around.stop, svg.timeline circle.timeline.center.stop {
|
||||
fill: #3a3a3a;
|
||||
}
|
||||
|
||||
svg > circle.svg_lock {
|
||||
svg.timeline circle.timeline.around.lock, svg.timeline circle.timeline.center.lock {
|
||||
fill: #e04343;
|
||||
}
|
||||
|
||||
svg > circle.svg_unlock {
|
||||
svg.timeline circle.timeline.around.unlock, svg.timeline circle.timeline.center.unlock {
|
||||
fill: #af1c1c;
|
||||
}
|
||||
|
||||
svg > circle.svg_signal {
|
||||
svg.timeline circle.timeline.around.signal, svg.timeline circle.timeline.center.signal {
|
||||
fill: #3258d8;
|
||||
}
|
||||
|
||||
svg > circle.svg_unsignal {
|
||||
svg.timeline circle.timeline.around.unsignal, svg.timeline circle.timeline.center.unsignal {
|
||||
fill: #2041ab;
|
||||
}
|
||||
|
||||
svg.timeline circle.timeline.around {
|
||||
opacity: .6;
|
||||
}
|
||||
|
||||
svg.timeline circle.timeline.user {
|
||||
fill: none;
|
||||
stroke-width: 1.5px;
|
||||
stroke: #777;
|
||||
stroke-opacity: .3;
|
||||
}
|
||||
|
||||
svg.timeline circle.timeline.center.start + .user {
|
||||
stroke: #2cde8b;
|
||||
}
|
||||
|
||||
svg.timeline circle.timeline.center.stop + .user {
|
||||
stroke: #3a3a3a;
|
||||
}
|
||||
|
||||
svg.timeline circle.timeline.center.lock + .user {
|
||||
stroke: #e04343;
|
||||
}
|
||||
|
||||
svg.timeline circle.timeline.center.unlock + .user {
|
||||
stroke: #af1c1c;
|
||||
}
|
||||
|
||||
svg.timeline circle.timeline.center.signal + .user {
|
||||
stroke: #3258d8;
|
||||
}
|
||||
|
||||
svg.timeline circle.timeline.center.unsignal + .user {
|
||||
stroke: #2041ab;
|
||||
}
|
||||
|
||||
svg.timeline image {
|
||||
-webkit-pointer-events: none;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
|
||||
/*# sourceMappingURL= container.css.map */
|
|
@ -151,3 +151,46 @@ if( section.archive.element != null ){
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* GESTION DE L'AFFICHAGE DES DETAILS
|
||||
*
|
||||
*/
|
||||
if( section.details.element != null ){
|
||||
|
||||
/* (1) Get useful DOM Elements
|
||||
---------------------------------------------------------*/
|
||||
section.details.event = {
|
||||
// svg parent
|
||||
parent: {
|
||||
text: section.details.text+' svg ',
|
||||
element: document.querySelector( section.details.text+' svg ' )
|
||||
},
|
||||
|
||||
// each node
|
||||
text: section.details.text+' svg circle.around ',
|
||||
element: document.querySelectorAll( section.details.text+' svg circle.around ' )
|
||||
};
|
||||
|
||||
/* (2) Function: show infobox on click on event
|
||||
---------------------------------------------------------*/
|
||||
section.details.event.handler = function(target){
|
||||
console.log('show infobox on element', target);
|
||||
};
|
||||
|
||||
/* (n) Trigger event */
|
||||
section.details.event.parent.element.addEventListener('click', function(e){
|
||||
|
||||
// {1} Trigger function only if element is an 'around circle' //
|
||||
if( e.target.nodeName && e.target.getData('user') && e.target.getData('machine') && e.target.getData('action') && e.target.getData('time') )
|
||||
section.details.event.handler(e.target);
|
||||
|
||||
}, false);
|
||||
|
||||
|
||||
}
|
Loading…
Reference in New Issue