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,18 +536,18 @@ $(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() {
$('#profile_description textarea, #profile_instructions textarea')
.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));
$('#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
......@@ -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,16 +1026,41 @@ $(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
......@@ -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);
fromrepo, gotscript, gotrspec, portal_converted);
if (! (gotscript || gotrspec)) {
$('#edit_topo_modal_button').html('Create Topology');
$('#show_source_modal_button').html('Edit Code');
}
else {
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,10 +415,18 @@ $(function ()
statusBusy = 1;
var callback = function(json) {
// 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;
}
var xmlthing = sup.CallServerMethod(ajaxurl,
......@@ -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)) { %>
......@@ -329,16 +339,11 @@
<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>
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>
id='show_source_modal_button'>Code</button>
<button class='btn btn-primary btn-xs hidden'
type='button'
style='margin-right: 10px;'
......@@ -362,13 +367,19 @@
<% } %>
<% if (! (viewing || window.CLONING)) { %>
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>
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">
<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">
<span style='margin-bottom: 4px; margin-left: 0px;'
class='glyphicon glyphicon-question-sign'></span></a>
</small></div>
class='glyphicon glyphicon-question-sign'>
</span>
</a>
</small>
</div>
</div>
</div>
</div>
</div>
<div class="form-group">
......@@ -455,22 +474,30 @@
profile after it starts.
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_instructions
id='profile_instructions'
class='form-control'
rows=3
<div id='profile_instructions'>
<textarea class="form-control hidden" rows=3
placeholder="Provide optional instructions for users of your profile."
type='textarea'></textarea>
<div class="geni-lib-warning hidden"><small class="pull-right">
<div class="textarea hidden">
<div class="form-control textdiv scrolly"></div>
<div class="geni-lib-warning">
<small class="pull-right">
Instructions 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>
class='glyphicon glyphicon-question-sign'>
</span>
</a>
</small>
</div>
</div>
</div>
</div>
</div>
</fieldset>
<fieldset>
<!-- Tour Table; hidden until the table is initialized
from the rspec. -->