All new accounts created on Gitlab now require administrator approval. If you invite any collaborators, please let Flux staff know so they can approve the accounts.

Commit c1b6cfdd authored by Leigh B Stoller's avatar Leigh B Stoller

Add a new popup modal for each reservation; show current and recent

usage in the project for the reserved node type. Work in progress.
parent 917356df
......@@ -86,6 +86,7 @@ use libtestbed;
use WebTask;
use APT_Geni;
use APT_Aggregate;
use APT_Instance;
use GeniResponse;
use GeniUser;
......@@ -451,6 +452,9 @@ sub DoList()
fatal($response->output());
}
my $list = $response->value()->{'reservations'};
my $history = $response->value()->{'history'}
if (exists($response->value()->{'history'}));
#
# Map remote URNs to local projects and users. Not all of them can
# be mapped of course, we leave those as is.
......@@ -477,6 +481,34 @@ sub DoList()
else {
$details->{'pid'} = $projhrn->id();
}
#
# If we have the history, then go through and map the
# experiments to local experiments so we can link to them in
# the web interface.
#
if (exists($history->{$projhrn})) {
foreach my $ref (@{ $history->{$projhrn} }) {
#print Dumper($ref);
# Local experiment on the remote cluster.
next
if (!(exists($ref->{'urn'}) && exists($ref->{'slice_uuid'})));
# Already processed.
next
if (exists($ref->{'instance_uuid'}));
my $hrn = GeniHRN->new($ref->{'urn'});
if (defined($hrn) &&
$hrn->domain() eq $OURDOMAIN && defined($hrn->project())) {
my $instance = APT_Instance->LookupBySlice($hrn);
if (defined($instance) &&
$instance->slice_uuid() eq $ref->{'slice_uuid'}) {
$ref->{'instance_uuid'} = $instance->uuid();
}
}
}
}
}
#
# Strip out unwanted results if we asked as an admin for a specific
......@@ -487,16 +519,25 @@ sub DoList()
foreach my $key (keys(%$list)) {
my $details = $list->{$key};
my $projhrn = $details->{'project'};
if (defined($project)) {
next
if (!defined($details->{'pid_idx'}) ||
$details->{'pid_idx'} != $project->pid_idx());
if (!defined($details->{'pid_idx'}) ||
$details->{'pid_idx'} != $project->pid_idx()) {
# Kill the history entry when skipping.
delete($history->{$projhrn})
if (defined($history) && exists($history->{$projhrn}));
next
}
}
else {
next
if (!defined($details->{'uid_idx'}) ||
$details->{'uid_idx'} != $user->uid_idx());
if (!defined($details->{'uid_idx'}) ||
$details->{'uid_idx'} != $user->uid_idx()) {
# Kill the history entry when skipping.
delete($history->{$projhrn})
if (defined($history) && exists($history->{$projhrn}));
next
}
}
$tmp->{$key} = $details;
}
......
......@@ -2,10 +2,11 @@ $(function ()
{
'use strict';
var template_list = ["reservation-list", "oops-modal", "confirm-modal",
"waitwait-modal"];
var template_list = ["reservation-list", "resusage-list",
"oops-modal", "confirm-modal", "waitwait-modal"];
var templates = APT_OPTIONS.fetchTemplateList(template_list);
var listTemplate = _.template(templates["reservation-list"]);
var usageTemplate = _.template(templates["resusage-list"]);
var confirmString = templates["confirm-modal"];
var oopsString = templates["oops-modal"];
var waitwaitString = templates["waitwait-modal"];
......@@ -109,6 +110,66 @@ $(function ()
return false;
});
}
if (_.has(json.value, "history")) {
var history = json.value.history;
console.info("history", name, history);
$('#' + name + " table tbody tr").each(function () {
// Grab the uuid, it is the key into the reservation list.
var uuid = $(this).attr('data-uuid');
var details = reservations[uuid];
var type = details.type;
var urn = details.project;
var pid = details.pid;
//console.info("uuid", uuid, details);
// No history for the project.
if (!_.has(history, urn))
return;
//console.info("history", urn, history[urn]);
/*
* Search history entries and prune to only
* those using the type reserved. Might not be
* any experiments using this type.
*/
var entries = [];
for (var i = 0; i < history[urn].length; i++) {
var entry = history[urn][i];
if (_.has(entry.types, type)) {
entries.push(entry);
}
}
if (entries.length == 0)
return;
// Contents of the new modal.
var html = usageTemplate({"uuid" : uuid,
"type" : type,
"project" : pid,
"history" : entries});
// And add to all the new modals.
$('#resusage-modals').append(html);
// Show/Activate the button in the list that shows modal.
$(this).find(".resusage-button").click(function (event) {
event.preventDefault();
sup.ShowModal('#' + "resusage-modal-" + uuid);
});
$(this).find(".resusage-button").removeClass("hidden");
// Format dates in the modal with moment before display.
$('#resusage-modal-' + uuid + ' .format-date').each(function() {
var date = $.trim($(this).html());
if (date != "") {
$(this).html(moment(date * 1000).format("lll"));
}
});
});
}
// This activates the tooltip subsystem.
$('[data-toggle="tooltip"]').tooltip({
delay: {"hide" : 250, "show" : 250},
......
......@@ -99,7 +99,7 @@ echo "</script>\n";
REQUIRE_UNDERSCORE();
REQUIRE_SUP();
REQUIRE_MOMENT();
AddTemplateList(array("reservation-list", "confirm-modal",
AddTemplateList(array("reservation-list", "confirm-modal", "resusage-list",
"oops-modal", "waitwait-modal"));
SPITREQUIRE("js/list-reservations.js",
"<script src='js/lib/jquery.tablesorter.min.js'></script>\n".
......
......@@ -549,6 +549,7 @@ function Do_ListReservations()
else {
$blob["approved"] = null;
}
$blob["project"] = $details['project'];
$blob["count"] = $details['nodes'];
$blob["type"] = $details['type'];
$blob["created"] = $details['created'];
......
......@@ -69,11 +69,11 @@
<% } %>
<% } %>>
<% if (showidx) { %>
<td>
<% if (isadmin) { %>
<a href="#" class="deny-button">
<td style='white-space: nowrap;'>
<% if (isadmin) { %>
<a href="#" class="deny-button">
<span class='glyphicon glyphicon-thumbs-down pull-left'
style='color: red; margin-right: 5px;
style='color: red; margin-left: 0px;
margin-bottom: 4px;'
data-toggle='tooltip'
data-container="body"
......@@ -83,7 +83,7 @@
<% } %>
<a href="#" class="delete-button">
<span class='glyphicon glyphicon-remove pull-left'
style='color: red; margin-right: 5px;
style='color: red; margin-left: 5px;
margin-bottom: 4px;'
data-toggle='tooltip'
data-container="body"
......@@ -92,34 +92,47 @@
</a>
<a href="reserve.php?edit=1&cluster=<%- value.cluster %>&uuid=<%- value.uuid %>"
class="edit-button">
<span class='glyphicon glyphicon-pencil pull-left'
style='color: red; margin-right: 5px;
margin-bottom: 4px;'
<span class='glyphicon glyphicon-pencil pull-left text-primary'
style='margin-left: 5px;
margin-bottom: 4px;'
data-toggle='tooltip'
data-container="body"
data-trigger="hover"
title='Edit reservation details'></span>
</a>
<% if (value.creator_idx) { %>
<a href="#" class="info-button">
<span class='glyphicon glyphicon-info-sign pull-left'
style='color: red; margin-bottom: 4px;
margin-right: 5px;'
data-toggle='tooltip'
data-container="body"
data-trigger="hover"
title='Send a message to user'></span>
</a>
<% if (isadmin) { %>
<% if (value.creator_idx) { %>
<a href="#" class="info-button">
<span class='glyphicon glyphicon-info-sign pull-left
text-warning'
style='margin-bottom: 4px;
margin-left: 5px;'
data-toggle='tooltip'
data-container="body"
data-trigger="hover"
title='Send a message to user'></span>
</a>
<% } %>
<a href="#" class="warn-button">
<span class='glyphicon glyphicon-warning-sign pull-left'
style='color: red; margin-bottom: 4px;
margin-right: 0px;'
<span class='glyphicon glyphicon-warning-sign pull-left
text-warning'
style='margin-bottom: 4px;
margin-left: 5px;'
data-toggle='tooltip'
data-container="body"
data-trigger="hover"
title='Warn user about unused reservaton'></span>
</a>
<% } %>
<% } %>
<a href="#" class="resusage-button hidden">
<span class='glyphicon glyphicon-list-alt pull-left text-info'
style='margin-bottom: 4px;
margin-left: 5px;'
data-toggle='tooltip'
data-container="body"
data-trigger="hover"
title='Show recent project activity'></span>
</a>
</td>
<% } %>
<% if (showuser) { %>
......@@ -232,3 +245,4 @@
</div>
</div>
</div>
<div id="resusage-modals"></div>
<div id='resusage-modal-<%- uuid %>' class='modal fade'>
<div class='modal-dialog'>
<div class='modal-content'>
<div class='modal-body'>
<button type='button' class='close' data-dismiss='modal'
aria-hidden='true'>&times;</button>
<center>
<h5>Recent/Current usage in project <%- project %> for
node type <%- type %></h5>
</center>
<div>
<table class='table table-condensed'>
<thead>
<tr>
<th>Name</th>
<th>Start</th>
<th style="min-width: 100px;">End</th>
<th>Count</th>
</tr>
</thead>
<tbody>
<% _.each(history, function(value, uuid) { %>
<tr>
<td>
<% if (_.has(value, "instance_uuid")) { %>
<a target="_blank"
href='status.php?uuid=<%- value.instance_uuid %>'>
<%- value.eid %></a>
<% } else { %>
<%= value.eid %>
<% } %>
</td>
<td class="format-date">
<%- value.start %></td>
<td class="format-date">
<%- value.end %></td>
<td><%- value.types[type].count %></td>
</tr>
<% }); %>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
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