Commit f673e2f8 authored by Jonathon Duerig's avatar Jonathon Duerig

New genilib-editor refactoring. Various bugfixes.

Fix error-handling errors.
Make the waitwait modal non-dismissable everywhere.
The new genilib-editor is now a kind of mega-modal which can live in both the show-profile and modify_profile pages. It is read-only in the former case and read/writable in the latter.

All of the form-submitting stuff that recent ajaxification broke has been stripped out. It is now a pure editor that notifies the surrounding page of changes when you click on 'accept'.
parent f646c14a
......@@ -48,7 +48,7 @@ sub usage()
}
my $optlist = "dvt:m";
my $debug = 0;
my $verbose = 1;
my $verbose = 0;
my $webtask;
my $webtask_id;
# VerifyXML sets these, need to declare early. Need to clean this up.
......@@ -959,6 +959,9 @@ sub UserError($)
my $errors = {};
if (ref($ref) eq "SCALAR") {
$errors->{"error"} = $$ref;
}
elsif (ref($ref) eq "") {
$errors->{"error"} = $ref;
}
else {
......
......@@ -289,6 +289,7 @@ if ($exit_status) {
}
unlink($outfile);
unlink($infile);
# We want to pass along the exit status, since it indicates an internal
# vs script error.
exit($exit_status >> 8);
......
#editor
#genilib-editor-body #genilib-editor
{
width: 100%;
height: 80%;
}
#jacks-root
#genilib-editor-body #jacks-root
{
display: none;
}
#error-root
#genilib-editor-body #error-root
{
display: none;
}
#settings-root
#genilib-editor-body #settings-root
{
display: none;
}
.edit-buttons
#genilib-editor-body .edit-buttons
{
padding-bottom: 10px;
}
#jacks-container
#genilib-editor-body #jacks-container
{
/*
position: absolute;
......@@ -36,12 +36,12 @@
background-color: #fff;
}
#error-root .panel-body
#genilib-editor-body #error-root .panel-body
{
background-color: #f5f5f5;
}
.error-item > pre
#genilib-editor-body .error-item > pre
{
background-color: inherit;
margin: 0;
......@@ -50,13 +50,13 @@
border: 1px solid #f0f0f0;
}
.error-item > button
#genilib-editor-body .error-item > button
{
margin-top: 5px;
margin-right: 5px;
}
#settingsButton
#genilib-editor-body #settingsButton
{
height: 34px;
}
......
<?php
#
# Copyright (c) 2000-2016 University of Utah and the Flux Group.
#
# {{{EMULAB-LICENSE
#
# This file is part of the Emulab network testbed software.
#
# This file is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or (at
# your option) any later version.
#
# This file is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
# License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this file. If not, see <http://www.gnu.org/licenses/>.
#
# }}}
#
chdir("..");
include("defs.php3");
chdir("apt");
include("quickvm_sup.php");
include_once("profile_defs.php");
$page_title = "Genilib Editor";
#
# Get current user.
#
RedirectSecure();
$this_user = CheckLogin($check_status);
if (isset($this_user)) {
# Allow unapproved users to edit their profile ...
CheckLoginOrDie(CHECKLOGIN_UNAPPROVED|CHECKLOGIN_NONLOCAL);
}
else {
CheckLoginOrRedirect();
}
#
# Verify page arguments.
#
$optargs = OptionalPageArguments("uuid", PAGEARG_STRING,
"profile",PAGEARG_STRING,
"project",PAGEARG_PROJECT,
"version",PAGEARG_INTEGER);
$canedit = 0;
$disabled = 0;
$source = "";
$profileObject = null;
$profileWho = "private";
if (isset($uuid)) {
$profileObject = Profile::Lookup($uuid);
}
elseif (isset($project) && isset($profile) && isset($version)) {
$profileObject = Profile::LookupByName($project, $profile, $version);
}
elseif (isset($project) && isset($profile)) {
$profileObject = Profile::LookupByName($project, $profile);
}
if (isset($profileObject)) {
$source = $profileObject->script();
$canedit = ($profileObject->CanEdit($this_user) ? 1 : 0);
$disabled = ($profileObject->isDisabled() ? 1 : 0);
if ($profileObject->shared()) {
$profileWho = "shared";
}
}
# We use a session. in case we need to do verification
session_start();
session_unset();
SPITHEADER(1);
echo "<script>\n";
if (isset($profileObject)) {
echo "window.PROFILE_NAME = '" . $profileObject->name() . "';";
echo "window.PROFILE_PROJECT = '" . $profileObject->pid() . "';";
echo "window.PROFILE_VERSION_UUID = '" . $profileObject->uuid() . "';";
echo "window.PROFILE_LATEST_UUID = '" . $profileObject->profile_uuid() . "';";
echo "window.PROFILE_WHO = '" . $profileWho . "';";
}
echo "window.PROFILE_CANEDIT = $canedit;\n";
echo "window.PROFILE_DISABLED = $disabled;\n";
#echo "window.APT_OPTIONS.nopassword = $nopassword;\n";
echo "</script>\n";
echo "<link rel='stylesheet' href='css/bootstrap-formhelpers.min.css'>\n";
echo "<link rel='stylesheet' href='css/genilib-editor.css'>\n";
echo "<div id='page-body'></div>\n";
echo "<div id='oops_div'></div>\n";
echo "<div id='waitwait_div'></div>\n";
echo "<script type='text/plain' id='source'>\n";
echo base64_encode($source);
#echo htmlentities(json_encode($defaults)) . "\n";
echo "</script>\n";
# Pass project list through. Need to convert to list without groups.
# When editing, pass through a single value. The template treats a
# a single value as a read-only field.
$projlist = $this_user->ProjectAccessList($TB_PROJECT_CREATEEXPT);
$plist = array();
while (list($proj) = each($projlist)) {
$plist[] = $proj;
}
echo "<script type='text/plain' id='projects-json'>\n";
echo htmlentities(json_encode($plist));
echo "</script>\n";
echo "<script src='js/lib/jquery-2.0.3.min.js'></script>\n";
echo "<script src='https://cdn.jsdelivr.net/ace/1.2.3/noconflict/ace.js'></script>\n";
echo "<script src='https://cdn.jsdelivr.net/ace/1.2.3/noconflict/keybinding-vim.js'></script>\n";
echo "<script src='https://cdn.jsdelivr.net/ace/1.2.3/noconflict/keybinding-emacs.js'></script>\n";
REQUIRE_UNDERSCORE();
REQUIRE_SUP();
REQUIRE_APTFORMS();
REQUIRE_JACKS();
SPITREQUIRE("js/genilib-editor.js");
AddTemplateList(array("genilib-editor", "oops-modal", "waitwait-modal", "manage-profile"));
SPITFOOTER();
?>
This diff is collapsed.
......@@ -30,6 +30,7 @@ $(function ()
var ajaxurl = "";
var amlist = null;
var modified = false;
var isInEditor = false;
var editor = null;
var myCodeMirror = null;
var isppprofile = false;
......@@ -111,7 +112,7 @@ $(function ()
// Warn user if they have not saved changes.
$(window).on('beforeunload.portal', function() {
if (! modified)
if (! modified && ! isInEditor)
return undefined;
return "You have unsaved changes!";
});
......@@ -152,7 +153,7 @@ $(function ()
});
manage_html = aptforms.FormatFormFieldsHorizontal(manage_html,
{"wide" : true});
$('#manage-body').html(manage_html);
$('#page-body').html(manage_html);
var waitwait_html = waitwaitTemplate({});
$('#waitwait_div').html(waitwait_html);
......@@ -254,8 +255,8 @@ $(function ()
var source = $.trim($('#profile_script_textarea').val());
var type = "source";
if (0 && source.length > 0 && window.ACTION === 'edit' && !fromrepo) {
openEditor();
if (source.length > 0 && window.ACTION === 'edit' && !fromrepo) {
openEditor(source);
} else {
if (source.length === 0) {
source = $.trim($('#profile_rspec_textarea').val());
......@@ -322,10 +323,6 @@ $(function ()
$('#rspec_modal').modal({'backdrop':'static','keyboard':false});
$('#rspec_modal').modal('show');
});
$('#edit_copy_button').click(function (event) {
openEditor();
});
$('#rspec_modal').on('shown.bs.modal', function() {
var source = $('#modal_profile_rspec_textarea').val();
......@@ -537,7 +534,6 @@ $(function ()
// We also got a geni-lib script, so show the XML button.
if (gotscript) {
$('#show_xml_modal_button').removeClass("hidden");
//$('#edit_copy_button').removeClass("hidden");
$('#profile_instructions').prop("readonly", true);
$('#profile_description').prop("readonly", true);
$('.geni-lib-warning').removeClass("hidden");
......@@ -601,15 +597,23 @@ $(function ()
{
var submit_callback = function(json) {
if (json.code) {
sup.SpitOops("oops", json.value);
return;
console.log(json);
if (json.code != 2) {
sup.SpitOops("oops", json.value);
}
else if (json.value.error) {
sup.SpitOops("oops", json.value.error);
} else {
sup.SpitOops("oops", JSON.stringify(json.value));
}
return;
}
window.location.replace(json.value);
};
var checkonly_callback = function(json) {
if (json.code) {
if (json.code != 2) {
sup.SpitOops("oops", json.value);
sup.SpitOops("oops", json.value);
}
return;
}
......@@ -639,9 +643,11 @@ $(function ()
else if (repoupdate_callback !== undefined) {
repoupdate_callback(false /* unmodified. */);
}
return;
}
NewRspecHandler(newRspec);
else
{
NewRspecHandler(newRspec);
}
}
//
......@@ -1428,9 +1434,19 @@ $(function ()
xmlthing.done(callback);
}
function openEditor()
function openEditor(source)
{
isInEditor = true;
window.SHOW_GENILIB_EDITOR(source, closeEditor);
}
function closeEditor(source)
{
window.location.href = 'genilib-editor.php?profile=' + profile_name + '&project=' + profile_pid + '&version=' + profile_version;
isInEditor = false;
if (source !== null)
{
changeRspec(source);
}
}
function ShowDeletionWarning(images)
......
......@@ -148,7 +148,7 @@ $(function ()
}
if ($(this).attr("id") == "show_source_modal_button" &&
isScript && !fromrepo) {
openEditor();
openEditor(source);
}
else
{
......@@ -282,9 +282,9 @@ $(function ()
}
}
function openEditor()
function openEditor(source)
{
window.location.href = 'genilib-editor.php?profile=' + profile_name + '&project=' + profile_pid + '&version=' + profile_version;
window.SHOW_GENILIB_EDITOR(source);
}
function SetupRepo()
......
......@@ -80,6 +80,7 @@ function SPITFORM($formfields, $errors)
$this_version = "null";
$latest_uuid = "null";
$latest_version = "null";
$editor_readonly = "true";
if ($action == "edit") {
$button_label = "Save";
......@@ -97,6 +98,7 @@ function SPITFORM($formfields, $errors)
$this_version = $profile->version();
if ($canmodify) {
$title = "Modify Profile";
$editor_readonly = "false";
}
else {
$title = "View Profile";
......@@ -121,7 +123,15 @@ function SPITFORM($formfields, $errors)
echo "<div id='ppviewmodal_div'></div>\n";
# Place to hang the toplevel template.
echo "<div id='manage-body'></div>\n";
echo "<div id='page-body'></div>\n";
# Place to hang the genilib-editor template.
echo "<div id='genilib-editor-body'></div>\n";
# These two modals live outside so that genilib-editor can
# use them as well.
echo "<div id='waitwait_div'></div>
<div id='oops_div'></div>";
# I think this will take care of XSS prevention?
echo "<script type='text/plain' id='form-json'>\n";
......@@ -131,6 +141,11 @@ function SPITFORM($formfields, $errors)
echo htmlentities(json_encode($errors));
echo "</script>\n";
# Needed for genilib-editor
echo "<script src='https://cdn.jsdelivr.net/ace/1.2.3/noconflict/ace.js'></script>\n";
echo "<script src='https://cdn.jsdelivr.net/ace/1.2.3/noconflict/keybinding-vim.js'></script>\n";
echo "<script src='https://cdn.jsdelivr.net/ace/1.2.3/noconflict/keybinding-emacs.js'></script>\n";
# Pass project list through. Need to convert to list without groups.
# When editing, pass through a single value. The template treats a
# a single value as a read-only field.
......@@ -160,6 +175,8 @@ function SPITFORM($formfields, $errors)
# For progress bubbles in the imaging modal.
echo "<link rel='stylesheet' href='css/progress.css'>\n";
echo "<link rel='stylesheet' href='css/codemirror.css'>\n";
echo "<link rel='stylesheet' href='css/genilib-editor.css'>\n";
SpitAggregateStatus();
echo "<script type='text/javascript'>\n";
echo " window.VIEWING = $viewing;\n";
......@@ -196,6 +213,7 @@ function SPITFORM($formfields, $errors)
echo " window.EXPUUID = '$fromexp';\n";
}
echo " window.CANREPO = $canrepo;\n";
echo " window.EDITOR_READONLY = $editor_readonly;\n";
echo "</script>\n";
echo "<script src='js/lib/jquery-ui.js'></script>\n";
echo "<script src='js/lib/jquery.appendGrid-1.3.1.min.js'></script>\n";
......@@ -210,6 +228,7 @@ function SPITFORM($formfields, $errors)
REQUIRE_APTFORMS();
REQUIRE_FILESTYLE();
REQUIRE_MARKED();
REQUIRE_GENILIB_EDITOR();
AddLibrary("js/gitrepo.js");
SPITREQUIRE("js/manage_profile.js");
......
......@@ -235,6 +235,16 @@ function REQUIRE_WIZARD_TEMPLATE()
AddLibrary("js/wizard-template.js");
}
function REQUIRE_GENILIB_EDITOR()
{
REQUIRE_UNDERSCORE();
REQUIRE_SUP();
REQUIRE_APTFORMS();
REQUIRE_JACKS();
AddTemplate("genilib-editor");
AddLibrary("js/genilib-editor.js");
}
#########################################################################################
function SPITREQUIRE($main, $extras = "")
......
......@@ -106,15 +106,29 @@ if ($profile->repourl() && $profile->repourl() != "") {
# Place to hang the toplevel template.
echo "<div id='page-body'></div>\n";
# Place to hang the genilib-editor template.
echo "<div id='genilib-editor-body'></div>\n";
# These two modals live outside so that genilib-editor can
# use them as well.
echo "<div id='waitwait_div'></div>
<div id='oops_div'></div>";
echo "<link rel='stylesheet'
href='css/jquery-ui-1.10.4.custom.min.css'>\n";
echo "<link rel='stylesheet' href='css/codemirror.css'>\n";
echo "<link rel='stylesheet' href='css/genilib-editor.css'>\n";
# I think this will take care of XSS prevention?
echo "<script type='text/plain' id='form-json'>\n";
echo htmlentities(json_encode($defaults)) . "\n";
echo "</script>\n";
# Needed for genilib-editor
echo "<script src='https://cdn.jsdelivr.net/ace/1.2.3/noconflict/ace.js'></script>\n";
echo "<script src='https://cdn.jsdelivr.net/ace/1.2.3/noconflict/keybinding-vim.js'></script>\n";
echo "<script src='https://cdn.jsdelivr.net/ace/1.2.3/noconflict/keybinding-emacs.js'></script>\n";
$am_array = Instance::DefaultAggregateList();
$amlist = array();
$amdefault = "";
......@@ -145,6 +159,7 @@ echo " window.DISABLED = $disabled;\n";
echo " window.HISTORY = $history;\n";
echo " window.ISPPPROFILE = $ispp;\n";
echo " window.WITHPUBLISHING = $WITHPUBLISHING;\n";
echo " window.EDITOR_READONLY = true;\n";
echo "</script>\n";
echo "<script src='js/lib/codemirror-min.js'></script>\n";
......@@ -154,6 +169,7 @@ REQUIRE_SUP();
REQUIRE_MOMENT();
REQUIRE_APTFORMS();
REQUIRE_MARKED();
REQUIRE_GENILIB_EDITOR();
AddLibrary("js/gitrepo.js");
SPITREQUIRE("js/show-profile.js",
"<script src='js/lib/jquery-ui.js'></script>\n".
......
......@@ -6,13 +6,13 @@
<button id="loadButton" class="btn btn-default">Load From Disk</button>
<button id="runButton" class="btn btn-default">Test Script</button>
<button id="settingsButton" class="btn btn-default"><span class="glyphicon glyphicon-cog" aria-hidden="true"></span></button>
<button id="updateButton" class="btn btn-primary pull-right hidden" style="margin-left: 10px">Update Profile</button>
<button id="createButton" class="btn btn-primary pull-right" style="margin-left: 10px">Create New Profile</button>
<button id="cancelButton" class="btn btn-danger pull-right" style="margin-left: 10px">Cancel</button>
<button id="okButton" class="btn btn-primary pull-right" style="margin-left: 10px">Accept</button>
</div>
</div>
<div class="row">
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
<div id="editor"></div>
<div id="genilib-editor"></div>
</div>
</div>
</div>
......
......@@ -331,11 +331,6 @@
<% if (viewing && canmodify && !fromrepo) { %>Edit <% } %>
Source
</button>
<button class='btn btn-primary btn-xs pull-right hidden'
type='button'
id='edit_copy_button'>
Edit a Copy
</button>
<button class='btn btn-primary btn-xs hidden'
type='button'
style='margin-right: 10px;'
......@@ -974,10 +969,8 @@ Instructions are optional.
<!-- place to hang the modals for now -->
<div id='showtopomodal_div'></div>
<div id='editmodal_div'></div>
<div id='waitwait_div'></div>
<div id='imaging_div'></div>
<div id='renderer_div'></div>
<div id='oops_div'></div>
<div id='guest_div'></div>
<div id='publish_div'></div>
<div id='instantiate_div'></div>
......
......@@ -250,10 +250,8 @@
<!-- place to hang the modals -->
<div id='showtopomodal_div'></div>
<div id='editmodal_div'></div>
<div id='waitwait_div'></div>
<div id='imaging_div'></div>
<div id='renderer_div'></div>
<div id='oops_div'></div>
<div id='guest_div'></div>
<div id='publish_div'></div>
<div id='instantiate_div'></div>
......
<!-- This is the Please Wait modal -->
<div id='waitwait-modal' class='modal fade'>
<div id='waitwait-modal' class='modal fade' data-keyboard='false' data-backdrop='static'>
<div class='modal-dialog'>
<div class='modal-content'>
<div class='modal-header'>
......
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