Commit 206f98b4 authored by Leigh Stoller's avatar Leigh Stoller

More work on URLs and publish.

* Add a uuid to the profile itself. So now we have a uuid for each specific
  version, and a uuid that points to the profile as a whole.

* On the manage page, move the URL to the left hand panel, and add a second
  URL. One is the URL of the specific version, and the other is a URL to
  the entire profile. Add popovers to explain the difference between.

* On the instantiate page, when you use this URL, we instantiate the most
  recently published version of the profile.

* Add a bit of verbiage to the publish modal.
parent 3b30c172
......@@ -83,7 +83,8 @@ sub Lookup($$;$$)
if (!defined($arg2)) {
if ($arg1 =~ /^(\d*)$/) {
my $result =
DBQueryWarn("select v.* from apt_profiles as i ".
DBQueryWarn("select i.*,v.*,i.uuid as profile_uuid ".
" from apt_profiles as i ".
"left join apt_profile_versions as v on ".
" v.profileid=i.profileid and ".
" v.version=i.version ".
......@@ -96,7 +97,8 @@ sub Lookup($$;$$)
elsif ($arg1 =~ /^([-\w]*),([-\w\.\+]*)$/ ||
$arg1 =~ /^([-\w]*)\/([-\w\.\+]*)$/) {
my $result =
DBQueryWarn("select v.* from apt_profiles as i ".
DBQueryWarn("select i.*,v.*,i.uuid as profile_uuid ".
" from apt_profiles as i ".
"left join apt_profile_versions as v on ".
" v.profileid=i.profileid and ".
" v.version=i.version ".
......@@ -109,7 +111,8 @@ sub Lookup($$;$$)
elsif ($arg1 =~ /^([-\w]*),([-\w\.\+]*):(\d*)$/ ||
$arg1 =~ /^([-\w]*)\/([-\w\.\+]*):(\d*)$/) {
my $result =
DBQueryWarn("select v.* from apt_profiles as i ".
DBQueryWarn("select i.*,v.*,i.uuid as profile_uuid ".
" from apt_profiles as i ".
"left join apt_profile_versions as v on ".
" v.profileid=i.profileid ".
"where i.pid='$1' and i.name='$2' and ".
......@@ -120,13 +123,32 @@ sub Lookup($$;$$)
return BlessRow($class, $result->fetchrow_hashref())
}
elsif ($arg1 =~ /^\w+\-\w+\-\w+\-\w+\-\w+$/) {
#
# First look to see if the uuid is for the profile itself,
# which means current version. Otherwise look for a
# version with the uuid.
#
my $result =
DBQueryWarn("select * from apt_profile_versions ".
"where uuid='$arg1' and deleted is null");
DBQueryWarn("select i.*,v.*,i.uuid as profile_uuid ".
" from apt_profiles as i ".
"left join apt_profile_versions as v on ".
" v.profileid=i.profileid and ".
" v.version=i.version ".
"where i.uuid='$arg1'");
return undef
if (! $result);
return BlessRow($class, $result->fetchrow_hashref())
if ($result->numrows);
$result =
DBQueryWarn("select i.*,v.*,i.uuid as profile_uuid ".
" from apt_profile_versions as v ".
"left join apt_profiles as i on ".
" v.profileid=i.profileid ".
"where v.uuid='$arg1' and ".
" v.deleted is null");
return undef
if (! $result || !$result->numrows);
return BlessRow($class, $result->fetchrow_hashref());
}
return undef;
......@@ -134,7 +156,8 @@ sub Lookup($$;$$)
elsif (!defined($arg3)) {
if ($arg1 =~ /^\d+$/ && $arg2 =~ /^\d+$/) {
my $result =
DBQueryWarn("select v.* from apt_profiles as i ".
DBQueryWarn("select i.*,v.*,i.uuid as profile_uuid ".
" from apt_profiles as i ".
"left join apt_profile_versions as v on ".
" v.profileid=i.profileid ".
"where i.profileid='$arg1' and v.version='$arg2' ".
......@@ -146,7 +169,8 @@ sub Lookup($$;$$)
}
elsif ($arg1 =~ /^[-\w]*$/ && $arg2 =~ /^([-\w\.\+]*):(\d+)$/) {
my $result =
DBQueryWarn("select v.* from apt_profiles as i ".
DBQueryWarn("select i.*,v.*,i.uuid as profile_uuid ".
" from apt_profiles as i ".
"left join apt_profile_versions as v on ".
" v.profileid=i.profileid ".
"where i.pid='$arg1' and i.name='$1' and ".
......@@ -158,7 +182,8 @@ sub Lookup($$;$$)
}
elsif ($arg1 =~ /^[-\w]*$/ && $arg2 =~ /^[-\w\.\+]*$/) {
my $result =
DBQueryWarn("select v.* from apt_profiles as i ".
DBQueryWarn("select i.*,v.*,i.uuid as profile_uuid ".
" from apt_profiles as i ".
"left join apt_profile_versions as v on ".
" v.profileid=i.profileid and ".
" v.version=i.version ".
......@@ -174,7 +199,8 @@ sub Lookup($$;$$)
if ($arg1 =~ /^[-\w]*$/ &&
$arg2 =~ /^[-\w\.\+]*$/ && $arg3 =~ /^\d+$/) {
my $result =
DBQueryWarn("select v.* from apt_profiles as i ".
DBQueryWarn("select i.*,v.*,i.uuid as profile_uuid ".
" from apt_profiles as i ".
"left join apt_profile_versions as v on ".
" v.profileid=i.profileid ".
"where i.pid='$arg1' and i.name='$arg2' and ".
......@@ -265,7 +291,8 @@ sub Create($$$$$$)
}
my $profileid = TBGetUniqueIndex("next_profile", undef, 1);
my $uuid = NewUUID();
my $puuid = NewUUID();
my $vuuid = NewUUID();
my $rspec = DBQuoteSpecial($argref->{'rspec'});
my $cquery = "";
my $vquery = "";
......@@ -278,7 +305,7 @@ sub Create($$$$$$)
# And the versions table.
$vquery = $cquery;
$vquery .= ",uuid='$uuid',created=now()";
$vquery .= ",uuid='$vuuid',created=now()";
$vquery .= ",creator='$uid',creator_idx='$uid_idx'";
$vquery .= ",rspec=$rspec";
......@@ -289,6 +316,7 @@ sub Create($$$$$$)
}
# Back to the main table.
$cquery .= ",uuid='$puuid'";
$cquery .= ",public=1"
if (exists($argref->{'public'}) && $argref->{'public'});
$cquery .= ",listed=1"
......
......@@ -65,8 +65,7 @@ if (isset($profile)) {
#
# Guest users must use the uuid, but logged in users may use the
# internal index. But, we have to support simple the URL too, which
# is /p/project/profilename, but only for public profiles. Need to
# deal with the version at some point.
# is /p/project/profilename, but only for public profiles.
#
if (isset($project) && isset($profile)) {
$obj = Profile::LookupByName($project, $profile, $version);
......@@ -83,10 +82,36 @@ if (isset($profile)) {
exit();
}
if (IsValidUUID($profile)) {
#
# If uuid was to profile, then find the most recently published
# version and instantiate that, since what we have is the most
# recent version, but might not be published.
#
if ($profile == $obj->profile_uuid() && !$obj->published()) {
$obj = $obj->LookupMostRecentPublished();
if (! $obj) {
SPITUSERERROR("No published version for profile");
exit();
}
$profile = $obj->uuid();
}
$profile_array[$profile] = $obj->name();
$profilename = $obj->name();
}
else {
#
# If no version provided, then find the most recently published
# version and instantiate that, since what we have is the most
# recent version, but might not be published.
#
if (!isset($version) && !$obj->published()) {
$obj = $obj->LookupMostRecentPublished();
if (! $obj) {
SPITUSERERROR("No published version for profile");
exit();
}
}
#
# Must be public or belong to user.
#
......
......@@ -17,7 +17,8 @@ function (_, sup, filesize, ShowImagingModal,
guestInstantiateString, publishString, instantiateString)
{
'use strict';
var uuid = null;
var profile_uuid = null;
var version_uuid = null;
var snapping= 0;
var gotrspec = 0;
var ajaxurl = "";
......@@ -34,9 +35,10 @@ function (_, sup, filesize, ShowImagingModal,
function initialize()
{
window.APT_OPTIONS.initialize(sup);
snapping = window.SNAPPING;
uuid = window.UUID;
ajaxurl = window.AJAXURL;
snapping = window.SNAPPING;
version_uuid = window.VERSION_UUID;
profile_uuid = window.PROFILE_UUID;
ajaxurl = window.AJAXURL;
var fields = JSON.parse(_.unescape($('#form-json')[0].textContent));
var errors = JSON.parse(_.unescape($('#error-json')[0].textContent));
......@@ -58,7 +60,8 @@ function (_, sup, filesize, ShowImagingModal,
gotrspec: gotrspec,
action: window.ACTION,
button_label: window.BUTTONLABEL,
uuid: window.UUID,
version_uuid: window.VERSION_UUID,
profile_uuid: window.PROFILE_UUID,
candelete: window.CANDELETE,
canmodify: window.CANMODIFY,
canpublish: window.CANPUBLISH,
......@@ -617,7 +620,7 @@ function (_, sup, filesize, ShowImagingModal,
var xmlthing = sup.CallServerMethod(ajaxurl,
"manage_profile",
"InstantiateAsGuest",
{"uuid" : uuid});
{"uuid" : version_uuid});
xmlthing.done(callback);
}
......@@ -638,7 +641,7 @@ function (_, sup, filesize, ShowImagingModal,
}
sup.HideModal("#instantiate_modal");
var blob = {"uuid" : uuid};
var blob = {"uuid" : version_uuid};
if (amlist.length) {
blob.where = $('#instantiate_where').val();
}
......@@ -659,7 +662,7 @@ function (_, sup, filesize, ShowImagingModal,
return sup.CallServerMethod(ajaxurl,
"manage_profile",
"CloneStatus",
{"uuid" : uuid});
{"uuid" : version_uuid});
},
function(failed)
{
......@@ -745,7 +748,7 @@ function (_, sup, filesize, ShowImagingModal,
var xmlthing = sup.CallServerMethod(ajaxurl,
"manage_profile",
"DeleteProfile",
{"uuid" : uuid});
{"uuid" : version_uuid});
xmlthing.done(callback);
}
......@@ -773,7 +776,7 @@ function (_, sup, filesize, ShowImagingModal,
var xmlthing = sup.CallServerMethod(ajaxurl,
"manage_profile",
"PublishProfile",
{"uuid" : uuid});
{"uuid" : version_uuid});
xmlthing.done(callback);
}
......
......@@ -72,11 +72,14 @@ function SPITFORM($formfields, $errors)
$canpublish = 0;
$history = 0;
$activity = 0;
$version_uuid = "null";
$profile_uuid = "null";
if ($action == "edit") {
$button_label = "Modify";
$viewing = 1;
$uuid = $profile->uuid();
$version_uuid = "'" . $profile->uuid() . "'";
$profile_uuid = "'" . $profile->profile_uuid() . "'";
$candelete = ($profile->IsHead() && !$profile->published() ? 1 : 0);
$history = ($profile->HasHistory() ? 1 : 0);
$canmodify = ($profile->CanModify() ? 1 : 0);
......@@ -142,7 +145,8 @@ function SPITFORM($formfields, $errors)
echo "<script type='text/javascript'>\n";
echo " window.VIEWING = $viewing;\n";
echo " window.UUID = " . (isset($uuid) ? "'$uuid'" : "null") . ";\n";
echo " window.VERSION_UUID = $version_uuid;\n";
echo " window.PROFILE_UUID = $profile_uuid;\n";
echo " window.UPDATED = $notifyupdate;\n";
echo " window.SNAPPING = $notifyclone;\n";
echo " window.AJAXURL = 'server-ajax.php';\n";
......@@ -236,7 +240,6 @@ if (! isset($create)) {
}
}
else {
$defaults["profile_uuid"] = $profile->uuid();
$defaults["profile_pid"] = $profile->pid();
$defaults["profile_name"] = $profile->name();
$defaults["profile_version"] = $profile->version();
......@@ -245,7 +248,8 @@ if (! isset($create)) {
$defaults["profile_created"] = $profile->created();
$defaults["profile_published"] =
($profile->published() ? $profile->published() : "");
$defaults["profile_url"] = $profile->url();
$defaults["profile_version_url"] = $profile->URL();
$defaults["profile_profile_url"] = $profile->ProfileURL();
$defaults["profile_listed"] =
($profile->listed() ? "checked" : "");
$defaults["profile_who"] =
......
......@@ -34,15 +34,33 @@ class Profile
$safe_profileid = addslashes($token);
if (preg_match("/^\w+\-\w+\-\w+\-\w+\-\w+$/", $token)) {
#
# First look to see if the uuid is for the profile itself,
# which means current version. Otherwise look for a
# version with the uuid.
#
$query_result =
DBQueryWarn("select i.*,v.* from apt_profile_versions as v ".
"left join apt_profiles as i on ".
" i.profileid=v.profileid ".
"where v.uuid='$token' and v.deleted is null");
DBQueryWarn("select i.*,v.*,i.uuid as profile_uuid ".
" from apt_profiles as i ".
"left join apt_profile_versions as v on ".
" v.profileid=i.profileid and ".
" v.version=i.version ".
"where i.uuid='$token' and v.deleted is null");
if (!$query_result || !mysql_num_rows($query_result)) {
$query_result =
DBQueryWarn("select i.*,v.*,i.uuid as profile_uuid ".
" from apt_profile_versions as v ".
"left join apt_profiles as i on ".
" v.profileid=i.profileid ".
"where v.uuid='$token' and ".
" v.deleted is null");
}
}
elseif (is_null($version)) {
$query_result =
DBQueryWarn("select i.*,v.* from apt_profiles as i ".
DBQueryWarn("select i.*,v.*,i.uuid as profile_uuid ".
" from apt_profiles as i ".
"left join apt_profile_versions as v on ".
" v.profileid=i.profileid and ".
" v.version=i.version ".
......@@ -51,7 +69,8 @@ class Profile
else {
$safe_version = addslashes($version);
$query_result =
DBQueryWarn("select i.*,v.* from apt_profile_versions as v ".
DBQueryWarn("select i.*,v.*,i.uuid as profile_uuid ".
" from apt_profile_versions as v ".
"left join apt_profiles as i on ".
" i.profileid=v.profileid ".
"where v.profileid='$safe_profileid' and ".
......@@ -82,6 +101,7 @@ class Profile
function published() { return $this->field('published'); }
function deleted() { return $this->field('deleted'); }
function uuid() { return $this->field('uuid'); }
function profile_uuid() { return $this->field('profile_uuid'); }
function ispublic() { return $this->field('public'); }
function shared() { return $this->field('shared'); }
function listed() { return $this->field('listed'); }
......@@ -147,6 +167,26 @@ class Profile
return null;
}
#
# Lookup the most recently published version of a profile.
#
function LookupMostRecentPublished() {
$profileid = $this->profileid();
$query_result =
DBQueryWarn("select version from apt_profile_versions as v ".
"where v.profileid='$profileid' and ".
" published is not null and ".
" deleted is null ".
"order by published desc limit 1");
if (!$query_result || !mysql_num_rows($query_result)) {
return null;
}
$row = mysql_fetch_row($query_result);
return Profile::Lookup($profileid, $row[0]);
}
#
# Refresh an instance by reloading from the DB.
#
......@@ -172,10 +212,10 @@ class Profile
}
#
# URL.
# URL. To the specific version of the profile.
#
function URL() {
global $APTBASE;
global $APTBASE, $ISVSERVER;
$uuid = $this->uuid();
......@@ -183,10 +223,34 @@ class Profile
$pid = $this->pid();
$name = $this->name();
$vers = $this->version();
return "$APTBASE/p/$pid/$name/$vers";
if ($ISVSERVER)
return "$APTBASE/p/$pid/$name/$vers";
return "$APTBASE/instantiate.php?profile=$name".
"&project=$pid&version=$vers";
}
else {
if ($ISVSERVER)
return "$APTBASE/p/$uuid";
return "$APTBASE/instantiate.php?profile=$uuid";
}
}
# And the URL of the profile itself.
function ProfileURL() {
global $APTBASE;
$uuid = $this->profile_uuid();
if ($this->ispublic()) {
$pid = $this->pid();
$name = $this->name();
if ($ISVSERVER)
return "$APTBASE/p/$pid/$name";
return "$APTBASE/instantiate.php?profile=$name&project=$pid";
}
else {
return "$APTBASE/p/$uuid";
if ($ISVSERVER)
return "$APTBASE/p/$uuid";
return "$APTBASE/instantiate.php?profile=$uuid";
}
}
......
......@@ -29,6 +29,7 @@ $FAVICON = "aptlab.ico";
$APTLOGO = "aptlogo.png";
$APTSTYLE = "apt.css";
$ISAPT = 1;
$ISVSERVER = 0;
#
# Global flag to disable accounts. We do this on some pages which
......@@ -44,6 +45,7 @@ $disable_accounts = 0;
# and forth.
#
if ($TBMAINSITE && $_SERVER["SERVER_NAME"] == "www.aptlab.net") {
$ISVSERVER = 1;
$TBAUTHDOMAIN = ".aptlab.net";
$APTHOST = "www.aptlab.net";
$WWWHOST = "www.aptlab.net";
......@@ -51,6 +53,7 @@ if ($TBMAINSITE && $_SERVER["SERVER_NAME"] == "www.aptlab.net") {
$APTMAIL = "APT Operations <testbed-ops@aptlab.net>";
}
elseif ($TBMAINSITE && $_SERVER["SERVER_NAME"] == "www.cloudlab.us") {
$ISVSERVER = 1;
$TBAUTHDOMAIN = ".cloudlab.us";
$APTHOST = "www.cloudlab.us";
$WWWHOST = "www.cloudlab.us";
......
......@@ -34,12 +34,30 @@
<td>Published:</td>
<td id='profile_published'><%- formfields.profile_published %></td>
</tr>
<tr>
<td>Version&nbspURL:</td>
<td><a href='<%- formfields.profile_version_url %>'
data-toggle="popover" data-html='true'
data-content="Anyone with this URL can instantiate this
<b>version</b> of your profile."
data-triger='hover'>https://...</a>
</td>
</tr>
<tr>
<td>Profile&nbspURL:</td>
<td><a href='<%- formfields.profile_profile_url %>'
data-toggle="popover" data-html='true'
data-content="This URL instantiates the
most recently <b>published</b> version of your profile."
data-triger='hover'>https://...</a>
</td>
</tr>
</table>
<% if (history) { %>
<a class='btn btn-info btn-xs pull-left'
id='profile_history_button'
style='margin-right: 10px; font-size: 12px'
href='profile-history.php?uuid=<%= uuid %>'
href='profile-history.php?uuid=<%= profile_uuid %>'
type='button'>History
</a>
<% } %>
......@@ -47,7 +65,7 @@
<a class='btn btn-info btn-xs pull-left'
id='profile_activity_button'
style='margin-right: 10px; font-size: 12px'
href='profile-activity.php?uuid=<%= uuid %>'
href='profile-activity.php?uuid=<%= profile_uuid %>'
type='button'>Activity
</a>
<% } %>
......@@ -90,7 +108,7 @@
</div>
</div>
<% if (viewing) { %>
<input type='hidden' name='uuid' value='<%= uuid %>'>
<input type='hidden' name='uuid' value='<%= version_uuid %>'>
<input type='hidden' name='formfields[profile_name]'
value='<%- formfields.profile_name %>'>
<input type='hidden' name='formfields[profile_pid]'
......@@ -291,15 +309,15 @@
</div>
<!-- The private URL -->
<% if (viewing) { %>
<input name="formfields[profile_url]"
value="<%- formfields.profile_url %>"
<% if (0) { %>
<input name="formfields[profile_version_url]"
value="<%- formfields.profile_version_url %>"
id='profile_url' readonly
class='form-control format-me'
data-key='profile_url'
data-label='Shared URL'
data-help='Anyone with this URL can instantiate
this profile'
this <b>version</b> of your profile'
type='text'>
<% } %>
</fieldset>
......
......@@ -3,11 +3,18 @@
<div class='modal-dialog'>
<div class='modal-content'>
<div class='modal-body'>
<p>Do you want to publish your profile ... explain what this
means ...
<p>
There are two types of profiles: working versions that should be
considered ephemeral, and published versions that are intended to
be long-term stable. For example, you may generate many working
versions as you refine the software, fix bugs, etc. Then, when
the profile is in a state where it is appropriate to share with
others, it can be published.
</p>
<br>
<center>
Do you want to publish your profile?
<br><br>
<button type='button' style='margin-right: 20px;'
class='btn btn-primary btn-sm'
data-dismiss='modal' aria-hidden='true'>
......
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