-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Adam Paulen
committed
Jan 19, 2025
1 parent
a547224
commit adecdfb
Showing
74 changed files
with
3,696 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,7 +10,7 @@ | |
|
||
# production | ||
/build | ||
dist/ | ||
dist*/ | ||
|
||
# misc | ||
.DS_Store | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
export const images = { | ||
simple: { | ||
"cerit.io/hubs/rstudio:4.3.1-snakemake": "RStudio with R 4.3.1 and Snakemake", | ||
}, | ||
} | ||
|
||
export const sectionTitles = { | ||
simple: "Simple Jupyter Images", | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
<!doctype html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8" /> | ||
<link /> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||
<title>JupyterHub</title> | ||
</head> | ||
|
||
<body> | ||
{% block main %} {% set named_spawners = | ||
user.all_spawners(include_default=False)|list %} | ||
<div id="root"></div> | ||
<script> | ||
const appConfig = { | ||
spawners: { | ||
{% for spawner in named_spawners %} | ||
"{{ spawner.name }}": { | ||
last_activity: {% if spawner.last_activity %} "{{ spawner.last_activity.isoformat() + 'Z' }}"{% else %} null{% endif %}, | ||
url: {% if spawner.ready %} "{{ user.server_url(spawner.name) }}"{% else %} null{% endif %}, | ||
active: {{ "true" if spawner.active else "false" }}, | ||
ready: {{ "true" if spawner.ready else "false" }}, | ||
} {% if not loop.last %}, {% endif %} | ||
{% endfor %} | ||
}, | ||
default_server_active: {{ "true" if default_server.active else "false" }}, | ||
url: "{{ url }}", | ||
userName: "{{ user.name }}", | ||
xsrf: "{{ xsrf_token }}", | ||
}; | ||
</script> | ||
<script type="module" src="/js/home.jsx"></script> | ||
{% endblock main %} | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
.wrapper { | ||
display: flex; | ||
flex-direction: column; | ||
position: absolute; | ||
left: 50%; | ||
transform: translateX(-50%); | ||
width: 50%; | ||
background: rgba(255, 255, 255, 0.5); | ||
padding: 50px; | ||
border-radius: 8px; | ||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); | ||
min-height: 100vh; | ||
} | ||
|
||
.GPU-wrapper { | ||
display: flex; | ||
flex-wrap: wrap; | ||
flex-direction: row; | ||
justify-content: center; | ||
align-items: center; | ||
} | ||
|
||
.GPU-stats { | ||
border: none; | ||
} | ||
|
||
@media (max-width: 768px) { | ||
.wrapper { | ||
display: flex; | ||
flex-direction: column; | ||
position: absolute; | ||
width: 90%; | ||
padding: 5%; | ||
background: rgba(255, 255, 255, 0.5); | ||
border-radius: 8px; | ||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); | ||
min-height: 80vh; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,202 @@ | ||
import "./Form.css"; | ||
import React, { useState, useEffect } from "react"; | ||
import ProgressiveForm from "../../src/components/Form/ProgressiveForm"; | ||
import { EinfraFooter } from "../../src/components/FooterAndHeader/EinfraFooter"; | ||
import { FieldHeader } from "../../src/components/FieldHeader/FieldHeader"; | ||
import { SliderCheckBox } from "../../src/components/SliderCheckBox/SliderCheckBox"; | ||
import { TileSelector } from "../../src/components/TileSelector/TileSelector"; | ||
import JupyterHubHeader from "../../src/components/FooterAndHeader/JupyterHubHeader"; | ||
import { | ||
DropDownButton, | ||
DropDownOption, | ||
} from "../../src/components/DropDownButton/DropDownButton"; | ||
import { | ||
images, | ||
sectionTitles, | ||
} from "../data/formData"; | ||
|
||
const StepOne = ({ setFormData }) => { | ||
const [activeDropdownIndex, setActiveDropdownIndex] = useState(null); | ||
const [selectedDropdownIndex, setSelectedDropdownIndex] = useState(null); | ||
const [activeDropdownOptionIndex, setActiveDropdownOptionIndex] = useState(null); | ||
|
||
const handleErase = (checked) => { | ||
setFormData((prev) => { | ||
const updatedFormData = { ...prev }; | ||
|
||
if (checked) { | ||
updatedFormData.delhome = "delete"; | ||
} else { | ||
delete updatedFormData.delhome; | ||
} | ||
|
||
return updatedFormData; | ||
}); | ||
}; | ||
|
||
const handleSelect = (key, image, index, dindex) => { | ||
setSelectedDropdownIndex(dindex); | ||
setActiveDropdownOptionIndex(index); | ||
setFormData((prev) => ({ | ||
...prev, | ||
dockerimage: image, | ||
})); | ||
}; | ||
|
||
const isActiveIndex = (index) => { | ||
return activeDropdownIndex === index; | ||
}; | ||
|
||
const isSelectedIndex = (index) => { | ||
return selectedDropdownIndex === index; | ||
}; | ||
|
||
let dropDownIndex = 0; | ||
|
||
return ( | ||
<div className="form-wrap"> | ||
<h2>Choosing Image</h2> | ||
{Object.entries(images).map(([key, options], dropdownIndex) => ( | ||
<DropDownButton | ||
key={dropdownIndex} | ||
isActive={true} | ||
onActivate={() => setActiveDropdownIndex(dropdownIndex)} | ||
isSelected={isSelectedIndex(dropdownIndex)} | ||
title={sectionTitles[key]} | ||
> | ||
{Object.entries(options).map(([value, label]) => { | ||
const currentIndex = dropDownIndex++; | ||
return ( | ||
<DropDownOption | ||
index={currentIndex} | ||
activeIndex={activeDropdownOptionIndex} | ||
title={label} | ||
onSelect={() => | ||
handleSelect(key, value, currentIndex, dropdownIndex) | ||
} | ||
/> | ||
); | ||
})} | ||
</DropDownButton> | ||
))} | ||
<h2>Choosing storage</h2> | ||
<FieldHeader | ||
title="Persistent Notebook Home" | ||
infoText="Persistent home means that even when notebook is deleted, the data will persist and can be used again." | ||
> | ||
<DropDownButton | ||
key={0} | ||
isActive={true} | ||
primary={false} | ||
title="New" | ||
> | ||
<SliderCheckBox | ||
title="Erase if home exists" | ||
onChange={handleErase} | ||
id="phCheckId" | ||
></SliderCheckBox> | ||
<div> | ||
Mounted to | ||
<code>/home/jovyan</code> | ||
</div> | ||
</DropDownButton> | ||
</FieldHeader> | ||
</div> | ||
); | ||
}; | ||
|
||
|
||
const StepThree = ({ setFormData }) => { | ||
|
||
const handleCPUSelect = (value) => { | ||
setFormData((prev) => ({ | ||
...prev, | ||
cpuselection: value, | ||
})); | ||
}; | ||
|
||
const handleMemSelect = (value) => { | ||
setFormData((prev) => ({ | ||
...prev, | ||
memselection: value, | ||
})); | ||
}; | ||
|
||
return ( | ||
<div className="form-wrap"> | ||
<h2>Resources</h2> | ||
<p> | ||
The notebook is spawned only when one node fulfills <b>all</b> your | ||
requirements. | ||
</p> | ||
<TileSelector | ||
setFormData={handleCPUSelect} | ||
title="CPU" | ||
selectionText="Select CPU limit:" | ||
numberOptions={[1, 4, 6, 8, 10, 16, 24, 32]} | ||
></TileSelector> | ||
<TileSelector | ||
setFormData={handleMemSelect} | ||
title="Memory" | ||
selectionText={"Select memory limit (in GB):"} | ||
numberOptions={[4, 8, 16, 32, 64, 128, 256]} | ||
></TileSelector> | ||
</div> | ||
); | ||
}; | ||
|
||
function FormPage() { | ||
|
||
const [formData, setFormData] = useState({ | ||
memselection: 4, | ||
cpuselection: 1, | ||
dockerimage: "cerit.io/hubs/rstudio:4.3.1-snakemake", | ||
}); | ||
|
||
const submitForm = () => { | ||
const formDataToSend = new FormData(); | ||
|
||
Object.entries(formData).forEach(([key, value]) => { | ||
formDataToSend.append(key, value); | ||
}); | ||
|
||
fetch(appConfig.postUrl, { | ||
method: "POST", | ||
body: formDataToSend, | ||
}) | ||
.then((response) => { | ||
if (response.ok) { | ||
const pendingUrl = appConfig.postUrl.replace( | ||
"/spawn/", | ||
"/spawn-pending/", | ||
); | ||
window.location.href = pendingUrl; | ||
} else { | ||
console.error("Error submitting form:", response.statusText); | ||
} | ||
}) | ||
.catch((error) => { | ||
console.error("Network error:", error); | ||
}); | ||
}; | ||
|
||
const steps = [ | ||
<StepOne key={0} formData={formData} setFormData={setFormData} />, | ||
<StepThree key={1} formData={formData} setFormData={setFormData} />, | ||
]; | ||
|
||
return ( | ||
<> | ||
<JupyterHubHeader userName={appConfig.userName}></JupyterHubHeader> | ||
<div className="wrapper"> | ||
<ProgressiveForm | ||
steps={steps} | ||
submitForm={submitForm} | ||
></ProgressiveForm> | ||
<EinfraFooter></EinfraFooter> | ||
</div> | ||
</> | ||
); | ||
} | ||
|
||
export default FormPage; |
Oops, something went wrong.