Skip to content

Commit

Permalink
wip: can select env type
Browse files Browse the repository at this point in the history
  • Loading branch information
leafty committed Jan 20, 2025
1 parent 3a41990 commit 77f61a9
Show file tree
Hide file tree
Showing 4 changed files with 202 additions and 46 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,15 @@
import { skipToken } from "@reduxjs/toolkit/query";
import cx from "classnames";
import { useMemo } from "react";
import { useWatch, type Control } from "react-hook-form";
import { type Control } from "react-hook-form";

import { WarnAlert } from "../../../../components/Alert";
import { Loader } from "../../../../components/Loader";
import { RtkOrNotebooksError } from "../../../../components/errors/RtkErrorAlert";
import { useProject } from "../../../ProjectPageV2/ProjectPageContainer/ProjectPageContainer";
import { useGetRepositoriesProbesQuery } from "../../../repositories/repositories.api";
import type { SessionLauncherForm } from "../../sessionsV2.types";
import BuilderTypeSelector from "./BuilderTypeSelector";
import CodeRepositorySelector from "./CodeRepositorySelector";

interface BuilderEnvironmentFieldsProps {
Expand All @@ -52,8 +53,6 @@ export default function BuilderEnvironmentFields({
[repositoriesDetails]
);

const watchCodeRepository = useWatch({ control, name: "code_repository" });

const content = isLoading ? (
<p className="mb-0">
<Loader className="me-1" inline size={16} />
Expand All @@ -75,12 +74,13 @@ export default function BuilderEnvironmentFields({
can only build session environments from public code repositories.
</WarnAlert>
) : (
<div>
<div className={cx("d-flex", "flex-column", "gap-3")}>
<CodeRepositorySelector
name="code_repository"
control={control}
repositoriesDetails={repositoriesDetails}
/>
<BuilderTypeSelector name="builder_type" control={control} />
</div>
);

Expand All @@ -92,14 +92,6 @@ export default function BuilderEnvironmentFields({
code repository.
</p>
{content}
<p>
Repo:
<code>
{'"'}
{watchCodeRepository}
{'"'}
</code>
</p>
</div>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
/*!
* Copyright 2025 - Swiss Data Science Center (SDSC)
* A partnership between École Polytechnique Fédérale de Lausanne (EPFL) and
* Eidgenössische Technische Hochschule Zürich (ETHZ).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import cx from "classnames";
import { useCallback, useEffect, useMemo } from "react";
import {
Controller,
type FieldValues,
type Path,
type PathValue,
type UseControllerProps,
} from "react-hook-form";
import Select, { type SingleValue } from "react-select";
import { Label } from "reactstrap";

/* eslint-disable spellcheck/spell-checker */
const BUILDER_TYPES = ["Python (conda)"] as const;
/* eslint-enable spellcheck/spell-checker */

interface BuilderTypeSelectorProps<T extends FieldValues>
extends UseControllerProps<T> {}

export default function BuilderTypeSelector<T extends FieldValues>({
...controllerProps
}: BuilderTypeSelectorProps<T>) {
const defaultValue = useMemo(
() =>
controllerProps.defaultValue
? controllerProps.defaultValue
: BUILDER_TYPES[0],
[controllerProps.defaultValue]
);

return (
<div>
<Label for="builder-environment-type-select-input">
Environment type
</Label>
<Controller
{...controllerProps}
render={({
field: { onBlur, onChange, value, disabled },
fieldState: { error },
}) => (
<>
<div
className={cx(error && "is-invalid")}
data-cy="environment-type-select"
>
<BuilderTypeSelect
name={controllerProps.name}
defaultValue={defaultValue}
options={BUILDER_TYPES}
onBlur={onBlur}
onChange={onChange}
value={value ?? ""}
disabled={disabled}
/>
</div>
<div className="invalid-feedback">
{error?.message ? (
<>{error.message}</>
) : (
<>Please select a valid environment type.</>
)}
</div>
</>
)}
rules={
controllerProps.rules ?? {
required: "Please select an environment type.",
}
}
defaultValue={defaultValue as PathValue<T, Path<T>>}
/>
</div>
);
}

interface CodeRepositorySelectProps {
name: string;

defaultValue?: string;

options: readonly string[];

onChange?: (newValue?: string) => void;
onBlur?: () => void;
value: string;
disabled?: boolean;
}

function BuilderTypeSelect({
name,
options,
defaultValue,
onBlur,
onChange: onChange_,
disabled,
value,
}: CodeRepositorySelectProps) {
const onChange = useCallback(
(newValue: SingleValue<{ value: string }>) => {
onChange_?.(newValue?.value);
},
[onChange_]
);

// We need to set the default value by hand here
useEffect(() => {
if (onChange_ != null && defaultValue) {
onChange_(defaultValue);
}
}, [defaultValue, onChange_]);

return (
<Select
id="builder-environment-type-select"
inputId="builder-environment-type-select-input"
name={name}
isClearable={false}
isSearchable
options={options.map((value) => ({ value }))}
getOptionLabel={({ value }) => value}
getOptionValue={({ value }) => value}
// unstyled
onChange={onChange}
onBlur={onBlur}
value={{ value }}
isDisabled={disabled}
defaultValue={defaultValue ? { value: defaultValue } : undefined}
/>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {
type UseControllerProps,
} from "react-hook-form";
import Select, { type SingleValue } from "react-select";
import { Label } from "reactstrap";

import type { GetRepositoriesProbesResponse } from "../../../repositories/repositories.types";

Expand All @@ -45,45 +46,53 @@ export default function CodeRepositorySelector<T extends FieldValues>({
);

return (
<Controller
{...controllerProps}
render={({
field: { onBlur, onChange, value, disabled },
fieldState: { error },
}) => (
<>
<div
className={cx(error && "is-invalid")}
data-cy="code-repository-select"
>
<CodeRepositorySelect
defaultValue={defaultValue}
options={repositoriesDetails}
onBlur={onBlur}
onChange={onChange}
value={value}
disabled={disabled}
/>
</div>
<div className="invalid-feedback">
{error?.message ? (
<>{error.message}</>
) : (
<>Please select a valid code repository.</>
)}
</div>
</>
)}
rules={
controllerProps.rules ?? {
required: "Please select a code repository.",
<div>
<Label for="builder-environment-code-repository-select-input">
Code repository
</Label>
<Controller
{...controllerProps}
render={({
field: { onBlur, onChange, value, disabled },
fieldState: { error },
}) => (
<>
<div
className={cx(error && "is-invalid")}
data-cy="code-repository-select"
>
<CodeRepositorySelect
name={controllerProps.name}
defaultValue={defaultValue}
options={repositoriesDetails}
onBlur={onBlur}
onChange={onChange}
value={value}
disabled={disabled}
/>
</div>
<div className="invalid-feedback">
{error?.message ? (
<>{error.message}</>
) : (
<>Please select a valid code repository.</>
)}
</div>
</>
)}
rules={
controllerProps.rules ?? {
required: "Please select a code repository.",
}
}
}
/>
/>
</div>
);
}

interface CodeRepositorySelectProps {
name: string;

defaultValue?: string;

options: GetRepositoriesProbesResponse;
Expand All @@ -95,6 +104,7 @@ interface CodeRepositorySelectProps {
}

function CodeRepositorySelect({
name,
options,
defaultValue: defaultValue_,
onBlur,
Expand Down Expand Up @@ -132,6 +142,9 @@ function CodeRepositorySelect({

return (
<Select
id="builder-environment-code-repository-select"
inputId="builder-environment-code-repository-select-input"
name={name}
isClearable={false}
isSearchable
options={options}
Expand Down
2 changes: 2 additions & 0 deletions client/src/features/sessionsV2/sessionsV2.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,8 @@ export interface SessionLauncherForm {

// new
code_repository: string;
builder_type: string;
builder_frontend: string;
}

export interface SessionResources {
Expand Down

0 comments on commit 77f61a9

Please sign in to comment.