Commit 92f2ab10 authored by Yannick Chudy's avatar Yannick Chudy

graph store, bug filter ALL, shortcuts

parent 242544d7
......@@ -7,7 +7,6 @@ import datetime
import logging
import codecs
import json
import pickle
from functools import wraps
from flask import Flask, Response, make_response, g, current_app, request
......@@ -17,6 +16,7 @@ from botapi import BotApiError, Botagraph, BotaIgraph, BotLoginError
from botapad import Botapad, BotapadError, BotapadParseError, BotapadURLError, BotapadCsvError
from cello.graphs import IN, OUT, ALL
from cello.graphs import pedigree
from cello.graphs.prox import ProxSubgraph
from cello.graphs.filter import RemoveNotConnected, GenericVertexFilter
......@@ -88,13 +88,17 @@ create table imports (
"""
import igraph
from igraph.utils import named_temporary_file
import pickle
import StringIO
from pdgapi.explor import export_graph, prepare_graph, igraph2dict, EdgeList
from pdglib.graphdb_ig import IGraphDB, engines
graphdb = IGraphDB({})
graphdb.open_database()
STORE = "../application/src/sample"
def get_db():
......@@ -236,43 +240,16 @@ def readme():
md = codecs.open('README.md', 'r', encoding='utf8').read()
return render_template('botapadapp.html', readme=md )
@app.route('/decalcograph/<string:gid>', methods=['GET'])
def decalcograph(gid):
padurl = "https://ethercalc.org/%s" % gid
graphurl = "/import/igraph.html?s=ethercalc&gid=%s&nofoot=1" % gid
return render_template('framagraph.html', graphurl=graphurl, padurl=padurl )
@app.route('/framagraph/<string:gid>', methods=['GET'])
def live(gid):
padurl = "https://annuel2.framapad.org/p/%s" % gid
graphurl = "/import/igraph.html?s=framapad&gid=%s&nofoot=1" % gid
return render_template('framagraph.html', graphurl=graphurl, padurl=padurl )
@app.route('/googledoc', methods=['GET'])
@app.route('/googledoc/<string:gid>', methods=['GET'])
def googledoc(gid=None):
if gid:
padurl = "https://docs.google.com/document/d/%s?embedded=true" % gid
else:
padurl = "https://docs.google.com/document/u/0/"
graphurl = "/import/igraph.html?s=google&gid=%s&nofoot=1" % gid
return render_template('framagraph.html', graphurl=graphurl, padurl=padurl )
def pad2pdg(gid, url):
description = "imported from %s" % url
bot = Botagraph(PADAGRAPH_HOST, KEY)
botapad = Botapad(bot, gid, description, delete=DELETE)
return botapad.parse(url, separator='auto', debug=app.config['DEBUG'])
def pad2igraph(gid, url):
def pad2igraph(gid, url, format="csv"):
if format == 'csv':
description = "imported from %s" % url
bot = BotaIgraph(directed=True)
botapad = Botapad(bot , gid, description, delete=DELETE)
......@@ -281,6 +258,42 @@ def pad2igraph(gid, url):
return graph
elif format in ('pickle', 'graphml', 'graphmlz', 'gml', 'pajek'):
if url[0:4] == 'http':
try :
url = convert_url(path)
if format in ( 'pickle', 'picklez') :
raise ValueError('no pickle from HTTP : %s ' % url )
log( " * Downloading %s %s\n" % (url, separator))
content = requests.get(url).text
except :
raise BotapadURLError("Can't download %s" % url, url)
elif DEBUG :
try :
content = open("%s/%s.%s" % (STORE, url, format) , 'rb').read()
except Exception as err :
raise BotapadURLError("Can't open file %s: %s" % (url, err.message ), url)
try :
with named_temporary_file(text=False) as tmpf:
outf = open(tmpf, "wt")
outf.write(content)
outf.close()
graph = igraph.read(tmpf, format=format)
return graph
except Exception as err :
raise
raise BotapadError('%s : cannot read %s file at %s : %s' % ( gid, format, url, err.message ))
raise BotapadError('%s : Unsuported format %s file at %s ' % ( gid, format, url ))
@app.route('/embed', methods=['GET'])
def embed():
......@@ -289,6 +302,14 @@ def embed():
return botimport('igraph', padurl, "graph", "embed")
FORMAT = [ (k, 'import' if v[0]!= None else "" ,'export' if v[1]!=None else "" ) for k,v in igraph.Graph._format_mapping.iteritems()]
FORMAT_IMPORT = ('graphml', 'graphmlz', 'csv')
FORMAT_EXPORT = ('graphml', 'graphmlz', 'picklez', 'pickle', 'csv', 'json')
@app.route('/import', methods=['GET'])
@app.route('/import/', methods=['GET'])
@app.route('/import/<string:repo>', methods=['GET', 'POST'])
......@@ -337,6 +358,7 @@ def botimport(repo, padurl, gid, content_type):
#args
args = request.args
color = "#" + args.get("color", "249999" )
reader = args.get("format", "csv" )
footer = not(args.get('nofoot', 0) == "1") # default true
......@@ -385,15 +407,20 @@ def botimport(repo, padurl, gid, content_type):
elif repo == "igraph":
if content_type == "embed":
complete = True
data = "%s/import/igraph.json?s=%s" % (ENGINES_HOST, padurl)
else :
graph = pad2igraph(gid, padurl)
graph = pad2igraph( gid, padurl, reader )
graph = prepare_graph(graph)
graph['meta']['date'] = datetime.datetime.now().strftime("%Y-%m-%d %Hh%M")
graph['meta']['owner'] = None
graph['meta']['pedigree'] = pedigree.compute(graph)
graphdb.graphs[gid] = graph
sync = "%s/graphs/g/%s" % (ENGINES_HOST, gid)
......@@ -418,6 +445,7 @@ def botimport(repo, padurl, gid, content_type):
data = export_graph(graph, id_attribute='uuid')
complete = True
if content_type == "json":
......@@ -485,7 +513,6 @@ def botimport(repo, padurl, gid, content_type):
footer=footer
)
import igraph
# === layout ===
......
This diff is collapsed.
......@@ -631,6 +631,7 @@ var GvizShortcuts = function(gviz){ return [
console.log("toggle image display", gviz.show_images)
}
],
"* Rendering ",
[
'r', "toggles autorotate", function(){
......@@ -710,8 +711,14 @@ function install_edit_shortcuts(context, graph, prefix){
}
}
],
];
bindAllKeyboardShortcuts(context, actions, prefix);
}
function install_navigation_shortcuts(context, graph, prefix){
var actions = [
[
'space', "Expands node relations",function(){
'enter', "Expands node relations",function(){
var vs = graph.vs.by_flag('selected');
if( vs.length == 1)
{
......@@ -720,7 +727,7 @@ function install_edit_shortcuts(context, graph, prefix){
}
}
],
[ 'o', "Explore", function(){
[ 'shift enter', "Explore", function(){
var vs = graph.vs.by_flag('selected');
if( vs.length == 1)
{
......@@ -730,7 +737,7 @@ function install_edit_shortcuts(context, graph, prefix){
}
],
[
'r', "Removes node from view", function(){
'backspace', "Removes node from view", function(){
var vs = graph.vs.by_flag('selected');
if( vs.length == 1)
{
......@@ -748,7 +755,7 @@ function install_edit_shortcuts(context, graph, prefix){
function install_gviz_shortcuts(gviz, prefix){
//- global no prefix
bindAllKeyboardShortcuts( gviz.$el, GvizShortcuts(gviz) , "");
bindAllKeyboardShortcuts( gviz.$el, GvizShortcuts(gviz) , prefix);
};
......@@ -1536,8 +1543,9 @@ App.Base = Backbone.View.extend({
/** === Keyboard shortcuts === */
install_shortcuts();
install_gviz_shortcuts(gviz, "!");
install_edit_shortcuts(this.$el, this.models.graph, ":");
install_gviz_shortcuts(gviz, "");
install_navigation_shortcuts(this.$el, this.models.graph, "");
install_edit_shortcuts(this.$el, this.models.graph, "");
gviz.animate();
},
......
This diff is collapsed.
This diff is collapsed.
......@@ -108,7 +108,7 @@
"textAlign": "left",
"textVerticalAlign" : 'center',
'textPaddingY' : -3,
'textPaddingY' : -4,
'textPaddingX' : 0.5,
} },
......
......@@ -9560,6 +9560,8 @@ require(['backbone', 'pdgconst'], function (Backbone, Const) {
} else if (action == 'expand') {
var params = { graph: this.model.graph.id, nodes: [this.model.id], weights: [] };
Backbone.trigger('engine:expand_prox', params);
} else if (action == 'remove') {
Backbone.trigger(Const.remove_node, this.model);
}
}
......@@ -9775,6 +9777,12 @@ require(['backbone', 'cello', 'gviz', 'materials', 'pdgconst'], function (Backbo
this._listener.stopListening();
if (!graph || !_.size(graph)) return;
this._listener.listenTo(this.graph.vs, 'remove', (function (model) {
if (_this.model == model) _this.model = null;
}).bind(this));
this._listener.listenTo(this.graph.es, 'remove', (function (model) {
if (_this.model == model) _this.model = null;
}).bind(this));
this._listener.listenTo(this.graph.vs, 'addflag:selected', (function (model) {
_this.model = model;
}).bind(this));
......@@ -10239,7 +10247,7 @@ require(['backbone', 'cello', 'gviz', 'materials', 'pdgconst'], function (Backbo
.ui.groupfilter.checkbox {
margin-top: 12px;
}
</style><template><template is="dom-if" if="{{asmenu}}"><div class="ui vertical menu"><template is="dom-if" if="{{ filter_visible('all') }}"> <div on-click="reset_filters" class="link item">All</div></template><template is="dom-if" if="[[ filter_visible('selected') ]]"> <div on-click="set_selected_label" class="item"><padagraph-vertex-card-xs model="[[selected_node]]"></padagraph-vertex-card-xs></div><div class="divider"></div></template><template is="dom-if" if="{{ filter_visible('label') }}"> <template is="dom-if" if="{{ filter_visible('headers') }}"> <h4 class="ui header">Label</h4></template><div class="ui form"><div style="margin: 0 1em 0.3em 0em;" class="field"><div class="ui small icon input"><i class="search icon"></i><input type="text" placeholder="Label filter" value="{{filter_label::input}}"></div></div><template is="dom-if" if="{{is_mode_node}}"> <div class="field"><div class="ui labelfilter checkbox"><input type="checkbox" on-click="click_filter_label_chk"><label>include neighbors</label></div></div></template></div><div class="divider"></div></template><template is="dom-if" if="{{ filter_visible('types') }}"> <template is="dom-if" if="{{ filter_visible('headers') }}"><h4 class="ui header">Types</h4></template><div class="ui form groups"><template is="dom-repeat" items="{{filter_groups}}" as="group"><div class="field"><div class="ui groupfilter checkbox"><input id="chkgroup{{group.label}}" on-click="set_group_filter" type="checkbox" checked="checked"><label for$="chkgroup{{group.label}}">{{group.label}} ({{group.count}}) </label></div></div><template is="dom-repeat" items="{{group.items}}" as="item"><div class="field"><div class="ui typefilter checkbox"><input id="type{{item.label}}" on-click="set_type_filter" type="checkbox" checked="checked"><label for$="type{{item.label}}">{{item.name}} ({{item.count}})</label></div></div></template></template></div><div class="divider"></div></template><template is="dom-if" if="{{ filter_visible('headers') }}"> <h4 class="ui header">Layout</h4></template><template is="dom-if" if="{{ filter_visible('layout') }}"> <div class="form"><div class="field"><div on-click="update_layout" class="ui primary compact button">update</div></div></div></template></div></template><template is="dom-if" if="{{!asmenu}}"> <div on-click="filter_count" class$="{{button_class('ui dropdown', asitem, aslabel)}}" class="ui dropdown"><template is="dom-if" if="{{is_mode_node}}"> <i class="ui circle thin icon"></i></template><template is="dom-if" if="{{is_mode_edge}}"> <i class="ui minus icon"></i></template><span>{{ filtered_count }} </span><div class="menu"><div on-click="set_type_filter" class="item">All</div><template is="dom-if" if="{{ selected_node }}"> <div on-click="set_selected_label" class="item"><padagraph-vertex-card-xs model="[[selected_node]]"></padagraph-vertex-card-xs></div></template><div class="divider"></div><h4 class="ui header">Label</h4><div class="ui form"><div style="margin: 0 1em 0.3em 0em;" class="field"><div class="ui small icon input"><i class="search icon"></i><input type="text" placeholder="Label filter" value="{{filter_label::input}}"></div></div><template is="dom-if" if="{{is_mode_node}}"> <div class="field"><div class="ui labelfilter checkbox"><input type="checkbox" on-click="click_filter_label_chk"><label>include neighbors</label></div></div></template></div><div class="divider"></div><h4 class="ui header">Types</h4><div class="ui form groups"><template is="dom-repeat" items="{{filter_groups}}" as="group"><div class="field"><div class="ui groupfilter checkbox"><input id="chkgroup{{group.label}}" on-click="set_group_filter" type="checkbox" checked="checked"><label for$="chkgroup{{group.label}}"><span class="name">{{group.label}}</span><span class="count">({{group.count}})</span></label></div></div><template is="dom-repeat" items="{{group.items}}" as="item"><div class="field"><div class="ui typefilter checkbox"><input id="type{{item.label}}" on-click="set_type_filter" type="checkbox" checked="checked"><label for$="type{{item.label}}"><span class="name">{{item.name}}</span><span class="count">({{item.count}})</span></label></div></div></template></template></div><div class="divider"></div><h4 class="ui header">Layout</h4><div class="form"><div class="field"><div on-click="update_layout" class="ui primary compact button">update</div></div></div></div></div></template></template><script>'use strict';
</style><template><template is="dom-if" if="{{asmenu}}"><div class="ui vertical menu"><template is="dom-if" if="{{ filter_visible('all') }}"> <div on-click="reset_filters" class="link item">All</div></template><template is="dom-if" if="[[ filter_visible('selected') ]]"> <div on-click="set_selected_label" class="item"><padagraph-vertex-card-xs model="[[selected_node]]"></padagraph-vertex-card-xs></div><div class="divider"></div></template><template is="dom-if" if="{{ filter_visible('label') }}"> <template is="dom-if" if="{{ filter_visible('headers') }}"> <h4 class="ui header">Label</h4></template><div class="ui form"><div style="margin: 0 1em 0.3em 0em;" class="field"><div class="ui small icon input"><i class="search icon"></i><input type="text" placeholder="Label filter" value="{{filter_label::input}}"></div></div><template is="dom-if" if="{{is_mode_node}}"> <div class="field"><div class="ui labelfilter checkbox"><input type="checkbox" on-click="click_filter_label_chk"><label>include neighbors</label></div></div></template></div><div class="divider"></div></template><template is="dom-if" if="{{ filter_visible('types') }}"> <template is="dom-if" if="{{ filter_visible('headers') }}"><h4 class="ui header">Types</h4></template><div class="ui form groups"><template is="dom-repeat" items="{{filter_groups}}" as="group"><div class="field"><div class="ui groupfilter checkbox"><input id="chkgroup{{group.label}}" on-click="set_group_filter" type="checkbox" checked="checked"><label for$="chkgroup{{group.label}}">{{group.label}} ({{group.count}}) </label></div></div><template is="dom-repeat" items="{{group.items}}" as="item"><div class="field"><div class="ui typefilter checkbox"><input id="type{{item.label}}" on-click="set_type_filter" type="checkbox" checked="checked"><label for$="type{{item.label}}">{{item.name}} ({{item.count}})</label></div></div></template></template></div><div class="divider"></div></template><template is="dom-if" if="{{ filter_visible('headers') }}"> <h4 class="ui header">Layout</h4></template><template is="dom-if" if="{{ filter_visible('layout') }}"> <div class="form"><div class="field"><div on-click="update_layout" class="ui primary compact button">update</div></div></div></template></div></template><template is="dom-if" if="{{!asmenu}}"> <div on-click="filter_count" class$="{{button_class('ui dropdown', asitem, aslabel)}}" class="ui dropdown"><template is="dom-if" if="{{is_mode_node}}"> <i class="ui circle thin icon"></i></template><template is="dom-if" if="{{is_mode_edge}}"> <i class="ui minus icon"></i></template><span>{{ filtered_count }} </span><div class="menu"><div on-click="reset_filters" class="item">All</div><template is="dom-if" if="{{ selected_node }}"> <div on-click="set_selected_label" class="item"><padagraph-vertex-card-xs model="[[selected_node]]"></padagraph-vertex-card-xs></div></template><div class="divider"></div><h4 class="ui header">Label</h4><div class="ui form"><div style="margin: 0 1em 0.3em 0em;" class="field"><div class="ui small icon input"><i class="search icon"></i><input type="text" placeholder="Label filter" value="{{filter_label::input}}"></div></div><template is="dom-if" if="{{is_mode_node}}"> <div class="field"><div class="ui labelfilter checkbox"><input type="checkbox" on-click="click_filter_label_chk"><label>include neighbors</label></div></div></template></div><div class="divider"></div><h4 class="ui header">Types</h4><div class="ui form groups"><template is="dom-repeat" items="{{filter_groups}}" as="group"><div class="field"><div class="ui groupfilter checkbox"><input id="chkgroup{{group.label}}" on-click="set_group_filter" type="checkbox" checked="checked"><label for$="chkgroup{{group.label}}"><span class="name">{{group.label}}</span><span class="count">({{group.count}})</span></label></div></div><template is="dom-repeat" items="{{group.items}}" as="item"><div class="field"><div class="ui typefilter checkbox"><input id="type{{item.label}}" on-click="set_type_filter" type="checkbox" checked="checked"><label for$="type{{item.label}}"><span class="name">{{item.name}}</span><span class="count">({{item.count}})</span></label></div></div></template></template></div><div class="divider"></div><h4 class="ui header">Layout</h4><div class="form"><div class="field"><div on-click="update_layout" class="ui primary compact button">update</div></div></div></div></div></template></template><script>'use strict';
require(['backbone', 'jquery', 'semantic'], function (Backbone, $, S) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment