Remove nodes/directions/conditions and updating language and play from position
This commit is contained in:
parent
3e06356edc
commit
e31918991c
5 changed files with 172 additions and 76 deletions
|
@ -66,7 +66,12 @@ class CentralCommand(object):
|
||||||
|
|
||||||
self.hugvey_ids = [i + 1 for i in range(self.config['hugveys'])]
|
self.hugvey_ids = [i + 1 for i in range(self.config['hugveys'])]
|
||||||
|
|
||||||
# load languages:
|
self.loadLanguages()
|
||||||
|
|
||||||
|
self.panopticon = Panopticon(self, self.config)
|
||||||
|
|
||||||
|
def loadLanguages(self):
|
||||||
|
logger.debug('load language files')
|
||||||
self.languages = {}
|
self.languages = {}
|
||||||
|
|
||||||
for lang in self.config['languages']:
|
for lang in self.config['languages']:
|
||||||
|
@ -75,7 +80,6 @@ class CentralCommand(object):
|
||||||
with open(lang_filename, 'r') as fp:
|
with open(lang_filename, 'r') as fp:
|
||||||
self.languages[lang['code']] = json.load(fp)
|
self.languages[lang['code']] = json.load(fp)
|
||||||
|
|
||||||
self.panopticon = Panopticon(self, self.config)
|
|
||||||
|
|
||||||
def getHugveyStatus(self, hv_id):
|
def getHugveyStatus(self, hv_id):
|
||||||
status = {'id': hv_id}
|
status = {'id': hv_id}
|
||||||
|
@ -93,7 +97,7 @@ class CentralCommand(object):
|
||||||
status['msg'] = hv.story.currentMessage.id if hv.story.currentMessage else None
|
status['msg'] = hv.story.currentMessage.id if hv.story.currentMessage else None
|
||||||
status['finished'] = hv.story.isFinished()
|
status['finished'] = hv.story.isFinished()
|
||||||
status['history'] = hv.story.getLogSummary()
|
status['history'] = hv.story.getLogSummary()
|
||||||
status['counts'] = {t: len(a) for t, a in status['history'].items() }
|
status['counts'] = {t: len(a) for t, a in status['history'].items() if t != 'directions' }
|
||||||
|
|
||||||
return status
|
return status
|
||||||
|
|
||||||
|
@ -354,13 +358,15 @@ class HugveyState(object):
|
||||||
if not self.story:
|
if not self.story:
|
||||||
self.logger.critical("No story to play message in")
|
self.logger.critical("No story to play message in")
|
||||||
else:
|
else:
|
||||||
msg = self.story.get(event['msg_id'])
|
#restart first so that story loads the new json
|
||||||
# if not msg or isinstance(msg, hugvey.story.Message):
|
|
||||||
# self.logger.critical("Invalid ID to play: {}".format(event['msg_id']))
|
|
||||||
self.restart()
|
self.restart()
|
||||||
|
# wait a tat for the restart loops to complete
|
||||||
await asyncio.sleep(.1)
|
await asyncio.sleep(.1)
|
||||||
|
msg = self.story.get(event['msg_id'])
|
||||||
|
if not msg:
|
||||||
|
self.logger.critical("Invalid ID to play: {}".format(event['msg_id']))
|
||||||
|
else:
|
||||||
self.story.setCurrentMessage(msg)
|
self.story.setCurrentMessage(msg)
|
||||||
# self.resume() # don't reset a finished story
|
|
||||||
|
|
||||||
self.eventQueue = None
|
self.eventQueue = None
|
||||||
|
|
||||||
|
|
|
@ -158,6 +158,9 @@ def getUploadHandler(central_command):
|
||||||
with open(langFile, 'w') as json_fp:
|
with open(langFile, 'w') as json_fp:
|
||||||
logger.info(f'Save story to {langFile} {json_fp}')
|
logger.info(f'Save story to {langFile} {json_fp}')
|
||||||
json.dump(storyData, json_fp)
|
json.dump(storyData, json_fp)
|
||||||
|
|
||||||
|
# Reload language files for new instances
|
||||||
|
central_command.loadLanguages()
|
||||||
self.finish()
|
self.finish()
|
||||||
|
|
||||||
return UploadHandler
|
return UploadHandler
|
||||||
|
|
|
@ -5,10 +5,10 @@ body {
|
||||||
.btn, input[type="submit"] {
|
.btn, input[type="submit"] {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
background: #333;
|
background: #345;
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
color: white;
|
color: white;
|
||||||
border-radius: 5px;
|
border-radius: 3px;
|
||||||
margin-right: 5px;
|
margin-right: 5px;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
border: none; }
|
border: none; }
|
||||||
|
@ -163,10 +163,12 @@ img.icon {
|
||||||
background: lightgray; }
|
background: lightgray; }
|
||||||
#story #msg h1 {
|
#story #msg h1 {
|
||||||
margin: 0; }
|
margin: 0; }
|
||||||
#story #msg .play {
|
#story #msg .msg__info .btn--delete {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 15px;
|
top: 15px;
|
||||||
right: 10px; }
|
right: 10px; }
|
||||||
|
#story #msg .play {
|
||||||
|
text-align: center; }
|
||||||
#story #msg .direction {
|
#story #msg .direction {
|
||||||
position: relative; }
|
position: relative; }
|
||||||
#story #msg .direction h3 {
|
#story #msg .direction h3 {
|
||||||
|
@ -175,10 +177,6 @@ img.icon {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 5px;
|
top: 5px;
|
||||||
right: 0px; }
|
right: 0px; }
|
||||||
#story #msg .direction .condition--add h4 {
|
|
||||||
margin: 0; }
|
|
||||||
#story #msg .direction .condition--add h4 + div {
|
|
||||||
margin-top: 10px; }
|
|
||||||
#story #nodes g:hover circle,
|
#story #nodes g:hover circle,
|
||||||
#story .selectedMsg circle {
|
#story .selectedMsg circle {
|
||||||
stroke: lightgreen;
|
stroke: lightgreen;
|
||||||
|
@ -188,8 +186,14 @@ img.icon {
|
||||||
stroke: lightgreen;
|
stroke: lightgreen;
|
||||||
stroke-width: 5;
|
stroke-width: 5;
|
||||||
stroke-dasharray: 10 3; }
|
stroke-dasharray: 10 3; }
|
||||||
|
#story .condition {
|
||||||
|
position: relative; }
|
||||||
#story .condition h4 {
|
#story .condition h4 {
|
||||||
text-align: center; }
|
text-align: center; }
|
||||||
|
#story .condition.condition--add h4 {
|
||||||
|
margin: 0; }
|
||||||
|
#story .condition.condition--add h4 + div {
|
||||||
|
margin-top: 10px; }
|
||||||
#story .condition + .condition::before {
|
#story .condition + .condition::before {
|
||||||
content: "OR";
|
content: "OR";
|
||||||
display: block;
|
display: block;
|
||||||
|
@ -198,8 +202,8 @@ img.icon {
|
||||||
margin-bottom: 15px;
|
margin-bottom: 15px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
text-shadow: 2px 2px 2px lightgray,-2px 2px 2px lightgray,2px -2px 2px lightgray,-2px -2px 2px lightgray; }
|
text-shadow: 2px 2px 2px lightgray,-2px 2px 2px lightgray,2px -2px 2px lightgray,-2px -2px 2px lightgray; }
|
||||||
#story .condition--add {
|
#story .condition + .condition .btn--delete {
|
||||||
/* text-align: center; */ }
|
margin-top: 20px; }
|
||||||
|
|
||||||
.flag-icon {
|
.flag-icon {
|
||||||
background-size: contain;
|
background-size: contain;
|
||||||
|
|
|
@ -274,23 +274,8 @@ class Graph {
|
||||||
let msgEl = document.getElementById( 'msg' );
|
let msgEl = document.getElementById( 'msg' );
|
||||||
msgEl.innerHTML = "";
|
msgEl.innerHTML = "";
|
||||||
|
|
||||||
if(panopticon.hugveys.selectedId) {
|
if(msg == null){
|
||||||
let playEl = crel(
|
return;
|
||||||
'div',
|
|
||||||
{'class': 'play'},
|
|
||||||
crel(
|
|
||||||
'div', {
|
|
||||||
'class': 'btn btn--play',
|
|
||||||
'on': {
|
|
||||||
'click': function (e) {
|
|
||||||
panopticon.playFromSelected(msg['@id']);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"Save & play on #" + panopticon.hugveys.selectedId
|
|
||||||
)
|
|
||||||
);
|
|
||||||
msgEl.appendChild(playEl);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -321,6 +306,17 @@ class Graph {
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
let msgInfoEl = crel( 'div', { 'class': 'msg__info' },
|
let msgInfoEl = crel( 'div', { 'class': 'msg__info' },
|
||||||
|
crel('div', {
|
||||||
|
'class':'btn btn--delete',
|
||||||
|
'on': {
|
||||||
|
'click': function(e) {
|
||||||
|
if(confirm(`Are you sure you want to remove message ${msg['@id']}`)) {
|
||||||
|
panopticon.graph.rmMsg(msg);
|
||||||
|
panopticon.graph.showMsg(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, 'delete'),
|
||||||
crel( 'h1', { 'class': 'msg__id' }, msg['@id'] ),
|
crel( 'h1', { 'class': 'msg__id' }, msg['@id'] ),
|
||||||
crel( 'label',
|
crel( 'label',
|
||||||
crel( 'span', 'Text' ),
|
crel( 'span', 'Text' ),
|
||||||
|
@ -363,6 +359,31 @@ class Graph {
|
||||||
msgEl.appendChild( msgInfoEl );
|
msgEl.appendChild( msgInfoEl );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if(panopticon.hugveys.selectedId) {
|
||||||
|
let playEl = crel(
|
||||||
|
'div',
|
||||||
|
{'class': 'play'},
|
||||||
|
crel(
|
||||||
|
'div', {
|
||||||
|
'class': 'btn btn--play',
|
||||||
|
'on': {
|
||||||
|
'click': function (e) {
|
||||||
|
console.log('go save');
|
||||||
|
panopticon.graph.saveJson(null, null, function(){
|
||||||
|
console.log('saved, now play');
|
||||||
|
panopticon.playFromSelected(msg['@id']);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Save & play on #" + panopticon.hugveys.selectedId
|
||||||
|
)
|
||||||
|
);
|
||||||
|
msgEl.appendChild(playEl);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// let directionHEl = document.createElement('h2');
|
// let directionHEl = document.createElement('h2');
|
||||||
// directionHEl.innerHTML = "Directions";
|
// directionHEl.innerHTML = "Directions";
|
||||||
|
|
||||||
|
@ -407,9 +428,13 @@ class Graph {
|
||||||
crel('div', {
|
crel('div', {
|
||||||
'class':'btn btn--delete',
|
'class':'btn btn--delete',
|
||||||
'on': {
|
'on': {
|
||||||
'click': ( e ) => g.rmDirection( direction )
|
'click': ( e ) => {
|
||||||
|
if(confirm("Do you want to remove this direction and its conditions?")) {
|
||||||
|
g.rmDirection( direction );
|
||||||
}
|
}
|
||||||
}, 'delete')
|
}
|
||||||
|
}
|
||||||
|
}, 'disconnect')
|
||||||
);
|
);
|
||||||
|
|
||||||
for ( let conditionId of direction['conditions'] ) {
|
for ( let conditionId of direction['conditions'] ) {
|
||||||
|
@ -424,7 +449,17 @@ class Graph {
|
||||||
|
|
||||||
getEditConditionFormEl( condition, direction ) {
|
getEditConditionFormEl( condition, direction ) {
|
||||||
let conditionEl = crel( 'div', { 'class': 'condition condition--edit' },
|
let conditionEl = crel( 'div', { 'class': 'condition condition--edit' },
|
||||||
crel( 'h4', { 'title': condition['@id'] }, condition['type'] )
|
crel( 'h4', { 'title': condition['@id'] }, condition['type'] ),
|
||||||
|
crel('div', {
|
||||||
|
'class':'btn btn--delete',
|
||||||
|
'on': {
|
||||||
|
'click': ( e ) => {
|
||||||
|
if(confirm("Do you want to remove this condition?")) {
|
||||||
|
panopticon.graph.rmCondition( condition, direction );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, 'delete')
|
||||||
)
|
)
|
||||||
let labelLabel = document.createElement( 'label' );
|
let labelLabel = document.createElement( 'label' );
|
||||||
labelLabel.innerHTML = "Description";
|
labelLabel.innerHTML = "Description";
|
||||||
|
@ -548,13 +583,40 @@ class Graph {
|
||||||
return addConditionEl;
|
return addConditionEl;
|
||||||
}
|
}
|
||||||
|
|
||||||
rmConditionFromDirection( condition, direction ) {
|
/**
|
||||||
|
* remove condition from the graph or merely from the given direction
|
||||||
|
* @param {any} condition The condition to remove
|
||||||
|
* @param {any} direction if given, only remove from this direction
|
||||||
|
*/
|
||||||
|
rmCondition( condition, direction ) {
|
||||||
let id = condition['@id'];
|
let id = condition['@id'];
|
||||||
// TODO
|
// TODO
|
||||||
if ( typeof direction != 'undefined' ) {
|
if ( typeof direction != 'undefined' ) {
|
||||||
|
let pos = direction['conditions'].indexOf(id);
|
||||||
|
if(pos > -1) {
|
||||||
|
direction['conditions'].splice(pos, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(let dir of this.directions) {
|
||||||
|
if(dir['conditions'].indexOf(id) > 0) {
|
||||||
|
console.log("Condition still in use");
|
||||||
|
this.updateFromData();
|
||||||
|
this.build();
|
||||||
|
this.updateMsg();
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
this._rmNode( id );
|
this._rmNode( id );
|
||||||
|
} else {
|
||||||
|
for(let dir of this.directions) {
|
||||||
|
let pos = dir['conditions'].indexOf(id);
|
||||||
|
if(pos > -1) {
|
||||||
|
dir['conditions'].splice(pos, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this._rmNode( id );
|
||||||
|
}
|
||||||
|
this.updateMsg();
|
||||||
}
|
}
|
||||||
|
|
||||||
getConditionEl( condition ) {
|
getConditionEl( condition ) {
|
||||||
|
@ -582,6 +644,8 @@ class Graph {
|
||||||
this.data.push( msg );
|
this.data.push( msg );
|
||||||
this.updateFromData();
|
this.updateFromData();
|
||||||
this.build();
|
this.build();
|
||||||
|
|
||||||
|
this.selectMsg(msg);
|
||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -645,6 +709,7 @@ class Graph {
|
||||||
|
|
||||||
rmDirection( dir ) {
|
rmDirection( dir ) {
|
||||||
this._rmNode( dir );
|
this._rmNode( dir );
|
||||||
|
// todo, remove orphaned conditions
|
||||||
}
|
}
|
||||||
|
|
||||||
createMsg() {
|
createMsg() {
|
||||||
|
@ -664,10 +729,12 @@ class Graph {
|
||||||
let graph = this;
|
let graph = this;
|
||||||
let el = function( e ) {
|
let el = function( e ) {
|
||||||
let parts = e.srcElement.name.split( '-' );
|
let parts = e.srcElement.name.split( '-' );
|
||||||
let id = parts[0], field = parts[1];
|
let field = parts.pop();
|
||||||
|
let id = parts.join('-');
|
||||||
console.log( this, graph );
|
console.log( this, graph );
|
||||||
let node = graph.getNodeById( id );
|
let node = graph.getNodeById( id );
|
||||||
let path = field.split( '.' ); // use vars.test to set ['vars']['test'] = value
|
let path = field.split( '.' ); // use vars.test to set ['vars']['test'] = value
|
||||||
|
console.log(id, node);
|
||||||
var res = node;
|
var res = node;
|
||||||
for ( var i = 0; i < path.length; i++ ) {
|
for ( var i = 0; i < path.length; i++ ) {
|
||||||
if ( i == ( path.length - 1 ) ) {
|
if ( i == ( path.length - 1 ) ) {
|
||||||
|
|
|
@ -9,10 +9,10 @@ body{
|
||||||
.btn, input[type="submit"]{
|
.btn, input[type="submit"]{
|
||||||
display:inline-block;
|
display:inline-block;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
background: #333;
|
background: #345;
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
color: white;
|
color: white;
|
||||||
border-radius: 5px;
|
border-radius: 3px;
|
||||||
margin-right: 5px;
|
margin-right: 5px;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
border: none;
|
border: none;
|
||||||
|
@ -269,11 +269,19 @@ img.icon{
|
||||||
margin:0;
|
margin:0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.play {
|
.msg__info {
|
||||||
|
.btn--delete {
|
||||||
position:absolute;
|
position:absolute;
|
||||||
top: 15px;
|
top: 15px;
|
||||||
right: 10px;
|
right: 10px;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.play{
|
||||||
|
// background: #ccc;
|
||||||
|
// padding: 20px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
.direction{
|
.direction{
|
||||||
position: relative;
|
position: relative;
|
||||||
|
@ -286,14 +294,6 @@ img.icon{
|
||||||
right: 0px;
|
right: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.condition--add{
|
|
||||||
h4{
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
h4 +div {
|
|
||||||
margin-top: 10px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -310,10 +310,24 @@ img.icon{
|
||||||
stroke-dasharray: 10 3;
|
stroke-dasharray: 10 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
.condition h4{
|
.condition{
|
||||||
|
position: relative;
|
||||||
|
h4{
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
.condition + .condition::before {
|
|
||||||
|
&.condition--add{
|
||||||
|
h4{
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
h4 +div {
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.condition + .condition {
|
||||||
|
|
||||||
|
&::before{
|
||||||
content: "OR";
|
content: "OR";
|
||||||
display: block;
|
display: block;
|
||||||
border-bottom: solid 2px;
|
border-bottom: solid 2px;
|
||||||
|
@ -321,11 +335,13 @@ img.icon{
|
||||||
margin-bottom: 15px;
|
margin-bottom: 15px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
text-shadow: 2px 2px 2px lightgray,-2px 2px 2px lightgray,2px -2px 2px lightgray,-2px -2px 2px lightgray;
|
text-shadow: 2px 2px 2px lightgray,-2px 2px 2px lightgray,2px -2px 2px lightgray,-2px -2px 2px lightgray;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn--delete{
|
||||||
|
margin-top: 20px;
|
||||||
}
|
}
|
||||||
.condition--add{
|
|
||||||
/* text-align: center; */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue