Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Link generator handles non-git sources #195

Open
wants to merge 13 commits into
base: gh-pages
Choose a base branch
from
204 changes: 158 additions & 46 deletions _static/link_gen/link.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
// Pure function that generates an nbgitpuller URL
function generateRegularUrl(hubUrl, urlPath, repoUrl, branch) {
function generateRegularUrl(hubUrl, urlPath, repoUrl, branch, compressed, contentProvider) {

// assume hubUrl is a valid URL
var url = new URL(hubUrl);

url.searchParams.set('repo', repoUrl);

if(compressed) {
url.searchParams.set('content_provider', contentProvider);
sean-morris marked this conversation as resolved.
Show resolved Hide resolved
}
if (urlPath) {
url.searchParams.set('urlpath', urlPath);
}

if (branch) {
url.searchParams.set('branch', branch);
} else if(contentProvider == "git"){
url.searchParams.set('branch', "main");
}

if (!url.pathname.endsWith('/')) {
consideRatio marked this conversation as resolved.
Show resolved Hide resolved
Expand All @@ -22,20 +26,24 @@ function generateRegularUrl(hubUrl, urlPath, repoUrl, branch) {
return url.toString();
}

function generateCanvasUrl(hubUrl, urlPath, repoUrl, branch) {
function generateCanvasUrl(hubUrl, urlPath, repoUrl, branch, compressed, contentProvider) {
// assume hubUrl is a valid URL
var url = new URL(hubUrl);

var nextUrlParams = new URLSearchParams();

nextUrlParams.append('repo', repoUrl);

if(compressed) {
nextUrlParams.append('content_provider', contentProvider);
sean-morris marked this conversation as resolved.
Show resolved Hide resolved
}
if (urlPath) {
nextUrlParams.append('urlpath', urlPath);
}

if (branch) {
nextUrlParams.append('branch', branch);
} else if(contentProvider == "git"){
nextUrlParams.append('branch', "main");
}

var nextUrl = '/hub/user-redirect/git-pull?' + nextUrlParams.toString();
Expand All @@ -49,27 +57,35 @@ function generateCanvasUrl(hubUrl, urlPath, repoUrl, branch) {
return url.toString();
}

function generateBinderUrl(hubUrl, userName, repoName, branch, urlPath,
contentRepoUrl, contentRepoBranch) {
function generateBinderUrl(hubUrl, userName, envRepoName, envGitBranch, urlPath,
contentGitRepoUrl, contentGitRepoBranch, compressed, contentProvider) {

var url = new URL(hubUrl);

var nextUrlParams = new URLSearchParams();

nextUrlParams.append('repo', contentRepoUrl);
nextUrlParams.append('repo', contentGitRepoUrl);

if(compressed) {
nextUrlParams.append('content_provider', contentProvider);
sean-morris marked this conversation as resolved.
Show resolved Hide resolved
}
if (urlPath) {
nextUrlParams.append('urlpath', urlPath);
}

if (contentRepoBranch) {
nextUrlParams.append('branch', contentRepoBranch);
if (contentGitRepoBranch) {
nextUrlParams.append('branch', contentGitRepoBranch);
} else if(contentProvider == "git"){
nextUrlParams.append('branch', "main");
}

if(envGitBranch == ""){
envGitBranch = "main"
}
var nextUrl = 'git-pull?' + nextUrlParams.toString();

var path = '/v2/gh/';
url.pathname = path.concat(userName, "/", repoName, "/", branch);
url.pathname = path.concat(userName, "/", envRepoName, "/", envGitBranch);
url.searchParams.append('urlpath', nextUrl);

return url.toString();
Expand Down Expand Up @@ -100,37 +116,37 @@ var apps = {
}
}

function clearLinks(){
document.getElementById('default-link').value = "";
document.getElementById('binder-link').value = "";
document.getElementById('canvas-link').value = "";
}

function changeTab(div) {
var hub = document.getElementById("hub");
var hub_help_text = document.getElementById("hub-help-text");
var env_repo = document.getElementById("repo");
var env_repo_branch = document.getElementById("branch");
var env_repo_help_text = document.getElementById("env-repo-help-text");
var content_repo = document.getElementById("content-repo-group");
var content_branch = document.getElementById("content-branch-group");
var env_repo_group = document.getElementById("env-repo-group");
var env_repo = document.getElementById("env-repo");
consideRatio marked this conversation as resolved.
Show resolved Hide resolved
var id = div.id;

var form = document.getElementById('linkgenerator');
clearLinks();
if (id.includes("binder")) {
hub.placeholder = "https://mybinder.org";
hub.value = "https://mybinder.org";
hub_help_text.hidden = true;
hub.labels[0].innerHTML = "BinderHub URL";
env_repo.labels[0].innerHTML = "Git Environment Repository URL";
env_repo_help_text.hidden = false;
env_repo_branch.required = true;
env_repo_branch.pattern = ".+";
content_repo.hidden = false;
content_branch.hidden = false;
env_repo_group.style.display = '';
env_repo.disabled = false;
} else {
hub.placeholder = "https://hub.example.com";
hub.value = "";
hub_help_text.hidden = false;
hub.labels[0].innerHTML = "JupyterHub URL";
env_repo.labels[0].innerHTML = "Git Repository URL";
env_repo_help_text.hidden = true;
env_repo_branch.required = false;
content_repo.hidden = true;
content_branch.hidden = true;

env_repo_group.style.display = 'none';
env_repo.disabled = true;
}
displayContentProvider();
}

/**
Expand All @@ -139,58 +155,116 @@ function changeTab(div) {
* nbgitpuller needs to redirect users to *inside* the directory it
* just cloned. We copy the logic git itself uses to determine that.
* See https://github.com/git/git/blob/1c52ecf4ba0f4f7af72775695fee653f50737c71/builtin/clone.c#L276
*
* The condition on the first line of this function ensures the user has not included a forward slash at the end of
* the URL. If they do, it is removed so that the rest of the function can split by forward slash and parse the name
* of directory from the URL.
*
* @param {string} gitCloneUrl This is the url to the git repo
*/
function generateCloneDirectoryName(gitCloneUrl) {
if(gitCloneUrl.slice(-1) == "/")
gitCloneUrl = gitCloneUrl.slice(0,-1);
var lastPart = gitCloneUrl.split('/').slice(-1)[0];
return lastPart.split(':').slice(-1)[0].replace(/(\.git|\.bundle)?/, '');
}
consideRatio marked this conversation as resolved.
Show resolved Hide resolved

/**
* This takes the values from the UI for content providers and sets three values in a
* json object(contentProviderUrl, branch, and compressed) based on what contentProvider is selected in the UI.
*
* The args contains the contentProvider selected in the UI as well as whatever text(if any)
* is in each of the content provider URL(e.g. driveURL, dropURL) text boxes, as well as the contentGitBranch.
*
* The return value is a a json object containing the branch, which may be an empty string if git is not the content
* provider, the contentProviderURL, and a boolean key, compressed, that indicates if you our notebooks are in a
* compressed archive.
*
* @param {json} args - contains UI element values for content providers(url, git branch,
*/
function configureContentProviderAttrs(args){
contentProvider = args["contentProvider"];
branch = "";
compressed = true;
contentProviderURL ="";
if(contentProvider == "git"){
contentProviderURL = args["contentGitRepoUrl"];
branch = args["contentGitRepoBranch"];
compressed = false;
} else if(contentProvider == "googledrive"){
contentProviderURL = args["driveUrl"];
} else if(contentProvider == "dropbox"){
contentProviderURL = args["dropUrl"];
} else if(contentProvider == "generic_web"){
contentProviderURL = args["webUrl"];
}
return {
"branch": branch,
"contentProviderURL": contentProviderURL,
"compressed": compressed
sean-morris marked this conversation as resolved.
Show resolved Hide resolved
}
}

function displayLink() {
var form = document.getElementById('linkgenerator');

form.classList.add('was-validated');
if (form.checkValidity()) {
var hubUrl = document.getElementById('hub').value;
var repoUrl = document.getElementById('repo').value;
var branch = document.getElementById('branch').value;
var contentRepoUrl = document.getElementById('content-repo').value;
var contentRepoBranch = document.getElementById('content-branch').value;
var driveUrl = document.getElementById('drive-url').value;
var dropUrl = document.getElementById('drop-url').value;
var webUrl = document.getElementById('generic-web-url').value;
var envGitRepoUrl = document.getElementById('env-repo').value;
var envGitBranch = document.getElementById('env-branch').value;
var contentGitRepoUrl = document.getElementById('content-repo').value;
var contentGitRepoBranch = document.getElementById('content-branch').value;
var filePath = document.getElementById('filepath').value;
var appName = form.querySelector('input[name="app"]:checked').value;
var activeTab = document.querySelector(".nav-link.active").id;

var contentProvider = form.querySelector('input[name="content-provider"]:checked').value;

consideRatio marked this conversation as resolved.
Show resolved Hide resolved
if (appName === 'custom') {
var urlPath = document.getElementById('urlpath').value;
} else {
var repoName = generateCloneDirectoryName(repoUrl);
var urlPath;
if (activeTab === "tab-auth-binder") {
var contentRepoName = new URL(contentRepoUrl).pathname.split('/').pop().replace(/\.git$/, '');
urlPath = apps[appName].generateUrlPath(contentRepoName + '/' + filePath);
} else {
urlPath = apps[appName].generateUrlPath(repoName + '/' + filePath);
var envGitRepoName = generateCloneDirectoryName(envGitRepoUrl);
var contentGitRepoName = generateCloneDirectoryName(contentGitRepoUrl);
var partialUrlPath = contentGitRepoName + '/' + filePath;
if(contentProvider !== "git"){
contentGitRepoName = "";
partialUrlPath = filePath;
}
var urlPath = apps[appName].generateUrlPath(partialUrlPath);
}

args = {
"contentProvider": contentProvider,
"contentGitRepoUrl": contentGitRepoUrl,
"contentGitRepoBranch": contentGitRepoBranch,
"driveUrl": driveUrl,
"dropUrl": dropUrl,
"webUrl": webUrl
sean-morris marked this conversation as resolved.
Show resolved Hide resolved
}
config = configureContentProviderAttrs(args)
if (activeTab === "tab-auth-default") {
document.getElementById('default-link').value = generateRegularUrl(
hubUrl, urlPath, repoUrl, branch
hubUrl, urlPath, config["contentProviderURL"], config["branch"], config["compressed"], contentProvider
);
} else if (activeTab === "tab-auth-canvas"){
document.getElementById('canvas-link').value = generateCanvasUrl(
hubUrl, urlPath, repoUrl, branch
hubUrl, urlPath, config["contentProviderURL"], config["branch"], config["compressed"], contentProvider
);
} else if (activeTab === "tab-auth-binder"){
// FIXME: userName parsing using new URL(...) assumes a
// HTTP based repoUrl. Does it make sense to create a
// BinderHub link for SSH URLs? Then let's fix this parsing.
var userName = new URL(repoUrl).pathname.split('/')[1];
var userName = new URL(envGitRepoUrl).pathname.split('/')[1];
document.getElementById('binder-link').value = generateBinderUrl(
hubUrl, userName, repoName, branch, urlPath, contentRepoUrl, contentRepoBranch
hubUrl, userName, envGitRepoName, envGitBranch, urlPath, config["contentProviderURL"], config["branch"], config["compressed"], contentProvider
);
}
} else {
clearLinks();
}
}

function populateFromQueryString() {
// preseed values if specified in the url
var params = new URLSearchParams(window.location.search);
Expand All @@ -213,6 +287,35 @@ function populateFromQueryString() {
}
}

function hideShowByClassName(cls, hideShow){
[].forEach.call(document.querySelectorAll(cls), function (el) {
el.style.display = hideShow;
setDisabled = (hideShow == 'none')
$(el).find("input").each(function(){
$(this).prop("disabled", setDisabled);
});
});
}
/**
* Depending on the content provider selected this hides and shows the appropriate divs
*
*/
function displayContentProvider(){
var form = document.getElementById('linkgenerator');
var contentProvider = form.querySelector('input[name="content-provider"]:checked').value;
hideShowByClassName(".content-provider", 'none');

if(contentProvider == 'git'){
hideShowByClassName(".content-provider-git", '');
} else if(contentProvider == 'googledrive'){
hideShowByClassName(".content-provider-googledrive", '');
} else if(contentProvider == 'dropbox'){
hideShowByClassName(".content-provider-dropbox", '');
} else if(contentProvider =="generic_web"){
hideShowByClassName(".content-provider-generic-web", '');
}
}

/**
* Main loop of the program.
*
Expand Down Expand Up @@ -246,11 +349,19 @@ function render() {
*/
function main() {
// Hook up any changes in form elements to call render()
document.querySelectorAll('#linkgenerator input[type="radio"]').forEach(
document.querySelectorAll('#linkgenerator input[name="app"]').forEach(
function (element) {
element.addEventListener('change', render);
}
)
document.querySelectorAll('#linkgenerator input[name="content-provider"]').forEach(
function (element) {
element.addEventListener('change', function(){
displayContentProvider();
render();
});
}
)
document.querySelectorAll('#linkgenerator input[type="text"], #linkgenerator input[type="url"]').forEach(
function (element) {
element.addEventListener('input', render);
Expand All @@ -270,6 +381,7 @@ function main() {
}

// Do an initial render, to make sure our disabled / enabled properties are correctly set
displayContentProvider();
render();
}

Expand Down
Loading