Skip to content

Instantly share code, notes, and snippets.

@jesuino
Created October 21, 2025 14:25
Show Gist options
  • Select an option

  • Save jesuino/0079dfe742457d817fe51e519cd20c44 to your computer and use it in GitHub Desktop.

Select an option

Save jesuino/0079dfe742457d817fe51e519cd20c44 to your computer and use it in GitHub Desktop.

Revisions

  1. jesuino created this gist Oct 21, 2025.
    615 changes: 615 additions & 0 deletions kale_any_remove_wip.diff
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,615 @@
    diff --git a/labextension/src/components/Input.tsx b/labextension/src/components/Input.tsx
    index 457b84d..044b0be 100644
    --- a/labextension/src/components/Input.tsx
    +++ b/labextension/src/components/Input.tsx
    @@ -1,173 +1,3 @@
    -// /*
    -// * Copyright 2020 The Kale Authors
    -// *
    -// * 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 * as React from 'react';
    -// import { useDebouncedCallback } from 'use-debounce';
    -// import TextField, { OutlinedTextFieldProps } from '@material-ui/core/TextField';
    -// import { createStyles, makeStyles } from '@material-ui/core/styles';
    -
    -// const useStyles = makeStyles(() =>
    -// createStyles({
    -// label: {
    -// color: 'var(--jp-input-border-color)',
    -// fontSize: 'var(--jp-ui-font-size2)',
    -// },
    -// input: {
    -// color: 'var(--jp-ui-font-color1)',
    -// },
    -// textField: {
    -// width: '100%',
    -// },
    -// helperLabel: {
    -// color: 'var(--jp-info-color0)',
    -// },
    -// }),
    -// );
    -
    -// // @ts-ignore
    -// export interface InputProps extends OutlinedTextFieldProps {
    -// value: string | number;
    -// regex?: string;
    -// regexErrorMsg?: string;
    -// inputIndex?: number;
    -// helperText?: string;
    -// readOnly?: boolean;
    -// validation?: 'int' | 'double';
    -// variant?: 'standard' | 'outlined' | 'filled';
    -// updateValue: Function;
    -// onBeforeUpdate?: (value: string) => boolean;
    -// }
    -
    -// export const Input: React.FunctionComponent<InputProps> = props => {
    -// const [value, setValue] = React.useState('' as any);
    -// const [error, updateError] = React.useState(false);
    -// const classes = useStyles({});
    -
    -// const {
    -// value: propsValue,
    -// className,
    -// helperText = null,
    -// regex,
    -// regexErrorMsg,
    -// validation,
    -// placeholder,
    -// inputIndex,
    -// readOnly = false,
    -// variant = 'outlined',
    -// InputProps,
    -// updateValue,
    -// onBeforeUpdate = undefined,
    -// ...rest
    -// } = props;
    -
    -// const getRegex = () => {
    -// if (regex) {
    -// return regex;
    -// } else if (validation && validation == 'int') {
    -// return /^(-\d)?\d*$/;
    -// } else if (validation && validation == 'double') {
    -// return /^(-\d)?\d*(\.\d)?\d*$/;
    -// } else {
    -// return undefined;
    -// }
    -// };
    -
    -// const getRegexMessage = () => {
    -// if (regexErrorMsg) {
    -// return regexErrorMsg;
    -// } else if (validation && validation == 'int') {
    -// return 'Integer value required';
    -// } else if (validation && validation == 'double') {
    -// return 'Double value required';
    -// } else {
    -// return undefined;
    -// }
    -// };
    -
    -// const onChange = (value: string, index: number) => {
    -// // if the input domain is restricted by a regex
    -// if (!getRegex()) {
    -// updateValue(value, index);
    -// return;
    -// }
    -
    -// let re = new RegExp(getRegex());
    -// if (!re.test(value)) {
    -// updateError(true);
    -// } else {
    -// updateError(false);
    -// updateValue(value, index);
    -// }
    -// };
    -
    -// React.useEffect(() => {
    -// // need this to set the value when the notebook is loaded and the metadata
    -// // is updated
    -// setValue(propsValue);
    -// }, [propsValue]); // Only re-run the effect if propsValue changes
    -
    -// const [debouncedCallback] = useDebouncedCallback(
    -// // function
    -// (value: string, idx: number) => {
    -// onChange(value, idx);
    -// },
    -// // delay in ms
    -// 500,
    -// );
    -
    -// return (
    -// // @ts-ignore
    -// <TextField
    -// {...rest}
    -// variant={variant}
    -// className={classes.textField}
    -// error={error}
    -// value={value}
    -// margin="dense"
    -// placeholder={placeholder}
    -// spellCheck={false}
    -// helperText={error ? getRegexMessage() : helperText}
    -// InputProps={{
    -// classes: { root: classes.input },
    -// readOnly: readOnly,
    -// ...InputProps,
    -// }}
    -// InputLabelProps={{
    -// classes: { root: classes.label },
    -// shrink: !!placeholder || value !== '',
    -// }}
    -// FormHelperTextProps={{ classes: { root: classes.helperLabel } }}
    -// onChange={evt => {
    -// setValue(evt.target.value);
    -// if (!onBeforeUpdate) {
    -// debouncedCallback(evt.target.value, inputIndex);
    -// } else {
    -// const r = onBeforeUpdate(evt.target.value);
    -// if (r) {
    -// updateError(true);
    -// } else {
    -// updateError(false);
    -// debouncedCallback(evt.target.value, inputIndex);
    -// }
    -// }
    -// }}
    -// />
    -// );
    -// };
    -
    /*
    * Copyright 2020 The Kale Authors
    *
    diff --git a/labextension/src/components/Select.tsx b/labextension/src/components/Select.tsx
    index 6dc4096..d757371 100644
    --- a/labextension/src/components/Select.tsx
    +++ b/labextension/src/components/Select.tsx
    @@ -14,124 +14,6 @@
    // * limitations under the License.
    // */

    -// import * as React from 'react';
    -// import TextField, { BaseTextFieldProps } from '@mui/material/TextField';
    -// import { MenuItem, Zoom } from '@mui/material';
    -// import { createStyles, makeStyles } from '@mui/material/styles';
    -// import { styled } from '@mui/material/styles';
    -// import { LightTooltip } from './LightTooltip';
    -
    -// export interface ISelectOption {
    -// label: string;
    -// value: string;
    -// tooltip?: any;
    -// invalid?: boolean;
    -// }
    -
    -// const useStyles = styled(TextField)({
    -// label: {
    -// color: 'var(--jp-input-border-color)',
    -// fontSize: 'var(--jp-ui-font-size2)',
    -// },
    -// input: {
    -// color: 'var(--jp-ui-font-color1)',
    -// },
    -// textField: {
    -// width: '100%',
    -// },
    -// menu: {
    -// backgroundColor: 'var(--jp-layout-color1)',
    -// color: 'var(--jp-ui-font-color1)',
    -// },
    -// helperLabel: {
    -// color: 'var(--jp-info-color0)',
    -// },
    -// });
    -
    -// interface SelectProps extends BaseTextFieldProps {
    -// index: number;
    -// values: ISelectOption[];
    -// variant?: 'filled' | 'standard' | 'outlined';
    -// updateValue: Function;
    -// }
    -
    -// export const Select: React.FC<SelectProps> = props => {
    -// const classes = useStyles({});
    -
    -// const {
    -// index,
    -// value,
    -// values,
    -// helperText = null,
    -// variant = 'outlined',
    -// updateValue,
    -// ...rest
    -// } = props;
    -
    -// const disableMenuItem = (event: React.MouseEvent, invalidOption: boolean) => {
    -// if (invalidOption) {
    -// event.stopPropagation();
    -// }
    -// };
    -
    -// const getOptionClassNames = (option: any) => {
    -// const classNames: string[] = [];
    -// if (option.tooltip) {
    -// classNames.push('menu-item-tooltip');
    -// }
    -// return classNames.join(' ');
    -// };
    -
    -// return (
    -// // @ts-ignore
    -// <TextField
    -// select
    -// {...rest}
    -// margin="dense"
    -// value={value}
    -// variant={variant}
    -// className={classes.textField}
    -// onChange={evt =>
    -// updateValue((evt.target as HTMLInputElement).value, index)
    -// }
    -// InputLabelProps={{
    -// classes: { root: classes.label },
    -// shrink: value !== '',
    -// }}
    -// InputProps={{ classes: { root: classes.input } }}
    -// SelectProps={{ MenuProps: { PaperProps: { className: classes.menu } } }}
    -// FormHelperTextProps={{ classes: { root: classes.helperLabel } }}
    -// >
    -// {values.map((option: any) => (
    -// <MenuItem
    -// key={option.value}
    -// value={option.value}
    -// disabled={!!option.invalid}
    -// className={getOptionClassNames(option)}
    -// >
    -// {option.tooltip ? (
    -// <LightTooltip
    -// title={option.tooltip}
    -// placement="top-start"
    -// interactive={!(typeof option.tooltip === 'string')}
    -// TransitionComponent={Zoom}
    -// >
    -// <div
    -// className="menu-item-label"
    -// onClick={ev => disableMenuItem(ev, !!option.invalid)}
    -// >
    -// {option.label}
    -// </div>
    -// </LightTooltip>
    -// ) : (
    -// option.label
    -// )}
    -// </MenuItem>
    -// ))}
    -// </TextField>
    -// );
    -// };
    -
    import * as React from 'react';
    import TextField, { BaseTextFieldProps } from '@mui/material/TextField';
    import { MenuItem, Zoom } from '@mui/material';
    diff --git a/labextension/src/index.ts b/labextension/src/index.ts
    index 5a26634..27f859c 100644
    --- a/labextension/src/index.ts
    +++ b/labextension/src/index.ts
    @@ -15,5 +15,5 @@
    */

    import { JupyterFrontEndPlugin } from '@jupyterlab/application';
    -import kubeflowKalePlugin from './widget';
    -export default [kubeflowKalePlugin] as JupyterFrontEndPlugin<any>[];
    +import kubeflowKalePlugin, { IKubeflowKale } from './widget';
    +export default [kubeflowKalePlugin] as JupyterFrontEndPlugin<IKubeflowKale>[];
    diff --git a/labextension/src/lib/Commands.ts b/labextension/src/lib/Commands.ts
    index ce139d5..ab706b7 100644
    --- a/labextension/src/lib/Commands.ts
    +++ b/labextension/src/lib/Commands.ts
    @@ -37,6 +37,8 @@ import NotebookUtils from './NotebookUtils';
    // } from '../widgets/VolumesPanel';
    import { IDocumentManager } from '@jupyterlab/docmanager';
    import CellUtils from './CellUtils';
    +import { Pipeline } from '../widgets/deploys-progress/Pipeline';
    +import { DeployProgressState } from '../widgets/deploys-progress/DeploysProgress';

    enum RUN_CELL_STATUS {
    OK = 'ok',
    @@ -56,7 +58,7 @@ interface IUploadPipelineArgs {

    interface IUploadPipelineResp {
    already_exists: boolean;
    - pipeline: { pipelineid: string; versionid: string; name: string };
    + pipeline: Pipeline;
    }

    interface IRunPipelineArgs {
    @@ -296,7 +298,7 @@ export default class Commands {
    versionId: string,
    compiledPipelineMetadata: IKaleNotebookMetadata,
    pipelinePackagePath: string,
    - onUpdate: (params: { showRunProgress?: boolean, runPipeline?: boolean }) => void,
    + onUpdate: (deployProgress: DeployProgressState) => void,
    ) => {
    onUpdate({ showRunProgress: true });
    const runPipelineArgs: IRunPipelineArgs = {
    @@ -310,9 +312,9 @@ export default class Commands {
    this._kernel,
    'kfp.run_pipeline',
    runPipelineArgs,
    - );
    + ) as Pipeline;
    if (runPipeline) {
    - onUpdate({ runPipeline });
    + onUpdate({ pipeline: runPipeline });
    } else {
    onUpdate({ showRunProgress: false, runPipeline: false });
    }
    diff --git a/labextension/src/lib/RPCUtils.tsx b/labextension/src/lib/RPCUtils.tsx
    index bc67ad5..f1b70f5 100644
    --- a/labextension/src/lib/RPCUtils.tsx
    +++ b/labextension/src/lib/RPCUtils.tsx
    @@ -21,7 +21,8 @@ import NotebookUtils from './NotebookUtils';
    import { isError, IError, IOutput } from '@jupyterlab/nbformat';

    export const globalUnhandledRejection = async (event: any) => {
    - // console.error(event.reason);
    + console.log('Unhandled promise rejection:');
    + console.error(event.reason);
    if (event.reason instanceof BaseError) {
    console.error(event.reason.message, event.reason.error);
    event.reason.showDialog().then();
    diff --git a/labextension/src/widgets/LeftPanel.tsx b/labextension/src/widgets/LeftPanel.tsx
    index 27e55be..ec4cdc6 100644
    --- a/labextension/src/widgets/LeftPanel.tsx
    +++ b/labextension/src/widgets/LeftPanel.tsx
    @@ -414,12 +414,12 @@ export class KubeflowKaleLeftPanel extends React.Component<IProps, IState> {

    if (!uploadPipeline) {
    this.setState({ runDeployment: false });
    - _updateDeployProgress({ pipeline: false });
    + _updateDeployProgress({ pipeline: undefined });
    return;
    }
    _updateDeployProgress({
    message: 'Pipeline uploaded successfully',
    - pipeline: true
    + pipeline: uploadPipeline.pipeline
    });
    // RUN
    if (this.state.deploymentType === 'run') {
    diff --git a/labextension/src/widgets/deploys-progress/DeployProgress.tsx b/labextension/src/widgets/deploys-progress/DeployProgress.tsx
    index bdb75fa..edbad38 100644
    --- a/labextension/src/widgets/deploys-progress/DeployProgress.tsx
    +++ b/labextension/src/widgets/deploys-progress/DeployProgress.tsx
    @@ -28,19 +28,9 @@ import StatusRunning from '../../icons/statusRunning';
    import TerminatedIcon from '../../icons/statusTerminated';
    import { DeployProgressState } from './DeploysProgress';
    import DeployUtils from './DeployUtils';
    +import { Pipeline } from './Pipeline';
    +

    -// From kubeflow/pipelines repo
    -enum PipelineStatus {
    - ERROR = 'Error',
    - FAILED = 'Failed',
    - PENDING = 'Pending',
    - RUNNING = 'Running',
    - SKIPPED = 'Skipped',
    - SUCCEEDED = 'Succeeded',
    - TERMINATING = 'Terminating',
    - TERMINATED = 'Terminated',
    - UNKNOWN = 'Unknown'
    -}

    interface IDeployProgressProps extends DeployProgressState {
    onRemove?: () => void;
    @@ -49,87 +39,87 @@ interface IDeployProgressProps extends DeployProgressState {
    export const DeployProgress: React.FunctionComponent<
    IDeployProgressProps
    > = props => {
    - const getUploadLink = (pipeline: any) => {
    + const getUploadLink = (deployProgress: DeployProgressState) => {
    // link: /_/pipeline/#/pipelines/details/<id>
    // id = uploadPipeline.pipeline.id
    - if (!pipeline.pipeline || !pipeline.pipeline.pipelineid) {
    + if (!deployProgress.pipeline || !deployProgress.pipeline.pipelineid) {
    return '#';
    }
    - const link = `${window.location.origin}/_/pipeline/#/pipelines/details/${pipeline.pipeline.pipelineid}/version/${pipeline.pipeline.versionid}`;
    + const link = `${window.location.origin}/_/pipeline/#/pipelines/details/${deployProgress.pipeline.pipelineid}/version/${deployProgress.pipeline.versionid}`;
    return props.namespace
    ? link.replace('#', `?ns=${props.namespace}#`)
    : link;
    };

    - const getRunLink = (run: any) => {
    + const getRunLink = (run: Pipeline | undefined) => {
    // link: /_/pipeline/#/runs/details/<id>
    // id = runPipeline.id
    - if (!run.id) {
    + if (!run?.pipelineid) {
    return '#';
    }
    - const link = `${window.location.origin}/_/pipeline/#/runs/details/${run.id}`;
    + const link = `${window.location.origin}/_/pipeline/#/runs/details/${run.pipelineid}`;
    return props.namespace
    ? link.replace('#', `?ns=${props.namespace}#`)
    : link;
    };

    - const getRunText = (pipeline: any) => {
    + const getRunText = (pipeline: Pipeline) => {
    switch (pipeline.status) {
    case null:
    - case 'Running':
    + case 'RUNNING':
    return 'View';
    - case 'Terminating':
    - case 'Failed':
    + case 'TERMINATING':
    + case 'FAILED':
    return pipeline.status as string;
    default:
    return 'Done';
    }
    };

    - const getRunComponent = (pipeline: any) => {
    + const getRunComponent = (pipeline: Pipeline) => {
    let IconComponent: any = UnknownIcon;
    let iconColor = '#5f6368';
    switch (pipeline.status) {
    - case PipelineStatus.ERROR:
    + case 'ERROR':
    IconComponent = ErrorIcon;
    iconColor = DeployUtils.color.errorText;
    // title = 'Error';
    break;
    - case PipelineStatus.FAILED:
    + case 'FAILED':
    IconComponent = ErrorIcon;
    iconColor = DeployUtils.color.errorText;
    // title = 'Failed';
    break;
    - case PipelineStatus.PENDING:
    + case 'PENDING':
    IconComponent = PendingIcon;
    iconColor = DeployUtils.color.weak;
    // title = 'Pending';
    break;
    - case PipelineStatus.RUNNING:
    + case 'RUNNING':
    IconComponent = StatusRunning;
    iconColor = DeployUtils.color.blue;
    // title = 'Running';
    break;
    - case PipelineStatus.TERMINATING:
    + case 'TERMINATING':
    IconComponent = StatusRunning;
    iconColor = DeployUtils.color.blue;
    // title = 'Terminating';
    break;
    - case PipelineStatus.SKIPPED:
    + case 'SKIPPED':
    IconComponent = SkippedIcon;
    // title = 'Skipped';
    break;
    - case PipelineStatus.SUCCEEDED:
    + case 'SUCCEEDED':
    IconComponent = SuccessIcon;
    iconColor = DeployUtils.color.success;
    // title = 'Succeeded';
    break;
    - case PipelineStatus.TERMINATED:
    + case 'TERMINATED':
    IconComponent = TerminatedIcon;
    iconColor = DeployUtils.color.terminated;
    // title = 'Terminated';
    break;
    - case PipelineStatus.UNKNOWN:
    + case 'UNKNOWN':
    break;
    default:
    console.error('pipeline status:', pipeline.status);
    @@ -220,7 +210,7 @@ export const DeployProgress: React.FunctionComponent<
    uploadTpl = (
    <React.Fragment>
    <a
    - href={getUploadLink(props.pipeline)}
    + href={getUploadLink(props)}
    target="_blank"
    rel="noopener noreferrer"
    >
    @@ -246,11 +236,11 @@ export const DeployProgress: React.FunctionComponent<
    runTpl = (
    <React.Fragment>
    <a
    - href={getRunLink(props.runPipeline)}
    + href={getRunLink(props.pipeline)}
    target="_blank"
    rel="noopener noreferrer"
    >
    - {getRunComponent(props.runPipeline)}
    + {props.pipeline && getRunComponent(props.pipeline)}
    </a>
    </React.Fragment>
    );
    diff --git a/labextension/src/widgets/deploys-progress/DeployUtils.tsx b/labextension/src/widgets/deploys-progress/DeployUtils.tsx
    index 0645ba7..ff10e8b 100644
    --- a/labextension/src/widgets/deploys-progress/DeployUtils.tsx
    +++ b/labextension/src/widgets/deploys-progress/DeployUtils.tsx
    @@ -51,7 +51,7 @@ export default class DeployUtils {
    canceled: '#ff992a'
    };

    - public static getInfoBadge(title: string, content: any) {
    + public static getInfoBadge(title: string, content: string[]) {
    return (
    content && (
    <a
    @@ -65,7 +65,7 @@ export default class DeployUtils {
    );
    }

    - public static getWarningBadge(title: string, content: any) {
    + public static getWarningBadge(title: string, content: string[] | undefined) {
    return (
    content && (
    <a
    diff --git a/labextension/src/widgets/deploys-progress/DeploysProgress.tsx b/labextension/src/widgets/deploys-progress/DeploysProgress.tsx
    index 25e4bcb..20312c1 100644
    --- a/labextension/src/widgets/deploys-progress/DeploysProgress.tsx
    +++ b/labextension/src/widgets/deploys-progress/DeploysProgress.tsx
    @@ -18,22 +18,21 @@ import * as React from 'react';
    import { IDocumentManager } from '@jupyterlab/docmanager';

    import { DeployProgress } from './DeployProgress';
    +import { Pipeline } from './Pipeline';

    export type DeployProgressState = {
    showValidationProgress?: boolean;
    notebookValidation?: boolean;
    - validationWarnings?: boolean;
    - // showSnapshotProgress?: boolean;
    - task?: any;
    + validationWarnings?: string[];
    // snapshotWarnings?: any;
    showCompileProgress?: boolean;
    compiledPath?: string;
    compileWarnings?: any;
    showUploadProgress?: boolean;
    - pipeline?: false | any;
    + pipeline?: Pipeline;
    uploadWarnings?: any;
    showRunProgress?: boolean;
    - runPipeline?: any;
    + runPipeline?: boolean;
    runWarnings?: any;
    deleted?: boolean;
    docManager?: IDocumentManager;
    @@ -67,9 +66,6 @@ export const DeploysProgress: React.FunctionComponent<
    showValidationProgress={dpState.showValidationProgress}
    notebookValidation={dpState.notebookValidation}
    validationWarnings={dpState.validationWarnings}
    - // showSnapshotProgress={dpState.showSnapshotProgress}
    - task={dpState.task}
    - // snapshotWarnings={dpState.snapshotWarnings}
    showCompileProgress={dpState.showCompileProgress}
    compiledPath={dpState.compiledPath}
    compileWarnings={dpState.compileWarnings}