Commit 9cca2ea0 authored by Leigh B Stoller's avatar Leigh B Stoller

Changes on the manage profile page:

As per Jon's suggestion at the meeting, do not show the text boxes until
there is a script or rspec to work with. In fact, do not show any of the
rest of the page until the user provides something.

Also suggested by Jon, is to now use a read-only textarea when the text
is not writable, do what we do on the show-profile page instead; show
the rendered text inside a plain scrollable div.

I also messed with the button labels, try it you'll like it.
parent f1ce5b40
......@@ -515,12 +515,12 @@ $(function ()
* the text back into the rspec since that is what actually
* gets submitted; the rspec is authoritative.
*/
$('#profile_instructions').change(function() {
ChangeHandlerAux("instructions");
$('#profile_instructions textarea').change(function() {
TourModified("instructions");
ProfileModified();
});
$('#profile_description').change(function() {
ChangeHandlerAux("description");
$('#profile_description textarea').change(function() {
TourModified("description");
ProfileModified();
});
......@@ -536,20 +536,20 @@ $(function ()
$('#profile_nodelete').change(function() { ProfileModified(); });
/*
* A double click handler that will render the instructions
* in a modal.
* A double click handler that will render the instructions or
* description in a modal.
*/
$('#profile_instructions').dblclick(function() {
var text = $(this).val();
$('#renderer_modal_div').html(marked(text));
sup.ShowModal("#renderer_modal");
});
// Ditto the description.
$('#profile_description').dblclick(function() {
var text = $(this).val();
$('#renderer_modal_div').html(marked(text));
sup.ShowModal("#renderer_modal");
});
$('#profile_description textarea, #profile_instructions textarea')
.dblclick(function() {
var text = $(this).val();
$('#renderer_modal_div').html(marked(text));
sup.ShowModal("#renderer_modal");
});
$('#profile_description .textdiv, #profile_instructions .textdiv')
.dblclick(function() {
$('#renderer_modal_div').html($(this).html());
sup.ShowModal("#renderer_modal");
});
// Handler for guest instantiate submit button, which is in
// the modal.
$('#guest_instantiate_submit_button').click(function (event) {
......@@ -587,27 +587,10 @@ $(function ()
/*
* If we were given an rspec, suck the description and instructions
* out of the rspec and put them into the text boxes. But
* watch for some already in the description box, it is an old
* one and we want to use it if no description in the rspec.
* out of the rspec and put them into the text boxes.
*/
if (gotrspec) {
if (window.VIEWING) {
ExtractFromRspec();
// We also got a geni-lib script, so show the XML button.
if (gotscript) {
$('#show_xml_modal_button').removeClass("hidden");
$('#profile_instructions').prop("readonly", true);
$('#profile_description').prop("readonly", true);
$('.geni-lib-warning').removeClass("hidden");
}
}
else {
/*
* Not editing, so disable the text boxes until we get
* an rspec via the file chooser.
*/
$('#profile_instructions').prop("disabled", true);
$('#profile_description').prop("disabled", true);
}
CreateJacksEditor();
UpdateButtons();
......@@ -721,6 +704,11 @@ $(function ()
}
else
{
// Kill existing script since we are switching back to XML. SAD!
if (gotscript) {
gotscript = 0;
$('#profile_script_textarea').val("");
}
NewRspecHandler(newRspec);
}
}
......@@ -918,12 +906,12 @@ $(function ()
return xml;
}
//
// Helper function for instructions/description change handler above.
// Take the text box contents and store back into the rspec.
// The description or instructions have changed in an rspec based
// profile, need to write the changes back into the rspec.
//
function ChangeHandlerAux(which)
function TourModified(which)
{
var text = $('#profile_' + which).val();
var text = $('#profile_' + which + ' textarea').val();
var rspec = $('#profile_rspec_textarea').val();
if (rspec === "") {
return;
......@@ -957,6 +945,8 @@ $(function ()
{
newrspec = $.trim(newrspec);
var oldrspec = $.trim($('#profile_rspec_textarea').val());
gotrspec = 1;
if (newrspec == oldrspec) {
// In case rspec does not change.
UpdateButtons();
......@@ -986,19 +976,6 @@ $(function ()
if (!fromrepo)
ProfileModified();
UpdateButtons();
if (gotscript) {
$('#profile_instructions').prop("readonly", true);
$('#profile_description').prop("readonly", true);
$('.geni-lib-warning').removeClass("hidden");
}
else {
// Allow editing the boxes now that we have an rspec.
// This only matters on a brand new create age.
$('#profile_instructions').prop("readonly", false);
$('#profile_description').prop("readonly", false);
$('#profile_instructions').prop("disabled", false);
$('#profile_description').prop("disabled", false);
}
};
// No old rspec, use new one.
......@@ -1049,17 +1026,42 @@ $(function ()
//console.info(rspec);
//console.info(xml);
$('#profile_description').val("");
$('#profile_description textarea').val("");
$('#profile_description .textdiv').html("");
$(xml).find("rspec_tour > description").each(function() {
var text = $(this).text();
$('#profile_description').val(text);
$('#profile_description textarea').val(text);
$('#profile_description .textdiv').html(marked(text));
});
$('#profile_instructions').val("");
$('#profile_instructions textarea').val("");
$('#profile_instructions .textdiv').html("");
$(xml).find("rspec_tour > instructions").each(function() {
var text = $(this).text();
$('#profile_instructions').val(text);
$('#profile_instructions textarea').val(text);
$('#profile_instructions .textdiv').html(marked(text));
});
if (gotscript) {
// We got here by a geni-lib script. No editing allowed
$('#show_xml_modal_button').removeClass("hidden");
$('#profile_description textarea').addClass("hidden");
$('#profile_description .textarea').removeClass("hidden");
$('#profile_instructions textarea').addClass("hidden");
$('#profile_instructions .textarea').removeClass("hidden");
}
else {
// User can edit the textareas
$('#show_xml_modal_button').addClass("hidden");
$('#profile_description textarea').removeClass("hidden");
$('#profile_description .textarea').addClass("hidden");
$('#profile_instructions textarea').removeClass("hidden");
$('#profile_instructions .textarea').addClass("hidden");
}
// Creating new profile, now we can show the tour/metadata fields.
if (!window.VIEWING) {
$('#tour-text-boxes').removeClass("hidden");
$('#metadata-fields').removeClass("hidden");
}
//
// First time we see the XML, grab step data out of it. But after
// that the steps table is authoritative, and so we sync the table
......@@ -1316,6 +1318,8 @@ $(function ()
}
if (json.value.rspec != "") {
gotscript = 1;
// Kill the rspec so that we always use the new one.
$('#profile_rspec_textarea').val("");
NewRspecHandler(json.value.rspec);
if (repoupdate_callback !== undefined) {
repoupdate_callback(true /* modified */);
......@@ -1685,14 +1689,22 @@ $(function ()
function UpdateButtons()
{
console.info(window.VIEWING, window.CANMODIFY,
fromrepo, gotscript, portal_converted);
if ((!window.VIEWING || window.CANMODIFY) &&
!fromrepo && (!gotscript || portal_converted)) {
$('#edit_topo_modal_button').html('Edit Topology');
fromrepo, gotscript, gotrspec, portal_converted);
if (! (gotscript || gotrspec)) {
$('#edit_topo_modal_button').html('Create Topology');
$('#show_source_modal_button').html('Edit Code');
}
else {
$('#edit_topo_modal_button').html('View Topology');
if ((!window.VIEWING || window.CANMODIFY) &&
!fromrepo && (!gotscript || portal_converted)) {
$('#edit_topo_modal_button').html('Edit Topology');
$('#show_source_modal_button').html('Edit Code');
}
else {
$('#edit_topo_modal_button').html('View Topology');
$('#show_source_modal_button').html('View Code');
}
}
}
......
......@@ -168,6 +168,7 @@ $(function ()
// Setup the extend modal.
$('button#extend_button').click(function (event) {
window.APT_OPTIONS.gaButtonEvent(event);
event.preventDefault();
if (isfadmin) {
sup.ShowModal("#extend_history_modal");
......@@ -184,17 +185,20 @@ $(function ()
// Handler for the refresh button
$('button#refresh_button').click(function (event) {
window.APT_OPTIONS.gaButtonEvent(event);
event.preventDefault();
DoRefresh();
});
// Handler for the Clone button.
$('button#clone_button').click(function (event) {
window.APT_OPTIONS.gaButtonEvent(event);
event.preventDefault();
window.location.replace('manage_profile.php?action=clone' +
'&snapuuid=' + uuid);
});
// Handler for the reload topology button
$('button#reload-topology-button').click(function (event) {
window.APT_OPTIONS.gaButtonEvent(event);
event.preventDefault();
DoReloadTopology();
});
......@@ -207,7 +211,8 @@ $(function ()
//
var popover_timer;
$("button#clone_button").mouseenter(function(){
$("button#clone_button").mouseenter(function(event) {
window.APT_OPTIONS.gaButtonEvent(event);
popover_timer = setTimeout(function() {
$('button#clone_button').popover({
html: true,
......@@ -217,17 +222,20 @@ $(function ()
container:'body',
});
$('button#clone_button').popover('show');
$('#clone_popover_close').on('click', function(e) {
$('#clone_popover_close').on('click', function(event) {
window.APT_OPTIONS.gaButtonEvent(event);
$('button#clone_button').popover('hide');
});
},1000)
}).mouseleave(function(){
clearTimeout(popover_timer);
}).click(function(){
}).click(function(event){
clearTimeout(popover_timer);
window.APT_OPTIONS.gaButtonEvent(event);
});
$("button#snapshot_button").mouseenter(function(){
$("button#snapshot_button").mouseenter(function(event) {
window.APT_OPTIONS.gaButtonEvent(event);
popover_timer = setTimeout(function() {
$('button#snapshot_button').popover({
html: true,
......@@ -237,23 +245,27 @@ $(function ()
container:'body',
});
$('button#snapshot_button').popover('show');
$('#snapshot_popover_close').on('click', function(e) {
$('#snapshot_popover_close').on('click', function(event) {
window.APT_OPTIONS.gaButtonEvent(event);
$('button#snapshot_button').popover('hide');
});
// Kill popover if user clicks through.
$('button#snapshot_button').on('click', function(e) {
$('button#snapshot_button').on('click', function(event) {
window.APT_OPTIONS.gaButtonEvent(event);
$('button#snapshot_button').popover('hide');
});
},1000)
}).mouseleave(function(){
clearTimeout(popover_timer);
}).click(function(){
}).click(function(event){
clearTimeout(popover_timer);
window.APT_OPTIONS.gaButtonEvent(event);
DoSnapshotNode();
});
// Terminate an experiment.
$('button#terminate').click(function (event) {
window.APT_OPTIONS.gaButtonEvent(event);
var lockdown_override = "";
event.preventDefault();
sup.HideModal('#terminate_modal');
......@@ -336,6 +348,9 @@ $(function ()
$('#instructions').on('show.bs.collapse', function () {
APT_OPTIONS.updatePage({ 'status_instructions': 'shown' });
});
$('#quicktabs_ul li a').on('shown.bs.tab', function (event) {
window.APT_OPTIONS.gaTabEvent(event.target);
})
addTutorialNotifyTab('profile');
addTutorialNotifyTab('listview');
......@@ -400,9 +415,17 @@ $(function ()
statusBusy = 1;
var callback = function(json) {
StatusWatchCallBack(json);
if (instanceStatus == 'terminated') {
// Watch for logged out, stop the loop. User will need to reload.
if (json.code == 222) {
clearInterval(statusID);
alert("You are no longer logged in, please refresh to " +
"continue getting page updates");
}
else {
StatusWatchCallBack(json);
if (instanceStatus == 'terminated') {
clearInterval(statusID);
}
}
statusBusy = 0;
}
......@@ -437,7 +460,7 @@ $(function ()
var status_html = "";
if (instanceStatus != lastStatus) {
APT_OPTIONS.updatePage({ 'instance-status': instanceStatus });
APT_OPTIONS.updatePage({ 'instance-status': instanceStatus });
console.info(json);
status_html = status;
......@@ -1126,6 +1149,7 @@ $(function ()
// Throw up a confirmation modal, with handler bound to confirm.
$('#confirm_reload_button').bind("click.reload", function (event) {
window.APT_OPTIONS.gaButtonEvent(event);
sup.HideModal('#confirm_reload_modal');
var callback = function(json) {
sup.HideModal('#waitwait-modal');
......@@ -1160,7 +1184,9 @@ $(function ()
});
// Throw up a confirmation modal, with handler bound to confirm.
$('button#deletenode_confirm').bind("click.deletenode", function (event) {
$('button#deletenode_confirm').bind("click.deletenode",
function (event) {
window.APT_OPTIONS.gaButtonEvent(event);
sup.HideModal('#deletenode_modal');
var callback = function(json) {
......@@ -1278,8 +1304,15 @@ $(function ()
// Append to end of tabs
$("#quicktabs_ul").append(html);
// GA handler.
$('#quicktabs_ul a[href="#' + tabname + '"]')
.on('shown.bs.tab', function (event) {
window.APT_OPTIONS.gaTabEvent(event.target);
});
// Install a click handler for the X button.
$("#" + tabname + "_kill").click(function(e) {
window.APT_OPTIONS.gaButtonEvent(e);
e.preventDefault();
// Trigger the custom event.
$("#" + tabname).trigger("killssh");
......@@ -1288,7 +1321,7 @@ $(function ()
// Remove the content div.
$("#" + tabname).remove();
// Activate the "profile" tab.
$('#quicktabs_ul a[href="#profile"]').tab('show');
$('#quicktabs_ul a[href="#topology"]').tab('show');
});
// The content div.
......@@ -1367,6 +1400,7 @@ $(function ()
$('#context').contextmenu({
target: '#' + cid,
onItem: function(context,e) {
window.APT_OPTIONS.gaButtonEvent(e);
$('#context').contextmenu('closemenu');
$('#context').contextmenu('destroy');
ActionHandler($(e.target).attr("name"), [client_id]);
......@@ -1607,6 +1641,7 @@ $(function ()
// Attach handler to the menu button.
$('#listview-row-' + node + ' [name=shell]')
.click(function (e) {
window.APT_OPTIONS.gaButtonEvent(e);
e.preventDefault();
ActionHandler("shell", [node]);
return false;
......@@ -1629,10 +1664,12 @@ $(function ()
// Attach handler to the menu button.
$('#listview-row-' + node + ' [name=console]')
.click(function (e) {
window.APT_OPTIONS.gaButtonEvent(e);
ActionHandler("console", [node]);
});
$('#listview-row-' + node + ' [name=consolelog]')
.click(function (e) {
window.APT_OPTIONS.gaButtonEvent(e);
ActionHandler("consolelog", [node]);
});
// Remember we have a console, for the context menu.
......@@ -1651,6 +1688,7 @@ $(function ()
//
$('#listview-row-' + node + ' [name=snapshot]')
.click(function (e) {
window.APT_OPTIONS.gaButtonEvent(e);
ActionHandler("snapshot", [node]);
});
//
......@@ -1658,6 +1696,7 @@ $(function ()
//
$('#listview-row-' + node + ' [name=delete]')
.click(function (e) {
window.APT_OPTIONS.gaButtonEvent(e);
ActionHandler("delete", [node]);
});
}
......@@ -1701,7 +1740,7 @@ $(function ()
// Pass all the manifests to the viewer.
$("#showtopo_container").removeClass("invisible");
$('#quicktabs_ul a[href="#profile"]').tab('show');
$('#quicktabs_ul a[href="#topology"]').tab('show');
ShowViewer('#showtopo_statuspage', json.value);
// Process all the manifests to create the list view.
......@@ -1748,6 +1787,7 @@ $(function ()
else {
$('#listview-action-menu li a')
.click(function (e) {
window.APT_OPTIONS.gaButtonEvent(e);
var checked = [];
// Get the list of checked nodes.
......@@ -2084,8 +2124,15 @@ $(function ()
// Append to end of tabs
$("#quicktabs_ul").append(html);
// GA handler.
$('#quicktabs_ul a[href="#' + tabname + '"]')
.on('shown.bs.tab', function (event) {
window.APT_OPTIONS.gaTabEvent(event.target);
});
// Install a kill click handler for the X button.
$("#" + tabname + "_kill").click(function(e) {
window.APT_OPTIONS.gaButtonEvent(e);
e.preventDefault();
// remove the li from the ul. this=ul.li.a.button
$(this).parent().parent().remove();
......@@ -2395,15 +2442,21 @@ $(function ()
// Append to end of tabs
$("#quicktabs_ul").append(html);
$('#quicktabs_ul a[href="#' + tabname + '"]')
.on('shown.bs.tab', function (event) {
window.APT_OPTIONS.gaTabEvent(event.target);
});
// Install a click handler for the X button.
$("#" + tabname + "_kill").click(function(e) {
window.APT_OPTIONS.gaButtonEvent(e);
e.preventDefault();
// remove the li from the ul.
$(this).parent().parent().remove();
// Remove the content div.
$("#" + tabname).remove();
// Activate the "profile" tab.
$('#quicktabs_ul a[href="#profile"]').tab('show');
$('#quicktabs_ul a[href="#topology"]').tab('show');
});
// The content div.
......@@ -2462,6 +2515,7 @@ $(function ()
// Handler for the linktest modal button
$('button#linktest-modal-button').click(function (event) {
window.APT_OPTIONS.gaButtonEvent(event);
event.preventDefault();
// Make the popover go away when button clicked.
$('button#linktest-modal-button').popover('hide');
......@@ -2469,11 +2523,13 @@ $(function ()
});
// And for the start button in the modal.
$('button#linktest-start-button').click(function (event) {
window.APT_OPTIONS.gaButtonEvent(event);
event.preventDefault();
StartLinktest();
});
// Stop button for a running or wedged linktest.
$('button#linktest-stop-button').click(function (event) {
window.APT_OPTIONS.gaButtonEvent(event);
event.preventDefault();
// Gack, we have to confirm popover hidden, or it sticks around.
// Probably cause we disable the button before popover is hidden?
......
......@@ -2,6 +2,13 @@
.popover {
max-width: none !important;
}
.scrolly {
overflow-y: auto;
position: relative;
height: auto;
max-height: 150px;
min-height: 24px;
}
}
</style>
<div class='row'>
......@@ -309,11 +316,14 @@
<% if (! genilib_editor) { %>
<div class="form-group">
<div class='format-me'
data-key='profile_rspec' data-label='Your script'
data-key='profile_rspec' data-label='Source code'
data-html="true"
data-help='You can supply either an
<a href="<%- manual %>/advanced-topics.html">
rspec or a geni-lib script</a> for your
profile source code.'>
profile source code. <br>You can also create a
topology with the topology editor, or you can
use an existing git repository.'>
<div class='row'>
<div class='col-xs-12'>
<% if (! (fromrepo || window.CLONING)) { %>
......@@ -327,18 +337,13 @@
</span>
<% } %>
<button class='btn btn-primary btn-xs'
type='button'
style='margin-right: 10px;'
id='edit_topo_modal_button'>
<% if ((!viewing || canmodify) && !fromrepo) { %>Edit <% } else { %>View <% } %>
Topology</button>
type='button'
style='margin-right: 10px;'
id='edit_topo_modal_button'>Topology</button>
<button class='btn btn-primary btn-xs'
type='button'
style='margin-right: 10px;'
id='show_source_modal_button'>
<% if ((!viewing || canmodify) && !fromrepo) { %>Edit <% } else { %>View <% } %>
Source
</button>
type='button'
style='margin-right: 10px;'
id='show_source_modal_button'>Code</button>
<button class='btn btn-primary btn-xs hidden'
type='button'
style='margin-right: 10px;'
......@@ -361,14 +366,20 @@
</span>
<% } %>
<% if (! (viewing || window.CLONING)) { %>
or
<button class='btn btn-primary btn-xs'
data-toggle='modal'
data-target='#git-repo-modal'
type='button'
style='margin-left: 10px;'
id='git-repo-button'>
Git Repo</button>
or
<span data-toggle='popover'
data-delay='{"hide":500, "show":500}'
data-html='true'
data-content="Supply your profile source from a
Git repository.
Click for more info.">
<button class='btn btn-primary btn-xs'
data-toggle='modal'
data-target='#git-repo-modal'
type='button'
style='margin-left: 10px;'
id='git-repo-button'>Git Repo</button>
</span>
<% } %>
</div>
</div>
......@@ -424,7 +435,8 @@
data-key='profile_script'
rows=5><%- formfields.profile_script %></textarea>
</fieldset>
<fieldset>
<fieldset id="tour-text-boxes"
<% if (!viewing) { %>class="hidden" <% } %> >
<div class="form-group">
<div class="format-me"
data-key='profile_description'
......@@ -432,19 +444,26 @@
data-help='Briefly describe what this profile
does. Use <a href="https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet" target=_blank>Markdown format</a>, double click
to see a rendering.'>
<textarea name=profile_description
id='profile_description'
rows=3
class='form-control'
type='textarea'></textarea>
<div class="geni-lib-warning hidden"><small class="pull-right">
Description set by geni-lib script
<a href='#' class='btn btn-xs'
data-toggle='modal'
data-target="#docstring-help-modal">
<span style='margin-bottom: 4px; margin-left: 0px;'
class='glyphicon glyphicon-question-sign'></span></a>
</small></div>
<div id='profile_description'>
<textarea class="form-control hidden"
placeholder="Please provide a description for your profile, its required."
rows=3 type='textarea'></textarea>
<div class="textarea hidden">
<div class="form-control textdiv scrolly"></div>
<div class="geni-lib-warning">
<small class="pull-right">
Description set by geni-lib script
<a href='#' class='btn btn-xs'
data-toggle='modal'
data-target="#docstring-help-modal">