Skip to content

Commit eefdbfd

Browse files
committed
Link generator handles non-git sources
The link generator creates gitpuller links for non-git sources including archives from google drive, dropbox and any publicly accessible web URL. In order to handle a non- git source correctly in nbgitpuller, we added the provider parameter to the URL string. Other Changes: - if git is the source, the branch parameter is always included on the URL and defaults to 'main' if none is provided. This should then allow users that have not upgraded their nbgitpuller version to still work. - All sources(git and non-git) can handle a path to a particular folder or notebook. I had taken this ability away from non-git sources in earlier versions.
1 parent a1ea521 commit eefdbfd

File tree

3 files changed

+243
-46
lines changed

3 files changed

+243
-46
lines changed

.circleci/config.yml

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
version: 2.1
2+
jobs:
3+
build:
4+
docker:
5+
- image: circleci/python:3.6
6+
steps:
7+
- run: echo "no operation build"
8+
9+
workflows:
10+
build:
11+
jobs:
12+
- build

_static/link_gen/link.js

+145-34
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,25 @@
11
// Pure function that generates an nbgitpuller URL
2-
function generateRegularUrl(hubUrl, urlPath, repoUrl, branch) {
2+
function generateRegularUrl(hubUrl, urlPath, repoUrl, branch, compressed, source) {
33

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

77
url.searchParams.set('repo', repoUrl);
8-
8+
9+
if(compressed) {
10+
url.searchParams.set('provider', source);
11+
}
12+
913
if (urlPath) {
1014
url.searchParams.set('urlpath', urlPath);
1115
}
1216

1317
if (branch) {
1418
url.searchParams.set('branch', branch);
19+
} else if(source == "git"){
20+
url.searchParams.set('branch', "main");
1521
}
16-
22+
1723
if (!url.pathname.endsWith('/')) {
1824
url.pathname += '/'
1925
}
@@ -22,20 +28,26 @@ function generateRegularUrl(hubUrl, urlPath, repoUrl, branch) {
2228
return url.toString();
2329
}
2430

25-
function generateCanvasUrl(hubUrl, urlPath, repoUrl, branch) {
31+
function generateCanvasUrl(hubUrl, urlPath, repoUrl, branch, compressed, source) {
2632
// assume hubUrl is a valid URL
2733
var url = new URL(hubUrl);
2834

2935
var nextUrlParams = new URLSearchParams();
3036

3137
nextUrlParams.append('repo', repoUrl);
32-
38+
39+
if(compressed) {
40+
nextUrlParams.append('provider', source);
41+
}
42+
3343
if (urlPath) {
3444
nextUrlParams.append('urlpath', urlPath);
3545
}
3646

3747
if (branch) {
3848
nextUrlParams.append('branch', branch);
49+
} else if(source == "git"){
50+
nextUrlParams.append('branch', "main");
3951
}
4052

4153
var nextUrl = '/hub/user-redirect/git-pull?' + nextUrlParams.toString();
@@ -50,20 +62,26 @@ function generateCanvasUrl(hubUrl, urlPath, repoUrl, branch) {
5062
}
5163

5264
function generateBinderUrl(hubUrl, userName, repoName, branch, urlPath,
53-
contentRepoUrl, contentRepoBranch) {
65+
contentRepoUrl, contentRepoBranch, compressed, source) {
5466

5567
var url = new URL(hubUrl);
5668

5769
var nextUrlParams = new URLSearchParams();
5870

5971
nextUrlParams.append('repo', contentRepoUrl);
6072

73+
if(compressed) {
74+
nextUrlParams.append('provider', source);
75+
}
76+
6177
if (urlPath) {
6278
nextUrlParams.append('urlpath', urlPath);
6379
}
6480

6581
if (contentRepoBranch) {
6682
nextUrlParams.append('branch', contentRepoBranch);
83+
} else if(source == "git"){
84+
nextUrlParams.append('branch', "main");
6785
}
6886

6987
var nextUrl = 'git-pull?' + nextUrlParams.toString();
@@ -100,37 +118,46 @@ var apps = {
100118
}
101119
}
102120

121+
function clearLinks(){
122+
document.getElementById('default-link').value = "";
123+
document.getElementById('binder-link').value = "";
124+
document.getElementById('canvas-link').value = "";
125+
}
126+
127+
103128
function changeTab(div) {
104129
var hub = document.getElementById("hub");
105130
var hub_help_text = document.getElementById("hub-help-text");
106-
var env_repo = document.getElementById("repo");
107-
var env_repo_branch = document.getElementById("branch");
108-
var env_repo_help_text = document.getElementById("env-repo-help-text");
109-
var content_repo = document.getElementById("content-repo-group");
110-
var content_branch = document.getElementById("content-branch-group");
131+
var env_repo_group = document.getElementById("env-repo-group");
132+
var env_repo = document.getElementById("env-repo");
133+
<<<<<<< HEAD
134+
=======
135+
// var env_repo_branch = document.getElementById("env-branch");
136+
// var env_repo_help_text = document.getElementById("env-repo-help-text");
137+
>>>>>>> b5b1e8e... JupyterHub link gen working
111138
var id = div.id;
112-
139+
var form = document.getElementById('linkgenerator');
140+
141+
clearLinks();
113142
if (id.includes("binder")) {
114143
hub.placeholder = "https://mybinder.org";
115144
hub.value = "https://mybinder.org";
116145
hub_help_text.hidden = true;
117146
hub.labels[0].innerHTML = "BinderHub URL";
118-
env_repo.labels[0].innerHTML = "Git Environment Repository URL";
119-
env_repo_help_text.hidden = false;
120-
env_repo_branch.required = true;
121-
env_repo_branch.pattern = ".+";
122-
content_repo.hidden = false;
123-
content_branch.hidden = false;
147+
148+
env_repo_group.style.display = '';
149+
env_repo.disabled = false;
150+
124151
} else {
125152
hub.placeholder = "https://hub.example.com";
153+
hub.value = "";
126154
hub_help_text.hidden = false;
127155
hub.labels[0].innerHTML = "JupyterHub URL";
128-
env_repo.labels[0].innerHTML = "Git Repository URL";
129-
env_repo_help_text.hidden = true;
130-
env_repo_branch.required = false;
131-
content_repo.hidden = true;
132-
content_branch.hidden = true;
156+
157+
env_repo_group.style.display = 'none';
158+
env_repo.disabled = true;
133159
}
160+
displaySource();
134161
}
135162

136163
/**
@@ -141,28 +168,60 @@ function changeTab(div) {
141168
* See https://github.com/git/git/blob/1c52ecf4ba0f4f7af72775695fee653f50737c71/builtin/clone.c#L276
142169
*/
143170
function generateCloneDirectoryName(gitCloneUrl) {
171+
if(gitCloneUrl.slice(-1) == "/")
172+
gitCloneUrl = gitCloneUrl.slice(0,-1);
144173
var lastPart = gitCloneUrl.split('/').slice(-1)[0];
145174
return lastPart.split(':').slice(-1)[0].replace(/(\.git|\.bundle)?/, '');
146175
}
147176

177+
function handleSource(args){
178+
source = args["source"];
179+
branch = "";
180+
compressed = true;
181+
sourceUrl ="";
182+
if(source == "git"){
183+
sourceUrl = args["contentRepoUrl"];
184+
branch = args["contentRepoBranch"];
185+
compressed = false;
186+
} else if(source == "googledrive"){
187+
sourceUrl = args["driveUrl"];
188+
} else if(source == "dropbox"){
189+
sourceUrl = args["dropUrl"];
190+
} else if(source == "standard"){
191+
sourceUrl = args["webUrl"];
192+
}
193+
return {
194+
"branch": branch,
195+
"sourceUrl": sourceUrl,
196+
"compressed": compressed
197+
}
198+
}
199+
148200
function displayLink() {
149201
var form = document.getElementById('linkgenerator');
150-
202+
151203
form.classList.add('was-validated');
152204
if (form.checkValidity()) {
153205
var hubUrl = document.getElementById('hub').value;
154-
var repoUrl = document.getElementById('repo').value;
155-
var branch = document.getElementById('branch').value;
206+
var driveUrl = document.getElementById('drive-url').value;
207+
var dropUrl = document.getElementById('drop-url').value;
208+
var webUrl = document.getElementById('standard-url').value;
209+
var envRepoUrl = document.getElementById('env-repo').value;
210+
var envGitBranch = document.getElementById('env-branch').value;
156211
var contentRepoUrl = document.getElementById('content-repo').value;
157212
var contentRepoBranch = document.getElementById('content-branch').value;
158213
var filePath = document.getElementById('filepath').value;
159214
var appName = form.querySelector('input[name="app"]:checked').value;
160215
var activeTab = document.querySelector(".nav-link.active").id;
161-
216+
var source = form.querySelector('input[name="source"]:checked').value;
217+
162218
if (appName === 'custom') {
163219
var urlPath = document.getElementById('urlpath').value;
164220
} else {
165-
var repoName = generateCloneDirectoryName(repoUrl);
221+
var repoName = generateCloneDirectoryName(contentRepoUrl);
222+
if(source !== "git"){
223+
repoName = ""
224+
}
166225
var urlPath;
167226
if (activeTab === "tab-auth-binder") {
168227
var contentRepoName = new URL(contentRepoUrl).pathname.split('/').pop().replace(/\.git$/, '');
@@ -171,26 +230,37 @@ function displayLink() {
171230
urlPath = apps[appName].generateUrlPath(repoName + '/' + filePath);
172231
}
173232
}
174-
233+
args = {
234+
"source": source,
235+
"contentRepoUrl": contentRepoUrl,
236+
"contentRepoBranch": contentRepoBranch,
237+
"driveUrl": driveUrl,
238+
"dropUrl": dropUrl,
239+
"webUrl": webUrl
240+
}
241+
config = handleSource(args)
175242
if (activeTab === "tab-auth-default") {
176243
document.getElementById('default-link').value = generateRegularUrl(
177-
hubUrl, urlPath, repoUrl, branch
244+
hubUrl, urlPath, config["sourceUrl"], config["branch"], config["compressed"], source
178245
);
179246
} else if (activeTab === "tab-auth-canvas"){
180247
document.getElementById('canvas-link').value = generateCanvasUrl(
181-
hubUrl, urlPath, repoUrl, branch
248+
hubUrl, urlPath, config["sourceUrl"], config["branch"], config["compressed"], source
182249
);
183250
} else if (activeTab === "tab-auth-binder"){
184251
// FIXME: userName parsing using new URL(...) assumes a
185252
// HTTP based repoUrl. Does it make sense to create a
186253
// BinderHub link for SSH URLs? Then let's fix this parsing.
187-
var userName = new URL(repoUrl).pathname.split('/')[1];
254+
var userName = new URL(envRepoUrl).pathname.split('/')[1];
188255
document.getElementById('binder-link').value = generateBinderUrl(
189-
hubUrl, userName, repoName, branch, urlPath, contentRepoUrl, contentRepoBranch
256+
hubUrl, userName, repoName, envGitBranch, urlPath, config["sourceUrl"], config["branch"], config["compressed"], source
190257
);
191258
}
259+
} else {
260+
clearLinks();
192261
}
193262
}
263+
194264
function populateFromQueryString() {
195265
// preseed values if specified in the url
196266
var params = new URLSearchParams(window.location.search);
@@ -213,6 +283,33 @@ function populateFromQueryString() {
213283
}
214284
}
215285

286+
function hideShowByClassName(cls, hideShow){
287+
[].forEach.call(document.querySelectorAll(cls), function (el) {
288+
el.style.display = hideShow;
289+
setDisabled = (hideShow == 'none')
290+
$(el).find("input").each(function(){
291+
$(this).prop("disabled", setDisabled);
292+
});
293+
});
294+
}
295+
296+
297+
function displaySource(){
298+
var form = document.getElementById('linkgenerator');
299+
var source = form.querySelector('input[name="source"]:checked').value;
300+
hideShowByClassName(".source", 'none');
301+
302+
if(source == 'git'){
303+
hideShowByClassName(".source-git", '');
304+
} else if(source == 'googledrive'){
305+
hideShowByClassName(".source-googledrive", '');
306+
} else if(source == 'dropbox'){
307+
hideShowByClassName(".source-dropbox", '');
308+
} else if(source =="standard"){
309+
hideShowByClassName(".source-standard", '');
310+
}
311+
}
312+
216313
/**
217314
* Main loop of the program.
218315
*
@@ -225,6 +322,7 @@ function render() {
225322
var form = document.getElementById('linkgenerator');
226323
var appName = form.querySelector('input[name="app"]:checked').value;
227324

325+
228326
if (appName == 'custom') {
229327
document.getElementById('urlpath').disabled = false;
230328
document.getElementById('filepath').disabled = true;
@@ -238,6 +336,7 @@ function render() {
238336
document.getElementById('filepath').disabled = false;
239337
}
240338
}
339+
241340
displayLink();
242341
}
243342

@@ -246,11 +345,21 @@ function render() {
246345
*/
247346
function main() {
248347
// Hook up any changes in form elements to call render()
249-
document.querySelectorAll('#linkgenerator input[type="radio"]').forEach(
348+
document.querySelectorAll('#linkgenerator input[name="app"]').forEach(
250349
function (element) {
251350
element.addEventListener('change', render);
252351
}
253352
)
353+
document.querySelectorAll('#linkgenerator input[name="source"]').forEach(
354+
function (element) {
355+
element.addEventListener('change', function(){
356+
displaySource();
357+
render();
358+
}
359+
);
360+
}
361+
)
362+
254363
document.querySelectorAll('#linkgenerator input[type="text"], #linkgenerator input[type="url"]').forEach(
255364
function (element) {
256365
element.addEventListener('input', render);
@@ -269,7 +378,9 @@ function main() {
269378
}
270379
}
271380

381+
272382
// Do an initial render, to make sure our disabled / enabled properties are correctly set
383+
displaySource();
273384
render();
274385
}
275386

0 commit comments

Comments
 (0)