Unverified Commit 9fb25ccc authored by SparkSnail's avatar SparkSnail Committed by GitHub
Browse files

Merge pull request #189 from microsoft/master

merge master
parents 1500458a 7c4bc33b
# Copyright (c) Microsoft Corporation. All rights reserved.
#
# MIT License
#
# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
# associated documentation files (the "Software"), to deal in the Software without restriction,
# including without limitation the rights to use, copy, modify, merge, publish, distribute,
# sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all copies or
# substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
# NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
# OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# ==================================================================================================
from . import trial
def classic_mode(
mutable_id,
mutable_layer_id,
funcs,
funcs_args,
fixed_inputs,
optional_inputs,
optional_input_size):
'''Execute the chosen function and inputs directly.
In this mode, the trial code is only running the chosen subgraph (i.e., the chosen ops and inputs),
without touching the full model graph.'''
if trial._params is None:
trial.get_next_parameter()
mutable_block = trial.get_current_parameter(mutable_id)
chosen_layer = mutable_block[mutable_layer_id]["chosen_layer"]
chosen_inputs = mutable_block[mutable_layer_id]["chosen_inputs"]
real_chosen_inputs = [optional_inputs[input_name]
for input_name in chosen_inputs]
layer_out = funcs[chosen_layer](
[fixed_inputs, real_chosen_inputs], **funcs_args[chosen_layer])
return layer_out
def enas_mode(
mutable_id,
mutable_layer_id,
funcs,
funcs_args,
fixed_inputs,
optional_inputs,
optional_input_size,
tf):
'''For enas mode, we build the full model graph in trial but only run a subgraph。
This is implemented by masking inputs and branching ops.
Specifically, based on the received subgraph (through nni.get_next_parameter),
it can be known which inputs should be masked and which op should be executed.'''
name_prefix = "{}_{}".format(mutable_id, mutable_layer_id)
# store namespace
if 'name_space' not in globals():
global name_space
name_space = dict()
name_space[mutable_id] = True
name_space[name_prefix] = dict()
name_space[name_prefix]['funcs'] = list(funcs)
name_space[name_prefix]['optional_inputs'] = list(optional_inputs)
# create tensorflow variables as 1/0 signals used to form subgraph
if 'tf_variables' not in globals():
global tf_variables
tf_variables = dict()
name_for_optional_inputs = name_prefix + '_optional_inputs'
name_for_funcs = name_prefix + '_funcs'
tf_variables[name_prefix] = dict()
tf_variables[name_prefix]['optional_inputs'] = tf.get_variable(name_for_optional_inputs,
[len(
optional_inputs)],
dtype=tf.bool,
trainable=False)
tf_variables[name_prefix]['funcs'] = tf.get_variable(
name_for_funcs, [], dtype=tf.int64, trainable=False)
# get real values using their variable names
real_optional_inputs_value = [optional_inputs[name]
for name in name_space[name_prefix]['optional_inputs']]
real_func_value = [funcs[name]
for name in name_space[name_prefix]['funcs']]
real_funcs_args = [funcs_args[name]
for name in name_space[name_prefix]['funcs']]
# build tensorflow graph of geting chosen inputs by masking
real_chosen_inputs = tf.boolean_mask(
real_optional_inputs_value, tf_variables[name_prefix]['optional_inputs'])
# build tensorflow graph of different branches by using tf.case
branches = dict()
for func_id in range(len(funcs)):
func_output = real_func_value[func_id](
[fixed_inputs, real_chosen_inputs], **real_funcs_args[func_id])
branches[tf.equal(tf_variables[name_prefix]['funcs'],
func_id)] = lambda: func_output
layer_out = tf.case(branches, exclusive=True,
default=lambda: func_output)
return layer_out
def oneshot_mode(
mutable_id,
mutable_layer_id,
funcs,
funcs_args,
fixed_inputs,
optional_inputs,
optional_input_size,
tf):
'''Similar to enas mode, oneshot mode also builds the full model graph.
The difference is that oneshot mode does not receive subgraph.
Instead, it uses dropout to randomly dropout inputs and ops.'''
# NNI requires to get_next_parameter before report a result. But the parameter will not be used in this mode
if trial._params is None:
trial.get_next_parameter()
optional_inputs = list(optional_inputs.values())
inputs_num = len(optional_inputs)
# Calculate dropout rate according to the formular r^(1/k), where r is a hyper-parameter and k is the number of inputs
if inputs_num > 0:
rate = 0.01 ** (1 / inputs_num)
noise_shape = [inputs_num] + [1] * len(optional_inputs[0].get_shape())
optional_inputs = tf.nn.dropout(
optional_inputs, rate=rate, noise_shape=noise_shape)
optional_inputs = [optional_inputs[idx] for idx in range(inputs_num)]
layer_outs = [func([fixed_inputs, optional_inputs], **funcs_args[func_name])
for func_name, func in funcs.items()]
layer_out = tf.add_n(layer_outs)
return layer_out
def reload_tensorflow_variables(session, tf=None):
'''In Enas mode, this function reload every signal varaible created in `enas_mode` function so
the whole tensorflow graph will be changed into certain subgraph recerived from Tuner.
---------------
session: the tensorflow session created by users
tf: tensorflow module
'''
subgraph_from_tuner = trial.get_next_parameter()
for mutable_id, mutable_block in subgraph_from_tuner.items():
if mutable_id not in name_space:
continue
for mutable_layer_id, mutable_layer in mutable_block.items():
name_prefix = "{}_{}".format(mutable_id, mutable_layer_id)
# extract layer information from the subgraph sampled by tuner
chosen_layer = name_space[name_prefix]['funcs'].index(
mutable_layer["chosen_layer"])
chosen_inputs = [1 if inp in mutable_layer["chosen_inputs"]
else 0 for inp in name_space[name_prefix]['optional_inputs']]
# load these information into pre-defined tensorflow variables
tf_variables[name_prefix]['funcs'].load(chosen_layer, session)
tf_variables[name_prefix]['optional_inputs'].load(
chosen_inputs, session)
......@@ -29,8 +29,9 @@ from scipy.linalg import LinAlgError, cho_solve, cholesky, solve_triangular
from scipy.optimize import linear_sum_assignment
from sklearn.metrics.pairwise import rbf_kernel
from nni.utils import OptimizeMode
from nni.networkmorphism_tuner.graph_transformer import transform
from nni.networkmorphism_tuner.utils import Constant, OptimizeMode
from nni.networkmorphism_tuner.utils import Constant
from nni.networkmorphism_tuner.layers import is_layer
......
......@@ -20,9 +20,11 @@
import random
import numpy as np
from .env_vars import trial_env_vars
from . import trial
from .nas_utils import classic_mode, enas_mode, oneshot_mode
__all__ = [
......@@ -124,7 +126,9 @@ else:
funcs_args,
fixed_inputs,
optional_inputs,
optional_input_size):
optional_input_size,
mode='classic_mode',
tf=None):
'''execute the chosen function and inputs.
Below is an example of chosen function and inputs:
{
......@@ -144,14 +148,38 @@ else:
fixed_inputs:
optional_inputs: dict of optional inputs
optional_input_size: number of candidate inputs to be chosen
tf: tensorflow module
'''
mutable_block = _get_param(mutable_id)
chosen_layer = mutable_block[mutable_layer_id]["chosen_layer"]
chosen_inputs = mutable_block[mutable_layer_id]["chosen_inputs"]
real_chosen_inputs = [optional_inputs[input_name] for input_name in chosen_inputs]
layer_out = funcs[chosen_layer]([fixed_inputs, real_chosen_inputs], **funcs_args[chosen_layer])
return layer_out
if mode == 'classic_mode':
return classic_mode(mutable_id,
mutable_layer_id,
funcs,
funcs_args,
fixed_inputs,
optional_inputs,
optional_input_size)
elif mode == 'enas_mode':
assert tf is not None, 'Internal Error: Tensorflow should not be None in enas_mode'
return enas_mode(mutable_id,
mutable_layer_id,
funcs,
funcs_args,
fixed_inputs,
optional_inputs,
optional_input_size,
tf)
elif mode == 'oneshot_mode':
assert tf is not None, 'Internal Error: Tensorflow should not be None in oneshot_mode'
return oneshot_mode(mutable_id,
mutable_layer_id,
funcs,
funcs_args,
fixed_inputs,
optional_inputs,
optional_input_size,
tf)
else:
raise RuntimeError('Unrecognized mode: %s' % mode)
def _get_param(key):
if trial._params is None:
......
......@@ -51,6 +51,14 @@ class NodeType:
NAME = '_name'
class MetricType:
"""The types of metric data
"""
FINAL = 'FINAL'
PERIODICAL = 'PERIODICAL'
REQUEST_PARAMETER = 'REQUEST_PARAMETER'
def split_index(params):
"""
Delete index infromation from params
......
......@@ -38,7 +38,13 @@ class SmartParamTestCase(TestCase):
'test_smartparam/choice3/choice': '[1, 2]',
'test_smartparam/choice4/choice': '{"a", 2}',
'test_smartparam/func/function_choice': 'bar',
'test_smartparam/lambda_func/function_choice': "lambda: 2*3"
'test_smartparam/lambda_func/function_choice': "lambda: 2*3",
'mutable_block_66':{
'mutable_layer_0':{
'chosen_layer': 'conv2D(size=5)',
'chosen_inputs': ['y']
}
}
}
nni.trial._params = { 'parameter_id': 'test_trial', 'parameters': params }
......@@ -61,6 +67,13 @@ class SmartParamTestCase(TestCase):
val = nni.function_choice({"lambda: 2*3": lambda: 2*3, "lambda: 3*4": lambda: 3*4}, name = 'lambda_func', key='test_smartparam/lambda_func/function_choice')
self.assertEqual(val, 6)
def test_mutable_layer(self):
layer_out = nni.mutable_layer('mutable_block_66',
'mutable_layer_0', {'conv2D(size=3)': conv2D, 'conv2D(size=5)': conv2D}, {'conv2D(size=3)':
{'size':3}, 'conv2D(size=5)': {'size':5}}, [100], {'x':1,'y':2}, 1, 'classic_mode')
self.assertEqual(layer_out, [100, 2, 5])
def foo():
return 'foo'
......@@ -68,6 +81,8 @@ def foo():
def bar():
return 'bar'
def conv2D(inputs, size=3):
return inputs[0] + inputs[1] + [size]
if __name__ == '__main__':
main()
......@@ -32,5 +32,9 @@
"@types/react-responsive": "^3.0.3",
"@types/react-router": "3.0.15",
"typescript": "^3.0.1"
},
"resolutions": {
"mem": "^4.0.0",
"handlebars": "^4.1.0"
}
}
\ No newline at end of file
.nni{
font-family: 'Segoe';
color: #212121;
font-size: 14px;
background: #f2f2f2;
......
......@@ -127,7 +127,7 @@ class Compare extends React.Component<CompareProps, {}> {
<td />
{Object.keys(idList).map(key => {
return (
<td className="value" key={key}>{idList[key]}</td>
<td className="value idList" key={key}>{idList[key]}</td>
);
})}
</tr>
......@@ -193,6 +193,7 @@ class Compare extends React.Component<CompareProps, {}> {
destroyOnClose={true}
maskClosable={false}
width="90%"
// centered={true}
>
<Row>{this.intermediate()}</Row>
<Row>{this.initColumn()}</Row>
......
......@@ -353,8 +353,10 @@ class Overview extends React.Component<OverviewProps, OverviewState> {
const indexarr: Array<number> = [];
Object.keys(sourcePoint).map(item => {
const items = sourcePoint[item];
accarr.push(items.acc.default);
indexarr.push(items.sequenceId);
if (items.acc !== undefined) {
accarr.push(items.acc.default);
indexarr.push(items.sequenceId);
}
});
const accOption = {
// support max show 0.0000000
......
......@@ -4,7 +4,7 @@ import axios from 'axios';
import { MANAGER_IP } from '../static/const';
import MediaQuery from 'react-responsive';
import { DOWNLOAD_IP } from '../static/const';
import { Row, Col, Menu, Dropdown, Icon, Select } from 'antd';
import { Row, Col, Menu, Dropdown, Icon, Select, Button } from 'antd';
const { SubMenu } = Menu;
const { Option } = Select;
import '../static/style/slideBar.scss';
......@@ -14,6 +14,7 @@ interface SliderState {
version: string;
menuVisible: boolean;
navBarVisible: boolean;
isdisabledFresh: boolean;
}
interface SliderProps {
......@@ -29,7 +30,6 @@ class SlideBar extends React.Component<SliderProps, SliderState> {
public _isMounted = false;
public divMenu: HTMLDivElement | null;
public countOfMenu: number = 0;
public selectHTML: Select | null;
constructor(props: SliderProps) {
......@@ -38,6 +38,7 @@ class SlideBar extends React.Component<SliderProps, SliderState> {
version: '',
menuVisible: false,
navBarVisible: false,
isdisabledFresh: false
};
}
......@@ -208,7 +209,6 @@ class SlideBar extends React.Component<SliderProps, SliderState> {
}
menu = () => {
this.countOfMenu = 0;
return (
<Menu onClick={this.handleMenuClick}>
<Menu.Item key="1">Experiment Parameters</Menu.Item>
......@@ -223,12 +223,9 @@ class SlideBar extends React.Component<SliderProps, SliderState> {
const { version } = this.state;
const feedBackLink = `https://github.com/Microsoft/nni/issues/new?labels=${version}`;
return (
<Menu onClick={this.handleMenuClick} mode="inline">
<Menu onClick={this.handleMenuClick} className="menuModal">
<Menu.Item key="overview"><Link to={'/oview'}>Overview</Link></Menu.Item>
<Menu.Item key="detail"><Link to={'/detail'}>Trials detail</Link></Menu.Item>
<Menu.Item key="fresh">
<span className="fresh" onClick={this.fresh}><span>Fresh</span></span>
</Menu.Item>
<Menu.Item key="feedback">
<a href={feedBackLink} target="_blank">Feedback</a>
</Menu.Item>
......@@ -250,38 +247,42 @@ class SlideBar extends React.Component<SliderProps, SliderState> {
);
}
// nav bar <1299
showMenu = () => {
if (this.divMenu !== null) {
this.countOfMenu = this.countOfMenu + 1;
if (this.countOfMenu % 2 === 0) {
this.divMenu.setAttribute('class', 'hide');
} else {
this.divMenu.setAttribute('class', 'show');
}
}
}
select = () => {
const { isdisabledFresh } = this.state;
return (
<Select
onSelect={this.getInterval}
defaultValue="Refresh every 10s"
className="interval"
>
<Option value="close">Disable Auto Refresh</Option>
<Option value="10">Refresh every 10s</Option>
<Option value="20">Refresh every 20s</Option>
<Option value="30">Refresh every 30s</Option>
<Option value="60">Refresh every 1min</Option>
</Select>
<div className="interval">
<Button
className="fresh"
onClick={this.fresh}
type="ghost"
disabled={isdisabledFresh}
>
<Icon type="sync" /><span>Refresh</span>
</Button>
<Select
onSelect={this.getInterval}
defaultValue="Refresh every 10s"
>
<Option value="close">Disable Auto Refresh</Option>
<Option value="10">Refresh every 10s</Option>
<Option value="20">Refresh every 20s</Option>
<Option value="30">Refresh every 30s</Option>
<Option value="60">Refresh every 1min</Option>
</Select>
</div>
);
}
fresh = (event: React.SyntheticEvent<EventTarget>) => {
event.preventDefault();
const whichPage = window.location.pathname;
this.props.changeFresh(whichPage);
event.stopPropagation();
if (this._isMounted) {
this.setState({ isdisabledFresh: true }, () => {
const whichPage = window.location.pathname;
this.props.changeFresh(whichPage);
setTimeout(() => { this.setState(() => ({ isdisabledFresh: false })); }, 1000);
});
}
}
componentDidMount() {
......@@ -298,73 +299,75 @@ class SlideBar extends React.Component<SliderProps, SliderState> {
const feed = `https://github.com/Microsoft/nni/issues/new?labels=${version}`;
return (
<Row>
<MediaQuery query="(min-width: 1299px)">
<Row className="nav">
<ul className="link">
<li className="logo">
<Col span={18}>
<MediaQuery query="(min-width: 1299px)">
<Row className="nav">
<ul className="link">
<li className="logo">
<Link to={'/oview'}>
<img
src={require('../static/img/logo2.png')}
style={{ width: 88 }}
alt="NNI logo"
/>
</Link>
</li>
<li className="tab firstTab">
<Link to={'/oview'} activeClassName="high">
Overview
</Link>
</li>
<li className="tab">
<Link to={'/detail'} activeClassName="high">
Trials detail
</Link>
</li>
<li className="feedback">
<Dropdown
className="dropdown"
overlay={this.menu()}
onVisibleChange={this.handleVisibleChange}
visible={menuVisible}
trigger={['click']}
>
<a className="ant-dropdown-link" href="#">
Download <Icon type="down" />
</a>
</Dropdown>
<a href={feed} target="_blank">
<img
src={require('../static/img/icon/issue.png')}
alt="NNI github issue"
/>
Feedback
</a>
<span className="version">Version: {version}</span>
</li>
</ul>
</Row>
</MediaQuery>
</Col>
<Col span={18}>
<MediaQuery query="(max-width: 1299px)">
<Row className="little">
<Col span={1} className="menu">
<Dropdown overlay={this.navigationBar()} trigger={['click']}>
<Icon type="unordered-list" className="more" />
</Dropdown>
</Col>
<Col span={14} className="logo">
<Link to={'/oview'}>
<img
src={require('../static/img/logo2.png')}
style={{ width: 88 }}
style={{ width: 80 }}
alt="NNI logo"
/>
</Link>
</li>
<li className="tab firstTab">
<Link to={'/oview'} activeClassName="high">
Overview
</Link>
</li>
<li className="tab">
<Link to={'/detail'} activeClassName="high">
Trials detail
</Link>
</li>
<li className="feedback">
<span className="fresh" onClick={this.fresh}>
<Icon type="sync"/><span>Fresh</span>
</span>
<Dropdown
className="dropdown"
overlay={this.menu()}
onVisibleChange={this.handleVisibleChange}
visible={menuVisible}
trigger={['click']}
>
<a className="ant-dropdown-link" href="#">
Download <Icon type="down" />
</a>
</Dropdown>
<a href={feed} target="_blank">
<img
src={require('../static/img/icon/issue.png')}
alt="NNI github issue"
/>
Feedback
</a>
<span className="version">Version: {version}</span>
</li>
</ul>
</Row>
</MediaQuery>
<MediaQuery query="(max-width: 1299px)">
<Row className="little">
<Col span={6} className="menu">
<Icon type="unordered-list" className="more" onClick={this.showMenu} />
<div ref={div => this.divMenu = div} className="hide">{this.navigationBar()}</div>
</Col>
<Col span={10} className="logo">
<Link to={'/oview'}>
<img
src={require('../static/img/logo2.png')}
style={{ width: 88 }}
alt="NNI logo"
/>
</Link>
</Col>
</Row>
</MediaQuery>
{this.select()}
</Col>
</Row>
</MediaQuery>
</Col>
<Col span={3}> {this.select()} </Col>
</Row>
);
}
......
......@@ -394,15 +394,13 @@ class TrialsDetail extends React.Component<TrialsDetailProps, TrialDetailState>
</Col>
<Col span={14} className="right">
<Button
type="primary"
className="tableButton editStyle"
className="common"
onClick={this.tableList ? this.tableList.addColumn : this.test}
>
Add column
</Button>
<Button
type="primary"
className="tableButton editStyle mediateBtn"
className="mediateBtn common"
// use child-component tableList's function, the function is in child-component.
onClick={this.tableList ? this.tableList.compareBtn : this.test}
>
......
......@@ -163,9 +163,9 @@ class Duration extends React.Component<DurationProps, DurationState> {
}
shouldComponentUpdate(nextProps: DurationProps, nextState: DurationState) {
const { whichGraph, source } = nextProps;
if (whichGraph === '3') {
if (whichGraph === '3') {
const beforeSource = this.props.source;
if (whichGraph !== this.props.whichGraph) {
return true;
......@@ -174,13 +174,14 @@ class Duration extends React.Component<DurationProps, DurationState> {
if (source.length !== beforeSource.length) {
return true;
}
if (source[source.length - 1].duration !== beforeSource[beforeSource.length - 1].duration) {
return true;
}
if (source[source.length - 1].status !== beforeSource[beforeSource.length - 1].status) {
return true;
if (beforeSource[beforeSource.length - 1] !== undefined) {
if (source[source.length - 1].duration !== beforeSource[beforeSource.length - 1].duration) {
return true;
}
if (source[source.length - 1].status !== beforeSource[beforeSource.length - 1].status) {
return true;
}
}
}
return false;
......
......@@ -12,7 +12,7 @@ interface IntermediateState {
eachIntermediateNum: number; // trial's intermediate number count
isLoadconfirmBtn: boolean;
isFilter: boolean;
length: number;
length: number;
clickCounts: number; // user filter intermediate click confirm btn's counts
}
......@@ -136,7 +136,7 @@ class Intermediate extends React.Component<IntermediateProps, IntermediateState>
},
yAxis: {
type: 'value',
name: 'Scape'
name: 'metric'
}
};
if (this._isMounted) {
......@@ -209,7 +209,7 @@ class Intermediate extends React.Component<IntermediateProps, IntermediateState>
componentWillReceiveProps(nextProps: IntermediateProps, nextState: IntermediateState) {
const { isFilter, filterSource } = nextState;
const { whichGraph, source } = nextProps;
if (whichGraph === '4') {
if (isFilter === true) {
const pointVal = this.pointInput !== null ? this.pointInput.value : '';
......@@ -226,16 +226,14 @@ class Intermediate extends React.Component<IntermediateProps, IntermediateState>
}
shouldComponentUpdate(nextProps: IntermediateProps, nextState: IntermediateState) {
const { whichGraph } = nextProps;
const { whichGraph, source } = nextProps;
const beforeGraph = this.props.whichGraph;
if (whichGraph === '4') {
const { source } = nextProps;
const { isFilter, length, clickCounts } = nextState;
const beforeLength = this.state.length;
const beforeSource = this.state.detailSource;
const beforeSource = this.props.source;
const beforeClickCounts = this.state.clickCounts;
if (isFilter !== this.state.isFilter) {
return true;
}
......@@ -243,7 +241,7 @@ class Intermediate extends React.Component<IntermediateProps, IntermediateState>
if (clickCounts !== beforeClickCounts) {
return true;
}
if (isFilter === false) {
if (whichGraph !== beforeGraph) {
return true;
......@@ -251,15 +249,20 @@ class Intermediate extends React.Component<IntermediateProps, IntermediateState>
if (length !== beforeLength) {
return true;
}
if (source[source.length - 1].description.intermediate.length !==
beforeSource[beforeSource.length - 1].description.intermediate.length) {
if (beforeSource.length !== source.length) {
return true;
}
if (source[source.length - 1].duration !== beforeSource[beforeSource.length - 1].duration) {
return true;
}
if (source[source.length - 1].status !== beforeSource[beforeSource.length - 1].status) {
return true;
if (beforeSource[beforeSource.length - 1] !== undefined) {
if (source[source.length - 1].description.intermediate.length !==
beforeSource[beforeSource.length - 1].description.intermediate.length) {
return true;
}
if (source[source.length - 1].duration !== beforeSource[beforeSource.length - 1].duration) {
return true;
}
if (source[source.length - 1].status !== beforeSource[beforeSource.length - 1].status) {
return true;
}
}
}
}
......@@ -291,7 +294,7 @@ class Intermediate extends React.Component<IntermediateProps, IntermediateState>
?
<div>
<Col span={3}>
<span>Scape</span>
<span>Step</span>
<input
placeholder="point"
ref={input => this.pointInput = input}
......
......@@ -145,7 +145,8 @@ class Para extends React.Component<ParaProps, ParaState> {
const parallelAxis: Array<Dimobj> = [];
// search space range and specific value [only number]
for (let i = 0; i < dimName.length; i++) {
let i = 0;
for (i; i < dimName.length; i++) {
const searchKey = searchRange[dimName[i]];
switch (searchKey._type) {
case 'uniform':
......@@ -213,6 +214,13 @@ class Para extends React.Component<ParaProps, ParaState> {
}
}
parallelAxis.push({
dim: i,
name: 'default metric',
nameTextStyle: {
fontWeight: 700
}
});
if (lenOfDataSource === 0) {
const optionOfNull = {
parallelAxis,
......@@ -229,8 +237,8 @@ class Para extends React.Component<ParaProps, ParaState> {
const length = value.length;
if (length > 16) {
const temp = value.split('');
for (let i = 16; i < temp.length; i += 17) {
temp[i] += '\n';
for (let m = 16; m < temp.length; m += 17) {
temp[m] += '\n';
}
return temp.join('');
} else {
......
......@@ -49,8 +49,4 @@ table {
border-collapse: collapse;
border-spacing: 0;
}
@font-face {
font-family: 'Segoe';
src: url('./static/font/SegoePro-Regular.ttf');
}
......@@ -97,6 +97,7 @@ interface Dimobj {
axisTick?: object;
axisLabel?: object;
axisLine?: object;
nameTextStyle?: object;
}
interface ParaObj {
......
.compare{
width: 92%;
table-layout: fixed;
margin: 0 auto;
color: #333;
tr{
line-height: 30px;
border-bottom: 1px solid #ccc;
}
tr:nth-of-type(even){
background-color: gainsboro;
}
.column{
width: 124px;
max-width: 124px;
padding-left: 18px;
font-weight: 700;
}
.value{
width: 152px;
max-width: 152px;
padding-right: 18px;
text-align: right;
text-align: left;
}
.idList{
font-weight: 700;
}
}
......@@ -4,6 +4,13 @@
margin: 0 auto;
.right{
text-align: right;
.common{
border-radius: 0;
}
.common:hover{
color: #0071BC;
border-radius: 0;
}
}
.entry{
width: 120px;
......@@ -31,8 +38,9 @@
}
}
/* compare button style */
Button.mediateBtn{
margin: 0 32px;
margin: 0 2px 0 8px;
}
/* each row's Intermediate btn -> Modal*/
......
......@@ -34,18 +34,10 @@ $drowHoverBgColor: #e2e2e2;
.feedback{
position: fixed;
right: 19%;
right: 26%;
line-height: $barHeight;
font-size: 16px;
color: #fff;
.fresh{
span{
margin: 0 10px 0 3px;
}
}
.fresh:hover{
cursor: pointer;
}
a{
color: #fff;
text-decoration: none;
......@@ -60,6 +52,17 @@ $drowHoverBgColor: #e2e2e2;
}
}
/* refresh button */
.fresh{
border: none;
color: #fff;
font-size: 16px;
padding: 0;
}
.fresh:hover{
color: #fff;
}
.link li{
float: left;
}
......@@ -70,8 +73,10 @@ $drowHoverBgColor: #e2e2e2;
}
.interval{
position: fixed;
right: 7%;
right: 6%;
top: 12px;
font-size: 16px;
color: #fff;
.ant-select-selection{
background-color: transparent;
border: none;
......@@ -82,6 +87,10 @@ $drowHoverBgColor: #e2e2e2;
.ant-select-arrow{
color: #fff;
}
.ant-btn-ghost[disabled]{
background-color: transparent;
color: #fff;
}
}
/* set select bgcolor */
.ant-select-dropdown-menu{
......@@ -99,22 +108,30 @@ $drowHoverBgColor: #e2e2e2;
padding: 0;
background-color: $drowBgColor;
border-radius: 0;
.ant-dropdown-menu-item:hover{
.ant-dropdown-menu-item{
font-size: 16px;
}
.ant-dropdown-menu-item:hover, .ant-dropdown-menu-submenu:hover{
background-color: $drowHoverBgColor;
}
}
}
.ant-dropdown-menu-sub{
padding: 0;
background-color: $drowBgColor;
border-radius: 0;
.ant-dropdown-menu-item:hover{
background-color: $drowHoverBgColor;
}
}
/* nav style*/
.little{
width: 100%;
width: 90%;
.menu{
.show{
display: block;
}
.hide{
display: none;
}
margin-left: 33px;
.more{
color: #fff;
font-size: 24px;
......@@ -125,6 +142,10 @@ $drowHoverBgColor: #e2e2e2;
}
}
.logo{
text-align: center;
text-align: right;
}
}
.menuModal{
width: 198px;
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment