Skip to content

Commit

Permalink
Add repo validation, enable branch selection
Browse files Browse the repository at this point in the history
  • Loading branch information
oliverroick committed Sep 3, 2024
1 parent 2f7b48f commit 1e84234
Show file tree
Hide file tree
Showing 8 changed files with 657 additions and 453 deletions.
601 changes: 169 additions & 432 deletions package-lock.json

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
},
"dependencies": {
"@jupyterhub/binderhub-client": "0.4.0",
"configurable-http-proxy": "^4.6.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-select": "^5.7.4",
Expand Down Expand Up @@ -48,13 +47,15 @@
"identity-obj-proxy": "^3.0.0",
"jest": "^29.7.0",
"jest-environment-jsdom": "^29.7.0",
"jest-fetch-mock": "^3.0.3",
"react-test-renderer": "^18.3.1",
"style-loader": "^3.3.2",
"webpack": "^5.6.0",
"webpack-cli": "^4.10.0",
"webpack-dev-server": "^4.9.3"
},
"jest": {
"automock": false,
"testEnvironment": "jsdom",
"testMatch": [
"<rootDir>/src/**/*.test.js"
Expand Down
18 changes: 18 additions & 0 deletions setupTests.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,22 @@
import {jest} from '@jest/globals';
import "@testing-library/jest-dom";
import fetchMock from "jest-fetch-mock";
fetchMock.enableMocks();

HTMLCanvasElement.prototype.getContext = () => {};
Object.defineProperty(window, 'matchMedia', {
writable: true,
value: jest.fn().mockImplementation(query => ({
matches: false,
media: query,
onchange: null,
addListener: jest.fn(), // Deprecated
removeListener: jest.fn(), // Deprecated
addEventListener: jest.fn(),
removeEventListener: jest.fn(),
dispatchEvent: jest.fn(),
})),
});

window.profileList = [
{
Expand Down
77 changes: 57 additions & 20 deletions src/ImageBuilder.jsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import { useEffect, useState } from "react";
import { useEffect, useState, useRef } from "react";
import Select from "react-select";
import useRepositoryField from "./hooks/useRepositoryField";
import useRefField from "./hooks/useRefField";

async function buildImage(repo, ref, term, fitAddon, onImageBuilt) {
const { BinderRepository } = await import("@jupyterhub/binderhub-client");
Expand Down Expand Up @@ -86,19 +89,28 @@ function ImageLogs({ setTerm, setFitAddon }) {
</div>
);
}

export function ImageBuilder({ name }) {
const [repo, setRepo] = useState("");
const { repo, repoId, repoFieldProps, repoError } = useRepositoryField();
const { ref, refError, refFieldProps } = useRefField(repoId);
const repoFieldRef = useRef();
const branchFieldRef = useRef();

const [customImage, setCustomImage] = useState("");
const [error, setError] = useState("");

// FIXME: Allow users to actually configure this
const [ref, _] = useState("HEAD"); // eslint-disable-line no-unused-vars
const [term, setTerm] = useState(null);
const [fitAddon, setFitAddon] = useState(null);

const handleBuildStart = async () => {
if (!repo) {
setError("Provide a Github repository.");
repoFieldRef.current.focus();
repoFieldRef.current.blur();
return;
}

if (!ref) {
branchFieldRef.current.focus();
branchFieldRef.current.blur();
return;
}

Expand All @@ -116,28 +128,53 @@ export function ImageBuilder({ name }) {
// don't generate the hidden input that posts the built image out.
return (
<>
<div className={`profile-option-container ${error ? "has-error" : ""}`}>
<div className="profile-option-container">
<div className="profile-option-label-container">
<label htmlFor="github-repo">GitHub Repository</label>
<b>Provider</b>
</div>
<div className="profile-option-control-container">
GitHub
</div>
</div>

<div className={`profile-option-container ${repoError ? "has-error" : ""}`}>
<div className="profile-option-label-container">
<label htmlFor="repo">Repository</label>
</div>
<div className="profile-option-control-container">
<input
id="github-repo"
id="repo"
type="text"
value={repo}
onChange={(e) => setRepo(e.target.value)}
ref={repoFieldRef}
{...repoFieldProps}
aria-invalid={!!repoError}
/>
{error && <div className="profile-option-control-error">{error}</div>}
<button
type="button"
className="btn btn-jupyter pull-right"
onClick={handleBuildStart}
>
Build image
</button>
{repoError && <div className="profile-option-control-error">{repoError}</div>}
</div>
<input name={name} type="hidden" value={customImage} />
</div>

{refFieldProps.options && (
<div className={`profile-option-container ${repoError ? "has-error" : ""}`}>
<div className="profile-option-label-container">
<label>Branch</label>
</div>
<div className="profile-option-control-container">
<Select aria-label="Branch" ref={branchFieldRef} {...refFieldProps} aria-invalid={!!refError} />
{refError && <div className="profile-option-control-error">{refError}</div>}
</div>
</div>
)}

<div className="right-button">
<button
type="button"
className="btn btn-jupyter"
onClick={handleBuildStart}
>
Build image
</button>
</div>
<input name={name} type="hidden" value={customImage} />
<ImageLogs setFitAddon={setFitAddon} setTerm={setTerm} />
</>
);
Expand Down
Loading

0 comments on commit 1e84234

Please sign in to comment.