diff --git a/circle/dashboard/static/dashboard/dashboard.css b/circle/dashboard/static/dashboard/dashboard.css index 5c18ff7..05063f4 100644 --- a/circle/dashboard/static/dashboard/dashboard.css +++ b/circle/dashboard/static/dashboard/dashboard.css @@ -187,7 +187,7 @@ html { height: 300px; } -#vm-details-rename, #vm-details-rename *, #vm-details-h1-name, #vm-list-rename, #vm-list-rename *, +#vm-details-rename, #vm-details-h1-name, #vm-details-rename , #node-details-rename, #node-details-rename *, #node-details-h1-name, #node-list-rename, #node-list-rename *#group-details-rename, #group-details-rename *, #group-details-h1-name, #group-list-rename, #group-list-rename * { display: inline; @@ -197,7 +197,11 @@ html { display: none; } -#vm-details-rename-name, #node-details-rename-name, #group-details-rename-name { +.vm-details-home-name { + max-width: 401px; +} + +#node-details-rename-name, #group-details-rename-name { max-width: 160px; } @@ -467,3 +471,23 @@ footer a, footer a:hover, footer a:visited { overflow: hidden; padding-left: 10px; } + +#vm-details-home-description { + display: inline-block; + position: relative; +} + +#vm-details-home-description textarea { + min-width: 240px; + min-height: 250px; +} + +.vm-details-home-edit-description-click, .vm-details-home-edit-name-click { + cursor: pointer; +} + +.vm-details-description-submit { + position: absolute; + bottom: 10px; + right: 20px; +} diff --git a/circle/dashboard/static/dashboard/vm-details.js b/circle/dashboard/static/dashboard/vm-details.js index e663a87..f6719cd 100644 --- a/circle/dashboard/static/dashboard/vm-details.js +++ b/circle/dashboard/static/dashboard/vm-details.js @@ -31,33 +31,6 @@ $(function() { return false; }); - /* rename */ - $("#vm-details-h1-name, .vm-details-rename-button").click(function() { - $("#vm-details-h1-name").hide(); - $("#vm-details-rename").css('display', 'inline'); - $("#vm-details-rename-name").focus(); - }); - - /* rename ajax */ - $('#vm-details-rename-submit').click(function() { - var name = $('#vm-details-rename-name').val(); - $.ajax({ - method: 'POST', - url: location.href, - data: {'new_name': name}, - headers: {"X-CSRFToken": getCookie('csrftoken')}, - success: function(data, textStatus, xhr) { - $("#vm-details-h1-name").text(data['new_name']).show(); - $('#vm-details-rename').hide(); - // addMessage(data['message'], "success"); - }, - error: function(xhr, textStatus, error) { - addMessage("Error during renaming!", "danger"); - } - }); - return false; - }); - /* remove tag */ $('.vm-details-remove-tag').click(function() { var to_remove = $.trim($(this).parent('div').text()); @@ -166,7 +139,6 @@ $(function() { $(".vm-details-help").stop().slideToggle(); }); - /* for interface remove buttons */ $('.interface-remove').click(function() { var interface_pk = $(this).data('interface-pk'); @@ -178,6 +150,87 @@ $(function() { }); return false; }); + + /* rename */ + $("#vm-details-h1-name, .vm-details-rename-button").click(function() { + $("#vm-details-h1-name").hide(); + $("#vm-details-rename").css('display', 'inline'); + $("#vm-details-rename-name").focus(); + }); + + /* rename in home tab */ + $(".vm-details-home-edit-name-click").click(function() { + $(".vm-details-home-edit-name-click").hide(); + $("#vm-details-home-rename").show(); + $("input", $("#vm-details-home-rename")).focus(); + }); + + /* rename ajax */ + $('.vm-details-rename-submit').click(function() { + var name = $(this).parent("span").prev("input").val(); + $.ajax({ + method: 'POST', + url: location.href, + data: {'new_name': name}, + headers: {"X-CSRFToken": getCookie('csrftoken')}, + success: function(data, textStatus, xhr) { + $(".vm-details-home-edit-name").text(data['new_name']).show(); + $(".vm-details-home-edit-name").parent("div").show(); + $(".vm-details-home-edit-name-click").show(); + $(".vm-details-home-rename-form-div").hide(); + // update the inputs too + $(".vm-details-rename-submit").parent("span").prev("input").val(data['new_name']); + }, + error: function(xhr, textStatus, error) { + addMessage("Error during renaming!", "danger"); + } + }); + return false; + }); + + /* update description click */ + $(".vm-details-home-edit-description-click").click(function() { + $(".vm-details-home-edit-description-click").hide(); + $("#vm-details-home-description").show(); + return false; + }); + + /* description update ajax */ + $('.vm-details-description-submit').click(function() { + var description = $(this).prev("textarea").val(); + console.log(description); + $.ajax({ + method: 'POST', + url: location.href, + data: {'new_description': description}, + headers: {"X-CSRFToken": getCookie('csrftoken')}, + success: function(data, textStatus, xhr) { + var new_desc = data['new_description']; + /* we can't simply use $.text, because we need new lines */ + var tagsToReplace = { + '&': "&", + '<': "<", + '>': ">", + }; + + new_desc = new_desc.replace(/[&<>]/g, function(tag) { + return tagsToReplace[tag] || tag; + }); + + $(".vm-details-home-edit-description") + .html(new_desc.replace(/\n/g, "<br />")); + $(".vm-details-home-edit-description-click").show(); + $("#vm-details-home-description").hide(); + // update the textareia + $("vm-details-home-description textarea").text(data['new_description']); + }, + error: function(xhr, textStatus, error) { + addMessage("Error during renaming!", "danger"); + } + }); + return false; + }); + }); diff --git a/circle/dashboard/templates/dashboard/vm-detail.html b/circle/dashboard/templates/dashboard/vm-detail.html index 2bcdcbd..e36dfbd 100644 --- a/circle/dashboard/templates/dashboard/vm-detail.html +++ b/circle/dashboard/templates/dashboard/vm-detail.html @@ -56,14 +56,18 @@ <a title="{% trans "Help" %}" href="#" class="btn btn-default btn-xs vm-details-help-button"><i class="icon-question"></i></a> </div> <h1> - <div id="vm-details-rename"> + <div id="vm-details-rename" class="vm-details-home-rename-form-div"> <form action="" method="POST" id="vm-details-rename-form"> {% csrf_token %} - <input id="vm-details-rename-name" class="form-control" name="new_name" type="text" value="{{ instance.name }}"/> - <button type="submit" id="vm-details-rename-submit" class="btn">{% trans "Rename" %}</button> + <div class="input-group vm-details-home-name"> + <input id="vm-details-rename-name" class="form-control input-sm" name="new_name" type="text" value="{{ instance.name }}"/> + <span class="input-group-btn"> + <button type="submit" class="btn btn-sm vm-details-rename-submit">{% trans "Rename" %}</button> + </span> + </div> </form> </div> - <div id="vm-details-h1-name"> + <div id="vm-details-h1-name" class="vm-details-home-edit-name"> {{ instance.name }} </div> <small>{{ instance.primary_host.get_fqdn }}</small> diff --git a/circle/dashboard/templates/dashboard/vm-detail/home.html b/circle/dashboard/templates/dashboard/vm-detail/home.html index c5a33cc..9294d92 100644 --- a/circle/dashboard/templates/dashboard/vm-detail/home.html +++ b/circle/dashboard/templates/dashboard/vm-detail/home.html @@ -4,8 +4,46 @@ <dl> <dt>{% trans "System" %}:</dt> <dd><i class="icon-{{ os_type_icon }}"></i> {{ instance.system }}</dd> - <dt style="margin-top: 5px;">{% trans "Description" %}:</dt> - <dd><small>{{ instance.description }}</small></dd> + <dt style="margin-top: 5px;"> + {% trans "Name" %}: + <a href="#" class="vm-details-home-edit-name-click"><i class="icon-pencil"></i></a> + </dt> + <dd> + <div class="vm-details-home-edit-name-click"> + <small class="vm-details-home-edit-name">{{ instance.name }}</small> + </div> + <div class="js-hidden vm-details-home-rename-form-div" id="vm-details-home-rename"> + <form method="POST"> + {% csrf_token %} + <div class="input-group"> + <input type="text" name="new_name" value="{{ instance.name }}" class="form-control input-sm"/> + <span class="input-group-btn"> + <button type="submit" class="btn btn-success btn-sm vm-details-rename-submit"> + <i class="icon-pencil"></i> {% trans "Rename" %} + </button> + </span> + </div> + </form> + </div> + </dd> + <dt style="margin-top: 5px;"> + {% trans "Description" %}: + <a href="#" class="vm-details-home-edit-description-click"><i class="icon-pencil"></i></a> + </dt> + <dd> + {% csrf_token %} + <div class="vm-details-home-edit-description-click"> + <small class="vm-details-home-edit-description">{{ instance.description|linebreaks }}</small> + </div> + <div id="vm-details-home-description" class="js-hidden"> + <form method="POST"> + <textarea name="new_description" class="form-control">{{ instance.description }}</textarea> + <button type="submit" class="btn btn-xs btn-success vm-details-description-submit"> + <i class="icon-pencil"></i> {% trans "Update" %} + </button> + </form> + </div> + </dd> </dl> <h4>{% trans "Expiration" %} {% if instance.is_expiring %}<i class="icon-warning-sign text-danger"></i>{% endif %} diff --git a/circle/dashboard/views.py b/circle/dashboard/views.py index 4ea2b0c..e612cac 100644 --- a/circle/dashboard/views.py +++ b/circle/dashboard/views.py @@ -238,6 +238,7 @@ class VmDetailView(CheckedDetailView): options = { 'change_password': self.__change_password, 'new_name': self.__set_name, + 'new_description': self.__set_description, 'new_tag': self.__add_tag, 'to_remove': self.__remove_tag, 'port': self.__add_port, @@ -316,8 +317,30 @@ class VmDetailView(CheckedDetailView): ) else: messages.success(request, success_message) - return redirect(reverse_lazy("dashboard.views.detail", - kwargs={'pk': self.object.pk})) + return redirect(self.object.get_absolute_url()) + + def __set_description(self, request): + self.object = self.get_object() + if not self.object.has_level(request.user, 'owner'): + raise PermissionDenied() + + new_description = request.POST.get("new_description") + Instance.objects.filter(pk=self.object.pk).update( + **{'description': new_description}) + + success_message = _("VM description successfully updated!") + if request.is_ajax(): + response = { + 'message': success_message, + 'new_description': new_description, + } + return HttpResponse( + json.dumps(response), + content_type="application/json" + ) + else: + messages.success(request, success_message) + return redirect(self.object.get_absolute_url()) def __add_tag(self, request): new_tag = request.POST.get('new_tag')