diff --git a/hugvey/central_command.py b/hugvey/central_command.py index e1c8177..a21ebb7 100644 --- a/hugvey/central_command.py +++ b/hugvey/central_command.py @@ -66,7 +66,12 @@ class CentralCommand(object): 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 = {} for lang in self.config['languages']: @@ -75,7 +80,6 @@ class CentralCommand(object): with open(lang_filename, 'r') as fp: self.languages[lang['code']] = json.load(fp) - self.panopticon = Panopticon(self, self.config) def getHugveyStatus(self, 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['finished'] = hv.story.isFinished() 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 @@ -354,13 +358,15 @@ class HugveyState(object): if not self.story: self.logger.critical("No story to play message in") else: - msg = self.story.get(event['msg_id']) -# if not msg or isinstance(msg, hugvey.story.Message): -# self.logger.critical("Invalid ID to play: {}".format(event['msg_id'])) - self.restart() + #restart first so that story loads the new json + self.restart() + # wait a tat for the restart loops to complete await asyncio.sleep(.1) - self.story.setCurrentMessage(msg) -# self.resume() # don't reset a finished story + 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.eventQueue = None diff --git a/hugvey/panopticon.py b/hugvey/panopticon.py index 416fba3..1e8c0ef 100644 --- a/hugvey/panopticon.py +++ b/hugvey/panopticon.py @@ -158,6 +158,9 @@ def getUploadHandler(central_command): with open(langFile, 'w') as json_fp: logger.info(f'Save story to {langFile} {json_fp}') json.dump(storyData, json_fp) + + # Reload language files for new instances + central_command.loadLanguages() self.finish() return UploadHandler diff --git a/www/css/styles.css b/www/css/styles.css index 1aaa28e..f9a1feb 100644 --- a/www/css/styles.css +++ b/www/css/styles.css @@ -5,10 +5,10 @@ body { .btn, input[type="submit"] { display: inline-block; cursor: pointer; - background: #333; + background: #345; padding: 5px; color: white; - border-radius: 5px; + border-radius: 3px; margin-right: 5px; white-space: nowrap; border: none; } @@ -163,10 +163,12 @@ img.icon { background: lightgray; } #story #msg h1 { margin: 0; } - #story #msg .play { + #story #msg .msg__info .btn--delete { position: absolute; top: 15px; right: 10px; } + #story #msg .play { + text-align: center; } #story #msg .direction { position: relative; } #story #msg .direction h3 { @@ -175,10 +177,6 @@ img.icon { position: absolute; top: 5px; 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 .selectedMsg circle { stroke: lightgreen; @@ -188,8 +186,14 @@ img.icon { stroke: lightgreen; stroke-width: 5; stroke-dasharray: 10 3; } - #story .condition h4 { - text-align: center; } + #story .condition { + position: relative; } + #story .condition h4 { + text-align: center; } + #story .condition.condition--add h4 { + margin: 0; } + #story .condition.condition--add h4 + div { + margin-top: 10px; } #story .condition + .condition::before { content: "OR"; display: block; @@ -198,8 +202,8 @@ img.icon { margin-bottom: 15px; text-align: center; text-shadow: 2px 2px 2px lightgray,-2px 2px 2px lightgray,2px -2px 2px lightgray,-2px -2px 2px lightgray; } - #story .condition--add { - /* text-align: center; */ } + #story .condition + .condition .btn--delete { + margin-top: 20px; } .flag-icon { background-size: contain; diff --git a/www/js/hugvey_console.js b/www/js/hugvey_console.js index 4623650..9fdffca 100644 --- a/www/js/hugvey_console.js +++ b/www/js/hugvey_console.js @@ -274,23 +274,8 @@ class Graph { let msgEl = document.getElementById( 'msg' ); msgEl.innerHTML = ""; - if(panopticon.hugveys.selectedId) { - let playEl = crel( - '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); + if(msg == null){ + return; } @@ -321,6 +306,17 @@ class Graph { )); } 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( 'label', crel( 'span', 'Text' ), @@ -363,6 +359,31 @@ class Graph { 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'); // directionHEl.innerHTML = "Directions"; @@ -407,9 +428,13 @@ class Graph { crel('div', { 'class':'btn btn--delete', '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'] ) { @@ -424,7 +449,17 @@ class Graph { getEditConditionFormEl( condition, direction ) { 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' ); labelLabel.innerHTML = "Description"; @@ -547,14 +582,41 @@ class Graph { 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']; // TODO 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 ); + } 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._rmNode( id ); + this.updateMsg(); } getConditionEl( condition ) { @@ -582,6 +644,8 @@ class Graph { this.data.push( msg ); this.updateFromData(); this.build(); + + this.selectMsg(msg); return msg; } @@ -645,6 +709,7 @@ class Graph { rmDirection( dir ) { this._rmNode( dir ); + // todo, remove orphaned conditions } createMsg() { @@ -664,10 +729,12 @@ class Graph { let graph = this; let el = function( e ) { 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 ); let node = graph.getNodeById( id ); let path = field.split( '.' ); // use vars.test to set ['vars']['test'] = value + console.log(id, node); var res = node; for ( var i = 0; i < path.length; i++ ) { if ( i == ( path.length - 1 ) ) { diff --git a/www/scss/styles.scss b/www/scss/styles.scss index b5f7298..1ba13d4 100644 --- a/www/scss/styles.scss +++ b/www/scss/styles.scss @@ -9,10 +9,10 @@ body{ .btn, input[type="submit"]{ display:inline-block; cursor: pointer; - background: #333; + background: #345; padding: 5px; color: white; - border-radius: 5px; + border-radius: 3px; margin-right: 5px; white-space: nowrap; border: none; @@ -269,11 +269,19 @@ img.icon{ margin:0; } - .play { - position:absolute; - top: 15px; - right: 10px; - } + .msg__info { + .btn--delete { + position:absolute; + top: 15px; + right: 10px; + } + } + + .play{ +// background: #ccc; +// padding: 20px; + text-align: center; + } .direction{ position: relative; @@ -286,14 +294,6 @@ img.icon{ right: 0px; } - .condition--add{ - h4{ - margin: 0; - } - h4 +div { - margin-top: 10px; - } - } } } @@ -309,23 +309,39 @@ img.icon{ stroke-width: 5; stroke-dasharray: 10 3; } - - .condition h4{ - text-align: center; - } - .condition + .condition::before { - content: "OR"; - display: block; - border-bottom: solid 2px; - height: 10px; - margin-bottom: 15px; - text-align: center; - text-shadow: 2px 2px 2px lightgray,-2px 2px 2px lightgray,2px -2px 2px lightgray,-2px -2px 2px lightgray; - - } - .condition--add{ - /* text-align: center; */ + + .condition{ + position: relative; + h4{ + text-align: center; + } + + &.condition--add{ + h4{ + margin: 0; + } + h4 +div { + margin-top: 10px; + } + } + } + .condition + .condition { + + &::before{ + content: "OR"; + display: block; + border-bottom: solid 2px; + height: 10px; + margin-bottom: 15px; + text-align: center; + text-shadow: 2px 2px 2px lightgray,-2px 2px 2px lightgray,2px -2px 2px lightgray,-2px -2px 2px lightgray; + } + + .btn--delete{ + margin-top: 20px; + } } + }