Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
druid-public
headwork
Commits
67ee206b
Commit
67ee206b
authored
Jun 07, 2021
by
Yannick Zohou
Committed by
GROSS-AMBLARD David
Jun 07, 2021
Browse files
merge-proj-viz-into-master
parent
1405a181
Changes
23
Expand all
Hide whitespace changes
Inline
Side-by-side
.gitignore
View file @
67ee206b
...
...
@@ -2,3 +2,4 @@ log/log.txt
projects/spipoll/*
.*
config.php
HWlib.php
\ No newline at end of file
AjaxManager.php
View file @
67ee206b
...
...
@@ -3,6 +3,7 @@
session_start
();
require_once
"HWlib.php"
;
require_once
"TaskViewerModel.php"
;
$manager
=
new
AjaxManager
();
...
...
@@ -19,22 +20,36 @@ if (isset($_POST['action'])) {
/**
* This class goal is to compute data to send back to the ajax call
*/
class
AjaxManager
{
class
AjaxManager
{
private
$db
;
// Constants : node types
private
const
ARTIFACT_CLASS
=
'artifactClass'
;
private
const
ARTIFACT
=
'artifact'
;
private
const
USER
=
'user'
;
// Constants : node prefix
private
const
ARTIFACT_CLASS_PREFIX
=
'artifactClass_'
;
private
const
ARTIFACT_PREFIX
=
'artifact_'
;
private
const
USER_PREFIX
=
'user_'
;
// Constants : edge types
private
const
EDGE_ARTIFACT_TO_ARTIFACT_CLASS
=
'artifact-to-artifactClass'
;
private
const
EDGE_ARTIFACT_TO_USER
=
'artifact-to-user'
;
private
const
EMPTY_PARAMETER
=
''
;
/**
* Class constructor
*/
function
__construct
()
{
function
__construct
()
{
$this
->
db
=
HWdbconnect
();
}
/**
* Retrieve the latest enabled task id and send its value through JSON
*/
function
getLastestTaskId
()
{
function
getLastestTaskId
()
{
if
(
isset
(
$_POST
[
'task'
]))
{
$taskId
=
$_POST
[
'task'
];
$stmt
=
$this
->
db
->
prepare
(
"SELECT idtask FROM profile WHERE idtask = (
...
...
@@ -55,6 +70,96 @@ class AjaxManager {
}
}
}
/**
* get_nodes_data
*
* Returns all nodes data required to build the graph.
*/
function
getNodesData
()
{
$t_data
=
array
();
// ArtifactClass nodes
$stmt
=
$this
->
db
->
prepare
(
"SELECT * FROM ArtifactClass;"
);
$stmt
->
execute
();
$result
=
$stmt
->
setFetchMode
(
PDO
::
FETCH_ASSOC
);
while
(
$line
=
(
$stmt
->
fetch
()))
{
$t_data
[]
=
new
NodeData
(
self
::
ARTIFACT_CLASS_PREFIX
.
$line
[
'id'
],
// id
$line
[
'description'
],
// label
self
::
ARTIFACT_CLASS
// type
);
}
// Artifact nodes
$stmt
=
$this
->
db
->
prepare
(
"SELECT * FROM Artifact;"
);
$stmt
->
execute
();
$result
=
$stmt
->
setFetchMode
(
PDO
::
FETCH_ASSOC
);
?>
\ No newline at end of file
while
(
$line
=
(
$stmt
->
fetch
()))
{
$t_data
[]
=
new
NodeData
(
self
::
ARTIFACT_PREFIX
.
$line
[
'id'
],
// id
self
::
EMPTY_PARAMETER
,
// label
self
::
ARTIFACT
// type
);
}
// Users nodes, retrieve users who answered tasks
$stmt
=
$this
->
db
->
prepare
(
"SELECT * FROM Users WHERE id IN (SELECT user FROM Answer);"
);
$stmt
->
execute
();
$result
=
$stmt
->
setFetchMode
(
PDO
::
FETCH_ASSOC
);
while
(
$line
=
(
$stmt
->
fetch
()))
{
$t_data
[]
=
new
NodeData
(
self
::
USER_PREFIX
.
$line
[
'id'
],
// id
$line
[
'name'
],
// label
self
::
USER
// type
);
}
echo
json_encode
(
$t_data
,
JSON_FORCE_OBJECT
);
}
/**
* get_edges_data
*
* Returns all edges data required to build the graph.
*/
function
getEdgesData
()
{
$t_data
=
array
();
// Edges from Artifact nodes to ArtifactClass nodes
$stmt
=
$this
->
db
->
prepare
(
"SELECT id, classid FROM Artifact;"
);
$stmt
->
execute
();
$result
=
$stmt
->
setFetchMode
(
PDO
::
FETCH_ASSOC
);
while
(
$line
=
(
$stmt
->
fetch
()))
{
$t_data
[]
=
new
EdgeData
(
self
::
ARTIFACT_PREFIX
.
$line
[
'id'
],
// source
self
::
ARTIFACT_CLASS_PREFIX
.
$line
[
'classid'
],
// target
self
::
EDGE_ARTIFACT_TO_ARTIFACT_CLASS
,
// type
self
::
EMPTY_PARAMETER
,
// label
self
::
EMPTY_PARAMETER
// state
);
}
// Edges from Artifact nodes to User nodes
$stmt
=
$this
->
db
->
prepare
(
"SELECT DISTINCT answer.artifact, answer.user, artifactclass.description, artifact.state FROM answered JOIN answer ON answered.modified = answer.modified JOIN artifact ON answer.artifact = artifact.id JOIN artifactclass ON artifact.classid = artifactclass.id;"
);
$stmt
->
execute
();
$result
=
$stmt
->
setFetchMode
(
PDO
::
FETCH_ASSOC
);
while
(
$line
=
(
$stmt
->
fetch
()))
{
$t_data
[]
=
new
EdgeData
(
self
::
ARTIFACT_PREFIX
.
$line
[
'artifact'
],
// source
self
::
USER_PREFIX
.
$line
[
'user'
],
// target
self
::
EDGE_ARTIFACT_TO_USER
,
// type
$line
[
'description'
],
// label
$line
[
'state'
]
// stage
);
}
echo
json_encode
(
$t_data
,
JSON_FORCE_OBJECT
);
}
}
HWlib.php
View file @
67ee206b
<?php
require_once
(
"config.php"
);
/**
* HW library
*
*/
require_once
(
"config.php"
);
/**
* If global constant DEBUG is true, echoes the parameter string. In any case, log the message.
...
...
TaskViewerModel.php
0 → 100644
View file @
67ee206b
<?php
/**
* Tasks Viewer Model.
*
* @author Projet M2 VIZ
* @see tasks-viewer.php
*/
/**
* Class NodeData.
*/
class
NodeData
{
public
$id
;
public
$label
;
public
$type
;
/**
* Class constructor
*/
public
function
__construct
(
string
$id
,
string
$label
,
string
$type
)
{
$this
->
id
=
$id
;
$this
->
label
=
$label
;
$this
->
type
=
$type
;
}
}
/**
* Class EdgeData.
*/
class
EdgeData
{
public
$source
;
public
$target
;
public
$type
;
public
$label
;
public
$state
;
/**
* Class constructor
*/
public
function
__construct
(
string
$source
,
string
$target
,
string
$type
,
string
$label
,
string
$state
)
{
$this
->
source
=
$source
;
$this
->
target
=
$target
;
$this
->
type
=
$type
;
$this
->
label
=
$label
;
$this
->
state
=
$state
;
}
}
artifacts.php
View file @
67ee206b
...
...
@@ -2,7 +2,6 @@
require_once
(
"wirk.php"
);
/**
* sugarFree
*
...
...
@@ -104,32 +103,58 @@ function updateonce($conn, $artifact, $artifactid, $count)
$query
=
"select definition from ArtifactClass,Artifact where Artifact.id=
$artifactid
and Artifact.classid=ArtifactClass.id"
;
$artifactfile
=
$conn
->
query
(
$query
)
->
fetch
()[
'definition'
];
$artifact
=
load_artifact
(
$artifactfile
);
$stateinfo
=
$artifact
[
$node
];
debug
(
"node data: "
.
HTMLpre
(
json_encode
(
$stateinfo
)));
// checking if we have reached a final node
if
(
empty
(
$artifact
[
$node
])){
debug
(
"Reaching final state
$node
"
);
$conn
->
query
(
"update Artifact set state='finished' where ID=
$artifactid
"
);
return
false
;
}
//Empty variable to hold guard value if found
$guard
=
''
;
$actions
=
''
;
foreach
(
$stateinfo
as
$dest
=>
$v
)
{
debug
(
"checking transition
$node
->
$dest
"
);
debug
(
"node data: "
.
json_encode
(
$stateinfo
[
$dest
]));
$guard
=
$artifact
[
$node
][
$dest
][
"guard"
];
$guard
=
sugarFree
(
$guard
);
if
(
isset
(
$artifact
[
$node
][
$dest
][
"guard"
])
){
$guard
=
$artifact
[
$node
][
$dest
][
"guard"
];
$guard
=
sugarFree
(
$guard
);
}
if
(
$guard
==
"none"
)
$guard
=
"select true from dual"
;
if
(
preg_match
(
"/^task ([0-9]+) is answered/"
,
$guard
,
$matches
)){
$guard
=
"select true from Answered where artifact=CURRENT_ARTIFACT and id="
.
$matches
[
1
];
}
$guard
=
str_replace
(
'SESSION_USER'
,
$_SESSION
[
'id'
],
$guard
);
$guard
=
str_replace
(
"CURRENT_ARTIFACT"
,
$artifactid
,
$guard
);
$actions
=
str_replace
(
'SESSION_USER'
,
$_SESSION
[
'id'
],
$artifact
[
$node
][
$dest
][
"actions"
]);
if
(
isset
(
$artifact
[
$node
][
$dest
][
"actions"
])
){
$actions
=
str_replace
(
'SESSION_USER'
,
$_SESSION
[
'id'
],
$artifact
[
$node
][
$dest
][
"actions"
]);
}
if
(
isset
(
$_SESSION
[
'skills'
]))
{
$actions
=
str_replace
(
'SKILLS'
,
$_SESSION
[
'skills'
],
$actions
);
// TODO but actions is an array?
// TODO what for?
}
//We make sure that guard and actions are not empty before sending a query to activate step
if
(
$guard
!==
''
&&
$actions
!==
''
){
$activated
=
step
(
$conn
,
$artifactid
,
$node
,
$dest
,
$guard
,
$actions
);
debug
(
"result:"
.
$activated
);
if
(
$activated
)
{
return
true
;
}
$activated
=
step
(
$conn
,
$artifactid
,
$node
,
$dest
,
$guard
,
$actions
);
if
(
$activated
)
{
return
true
;
...
...
@@ -138,6 +163,7 @@ function updateonce($conn, $artifact, $artifactid, $count)
debug
(
"no transition from
$node
"
);
return
false
;
// no guard is validated
}
}
/**
* Return the json description of an artifact, stored in the artifactclasses directory
...
...
@@ -276,6 +302,7 @@ function step($conn, $artifactid, $from, $to, $guard, $actions)
$conn
->
commit
();
return
$guardvalue
;
}
/**
* startArtifact
*
...
...
@@ -344,8 +371,3 @@ function pignistic($conn,$artifactid){
$conn
->
query
(
"insert into Answer(idtask,user,Artifact,value,mass) select MAX(idtask)+1,1,
$artifactid
,
$choice
,1 from Answer where Artifact=
$artifactid
"
);
}
?>
config.php.example
deleted
100644 → 0
View file @
1405a181
<?php
/**
* Configuration file
*
*/
// Set DEBUG to true to see plenty of error messages
define
(
"DEBUG"
,
false
);
//define("DEBUG",true);
// Location of the log file
define
(
"LOGFILENAME"
,
"log/log.txt"
);
// Add more error messages from PHP
ini_set
(
'display_startup_errors'
,
1
);
ini_set
(
'display_errors'
,
1
);
error_reporting
(
-
1
);
// Mysql parameters
define
(
"SERVERNAME"
,
"localhost"
);
define
(
"USERNAME"
,
"headworkadmin"
);
define
(
"PASSWORD"
,
"<your password here>"
);
define
(
"DATABASE"
,
"headwork"
);
// Wirk connector parameters
define
(
"WIRKAPIUSER"
,
"<your WIRK endpoint here>"
);
define
(
"WIRKAPIPASSWORD"
,
"<your WIRK API password here>"
);
define
(
"WIRKAPPID"
,
"853"
);
define
(
"WIRKQUALITYID"
,
"1386"
);
define
(
"WIRKPROJECTENDPOINT"
,
"https://api.wirk.io/v1_0/AppProject"
);
define
(
"WIRKTASKLINEENDPOINT"
,
"https://api.wirk.io/v1_0/TaskLine"
);
// Bot parameters
define
(
"NBBOTS"
,
10
);
?>
css/style.css
0 → 100644
View file @
67ee206b
.workflow-tittle
{
border
:
1px
solid
#6c757d
;
background-color
:
#6c757d
;
border-radius
:
5px
;
}
.div-artifact-title
{
height
:
fit-content
;
overflow
:
auto
;
font-size
:
15px
;
padding-left
:
2px
;
}
.div-artifact-info
{
height
:
fit-content
;
overflow
:
auto
;
padding-left
:
2px
;
margin-top
:
2px
;
}
.toggle
{
display
:
none
;
height
:
fit-content
;
}
.artifact-infos
{
height
:
560px
;
overflow-y
:
auto
;
}
.tittle-style
{
font-weight
:
bold
;
font-family
:
Times
;
}
.info-style
{
font-style
:
italic
;
font-family
:
courier
;
font-size
:
16px
;
}
.div-artifact-title
:hover
{
transform
:
translateY
(
10px
)
scale
(
1
);
transition
:
transform
300ms
;
}
.div-artifact-info
:hover
{
transform
:
translateY
(
10px
)
scale
(
1
);
transition
:
transform
300ms
;
}
.target-popper
{
display
:
none
;
max-width
:
300px
;
padding
:
1em
;
text-align
:
left
;
border-radius
:
10px
;
border
:
1px
solid
#ccc
;
background
:
#fff
;
z-index
:
2
;
top
:
-2.5%
!important
;
left
:
2%
!important
;
}
.target-popper.active
tr
td
:first-child
{
font-weight
:
bold
;
color
:
#17a2b8
!important
;
}
.target-popper.active
{
display
:
block
;
}
.sugar-show
{
-webkit-transition
:
opacity
1s
linear
;
-o-transition
:
opacity
1s
linear
;
transition
:
opacity
1s
linear
;}
.sugar-hidden
{
opacity
:
0
;
display
:
none
;}
.legend-label
{
font-size
:
14px
;
position
:
relative
;
top
:
95%
;
left
:
58%
;
}
.legend-curent
{
background-color
:
#006400
;
height
:
10px
;
width
:
30px
;
margin-left
:
2px
;
display
:
inline-block
;
position
:
relative
;
top
:
95%
;
left
:
58%
;
}
.legend-visited
{
background-color
:
#90EE90
;
height
:
10px
;
width
:
30px
;
margin-left
:
2px
;
display
:
inline-block
;
position
:
relative
;
top
:
95%
;
left
:
58%
;
}
\ No newline at end of file
drawArtifact.php
View file @
67ee206b
...
...
@@ -54,6 +54,20 @@
*/
// TODO here convert into drawArtifact function
require_once
(
"artifacts.php"
);
//Fonction récursive pour convertir un tableau d'artifact en ligne sugarfree
function
recursiveConvertSugarFree
(
array
$data
,
array
&
$convertedData
=
[]){
foreach
(
$data
as
$key
=>
$val
){
if
(
is_array
(
$val
)){
$convertedData
[
$key
]
=
[];
recursiveConvertSugarFree
(
$val
,
$convertedData
[
$key
]);
}
else
{
$convertedData
[
$key
]
=
sugarFree
(
$val
);
}
}
return
$convertedData
;
}
function
drawArtifact
(
$conn
,
$artifactid
){
global
$VIEW
;
...
...
@@ -64,29 +78,42 @@ function drawArtifact($conn,$artifactid){
//$jsonString=htmlentities(json_encode(load_artifact($artifact_file),JSON_PRETTY_PRINT));
//$jsonString=json_encode(load_artifact($artifact_file),JSON_PRETTY_PRINT);
$jsonString
=
json_encode
(
load_artifact
(
$artifact_file
));
$loadedArtifact
=
load_artifact
(
$artifact_file
);
$jsonString
=
json_encode
(
$loadedArtifact
);
//Convertir le contenu du json en code sugar free au chargement
$jsonStringSugarFree
=
json_encode
(
recursiveConvertSugarFree
(
$loadedArtifact
));
//$jsonString='{"author":"bob"}';
$VIEW
[
'MAIN'
]
.
=
<<<EOF
<div class="container">
<div class="row">
<div class="col bg-secondary text-white">
<div id="hw-artefact-info">placeholder
<div class="workflow-tittle">
<div class="row">
<div class="col bg-secondary text-white">
<div id="hw-artefact-info">placeholder
</div>
</div>
</div>
<
/
div>
<div class="
row
">
<div
class="col bg-secondary text-white">
<div id="hw-artefact-author">placeholder
<div
class="row"
>
<div class="
col bg-secondary text-white
">
<div
id="hw-artefact-author">placeholder
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-6">
<div id="cy"></div>
<div>
<label class="legend-label">Current node</label><div class="legend-curent"></div>
<label class="legend-label">Visited node</label><div class="legend-visited"></div>
</div>
</div>
<div class="col-6">
<div id="info">(move your mouse on nodes and arrows for infos)</div>
<div class="row">
<input type="checkbox" id="toggleId" checked data-toggle="toggle" data-on="Sugar" data-off="Sugar free" data-onstyle="success" data-offstyle="danger">
</div>
<div id="info" style="position: relative;top: 5px; left: 20px;">(move your mouse on nodes and arrows for infos)</div>
</div>
</div>
</div>
...
...
@@ -94,11 +121,13 @@ function drawArtifact($conn,$artifactid){
EOF;
$VIEW
[
'MAIN'
]
.
=
"var jsonString=`"
.
$jsonString
.
"`;"
;
$VIEW
[
'MAIN'
]
.
=
"var jsonStringSugarFree=`"
.
$jsonStringSugarFree
.
"`;"
;
$VIEW
[
'MAIN'
]
.
=
<<<'EOF'
var obj;
try {
obj = JSON.parse(jsonString);
objSugarFree = JSON.parse(jsonStringSugarFree);
} catch(e) {
console.log("error"+jsonString);
alert(e); // error in the above string (in this case, yes)!
...
...
@@ -130,6 +159,15 @@ var cy = cytoscape({
'color':"white"
}
},
{
selector: ':selected',
css: {
'background-color': '#17a2b8',
'line-color': '#17a2b8',
'target-arrow-color': '#17a2b8',
'source-arrow-color': '#17a2b8'
}
},
{
selector: 'node[id="node1"]',
style: {
...
...
@@ -141,7 +179,7 @@ var cy = cytoscape({
style: {
'curve-style':'straight',
'line-color': 'black',
'target-arrow-shape': '
triangl
e',
'target-arrow-shape': '
ve
e',
'target-arrow-fill':'filled',
'target-arrow-color':'black',
width:3
...
...
@@ -152,30 +190,37 @@ var cy = cytoscape({
});
for (var i in obj){
if (i!="author" && i!="doc"){
if (i!="author" && i!="doc"
&& i!="nodetip"
){
cy.add({
data: { id: i }
data: {
id: i,
nodetip: obj[i]["nodetip"]
}
});
console.log('node'+i);
//console.log('node'+i);
}
}
for (var i in obj){
if (i!="author" && i!="doc"){
if (i!="author" && i!="doc"
&& i!="nodetip"
){
for (var j in obj[i]){
console.log('edge' + i + '-' +j);
cy.add({
data: { id: i + '-' +j,
source: i,
target: j
}
});
if(j!="nodetip" ){
cy.add({
data: {
id: i + '-' +j,
source: i,
target: j,
guardtip: obj[i][j]["guardtip"],
actiontip: obj[i][j]["actiontip"]
}
});
}
};
}
}
cy.layout({
name: 'breadthfirst',
//roots: "node1",
...
...
@@ -188,46 +233,261 @@ document.getElementById("hw-artefact-info").innerHTML = obj['doc'];
document.getElementById("hw-artefact-author").innerHTML = 'Author: '+obj['author'];
// Popover sur edge et node ---------------------------------------------------------------
function bindPopper(target) {
let tooltipId = `popper-target-${target.id()}`;
let existingTarget = document.getElementById(tooltipId);
if (existingTarget && existingTarget.length !== 0) {
existingTarget.remove();
}
let popper = target.popper({
content: () => {
// create div container