From 37c7213d0b1ca33c5750fdb7404984b1d302d2af Mon Sep 17 00:00:00 2001 From: Estók Dániel <estok.daniel@cloud.bme.hu> Date: Mon, 25 Jan 2016 14:12:09 +0100 Subject: [PATCH] Improved dashboard-integration and refactor. --- circle/setty/models.py | 4 ++-- circle/setty/static/setty/setty.js | 386 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------------------------------------------------------------------------------------------------------------------------------------------------- circle/setty/templates/setty/index.html | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++------------ circle/setty/templates/setty/service_confirm_delete.html | 5 ----- circle/setty/urls.py | 8 +++++++- circle/setty/views.py | 145 ++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------------------------------------------------------------------------- 6 files changed, 339 insertions(+), 274 deletions(-) delete mode 100644 circle/setty/templates/setty/service_confirm_delete.html diff --git a/circle/setty/models.py b/circle/setty/models.py index 3ddcf73..a23bb39 100644 --- a/circle/setty/models.py +++ b/circle/setty/models.py @@ -53,7 +53,7 @@ class Element(Model): anchors = models.PositiveSmallIntegerField() def __unicode__(self): - return self.service.name + ", id: " + self.display_id + return "%s (%s)" % (self.service.name, self.display_id) class ElementConnection(Model): @@ -70,4 +70,4 @@ class ElementConnection(Model): parameters = models.TextField() def __unicode__(self): - return self.target.service.name + ", " + str(self.id) + return "%s (%d)" % (self.target.service.name, self.id) diff --git a/circle/setty/static/setty/setty.js b/circle/setty/static/setty/setty.js index 2451bb7..4e35b8e 100644 --- a/circle/setty/static/setty/setty.js +++ b/circle/setty/static/setty/setty.js @@ -1,5 +1,34 @@ -(function($){ +function getCookie(name) { + var cookieValue = null; + if (document.cookie && document.cookie !== '') { + var cookies = document.cookie.split(';'); + for (var i = 0; i < cookies.length; i++) { + var cookie = jQuery.trim(cookies[i]); + if (cookie.substring(0, name.length + 1) == (name + '=')) { + cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); + break; + } + } + } + return cookieValue; +} + +function csrfSafeMethod(method) { + return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method)); +} + +var csrftoken = getCookie('csrftoken'); + +$.ajaxSetup({ + beforeSend: function(xhr, settings) { + if (!csrfSafeMethod(settings.type) && !this.crossDomain) { + xhr.setRequestHeader("X-CSRFToken", csrftoken); + } + } +}); + +(function($){ $.event.special.doubletap = { bindType: 'touchend', delegateType: 'touchend', @@ -18,7 +47,6 @@ event[property] = event.originalEvent.changedTouches[0][property]; }); - // let jQuery handle the triggering of "doubletap" event handlers handleObj.handler.apply(this, arguments); } else { targetData.lastTouch = now; @@ -72,28 +100,27 @@ jsPlumb.ready(function() { var stackIndexer = 0; var stackSize = 0; - var objectStack = []; var undoStack = []; var redoStack = []; - $("#dropContainer").attr('unselectable', 'on') - .css({ + $("#dropContainer").attr('unselectable', 'on').css({ 'user-select': 'none', - 'MozUserSelect': 'none' - }) + 'MozUserSelect': 'none'}) .on('selectstart', false) .on('mousedown', false); + setServiceStatus = function(status) { if (status == "unsaved") { $("#serviceStatus").text("Unsaved"); } - if (status == "saved") { + else { $("#serviceStatus").empty(); } }; + addInfo = function(title, info, type, object) { $("#informationContainer").empty(); @@ -167,67 +194,14 @@ jsPlumb.ready(function() { $("#informationContainer").append(div); - $("#infoInput").val(info).keyup(function() { - setServiceStatus("unsaved"); - newParams = $("#infoInput").val(); - - if (type == "connection") object.parameters = newParams; - if (type == "element") object.attr("parameters", newParams); - }); - - $("#addEndpoint").click(function() { - addEndpoint(object); - undoStack.splice(stackIndexer, 0, removeEndoint); - redoStack.splice(stackIndexer, 0, addEndpoint); - objectStack.splice(stackIndexer, 0, object); - stackIndexer++; - stackSize++; - }); - - $("#removeEndpoint").click(function() { - removeEndoint(object); - undoStack.splice(stackIndexer, 0, addEndpoint); - redoStack.splice(stackIndexer, 0, removeEndoint); - objectStack.splice(stackIndexer, 0, object); - stackIndexer++; - stackSize++; - }); - - $("#removeFromWorkspace").click(function() { - $('.element').removeClass('elementSelected'); - removeElement(object); - - $("#informationPanel").hide(); - $("#dragPanel").show(); - - undoStack.splice(stackIndexer, 0, addElement); - redoStack.splice(stackIndexer, 0, removeElement); - objectStack.splice(stackIndexer, 0, object); - stackSize++; - stackIndexer++; - }); - - $("#removeConnection").click(function() { - jsPlumbInstance.detach(object); - $("#informationPanel").hide(); - $("#dragPanel").show(); - }); - - $("#addElementToWorkspace").click(function() { - addElement(object.attr("id"), (++elementIndex) + "_" + object.attr("id"), (elementIndex % 21) * 30, 4, "", (elementIndex % 21) * 30); - - undoStack.splice(stackIndexer, 0, removeElement); - redoStack.splice(stackIndexer, 0, addElement); - objectStack.splice(stackIndexer, 0, newInstance); - stackSize++; - stackIndexer++; - }); + $("#infoInput").val(info); $("#dragPanel").hide(); $("#informationPanel").show(); }; + updateConnections = function(connection, remove) { if (!remove) { elementConnections.push(connection); @@ -277,6 +251,7 @@ jsPlumb.ready(function() { return true; }; + checkSourceTargetEquality = function(connection) { if (connection.targetId == connection.sourceId) { addMessage("Connecting element to itself is forbidden.", "danger"); @@ -285,6 +260,7 @@ jsPlumb.ready(function() { return true; }; + getAnchorCoordinate = function(rate) { x = Math.cos(2.0 * Math.PI * rate) / 2; y = Math.sin(2.0 * Math.PI * rate) / 2; @@ -317,6 +293,7 @@ jsPlumb.ready(function() { return [y + 0.5, -x + 0.5, dy, -dx]; }; + isConnected = function(anchorId) { returnValue = false; $.each(elementConnections, function(index) { @@ -329,6 +306,7 @@ jsPlumb.ready(function() { return returnValue; }; + getConnectionparamAndAnchor = function(anchorId) { parameters = ""; otherAnchor = ""; @@ -350,6 +328,7 @@ jsPlumb.ready(function() { return [otherAnchor, parameters]; }; + addEndpoint = function(element) { anchors = element.attr("anchors"); @@ -357,37 +336,35 @@ jsPlumb.ready(function() { anchors++; - jsPlumbInstance.addEndpoint(document.getElementById( - element.attr("id")), { - anchor: getAnchorCoordinate((anchors - 1) / anchors), + jsPlumbInstance.addEndpoint(document.getElementById(element.attr("id")), { uuid: (anchors - 1) + "_" + element.attr("id") }, jsPlumbEndpoint); - for (i = 0; i < anchors; i++) jsPlumbInstance.getEndpoint(i + "_" + element.attr("id")).setAnchor(getAnchorCoordinate(i / (anchors))); + for (i = 0; i < anchors; i++) { + jsPlumbInstance.getEndpoint(i + "_" + element.attr("id")).setAnchor(getAnchorCoordinate(i / (anchors))); + } element.attr("anchors", anchors); jsPlumbInstance.repaintEverything(); }; + removeEndoint = function(element) { anchors = element.attr("anchors"); if (anchors == 4) return; - i = anchors - 1; - anchors--; + i = --anchors; - while (isConnected(i + "_" + element.attr("id")) && - i >= 0) i--; + while (isConnected(i + "_" + element.attr("id")) && i >= 0) i--; if (i == -1) { addMessage("Removing anchors is obstructed.", "danger"); return; } else if (i == anchors) { - jsPlumbInstance.deleteEndpoint( - jsPlumbInstance.getEndpoint(anchors + "_" + element.attr("id"))); + jsPlumbInstance.deleteEndpoint(jsPlumbInstance.getEndpoint(anchors + "_" + element.attr("id"))); } else { newId = i + "_" + element.attr("id"); oldId = anchors + "_" + element.attr("id"); @@ -408,6 +385,7 @@ jsPlumb.ready(function() { jsPlumbInstance.repaintEverything(); }; + connectEndpoints = function(data) { connectionObject = jsPlumbInstance.connect({ @@ -419,6 +397,7 @@ jsPlumb.ready(function() { setServiceStatus("unsaved"); }; + disconnectEndpoints = function(data) { for (var i = 0; i < elementConnections.length; i++) { if (elementConnections[i].endpoints[0].getUuid() == data[0] && @@ -430,6 +409,7 @@ jsPlumb.ready(function() { return; }; + addElement = function(idOrInstance, newId, newPositionY, endpoints, parameters, newPositionX) { newInstance = ""; @@ -460,47 +440,51 @@ jsPlumb.ready(function() { containment: $("#dropContainer") }); - newInstance.on('dblclick doubletap', function() { - element = $(this); - $('.element').removeClass('elementSelected'); - jsPlumbInstance.select().setPaintStyle({strokeStyle:'#9932cc', lineWidth: 8}); - element.addClass("elementSelected"); - addInfo(element.attr("alt"), element.attr("parameters"), "element", element); - }).mousedown(function(e) { - if (e.button == 2) { - setServiceStatus("unsaved"); - $("#informationPanel").hide(); - $("#dragPanel").show(); - - $('.element').removeClass('elementSelected'); - jsPlumbInstance.select().setPaintStyle({strokeStyle:'#9932cc', lineWidth: 8}); - - removeElement($(this)); - - undoStack.splice(stackIndexer, 0, addElement); - redoStack.splice(stackIndexer, 0, removeElement); - objectStack.splice(stackIndexer, 0, $(this)); - stackSize++; - stackIndexer++; - return false; - } - return true; - }); - setServiceStatus("unsaved"); jsPlumbInstance.repaintEverything(); }; + removeElement = function(object) { jsPlumbInstance.detachAllConnections(object); jsPlumbInstance.remove(object.attr("id")); }; + + scrollContainer = function(direction) { + dragContainerScroll += direction; + + if (dragContainerScroll == $(".elementTemplate").length - 2) dragContainerScroll--; + if (dragContainerScroll == -1) dragContainerScroll++; + + $("#dragContainer").scrollTop( + dragContainerScroll * $("#elementTemplatePanel").height() + ); + }; + + + mouseScrollContainer = function(event) { + var e = window.event || event; + var delta = Math.max(-1, Math.min(1, (e.wheelDelta || -e.detail))); + + $('body').addClass("noScroll"); + + scrollContainer(-delta); + + $('body').removeClass("noScroll"); + }; + + jsPlumbInstance.bind("connection", function(info) { updateConnections(info.connection); info.connection.parameters = ""; + // For right click on a connection. + $("path").on('doubletap', function() { + //Todo + }); + if (clickEvent === 0) { undoStack.splice(stackIndexer, 0, disconnectEndpoints); redoStack.splice(stackIndexer, 0, connectEndpoints); @@ -513,11 +497,15 @@ jsPlumb.ready(function() { stackSize++; } }); + + jsPlumbInstance.bind("beforeDrop", function(info) { return checkDuplicateConnection(info.connection) && checkSourceTargetEquality(info.connection) && checkCompatibility(info.connection.sourceId, info.connection.targetId); }); + + jsPlumbInstance.bind("connectionDetached", function(info) { updateConnections(info.connection, true); @@ -533,14 +521,20 @@ jsPlumb.ready(function() { stackSize++; } }); + + jsPlumbInstance.bind("connectionMoved", function(info) { updateConnections(info.connection, true); }); + + jsPlumbInstance.bind("contextmenu", function(info) { jsPlumbInstance.detach(info); $("#informationPanel").hide(); $("#dragPanel").show(); }); + + jsPlumbInstance.bind("dblclick", function(info) { $('.element').removeClass('elementSelected'); jsPlumbInstance.select().setPaintStyle({strokeStyle:'#9932cc', lineWidth: 8}); @@ -550,11 +544,14 @@ jsPlumb.ready(function() { "connection", info); }); + + jsPlumbInstance.draggable(jsPlumb.getSelector(".element"), { containment: $("#dropContainer") }); - $(".elementTemplate").click(function() { + + $('body').on('click', '.elementTemplate', function() { addElement($(this).attr("id"), (++elementIndex) + "_" + $(this).attr("id"), (elementIndex % 21) * 30, 4, "", (elementIndex % 21) * 30); undoStack.splice(stackIndexer, 0, removeElement); @@ -564,25 +561,115 @@ jsPlumb.ready(function() { stackIndexer++; }); - $("#closeInfoPanel").click(function(){ + + $('body').on('dblclick doubletap', '.element', function() { + element = $(this); + $('.element').removeClass('elementSelected'); + jsPlumbInstance.select().setPaintStyle({strokeStyle:'#9932cc', lineWidth: 8}); + element.addClass("elementSelected"); + addInfo(element.attr("alt"), element.attr("parameters"), "element", element); + $(document).scrollTop(0); + }); + + + $('body').on('contextmenu', '.element', function(event) { + setServiceStatus("unsaved"); + $("#informationPanel").hide(); + $("#dragPanel").show(); + + $('.element').removeClass('elementSelected'); + jsPlumbInstance.select().setPaintStyle({strokeStyle:'#9932cc', lineWidth: 8}); + + removeElement($(this)); + + undoStack.splice(stackIndexer, 0, addElement); + redoStack.splice(stackIndexer, 0, removeElement); + objectStack.splice(stackIndexer, 0, $(this)); + stackSize++; + stackIndexer++; + }); + + + $('body').on('click', '#closeInfoPanel', function() { $('#informationPanel').hide(); $('#dragPanel').show(); $('.element').removeClass('elementSelected'); jsPlumbInstance.select().setPaintStyle({strokeStyle:'#9932cc', lineWidth: 8}); }); - $("#clearService").click(function() { - jsPlumbInstance.detachEveryConnection(); - jsPlumbInstance.deleteEveryEndpoint(); - $(".element").remove(); + + $('body').on('keyUp', '#infoInput', function() { setServiceStatus("unsaved"); + newParams = $("#infoInput").val(); + + if (type == "connection") object.parameters = newParams; + if (type == "element") object.attr("parameters", newParams); + }); + + + $('body').on('click', '#addEndpoint', function() { + addEndpoint(object); + undoStack.splice(stackIndexer, 0, removeEndoint); + redoStack.splice(stackIndexer, 0, addEndpoint); + objectStack.splice(stackIndexer, 0, object); + stackIndexer++; + stackSize++; + }); + + + $('body').on('click', '#removeEndpoint', function() { + removeEndoint(object); + undoStack.splice(stackIndexer, 0, addEndpoint); + redoStack.splice(stackIndexer, 0, removeEndoint); + objectStack.splice(stackIndexer, 0, object); + stackIndexer++; + stackSize++; + }); + + + $('body').on('click', '#removeFromWorkspace', function() { + $('.element').removeClass('elementSelected'); + removeElement(object); + + $("#informationPanel").hide(); + $("#dragPanel").show(); + + undoStack.splice(stackIndexer, 0, addElement); + redoStack.splice(stackIndexer, 0, removeElement); + objectStack.splice(stackIndexer, 0, object); + stackSize++; + stackIndexer++; + }); + + + $('body').on('click', '#removeConnection', function() { + jsPlumbInstance.detach(object); + $("#informationPanel").hide(); + $("#dragPanel").show(); + }); + + + $('body').on('click', '#addElementToWorkspace', function() { + addElement(object.attr("id"), (++elementIndex) + "_" + object.attr("id"), (elementIndex % 21) * 30, 4, "", (elementIndex % 21) * 30); + + undoStack.splice(stackIndexer, 0, removeElement); + redoStack.splice(stackIndexer, 0, addElement); + objectStack.splice(stackIndexer, 0, newInstance); + stackSize++; + stackIndexer++; + }); - jsPlumbInstance.repaintEverything(); + + $('body').on('click', '#clearService', function() { + jsPlumbInstance.reset(); + $(".element").remove(); + setServiceStatus("unsaved"); elementIndex = 0; }); - $("#undoMovement").click(function() { + + $('body').on('click', '#undoMovement', function() { if (stackIndexer <= 0) return; stackIndexer--; clickEvent = 1; @@ -591,7 +678,8 @@ jsPlumb.ready(function() { clickEvent = 0; }); - $("#redoMovement").click(function() { + + $('body').on('click', '#redoMovement', function() { if (stackIndexer >= stackSize) return; clickEvent = 1; object = objectStack[stackIndexer]; @@ -599,19 +687,32 @@ jsPlumb.ready(function() { clickEvent = 0; }); - $(".elementTemplateInfo").click(function() { - id = $(this).attr("element"); + $('body').on('click', '.elementTemplateInfo', function() { + id = $(this).attr("element"); addInfo($("#" + id).attr("alt"), $("#" + id).attr("desc"), "elementTemplate", $("#" + id)); }); - $("#serviceName").keydown(function() { + $('body').on('click', '#serviceName', function() { + $(this).replaceWith('<input type="text" id="serviceName" class="form-control form-control-sm" style="margin-top: -4px !important; margin-bottom: -4px !important;" value="' + $(this).html() + '" />'); + document.getElementById("serviceName").select(); setServiceStatus("unsaved"); }); - $("#saveService").click(function() { - serviceName = $("#serviceName").text(); + + $('body').on('click', '#dragContainerScrollUp', function() { + scrollContainer(-1); + }); + + + $('body').on('click', '#dragContainerScrollDown', function() { + scrollContainer(1); + }); + + + $('body').on('click', '#saveService', function() { + serviceName = $("#serviceName").val() === ''?$("#serviceName").text():$("#serviceName").val(); connectionSet = []; instanceSet = []; @@ -621,8 +722,7 @@ jsPlumb.ready(function() { "sourceEndpoint": elementConnections[index].endpoints[0].getUuid(), "targetId": elementConnections[index].targetId, "targetEndpoint": elementConnections[index].endpoints[1].getUuid(), - "parameters": elementConnections[index].parameters - }); + "parameters": elementConnections[index].parameters}); }); $.each($(".element"), function() { @@ -631,8 +731,7 @@ jsPlumb.ready(function() { "posX": Math.floor($(this).position().left), "posY": Math.floor($(this).position().top), "anchors": $(this).attr("anchors"), - "parameters": $(this).attr("parameters") - }); + "parameters": $(this).attr("parameters")}); }); $.post("", { @@ -640,17 +739,10 @@ jsPlumb.ready(function() { data: JSON.stringify({ "serviceName": serviceName, "elementConnections": connectionSet, - "elements": instanceSet - }) - }, function(resultValue) { - if (window.location.href.indexOf( - "/create") >= 0) { - window.location = "../" + - resultValue; - } else { - addMessage("Saved successfully.","success"); - setServiceStatus("saved"); - } + "elements": instanceSet}) + }, function(result) { + addMessage(result.serviceName + " saved successfully.","success"); + setServiceStatus("saved"); }); }); @@ -665,37 +757,6 @@ jsPlumb.ready(function() { }); - scrollContainer = function(direction) { - dragContainerScroll += direction; - - if (dragContainerScroll == $(".elementTemplate").length - 2) dragContainerScroll--; - if (dragContainerScroll == -1) dragContainerScroll++; - - $("#dragContainer").scrollTop( - dragContainerScroll * $("#elementTemplatePanel").height() - ); - }; - - - mouseScrollContainer = function(ev) { - var e = window.event || ev; - var delta = Math.max(-1, Math.min(1, (e.wheelDelta || -e.detail))); - - $('body').addClass("noScroll"); - - scrollContainer(-delta); - - $('body').removeClass("noScroll"); - }; - - $("#dragContainerScrollUp").click(function() { - scrollContainer(-1); - }); - - $("#dragContainerScrollDown").click(function() { - scrollContainer(1); - }); - var dragContainer = document.getElementById("dragContainer"); if (dragContainer.addEventListener) { @@ -716,10 +777,9 @@ jsPlumb.ready(function() { $(document).ready(function() { $.post("", { event: "loadService" - }, function(resultValue) { - if (resultValue === "") return; + }, function(result) { + if (result === "") return; - result = jQuery.parseJSON(resultValue); $("#serviceName").text(result.serviceName); $.each(result.elements, function(i, element) { diff --git a/circle/setty/templates/setty/index.html b/circle/setty/templates/setty/index.html index 86db7ba..33b7df0 100644 --- a/circle/setty/templates/setty/index.html +++ b/circle/setty/templates/setty/index.html @@ -7,6 +7,8 @@ {% block content %} +<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"> + <link type="text/css" rel="stylesheet" href="{% static 'setty/style.css' %}"> <div class="row" id="workspace"> @@ -14,16 +16,14 @@ <div class="panel panel-default initHidden" id="informationPanel"> <div class="panel-heading text-center"> <div class="row"> - <div class="col-xs-2 text-left"> + <div class="col-xs-10 text-left"> + <h3 class="no-margin"><i class="fa fa-info"></i> {% trans 'Information' %}</h3> + </div> + <div class="col-xs-2"> <button class="btn btn-danger btn-xs" id="closeInfoPanel"> <i class="fa fa-times"></i> </button> </div> - <div class="col-xs-8"> - <h3 class="no-margin">{% trans 'Information' %}</h3> - </div> - <div class="col-xs-2"> - </div> </div> </div> <div class="panel-body" id="informationContainer"> @@ -36,7 +36,9 @@ <div class="panel panel-default text-center" id="dragPanel"> <div class="panel-heading"> <div class="row"> - <h3 class="no-margin">{% trans 'Elements' %}</h3> + <div class="col-xs-12 text-left"> + <h3 class="no-margin"><i class="fa fa-outdent"></i> {% trans 'Elements' %}</h3> + </div> </div> </div> <div class="panel-heading text-center"> @@ -90,17 +92,17 @@ <div class="panel panel-default"> <div class="panel-heading text-center"> <div class="row"> - <div class="col-xs-2"> + <div class="col-xs-2 text-left"> <button class="btn btn-info btn-xs" id="undoMovement" title="{% trans 'Undo' %}"><i class="fa fa-undo"></i></button> </div> - <div class="col-xs-2"> + <div class="col-xs-2 text-left"> <button class="btn btn-info btn-xs" id="redoMovement" title="{% trans 'Redo' %}"><i class="fa fa-repeat"></i></button> </div> <div class="col-xs-4"> - <h3 class="no-margin" id="serviceName" contenteditable="true">Service</h3> + <h3 class="no-margin" id="serviceName">Service</h3> </div> <div class="col-xs-2 text-right"> - <button class="btn btn-info btn-xs" id="clearService" title="{% trans 'Clear workspace' %}"><i class="fa fa-trash-o"></i></button> + <button class="btn btn-info btn-xs" id="clearService" title="{% trans 'Clear workspace' %}"><i class="fa fa-eraser"></i></button> </div> <div class="col-xs-2 text-right"> <button class="btn btn-success btn-xs" id="saveService" title="{% trans 'Save workspace' %}"><i class="fa fa-floppy-o"></i></button> @@ -109,12 +111,51 @@ </div> <div class="panel-body" id="dropContainer" oncontextmenu="return false;"></div> <div class="panel-footer no-margin text-left"> - <label class="no-margin" id="serviceStatus"></label> + <div class="row"> + <div class="col-xs-2 text-left"> + <label class="no-margin" id="serviceStatus"></label> + </div> + <div class="col-xs-2 col-xs-push-8 text-right"> + <button class="btn btn-danger btn-xs" id="deteleService" title="{% trans 'Delete service' %}" data-toggle="modal" data-target="#deleteServiceDialog"><i class="fa fa-trash-o"></i></button> + </div> + </div> </div> </div> </div> </div> +{% if actualId %} + +<!-- Modal --> +<div id="deleteServiceDialog" class="modal fade" role="dialog"> + <div class="modal-dialog"> + <div class="modal-content"> + <div class="modal-header"> + <button type="button" class="close" data-dismiss="modal">×</button> + <h4 class="modal-title"><i class="fa fa-trash-o"></i> {% trans 'Deleting service' %}</h4> + </div> + <div class="modal-body"> + <p>{% trans 'Are you sure you want to delete this service?' %}</p> + </div> + <div class="modal-footer"> + <div class="row"> + <div class="col-xs-2 col-xs-push-8"> + <form method="post" action="{% url 'setty.views.service-delete' actualId %}"> + {% csrf_token %} + <input type="submit" class="btn btn-danger btn-sm" value="{% trans 'Delete' %}" /> + </form> + </div> + <div class="col-xs-2 col-xs-push-8"> + <button type="button" class="btn btn-primary btn-sm" data-dismiss="modal">{% trans 'Close' %}</button> + </div> + </div> + </div> + </div> + </div> +</div> + +{% endif %} + {% endblock %} diff --git a/circle/setty/templates/setty/service_confirm_delete.html b/circle/setty/templates/setty/service_confirm_delete.html deleted file mode 100644 index cddb18f..0000000 --- a/circle/setty/templates/setty/service_confirm_delete.html +++ /dev/null @@ -1,5 +0,0 @@ -<!DOCTYPE html> -<form method="post">{% csrf_token %} - Are you sure you want to delete "{{ object }}" ? - <input type="submit" value="Submit" /> -</form> \ No newline at end of file diff --git a/circle/setty/urls.py b/circle/setty/urls.py index f888ba4..2850187 100644 --- a/circle/setty/urls.py +++ b/circle/setty/urls.py @@ -20,7 +20,7 @@ from . import views urlpatterns = [ url(r'^create/$', - views.IndexView.as_view(), + views.CreateView.as_view(), name='setty.views.service-create'), url(r'^delete/(?P<pk>\d+)$', views.DeleteView.as_view(), @@ -28,6 +28,12 @@ urlpatterns = [ url(r'^start/(?P<pk>\d+)$', views.StartView.as_view(), name='setty.views.service-start'), + url(r'^stop/(?P<pk>\d+)$', + views.StopView.as_view(), + name='setty.views.service-start'), + url(r'^stop/(?P<pk>\d+)$', + views.StartView.as_view(), + name='setty.views.service-stop'), url(r'^list/$', views.ListView.as_view(), name='setty.views.service-list'), diff --git a/circle/setty/views.py b/circle/setty/views.py index b241a5f..fcd9aee 100644 --- a/circle/setty/views.py +++ b/circle/setty/views.py @@ -15,67 +15,46 @@ # You should have received a copy of the GNU General Public License along # with CIRCLE. If not, see <http://www.gnu.org/licenses/>. -from django.template import RequestContext -from django.http import HttpResponse -from django.views.decorators.csrf import csrf_exempt -from django.views.generic import TemplateView, DeleteView +from django.core.exceptions import PermissionDenied from django.core.urlresolvers import reverse_lazy from django.db.models import Q -from django.http import HttpResponseForbidden, Http404 -from django.shortcuts import redirect -from django.contrib import auth -from .models import ( - Element, - ElementTemplate, - ElementConnection, - Service -) +from django.http import JsonResponse +from braces.views import LoginRequiredMixin +from django.views.generic import TemplateView, DeleteView, CreateView +from .models import Element, ElementTemplate, ElementConnection, Service import json -class IndexView(TemplateView): +class DetailView(LoginRequiredMixin, TemplateView): template_name = "setty/index.html" - def get(self, request, *args, **kwargs): - if self.request.user.is_authenticated(): - return TemplateView.get(self, request, *args, **kwargs) - else: - return redirect(auth.views.login) - def get_context_data(self, **kwargs): - elementTemplateList = ElementTemplate.objects.all() - context = RequestContext( - self.request, - {'elementTemplateList': elementTemplateList}) + context = super(DetailView, self).get_context_data(**kwargs) + context['elementTemplateList'] = ElementTemplate.objects.all() return context - @csrf_exempt def post(self, request, *args, **kwargs): - if not self.request.user.is_authenticated(): - return redirect(auth.views.login) - if self.request.POST.get('event') == "saveService": - jsonData = json.loads(self.request.POST.get('data')) - - serviceName = jsonData['serviceName'] + data = json.loads(self.request.POST.get('data')) + service_name = data['serviceName'] if 'pk' in kwargs: - serviceObject = Service.objects.get(id=kwargs['pk']) - serviceObject.name = serviceName - serviceObject.save() + service = Service.objects.get(id=kwargs['pk']) + service.name = service_name + service.save() - Element.objects.filter(service=serviceObject).delete() + Element.objects.filter(service=service).delete() else: - serviceObject = Service( - name=serviceName, + service = Service( + name=service_name, user=self.request.user ) - serviceObject.save() + service.save() - for element in jsonData['elements']: + for element in data['elements']: elementObject = Element( - service=serviceObject, + service=service, parameters=element['parameters'], display_id=element['displayId'], pos_x=element['posX'], @@ -84,7 +63,7 @@ class IndexView(TemplateView): ) elementObject.save() - for elementConnection in jsonData['elementConnections']: + for elementConnection in data['elementConnections']: sourceId = elementConnection['sourceId'] targetId = elementConnection['targetId'] sourceEndpoint = elementConnection['sourceEndpoint'] @@ -93,11 +72,11 @@ class IndexView(TemplateView): targetObject = Element.objects.get( display_id=targetId, - service=serviceObject) + service=service) sourceObject = Element.objects.get( display_id=sourceId, - service=serviceObject) + service=service) connectionObject = ElementConnection( target=targetObject, @@ -108,46 +87,11 @@ class IndexView(TemplateView): ) connectionObject.save() - return HttpResponse(serviceObject.pk) - - else: - return HttpResponse() - - -class DeleteView(DeleteView): - model = Service - - success_url = reverse_lazy("dashboard.index") - - -class StartView(TemplateView): - pass - - -class ListView(TemplateView): - pass - - -class DetailView(IndexView): - def get(self, request, *args, **kwargs): - try: - serviceObject = Service.objects.get(id=kwargs['pk']) - if serviceObject.user != self.request.user: - return HttpResponseForbidden( - "You don't have permission to open the service.") - except: - raise Http404 - else: - return IndexView.get(self, request, *args, **kwargs) - - @csrf_exempt - def post(self, request, *args, **kwargs): - if not self.request.user.is_authenticated(): - return redirect(auth.views.login) + return JsonResponse({'serviceName': service.name}) - if self.request.POST.get('event') == "loadService": - serviceObject = Service.objects.get(id=kwargs['pk']) - elementList = Element.objects.filter(service=serviceObject) + elif self.request.POST.get('event') == "loadService": + service = Service.objects.get(id=kwargs['pk']) + elementList = Element.objects.filter(service=service) elementConnectionList = ElementConnection.objects.filter( Q(target__in=elementList) | Q(source__in=elementList)) @@ -160,20 +104,39 @@ class DetailView(IndexView): 'displayId': item.display_id, 'posX': item.pos_x, 'posY': item.pos_y, - 'anchors': item.anchors - }) + 'anchors': item.anchors}) for item in elementConnectionList: elementConnections.append({ 'targetEndpoint': item.target_endpoint, 'sourceEndpoint': item.source_endpoint, - 'parameters': item.parameters - }) + 'parameters': item.parameters}) - return HttpResponse(json.dumps( - {"elements": elements, - "elementConnections": elementConnections, - "serviceName": serviceObject.name})) + return JsonResponse( + {'elements': elements, + 'elementConnections': elementConnections, + 'serviceName': service.name}) else: - return IndexView.post(self, request, *args, **kwargs) + raise PermissionDenied + + +class DeleteView(LoginRequiredMixin, DeleteView): + model = Service + success_url = reverse_lazy("dashboard.index") + + +class CreateView(LoginRequiredMixin, CreateView): + pass + + +class StartView(LoginRequiredMixin, TemplateView): + pass + + +class StopView(LoginRequiredMixin, TemplateView): + pass + + +class ListView(LoginRequiredMixin, TemplateView): + pass -- libgit2 0.26.0