Skip to content

Commit d2b26ed

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 d2b26ed

File tree

3 files changed

+238
-46
lines changed

3 files changed

+238
-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

+140-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,41 @@ 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");
111133
var id = div.id;
112-
134+
var form = document.getElementById('linkgenerator');
135+
136+
clearLinks();
113137
if (id.includes("binder")) {
114138
hub.placeholder = "https://mybinder.org";
115139
hub.value = "https://mybinder.org";
116140
hub_help_text.hidden = true;
117141
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;
142+
143+
env_repo_group.style.display = '';
144+
env_repo.disabled = false;
145+
124146
} else {
125147
hub.placeholder = "https://hub.example.com";
148+
hub.value = "";
126149
hub_help_text.hidden = false;
127150
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;
151+
152+
env_repo_group.style.display = 'none';
153+
env_repo.disabled = true;
133154
}
155+
displaySource();
134156
}
135157

136158
/**
@@ -141,28 +163,60 @@ function changeTab(div) {
141163
* See https://github.com/git/git/blob/1c52ecf4ba0f4f7af72775695fee653f50737c71/builtin/clone.c#L276
142164
*/
143165
function generateCloneDirectoryName(gitCloneUrl) {
166+
if(gitCloneUrl.slice(-1) == "/")
167+
gitCloneUrl = gitCloneUrl.slice(0,-1);
144168
var lastPart = gitCloneUrl.split('/').slice(-1)[0];
145169
return lastPart.split(':').slice(-1)[0].replace(/(\.git|\.bundle)?/, '');
146170
}
147171

