Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: Port smaller Antd.Modals to standard Hew Modal #8567

Merged
merged 14 commits into from
Dec 8, 2023
Merged
Show file tree
Hide file tree
Changes from 11 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
7 changes: 4 additions & 3 deletions webui/react/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion webui/react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
"fp-ts": "^2.16.1",
"fuse.js": "^7.0.0",
"hermes-parallel-coordinates": "^0.6.17",
"hew": "git+https://git@github.com/determined-ai/hew.git#v0.6.12",
"hew": "git+https://git@github.com/determined-ai/hew.git#e93d03e6caf946d7861ad04d6c999e33b6ef40f7",
"humanize-duration": "^3.28.0",
"immutable": "^4.3.0",
"io-ts": "^2.2.20",
Expand Down
1 change: 1 addition & 0 deletions webui/react/src/components/GalleryModal.module.scss
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
.base {
height: 450px;
padding: 0 24px;

.prev,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,39 +1,32 @@
import { Modal } from 'antd';
import { ModalProps } from 'antd/es/modal/Modal';
import Button from 'hew/Button';
import Icon from 'hew/Icon';
import { useTheme } from 'hew/Theme';
import React, { useCallback, useEffect, useState } from 'react';
import { UPlotScatterProps } from 'hew/internal/UPlot/types';
import { Modal } from 'hew/Modal';
import React, { useCallback, useEffect } from 'react';

import { keyEmitter, KeyEvent } from 'hooks/useKeyTracker';
import useResize from 'hooks/useResize';
import { isNumber } from 'utils/data';
import { isPercent, percentToFloat } from 'utils/number';
import { Scale } from 'types';

import css from './GalleryModal.module.scss';
import UPlotScatter from './UPlot/UPlotScatter';

interface Props extends ModalProps {
children: React.ReactNode;
height?: number | string;
interface Props {
onNext?: () => void;
onPrevious?: () => void;
onCancel: () => void;
chartProps: Record<string, UPlotScatterProps> | undefined;
activeHParam: string | undefined;
selectedScale: Scale;
}

const GalleryModal: React.FC<Props> = ({
height = '80%',
const GalleryModalComponent: React.FC<Props> = ({
onNext,
onPrevious,
children,
...props
onCancel,
chartProps,
activeHParam,
selectedScale,
}: Props) => {
const resize = useResize();
const [width, setWidth] = useState<number>();
const [minHeight, setMinHeight] = useState<number>();

const {
themeSettings: { className: themeClass },
} = useTheme();

const handlePrevious = useCallback(() => {
if (onPrevious) onPrevious();
}, [onPrevious]);
Expand All @@ -42,17 +35,6 @@ const GalleryModal: React.FC<Props> = ({
if (onNext) onNext();
}, [onNext]);

useEffect(() => {
setWidth(resize.width);

if (isPercent(height)) {
const newMinHeight = percentToFloat(height) * resize.height;
setMinHeight(newMinHeight);
} else if (isNumber(height) && height < resize.height) {
setMinHeight(height);
}
}, [height, resize]);

useEffect(() => {
const keyUpListener = (e: KeyboardEvent) => {
if (e.key === 'ArrowLeft') {
Expand All @@ -70,9 +52,28 @@ const GalleryModal: React.FC<Props> = ({
}, [onNext, onPrevious]);

return (
<Modal centered footer={null} open width={width} {...props} wrapClassName={themeClass}>
<div className={css.base} style={{ minHeight }}>
{children}
<Modal
size="large"
submit={{
handleError: () => {},
handler: onCancel,
text: 'Close',
}}
title=""
onClose={onCancel}>
<div className={css.base}>
{chartProps && activeHParam && (
<UPlotScatter
colorScaleDistribution={selectedScale}
data={chartProps[activeHParam].data}
options={{
...chartProps[activeHParam].options,
cursor: { drag: undefined },
height: 400,
}}
tooltipLabels={chartProps[activeHParam].tooltipLabels}
/>
)}
<div className={css.prev}>
<Button
icon={<Icon name="arrow-left" showTooltip title="Previous" />}
Expand All @@ -90,4 +91,4 @@ const GalleryModal: React.FC<Props> = ({
);
};

export default GalleryModal;
export default GalleryModalComponent;
Original file line number Diff line number Diff line change
@@ -1,52 +1,37 @@
import { Divider, Modal } from 'antd';
import { useTheme } from 'hew/Theme';
import React, { Fragment } from 'react';
import { Divider } from 'antd';
import { Modal } from 'hew/Modal';
import React, { Fragment, useCallback } from 'react';

import JsonGlossary from 'components/JsonGlossary';
import { V1ResourcePoolDetail } from 'services/api-ts-sdk';
import { JsonObject, ResourcePool } from 'types';
import { camelCaseToSentence } from 'utils/string';

import { PoolLogo } from './ResourcePoolCard';
import css from './ResourcePoolDetails.module.scss';

interface Props {
finally?: () => void;
onCloseModal?: () => void;
resourcePool: ResourcePool;
visible: boolean;
}

const ResourcePoolDetails: React.FC<Props> = ({ resourcePool: pool, ...props }: Props) => {
const ResourcePoolDetailsModalComponent: React.FC<Props> = ({
resourcePool: pool,
onCloseModal,
}: Props) => {
const { details, ...mainSection } = pool;

const {
themeSettings: { className: themeClass },
} = useTheme();
const handleClose = useCallback(() => {
if (onCloseModal) onCloseModal();
}, [onCloseModal]);

for (const key in details) {
if (details[key as keyof V1ResourcePoolDetail] === null) {
delete details[key as keyof V1ResourcePoolDetail];
}
}

const title = (
<div>
<PoolLogo type={pool.type} />
{' ' + pool.name}
</div>
);

return (
<Modal
cancelButtonProps={{ style: { display: 'none' } }}
cancelText=""
mask
open={props.visible}
style={{ minWidth: '600px' }}
title={title}
wrapClassName={themeClass}
onCancel={props.finally}
onOk={props.finally}>
<Modal size="medium" title={pool.name} onClose={handleClose}>
<JsonGlossary
json={mainSection as unknown as JsonObject}
translateLabel={camelCaseToSentence}
Expand All @@ -65,4 +50,4 @@ const ResourcePoolDetails: React.FC<Props> = ({ resourcePool: pool, ...props }:
);
};

export default ResourcePoolDetails;
export default ResourcePoolDetailsModalComponent;
5 changes: 0 additions & 5 deletions webui/react/src/components/TaskList.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,3 @@
margin-right: 8px;
}
}
.sourceLinks {
label {
font-size: 12px;
}
}
41 changes: 12 additions & 29 deletions webui/react/src/components/TaskList.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Modal, Space } from 'antd';
import { Space } from 'antd';
import {
FilterDropdownProps,
FilterValue,
Expand All @@ -8,16 +8,13 @@ import {
import Button from 'hew/Button';
import Icon from 'hew/Icon';
import { useModal } from 'hew/Modal';
import { ShirtSize, useTheme } from 'hew/Theme';
import { Loadable } from 'hew/utils/loadable';
import _ from 'lodash';
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';

import Badge, { BadgeType } from 'components/Badge';
import FilterCounter from 'components/FilterCounter';
import Grid from 'components/Grid';
import JupyterLabButton from 'components/JupyterLabButton';
import Link from 'components/Link';
import InteractiveTable, { ColumnDef } from 'components/Table/InteractiveTable';
import {
defaultRowClassName,
Expand Down Expand Up @@ -66,6 +63,7 @@ import { getDisplayName } from 'utils/user';

import BatchActionConfirmModalComponent from './BatchActionConfirmModal';
import css from './TaskList.module.scss';
import TaskListModalComponent, { SourceInfo } from './TaskListModalComponent';
import WorkspaceFilter from './WorkspaceFilter';

const TensorBoardSourceType = {
Expand All @@ -85,12 +83,6 @@ interface TensorBoardSource {
type: TensorBoardSourceType;
}

interface SourceInfo {
path: string;
plural: string;
sources: TensorBoardSource[];
}

const filterKeys: Array<keyof Settings> = ['search', 'state', 'type', 'user', 'workspace'];

const TaskList: React.FC<Props> = ({ workspace }: Props) => {
Expand All @@ -106,13 +98,16 @@ const TaskList: React.FC<Props> = ({ workspace }: Props) => {
useSettings<Settings>(stgsConfig);
const { canCreateNSC, canCreateWorkspaceNSC } = usePermissions();
const { canModifyWorkspaceNSC } = usePermissions();
const taskListModal = useModal(TaskListModalComponent);
const canceler = useRef(new AbortController());

const BatchActionConfirmModal = useModal(BatchActionConfirmModalComponent);

const {
themeSettings: { className: themeClass },
} = useTheme();
useEffect(() => {
if (sourcesModal) {
taskListModal.open();
}
}, [taskListModal, sourcesModal]);

const loadedTasks = useMemo(() => tasks?.map(taskFromCommandTask) || [], [tasks]);

Expand Down Expand Up @@ -654,26 +649,14 @@ const TaskList: React.FC<Props> = ({ workspace }: Props) => {
itemName="task"
onConfirm={handleBatchKill}
/>
<Modal
footer={null}
open={!!sourcesModal}
style={{ minWidth: '600px' }}
<taskListModal.Component
sourcesModal={sourcesModal}
title={`
${sourcesModal?.sources.length}
TensorBoard Source${sourcesModal?.plural}
`}
wrapClassName={themeClass}
onCancel={handleSourceDismiss}>
<div className={css.sourceLinks}>
<Grid gap={ShirtSize.Medium} minItemWidth={120}>
{sourcesModal?.sources.map((source) => (
<Link key={source.id} path={source.path}>
{source.type} {source.id}
</Link>
))}
</Grid>
</div>
</Modal>
onClose={handleSourceDismiss}
/>
</>
);
};
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.sourceLinks {
label {
font-size: 12px;
}
}
60 changes: 60 additions & 0 deletions webui/react/src/components/TaskListModalComponent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { Modal } from 'hew/Modal';
import { ShirtSize } from 'hew/Theme';
import React from 'react';

import Grid from 'components/Grid';
import Link from 'components/Link';
import { ValueOf } from 'types';

import css from './TaskListModalComponent.module.scss';

export interface TensorBoardSource {
id: number;
path: string;
type: TensorBoardSourceType;
}

export interface SourceInfo {
path: string;
plural: string;
sources: TensorBoardSource[];
}

const TensorBoardSourceType = {
Experiment: 'Experiment',
Trial: 'Trial',
} as const;

type TensorBoardSourceType = ValueOf<typeof TensorBoardSourceType>;

interface Props {
title: string;
sourcesModal?: SourceInfo;
onClose: () => void;
}

const TaskListModalComponent: React.FC<Props> = ({ onClose, sourcesModal, title }: Props) => {
return (
<Modal
size="medium"
submit={{
handleError: () => {},
handler: onClose,
text: 'Close',
}}
title={title}
onClose={onClose}>
<div className={css.sourceLinks}>
<Grid gap={ShirtSize.Medium} minItemWidth={120}>
{sourcesModal?.sources.map((source) => (
<Link key={source.id} path={source.path}>
{source.type} {source.id}
</Link>
))}
</Grid>
</div>
</Modal>
);
};

export default TaskListModalComponent;
3 changes: 0 additions & 3 deletions webui/react/src/components/TextEditorModal.module.scss

This file was deleted.

Loading