Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 13 additions & 11 deletions client/src/features/dashboardV2/DashboardV2Sessions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import cx from "classnames";
import { generatePath, Link } from "react-router";
import { Col, ListGroup, Row } from "reactstrap";

import { sessionLauncherKindToCategory } from "~/features/sessionsV2/session.utils.ts";
import RtkOrDataServicesError from "../../components/errors/RtkOrDataServicesError";
import { Loader } from "../../components/Loader";
import { ABSOLUTE_ROUTES } from "../../routing/routes.constants";
Expand Down Expand Up @@ -112,10 +113,10 @@ interface DashboardSessionProps {
function DashboardSession({ session }: DashboardSessionProps) {
const { project_id: projectId, launcher_id: launcherId } = session;
const { data: project } = useGetProjectsByProjectIdQuery(
projectId ? { projectId } : skipToken,
projectId ? { projectId } : skipToken
);
const { data: launcher } = useGetProjectSessionLauncherQuery(
launcherId ? { launcherId } : skipToken,
launcherId ? { launcherId } : skipToken
);

const projectUrl = project
Expand All @@ -124,10 +125,10 @@ function DashboardSession({ session }: DashboardSessionProps) {
slug: project.slug,
})
: projectId
? generatePath(ABSOLUTE_ROUTES.v2.projects.showById, {
id: projectId,
})
: ABSOLUTE_ROUTES.v2.index;
? generatePath(ABSOLUTE_ROUTES.v2.projects.showById, {
id: projectId,
})
: ABSOLUTE_ROUTES.v2.index;
const showSessionUrl = project
? generatePath(ABSOLUTE_ROUTES.v2.projects.show.sessions.show, {
namespace: project.namespace,
Expand All @@ -136,7 +137,8 @@ function DashboardSession({ session }: DashboardSessionProps) {
})
: ABSOLUTE_ROUTES.v2.index;

const sessionStyles = getSessionStatusStyles(session);
const launcherCategory = sessionLauncherKindToCategory(session.session_type);
const sessionStyles = getSessionStatusStyles(session, launcherCategory);
const state = session.status.state;

return (
Expand All @@ -151,7 +153,7 @@ function DashboardSession({ session }: DashboardSessionProps) {
"gap-3",
"link-primary",
"text-body",
"text-decoration-none",
"text-decoration-none"
)}
to={{ pathname: projectUrl }}
>
Expand All @@ -165,7 +167,7 @@ function DashboardSession({ session }: DashboardSessionProps) {
"cursor-pointer",
"d-inline-block",
"link-primary",
"text-body",
"text-body"
)}
data-cy="list-session-link"
>
Expand All @@ -176,7 +178,7 @@ function DashboardSession({ session }: DashboardSessionProps) {
{launcher?.environment?.name}
</>
) : (
(projectId ?? "Unknown")
projectId ?? "Unknown"
)}
</h4>
</Col>
Expand All @@ -195,7 +197,7 @@ function DashboardSession({ session }: DashboardSessionProps) {
"mt-2",
"d-block",
"d-sm-flex",
"gap-5",
"gap-5"
)}
xs={12}
>
Expand Down
17 changes: 10 additions & 7 deletions client/src/features/logsDisplay/LogsModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -100,10 +100,13 @@ export default function LogsModal({
"fs-4",
"fst-italic",
"mb-0",
getSessionStatusStyles({
status: { state: sessionState },
image: "url",
})["textColorCard"],
getSessionStatusStyles(
{
status: { state: sessionState },
image: "url",
},
"session"
)["textColorCard"]
)}
>
Session status: {sessionState}
Expand Down Expand Up @@ -217,7 +220,7 @@ function TabbedLogs({ data, defaultTab }: TabbedLogsProps) {
}, [data, defaultTab]);

const [activeTab, setActiveTab] = useState<string>(
sortedLogs.at(0)?.tab ?? "",
sortedLogs.at(0)?.tab ?? ""
);

