new highlighting mode: viewers of states/actions
This commit is contained in:
parent
48f7de6220
commit
89809dc551
@ -42,7 +42,8 @@ module Export where
|
||||
"target" .= values ! "target",
|
||||
"actionData" .= object [
|
||||
"mode" .= values ! "mode",
|
||||
"actors" .= values ! "actors"]] : result
|
||||
"actors" .= values ! "actors",
|
||||
"viewers" .= values ! "viewers"]] : result
|
||||
|
||||
instance ToJSON GraphData where
|
||||
toJSON (GData (nd, ed)) = object ["states" .= toJSON nd, "actions" .= toJSON ed]
|
||||
|
||||
@ -87,7 +87,7 @@ module Workflow where
|
||||
name :: Maybe Label,
|
||||
actors :: Maybe [Map String Value],
|
||||
viewActor :: Maybe Value,
|
||||
viewers :: Maybe Value,
|
||||
viewers :: Maybe [Map String Value],
|
||||
messages :: Maybe Value,
|
||||
form :: Maybe Value
|
||||
} deriving (Show, Generic)
|
||||
@ -155,7 +155,8 @@ module Workflow where
|
||||
("source", Single source),
|
||||
("target", Single targetID),
|
||||
("mode", Single mode),
|
||||
("actors", List $ Prelude.map Dict actors)] where
|
||||
("actors", List $ Prelude.map Dict actors),
|
||||
("viewers", List $ Prelude.map Dict viewers)] where
|
||||
name = if isNothing a.name
|
||||
then ident
|
||||
else case (fromJust a.name).fallback of
|
||||
@ -164,5 +165,6 @@ module Workflow where
|
||||
source = fromMaybe initID a.source
|
||||
mode = fromMaybe "" a.mode
|
||||
actors = fromMaybe [] a.actors
|
||||
viewers = fromMaybe [] a.viewers
|
||||
|
||||
---------------------------------------
|
||||
28
editor.css
28
editor.css
@ -4,4 +4,30 @@
|
||||
|
||||
#editor {
|
||||
border: 10px solid red;
|
||||
} */
|
||||
} */
|
||||
|
||||
body {
|
||||
margin: 0 0 0 0;
|
||||
}
|
||||
|
||||
#settings {
|
||||
line-height: 2;
|
||||
box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.16), 0 2px 10px 0 rgba(0, 0, 0, 0.12);
|
||||
top: 0px;
|
||||
width: 100%;
|
||||
position: fixed;
|
||||
padding: 8 8 8 8;
|
||||
background-color: rgb(230, 230, 230);
|
||||
z-index: 2;
|
||||
float: left;
|
||||
overflow: auto;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#settings div {
|
||||
width: fit-content;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
float: left;
|
||||
margin-right: 20;
|
||||
}
|
||||
15
editor.html
15
editor.html
@ -8,17 +8,22 @@
|
||||
<!--<script src="../../dist/force-graph.js"></script>-->
|
||||
</head>
|
||||
|
||||
<body style="margin: 0 0 0 0;">
|
||||
<body>
|
||||
<div id="editor">
|
||||
<!-- <br/>
|
||||
<div style="text-align: center; color: silver">
|
||||
<b>New node:</b> click on the canvas, <b>New link:</b> drag one node close enough to another one,
|
||||
<b>Rename</b> node or link by clicking on it, <b>Remove</b> node or link by right-clicking on it
|
||||
</div> -->
|
||||
<div id="settings" style="line-height: 2; box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.16), 0 2px 10px 0 rgba(0, 0, 0, 0.12); top: 0px;
|
||||
width: 100%; position: fixed; padding: 8 8 8 8; background-color: rgb(230, 230, 230); z-index: 2;">
|
||||
<label for="actor">Highlight actor: </label>
|
||||
<select name="actor" id="actor" onchange="selectActor();"></select>
|
||||
<div id="settings">
|
||||
<div>
|
||||
<label for="actor">Highlight actor: </label>
|
||||
<select name="actor" id="actor" onchange="selectActor();"></select>
|
||||
</div>
|
||||
<div>
|
||||
<label for="viewer">Highlight viewer: </label>
|
||||
<select name="viewer" id="viewer" onchange="selectViewer();"></select>
|
||||
</div>
|
||||
</div>
|
||||
<div id="graph"></div>
|
||||
</div>
|
||||
|
||||
119
editor.js
119
editor.js
@ -11,49 +11,122 @@ var workflow = {}
|
||||
var stateIdCounter = workflow.states ? workflow.states.length : 0;
|
||||
var actionIdCounter = workflow.states ? workflow.actions.length : 0;
|
||||
|
||||
//Persons & roles of the workflow
|
||||
//Actors of the workflow
|
||||
var actors = [];
|
||||
workflow.actions.forEach(act => act.actionData.actors.forEach(a => {
|
||||
var includes = false;
|
||||
actors.forEach(actor => includes = includes || equalRoles(a, actor));
|
||||
(!includes) && actors.push(a);
|
||||
(!act.actionData.actorNames) && (act.actionData.actorNames = []);
|
||||
act.actionData.actorNames.push(getActorName(a));
|
||||
act.actionData.actorNames.push(getRoleName(a));
|
||||
}));
|
||||
// console.log(actors);
|
||||
// workflow.actions.forEach(a => console.log(a.actionData.actorNames));
|
||||
|
||||
function getActorName(actor) {
|
||||
if (actor.tag == 'payload-reference') {
|
||||
return actor['payload-label'];
|
||||
} else if (actor.authorized) {
|
||||
return actor.authorized['dnf-terms'][0][0].var + ' (auth)';
|
||||
function getRoleName(role) {
|
||||
if (typeof role == 'string') {
|
||||
return role;
|
||||
} else if (role.tag == 'payload-reference') {
|
||||
return role['payload-label'];
|
||||
} else if (role.authorized) {
|
||||
return role.authorized['dnf-terms'][0][0].var + ' (auth)';
|
||||
} else {
|
||||
return actor.user;
|
||||
}
|
||||
|
||||
return role.user || JSON.stringify(role);
|
||||
}
|
||||
}
|
||||
|
||||
const NO_ACTOR = 'None';
|
||||
|
||||
//Prepare actor highlighting
|
||||
const selectedActor = document.getElementById('actor');
|
||||
var allActors = document.createElement('option');
|
||||
allActors.text = 'All Actors';
|
||||
allActors.text = NO_ACTOR;
|
||||
selectedActor.add(allActors);
|
||||
actors.forEach(actor => {
|
||||
var option = document.createElement('option');
|
||||
option.text = getActorName(actor);
|
||||
option.text = getRoleName(actor);
|
||||
selectedActor.add(option);
|
||||
});
|
||||
|
||||
|
||||
//Viewers of the workflow
|
||||
var viewers = [];
|
||||
//Actions/States with no explicit viewers
|
||||
var viewableByAll = []
|
||||
//Possible initiators
|
||||
var initiators = []
|
||||
//Implicit state from which initial actions can be selected
|
||||
var initState = null;
|
||||
//Identify all viewers of every action
|
||||
workflow.actions.forEach(act => {
|
||||
if (act.actionData.viewers.length === 0) {
|
||||
viewableByAll.push(act.actionData);
|
||||
} else {
|
||||
act.actionData.viewers.forEach(v => {
|
||||
var includes = false;
|
||||
viewers.forEach(viewer => includes = includes || equalRoles(v, viewer));
|
||||
(!includes) && viewers.push(v);
|
||||
(!act.actionData.viewerNames) && (act.actionData.viewerNames = []);
|
||||
act.actionData.viewerNames.push(getRoleName(v));
|
||||
})
|
||||
}
|
||||
if (act.actionData.mode === 'initial') {
|
||||
act.actionData.actorNames.forEach(an => !initiators.includes(an) && initiators.push(an));
|
||||
}
|
||||
});
|
||||
//Identify all viewers of every state
|
||||
workflow.states.forEach(st => {
|
||||
if (st.name === '@@INIT') {
|
||||
initState = st;
|
||||
} else if (st.stateData.viewers.length === 0) {
|
||||
viewableByAll.push(st.stateData);
|
||||
} else {
|
||||
st.stateData.viewers.forEach(v => {
|
||||
var includes = false;
|
||||
viewers.forEach(viewer => includes = includes || equalRoles(v, viewer));
|
||||
(!includes) && viewers.push(v);
|
||||
(!st.stateData.viewerNames) && (st.stateData.viewerNames = []);
|
||||
st.stateData.viewerNames.push(getRoleName(v));
|
||||
})
|
||||
}
|
||||
});
|
||||
|
||||
initState.stateData.viewerNames = initiators;
|
||||
|
||||
const ALL_VIEW = "All Roles";
|
||||
if (viewableByAll.length > 0) {
|
||||
viewers.push(ALL_VIEW);
|
||||
var viewerNames = []
|
||||
viewers.forEach(viewer => viewerNames.push(getRoleName(viewer)));
|
||||
viewableByAll.forEach(data => {
|
||||
data.viewerNames = viewerNames;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
const NO_VIEWER = NO_ACTOR;
|
||||
|
||||
//Prepare viewer highlighting
|
||||
const selectedViewer = document.getElementById('viewer');
|
||||
var allViewers = document.createElement('option');
|
||||
allViewers.text = NO_VIEWER;
|
||||
selectedViewer.add(allViewers);
|
||||
viewers.forEach(viewer => {
|
||||
var option = document.createElement('option');
|
||||
option.text = getRoleName(viewer);
|
||||
selectedViewer.add(option);
|
||||
});
|
||||
|
||||
|
||||
//source & target nodes of all currently highlighted actions
|
||||
var highlightedSources = [];
|
||||
var highlightedTargets = [];
|
||||
|
||||
function selectActor() {
|
||||
console.log(selectedActor.value);
|
||||
// console.log(selectedActor.value);
|
||||
highlightedSources = [];
|
||||
highlightedTargets = [];
|
||||
selectedViewer.value = NO_VIEWER;
|
||||
workflow.actions.forEach(act => {
|
||||
if (act.actionData.mode != 'automatic' && act.actionData.actorNames.includes(selectedActor.value)) {
|
||||
highlightedSources.push(act.source.id);
|
||||
@ -62,6 +135,17 @@ function selectActor() {
|
||||
});
|
||||
}
|
||||
|
||||
function selectViewer() {
|
||||
highlightedSources = [];
|
||||
highlightedTargets = [];
|
||||
selectedActor.value = NO_ACTOR;
|
||||
workflow.states.forEach(st => {
|
||||
if (st.stateData.viewerNames.includes(selectedViewer.value)) {
|
||||
highlightedSources.push(st.id);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
var selfLoops = {}; // All edges whose targets equal their sources.
|
||||
var overlappingEdges = {}; // All edges whose target and source are connected by further.
|
||||
@ -221,7 +305,8 @@ function removeState(state) {
|
||||
* @returns The colour the given node should have.
|
||||
*/
|
||||
function getNodeColour(node) {
|
||||
var standard = selectedActor.value === 'All Actors' || highlightedSources.includes(node.id) || highlightedTargets.includes(node.id)
|
||||
var standard = (selectedActor.value === NO_ACTOR && selectedViewer.value === NO_VIEWER)
|
||||
|| highlightedSources.includes(node.id) || highlightedTargets.includes(node.id)
|
||||
var alpha = standard ? 'ff' : '55';
|
||||
if (node.stateData && node.stateData.final !== 'False' && node.stateData.final !== '') {
|
||||
if (node.stateData.final === 'True' || node.stateData.final === 'ok') {
|
||||
@ -239,13 +324,15 @@ function getNodeColour(node) {
|
||||
}
|
||||
|
||||
function isHighlightedEdge(edge) {
|
||||
return (edge.actionData.mode != 'automatic' && edge.actionData.actorNames.includes(selectedActor.value)) || (edge.actionData.mode === 'automatic' && highlightedTargets.includes(edge.source.id));
|
||||
var data = edge.actionData
|
||||
var selectedRole = data.mode != 'automatic' && (data.actorNames.includes(selectedActor.value) || data.viewerNames.includes(selectedViewer.value))
|
||||
return selectedRole || (data.mode === 'automatic' && highlightedTargets.includes(edge.source.id));
|
||||
}
|
||||
|
||||
function getEdgeColour(edge) {
|
||||
if (isHighlightedEdge(edge)) {
|
||||
return selection === edge ? edgeColourHighlightSelected : edgeColourHighlightDefault;
|
||||
} else if (selectedActor.value !== 'All Actors') {
|
||||
} else if (selectedActor.value !== NO_ACTOR) {
|
||||
return selection === edge ? edgeColourSubtleSelected : edgeColourSubtleDefault;
|
||||
} else {
|
||||
return selection === edge ? edgeColourSelected : edgeColourDefault;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user