Commit 539f7c8f authored by Thibaut Frain's avatar Thibaut Frain Committed by Jérome Perrin

Added save button to allow saving graph with jio

parent 2e471357
...@@ -7,6 +7,8 @@ ...@@ -7,6 +7,8 @@
<script src="../<%= copy.rsvp.relative_dest %>" type="text/javascript"></script> <script src="../<%= copy.rsvp.relative_dest %>" type="text/javascript"></script>
<script src="../<%= copy.renderjs.relative_dest %>" type="text/javascript"></script> <script src="../<%= copy.renderjs.relative_dest %>" type="text/javascript"></script>
<script src="mixin_promise.js" type="text/javascript"></script>
<script src="Input_viewProductionLine.js" type="text/javascript"></script> <script src="Input_viewProductionLine.js" type="text/javascript"></script>
</head> </head>
<body> <body>
...@@ -14,5 +16,9 @@ ...@@ -14,5 +16,9 @@
data-gadget-scope="productionline_toolbox"></div> data-gadget-scope="productionline_toolbox"></div>
<div data-gadget-url="../jsplumb/index.html" <div data-gadget-url="../jsplumb/index.html"
data-gadget-scope="productionline_graph"></div> data-gadget-scope="productionline_graph"></div>
<form class="save_form">
<button type="submit" class="ui-btn ui-btn-b ui-btn-inline
ui-icon-edit ui-btn-icon-right">Save</button>
</form>
</body> </body>
</html> </html>
/*global window, rJS, RSVP */ /*global window, rJS, RSVP, loopEventListener*/
(function (window, rJS, RSVP) { (function (window, rJS, RSVP, loopEventListener) {
"use strict"; "use strict";
var gadget_klass = rJS(window); var gadget_klass = rJS(window);
function saveGraph(evt) {
var gadget = this,
graph_data,
graph_gadget;
return new RSVP.Queue()
.push(function () {
// Prevent double click
evt.target.getElementsByClassName("ui-btn")[0].disabled = true;
return gadget.getDeclaredGadget("productionline_graph");
})
.push(function (graphgadget) {
graph_gadget = graphgadget;
return graph_gadget.getData();
})
.push(function (data) {
graph_data = data;
// Always get a fresh version, to prevent deleting spreadsheet & co
return gadget.aq_getAttachment({
"_id": gadget.props.jio_key,
"_attachment": "body.json"
});
})
.push(function (body) {
var data = JSON.parse(body);
data.nodes = JSON.parse(graph_data).nodes;
data.edges = JSON.parse(graph_data).edges;
data.preference = JSON.parse(graph_data).preference;
return gadget.aq_putAttachment({
"_id": gadget.props.jio_key,
"_attachment": "body.json",
"_data": JSON.stringify(data, null, 2),
"_mimetype": "application/json"
});
})
.push(function () {
evt.target.getElementsByClassName("ui-btn")[0].disabled = false;
});
}
function waitForSave(gadget) {
return loopEventListener(
gadget.props.element.getElementsByClassName("save_form")[0],
'submit',
false,
saveGraph.bind(gadget)
);
}
gadget_klass gadget_klass
.ready(function (g) { .ready(function (g) {
...@@ -16,6 +65,7 @@ ...@@ -16,6 +65,7 @@
}) })
.declareAcquiredMethod("aq_getAttachment", "jio_getAttachment") .declareAcquiredMethod("aq_getAttachment", "jio_getAttachment")
.declareAcquiredMethod("aq_putAttachment", "jio_putAttachment")
.declareMethod("render", function (options) { .declareMethod("render", function (options) {
var jio_key = options.id, gadget = this; var jio_key = options.id, gadget = this;
...@@ -51,8 +101,9 @@ ...@@ -51,8 +101,9 @@
.push(function (toolbox) { .push(function (toolbox) {
return RSVP.all([ return RSVP.all([
graph.startService(), graph.startService(),
toolbox.startService() toolbox.startService(),
waitForSave(g)
]); ]);
}); });
}); });
}(window, rJS, RSVP)); }(window, rJS, RSVP, loopEventListener));
...@@ -31,6 +31,51 @@ ...@@ -31,6 +31,51 @@
node_template = Handlebars.compile(node_template_source), node_template = Handlebars.compile(node_template_source),
domParser = new DOMParser(); domParser = new DOMParser();
function loopJsplumbBind(gadget, type, callback) {
//////////////////////////
// Infinite event listener (promise is never resolved)
// eventListener is removed when promise is cancelled/rejected
//////////////////////////
var handle_event_callback,
callback_promise,
jsplumb_instance = gadget.props.jsplumb_instance;
function cancelResolver() {
if ((callback_promise !== undefined) &&
(typeof callback_promise.cancel === "function")) {
callback_promise.cancel();
}
}
function canceller() {
if (handle_event_callback !== undefined) {
jsplumb_instance.unbind(type);
}
cancelResolver();
}
function itsANonResolvableTrap(resolve, reject) {
handle_event_callback = function () {
var args = arguments;
cancelResolver();
callback_promise = new RSVP.Queue()
.push(function () {
return callback.apply(jsplumb_instance, args);
})
.push(undefined, function (error) {
if (!(error instanceof RSVP.CancellationError)) {
canceller();
reject(error);
}
});
};
jsplumb_instance.bind(type, handle_event_callback);
}
return new RSVP.Promise(itsANonResolvableTrap, canceller);
}
function getNodeId(node_container, element_id) { function getNodeId(node_container, element_id) {
var node_id; var node_id;
$.each(node_container, function (k, v) { $.each(node_container, function (k, v) {
...@@ -46,15 +91,15 @@ ...@@ -46,15 +91,15 @@
return node_container[node_id].element_id; return node_container[node_id].element_id;
} }
// function generateNodeId(node_container, element_type, option) { function generateNodeId(gadget, element_type, option) {
// var n = 1; var n = 1;
// while (node_container[ while (gadget.props.node_container[
// ((option.short_id || element_type) + n) ((option.short_id || element_type) + n)
// ] !== undefined) { ] !== undefined) {
// n += 1; n += 1;
// } }
// return (option.short_id || element_type) + n; return (option.short_id || element_type) + n;
// } }
function generateElementId(gadget_element) { function generateElementId(gadget_element) {
var n = 1; var n = 1;
...@@ -69,6 +114,36 @@ ...@@ -69,6 +114,36 @@
return undefined; return undefined;
} }
function updateConnectionData(gadget, connection, remove, edge_data) {
if (remove) {
delete gadget.props.edge_container[connection.id];
} else {
gadget.props.edge_container[connection.id] = [
getNodeId(gadget.props.node_container, connection.sourceId),
getNodeId(gadget.props.node_container, connection.targetId),
edge_data || {}
];
}
onDataChange();
}
// bind to connection/connectionDetached events,
// and update the list of connections on screen.
function waitForConnection(gadget) {
loopJsplumbBind(gadget, 'connection',
function (info, originalEvent) {
updateConnectionData(gadget, info.connection);
});
}
function waitForConnectionDetached(gadget) {
loopJsplumbBind(gadget, 'connectionDetached',
function (info, originalEvent) {
updateConnectionData(gadget, info.connection, true);
});
}
function convertToAbsolutePosition(gadget, x, y) { function convertToAbsolutePosition(gadget, x, y) {
var zoom_level = (gadget.props.preference_container.zoom_level || 1.0) * var zoom_level = (gadget.props.preference_container.zoom_level || 1.0) *
1.1111, 1.1111,
...@@ -204,30 +279,7 @@ ...@@ -204,30 +279,7 @@
// return undefined; // return undefined;
// }); // });
// split in 2 methods ? one for events one for manip // split in 2 methods ? one for events one for manip
gadget.props.updateConnectionData
= function (connection, remove, edge_data) {
if (remove) {
delete gadget.props.edge_container[connection.id];
} else {
gadget.props.edge_container[connection.id] = [
getNodeId(gadget.props.node_container, connection.sourceId),
getNodeId(gadget.props.node_container, connection.targetId),
edge_data || {}
];
}
onDataChange();
};
// bind to connection/connectionDetached events,
// and update the list of connections on screen.
// jsplumb_instance
// .bind("connection", function (info, originalEvent) {
// gadget.props.updateConnectionData(info.connection);
// });
// jsplumb_instance
// .bind("connectionDetached", function (info, originalEvent) {
// gadget.props.updateConnectionData(info.connection, true);
// });
onDataChange(); onDataChange();
draggable(gadget); draggable(gadget);
} }
...@@ -423,13 +475,19 @@ ...@@ -423,13 +475,19 @@
// onDataChange(); // onDataChange();
// } // }
function newElement(gadget, element, option) { function newElement(gadget, element, configuration) {
element.name = element.name || option.name; var element_type = element._class.replace('.', '-'),
addElementToContainer(gadget.props.node_container, element); option = configuration[element_type],
var render_element = $(gadget.props.element).find("#main"), render_element = $(gadget.props.element).find("#main"),
coordinate = element.coordinate, coordinate = element.coordinate,
box, box,
absolute_position; absolute_position;
element.element_id = generateElementId(gadget.props.element);
if (!element.id) {
element.id = generateNodeId(gadget, element_type, option);
}
addElementToContainer(gadget.props.node_container, element);
element.name = element.name || option.name;
if (coordinate !== undefined) { if (coordinate !== undefined) {
coordinate = updateElementCoordinate( coordinate = updateElementCoordinate(
gadget, gadget,
...@@ -469,7 +527,7 @@ ...@@ -469,7 +527,7 @@
); );
} }
function waitForDrop(gadget) { function waitForDrop(gadget, config) {
var target = gadget.props.element var target = gadget.props.element
.querySelector('#main'), .querySelector('#main'),
...@@ -504,7 +562,8 @@ ...@@ -504,7 +562,8 @@
}, },
"_class": element_class, "_class": element_class,
"name": element_class "name": element_class
}); },
config);
}; };
target.addEventListener('drop', callback, false); target.addEventListener('drop', callback, false);
...@@ -515,6 +574,9 @@ ...@@ -515,6 +574,9 @@
initGadgetMixin(gadget_klass); initGadgetMixin(gadget_klass);
gadget_klass gadget_klass
.declareAcquiredMethod('getConfigurationDict', 'getConfigurationDict')
.ready(function (g) { .ready(function (g) {
g.props.node_container = {}; g.props.node_container = {};
g.props.edge_container = {}; g.props.edge_container = {};
...@@ -544,34 +606,42 @@ ...@@ -544,34 +606,42 @@
var g = this, var g = this,
preference = g.props.data.preference !== undefined ? preference = g.props.data.preference !== undefined ?
g.props.data.preference : {}, g.props.data.preference : {},
coordinates = preference.coordinates; coordinates = preference.coordinates,
config;
g.props.main = g.props.element.querySelector('#main'); return g.getConfigurationDict()
initJsPlumb(g); .push(function (config_dict) {
$.each(g.props.data.nodes, function (key, value) { config = config_dict;
if (coordinates === undefined || coordinates[key] === undefined) { g.props.main = g.props.element.querySelector('#main');
value.coordinate = { initJsPlumb(g);
'top': 0.0, $.each(g.props.data.nodes, function (key, value) {
'left': 0.0 if (coordinates === undefined || coordinates[key] === undefined) {
}; value.coordinate = {
} else { 'top': 0.0,
value.coordinate = coordinates[key]; 'left': 0.0
} };
value.id = key; } else {
newElement(g, value); value.coordinate = coordinates[key];
if (value.data) { // backward compatibility }
updateElementData(g, key, { value.id = key;
data: value.data newElement(g, value, config);
if (value.data) { // backward compatibility
updateElementData(g, key, {
data: value.data
});
}
}); });
} $.each(g.props.data.edges, function (key, value) {
}); addEdge(g, key, value);
$.each(g.props.data.edges, function (key, value) { });
addEdge(g, key, value); })
}); .push(function () {
return RSVP.all([ return RSVP.all([
waitForDragover(g), waitForDragover(g),
waitForDrop(g) waitForDrop(g, config),
]); waitForConnection(g),
waitForConnectionDetached(g)
]);
});
}); });
}(RSVP, rJS, $, jsPlumb, Handlebars, initGadgetMixin, }(RSVP, rJS, $, jsPlumb, Handlebars, initGadgetMixin,
loopEventListener, DOMParser)); loopEventListener, DOMParser));
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