Commit 4833c479 by Kálmán Viktor

Merge branch 'feature-stacked-activites' into 'master'

Feature Stacked Activites

Closes  #141
parents 695cd9bd e6a26476
...@@ -328,6 +328,17 @@ function decideActivityRefresh() { ...@@ -328,6 +328,17 @@ function decideActivityRefresh() {
return check; return check;
} }
/* unescapes html got via the request, also removes whitespaces and replaces all ' with " */
function unescapeHTML(html) {
return html.replace(/&lt;/g,'<').replace(/&gt;/g,'>').replace(/&amp;/g,'&').replace(/&ndash;/g, "–").replace(/\//g, "").replace(/'/g, '"').replace(/ /g, '');
}
/* the html page contains some tags that were modified via js (titles for example), we delete these
also some html tags are closed with / */
function changeHTML(html) {
return html.replace(/data-original-title/g, "title").replace(/title=""/g, "").replace(/\//g, '').replace(/ /g, '');
}
function checkNewActivity(only_status, runs) { function checkNewActivity(only_status, runs) {
// set default only_status to false // set default only_status to false
only_status = typeof only_status !== 'undefined' ? only_status : false; only_status = typeof only_status !== 'undefined' ? only_status : false;
...@@ -339,7 +350,10 @@ function checkNewActivity(only_status, runs) { ...@@ -339,7 +350,10 @@ function checkNewActivity(only_status, runs) {
data: {'only_status': only_status}, data: {'only_status': only_status},
success: function(data) { success: function(data) {
if(!only_status) { if(!only_status) {
$("#activity-timeline").html(data['activities']); a = unescapeHTML(data['activities']);
b = changeHTML($("#activity-timeline").html());
if(a != b)
$("#activity-timeline").html(data['activities']);
$("#ops").html(data['ops']); $("#ops").html(data['ops']);
$("#disk-ops").html(data['disk_ops']); $("#disk-ops").html(data['disk_ops']);
$("[title]").tooltip(); $("[title]").tooltip();
......
...@@ -6,16 +6,18 @@ ...@@ -6,16 +6,18 @@
</span> </span>
<strong{% if user.is_superuser and a.result %} title="{{ a.result }}"{% endif %}> <strong{% if user.is_superuser and a.result %} title="{{ a.result }}"{% endif %}>
{% if user.is_superuser %}<a href="{{ a.get_absolute_url }}">{% endif %} {% if user.is_superuser %}<a href="{{ a.get_absolute_url }}">{% endif %}
{% if a.times > 1 %}({{ a.times }}x){% endif %}
{{ a.get_readable_name }}{% if user.is_superuser %}</a>{% endif %} {{ a.get_readable_name }}{% if user.is_superuser %}</a>{% endif %}
{% if a.has_percent %}
- {{ a.percentage }}%
{% endif %}
</strong> </strong>
{{ a.started|date:"Y-m-d H:i" }}{% if a.user %}, {% if a.times < 2%}{{ a.started|date:"Y-m-d H:i" }}{% endif %}{% if a.user %},
<a class="no-style-link" href="{% url "dashboard.views.profile" username=a.user.username %}"> <a class="no-style-link" href="{% url "dashboard.views.profile" username=a.user.username %}">
{% include "dashboard/_display-name.html" with user=a.user show_org=True %} {% include "dashboard/_display-name.html" with user=a.user show_org=True %}
</a> </a>
{% endif %} {% endif %}
{% if a.has_percent %}
{{ a.percentage }}%
{% endif %}
{% if a.is_abortable_for_user %} {% if a.is_abortable_for_user %}
<form action="{{ a.instance.get_absolute_url }}" method="POST" class="pull-right"> <form action="{{ a.instance.get_absolute_url }}" method="POST" class="pull-right">
{% csrf_token %} {% csrf_token %}
......
...@@ -272,7 +272,8 @@ class VmDetailView(CheckedDetailView): ...@@ -272,7 +272,8 @@ class VmDetailView(CheckedDetailView):
}) })
# activity data # activity data
context['activities'] = self.object.get_activities(self.request.user) context['activities'] = self.object.get_merged_activities(
self.request.user)
context['vlans'] = Vlan.get_objects_with_level( context['vlans'] = Vlan.get_objects_with_level(
'user', self.request.user 'user', self.request.user
...@@ -2115,7 +2116,7 @@ class LeaseDelete(LoginRequiredMixin, SuperuserRequiredMixin, DeleteView): ...@@ -2115,7 +2116,7 @@ class LeaseDelete(LoginRequiredMixin, SuperuserRequiredMixin, DeleteView):
@require_GET @require_GET
def vm_activity(request, pk): def vm_activity(request, pk):
instance = Instance.objects.get(pk=pk) instance = Instance.objects.get(pk=pk)
if not instance.has_level(request.user, 'owner'): if not instance.has_level(request.user, 'user'):
raise PermissionDenied() raise PermissionDenied()
response = {} response = {}
...@@ -2127,7 +2128,7 @@ def vm_activity(request, pk): ...@@ -2127,7 +2128,7 @@ def vm_activity(request, pk):
if only_status == "false": # instance activity if only_status == "false": # instance activity
context = { context = {
'instance': instance, 'instance': instance,
'activities': instance.get_activities(request.user), 'activities': instance.get_merged_activities(request.user),
'ops': get_operations(instance, request.user), 'ops': get_operations(instance, request.user),
} }
......
...@@ -927,6 +927,27 @@ class Instance(AclBase, VirtualMachineDescModel, StatusModel, OperatedMixin, ...@@ -927,6 +927,27 @@ class Instance(AclBase, VirtualMachineDescModel, StatusModel, OperatedMixin,
user=user) user=user)
return acts return acts
def get_merged_activities(self, user=None):
whitelist = ("create_disk", "download_disk")
acts = self.get_activities(user)
merged_acts = []
latest = None
for a in acts:
if (latest == a.activity_code and
merged_acts[-1].result == a.result and
a.finished and merged_acts[-1].finished and
a.user == merged_acts[-1].user and
(merged_acts[-1].finished - a.finished).days < 7 and
not a.activity_code.endswith(whitelist)):
merged_acts[-1].times += 1
else:
merged_acts.append(a)
merged_acts[-1].times = 1
latest = a.activity_code
return merged_acts
def get_screenshot(self, timeout=5): def get_screenshot(self, timeout=5):
queue_name = self.get_remote_queue_name('vm') queue_name = self.get_remote_queue_name('vm')
return vm_tasks.screenshot.apply_async(args=[self.vm_name], return vm_tasks.screenshot.apply_async(args=[self.vm_name],
......
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