未验证 提交 d7e87995 编写于 作者: P Peter Pan 提交者: GitHub

frontend 2.0.0-beta.26 (#609)

* resolve server rename conflict

* feat: add running toggle stopped color

* feat: revalidate runs and tags when refreshing

* v2.0.0-beta.26

* fix: make language optional

* fix: language before open_browser
上级 f8aa0f06
import React, {FunctionComponent} from 'react';
import {
WithStyled,
dangerActiveColor,
dangerColor,
dangerFocusedColor,
ellipsis,
em,
half,
......@@ -15,13 +18,25 @@ import RawIcon from '~/components/Icon';
import styled from 'styled-components';
const height = em(36);
const colors = {
primary: {
default: primaryColor,
active: primaryActiveColor,
focused: primaryFocusedColor
},
danger: {
default: dangerColor,
active: dangerActiveColor,
focused: dangerFocusedColor
}
};
const Wrapper = styled.a`
const Wrapper = styled.a<{type: keyof typeof colors}>`
cursor: pointer;
height: ${height};
line-height: ${height};
border-radius: ${half(height)};
background-color: ${primaryColor};
background-color: ${props => colors[props.type].default};
color: ${textInvertColor};
display: block;
text-align: center;
......@@ -30,11 +45,11 @@ const Wrapper = styled.a`
&:hover,
&:focus {
background-color: ${primaryFocusedColor};
background-color: ${props => colors[props.type].focused};
}
&:active {
background-color: ${primaryActiveColor};
background-color: ${props => colors[props.type].active};
}
`;
......@@ -44,11 +59,12 @@ const Icon = styled(RawIcon)`
type ButtonProps = {
icon?: string;
type?: keyof typeof colors;
onClick?: () => unknown;
};
const Button: FunctionComponent<ButtonProps & WithStyled> = ({icon, children, className, onClick}) => (
<Wrapper className={className} onClick={onClick}>
const Button: FunctionComponent<ButtonProps & WithStyled> = ({icon, type, children, className, onClick}) => (
<Wrapper className={className} onClick={onClick} type={type || 'primary'}>
{icon && <Icon type={icon}></Icon>}
{children}
</Wrapper>
......
......@@ -25,7 +25,11 @@ const RunningToggle: FunctionComponent<RunningToggleProps> = ({running, onToggle
onToggle?.(state);
}, [onToggle, state]);
return <StyledButton onClick={() => setState(s => !s)}>{t(state ? 'running' : 'stopped')}</StyledButton>;
return (
<StyledButton onClick={() => setState(s => !s)} type={state ? 'primary' : 'danger'}>
{t(state ? 'running' : 'stopped')}
</StyledButton>
);
};
export default RunningToggle;
......@@ -4,8 +4,8 @@ import {Tag} from '~/types';
import groupBy from 'lodash/groupBy';
import intersection from 'lodash/intersection';
import uniq from 'lodash/uniq';
import useRequest from '~/hooks/useRequest';
import {useRouter} from 'next/router';
import {useRunningRequest} from '~/hooks/useRequest';
type Runs = string[];
type Tags = Record<string, string[]>;
......@@ -102,11 +102,11 @@ const reducer = (state: State, action: Action): State => {
}
};
const useTagFilters = (type: string) => {
const useTagFilter = (type: string, running: boolean) => {
const router = useRouter();
const {data: runs, loading: loadingRuns} = useRequest<Runs>('/runs');
const {data: tags, loading: loadingTags} = useRequest<Tags>(`/${type}/tags`);
const {data: runs, loading: loadingRuns} = useRunningRequest<Runs>('/runs', running);
const {data: tags, loading: loadingTags} = useRunningRequest<Tags>(`/${type}/tags`, running);
const selectedRuns = useMemo(
() =>
......@@ -152,4 +152,4 @@ const useTagFilters = (type: string) => {
};
};
export default useTagFilters;
export default useTagFilter;
{
"name": "visualdl",
"version": "2.0.0-beta.25",
"version": "2.0.0-beta.26",
"title": "VisualDL",
"description": "A platform to visualize the deep learning process and result.",
"keywords": [
......
......@@ -17,8 +17,8 @@ import RunningToggle from '~/components/RunningToggle';
import SearchInput from '~/components/SearchInput';
import Title from '~/components/Title';
import styled from 'styled-components';
import useRequest from '~/hooks/useRequest';
import {useRouter} from 'next/router';
import {useRunningRequest} from '~/hooks/useRequest';
import useSearchValue from '~/hooks/useSearchValue';
const dimensions = ['2d', '3d'];
......@@ -39,9 +39,11 @@ const AsideTitle = styled.div`
const HighDimensional: NextI18NextPage = () => {
const {t} = useTranslation(['high-dimensional', 'common']);
const [running, setRunning] = useState(true);
const {query} = useRouter();
const queryRun = Array.isArray(query.run) ? query.run[0] : query.run;
const {data: runs, error, loading} = useRequest<string[]>('/runs');
const {data: runs, error, loading} = useRunningRequest<string[]>('/runs', running);
const selectedRun = runs?.includes(queryRun) ? queryRun : runs?.[0];
const [run, setRun] = useState(selectedRun);
......@@ -51,7 +53,6 @@ const HighDimensional: NextI18NextPage = () => {
const debounceSearch = useSearchValue(search);
const [dimension, setDimension] = useState(dimensions[0] as Dimension);
const [reduction, setReduction] = useState(reductions[0] as Reduction);
const [running, setRunning] = useState(true);
const [labelVisibility, setLabelVisibility] = useState(true);
const aside = (
......
......@@ -2,35 +2,36 @@
import {NextI18NextPage, useTranslation} from '~/utils/i18n';
import React, {useCallback, useMemo, useState} from 'react';
import {em, rem} from '~/utils/style';
// import {em, rem} from '~/utils/style';
import AsideDivider from '~/components/AsideDivider';
import ChartPage from '~/components/ChartPage';
import Checkbox from '~/components/Checkbox';
import Content from '~/components/Content';
import Field from '~/components/Field';
import Icon from '~/components/Icon';
// import Icon from '~/components/Icon';
import Preloader from '~/components/Preloader';
import RunSelect from '~/components/RunSelect';
import RunningToggle from '~/components/RunningToggle';
import SampleChart from '~/components/SamplesPage/SampleChart';
import TagFilter from '~/components/TagFilter';
import Title from '~/components/Title';
import {rem} from '~/utils/style';
import styled from 'styled-components';
import useTagFilter from '~/hooks/useTagFilter';
const StyledIcon = styled(Icon)`
font-size: ${rem(16)};
margin-left: ${em(6)};
margin-right: ${em(4)};
vertical-align: middle;
`;
// const StyledIcon = styled(Icon)`
// font-size: ${rem(16)};
// margin-left: ${em(6)};
// margin-right: ${em(4)};
// vertical-align: middle;
// `;
const CheckboxTitle = styled.span`
font-size: ${rem(16)};
font-weight: 700;
vertical-align: text-top;
`;
// const CheckboxTitle = styled.span`
// font-size: ${rem(16)};
// font-weight: 700;
// vertical-align: text-top;
// `;
const SubField = styled(Field)`
margin-left: ${rem(26)};
......@@ -44,8 +45,11 @@ type Item = {
const Samples: NextI18NextPage = () => {
const {t} = useTranslation(['samples', 'common']);
const [running, setRunning] = useState(true);
const {runs, tags, selectedRuns, selectedTags, onChangeRuns, onFilterTags, loadingRuns, loadingTags} = useTagFilter(
'images'
'images',
running
);
const ungroupedSelectedTags = useMemo(
() =>
......@@ -59,24 +63,23 @@ const Samples: NextI18NextPage = () => {
[selectedTags]
);
const [showImage, setShowImage] = useState(true);
const showImage = true;
// const [showImage, setShowImage] = useState(true);
// const [showAudio, setShowAudio] = useState(true);
// const [showText, setShowText] = useState(true);
const [showActualSize, setShowActualSize] = useState(false);
const [running, setRunning] = useState(true);
const aside = (
<section>
<RunSelect runs={runs} value={selectedRuns} onChange={onChangeRuns} />
<AsideDivider />
<Field>
{/* <Field>
<Checkbox value={showImage} onChange={setShowImage} disabled>
<StyledIcon type="image" />
<CheckboxTitle>{t('image')}</CheckboxTitle>
</Checkbox>
</Field>
</Field> */}
{showImage && (
<SubField>
<Checkbox value={showActualSize} onChange={setShowActualSize}>
......
......@@ -27,8 +27,11 @@ const toolTipSortingValues = ['default', 'descending', 'ascending', 'nearest'];
const Scalars: NextI18NextPage = () => {
const {t} = useTranslation(['scalars', 'common']);
const [running, setRunning] = useState(true);
const {runs, tags, selectedRuns, selectedTags, onChangeRuns, onFilterTags, loadingRuns, loadingTags} = useTagFilter(
'scalars'
'scalars',
running
);
const debounceTags = useSearchValue(selectedTags);
......@@ -44,8 +47,6 @@ const Scalars: NextI18NextPage = () => {
const [ignoreOutliers, setIgnoreOutliers] = useState(false);
const [running, setRunning] = useState(true);
const aside = (
<section>
<RunSelect runs={runs} value={selectedRuns} onChange={onChangeRuns} />
......
......@@ -23,8 +23,11 @@ export const progressSpinnerSize = '20px';
// colors
export const primaryColor = '#2932E1';
export const dangerColor = '#FF3912';
export const primaryFocusedColor = lighten(0.08, primaryColor);
export const primaryActiveColor = lighten(0.12, primaryColor);
export const dangerFocusedColor = lighten(0.08, dangerColor);
export const dangerActiveColor = lighten(0.12, dangerColor);
export const selectedColor = '#1A73E8';
export const lightColor = '#F4F5FC';
export const lightFocusedColor = darken(0.03, lightColor);
......
......@@ -28,6 +28,7 @@ from argparse import ArgumentParser
from flask import (Flask, Response, redirect, request, send_file,
send_from_directory)
from flask_babel import Babel
import visualdl
import visualdl.server
......@@ -57,7 +58,7 @@ mock_data_path = os.path.join(SERVER_DIR, "./mock_data/")
class ParseArgs(object):
def __init__(self, logdir, host="0.0.0.0", port=8040, model_pb="", cache_timeout=20, language=default_language):
def __init__(self, logdir, host="0.0.0.0", port=8040, model_pb="", cache_timeout=20, language=None):
self.logdir = logdir
self.host = host
self.port = port
......@@ -70,7 +71,7 @@ def try_call(function, *args, **kwargs):
res = lib.retry(error_retry_times, function, error_sleep_time, *args,
**kwargs)
if not res:
logger.error("server temporary error, will retry latter.")
logger.error("Internal server error. Retry later.")
return res
......@@ -119,7 +120,6 @@ def parse_args():
"-L",
"--language",
type=str,
default=default_language,
action="store",
help="set the default language")
......@@ -149,6 +149,9 @@ def create_app(args):
# set static expires in a short time to reduce browser's memory usage.
app.config['SEND_FILE_MAX_AGE_DEFAULT'] = 30
app.config['BABEL_DEFAULT_LOCALE'] = default_language
babel = Babel(app)
log_reader = LogReader(args.logdir)
# mannully put graph's image on this path also works.
......@@ -157,11 +160,16 @@ def create_app(args):
CACHE = MemCache(timeout=args.cache_timeout)
cache_get = lib.cache_get(CACHE)
@babel.localeselector
def get_locale():
language = args.language
if not language or not language in support_language:
language = request.accept_languages.best_match(support_language)
return language
@app.route("/")
def index():
language = args.language
if not language in support_language:
language = default_language
language = get_locale()
if language == default_language:
return redirect('/app/index', code=302)
return redirect('/app/' + language + '/index', code=302)
......@@ -188,9 +196,7 @@ def create_app(args):
@app.route('/api/language')
def language():
data = args.language
if not data in support_language:
data = default_language
data = get_locale()
result = gen_result(0, "", data)
return Response(json.dumps(result), mimetype='application/json')
......@@ -331,7 +337,7 @@ def _open_browser(app, index_url):
webbrowser.open(index_url)
def _run(logdir, host="127.0.0.1", port=8080, model_pb="", cache_timeout=20, language=default_language, open_browser=False):
def _run(logdir, host="127.0.0.1", port=8080, model_pb="", cache_timeout=20, language=None, open_browser=False):
args = ParseArgs(logdir=logdir, host=host, port=port, model_pb=model_pb, cache_timeout=cache_timeout, language=language)
logger.info(" port=" + str(args.port))
app = create_app(args)
......@@ -341,7 +347,7 @@ def _run(logdir, host="127.0.0.1", port=8080, model_pb="", cache_timeout=20, lan
app.run(debug=False, host=args.host, port=args.port, threaded=True)
def run(logdir, host="127.0.0.1", port=8080, model_pb="", cache_timeout=20, language=default_language, open_browser=False):
def run(logdir, host="127.0.0.1", port=8080, model_pb="", cache_timeout=20, language=None, open_browser=False):
kwarg = {
"logdir": logdir,
"host": host,
......@@ -360,5 +366,5 @@ def run(logdir, host="127.0.0.1", port=8080, model_pb="", cache_timeout=20, lang
def main():
args = parse_args()
logger.info(" port=" + str(args.port))
app = create_app(args=parse_args())
app = create_app(args=args)
app.run(debug=False, host=args.host, port=args.port, threaded=True)
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册