Show experiment error message and refactor function component props (#5029)

This commit is contained in:
Lijiaoa 2022-08-08 10:43:17 +08:00 коммит произвёл GitHub
Родитель 119a2b60a3
Коммит 4ab85d3d47
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
22 изменённых файлов: 254 добавлений и 147 удалений

Просмотреть файл

@ -1,12 +1,17 @@
import React, { useRef } from 'react';
import PropTypes from 'prop-types';
import copy from 'copy-to-clipboard';
import { IconButton, FontSizes, TooltipHost } from '@fluentui/react';
import { TOOLTIP_BACKGROUND_COLOR } from '@static/const';
interface CopyButtonProps {
value: string;
hideTooltip?: boolean;
}
const COPIED_TOOLTIP_CLOSE_DELAY = 1000;
const CopyButton = ({ value, hideTooltip }): any => {
const CopyButton = (props: CopyButtonProps): any => {
const { value, hideTooltip } = props;
const ref = useRef(null);
return (
<div>
@ -47,9 +52,4 @@ const CopyButton = ({ value, hideTooltip }): any => {
);
};
CopyButton.propTypes = {
value: PropTypes.string.isRequired,
hideTooltip: PropTypes.bool
};
export default CopyButton;

Просмотреть файл

@ -1,10 +1,14 @@
import * as React from 'react';
import PropTypes from 'prop-types';
import { DetailsRow } from '@fluentui/react';
import { DetailsRow, IDetailsRowBaseProps } from '@fluentui/react/lib/DetailsList';
import OpenRow from './OpenRow';
import '@style/table.scss';
const ExpandableDetails = (props): any => {
interface ExpandableDetailsProps {
detailsProps: IDetailsRowBaseProps;
isExpand: boolean;
}
const ExpandableDetails = (props: ExpandableDetailsProps): any => {
const { detailsProps, isExpand } = props;
return (
<div>
@ -14,9 +18,4 @@ const ExpandableDetails = (props): any => {
);
};
ExpandableDetails.propTypes = {
detailsProps: PropTypes.object,
isExpand: PropTypes.bool
};
export default ExpandableDetails;

Просмотреть файл

@ -1,5 +1,4 @@
import React, { useState } from 'react';
import PropTypes from 'prop-types';
import { Stack, PrimaryButton, Pivot, PivotItem, DefaultButton } from '@fluentui/react';
import * as copy from 'copy-to-clipboard';
import JSONTree from 'react-json-tree';
@ -18,7 +17,11 @@ import '@style/experiment/overview/overview.scss';
* Remember to update it if the value is changed or this file is moved.
**/
const OpenRow = (props): any => {
interface OpenRowProps {
trialId: string;
}
const OpenRow = (props: OpenRowProps): any => {
const [typeInfo, setTypeInfo] = useState('');
const [info, setInfo] = useState('');
const [isHidenInfo, setHideninfo] = useState(true);
@ -161,8 +164,4 @@ const OpenRow = (props): any => {
);
};
OpenRow.propTypes = {
trialId: PropTypes.string
};
export default OpenRow;

Просмотреть файл

@ -1,8 +1,11 @@
import * as React from 'react';
import PropTypes from 'prop-types';
import TrialLog from './TrialLog';
const PaitrialLog = (props): any => {
interface PaitrialLogProps {
logStr: string;
}
const PaitrialLog = (props: PaitrialLogProps): any => {
const { logStr } = props;
const isHasNFSLog = logStr.indexOf(',') !== -1 ? true : false;
return (
@ -19,8 +22,4 @@ const PaitrialLog = (props): any => {
);
};
PaitrialLog.propTypes = {
logStr: PropTypes.string
};
export default PaitrialLog;

Просмотреть файл

@ -1,7 +1,11 @@
import * as React from 'react';
import PropTypes from 'prop-types';
const TrialLog = (props): any => {
interface TrialLogProps {
logStr: string;
logName: string;
}
const TrialLog = (props: TrialLogProps): any => {
const { logStr, logName } = props;
const isHyperlink = logStr.toLowerCase().startsWith('http');
@ -19,9 +23,4 @@ const TrialLog = (props): any => {
);
};
TrialLog.propTypes = {
logStr: PropTypes.string,
logName: PropTypes.string
};
export default TrialLog;

Просмотреть файл

@ -1,6 +1,6 @@
import * as React from 'react';
import { Stack, PrimaryButton, Toggle, IStackTokens } from '@fluentui/react';
import { TooltipForIntermediate, EventMap, allTrialsIntermediateChart } from '@static/interface';
import { TooltipForIntermediate, EventMap, AllTrialsIntermediateChart } from '@static/interface';
import { reformatRetiariiParameter } from '@static/function';
import ReactEcharts from 'echarts-for-react';
import 'echarts/lib/component/tooltip';
@ -11,9 +11,9 @@ const stackTokens: IStackTokens = {
};
interface IntermediateState {
detailSource: allTrialsIntermediateChart[];
detailSource: AllTrialsIntermediateChart[];
interSource: object;
filterSource: allTrialsIntermediateChart[];
filterSource: AllTrialsIntermediateChart[];
eachIntermediateNum: number; // trial's intermediate number count
isLoadconfirmBtn: boolean;
isFilter?: boolean | undefined;
@ -23,7 +23,7 @@ interface IntermediateState {
}
interface IntermediateProps {
source: allTrialsIntermediateChart[];
source: AllTrialsIntermediateChart[];
}
class Intermediate extends React.Component<IntermediateProps, IntermediateState> {
@ -47,7 +47,7 @@ class Intermediate extends React.Component<IntermediateProps, IntermediateState>
};
}
drawIntermediate = (source: allTrialsIntermediateChart[]): void => {
drawIntermediate = (source: AllTrialsIntermediateChart[]): void => {
if (source.length > 0) {
this.setState({
length: source.length,
@ -145,7 +145,7 @@ class Intermediate extends React.Component<IntermediateProps, IntermediateState>
// confirm btn function [filter data]
filterLines = (): void => {
const filterSource: allTrialsIntermediateChart[] = [];
const filterSource: AllTrialsIntermediateChart[] = [];
this.setState({ isLoadconfirmBtn: true }, () => {
const { source } = this.props;
// get input value

Просмотреть файл

@ -1,8 +1,14 @@
import React from 'react';
import PropTypes from 'prop-types';
import { PrimaryButton, Dialog, DialogType, DialogFooter } from '@fluentui/react';
import { KillJobIsError } from '@static/interface';
function KillJobDialog(props): any {
interface KillJobDialogProps {
trialId: string;
isError: KillJobIsError;
onHideDialog: () => void;
}
function KillJobDialog(props: KillJobDialogProps): any {
const { onHideDialog, trialId, isError } = props;
const dialogContentProps = {
@ -29,10 +35,4 @@ function KillJobDialog(props): any {
);
}
KillJobDialog.propTypes = {
trialId: PropTypes.string,
isError: PropTypes.object,
onHideDialog: PropTypes.func
};
export default KillJobDialog;

Просмотреть файл

@ -1,5 +1,4 @@
import React, { useState, useRef, useContext } from 'react';
import PropTypes from 'prop-types';
import axios from 'axios';
import { Stack, FocusTrapCallout, DefaultButton, FocusZone, PrimaryButton } from '@fluentui/react';
import { MANAGER_IP } from '@static/const';
@ -9,7 +8,11 @@ import { gap10 } from '@components/fluent/ChildrenGap';
import { styles } from '@components/experiment/overview/params/basicInfoStyles';
import { AppContext } from '@/App';
function KillJobIndex(props): any {
interface KillJobIndexProps {
trialId: string;
}
function KillJobIndex(props: KillJobIndexProps): any {
const menuButtonElement = useRef(null);
const { startTimer, closeTimer, interval, refreshDetailTable } = useContext(AppContext);
const { trialId } = props;
@ -118,9 +121,4 @@ function KillJobIndex(props): any {
);
}
KillJobIndex.propTypes = {
trialId: PropTypes.string,
updatePage: PropTypes.func
};
export default KillJobIndex;

Просмотреть файл

@ -1,8 +1,8 @@
import React, { useState, useContext } from 'react';
import PropTypes from 'prop-types';
import { Stack, PrimaryButton } from '@fluentui/react';
import { gap10 } from '@components/fluent/ChildrenGap';
import { AppContext } from '@/App';
import { SearchItems } from '@static/interface';
import { getSearchInputValueBySearchList } from './searchFunction';
// This file is for search trial ['Trial id', 'Trial No.']
@ -14,11 +14,19 @@ import { getSearchInputValueBySearchList } from './searchFunction';
// 1 // only filter one trial that trial no is 1
// bw // only filter that trial id include `bw`
function GeneralSearch(props): any {
interface GeneralSearchProps {
searchName: string;
searchFilter: SearchItems[];
dismiss: () => void;
setSearchInputVal: (a: string) => void;
changeSearchFilterList: (a: SearchItems[]) => void;
}
function GeneralSearch(props: GeneralSearchProps): any {
const { updateDetailPage } = useContext(AppContext);
// searchName val: Trial No. | Trial id
const { searchName, searchFilter, dismiss, changeSearchFilterList, setSearchInputVal } = props;
const [firstInputVal, setFirstInputVal] = useState(getSearchNameInit());
const [firstInputVal, setFirstInputVal] = useState(getSearchNameInit() as string);
function updateFirstInputVal(ev: React.ChangeEvent<HTMLInputElement>): void {
setFirstInputVal(ev.target.value);
@ -79,12 +87,4 @@ function GeneralSearch(props): any {
);
}
GeneralSearch.propTypes = {
searchName: PropTypes.string,
searchFilter: PropTypes.array,
dismiss: PropTypes.func,
setSearchInputVal: PropTypes.func,
changeSearchFilterList: PropTypes.func
};
export default GeneralSearch;

Просмотреть файл

@ -1,5 +1,4 @@
import React, { useState, useContext } from 'react';
import PropTypes from 'prop-types';
import {
Stack,
DefaultButton,
@ -18,11 +17,15 @@ import { classNames, isChoiceType } from './searchFunction';
import { AppContext } from '@/App';
// TableList search layout
interface SearchProps {
searchFilter: SearchItems[];
changeSearchFilterList: (a: SearchItems[]) => void;
}
function Search(props): any {
function Search(props: SearchProps): any {
const { searchFilter, changeSearchFilterList } = props;
const { updateDetailPage } = useContext(AppContext);
const [searchInputVal, setSearchInputVal] = useState('');
const [searchInputVal, setSearchInputVal] = useState('' as string);
function getSearchMenu(parameterList): IContextualMenuProps {
const menu: Array<object> = [];
@ -96,7 +99,7 @@ function Search(props): any {
function renderParametersSearchComponent(item: IContextualMenuItem, dismissMenu: () => void): JSX.Element {
return (
<SearchParameterConditions
parameter={item.text}
parameter={item.text ?? ''}
searchFilter={searchFilter} // search filter list
changeSearchFilterList={changeSearchFilterList}
updatePage={updateDetailPage}
@ -109,7 +112,7 @@ function Search(props): any {
function renderDefaultMetricSearchComponent(item: IContextualMenuItem, dismissMenu: () => void): JSX.Element {
return (
<SearchDefaultMetric
parameter={item.text}
parameter={item.text ?? ''}
searchFilter={searchFilter} // search filter list
changeSearchFilterList={changeSearchFilterList}
updatePage={updateDetailPage}
@ -122,7 +125,7 @@ function Search(props): any {
function renderIdAndNoComponent(item: IContextualMenuItem, dismissMenu: () => void): JSX.Element {
return (
<GeneralSearch
searchName={item.text}
searchName={item.text ?? ''}
searchFilter={searchFilter} // search fliter list
changeSearchFilterList={changeSearchFilterList}
setSearchInputVal={setSearchInputVal}
@ -136,7 +139,7 @@ function Search(props): any {
}
// update TableList page
function changeTableListPage(searchFilterList: Array<SearchItems>): void {
function changeTableListPage(searchFilterList: SearchItems[]): void {
changeSearchFilterList(searchFilterList);
updateDetailPage();
}
@ -310,9 +313,4 @@ function Search(props): any {
);
}
Search.propTypes = {
searchFilter: PropTypes.array,
changeSearchFilterList: PropTypes.func
};
export default Search;

Просмотреть файл

@ -1,10 +1,10 @@
import React, { useState, useContext } from 'react';
import PropTypes from 'prop-types';
import { Stack, PrimaryButton, Dropdown, IDropdownOption } from '@fluentui/react';
import { EXPERIMENT } from '@static/datamodel';
import { getSearchInputValueBySearchList } from './searchFunction';
import { gap10 } from '@components/fluent/ChildrenGap';
import { AppContext } from '@/App';
import { SearchItems } from '@static/interface';
// This file is for filtering trial default metric column including intermediate results
// you could click `filter` button -> `Default metric` use it
@ -14,13 +14,22 @@ import { AppContext } from '@/App';
// Default metric:[0.1,0.2]; // 0.1 < trial metric < 0.2
// Default metric:0.1009; // trial metric = 0.1009, because shown metric is dealed with,so it's no use in most time
function SearchDefaultMetric(props): any {
interface SearchDefaultMetricProps {
parameter: string;
searchFilter: SearchItems[];
dismiss: () => void;
setSearchInputVal: (a: string) => void;
changeSearchFilterList: (a: SearchItems[]) => void;
updatePage: () => void;
}
function SearchDefaultMetric(props: SearchDefaultMetricProps): any {
const { parameter, searchFilter, dismiss, changeSearchFilterList, setSearchInputVal } = props;
const { updateDetailPage } = useContext(AppContext);
const operatorList = ['between', '>', '<', '='];
const initValueList = getInitVal();
const [operatorVal, setOperatorVal] = useState(initValueList[0]);
const [operatorVal, setOperatorVal] = useState(initValueList[0] as string);
const [firstInputVal, setFirstInputVal] = useState(initValueList[1] as string);
const [secondInputVal, setSecondInputVal] = useState(initValueList[2] as string);
@ -61,7 +70,7 @@ function SearchDefaultMetric(props): any {
if (secondInputVal === '' && operatorVal === 'between') {
// if user uses 'between' operator and doesn't write the second input value,
// help to set second value as this parameter max value
return EXPERIMENT.searchSpace[parameter]._value[1].toString();
return String(EXPERIMENT.searchSpace[parameter]._value[1]);
}
return secondInputVal as string;
@ -141,13 +150,4 @@ function SearchDefaultMetric(props): any {
);
}
SearchDefaultMetric.propTypes = {
parameter: PropTypes.string,
searchFilter: PropTypes.array,
dismiss: PropTypes.func,
setSearchInputVal: PropTypes.func,
changeSearchFilterList: PropTypes.func,
updatePage: PropTypes.func
};
export default SearchDefaultMetric;

Просмотреть файл

@ -1,10 +1,10 @@
import React, { useState, useContext } from 'react';
import PropTypes from 'prop-types';
import { Stack, PrimaryButton, Dropdown, IDropdownOption } from '@fluentui/react';
import { EXPERIMENT } from '@static/datamodel';
import { getDropdownOptions, getSearchInputValueBySearchList } from './searchFunction';
import { gap10 } from '@components/fluent/ChildrenGap';
import { AppContext } from '@/App';
import { SearchItems } from '@static/interface';
/***
* This file is for filtering trial parameters and trial status
@ -30,14 +30,23 @@ import { AppContext } from '@/App';
* hidden_size1024 // please don't input this format!
*/
function SearchParameterConditions(props): any {
interface SearchParameterConditionsProps {
parameter: string;
searchFilter: SearchItems[];
dismiss: () => void;
setSearchInputVal: (a: string) => void;
changeSearchFilterList: (a: SearchItems[]) => void;
updatePage: () => void;
}
function SearchParameterConditions(props: SearchParameterConditionsProps): any {
const { parameter, searchFilter, dismiss, changeSearchFilterList, setSearchInputVal } = props;
const { updateDetailPage } = useContext(AppContext);
const isChoiceTypeSearchFilter = parameter === 'StatusNNI' || EXPERIMENT.searchSpace[parameter]._type === 'choice';
const operatorList = isChoiceTypeSearchFilter ? ['=', '≠'] : ['between', '>', '<', '=', '≠'];
const initValueList = getInitVal();
const [operatorVal, setOperatorVal] = useState(initValueList[0]);
const [operatorVal, setOperatorVal] = useState(initValueList[0] as string);
const [firstInputVal, setFirstInputVal] = useState(initValueList[1] as string);
const [secondInputVal, setSecondInputVal] = useState(initValueList[2] as string);
// status or choice parameter dropdown selected value list
@ -209,13 +218,4 @@ function SearchParameterConditions(props): any {
);
}
SearchParameterConditions.propTypes = {
parameter: PropTypes.string,
searchFilter: PropTypes.array,
dismiss: PropTypes.func,
setSearchInputVal: PropTypes.func,
changeSearchFilterList: PropTypes.func,
updatePage: PropTypes.func
};
export default SearchParameterConditions;

Просмотреть файл

@ -159,7 +159,7 @@ function searchChoiceFilter(arr: TableRecord[], element: SearchItems, field: str
}
// click Apply btn: set searchBox value now
function getSearchInputValueBySearchList(searchFilter): string {
function getSearchInputValueBySearchList(searchFilter: SearchItems[]): string {
let str = ''; // store search input value
searchFilter.forEach(item => {

Просмотреть файл

@ -1,8 +1,16 @@
import React from 'react';
import PropTypes from 'prop-types';
import { PrimaryButton, Dialog, DialogType, DialogFooter } from '@fluentui/react';
import { KillJobIsError, TensorboardTaskInfo } from '@static/interface';
function TensorboardDialog(props): any {
interface TensorboardDialogProps {
isReaptedStartTensorboard: boolean;
isShowTensorboardDetail: boolean;
onHideDialog: () => void;
item: TensorboardTaskInfo;
errorMessage: KillJobIsError;
}
function TensorboardDialog(props: TensorboardDialogProps): any {
const { isReaptedStartTensorboard, onHideDialog, item, isShowTensorboardDetail, errorMessage } = props;
const dialogContentProps = {
@ -19,7 +27,7 @@ function TensorboardDialog(props): any {
return (
<Dialog hidden={false} dialogContentProps={dialogContentProps} modalProps={{ className: 'dialog' }}>
{errorMessage.error ? (
{errorMessage.isError ? (
<div>
<span>Error message: {errorMessage.message}</span>
</div>
@ -44,7 +52,7 @@ function TensorboardDialog(props): any {
</div>
</div>
)}
{errorMessage.error ? (
{errorMessage.isError ? (
<DialogFooter>
<PrimaryButton onClick={onHideDialog} text='Close' />
</DialogFooter>
@ -60,12 +68,4 @@ function TensorboardDialog(props): any {
);
}
TensorboardDialog.propTypes = {
isReaptedStartTensorboard: PropTypes.bool,
isShowTensorboardDetail: PropTypes.bool,
onHideDialog: PropTypes.func,
item: PropTypes.object,
errorMessage: PropTypes.object
};
export default TensorboardDialog;

Просмотреть файл

@ -1,29 +1,33 @@
import React, { useState, useEffect } from 'react';
import PropTypes from 'prop-types';
import axios from 'axios';
import { DefaultButton, IContextualMenuProps } from '@fluentui/react';
import { MANAGER_IP } from '@static/const';
import { disableTensorboard, getTensorboardMenu } from '@static/function';
import { Tensorboard } from '@static/interface';
import TensorboardDialog from './TensorboardDialog';
import { KillJobIsError, TensorboardTaskInfo } from '@static/interface';
function TensorboardUI(props): any {
interface TensorboardUIProps {
selectedRowIds: string[];
changeSelectTrialIds: () => void;
}
function TensorboardUI(props: TensorboardUIProps): any {
let refreshTensorboard = 0;
const { selectedRowIds, changeSelectTrialIds } = props;
const [queryTensorboardList, setQueryTensorboardList] = useState([]);
const [queryTensorboardList, setQueryTensorboardList] = useState([] as TensorboardTaskInfo[]);
const [isReaptedStartTensorboard, setReaptedTensorboard] = useState(false);
const [tensorboardPanelVisible, setTensorboardPanelVisible] = useState(false);
const [isShowTensorboardDetail, setIsShowTensorboardDetail] = useState(false);
const [selectedTensorboard, setSelectedTensorboard] = useState({});
const [errorMessage, setErrorMessage] = useState({});
const [timerList, setTimerList] = useState([0]);
const [selectedTensorboard, setSelectedTensorboard] = useState({} as TensorboardTaskInfo);
const [errorMessage, setErrorMessage] = useState({} as KillJobIsError);
const [timerList, setTimerList] = useState([0] as number[]);
function startTrialTensorboard(): void {
const { selectedRowIds } = props;
if (selectedRowIds.length > 0) {
setIsShowTensorboardDetail(false);
const result = queryTensorboardList.filter(
(item: Tensorboard) => item.trialJobIdList.join(',') === selectedRowIds.join(',')
(item: TensorboardTaskInfo) => item.trialJobIdList.join(',') === selectedRowIds.join(',')
);
if (result.length > 0) {
setReaptedTensorboard(true);
@ -34,17 +38,18 @@ function TensorboardUI(props): any {
startTensorboard
.then(res => {
if (res.status === 200) {
console.info(res.data);
setSelectedTensorboard(res.data);
closeTimer();
queryAllTensorboard();
setErrorMessage({ error: false, message: '' });
setErrorMessage({ isError: false, message: '' });
setTensorboardPanelVisible(true);
}
})
.catch(err => {
if (err.response) {
setErrorMessage({
error: true,
isError: true,
message: err.response.data.error || 'Failed to start tensorBoard!'
});
}
@ -88,7 +93,7 @@ function TensorboardUI(props): any {
});
}
function seeTensorboardWebportal(item: Tensorboard): void {
function seeTensorboardWebportal(item: TensorboardTaskInfo): void {
setSelectedTensorboard(item);
setIsShowTensorboardDetail(true);
setTensorboardPanelVisible(true);
@ -140,9 +145,4 @@ function TensorboardUI(props): any {
);
}
TensorboardUI.propTypes = {
selectedRowIds: PropTypes.array,
changeSelectTrialIds: PropTypes.func
};
export default TensorboardUI;

Просмотреть файл

@ -9,6 +9,7 @@ const completed = <Icon iconName='Completed' />;
const blocked = <Icon iconName='StatusCircleBlock' />;
const copy = <Icon iconName='Copy' />;
const tableListIcon = <Icon iconName='BulletedList' />;
const Important = <Icon iconName='Important' />;
const downLoadIcon = { iconName: 'Download' };
const infoIconAbout = { iconName: 'info' };
const timeIcon = { iconName: 'ReminderTime' };
@ -43,5 +44,6 @@ export {
Cancel,
ReplyAll,
RevToggleKey,
ChevronRightMed
ChevronRightMed,
Important
};

Просмотреть файл

@ -0,0 +1,38 @@
import React, { useState, useCallback } from 'react';
import { Stack } from '@fluentui/react/lib/Stack';
import { DefaultButton } from '@fluentui/react/lib/Button';
import LogPanel from '@components/nav/slideNav/LogPanel';
import { Important, Cancel } from '@components/fluent/Icon';
import { EXPERIMENT } from '@static/datamodel';
import '@style/nav/slideNavBtns.scss';
export const ErrorMessage: React.FunctionComponent = () => {
const [hideDialog, setHideDialog] = useState(EXPERIMENT.status === 'ERROR' ? true : false);
const [isShowLogPanel, setShowLogPanel] = useState(false);
const closeLogPanel = useCallback(() => setShowLogPanel(false), []);
const ShowLogPanel = useCallback(() => setShowLogPanel(true), []);
return (
<>
{hideDialog ? (
<div className='experiment-error'>
<Stack horizontal className='head'>
<Stack horizontal>
<div className='icon'>{Important}</div>
<div className='title'>Error</div>
</Stack>
<Stack className='close cursor' onClick={() => setHideDialog(false)}>
{Cancel}
</Stack>
</Stack>
<div className='message'>{EXPERIMENT.error}</div>
<Stack horizontalAlign='end' className='experiment-error-buttons'>
<DefaultButton className='detailsBtn' onClick={ShowLogPanel} text='Learn more' />
</Stack>
{/* learn about click -> default active key is dispatcher. */}
{isShowLogPanel ? <LogPanel closePanel={closeLogPanel} activeTab='dispatcher' /> : null}
</div>
) : null}
</>
);
};

Просмотреть файл

@ -17,6 +17,7 @@ import {
} from '@components/fluent/Icon';
import '@style/nav/nav.scss';
import '@style/icon.scss';
import { ErrorMessage } from '@components/nav/ErrorMessage';
interface NavState {
version: string;
@ -165,6 +166,8 @@ class NavCon extends React.Component<NavProps, NavState> {
/>
)}
</React.Fragment>
{/* experiment error model */}
<ErrorMessage />
</Stack>
);
}

Просмотреть файл

@ -3,7 +3,7 @@ import axios from 'axios';
import { IContextualMenuProps } from '@fluentui/react';
import { RETIARIIPARAMETERS } from './const';
import { EXPERIMENT } from './datamodel';
import { MetricDataRecord, FinalType, Tensorboard } from './interface';
import { MetricDataRecord, FinalType, TensorboardTaskInfo } from './interface';
function getPrefix(): string | undefined {
const pathName = window.location.pathname;
@ -286,7 +286,7 @@ function copyAndSort<T>(items: T[], columnKey: string, isSortedDescending?: bool
});
}
function disableTensorboard(selectedRowIds: string[], queryTensorboardList: Tensorboard[]): boolean {
function disableTensorboard(selectedRowIds: string[], queryTensorboardList: TensorboardTaskInfo[]): boolean {
let flag = true;
if (selectedRowIds.length !== 0) {
@ -300,7 +300,11 @@ function disableTensorboard(selectedRowIds: string[], queryTensorboardList: Tens
return flag;
}
function getTensorboardMenu(queryTensorboardList: Tensorboard[], stopFunc, seeDetailFunc): IContextualMenuProps {
function getTensorboardMenu(
queryTensorboardList: TensorboardTaskInfo[],
stopFunc,
seeDetailFunc
): IContextualMenuProps {
const result: Array<object> = [];
if (queryTensorboardList.length !== 0) {
result.push({

Просмотреть файл

@ -167,13 +167,20 @@ interface AllExperimentList {
prefixUrl: string;
}
interface Tensorboard {
interface KillJobIsError {
isError: boolean;
message: string;
}
type TensorboardTaskStatus = 'RUNNING' | 'DOWNLOADING_DATA' | 'STOPPING' | 'STOPPED' | 'ERROR' | 'FAIL_DOWNLOAD_DATA';
interface TensorboardTaskInfo {
id: string;
status: string;
status: TensorboardTaskStatus;
trialJobIdList: string[];
trialLogDirectoryList: string[];
pid: number;
port: string;
pid?: number;
port?: string;
}
// for TableList search
@ -186,7 +193,7 @@ interface SearchItems {
isChoice: boolean; // for parameters: type = choice and status also as choice type
}
interface allTrialsIntermediateChart {
interface AllTrialsIntermediateChart {
name: string;
// id: string;
sequenceId: number;
@ -215,7 +222,8 @@ export {
MultipleAxes,
SortInfo,
AllExperimentList,
Tensorboard,
TensorboardTaskInfo,
SearchItems,
allTrialsIntermediateChart
KillJobIsError,
AllTrialsIntermediateChart
};

Просмотреть файл

@ -3,7 +3,7 @@ import { MetricDataRecord, TableRecord, TrialJobInfo, MultipleAxes } from '../in
import { Trial } from './trial';
import { SearchSpace, MetricSpace } from './searchspace';
import { requestAxios, parseMetrics } from '../function';
import { allTrialsIntermediateChart } from '../interface';
import { AllTrialsIntermediateChart } from '../interface';
function groupMetricsByTrial(metrics: MetricDataRecord[]): Map<string, MetricDataRecord[]> {
const ret = new Map<string, MetricDataRecord[]>();
@ -91,8 +91,8 @@ class TrialManager {
return this.filter(trial => trial.status !== 'WAITING');
}
public allTrialsIntermediateChart(): allTrialsIntermediateChart[] {
const ret: allTrialsIntermediateChart[] = [];
public allTrialsIntermediateChart(): AllTrialsIntermediateChart[] {
const ret: AllTrialsIntermediateChart[] = [];
for (const trial of this.trials.values()) {
const mediate: number[] = [];
for (const items of trial.intermediates) {

Просмотреть файл

@ -1,5 +1,5 @@
$buttonBorderRadius: 23px;
$errorseriscolor: #FC615C;
.config {
position: fixed;
right: 0;
@ -80,3 +80,63 @@ $buttonBorderRadius: 23px;
margin: 0;
}
}
.experiment-error {
position: fixed;
bottom: 20px;
right: 20px;
max-width: 455px;
min-width: 300px;
padding: 28px 32px;
border-radius: 8px;
box-shadow: 0px 4px 16px rgba(78, 97, 123, 0.2);
background-color: #fff;
.head {
height: 27px;
line-height: 27px;
font-size: 20px;
font-weight: 700;
margin-bottom: 15px;
.title {
color: $errorseriscolor;
}
.close {
position: absolute;
right: 30px;
}
.icon{
width: 25px;
height: 25px;
background-color: $errorseriscolor;
border-radius: 50%;
margin-right: 15px;
i{
font-size: 21px;
color: #fff;
margin-left: 2px;
}
}
}
.message {
line-height: 24px;
}
&-buttons {
margin-top: 10px;
}
.detailsBtn {
width: 113px;
height: 32px;
color: #fff;
background: $errorseriscolor;
border: none;
border-radius: 6px;
}
}