172+
function handleSource(args){
173+
source = args["source"];
174+
branch = "";
175+
compressed = true;
176+
sourceUrl ="";
177+
if(source == "git"){
178+
sourceUrl = args["contentRepoUrl"];
179+
branch = args["contentRepoBranch"];
180+
compressed = false;
181+
} else if(source == "googledrive"){
182+
sourceUrl = args["driveUrl"];
183+
} else if(source == "dropbox"){
184+
sourceUrl = args["dropUrl"];
185+
} else if(source == "standard"){
186+
sourceUrl = args["webUrl"];
187+
}
188+
return {
189+
"branch": branch,
190+
"sourceUrl": sourceUrl,
191+
"compressed": compressed
192+
}
193+
}
194+
148195
function displayLink() {
149196
var form = document.getElementById('linkgenerator');
150-
197+
151198
form.classList.add('was-validated');
152199
if (form.checkValidity()) {
153200
var hubUrl = document.getElementById('hub').value;
154-
var repoUrl = document.getElementById('repo').value;
155-
var branch = document.getElementById('branch').value;
201+
var driveUrl = document.getElementById('drive-url').value;
202+
var dropUrl = document.getElementById('drop-url').value;
203+
var webUrl = document.getElementById('standard-url').value;
204+
var envRepoUrl = document.getElementById('env-repo').value;
205+
var envGitBranch = document.getElementById('env-branch').value;
156206
var contentRepoUrl = document.getElementById('content-repo').value;
157207
var contentRepoBranch = document.getElementById('content-branch').value;
158208
var filePath = document.getElementById('filepath').value;
159209
var appName = form.querySelector('input[name="app"]:checked').value;
160210
var activeTab = document.querySelector(".nav-link.active").id;
161-
211+
var source = form.querySelector('input[name="source"]:checked').value;
212+
162213
if (appName === 'custom') {
163214
var urlPath = document.getElementById('urlpath').value;
164215
} else {
165-
var repoName = generateCloneDirectoryName(repoUrl);
216+
var repoName = generateCloneDirectoryName(contentRepoUrl);
217+
if(source !== "git"){
218+
repoName = ""
219+
}
166220
var urlPath;
167221
if (activeTab === "tab-auth-binder") {
168222
var contentRepoName = new URL(contentRepoUrl).pathname.split('/').pop().replace(/\.git$/, '');
@@ -171,26 +225,37 @@ function displayLink() {
171225
urlPath = apps[appName].generateUrlPath(repoName + '/' + filePath);
172226
}
173227
}
174-
228+
args = {
229+
"source": source,
230+
"contentRepoUrl": contentRepoUrl,
231+
"contentRepoBranch": contentRepoBranch,
232+
"driveUrl": driveUrl,
233+
"dropUrl": dropUrl,
234+
"webUrl": webUrl
235+
}
236+
config = handleSource(args)
175237
if (activeTab === "tab-auth-default") {
176238
document.getElementById('default-link').value = generateRegularUrl(
177-
hubUrl, urlPath, repoUrl, branch
239+
hubUrl, urlPath, config["sourceUrl"], config["branch"], config["compressed"], source
178240
);
179241
} else if (activeTab === "tab-auth-canvas"){
180242
document.getElementById('canvas-link').value = generateCanvasUrl(
181-
hubUrl, urlPath, repoUrl, branch
243+
hubUrl, urlPath, config["sourceUrl"], config["branch"], config["compressed"], source
182244
);
183245
} else if (activeTab === "tab-auth-binder"){
184246
// FIXME: userName parsing using new URL(...) assumes a
185247
// HTTP based repoUrl. Does it make sense to create a
186248
// BinderHub link for SSH URLs? Then let's fix this parsing.
187-
var userName = new URL(repoUrl).pathname.split('/')[1];
249+
var userName = new URL(envRepoUrl).pathname.split('/')[1];
188250
document.getElementById('binder-link').value = generateBinderUrl(
189-
hubUrl, userName, repoName, branch, urlPath, contentRepoUrl, contentRepoBranch
251+
hubUrl, userName, repoName, envGitBranch, urlPath, config["sourceUrl"], config["branch"], config["compressed"], source
190252
);
191253
}
254+
} else {
255+
clearLinks();
192256
}
193257
}
258+
194259
function populateFromQueryString() {
195260
// preseed values if specified in the url
196261
var params = new URLSearchParams(window.location.search);
@@ -213,6 +278,33 @@ function populateFromQueryString() {
213278
}
214279
}
215280

281+
function hideShowByClassName(cls, hideShow){
282+
[].forEach.call(document.querySelectorAll(cls), function (el) {
283+
el.style.display = hideShow;
284+
setDisabled = (hideShow == 'none')
285+
$(el).find("input").each(function(){
286+
$(this).prop("disabled", setDisabled);
287+
});
288+
});
289+
}
290+
291+
292+
function displaySource(){
293+
var form = document.getElementById('linkgenerator');
294+
var source = form.querySelector('input[name="source"]:checked').value;
295+
hideShowByClassName(".source", 'none');
296+
297+
if(source == 'git'){
298+
hideShowByClassName(".source-git", '');
299+
} else if(source == 'googledrive'){
300+
hideShowByClassName(".source-googledrive", '');
301+
} else if(source == 'dropbox'){
302+
hideShowByClassName(".source-dropbox", '');
303+
} else if(source =="standard"){
304+
hideShowByClassName(".source-standard", '');
305+
}
306+
}
307+
216308
/**
217309
* Main loop of the program.
218310
*
@@ -225,6 +317,7 @@ function render() {
225317
var form = document.getElementById('linkgenerator');
226318
var appName = form.querySelector('input[name="app"]:checked').value;
227319

320+
228321
if (appName == 'custom') {
229322
document.getElementById('urlpath').disabled = false;
230323
document.getElementById('filepath').disabled = true;
@@ -238,6 +331,7 @@ function render() {
238331
document.getElementById('filepath').disabled = false;
239332
}
240333
}
334+
241335
displayLink();
242336
}
243337

@@ -246,11 +340,21 @@ function render() {
246340
*/
247341
function main() {
248342
// Hook up any changes in form elements to call render()
249-
document.querySelectorAll('#linkgenerator input[type="radio"]').forEach(
343+
document.querySelectorAll('#linkgenerator input[name="app"]').forEach(
250344
function (element) {
251345
element.addEventListener('change', render);
252346
}
253347
)
348+
document.querySelectorAll('#linkgenerator input[name="source"]').forEach(
349+
function (element) {
350+
element.addEventListener('change', function(){
351+
displaySource();
352+
render();
353+
}
354+
);
355+
}
356+
)
357+
254358
document.querySelectorAll('#linkgenerator input[type="text"], #linkgenerator input[type="url"]').forEach(
255359
function (element) {
256360
element.addEventListener('input', render);
@@ -269,7 +373,9 @@ function main() {
269373
}
270374
}
271375

376+
272377
// Do an initial render, to make sure our disabled / enabled properties are correctly set
378+
displaySource();
273379
render();
274380
}
275381

0 commit comments

Comments
 (0)