Commit d3b23cb1 by Kálmán Viktor
parents 6116fd30 87cf344b
/* ===========================================================
# bootstrap-tour - v0.9.1
# http://bootstraptour.com
# ==============================================================
# Copyright 2012-2013 Ulrich Sossou
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
*/
.tour-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1100;background-color:#000;opacity:.8}.tour-step-backdrop{position:relative;z-index:1101;background:inherit}.tour-step-background{position:absolute;z-index:1100;background:inherit;border-radius:6px}.popover[class*=tour-]{z-index:1100}.popover[class*=tour-] .popover-navigation{padding:9px 14px}.popover[class*=tour-] .popover-navigation [data-role=end]{float:right}.popover[class*=tour-] .popover-navigation [data-role=prev],.popover[class*=tour-] .popover-navigation [data-role=next],.popover[class*=tour-] .popover-navigation [data-role=end]{cursor:pointer}.popover[class*=tour-] .popover-navigation [data-role=prev].disabled,.popover[class*=tour-] .popover-navigation [data-role=next].disabled,.popover[class*=tour-] .popover-navigation [data-role=end].disabled{cursor:default}.popover[class*=tour-].orphan{position:fixed;margin-top:0}.popover[class*=tour-].orphan .arrow{display:none}
\ No newline at end of file
...@@ -688,7 +688,7 @@ textarea[name="new_members"] { ...@@ -688,7 +688,7 @@ textarea[name="new_members"] {
.dashboard-vm-details-connect-command { .dashboard-vm-details-connect-command {
/* for mobile view */ /* for mobile view */
margin-bottom: 20px; padding-bottom: 20px;
} }
#store-list-list { #store-list-list {
...@@ -961,6 +961,14 @@ textarea[name="new_members"] { ...@@ -961,6 +961,14 @@ textarea[name="new_members"] {
cursor: pointer cursor: pointer
} }
#vm-details-resources-disk {
padding: 2px 5px 10px 5px;
}
#vm-details-start-template-tour {
margin-right: 5px;
}
#vm-activity-state { #vm-activity-state {
margin-bottom: 15px; margin-bottom: 15px;
} }
...@@ -974,6 +982,24 @@ textarea[name="new_members"] { ...@@ -974,6 +982,24 @@ textarea[name="new_members"] {
color: orange; color: orange;
} }
.introjs-skipbutton {
color: #333;
}
.introjs-button:focus {
text-decoration: none;
color: #333;
outline: none;
}
.introjs-button:hover:not(.introjs-disabled) {
color: #428bca;
}
.introjs-tooltip {
min-width: 250px;
}
#vm-info-pane { #vm-info-pane {
margin-bottom: 20px; margin-bottom: 20px;
} }
......
.introjs-overlay{position:absolute;z-index:999999;background-color:#000;opacity:0;background:-moz-radial-gradient(center,ellipse cover,rgba(0,0,0,0.4) 0,rgba(0,0,0,0.9) 100%);background:-webkit-gradient(radial,center center,0px,center center,100%,color-stop(0%,rgba(0,0,0,0.4)),color-stop(100%,rgba(0,0,0,0.9)));background:-webkit-radial-gradient(center,ellipse cover,rgba(0,0,0,0.4) 0,rgba(0,0,0,0.9) 100%);background:-o-radial-gradient(center,ellipse cover,rgba(0,0,0,0.4) 0,rgba(0,0,0,0.9) 100%);background:-ms-radial-gradient(center,ellipse cover,rgba(0,0,0,0.4) 0,rgba(0,0,0,0.9) 100%);background:radial-gradient(center,ellipse cover,rgba(0,0,0,0.4) 0,rgba(0,0,0,0.9) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#66000000',endColorstr='#e6000000',GradientType=1);-ms-filter:"alpha(opacity=50)";filter:alpha(opacity=50);-webkit-transition:all .3s ease-out;-moz-transition:all .3s ease-out;-ms-transition:all .3s ease-out;-o-transition:all .3s ease-out;transition:all .3s ease-out}.introjs-fixParent{z-index:auto !important;opacity:1.0 !important}.introjs-showElement,tr.introjs-showElement>td,tr.introjs-showElement>th{z-index:9999999 !important}.introjs-relativePosition,tr.introjs-showElement>td,tr.introjs-showElement>th{position:relative}.introjs-helperLayer{position:absolute;z-index:9999998;background-color:#FFF;background-color:rgba(255,255,255,.9);border:1px solid #777;border:1px solid rgba(0,0,0,.5);border-radius:4px;box-shadow:0 2px 15px rgba(0,0,0,.4);-webkit-transition:all .3s ease-out;-moz-transition:all .3s ease-out;-ms-transition:all .3s ease-out;-o-transition:all .3s ease-out;transition:all .3s ease-out}.introjs-helperNumberLayer{position:absolute;top:-16px;left:-16px;z-index:9999999999 !important;padding:2px;font-family:Arial,verdana,tahoma;font-size:13px;font-weight:bold;color:white;text-align:center;text-shadow:1px 1px 1px rgba(0,0,0,.3);background:#ff3019;background:-webkit-linear-gradient(top,#ff3019 0,#cf0404 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0%,#ff3019),color-stop(100%,#cf0404));background:-moz-linear-gradient(top,#ff3019 0,#cf0404 100%);background:-ms-linear-gradient(top,#ff3019 0,#cf0404 100%);background:-o-linear-gradient(top,#ff3019 0,#cf0404 100%);background:linear-gradient(to bottom,#ff3019 0,#cf0404 100%);width:20px;height:20px;line-height:20px;border:3px solid white;border-radius:50%;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3019',endColorstr='#cf0404',GradientType=0);filter:progid:DXImageTransform.Microsoft.Shadow(direction=135,strength=2,color=ff0000);box-shadow:0 2px 5px rgba(0,0,0,.4)}.introjs-arrow{border:5px solid white;content:'';position:absolute}.introjs-arrow.top{top:-10px;border-top-color:transparent;border-right-color:transparent;border-bottom-color:white;border-left-color:transparent}.introjs-arrow.top-right{top:-10px;right:10px;border-top-color:transparent;border-right-color:transparent;border-bottom-color:white;border-left-color:transparent}.introjs-arrow.top-middle{top:-10px;left:50%;margin-left:-5px;border-top-color:transparent;border-right-color:transparent;border-bottom-color:white;border-left-color:transparent}.introjs-arrow.right{right:-10px;top:10px;border-top-color:transparent;border-right-color:transparent;border-bottom-color:transparent;border-left-color:white}.introjs-arrow.bottom{bottom:-10px;border-top-color:white;border-right-color:transparent;border-bottom-color:transparent;border-left-color:transparent}.introjs-arrow.left{left:-10px;top:10px;border-top-color:transparent;border-right-color:white;border-bottom-color:transparent;border-left-color:transparent}.introjs-tooltip{position:absolute;padding:10px;background-color:white;min-width:200px;max-width:300px;border-radius:3px;box-shadow:0 1px 10px rgba(0,0,0,.4);-webkit-transition:opacity .1s ease-out;-moz-transition:opacity .1s ease-out;-ms-transition:opacity .1s ease-out;-o-transition:opacity .1s ease-out;transition:opacity .1s ease-out}.introjs-tooltipbuttons{text-align:right}.introjs-button{position:relative;overflow:visible;display:inline-block;padding:.3em .8em;border:1px solid #d4d4d4;margin:0;text-decoration:none;text-shadow:1px 1px 0 #fff;font:11px/normal sans-serif;color:#333;white-space:nowrap;cursor:pointer;outline:0;background-color:#ececec;background-image:-webkit-gradient(linear,0 0,0 100%,from(#f4f4f4),to(#ececec));background-image:-moz-linear-gradient(#f4f4f4,#ececec);background-image:-o-linear-gradient(#f4f4f4,#ececec);background-image:linear-gradient(#f4f4f4,#ececec);-webkit-background-clip:padding;-moz-background-clip:padding;-o-background-clip:padding-box;-webkit-border-radius:.2em;-moz-border-radius:.2em;border-radius:.2em;zoom:1;*display:inline;margin-top:10px}.introjs-button:hover{border-color:#bcbcbc;text-decoration:none;box-shadow:0 1px 1px #e3e3e3}.introjs-button:focus,.introjs-button:active{background-image:-webkit-gradient(linear,0 0,0 100%,from(#ececec),to(#f4f4f4));background-image:-moz-linear-gradient(#ececec,#f4f4f4);background-image:-o-linear-gradient(#ececec,#f4f4f4);background-image:linear-gradient(#ececec,#f4f4f4)}.introjs-button::-moz-focus-inner{padding:0;border:0}.introjs-skipbutton{margin-right:5px;color:#7a7a7a}.introjs-prevbutton{-webkit-border-radius:.2em 0 0 .2em;-moz-border-radius:.2em 0 0 .2em;border-radius:.2em 0 0 .2em;border-right:0}.introjs-nextbutton{-webkit-border-radius:0 .2em .2em 0;-moz-border-radius:0 .2em .2em 0;border-radius:0 .2em .2em 0}.introjs-disabled,.introjs-disabled:hover,.introjs-disabled:focus{color:#9a9a9a;border-color:#d4d4d4;box-shadow:none;cursor:default;background-color:#f4f4f4;background-image:none;text-decoration:none}.introjs-bullets{text-align:center}.introjs-bullets ul{clear:both;margin:15px auto 0;padding:0;display:inline-block}.introjs-bullets ul li{list-style:none;float:left;margin:0 2px}.introjs-bullets ul li a{display:block;width:6px;height:6px;background:#ccc;border-radius:10px;-moz-border-radius:10px;-webkit-border-radius:10px;text-decoration:none}.introjs-bullets ul li a:hover{background:#999}.introjs-bullets ul li a.active{background:#999}.introjsFloatingElement{position:absolute;height:0;width:0;left:50%;top:50%}
.introjs-helperLayer *,
.introjs-helperLayer *:before,
.introjs-helperLayer *:after {
-webkit-box-sizing: content-box;
-moz-box-sizing: content-box;
-ms-box-sizing: content-box;
-o-box-sizing: content-box;
box-sizing: content-box;
}
...@@ -19,7 +19,7 @@ $(function() { ...@@ -19,7 +19,7 @@ $(function() {
$('#vm-migrate-node-list li input:checked').closest('li').addClass('panel-primary'); $('#vm-migrate-node-list li input:checked').closest('li').addClass('panel-primary');
} }
}); });
return false; e.preventDefault();
}); });
/* if the operation fails show the modal again */ /* if the operation fails show the modal again */
......
...@@ -28,7 +28,7 @@ $(function() { ...@@ -28,7 +28,7 @@ $(function() {
}); });
/* save resources */ /* save resources */
$('#vm-details-resources-save').click(function() { $('#vm-details-resources-save').click(function(e) {
var error = false; var error = false;
$(".cpu-count-input, .ram-input").each(function() { $(".cpu-count-input, .ram-input").each(function() {
if(!$(this)[0].checkValidity()) { if(!$(this)[0].checkValidity()) {
...@@ -61,7 +61,7 @@ $(function() { ...@@ -61,7 +61,7 @@ $(function() {
} }
} }
}); });
return false; e.preventDefault();
}); });
/* remove tag */ /* remove tag */
...@@ -205,11 +205,11 @@ $(function() { ...@@ -205,11 +205,11 @@ $(function() {
}); });
/* rename in home tab */ /* rename in home tab */
$(".vm-details-home-edit-name-click").click(function() { $(".vm-details-home-edit-name-click").click(function(e) {
$(".vm-details-home-edit-name-click").hide(); $(".vm-details-home-edit-name-click").hide();
$("#vm-details-home-rename").show(); $("#vm-details-home-rename").show();
$("input", $("#vm-details-home-rename")).select(); $("input", $("#vm-details-home-rename")).select();
return false; e.preventDefault();
}); });
/* rename ajax */ /* rename ajax */
...@@ -236,7 +236,7 @@ $(function() { ...@@ -236,7 +236,7 @@ $(function() {
}); });
/* update description click */ /* update description click */
$(".vm-details-home-edit-description-click").click(function() { $(".vm-details-home-edit-description-click").click(function(e) {
$(".vm-details-home-edit-description-click").hide(); $(".vm-details-home-edit-description-click").hide();
$("#vm-details-home-description").show(); $("#vm-details-home-description").show();
var ta = $("#vm-details-home-description textarea"); var ta = $("#vm-details-home-description textarea");
...@@ -244,7 +244,7 @@ $(function() { ...@@ -244,7 +244,7 @@ $(function() {
ta.val(""); ta.val("");
ta.focus(); ta.focus();
ta.val(tmp) ta.val(tmp)
return false; e.preventDefault();
}); });
/* description update ajax */ /* description update ajax */
...@@ -316,6 +316,24 @@ $(function() { ...@@ -316,6 +316,24 @@ $(function() {
if(Boolean($(this).data("disabled"))) return false; if(Boolean($(this).data("disabled"))) return false;
}); });
$("#dashboard-tutorial-toggle").click(function() {
var box = $("#alert-new-template");
var list = box.find("ol")
list.stop().slideToggle(function() {
var url = box.find("form").prop("action");
var hidden = list.css("display") === "none";
box.find("button i").prop("class", "fa fa-caret-" + (hidden ? "down" : "up"));
$.ajax({
type: 'POST',
url: url,
data: {'hidden': hidden},
headers: {"X-CSRFToken": getCookie('csrftoken')},
success: function(re, textStatus, xhr) {}
});
});
return false;
});
}); });
...@@ -344,9 +362,6 @@ function decideActivityRefresh() { ...@@ -344,9 +362,6 @@ function decideActivityRefresh() {
/* if something is still spinning */ /* if something is still spinning */
if($('.timeline .activity i').hasClass('fa-spin')) if($('.timeline .activity i').hasClass('fa-spin'))
check = true; check = true;
/* if there is only one activity */
if($('#activity-timeline div[class="activity"]').length < 2)
check = true;
return check; return check;
} }
...@@ -377,6 +392,7 @@ function checkNewActivity(runs) { ...@@ -377,6 +392,7 @@ function checkNewActivity(runs) {
} else { } else {
icon.prop("class", "fa " + data['icon']); icon.prop("class", "fa " + data['icon']);
} }
$("#vm-details-state").data("status", data['status']);
$("#vm-details-state span").html(data['human_readable_status'].toUpperCase()); $("#vm-details-state span").html(data['human_readable_status'].toUpperCase());
if(data['status'] == "RUNNING") { if(data['status'] == "RUNNING") {
if(data['connect_uri']) { if(data['connect_uri']) {
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
{% block extra_link %} {% block extra_link %}
<link rel="stylesheet" href="{{ STATIC_URL }}dashboard/loopj-jquery-simple-slider/css/simple-slider.css"/> <link rel="stylesheet" href="{{ STATIC_URL }}dashboard/loopj-jquery-simple-slider/css/simple-slider.css"/>
<link href="{{ STATIC_URL }}dashboard/bootstrap-tour.min.css" rel="stylesheet"> <link rel="stylesheet" href="{{ STATIC_URL }}dashboard/introjs/introjs.min.css">
<link href="{{ STATIC_URL }}dashboard/dashboard.css" rel="stylesheet"> <link href="{{ STATIC_URL }}dashboard/dashboard.css" rel="stylesheet">
{% endblock %} {% endblock %}
......
...@@ -6,14 +6,25 @@ ...@@ -6,14 +6,25 @@
{% block content %} {% block content %}
{% if instance.is_base %} {% if instance.is_base %}
<div class="alert alert-info alert-new-template"> <div class="alert alert-info alert-new-template" id="alert-new-template" style="position: relative;">
<strong>{% trans "This is the master vm of your new template" %}</strong> <form action="{% url "dashboard.views.vm-toggle-tutorial" pk=instance.pk %}"
<div id="vm-details-template-tour-button" class="pull-right"> method="POST">
<a href="#" class="btn btn-default btn-lg pull-right vm-details-start-template-tour"> {% csrf_token %}
<input name="hidden" type="hidden"
value="{{ hide_tutorial|yesno:"false,true" }}"/>
<button type="submit"
id="dashboard-tutorial-toggle" class="btn btn-sm pull-right btn-success">
<i class="fa fa-caret-{% if hide_tutorial %}down{% else %}up{% endif %}"></i>
{% trans "Toggle tutorial panel" %}
</button>
<a href="#" class="btn btn-default btn-sm pull-right"
id="vm-details-start-template-tour">
<i class="fa fa-play"></i> {% trans "Start template tutorial" %} <i class="fa fa-play"></i> {% trans "Start template tutorial" %}
</a> </a>
</div> </form>
<ol> <strong>{% trans "This is the master vm of your new template" %}</strong>
<ol {% if hide_tutorial %}style="display: none;"{% endif %}>
<li>{% trans "Modify the virtual machine to suit your needs <strong>(optional)</strong>" %} <li>{% trans "Modify the virtual machine to suit your needs <strong>(optional)</strong>" %}
<ul> <ul>
<li>{% trans "Change the description" %}</li> <li>{% trans "Change the description" %}</li>
...@@ -65,7 +76,7 @@ ...@@ -65,7 +76,7 @@
<div class="row"> <div class="row">
<div class="col-md-4" id="vm-info-pane"> <div class="col-md-4" id="vm-info-pane">
<div class="big"> <div class="big">
<span id="vm-details-state" class="label label-success"> <span id="vm-details-state" class="label label-success" data-status="{{ instance.status }}">
<i class="fa <i class="fa
{% if is_new_state %} {% if is_new_state %}
fa-spinner fa-spin fa-spinner fa-spin
...@@ -202,7 +213,7 @@ ...@@ -202,7 +213,7 @@
{% endblock %} {% endblock %}
{% block extra_js %} {% block extra_js %}
<script src="{{ STATIC_URL }}dashboard/bootstrap-tour.min.js"></script> <script src="{{ STATIC_URL }}dashboard/introjs/intro.min.js"></script>
<script src="{{ STATIC_URL }}dashboard/vm-details.js"></script> <script src="{{ STATIC_URL }}dashboard/vm-details.js"></script>
<script src="{{ STATIC_URL }}dashboard/vm-common.js"></script> <script src="{{ STATIC_URL }}dashboard/vm-common.js"></script>
<script src="{{ STATIC_URL }}dashboard/vm-console.js"></script> <script src="{{ STATIC_URL }}dashboard/vm-console.js"></script>
......
{% load i18n %} {% load i18n %}
<div class="row"> <div class="row">
<div class="col-md-4"> <div class="col-md-4">
<dl> <dl id="home_name_and_description">
<dt>{% trans "System" %}:</dt> <dt>{% trans "System" %}:</dt>
<dd><i class="fa fa-{{ os_type_icon }}"></i> {{ instance.system }}</dd> <dd><i class="fa fa-{{ os_type_icon }}"></i> {{ instance.system }}</dd>
<dt style="margin-top: 5px;"> <dt style="margin-top: 5px;">
...@@ -52,7 +52,10 @@ ...@@ -52,7 +52,10 @@
</dd> </dd>
</dl> </dl>
<h4>{% trans "Expiration" %} {% if instance.is_expiring %}<i class="fa fa-warning-sign text-danger"></i>{% endif %} <div id="home_expiration_and_lease">
<h4>
{% trans "Expiration" %}
{% if instance.is_expiring %}<i class="fa fa-warning-sign text-danger"></i>{% endif %}
<span id="vm-details-renew-op"> <span id="vm-details-renew-op">
{% with op=op.renew %}{% if op %} {% with op=op.renew %}{% if op %}
<a href="{{op.get_url}}" class="btn btn-success btn-xs <a href="{{op.get_url}}" class="btn btn-success btn-xs
...@@ -76,6 +79,7 @@ ...@@ -76,6 +79,7 @@
</span> </span>
</dd> </dd>
</dl> </dl>
</div>
<div style="font-weight: bold;">{% trans "Tags" %}</div> <div style="font-weight: bold;">{% trans "Tags" %}</div>
<div id="vm-details-tags" style="margin-bottom: 20px;"> <div id="vm-details-tags" style="margin-bottom: 20px;">
......
...@@ -18,12 +18,9 @@ ...@@ -18,12 +18,9 @@
{% endif %} {% endif %}
</form> </form>
<hr /> <hr />
<div id="vm-details-resources-disk">
<div class="row" id="vm-details-resources-disk">
<div class="col-sm-11">
<h3> <h3>
{% trans "Disks" %} {% trans "Disks" %}
<div class="pull-right"> <div class="pull-right">
...@@ -33,10 +30,8 @@ ...@@ -33,10 +30,8 @@
</div> </div>
</h3> </h3>
<div class="row" id="vm-details-disk-add-for-form"></div>
{% if not instance.disks.all %} {% if not instance.disks.all %}
{% trans "No disks are added!" %} {% trans "No disks are added." %}
{% endif %} {% endif %}
{% for d in instance.disks.all %} {% for d in instance.disks.all %}
<h4 class="list-group-item-heading dashboard-vm-details-network-h3"> <h4 class="list-group-item-heading dashboard-vm-details-network-h3">
...@@ -45,7 +40,6 @@ ...@@ -45,7 +40,6 @@
{% endwith %} {% endwith %}
</h4> </h4>
{% endfor %} {% endfor %}
</div>
</div> </div>
{% if user.is_superuser %} {% if user.is_superuser %}
......
...@@ -45,6 +45,7 @@ from .views import ( ...@@ -45,6 +45,7 @@ from .views import (
VmTraitsUpdate, VmRawDataUpdate, VmTraitsUpdate, VmRawDataUpdate,
GroupPermissionsView, GroupPermissionsView,
LeaseAclUpdateView, LeaseAclUpdateView,
toggle_template_tutorial,
ClientCheck, TokenLogin, ClientCheck, TokenLogin,
VmGraphView, NodeGraphView, NodeListGraphView, VmGraphView, NodeGraphView, NodeListGraphView,
) )
...@@ -99,6 +100,8 @@ urlpatterns = patterns( ...@@ -99,6 +100,8 @@ urlpatterns = patterns(
name='dashboard.views.vm-traits'), name='dashboard.views.vm-traits'),
url(r'^vm/(?P<pk>\d+)/raw_data/$', VmRawDataUpdate.as_view(), url(r'^vm/(?P<pk>\d+)/raw_data/$', VmRawDataUpdate.as_view(),
name='dashboard.views.vm-raw-data'), name='dashboard.views.vm-raw-data'),
url(r'^vm/(?P<pk>\d+)/toggle_tutorial/$', toggle_template_tutorial,
name='dashboard.views.vm-toggle-tutorial'),
url(r'^node/list/$', NodeList.as_view(), name='dashboard.views.node-list'), url(r'^node/list/$', NodeList.as_view(), name='dashboard.views.node-list'),
url(r'^node/(?P<pk>\d+)/$', NodeDetailView.as_view(), url(r'^node/(?P<pk>\d+)/$', NodeDetailView.as_view(),
......
...@@ -24,6 +24,7 @@ from os import getenv ...@@ -24,6 +24,7 @@ from os import getenv
from django.conf import settings from django.conf import settings
from django.contrib import messages from django.contrib import messages
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.contrib.auth.decorators import login_required
from django.core import signing from django.core import signing
from django.core.exceptions import PermissionDenied, SuspiciousOperation from django.core.exceptions import PermissionDenied, SuspiciousOperation
from django.core.urlresolvers import reverse, reverse_lazy from django.core.urlresolvers import reverse, reverse_lazy
...@@ -102,13 +103,16 @@ class VmDetailView(GraphMixin, CheckedDetailView): ...@@ -102,13 +103,16 @@ class VmDetailView(GraphMixin, CheckedDetailView):
is_operator = instance.has_level(user, "operator") is_operator = instance.has_level(user, "operator")
is_owner = instance.has_level(user, "owner") is_owner = instance.has_level(user, "owner")
ops = get_operations(instance, user) ops = get_operations(instance, user)
hide_tutorial = self.request.COOKIES.get(
"hide_tutorial_for_%s" % instance.pk) == "True"
context.update({ context.update({
'graphite_enabled': settings.GRAPHITE_URL is not None, 'graphite_enabled': settings.GRAPHITE_URL is not None,
'vnc_url': reverse_lazy("dashboard.views.detail-vnc", 'vnc_url': reverse_lazy("dashboard.views.detail-vnc",
kwargs={'pk': self.object.pk}), kwargs={'pk': self.object.pk}),
'ops': ops, 'ops': ops,
'op': {i.op: i for i in ops}, 'op': {i.op: i for i in ops},
'connect_commands': user.profile.get_connect_commands(instance) 'connect_commands': user.profile.get_connect_commands(instance),
'hide_tutorial': hide_tutorial,
}) })
# activity data # activity data
...@@ -1435,3 +1439,13 @@ class TransferOwnershipConfirmView(LoginRequiredMixin, View): ...@@ -1435,3 +1439,13 @@ class TransferOwnershipConfirmView(LoginRequiredMixin, View):
unicode(user), user.pk, new_owner, key) unicode(user), user.pk, new_owner, key)
raise PermissionDenied() raise PermissionDenied()
return (instance, new_owner) return (instance, new_owner)
@login_required
def toggle_template_tutorial(request, pk):
hidden = request.POST.get("hidden", "").lower() == "true"
instance = get_object_or_404(Instance, pk=pk)
response = HttpResponseRedirect(instance.get_absolute_url())
response.set_cookie( # for a week
"hide_tutorial_for_%s" % pk, hidden, 7 * 24 * 60 * 60)
return response
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 sign in to comment