const preRef = useRef<HTMLPreElement>(null);
Expand Down Expand Up @@ -301,7 +304,7 @@ function ModalFooterButtons({
const [isDownloading, triggerDownload] = useDownloadLogs(
name,
refetch,
downloadQueryTrigger,
downloadQueryTrigger
);
const canDownload =
!isFetching &&
Expand Down Expand Up @@ -350,7 +353,7 @@ function ModalFooterButtons({
function useDownloadLogs(
name: string,
refetch: LogsQuery["refetch"],
downloadQueryTrigger: DownloadLogsLazyQueryTrigger | undefined | null,
downloadQueryTrigger: DownloadLogsLazyQueryTrigger | undefined | null
): [boolean, () => void] {
const [isDownloading, setIsDownloading] = useState<boolean>(false);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1197,7 +1197,7 @@
"description": "A container image",
"type": "string",
"maxLength": 500,
"pattern": "^[a-z0-9]+((\\.|_|__|-+)[a-z0-9]+)*(\\/[a-z0-9]+((\\.|_|__|-+)[a-z0-9]+)*)*(:[a-zA-Z0-9_][a-zA-Z0-9._-]{0,127}|@sha256:[a-fA-F0-9]{64}){0,1}$",
"minLength": 3,
"example": "renku/renkulab-py:3.10-0.18.1"
},
"DefaultUrl": {
Expand Down
56 changes: 33 additions & 23 deletions client/src/features/sessionsV2/DataConnectorSecretsModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,13 @@ const CONTEXT_STRINGS = {
testError:
"The data connector could not be mounted. Please retry with different credentials, or skip the data connector. If you skip, the data connector will not be mounted in the session.",
},
job: {
continueButton: "Continue",
dataCy: "job-data-connector-credentials-modal",
header: "Job Storage Credentials",
testError:
"The data connector could not be mounted. Please retry with different credentials, or skip the data connector. If you skip, the data connector will not be mounted in the job.",
},
storage: {
continueButton: "Test and Save",
dataCy: "data-connector-credentials-modal",
Expand Down Expand Up @@ -113,7 +120,7 @@ function DataConnectorSecrets({
dataConnectorConfig.savedCredentialFields.map((secret) => [
storageSecretNameToFieldName({ name: secret }),
secret,
]),
])
)
: {};

Expand Down Expand Up @@ -158,7 +165,7 @@ function DataConnectorSecrets({
}

interface DataConnectorSecretsModalProps {
context?: "session" | "storage";
context?: "session" | "job" | "storage";
isOpen: boolean;
onCancel: () => void;
onStart: (dataConnectorConfigs: DataConnectorConfiguration[]) => void;
Expand All @@ -176,16 +183,16 @@ export default function DataConnectorSecretsModal({
initialDataConnectorConfigs == null
? []
: initialDataConnectorConfigs.filter(
(config) => config.sensitiveFieldDefinitions.length === 0,
(config) => config.sensitiveFieldDefinitions.length === 0
),
[initialDataConnectorConfigs],
[initialDataConnectorConfigs]
);
const [dataConnectorConfigs, setDataConnectorConfigs] = useState(
initialDataConnectorConfigs == null
? []
: initialDataConnectorConfigs.filter(
(config) => config.sensitiveFieldDefinitions.length > 0,
),
(config) => config.sensitiveFieldDefinitions.length > 0
)
);
const [index, setIndex] = useState(0);
const { control, handleSubmit, reset: resetForm } = useForm();
Expand All @@ -204,7 +211,7 @@ export default function DataConnectorSecretsModal({
onStart([...noCredentialsConfigs, ...csConfigs]);
}
},
[index, noCredentialsConfigs, onStart, resetForm, validationResult],
[index, noCredentialsConfigs, onStart, resetForm, validationResult]
);

const onSkip = useCallback(() => {
Expand Down Expand Up @@ -256,7 +263,7 @@ export default function DataConnectorSecretsModal({
newCloudStorageConfigs[index] = config;
setDataConnectorConfigs(newCloudStorageConfigs);
},
[dataConnectorConfigs, index, validateCloudStorageConnection],
[dataConnectorConfigs, index, validateCloudStorageConnection]
);

useEffect(() => {
Expand All @@ -278,7 +285,7 @@ export default function DataConnectorSecretsModal({
if (dataConnectorConfigs == null) return null;
if (dataConnectorConfigs.length < 1) return null;
const hasSavedCredentials = dataConnectorConfigs.some(
(csc) => csc.savedCredentialFields?.length > 0,
(csc) => csc.savedCredentialFields?.length > 0
);

return (
Expand Down Expand Up @@ -327,10 +334,8 @@ export default function DataConnectorSecretsModal({
);
}

interface CredentialsButtonsProps extends Pick<
DataConnectorSecretsModalProps,
"onCancel"
> {
interface CredentialsButtonsProps
extends Pick<DataConnectorSecretsModalProps, "onCancel"> {
context: NonNullable<DataConnectorSecretsModalProps["context"]>;
hasSavedCredentials: boolean;
onSkip: () => void;
Expand All @@ -352,7 +357,9 @@ function CredentialsButtons({
<XLg className={cx("bi", "me-1")} />
Cancel
</Button>
{context === "session" && <SkipConnectionTestButton onSkip={onSkip} />}
{(context === "session" || context === "job") && (
<SkipConnectionTestButton context={context} onSkip={onSkip} />
)}
{context === "storage" && (
<ClearCredentialsButton
onSkip={onSkip}
Expand All @@ -364,10 +371,10 @@ function CredentialsButtons({
validationResult == null
? "primary"
: validationResult.isSuccess
? "primary"
: validationResult.isError
? "danger"
: "primary"
? "primary"
: validationResult.isError
? "danger"
: "primary"
}
className={cx("ms-2")}
disabled={validationResult.isLoading}
Expand Down Expand Up @@ -431,7 +438,7 @@ function ProgressBreadcrumbs({
"btn-link",
"p-0",
idx === index && ["text-decoration-none", "link-rk-text"],
idx > index && "text-decoration-none",
idx > index && "text-decoration-none"
)}
disabled={idx >= index}
onClick={() => {
Expand Down Expand Up @@ -485,7 +492,8 @@ function SaveCredentialsInput({
);
}

interface SensitiveFieldWidgetProps extends DataConnectorConfigurationSecretsProps {
interface SensitiveFieldWidgetProps
extends DataConnectorConfigurationSecretsProps {
credentialFieldDict: Record<string, string>;
field: {
name: string;
Expand Down Expand Up @@ -573,7 +581,7 @@ function SensitiveFieldInput({
"form-control",
"rounded-0",
"rounded-start",
fieldState.error && "is-invalid",
fieldState.error && "is-invalid"
)}
placeholder={""}
{...field}
Expand Down Expand Up @@ -612,9 +620,11 @@ function SensitiveFieldInput({
}

function SkipConnectionTestButton({
context,
onSkip,
}: Pick<CredentialsButtonsProps, "onSkip">) {
}: Pick<CredentialsButtonsProps, "context" | "onSkip">) {
const skipButtonRef = useRef<HTMLAnchorElement>(null);
const targetLabel = context === "job" ? "job" : "session";
return (
<>
<span ref={skipButtonRef}>
Expand All @@ -624,7 +634,7 @@ function SkipConnectionTestButton({
</Button>
</span>
<UncontrolledTooltip target={skipButtonRef}>
Skip the data connector. It will not be mounted in the session.
{`Skip the data connector. It will not be mounted in the ${targetLabel}.`}
</UncontrolledTooltip>
</>
);
Expand Down
Loading
Loading