Unverified Commit 6ef0c23f authored by 陈帅's avatar 陈帅 Committed by GitHub

fix all eslint-error (#28)

* run eslint fix

* import sorted

* fix some warning

* fix all eslint-error

* fix all eslint-error

* fix all eslint error

* remove .eslintcache
parent 8ae5c0b9
/functions/mock/**
/scripts
/config
**/node_modules/**
_scripts
\ No newline at end of file
const fabric = require('@umijs/fabric');
module.exports = {
parser: 'babel-eslint',
extends: ['airbnb', 'prettier', 'plugin:compat/recommended'],
env: {
browser: true,
node: true,
es6: true,
mocha: true,
jest: true,
jasmine: true,
...fabric.default,
rules: {
...fabric.default.rules,
'@typescript-eslint/camelcase': 0,
'@typescript-eslint/class-name-casing': 0,
},
globals: {
APP_TYPE: true,
ANT_DESIGN_PRO_ONLY_DO_NOT_USE_IN_YOUR_PRODUCTION: true,
page: true,
},
rules: {
'react/jsx-filename-extension': [1, { extensions: ['.js'] }],
'react/jsx-wrap-multilines': 0,
'react/prop-types': 0,
'react/forbid-prop-types': 0,
'react/jsx-one-expression-per-line': 0,
'import/no-unresolved': [2, { ignore: ['^@/', '^umi/'] }],
'import/no-extraneous-dependencies': [
2,
{
optionalDependencies: true,
devDependencies: ['**/tests/**.js', '/mock/**.js', '**/**.test.js'],
},
],
'jsx-a11y/no-noninteractive-element-interactions': 0,
'jsx-a11y/click-events-have-key-events': 0,
'jsx-a11y/no-static-element-interactions': 0,
'jsx-a11y/anchor-is-valid': 0,
'linebreak-style': 0,
},
settings: {
polyfills: ['fetch', 'promises', 'url'],
},
};
......@@ -36,3 +36,5 @@ functions/mock
# screenshot
screenshot
.firebase
.eslintcache
{
"singleQuote": true,
"trailingComma": "all",
"printWidth": 100,
"proseWrap": "never",
"overrides": [
{
"files": ".prettierrc",
"options": {
"parser": "json"
}
}
]
}
\ No newline at end of file
const fabric = require('@umijs/fabric');
module.exports = {
...fabric.prettier,
};
const fabric = require('@umijs/fabric');
module.exports = {
...fabric.stylelint,
};
{
"extends": [
"stylelint-config-standard",
"stylelint-config-css-modules",
"stylelint-config-rational-order",
"stylelint-config-prettier"
],
"plugins": ["stylelint-order", "stylelint-declaration-block-no-ignored-properties"],
"rules": {
"no-descending-specificity": null,
"plugin/declaration-block-no-ignored-properties": true
}
}
......@@ -11,16 +11,21 @@
"url": "https://github.com/umijs/umi-blocks/ant-design-pro/accountcenter"
},
"dependencies": {
"@ant-design/pro-layout": "^4.5.5",
"antd": "^3.16.3",
"classnames": "^2.2.6",
"dva": "^2.4.0",
"moment": "^2.24.0",
"numeral": "^2.0.6",
"react": "^16.6.3",
"react-router": "^5.0.1",
"redux": "^4.0.1",
"umi-request": "^1.0.0"
},
"devDependencies": {
"umi": "^2.6.9",
"umi-plugin-react": "^1.7.2",
"umi-plugin-block-dev": "^1.0.0"
"umi-plugin-block-dev": "^1.0.0",
"umi-plugin-react": "^1.7.2"
},
"license": "ISC",
"blockConfig": {
......
import { ListItemDataType } from './data';
import { ListItemDataType } from './data.d';
const titles = [
'Alipay',
......@@ -21,69 +21,6 @@ const avatars = [
'https://gw.alipayobjects.com/zos/rmsportal/nxkuOJlFJuAUhzlMTCEe.png', // Webpack
];
const getNotice = [
{
id: 'xxx1',
title: titles[0],
logo: avatars[0],
description: '那是一种内在的东西,他们到达不了,也无法触及的',
updatedAt: new Date(),
member: '科学搬砖组',
href: '',
memberLink: '',
},
{
id: 'xxx2',
title: titles[1],
logo: avatars[1],
description: '希望是一个好东西,也许是最好的,好东西是不会消亡的',
updatedAt: new Date('2017-07-24'),
member: '全组都是吴彦祖',
href: '',
memberLink: '',
},
{
id: 'xxx3',
title: titles[2],
logo: avatars[2],
description: '城镇中有那么多的酒馆,她却偏偏走进了我的酒馆',
updatedAt: new Date(),
member: '中二少女团',
href: '',
memberLink: '',
},
{
id: 'xxx4',
title: titles[3],
logo: avatars[3],
description: '那时候我只会想自己想要什么,从不想自己拥有什么',
updatedAt: new Date('2017-07-23'),
member: '程序员日常',
href: '',
memberLink: '',
},
{
id: 'xxx5',
title: titles[4],
logo: avatars[4],
description: '凛冬将至',
updatedAt: new Date('2017-07-23'),
member: '高逼格设计天团',
href: '',
memberLink: '',
},
{
id: 'xxx6',
title: titles[5],
logo: avatars[5],
description: '生命就像一盒巧克力,结果往往出人意料',
updatedAt: new Date('2017-07-23'),
member: '骗你来学计算机',
href: '',
memberLink: '',
},
];
const covers = [
'https://gw.alipayobjects.com/zos/rmsportal/uMfMFlvUuceEyPpotzlq.png',
'https://gw.alipayobjects.com/zos/rmsportal/iZBVOIhGJiAnhplqjvZW.png',
......@@ -119,7 +56,7 @@ function fakeList(count: number): ListItemDataType[] {
owner: user[i % 10],
title: titles[i % 8],
avatar: avatars[i % 8],
cover: parseInt(i / 4 + '', 10) % 2 === 0 ? covers[i % 4] : covers[3 - (i % 4)],
cover: parseInt(`${i / 4}`, 10) % 2 === 0 ? covers[i % 4] : covers[3 - (i % 4)],
status: ['active', 'exception', 'normal'][i % 3] as
| 'normal'
| 'exception'
......
import { Avatar, Card, Dropdown, Icon, List, Menu, Tooltip } from 'antd';
import React, { Component } from 'react';
import { List, Card, Icon, Dropdown, Menu, Avatar, Tooltip } from 'antd';
import numeral from 'numeral';
import { connect } from 'dva';
import stylesApplications from './index.less';
import numeral from 'numeral';
import { ModalState } from '../../model';
import stylesApplications from './index.less';
export function formatWan(val: number) {
const v = val * 1;
......
import { Avatar } from 'antd';
import React from 'react';
import moment from 'moment';
import { Avatar } from 'antd';
import styles from './index.less';
export interface ApplicationsProps {
......
import { Icon, List, Tag } from 'antd';
import React, { Component } from 'react';
import { List, Icon, Tag } from 'antd';
import { connect } from 'dva';
import ArticleListContent from '../ArticleListContent';
import styles from './index.less';
import { ListItemDataType } from '../../data.d';
import { ModalState } from '../../model';
import { ListItemDataType } from '../../data';
import styles from './index.less';
@connect(({ BLOCK_NAME_CAMEL_CASE }: { BLOCK_NAME_CAMEL_CASE: ModalState }) => ({
list: BLOCK_NAME_CAMEL_CASE.list,
......
import { Avatar, Tooltip } from 'antd';
import React from 'react';
import { Tooltip, Avatar } from 'antd';
import classNames from 'classnames';
import styles from './index.less';
......@@ -19,10 +20,10 @@ export interface AvatarListProps {
maxLength?: number;
excessItemsStyle?: React.CSSProperties;
style?: React.CSSProperties;
children: React.ReactElement<AvatarItemProps> | Array<React.ReactElement<AvatarItemProps>>;
children: React.ReactElement<AvatarItemProps> | React.ReactElement<AvatarItemProps>[];
}
const avatarSizeToClassName = (size?: SizeType) =>
const avatarSizeToClassName = (size?: SizeType | 'mini') =>
classNames(styles.avatarItem, {
[styles.avatarItemLarge]: size === 'large',
[styles.avatarItemSmall]: size === 'small',
......@@ -54,9 +55,7 @@ const AvatarList: React.SFC<AvatarListProps> & { Item: typeof Item } = ({
}) => {
const numOfChildren = React.Children.count(children);
const numToShow = maxLength >= numOfChildren ? numOfChildren : maxLength;
const childrenArray = React.Children.toArray(children) as Array<
React.ReactElement<AvatarItemProps>
>;
const childrenArray = React.Children.toArray(children) as React.ReactElement<AvatarItemProps>[];
const childrenWithProps = childrenArray.slice(0, numToShow).map(child =>
React.cloneElement(child, {
size,
......
import { Card, List } from 'antd';
import React, { Component } from 'react';
import { List, Card } from 'antd';
import moment from 'moment';
import { connect } from 'dva';
import moment from 'moment';
import AvatarList from '../AvatarList';
import styles from './index.less';
import { ListItemDataType } from '../../data.d';
import { ModalState } from '../../model';
import { ListItemDataType } from '../../data';
import styles from './index.less';
@connect(({ BLOCK_NAME_CAMEL_CASE }: { BLOCK_NAME_CAMEL_CASE: ModalState }) => ({
list: BLOCK_NAME_CAMEL_CASE.list,
......
export interface ITag {
export interface TagType {
key: string;
label: string;
}
export interface IProvince {
export interface ProvinceType {
label: string;
key: string;
}
export interface ICity {
export interface CityType {
label: string;
key: string;
}
export interface IGeographic {
province: IProvince;
city: ICity;
export interface GeographicType {
province: ProvinceType;
city: CityType;
}
export interface INotice {
export interface NoticeType {
id: string;
title: string;
logo: string;
......@@ -33,16 +33,16 @@ export interface CurrentUser {
name: string;
avatar: string;
userid: string;
notice: INotice[];
notice: NoticeType[];
email: string;
signature: string;
title: string;
group: string;
tags: ITag[];
tags: TagType[];
notifyCount: number;
unreadCount: number;
country: string;
geographic: IGeographic;
geographic: GeographicType;
address: string;
phone: string;
}
......
import { Avatar, Card, Col, Divider, Icon, Input, Row, Tag } from 'antd';
import React, { PureComponent } from 'react';
import { connect } from 'dva';
import { Dispatch } from 'redux';
import Link from 'umi/link';
import { GridContent } from '@ant-design/pro-layout';
import Link from 'umi/link';
import { RouteChildrenProps } from 'react-router';
import { Card, Row, Col, Icon, Avatar, Tag, Divider, Input } from 'antd';
import styles from './Center.less';
import { ITag, CurrentUser } from './data';
import { connect } from 'dva';
import { ModalState } from './model';
import Projects from './components/Projects';
import Articles from './components/Articles';
import Applications from './components/Applications';
import Projects from './components/Projects';
import { CurrentUser, TagType } from './data.d';
import styles from './Center.less';
const operationTabList = [
{
......@@ -45,7 +46,7 @@ interface BLOCK_NAME_CAMEL_CASEProps extends RouteChildrenProps {
currentUserLoading: boolean;
}
interface BLOCK_NAME_CAMEL_CASEState {
newTags: ITag[];
newTags: TagType[];
tabKey: 'articles' | 'applications' | 'projects';
inputVisible: boolean;
inputValue: string;
......@@ -56,7 +57,7 @@ interface BLOCK_NAME_CAMEL_CASEState {
loading,
BLOCK_NAME_CAMEL_CASE,
}: {
loading: { effects: any };
loading: { effects: { [key: string]: boolean } };
BLOCK_NAME_CAMEL_CASE: ModalState;
}) => ({
currentUser: BLOCK_NAME_CAMEL_CASE.currentUser,
......@@ -92,7 +93,7 @@ class PAGE_NAME_UPPER_CAMEL_CASE extends PureComponent<
tabKey: 'articles',
};
input: Input | null | undefined;
public input: Input | null | undefined = undefined;
componentDidMount() {
const { dispatch } = this.props;
......@@ -138,6 +139,7 @@ class PAGE_NAME_UPPER_CAMEL_CASE extends PureComponent<
inputValue: '',
});
};
renderChildrenByTabKey = (tabKey: BLOCK_NAME_CAMEL_CASEState['tabKey']) => {
if (tabKey === 'projects') {
return <Projects />;
......@@ -150,6 +152,7 @@ class PAGE_NAME_UPPER_CAMEL_CASE extends PureComponent<
}
return null;
};
render() {
const { newTags, inputVisible, inputValue, tabKey } = this.state;
const { currentUser, currentUserLoading } = this.props;
......@@ -184,9 +187,9 @@ class PAGE_NAME_UPPER_CAMEL_CASE extends PureComponent<
<Divider dashed />
<div className={styles.tags}>
<div className={styles.tagsTitle}>标签</div>
{currentUser.tags.concat(newTags).map(item => {
return <Tag key={item.key}>{item.label}</Tag>;
})}
{currentUser.tags.concat(newTags).map(item => (
<Tag key={item.key}>{item.label}</Tag>
))}
{inputVisible && (
<Input
ref={ref => this.saveInputRef(ref)}
......
import { AnyAction, Reducer } from 'redux';
import { EffectsCommandMap } from 'dva';
import { CurrentUser, ListItemDataType } from './data.d';
import { queryCurrent, queryFakeList } from './service';
import { CurrentUser, ListItemDataType } from './data';
export interface ModalState {
currentUser: Partial<CurrentUser>;
list: ListItemDataType[];
}
import { Reducer } from 'redux';
import { EffectsCommandMap } from 'dva';
import { AnyAction } from 'redux';
export type Effect = (
action: AnyAction,
effects: EffectsCommandMap & { select: <T>(func: (state: ModalState) => T) => T },
......@@ -56,13 +54,13 @@ const Model: ModelType = {
reducers: {
saveCurrentUser(state, action) {
return {
...state!,
...(state as ModalState),
currentUser: action.payload || {},
};
},
queryList(state, action) {
return {
...state!,
...(state as ModalState),
list: action.payload,
};
},
......
......@@ -5,7 +5,7 @@ export async function queryCurrent() {
}
export async function queryFakeList(params: { count: number }) {
return request(`/api/fake_list`, {
return request('/api/fake_list', {
params,
});
}
......@@ -12,15 +12,18 @@
"dev": "umi dev"
},
"dependencies": {
"@ant-design/pro-layout": "^4.5.5",
"antd": "^3.16.3",
"dva": "^2.4.0",
"react": "^16.6.3",
"umi-request": "^1.0.0"
"redux": "^4.0.1",
"umi-request": "^1.0.0",
"umi-plugin-react": "^1.8.4",
"umi": "^2.6.9"
},
"devDependencies": {
"umi": "^2.6.9",
"umi-plugin-block-dev": "^1.0.0",
"umi-plugin-react": "^1.3.0-beta.1"
"umi-plugin-block-dev": "^1.0.0"
},
"blockConfig": {
"specVersion": "0.1"
......
import React, { Component } from 'react';
import { Select, Spin } from 'antd';
import { Dispatch } from 'redux';
import { connect } from 'dva';
import { CityType, ProvinceType } from '../data.d';
import styles from './GeographicView.less';
import { Dispatch } from 'redux';
import { ProvinceData, CityData } from '../data';
const { Option } = Select;
interface SelectItem {
label: string;
key: string;
}
const nullSlectItem: SelectItem = {
const nullSelectItem: SelectItem = {
label: '',
key: '',
};
interface GeographicViewProps {
dispatch?: Dispatch<any>;
province?: ProvinceData[];
city?: CityData[];
province?: ProvinceType[];
city?: CityType[];
value?: {
province: SelectItem;
city: SelectItem;
......@@ -33,8 +35,8 @@ interface GeographicViewProps {
loading,
}: {
BLOCK_NAME_CAMEL_CASE: {
province: ProvinceData[];
city: CityData[];
province: ProvinceType[];
city: CityType[];
};
loading: any;
}) => {
......@@ -85,7 +87,7 @@ class GeographicView extends Component<GeographicViewProps> {
return [];
};
getOption = (list: CityData[] | ProvinceData[]) => {
getOption = (list: CityType[] | ProvinceType[]) => {
if (!list || list.length < 1) {
return (
<Option key={0} value={0}>
......@@ -93,9 +95,9 @@ class GeographicView extends Component<GeographicViewProps> {
</Option>
);
}
return (list as CityData[]).map(item => (
<Option key={item.id} value={item.id}>
{item.name}
return (list as CityType[]).map(item => (
<Option key={item.key} value={item.key}>
{item.label}
</Option>
));
};
......@@ -112,7 +114,7 @@ class GeographicView extends Component<GeographicViewProps> {
if (onChange) {
onChange({
province: item,
city: nullSlectItem,
city: nullSelectItem,
});
}
};
......@@ -131,14 +133,14 @@ class GeographicView extends Component<GeographicViewProps> {
const { value } = this.props;
if (!value) {
return {
province: nullSlectItem,
city: nullSlectItem,
province: nullSelectItem,
city: nullSelectItem,
};
}
const { province, city } = value;
return {
province: province || nullSlectItem,
city: city || nullSlectItem,
province: province || nullSelectItem,
city: city || nullSelectItem,
};
}
......
import React, { Fragment, PureComponent } from 'react';
import { Input } from 'antd';
import styles from './PhoneView.less';
......@@ -20,15 +21,17 @@ class PhoneView extends PureComponent<PhoneViewProps> {
className={styles.area_code}
value={values[0]}
onChange={e => {
// tslint:disable-next-line: no-unused-expression
onChange && onChange(`${e.target.value}-${values[1]}`);
if (onChange) {
onChange(`${e.target.value}-${values[1]}`);
}
}}
/>
<Input
className={styles.phone_number}
onChange={e => {
// tslint:disable-next-line: no-unused-expression
onChange && onChange(`${values[0]}-${e.target.value}`);
if (onChange) {
onChange(`${values[0]}-${e.target.value}`);
}
}}
value={values[1]}
/>
......
import { Button, Form, Input, Select, Upload, message } from 'antd';
import { FormattedMessage, formatMessage } from 'umi-plugin-react/locale';
import React, { Component, Fragment } from 'react';
import { formatMessage, FormattedMessage } from 'umi-plugin-react/locale';
import { Form, Input, Upload, Select, Button, message } from 'antd';
import { FormComponentProps } from 'antd/es/form';
import { connect } from 'dva';
import styles from './BaseView.less';
import { CurrentUser } from '../data.d';
import GeographicView from './GeographicView';
import PhoneView from './PhoneView';
import { CurrentUser } from '../data';
import styles from './BaseView.less';
const FormItem = Form.Item;
const { Option } = Select;
......@@ -70,7 +72,8 @@ interface BaseViewProps extends FormComponentProps {
currentUser: BLOCK_NAME_CAMEL_CASE.currentUser,
}))
class BaseView extends Component<BaseViewProps> {
view: HTMLDivElement | undefined;
view: HTMLDivElement | undefined = undefined;
componentDidMount() {
this.setBaseInfo();
}
......@@ -102,10 +105,10 @@ class BaseView extends Component<BaseViewProps> {
this.view = ref;
};
handlerSubmit = (event: Event) => {
handlerSubmit = (event: React.MouseEvent) => {
event.preventDefault();
const { form } = this.props;
form.validateFields((err, values) => {
form.validateFields(err => {
if (!err) {
message.success(formatMessage({ id: 'BLOCK_NAME.basic.update.success' }));
}
......
import React, { Component, Fragment } from 'react';
import { formatMessage, FormattedMessage } from 'umi-plugin-react/locale';
import { FormattedMessage, formatMessage } from 'umi-plugin-react/locale';
import { Icon, List } from 'antd';
import React, { Component, Fragment } from 'react';
class BindingView extends Component {
getData = () => [
......
import { List, Switch } from 'antd';
import React, { Component, Fragment } from 'react';
import { formatMessage } from 'umi-plugin-react/locale';
import { Switch, List } from 'antd';
type Unpacked<T> = T extends (infer U)[] ? U : T;
......
import { FormattedMessage, formatMessage } from 'umi-plugin-react/locale';
import React, { Component, Fragment } from 'react';
import { formatMessage, FormattedMessage } from 'umi-plugin-react/locale';
import { List } from 'antd';
type Unpacked<T> = T extends (infer U)[] ? U : T;
......
export interface ITag {
export interface TagType {
key: string;
label: string;
}
export interface IProvince {
export interface ProvinceType {
label: string;
key: string;
}
export interface ICity {
export interface CityType {
label: string;
key: string;
}
export interface IGeographic {
province: IProvince;
city: ICity;
export interface GeographicType {
province: ProvinceType;
city: CityType;
}
export interface INotice {
export interface NoticeType {
id: string;
title: string;
logo: string;
......@@ -33,16 +33,16 @@ export interface CurrentUser {
name: string;
avatar: string;
userid: string;
notice: INotice[];
notice: NoticeType[];
email: string;
signature: string;
title: string;
group: string;
tags: ITag[];
tags: TagType[];
notifyCount: number;
unreadCount: number;
country: string;
geographic: IGeographic;
geographic: GeographicType;
address: string;
phone: string;
}
import React, { Component } from 'react';
import { connect } from 'dva';
import { Dispatch } from 'redux';
import { FormattedMessage } from 'umi-plugin-react/locale';
import { GridContent } from '@ant-design/pro-layout';
import { Menu } from 'antd';
import styles from './style.less';
import { connect } from 'dva';
import BaseView from './components/base';
import SecurityView from './components/security';
import BindingView from './components/binding';
import { CurrentUser } from './data.d';
import NotificationView from './components/notification';
import { CurrentUser } from './data';
import SecurityView from './components/security';
import styles from './style.less';
const { Item } = Menu;
......@@ -33,7 +34,8 @@ class PAGE_NAME_UPPER_CAMEL_CASE extends Component<
PAGE_NAME_UPPER_CAMEL_CASEProps,
PAGE_NAME_UPPER_CAMEL_CASEState
> {
main: HTMLDivElement | undefined;
main: HTMLDivElement | undefined = undefined;
constructor(props: PAGE_NAME_UPPER_CAMEL_CASEProps) {
super(props);
const menuMap = {
......
import { query as queryUsers, queryCurrent, queryProvince, queryCity } from './service';
import { Reducer } from 'redux';
import { AnyAction, Reducer } from 'redux';
import { EffectsCommandMap } from 'dva';
import { AnyAction } from 'redux';
import { CurrentUser, City, Province } from './data';
import { CityType, CurrentUser, ProvinceType } from './data.d';
import { queryCity, queryCurrent, queryProvince, query as queryUsers } from './service';
export interface ModalState {
currentUser?: Partial<CurrentUser>;
province?: Province[];
city?: City[];
province?: ProvinceType[];
city?: CityType[];
isLoading?: boolean;
}
......
......@@ -12,22 +12,27 @@
"dev": "umi dev"
},
"dependencies": {
"@ant-design/pro-layout": "^4.5.5",
"@antv/data-set": "^0.10.2",
"antd": "^3.16.3",
"bizcharts": "^3.5.3-beta.0",
"bizcharts-plugin-slider": "^2.1.1-beta.1",
"classnames": "^2.2.6",
"dva": "^2.4.0",
"@types/lodash.debounce": "^4.0.6",
"lodash.debounce": "^4.0.8",
"moment": "^2.22.2",
"numeral": "^2.0.6",
"react": "^16.6.3",
"react-fittext": "^1.0.0",
"redux": "^4.0.1",
"umi-plugin-react": "^1.7.2",
"umi-request": "^1.0.0"
},
"devDependencies": {
"@types/numeral": "^0.0.25",
"umi": "^2.6.9",
"umi-plugin-block-dev": "^1.1.0",
"umi-plugin-react": "^1.7.2",
"@types/numeral": "^0.0.25"
"umi-plugin-block-dev": "^1.1.0"
},
"blockConfig": {
"specVersion": "0.1"
......
import moment from 'moment';
import { IVisitData, IRadarData, IAnalysisData } from './data';
import { AnalysisData, RadarData, VisitDataType } from './data.d';
// mock data
const visitData: IVisitData[] = [];
const visitData: VisitDataType[] = [];
const beginDay = new Date().getTime();
const fakeY = [7, 5, 4, 2, 4, 7, 5, 6, 5, 9, 6, 3, 1, 5, 3, 6, 5];
......@@ -159,7 +159,7 @@ const radarOriginData = [
},
];
const radarData: IRadarData[] = [];
const radarData: RadarData[] = [];
const radarTitleMap = {
ref: '引用',
koubei: '口碑',
......@@ -179,7 +179,7 @@ radarOriginData.forEach(item => {
});
});
const getFakeChartData: IAnalysisData = {
const getFakeChartData: AnalysisData = {
visitData,
visitData2,
salesData,
......
import { Axis, Chart, Geom, Tooltip } from 'bizcharts';
import React, { Component } from 'react';
import { Chart, Axis, Tooltip, Geom } from 'bizcharts';
import Debounce from 'lodash-decorators/debounce';
import Bind from 'lodash-decorators/bind';
import Debounce from 'lodash.debounce';
import autoHeight from '../autoHeight';
import styles from '../index.less';
export interface IBarProps {
export interface BarProps {
title: React.ReactNode;
color?: string;
padding?: [number, number, number, number];
height?: number;
data: Array<{
data: {
x: string;
y: number;
}>;
}[];
forceFit?: boolean;
autoLabel?: boolean;
style?: React.CSSProperties;
}
class Bar extends Component<
IBarProps,
BarProps,
{
autoHideXLabels: boolean;
}
......@@ -28,26 +28,12 @@ class Bar extends Component<
state = {
autoHideXLabels: false,
};
root: HTMLDivElement | undefined;
node: HTMLDivElement | undefined;
componentDidMount() {
window.addEventListener('resize', this.resize, { passive: true });
}
root: HTMLDivElement | undefined = undefined;
componentWillUnmount() {
window.removeEventListener('resize', this.resize);
}
handleRoot = (n: HTMLDivElement) => {
this.root = n;
};
handleRef = (n: HTMLDivElement) => {
this.node = n;
};
node: HTMLDivElement | undefined = undefined;
@Bind()
@Debounce(400)
resize() {
resize = Debounce(() => {
if (!this.node || !this.node.parentNode) {
return;
}
......@@ -70,8 +56,24 @@ class Bar extends Component<
autoHideXLabels: false,
});
}
}, 500);
componentDidMount() {
window.addEventListener('resize', this.resize, { passive: true });
}
componentWillUnmount() {
window.removeEventListener('resize', this.resize);
}
handleRoot = (n: HTMLDivElement) => {
this.root = n;
};
handleRef = (n: HTMLDivElement) => {
this.node = n;
};
render() {
const {
height = 1,
......@@ -115,8 +117,8 @@ class Bar extends Component<
<Axis
name="x"
title={false}
label={autoHideXLabels ? false : {}}
tickLine={autoHideXLabels ? false : {}}
label={autoHideXLabels ? undefined : {}}
tickLine={autoHideXLabels ? undefined : {}}
/>
<Axis name="y" min={0} />
<Tooltip showTitle={false} crosshairs={false} />
......
import React from 'react';
import { Card } from 'antd';
import classNames from 'classnames';
import { CardProps } from 'antd/es/card';
import React from 'react';
import classNames from 'classnames';
import styles from './index.less';
type totalType = () => React.ReactNode;
const renderTotal = (total?: number | totalType | React.ReactNode) => {
if (!total) {
return;
return null;
}
let totalDom;
switch (typeof total) {
......@@ -25,7 +24,7 @@ const renderTotal = (total?: number | totalType | React.ReactNode) => {
return totalDom;
};
export interface IChartCardProps extends CardProps {
export interface ChartCardProps extends CardProps {
title: React.ReactNode;
action?: React.ReactNode;
total?: React.ReactNode | number | (() => React.ReactNode | number);
......@@ -35,7 +34,7 @@ export interface IChartCardProps extends CardProps {
style?: React.CSSProperties;
}
class ChartCard extends React.Component<IChartCardProps> {
class ChartCard extends React.Component<ChartCardProps> {
renderContent = () => {
const { contentHeight, title, avatar, action, total, footer, children, loading } = this.props;
if (loading) {
......
import React from 'react';
import styles from './index.less';
export interface IFieldProps {
export interface FieldProps {
label: React.ReactNode;
value: React.ReactNode;
style?: React.CSSProperties;
}
const Field: React.SFC<IFieldProps> = ({ label, value, ...rest }) => (
const Field: React.SFC<FieldProps> = ({ label, value, ...rest }) => (
<div className={styles.field} {...rest}>
<span className={styles.label}>{label}</span>
<span className={styles.number}>{value}</span>
......
import { Axis, Chart, Coord, Geom, Guide, Shape } from 'bizcharts';
import React from 'react';
import { Chart, Geom, Axis, Coord, Guide, Shape } from 'bizcharts';
import autoHeight from '../autoHeight';
const { Arc, Html, Line } = Guide;
export interface IGaugeProps {
export interface GaugeProps {
title: React.ReactNode;
color?: string;
height?: number;
......@@ -30,7 +31,8 @@ const defaultFormatter = (val: string): string => {
}
};
Shape.registerShape!('point', 'pointer', {
if (Shape.registerShape) {
Shape.registerShape('point', 'pointer', {
drawShape(cfg: any, group: any) {
let point = cfg.points[0];
point = (this as any).parsePoint(point);
......@@ -60,10 +62,10 @@ Shape.registerShape!('point', 'pointer', {
},
});
},
});
});
}
class Gauge extends React.Component<IGaugeProps> {
render() {
const Gauge: React.FC<GaugeProps> = props => {
const {
title,
height = 1,
......@@ -72,7 +74,7 @@ class Gauge extends React.Component<IGaugeProps> {
formatter = defaultFormatter,
color = '#2F9CFF',
bgColor = '#F0F2F5',
} = this.props;
} = props;
const cols = {
value: {
type: 'linear',
......@@ -82,6 +84,7 @@ class Gauge extends React.Component<IGaugeProps> {
nice: true,
},
};
const data = [{ value: percent / 10 }];
const renderHtml = () => `
<div style="width: 300px;text-align: center;font-size: 12px!important;">
<p style="font-size: 14px; color: rgba(0,0,0,0.43);margin: 0;">${title}</p>
......@@ -89,7 +92,6 @@ class Gauge extends React.Component<IGaugeProps> {
${(data[0].value * 10).toFixed(2)}%
</p>
</div>`;
const data = [{ value: percent / 10 }];
const textStyle: {
fontSize: number;
fill: string;
......@@ -99,6 +101,7 @@ class Gauge extends React.Component<IGaugeProps> {
fill: 'rgba(0, 0, 0, 0.65)',
textAlign: 'center',
};
return (
<Chart height={height} data={data} scale={cols} padding={[-16, 0, 16, 0]} forceFit={forceFit}>
<Coord type="polar" startAngle={-1.25 * Math.PI} endAngle={0.25 * Math.PI} radius={0.8} />
......@@ -112,7 +115,7 @@ class Gauge extends React.Component<IGaugeProps> {
label={{
offset: -12,
formatter,
textStyle: textStyle,
textStyle,
}}
/>
<Guide>
......@@ -171,7 +174,6 @@ class Gauge extends React.Component<IGaugeProps> {
/>
</Chart>
);
}
}
};
export default autoHeight()(Gauge);
import { Axis, Chart, Geom, Tooltip, AxisProps } from 'bizcharts';
import React from 'react';
import { Chart, Axis, Tooltip, Geom } from 'bizcharts';
import autoHeight from '../autoHeight';
import styles from '../index.less';
export interface IAxis {
title: any;
line: any;
gridAlign: any;
labels: any;
tickLine: any;
grid: any;
}
export interface IMiniAreaProps {
export interface MiniAreaProps {
color?: string;
height?: number;
borderColor?: string;
line?: boolean;
animate?: boolean;
xAxis?: IAxis;
xAxis?: AxisProps;
forceFit?: boolean;
scale?: { x: any; y: any };
yAxis?: IAxis;
scale?: {
x?: {
tickCount: number;
};
y?: {
tickCount: number;
};
};
yAxis?: Partial<AxisProps>;
borderWidth?: number;
data: Array<{
data: {
x: number | string;
y: number;
}>;
}[];
}
class MiniArea extends React.Component<IMiniAreaProps> {
render() {
const MiniArea: React.FC<MiniAreaProps> = props => {
const {
height = 1,
data = [],
......@@ -43,7 +41,7 @@ class MiniArea extends React.Component<IMiniAreaProps> {
xAxis,
yAxis,
animate = true,
} = this.props;
} = props;
const padding: [number, number, number, number] = [36, 5, 30, 5];
......@@ -51,11 +49,11 @@ class MiniArea extends React.Component<IMiniAreaProps> {
x: {
type: 'cat',
range: [0, 1],
...scale!.x,
...scale.x,
},
y: {
min: 0,
...scale!.y,
...scale.y,
},
};
......@@ -84,19 +82,19 @@ class MiniArea extends React.Component<IMiniAreaProps> {
<Axis
key="axis-x"
name="x"
label={false}
line={false}
tickLine={false}
grid={false}
label={undefined}
line={undefined}
tickLine={undefined}
grid={undefined}
{...xAxis}
/>
<Axis
key="axis-y"
name="y"
label={false}
line={false}
tickLine={false}
grid={false}
label={undefined}
line={undefined}
tickLine={undefined}
grid={undefined}
{...yAxis}
/>
<Tooltip showTitle={false} crosshairs={false} />
......@@ -127,7 +125,6 @@ class MiniArea extends React.Component<IMiniAreaProps> {
</div>
</div>
);
}
}
};
export default autoHeight()(MiniArea);
import { Chart, Geom, Tooltip } from 'bizcharts';
import React from 'react';
import { Chart, Tooltip, Geom } from 'bizcharts';
import autoHeight from '../autoHeight';
import styles from '../index.less';
export interface IMiniBarProps {
export interface MiniBarProps {
color?: string;
height?: number;
data: Array<{
data: {
x: number | string;
y: number;
}>;
}[];
forceFit?: boolean;
style?: React.CSSProperties;
}
class MiniBar extends React.Component<IMiniBarProps> {
render() {
const { height = 0, forceFit = true, color = '#1890FF', data = [] } = this.props;
const MiniBar: React.FC<MiniBarProps> = props => {
const { height = 0, forceFit = true, color = '#1890FF', data = [] } = props;
const scale = {
x: {
......@@ -43,19 +43,12 @@ class MiniBar extends React.Component<IMiniBarProps> {
return (
<div className={styles.miniChart} style={{ height }}>
<div className={styles.chartContent}>
<Chart
scale={scale}
height={chartHeight}
forceFit={forceFit}
data={data}
padding={padding}
>
<Chart scale={scale} height={chartHeight} forceFit={forceFit} data={data} padding={padding}>
<Tooltip showTitle={false} crosshairs={false} />
<Geom type="interval" position="x*y" color={color} tooltip={tooltip} />
</Chart>
</div>
</div>
);
}
}
};
export default autoHeight()(MiniBar);
......@@ -2,7 +2,7 @@ import React from 'react';
import { Tooltip } from 'antd';
import styles from './index.less';
export interface IMiniProgressProps {
export interface MiniProgressProps {
target: number;
targetLabel?: string;
color?: string;
......@@ -11,14 +11,13 @@ export interface IMiniProgressProps {
style?: React.CSSProperties;
}
const MiniProgress: React.SFC<IMiniProgressProps> = ({
const MiniProgress: React.SFC<MiniProgressProps> = ({
targetLabel,
target,
color = 'rgb(19, 194, 194)',
strokeWidth,
percent,
}) => {
return (
}) => (
<div className={styles.miniProgress}>
<Tooltip title={targetLabel}>
<div className={styles.target} style={{ left: target ? `${target}%` : undefined }}>
......@@ -37,7 +36,6 @@ const MiniProgress: React.SFC<IMiniProgressProps> = ({
/>
</div>
</div>
);
};
);
export default MiniProgress;
import { Chart, Coord, Geom, Tooltip } from 'bizcharts';
import React, { Component } from 'react';
import { Chart, Tooltip, Geom, Coord } from 'bizcharts';
import { DataView } from '@antv/data-set';
import Debounce from 'lodash.debounce';
import { Divider } from 'antd';
import classNames from 'classnames';
import ReactFitText from 'react-fittext';
import Debounce from 'lodash-decorators/debounce';
import Bind from 'lodash-decorators/bind';
import classNames from 'classnames';
import autoHeight from '../autoHeight';
import styles from './index.less';
export interface IPieProps {
export interface PieProps {
animate?: boolean;
color?: string;
colors?: string[];
......@@ -19,10 +19,10 @@ export interface IPieProps {
hasLegend?: boolean;
padding?: [number, number, number, number];
percent?: number;
data?: Array<{
data?: {
x: string | string;
y: number;
}>;
}[];
inner?: number;
lineWidth?: number;
forceFit?: boolean;
......@@ -34,19 +34,46 @@ export interface IPieProps {
valueFormat?: (value: string) => string | React.ReactNode;
subTitle?: React.ReactNode;
}
interface IPieState {
legendData: Array<{ checked: boolean; x: string; color: string; percent: number; y: string }>;
interface PieState {
legendData: { checked: boolean; x: string; color: string; percent: number; y: string }[];
legendBlock: boolean;
}
class Pie extends Component<IPieProps, IPieState> {
state: IPieState = {
class Pie extends Component<PieProps, PieState> {
state: PieState = {
legendData: [],
legendBlock: false,
};
requestRef: number | undefined;
root!: HTMLDivElement;
chart: G2.Chart | undefined;
requestRef: number | undefined = undefined;
root: HTMLDivElement | undefined = undefined;
chart: G2.Chart | undefined = undefined;
// for window resize auto responsive legend
resize = Debounce(() => {
const { hasLegend } = this.props;
const { legendBlock } = this.state;
if (!hasLegend || !this.root) {
window.removeEventListener('resize', this.resize);
return;
}
if (
this.root &&
this.root.parentNode &&
(this.root.parentNode as HTMLElement).clientWidth <= 380
) {
if (!legendBlock) {
this.setState({
legendBlock: true,
});
}
} else if (legendBlock) {
this.setState({
legendBlock: false,
});
}
}, 400);
componentDidMount() {
window.addEventListener(
......@@ -58,7 +85,7 @@ class Pie extends Component<IPieProps, IPieState> {
);
}
componentDidUpdate(preProps: IPieProps) {
componentDidUpdate(preProps: PieProps) {
const { data } = this.props;
if (data !== preProps.data) {
// because of charts data create when rendered
......@@ -90,7 +117,7 @@ class Pie extends Component<IPieProps, IPieState> {
if (!this.chart) return;
const geom = this.chart.getAllGeoms()[0]; // 获取所有的图形
if (!geom) return;
const items = geom.get('dataArray') || []; // 获取图形对应的
const items = (geom as any).get('dataArray') || []; // 获取图形对应的
const legendData = items.map((item: { color: any; _origin: any }[]) => {
/* eslint no-underscore-dangle:0 */
......@@ -104,6 +131,7 @@ class Pie extends Component<IPieProps, IPieState> {
legendData,
});
};
handleRoot = (n: HTMLDivElement) => {
this.root = n;
};
......@@ -118,7 +146,7 @@ class Pie extends Component<IPieProps, IPieState> {
const filteredLegendData = legendData.filter(l => l.checked).map(l => l.x);
if (this.chart) {
this.chart.filter('x', val => filteredLegendData.indexOf(val + '') > -1);
this.chart.filter('x', val => filteredLegendData.indexOf(`${val}`) > -1);
}
this.setState({
......@@ -126,33 +154,6 @@ class Pie extends Component<IPieProps, IPieState> {
});
};
// for window resize auto responsive legend
@Bind()
@Debounce(300)
resize() {
const { hasLegend } = this.props;
const { legendBlock } = this.state;
if (!hasLegend || !this.root) {
window.removeEventListener('resize', this.resize);
return;
}
if (
this.root &&
this.root.parentNode &&
(this.root.parentNode as HTMLElement).clientWidth <= 380
) {
if (!legendBlock) {
this.setState({
legendBlock: true,
});
}
} else if (legendBlock) {
this.setState({
legendBlock: false,
});
}
}
render() {
const {
valueFormat,
......@@ -216,11 +217,11 @@ class Pie extends Component<IPieProps, IPieState> {
data = [
{
x: '占比',
y: parseFloat(percent + ''),
y: parseFloat(`${percent}`),
},
{
x: '反比',
y: 100 - parseFloat(percent + ''),
y: 100 - parseFloat(`${percent}`),
},
];
}
......
import { Chart, Coord, Geom, Shape, Tooltip } from 'bizcharts';
import React, { Component } from 'react';
import { Chart, Geom, Coord, Shape, Tooltip } from 'bizcharts';
import DataSet from '@antv/data-set';
import Debounce from 'lodash-decorators/debounce';
import Bind from 'lodash-decorators/bind';
import Debounce from 'lodash.debounce';
import classNames from 'classnames';
import autoHeight from '../autoHeight';
import styles from './index.less';
......@@ -12,33 +12,36 @@ import styles from './index.less';
const imgUrl = 'https://gw.alipayobjects.com/zos/rmsportal/gWyeGLCdFFRavBGIDzWk.png';
export interface ITagCloudProps {
data: Array<{
export interface TagCloudProps {
data: {
name: string;
value: number;
}>;
}[];
height?: number;
className?: string;
style?: React.CSSProperties;
}
interface ITagCloudState {
interface TagCloudState {
dv: any;
height?: number;
width: number;
}
class TagCloud extends Component<ITagCloudProps, ITagCloudState> {
class TagCloud extends Component<TagCloudProps, TagCloudState> {
state = {
dv: null,
height: 0,
width: 0,
};
isUnmount!: boolean;
requestRef!: number;
root: HTMLDivElement | undefined;
imageMask: HTMLImageElement | undefined;
isUnmount: boolean = false;
requestRef: number = 0;
root: HTMLDivElement | undefined = undefined;
imageMask: HTMLImageElement | undefined = undefined;
componentDidMount() {
requestAnimationFrame(() => {
......@@ -48,22 +51,25 @@ class TagCloud extends Component<ITagCloudProps, ITagCloudState> {
window.addEventListener('resize', this.resize, { passive: true });
}
componentDidUpdate(preProps?: ITagCloudProps) {
componentDidUpdate(preProps?: TagCloudProps) {
const { data } = this.props;
if (preProps && JSON.stringify(preProps.data) !== JSON.stringify(data)) {
this.renderChart(this.props);
}
}
componentWillUnmount() {
this.isUnmount = true;
window.cancelAnimationFrame(this.requestRef);
window.removeEventListener('resize', this.resize);
}
resize = () => {
this.requestRef = requestAnimationFrame(() => {
this.renderChart(this.props);
});
};
saveRootRef = (node: HTMLDivElement) => {
this.root = node;
};
......@@ -77,7 +83,8 @@ class TagCloud extends Component<ITagCloudProps, ITagCloudState> {
origin?: any;
color?: any;
}) {
return Object.assign({}, cfg.style, {
return {
...cfg.style,
fillOpacity: cfg.opacity,
fontSize: cfg.origin._origin.size,
rotate: cfg.origin._origin.rotate,
......@@ -86,7 +93,7 @@ class TagCloud extends Component<ITagCloudProps, ITagCloudState> {
fontFamily: cfg.origin._origin.font,
fill: cfg.color,
textBaseline: 'Alphabetic',
});
};
}
(Shape as any).registerShape('point', 'cloud', {
......@@ -96,18 +103,17 @@ class TagCloud extends Component<ITagCloudProps, ITagCloudState> {
) {
const attrs = getTextAttrs(cfg);
return container.addShape('text', {
attrs: Object.assign(attrs, {
attrs: {
...attrs,
x: cfg.x,
y: cfg.y,
}),
},
});
},
});
};
@Bind()
@Debounce(500)
renderChart(nextProps: ITagCloudProps) {
renderChart = Debounce((nextProps: TagCloudProps) => {
// const colors = ['#1890FF', '#41D9C7', '#2FC25B', '#FACC14', '#9AE65C'];
const { data, height } = nextProps || this.props;
......@@ -134,8 +140,8 @@ class TagCloud extends Component<ITagCloudProps, ITagCloudState> {
return 0;
},
fontSize(d: { value: number }) {
// eslint-disable-next-line
return Math.pow((d.value - min) / (max - min), 2) * (17.5 - 5) + 5;
const size = ((d.value - min) / (max - min)) ** 2;
return size * (17.5 - 5) + 5;
},
});
......@@ -159,7 +165,7 @@ class TagCloud extends Component<ITagCloudProps, ITagCloudState> {
} else {
onload();
}
}
}, 500);
render() {
const { className, height } = this.props;
......
import React from 'react';
import { Chart, Tooltip, Geom, Legend, Axis } from 'bizcharts';
import { Axis, Chart, Geom, Legend, Tooltip } from 'bizcharts';
import DataSet from '@antv/data-set';
import React from 'react';
import Slider from 'bizcharts-plugin-slider';
import autoHeight from '../autoHeight';
import styles from './index.less';
export interface ITimelineChartProps {
data: Array<{
export interface TimelineChartProps {
data: {
x: number;
y1: number;
y2: number;
}>;
}[];
title?: string;
titleMap: { y1: string; y2: string };
padding?: [number, number, number, number];
......@@ -19,8 +20,7 @@ export interface ITimelineChartProps {
borderWidth?: number;
}
class TimelineChart extends React.Component<ITimelineChartProps> {
render() {
const TimelineChart: React.FC<TimelineChartProps> = props => {
const {
title,
height = 400,
......@@ -31,7 +31,7 @@ class TimelineChart extends React.Component<ITimelineChartProps> {
},
borderWidth = 2,
data: sourceData,
} = this.props;
} = props;
const data = Array.isArray(sourceData) ? sourceData : [{ x: 0, y1: 0, y2: 0 }];
......@@ -127,7 +127,6 @@ class TimelineChart extends React.Component<ITimelineChartProps> {
</div>
</div>
);
}
}
};
export default autoHeight()(TimelineChart);
import React, { Component } from 'react';
import autoHeight from '../autoHeight';
import styles from './index.less';
......@@ -6,7 +7,7 @@ import styles from './index.less';
/* eslint no-mixed-operators: 0 */
// riddle: https://riddle.alibaba-inc.com/riddles/2d9a4b90
export interface IWaterWaveProps {
export interface WaterWaveProps {
title: React.ReactNode;
color?: string;
height?: number;
......@@ -14,13 +15,16 @@ export interface IWaterWaveProps {
style?: React.CSSProperties;
}
class WaterWave extends Component<IWaterWaveProps> {
class WaterWave extends Component<WaterWaveProps> {
state = {
radio: 1,
};
timer: number = 0;
root: HTMLDivElement | undefined | null;
node: HTMLCanvasElement | undefined | null;
root: HTMLDivElement | undefined | null = null;
node: HTMLCanvasElement | undefined | null = null;
componentDidMount() {
this.renderChart();
......@@ -34,7 +38,7 @@ class WaterWave extends Component<IWaterWaveProps> {
);
}
componentDidUpdate(props: IWaterWaveProps) {
componentDidUpdate(props: WaterWaveProps) {
const { percent } = this.props;
if (props.percent !== percent) {
// 不加这个会造成绘制缓慢
......@@ -59,6 +63,7 @@ class WaterWave extends Component<IWaterWaveProps> {
});
}
};
renderChart(type?: string) {
const { percent, color = '#1890FF' } = this.props;
const data = percent / 100;
......@@ -201,6 +206,7 @@ class WaterWave extends Component<IWaterWaveProps> {
}
render();
}
render() {
const { radio } = this.state;
const { percent, title, height = 1 } = this.props;
......
......@@ -6,15 +6,16 @@ export type IReactComponent<P = any> =
| React.ClassicComponentClass<P>;
function computeHeight(node: HTMLDivElement) {
node.style.height = '100%';
const totalHeight = parseInt(getComputedStyle(node).height + '', 10);
const { style } = node;
style.height = '100%';
const totalHeight = parseInt(`${getComputedStyle(node).height}`, 10);
const padding =
parseInt(getComputedStyle(node).paddingTop + '', 10) +
parseInt(getComputedStyle(node).paddingBottom + '', 10);
parseInt(`${getComputedStyle(node).paddingTop}`, 10) +
parseInt(`${getComputedStyle(node).paddingBottom}`, 10);
return totalHeight - padding;
}
function getAutoHeight(n: HTMLDivElement) {
function getAutoHeight(n: HTMLDivElement | undefined) {
if (!n) {
return 0;
}
......@@ -30,24 +31,25 @@ function getAutoHeight(n: HTMLDivElement) {
return height;
}
interface IAutoHeightProps {
interface AutoHeightProps {
height?: number;
}
function autoHeight() {
return function<P extends IAutoHeightProps>(
return <P extends AutoHeightProps>(
WrappedComponent: React.ComponentClass<P> | React.SFC<P>,
): React.ComponentClass<P> {
class AutoHeightComponent extends React.Component<P & IAutoHeightProps> {
): React.ComponentClass<P> => {
class AutoHeightComponent extends React.Component<P & AutoHeightProps> {
state = {
computedHeight: 0,
};
root!: HTMLDivElement;
root: HTMLDivElement | undefined = undefined;
componentDidMount() {
const { height } = this.props;
if (!height) {
let h = getAutoHeight(this.root);
// eslint-disable-next-line
this.setState({ computedHeight: h });
if (h < 1) {
h = getAutoHeight(this.root);
......@@ -55,9 +57,11 @@ function autoHeight() {
}
}
}
handleRoot = (node: HTMLDivElement) => {
this.root = node;
};
render() {
const { height } = this.props;
const { computedHeight } = this.state;
......
import numeral from 'numeral';
import Bar from './Bar';
import ChartCard from './ChartCard';
import Field from './Field';
import Bar from './Bar';
import Pie from './Pie';
import Gauge from './Gauge';
import MiniArea from './MiniArea';
import MiniBar from './MiniBar';
import MiniProgress from './MiniProgress';
import WaterWave from './WaterWave';
import Pie from './Pie';
import TagCloud from './TagCloud';
import TimelineChart from './TimelineChart';
import WaterWave from './WaterWave';
const yuan = (val: number | string) => ${numeral(val).format('0,0')}`;
......
import React from 'react';
import { Row, Col, Icon, Tooltip } from 'antd';
import { Col, Icon, Row, Tooltip } from 'antd';
import { FormattedMessage } from 'umi-plugin-react/locale';
import Charts from './Charts';
import React from 'react';
import numeral from 'numeral';
import styles from '../style.less';
import Yuan from '../utils/Yuan';
import { ChartCard, MiniArea, MiniBar, MiniProgress, Field } from './Charts';
import { VisitDataType } from '../data.d';
import Trend from './Trend';
import { IVisitData } from '../data.d';
const { ChartCard, MiniArea, MiniBar, MiniProgress, Field } = Charts;
import Yuan from '../utils/Yuan';
import styles from '../style.less';
const topColResponsiveProps = {
xs: 24,
......@@ -18,8 +18,7 @@ const topColResponsiveProps = {
style: { marginBottom: 24 },
};
const IntroduceRow = ({ loading, visitData }: { loading: boolean; visitData: IVisitData[] }) => {
return (
const IntroduceRow = ({ loading, visitData }: { loading: boolean; visitData: VisitDataType[] }) => (
<Row gutter={24}>
<Col {...topColResponsiveProps}>
<ChartCard
......@@ -77,10 +76,7 @@ const IntroduceRow = ({ loading, visitData }: { loading: boolean; visitData: IVi
footer={
<Field
label={
<FormattedMessage
id="BLOCK_NAME.analysis.day-visits"
defaultMessage="Daily Visits"
/>
<FormattedMessage id="BLOCK_NAME.analysis.day-visits" defaultMessage="Daily Visits" />
}
value={numeral(1234).format('0,0')}
/>
......@@ -159,7 +155,6 @@ const IntroduceRow = ({ loading, visitData }: { loading: boolean; visitData: IVi
</ChartCard>
</Col>
</Row>
);
};
);
export default IntroduceRow;
import React from 'react';
import { Icon } from 'antd';
import React from 'react';
import classNames from 'classnames';
import styles from './index.less';
export interface NumberInfoProps {
title?: React.ReactNode | string;
subTitle?: React.ReactNode | string;
......
import { Card, Col, Row, Tabs } from 'antd';
import { FormattedMessage, formatMessage } from 'umi-plugin-react/locale';
import React from 'react';
import { Card, Tabs, Row, Col } from 'antd';
import { formatMessage, FormattedMessage } from 'umi-plugin-react/locale';
import Charts from './Charts';
import styles from '../style.less';
import { OfflineChartData, OfflineDataType } from '../data.d';
import { TimelineChart, Pie } from './Charts';
import NumberInfo from './NumberInfo';
import { IOfflineData, IOfflineChartData } from '../data';
const { TimelineChart, Pie } = Charts;
import styles from '../style.less';
const CustomTab = ({
data,
currentTabKey: currentKey,
}: {
data: IOfflineData;
data: OfflineDataType;
currentTabKey: string;
}) => {
return (
}) => (
<Row gutter={8} style={{ width: 138, margin: '8px 0' }}>
<Col span={12}>
<NumberInfo
......@@ -41,8 +40,7 @@ const CustomTab = ({
/>
</Col>
</Row>
);
};
);
const { TabPane } = Tabs;
......@@ -55,8 +53,8 @@ const OfflineData = ({
}: {
activeKey: string;
loading: boolean;
offlineData: IOfflineData[];
offlineChartData: IOfflineChartData[];
offlineData: OfflineDataType[];
offlineChartData: OfflineChartData[];
handleTabChange: (activeKey: string) => void;
}) => (
<Card loading={loading} className={styles.offlineCard} bordered={false} style={{ marginTop: 32 }}>
......
import React from 'react';
import { Card, Radio } from 'antd';
import Charts from './Charts';
import { FormattedMessage } from 'umi-plugin-react/locale';
import styles from '../style.less';
import Yuan from '../utils/Yuan';
import { RadioChangeEvent } from 'antd/es/radio';
import { ISalesData } from '../data';
const { Pie } = Charts;
import React from 'react';
import { VisitDataType } from '../data.d';
import { Pie } from './Charts';
import Yuan from '../utils/Yuan';
import styles from '../style.less';
const ProportionSales = ({
dropdownGroup,
......@@ -19,10 +18,9 @@ const ProportionSales = ({
loading: boolean;
dropdownGroup: React.ReactNode;
salesType: 'all' | 'online' | 'stores';
salesPieData: ISalesData[];
salesPieData: VisitDataType[];
handleChangeSalesType?: (e: RadioChangeEvent) => void;
}) => {
return (
}) => (
<Card
loading={loading}
className={styles.salesCard}
......@@ -73,7 +71,6 @@ const ProportionSales = ({
/>
</div>
</Card>
);
};
);
export default ProportionSales;
import React from 'react';
import { Row, Col, Card, Tabs, DatePicker } from 'antd';
import { Card, Col, DatePicker, Row, Tabs } from 'antd';
import { FormattedMessage, formatMessage } from 'umi-plugin-react/locale';
import numeral from 'numeral';
import Charts from './Charts';
import { RangePickerValue } from 'antd/es/date-picker/interface';
import { ISalesData } from '../data';
import React from 'react';
import numeral from 'numeral';
import { VisitDataType } from '../data.d';
import { Bar } from './Charts';
import styles from '../style.less';
const { Bar } = Charts;
const { RangePicker } = DatePicker;
const { TabPane } = Tabs;
......@@ -30,7 +29,7 @@ const SalesCard = ({
}: {
rangePickerValue: RangePickerValue;
isActive: (key: 'today' | 'week' | 'month' | 'year') => string;
salesData: ISalesData[];
salesData: VisitDataType[];
loading: boolean;
handleRangePickerChange: (dates: RangePickerValue, dateStrings: [string, string]) => void;
selectDate: (key: 'today' | 'week' | 'month' | 'year') => void;
......
import React from 'react';
import { Row, Col, Table, Tooltip, Card, Icon } from 'antd';
import { Card, Col, Icon, Row, Table, Tooltip } from 'antd';
import { FormattedMessage } from 'umi-plugin-react/locale';
import Charts from './Charts';
import Trend from './Trend';
import NumberInfo from './NumberInfo';
import React from 'react';
import numeral from 'numeral';
import styles from '../style.less';
import { ISearchData, IVisitData2 } from '../data';
import { SearchDataType, VisitDataType } from '../data.d';
const { MiniArea } = Charts;
import { MiniArea } from './Charts';
import NumberInfo from './NumberInfo';
import Trend from './Trend';
import styles from '../style.less';
const columns = [
{
......@@ -51,9 +50,9 @@ const TopSearch = ({
dropdownGroup,
}: {
loading: boolean;
visitData2: IVisitData2[];
visitData2: VisitDataType[];
dropdownGroup: React.ReactNode;
searchData: ISearchData[];
searchData: SearchDataType[];
}) => (
<Card
loading={loading}
......
import React from 'react';
import { Icon } from 'antd';
import React from 'react';
import classNames from 'classnames';
import styles from './index.less';
export interface ITrendProps {
export interface TrendProps {
colorful?: boolean;
flag: 'up' | 'down';
style?: React.CSSProperties;
......@@ -11,7 +11,7 @@ export interface ITrendProps {
className?: string;
}
const Trend: React.SFC<ITrendProps> = ({
const Trend: React.SFC<TrendProps> = ({
colorful = true,
reverseColor = false,
flag,
......
export interface IVisitData {
export interface VisitDataType {
x: string;
y: number;
}
export interface IVisitData2 {
x: string;
y: number;
}
export interface ISalesData {
x: string;
y: number;
}
export interface ISearchData {
export interface SearchDataType {
index: number;
keyword: string;
count: number;
......@@ -21,47 +11,32 @@ export interface ISearchData {
status: number;
}
export interface IOfflineData {
export interface OfflineDataType {
name: string;
cvr: number;
}
export interface IOfflineChartData {
export interface OfflineChartData {
x: any;
y1: number;
y2: number;
}
export interface ISalesTypeData {
x: string;
y: number;
}
export interface ISalesTypeDataOnline {
x: string;
y: number;
}
export interface ISalesTypeDataOffline {
x: string;
y: number;
}
export interface IRadarData {
export interface RadarData {
name: string;
label: string;
value: number;
}
export interface IAnalysisData {
visitData: IVisitData[];
visitData2: IVisitData2[];
salesData: ISalesData[];
searchData: ISearchData[];
offlineData: IOfflineData[];
offlineChartData: IOfflineChartData[];
salesTypeData: ISalesTypeData[];
salesTypeDataOnline: ISalesTypeDataOnline[];
salesTypeDataOffline: ISalesTypeDataOffline[];
radarData: IRadarData[];
export interface AnalysisData {
visitData: VisitDataType[];
visitData2: VisitDataType[];
salesData: VisitDataType[];
searchData: SearchDataType[];
offlineData: OfflineDataType[];
offlineChartData: OfflineChartData[];
salesTypeData: VisitDataType[];
salesTypeDataOnline: VisitDataType[];
salesTypeDataOffline: VisitDataType[];
radarData: RadarData[];
}
import { Col, Dropdown, Icon, Menu, Row } from 'antd';
import React, { Component, Suspense } from 'react';
import { connect } from 'dva';
import { Row, Col, Icon, Menu, Dropdown } from 'antd';
import { Dispatch } from 'redux';
import { GridContent } from '@ant-design/pro-layout';
import { RadioChangeEvent } from 'antd/es/radio';
import { RangePickerValue } from 'antd/es/date-picker/interface';
import { connect } from 'dva';
import PageLoading from './components/PageLoading';
import { getTimeDistance } from './utils/utils';
import { AnalysisData } from './data.d';
import styles from './style.less';
import PageLoading from './components/PageLoading';
import { Dispatch } from 'redux';
import { IAnalysisData } from './data.d';
import { RadioChangeEvent } from 'antd/es/radio';
import { GridContent } from '@ant-design/pro-layout';
const IntroduceRow = React.lazy(() => import('./components/IntroduceRow'));
const SalesCard = React.lazy(() => import('./components/SalesCard'));
......@@ -17,7 +18,7 @@ const ProportionSales = React.lazy(() => import('./components/ProportionSales'))
const OfflineData = React.lazy(() => import('./components/OfflineData'));
interface BLOCK_NAME_CAMEL_CASEProps {
BLOCK_NAME_CAMEL_CASE: IAnalysisData;
BLOCK_NAME_CAMEL_CASE: AnalysisData;
dispatch: Dispatch<any>;
loading: boolean;
}
......@@ -51,8 +52,11 @@ class PAGE_NAME_UPPER_CAMEL_CASE extends Component<
currentTabKey: '',
rangePickerValue: getTimeDistance('year'),
};
reqRef!: number;
timeoutId!: number;
reqRef: number = 0;
timeoutId: number = 0;
componentDidMount() {
const { dispatch } = this.props;
this.reqRef = requestAnimationFrame(() => {
......
import { fakeChartData } from './service';
import { IAnalysisData } from './data';
import { Reducer } from 'redux';
import { AnyAction, Reducer } from 'redux';
import { EffectsCommandMap } from 'dva';
import { AnyAction } from 'redux';
import { AnalysisData } from './data.d';
import { fakeChartData } from './service';
export type Effect = (
action: AnyAction,
effects: EffectsCommandMap & { select: <T>(func: (state: IAnalysisData) => T) => T },
effects: EffectsCommandMap & { select: <T>(func: (state: AnalysisData) => T) => T },
) => void;
export interface ModelType {
namespace: string;
state: IAnalysisData;
state: AnalysisData;
effects: {
fetch: Effect;
fetchSalesData: Effect;
};
reducers: {
save: Reducer<IAnalysisData>;
clear: Reducer<IAnalysisData>;
save: Reducer<AnalysisData>;
clear: Reducer<AnalysisData>;
};
}
......
......@@ -6,7 +6,8 @@ import { yuan } from '../components/Charts';
export default class Yuan extends React.Component<{
children: React.ReactText;
}> {
main: HTMLSpanElement | undefined | null;
main: HTMLSpanElement | undefined | null = null;
componentDidMount() {
this.renderToHtml();
}
......@@ -14,6 +15,7 @@ export default class Yuan extends React.Component<{
componentDidUpdate() {
this.renderToHtml();
}
renderToHtml = () => {
const { children } = this.props;
if (this.main) {
......
import moment from 'moment';
import { RangePickerValue } from 'antd/es/date-picker/interface';
import moment from 'moment';
export function fixedZero(val: number) {
return val * 1 < 10 ? `0${val}` : val;
......
......@@ -13,21 +13,25 @@
"dependencies": {
"@ant-design/pro-layout": "^4.5.2",
"@antv/data-set": "^0.10.2",
"@types/lodash.debounce": "^4.0.6",
"antd": "^3.16.3",
"bizcharts": "^3.5.3-beta.0",
"bizcharts-plugin-slider": "^2.1.1-beta.1",
"classnames": "^2.2.6",
"dva": "^2.4.0",
"lodash.debounce": "^4.0.8",
"numeral": "^2.0.6",
"react": "^16.8.6",
"react-fittext": "^1.0.0",
"umi-request": "^1.0.0"
},
"devDependencies": {
"@types/numeral": "^0.0.25",
"mockjs": "^1.0.1-beta3",
"redux": "^4.0.1",
"umi": "^2.6.9",
"umi-plugin-block-dev": "^1.0.0",
"umi-plugin-react": "^1.7.2"
"umi-plugin-react": "^1.7.2",
"umi-request": "^1.0.0",
"mockjs": "^1.0.1-beta3"
},
"devDependencies": {
"@types/numeral": "^0.0.25"
},
"license": "ISC",
"blockConfig": {
......
import React, { Component } from 'react';
import Charts from '../Charts';
import { Statistic } from 'antd';
import { MiniArea } from '../Charts';
import styles from './index.less';
const { MiniArea } = Charts;
function fixedZero(val: number) {
return val * 1 < 10 ? `0${val}` : val;
}
......@@ -24,12 +23,15 @@ export default class ActiveChart extends Component {
state = {
activeData: getActiveData(),
};
timer: number | undefined;
requestRef: number | undefined;
timer: number | undefined = undefined;
requestRef: number | undefined = undefined;
componentDidMount() {
this.loopData();
}
componentWillUnmount() {
clearTimeout(this.timer);
if (this.requestRef) {
......
import { Axis, Chart, Coord, Geom, Guide, Shape } from 'bizcharts';
import React from 'react';
import { Chart, Geom, Axis, Coord, Guide, Shape } from 'bizcharts';
import autoHeight from '../autoHeight';
const { Arc, Html, Line } = Guide;
export interface IGaugeProps {
export interface GaugeProps {
title: React.ReactNode;
color?: string;
height?: number;
......@@ -30,7 +31,8 @@ const defaultFormatter = (val: string): string => {
}
};
Shape.registerShape!('point', 'pointer', {
if (Shape.registerShape) {
Shape.registerShape('point', 'pointer', {
drawShape(cfg: any, group: any) {
let point = cfg.points[0];
point = (this as any).parsePoint(point);
......@@ -60,10 +62,10 @@ Shape.registerShape!('point', 'pointer', {
},
});
},
});
});
}
class Gauge extends React.Component<IGaugeProps> {
render() {
const Gauge: React.FC<GaugeProps> = props => {
const {
title,
height = 1,
......@@ -72,7 +74,7 @@ class Gauge extends React.Component<IGaugeProps> {
formatter = defaultFormatter,
color = '#2F9CFF',
bgColor = '#F0F2F5',
} = this.props;
} = props;
const cols = {
value: {
type: 'linear',
......@@ -82,6 +84,8 @@ class Gauge extends React.Component<IGaugeProps> {
nice: true,
},
};
const data = [{ value: percent / 10 }];
const renderHtml = () => `
<div style="width: 300px;text-align: center;font-size: 12px!important;">
<p style="font-size: 14px; color: rgba(0,0,0,0.43);margin: 0;">${title}</p>
......@@ -89,7 +93,6 @@ class Gauge extends React.Component<IGaugeProps> {
${(data[0].value * 10).toFixed(2)}%
</p>
</div>`;
const data = [{ value: percent / 10 }];
const textStyle: {
fontSize: number;
fill: string;
......@@ -112,7 +115,7 @@ class Gauge extends React.Component<IGaugeProps> {
label={{
offset: -12,
formatter,
textStyle: textStyle,
textStyle,
}}
/>
<Guide>
......@@ -171,7 +174,6 @@ class Gauge extends React.Component<IGaugeProps> {
/>
</Chart>
);
}
}
};
export default autoHeight()(Gauge);
import { Axis, AxisProps, Chart, Geom, Tooltip } from 'bizcharts';
import React from 'react';
import { Chart, Axis, Tooltip, Geom } from 'bizcharts';
import autoHeight from '../autoHeight';
import styles from '../index.less';
export interface IAxis {
title: any;
line: any;
gridAlign: any;
labels: any;
tickLine: any;
grid: any;
label: any;
}
export interface IMiniAreaProps {
export interface MiniAreaProps {
color?: string;
height?: number;
borderColor?: string;
line?: boolean;
animate?: boolean;
xAxis?: IAxis;
xAxis?: AxisProps;
forceFit?: boolean;
scale?: { x?: any; y?: any };
yAxis?: Partial<IAxis>;
scale?: {
x?: {
tickCount: number;
};
y?: {
tickCount: number;
};
};
yAxis?: Partial<AxisProps>;
borderWidth?: number;
data: Array<{
data: {
x: number | string;
y: number;
}>;
}[];
}
class MiniArea extends React.Component<IMiniAreaProps> {
render() {
const MiniArea: React.FC<MiniAreaProps> = props => {
const {
height = 1,
data = [],
......@@ -44,7 +41,7 @@ class MiniArea extends React.Component<IMiniAreaProps> {
xAxis,
yAxis,
animate = true,
} = this.props;
} = props;
const padding: [number, number, number, number] = [36, 5, 30, 5];
......@@ -52,11 +49,11 @@ class MiniArea extends React.Component<IMiniAreaProps> {
x: {
type: 'cat',
range: [0, 1],
...scale!.x,
...scale.x,
},
y: {
min: 0,
...scale!.y,
...scale.y,
},
};
......@@ -85,19 +82,19 @@ class MiniArea extends React.Component<IMiniAreaProps> {
<Axis
key="axis-x"
name="x"
label={false}
line={false}
tickLine={false}
grid={false}
label={null}
line={null}
tickLine={null}
grid={null}
{...xAxis}
/>
<Axis
key="axis-y"
name="y"
label={false}
line={false}
tickLine={false}
grid={false}
label={null}
line={null}
tickLine={null}
grid={null}
{...yAxis}
/>
<Tooltip showTitle={false} crosshairs={false} />
......@@ -128,7 +125,6 @@ class MiniArea extends React.Component<IMiniAreaProps> {
</div>
</div>
);
}
}
};
export default autoHeight()(MiniArea);
import { Chart, Coord, Geom, Tooltip } from 'bizcharts';
import React, { Component } from 'react';
import { Chart, Tooltip, Geom, Coord } from 'bizcharts';
import { DataView } from '@antv/data-set';
import Debounce from 'lodash.debounce';
import { Divider } from 'antd';
import classNames from 'classnames';
import ReactFitText from 'react-fittext';
import Debounce from 'lodash-decorators/debounce';
import Bind from 'lodash-decorators/bind';
import classNames from 'classnames';
import autoHeight from '../autoHeight';
import styles from './index.less';
export interface IPieProps {
export interface PieProps {
animate?: boolean;
color?: string;
colors?: string[];
......@@ -19,10 +19,10 @@ export interface IPieProps {
hasLegend?: boolean;
padding?: [number, number, number, number];
percent?: number;
data?: Array<{
data?: {
x: string | string;
y: number;
}>;
}[];
inner?: number;
lineWidth?: number;
forceFit?: boolean;
......@@ -34,19 +34,46 @@ export interface IPieProps {
valueFormat?: (value: string) => string | React.ReactNode;
subTitle?: React.ReactNode;
}
interface IPieState {
legendData: Array<{ checked: boolean; x: string; color: string; percent: number; y: string }>;
interface PieState {
legendData: { checked: boolean; x: string; color: string; percent: number; y: string }[];
legendBlock: boolean;
}
class Pie extends Component<IPieProps, IPieState> {
state: IPieState = {
class Pie extends Component<PieProps, PieState> {
state: PieState = {
legendData: [],
legendBlock: false,
};
requestRef: number | undefined;
root!: HTMLDivElement;
chart: G2.Chart | undefined;
chart: G2.Chart | undefined = undefined;
root: HTMLDivElement | undefined = undefined;
requestRef: number | undefined = 0;
// for window resize auto responsive legend
resize = Debounce(() => {
const { hasLegend } = this.props;
const { legendBlock } = this.state;
if (!hasLegend || !this.root) {
window.removeEventListener('resize', this.resize);
return;
}
if (
this.root &&
this.root.parentNode &&
(this.root.parentNode as HTMLElement).clientWidth <= 380
) {
if (!legendBlock) {
this.setState({
legendBlock: true,
});
}
} else if (legendBlock) {
this.setState({
legendBlock: false,
});
}
}, 300);
componentDidMount() {
window.addEventListener(
......@@ -58,7 +85,7 @@ class Pie extends Component<IPieProps, IPieState> {
);
}
componentDidUpdate(preProps: IPieProps) {
componentDidUpdate(preProps: PieProps) {
const { data } = this.props;
if (data !== preProps.data) {
// because of charts data create when rendered
......@@ -90,7 +117,8 @@ class Pie extends Component<IPieProps, IPieState> {
if (!this.chart) return;
const geom = this.chart.getAllGeoms()[0]; // 获取所有的图形
if (!geom) return;
const items = geom.get('dataArray') || []; // 获取图形对应的
// g2 的类型有问题
const items = (geom as any).get('dataArray') || []; // 获取图形对应的
const legendData = items.map((item: { color: any; _origin: any }[]) => {
/* eslint no-underscore-dangle:0 */
......@@ -104,11 +132,12 @@ class Pie extends Component<IPieProps, IPieState> {
legendData,
});
};
handleRoot = (n: HTMLDivElement) => {
this.root = n;
};
handleLegendClick = (item: any, i: string | number) => {
handleLegendClick = (item: { checked: boolean }, i: string | number) => {
const newItem = item;
newItem.checked = !newItem.checked;
......@@ -118,7 +147,7 @@ class Pie extends Component<IPieProps, IPieState> {
const filteredLegendData = legendData.filter(l => l.checked).map(l => l.x);
if (this.chart) {
this.chart.filter('x', val => filteredLegendData.indexOf(val + '') > -1);
this.chart.filter('x', val => filteredLegendData.indexOf(`${val}`) > -1);
}
this.setState({
......@@ -126,33 +155,6 @@ class Pie extends Component<IPieProps, IPieState> {
});
};
// for window resize auto responsive legend
@Bind()
@Debounce(300)
resize() {
const { hasLegend } = this.props;
const { legendBlock } = this.state;
if (!hasLegend || !this.root) {
window.removeEventListener('resize', this.resize);
return;
}
if (
this.root &&
this.root.parentNode &&
(this.root.parentNode as HTMLElement).clientWidth <= 380
) {
if (!legendBlock) {
this.setState({
legendBlock: true,
});
}
} else if (legendBlock) {
this.setState({
legendBlock: false,
});
}
}
render() {
const {
valueFormat,
......@@ -216,11 +218,11 @@ class Pie extends Component<IPieProps, IPieState> {
data = [
{
x: '占比',
y: parseFloat(percent + ''),
y: parseFloat(`${percent}`),
},
{
x: '反比',
y: 100 - parseFloat(percent + ''),
y: 100 - parseFloat(`${percent}`),
},
];
}
......
import { Chart, Coord, Geom, Shape, Tooltip } from 'bizcharts';
import React, { Component } from 'react';
import { Chart, Geom, Coord, Shape, Tooltip } from 'bizcharts';
import DataSet from '@antv/data-set';
import Debounce from 'lodash-decorators/debounce';
import Bind from 'lodash-decorators/bind';
import Debounce from 'lodash.debounce';
import classNames from 'classnames';
import autoHeight from '../autoHeight';
import styles from './index.less';
......@@ -12,33 +12,36 @@ import styles from './index.less';
const imgUrl = 'https://gw.alipayobjects.com/zos/rmsportal/gWyeGLCdFFRavBGIDzWk.png';
export interface ITagCloudProps {
data: Array<{
export interface TagCloudProps {
data: {
name: string;
value: string;
}>;
}[];
height?: number;
className?: string;
style?: React.CSSProperties;
}
interface ITagCloudState {
interface TagCloudState {
dv: any;
height?: number;
width: number;
}
class TagCloud extends Component<ITagCloudProps, ITagCloudState> {
class TagCloud extends Component<TagCloudProps, TagCloudState> {
state = {
dv: null,
height: 0,
width: 0,
};
isUnmount!: boolean;
requestRef!: number;
root: HTMLDivElement | undefined;
imageMask: HTMLImageElement | undefined;
requestRef: number = 0;
isUnmount: boolean = false;
root: HTMLDivElement | undefined = undefined;
imageMask: HTMLImageElement | undefined = undefined;
componentDidMount() {
requestAnimationFrame(() => {
......@@ -48,22 +51,25 @@ class TagCloud extends Component<ITagCloudProps, ITagCloudState> {
window.addEventListener('resize', this.resize, { passive: true });
}
componentDidUpdate(preProps?: ITagCloudProps) {
componentDidUpdate(preProps?: TagCloudProps) {
const { data } = this.props;
if (preProps && JSON.stringify(preProps.data) !== JSON.stringify(data)) {
this.renderChart(this.props);
}
}
componentWillUnmount() {
this.isUnmount = true;
window.cancelAnimationFrame(this.requestRef);
window.removeEventListener('resize', this.resize);
}
resize = () => {
this.requestRef = requestAnimationFrame(() => {
this.renderChart(this.props);
});
};
saveRootRef = (node: HTMLDivElement) => {
this.root = node;
};
......@@ -77,7 +83,8 @@ class TagCloud extends Component<ITagCloudProps, ITagCloudState> {
origin?: any;
color?: any;
}) {
return Object.assign({}, cfg.style, {
return {
...cfg.style,
fillOpacity: cfg.opacity,
fontSize: cfg.origin._origin.size,
rotate: cfg.origin._origin.rotate,
......@@ -86,7 +93,7 @@ class TagCloud extends Component<ITagCloudProps, ITagCloudState> {
fontFamily: cfg.origin._origin.font,
fill: cfg.color,
textBaseline: 'Alphabetic',
});
};
}
(Shape as any).registerShape('point', 'cloud', {
......@@ -96,18 +103,17 @@ class TagCloud extends Component<ITagCloudProps, ITagCloudState> {
) {
const attrs = getTextAttrs(cfg);
return container.addShape('text', {
attrs: Object.assign(attrs, {
attrs: {
...attrs,
x: cfg.x,
y: cfg.y,
}),
},
});
},
});
};
@Bind()
@Debounce(500)
renderChart(nextProps: ITagCloudProps) {
renderChart = Debounce((nextProps: TagCloudProps) => {
// const colors = ['#1890FF', '#41D9C7', '#2FC25B', '#FACC14', '#9AE65C'];
const { data, height } = nextProps || this.props;
if (data.length < 1 || !this.root) {
......@@ -133,8 +139,8 @@ class TagCloud extends Component<ITagCloudProps, ITagCloudState> {
return 0;
},
fontSize(d: { value: number }) {
// eslint-disable-next-line
return Math.pow((d.value - min) / (max - min), 2) * (17.5 - 5) + 5;
const size = ((d.value - min) / (max - min)) ** 2;
return size * (17.5 - 5) + 5;
},
});
......@@ -158,7 +164,7 @@ class TagCloud extends Component<ITagCloudProps, ITagCloudState> {
} else {
onload();
}
}
}, 200);
render() {
const { className, height } = this.props;
......
import React, { Component } from 'react';
import autoHeight from '../autoHeight';
import styles from './index.less';
......@@ -6,7 +7,7 @@ import styles from './index.less';
/* eslint no-mixed-operators: 0 */
// riddle: https://riddle.alibaba-inc.com/riddles/2d9a4b90
export interface IWaterWaveProps {
export interface WaterWaveProps {
title: React.ReactNode;
color?: string;
height?: number;
......@@ -14,13 +15,16 @@ export interface IWaterWaveProps {
style?: React.CSSProperties;
}
class WaterWave extends Component<IWaterWaveProps> {
class WaterWave extends Component<WaterWaveProps> {
state = {
radio: 1,
};
timer: number = 0;
root: HTMLDivElement | undefined | null;
node: HTMLCanvasElement | undefined | null;
root: HTMLDivElement | undefined | null = null;
node: HTMLCanvasElement | undefined | null = null;
componentDidMount() {
this.renderChart();
......@@ -34,7 +38,7 @@ class WaterWave extends Component<IWaterWaveProps> {
);
}
componentDidUpdate(props: IWaterWaveProps) {
componentDidUpdate(props: WaterWaveProps) {
const { percent } = this.props;
if (props.percent !== percent) {
// 不加这个会造成绘制缓慢
......@@ -59,6 +63,7 @@ class WaterWave extends Component<IWaterWaveProps> {
});
}
};
renderChart(type?: string) {
const { percent, color = '#1890FF' } = this.props;
const data = percent / 100;
......@@ -201,6 +206,7 @@ class WaterWave extends Component<IWaterWaveProps> {
}
render();
}
render() {
const { radio } = this.state;
const { percent, title, height = 1 } = this.props;
......
......@@ -6,11 +6,12 @@ export type IReactComponent<P = any> =
| React.ClassicComponentClass<P>;
function computeHeight(node: HTMLDivElement) {
node.style.height = '100%';
const totalHeight = parseInt(getComputedStyle(node).height + '', 10);
const { style } = node;
style.height = '100%';
const totalHeight = parseInt(`${getComputedStyle(node).height}`, 10);
const padding =
parseInt(getComputedStyle(node).paddingTop + '', 10) +
parseInt(getComputedStyle(node).paddingBottom + '', 10);
parseInt(`${getComputedStyle(node).paddingTop}`, 10) +
parseInt(`${getComputedStyle(node).paddingBottom}`, 10);
return totalHeight - padding;
}
......@@ -30,22 +31,24 @@ function getAutoHeight(n: HTMLDivElement) {
return height;
}
interface IAutoHeightProps {
interface AutoHeightProps {
height?: number;
}
function autoHeight() {
return function<P extends IAutoHeightProps>(
return <P extends AutoHeightProps>(
WrappedComponent: React.ComponentClass<P> | React.SFC<P>,
): React.ComponentClass<P> {
class AutoHeightComponent extends React.Component<P & IAutoHeightProps> {
): React.ComponentClass<P> => {
class AutoHeightComponent extends React.Component<P & AutoHeightProps> {
state = {
computedHeight: 0,
};
root!: HTMLDivElement;
root: HTMLDivElement | null = null;
componentDidMount() {
const { height } = this.props;
if (!height) {
if (!height && this.root) {
let h = getAutoHeight(this.root);
this.setState({ computedHeight: h });
if (h < 1) {
......@@ -54,9 +57,11 @@ function autoHeight() {
}
}
}
handleRoot = (node: HTMLDivElement) => {
this.root = node;
};
render() {
const { height } = this.props;
const { computedHeight } = this.state;
......
import Pie from './Pie';
import Gauge from './Gauge';
import WaterWave from './WaterWave';
import TagCloud from './TagCloud';
import MiniArea from './MiniArea';
import Pie from './Pie';
import TagCloud from './TagCloud';
import WaterWave from './WaterWave';
const Charts = {
Pie,
WaterWave,
......
export interface ITag {
export interface TagType {
name: string;
value: string;
type: string;
......
import { Card, Col, Row, Statistic, Tooltip } from 'antd';
import { FormattedMessage, formatMessage } from 'umi-plugin-react/locale';
import React, { Component } from 'react';
import { Dispatch } from 'redux';
import { GridContent } from '@ant-design/pro-layout';
import { connect } from 'dva';
import { formatMessage, FormattedMessage } from 'umi-plugin-react/locale';
import { Row, Col, Card, Statistic, Tooltip } from 'antd';
import numeral from 'numeral';
import { Dispatch } from 'redux';
import { IStateType } from './model';
import { StateType } from './model';
import { Pie, WaterWave, Gauge, TagCloud } from './components/Charts';
import ActiveChart from './components/ActiveChart';
import styles from './style.less';
import Charts from './components/Charts';
import { GridContent } from '@ant-design/pro-layout';
const { Countdown } = Statistic;
const { Pie, WaterWave, Gauge, TagCloud } = Charts;
const targetTime = new Date().getTime() + 3900000;
interface PAGE_NAME_UPPER_CAMEL_CASEProps {
BLOCK_NAME_CAMEL_CASE: IStateType;
BLOCK_NAME_CAMEL_CASE: StateType;
dispatch: Dispatch<any>;
loading: boolean;
}
......@@ -27,7 +26,7 @@ interface PAGE_NAME_UPPER_CAMEL_CASEProps {
BLOCK_NAME_CAMEL_CASE,
loading,
}: {
BLOCK_NAME_CAMEL_CASE: IStateType;
BLOCK_NAME_CAMEL_CASE: StateType;
loading: {
models: { [key: string]: boolean };
};
......
import { queryTags } from './service';
import { ITag } from './data';
import { Reducer } from 'redux';
import { AnyAction, Reducer } from 'redux';
import { EffectsCommandMap } from 'dva';
import { AnyAction } from 'redux';
import { TagType } from './data.d';
import { queryTags } from './service';
export interface IStateType {
tags: ITag[];
export interface StateType {
tags: TagType[];
}
export type Effect = (
action: AnyAction,
effects: EffectsCommandMap & { select: <T>(func: (state: IStateType) => T) => T },
effects: EffectsCommandMap & { select: <T>(func: (state: StateType) => T) => T },
) => void;
export interface ModelType {
namespace: string;
state: IStateType;
state: StateType;
effects: {
fetchTags: Effect;
};
reducers: {
saveTags: Reducer<IStateType>;
saveTags: Reducer<StateType>;
};
}
......
......@@ -11,13 +11,15 @@
"url": "https://github.com/umijs/umi-blocks/ant-design-pro/workplace"
},
"dependencies": {
"@ant-design/pro-layout": "^4.5.5",
"antd": "^3.16.3",
"bizcharts": "^3.5.3-beta.0",
"dva": "^2.4.0",
"moment": "^2.22.2",
"prop-types": "^15.5.10",
"react": "^16.6.3",
"umi-request": "^1.0.0",
"bizcharts": "^3.5.3-beta.0"
"redux": "^4.0.1",
"umi-request": "^1.0.0"
},
"devDependencies": {
"umi": "^2.6.9",
......
import React, { PureComponent, createElement } from 'react';
import { Button } from 'antd';
import styles from './index.less';
......
......@@ -6,15 +6,16 @@ export type IReactComponent<P = any> =
| React.ClassicComponentClass<P>;
function computeHeight(node: HTMLDivElement) {
node.style.height = '100%';
const totalHeight = parseInt(getComputedStyle(node).height + '', 10);
const { style } = node;
style.height = '100%';
const totalHeight = parseInt(`${getComputedStyle(node).height}`, 10);
const padding =
parseInt(getComputedStyle(node).paddingTop + '', 10) +
parseInt(getComputedStyle(node).paddingBottom + '', 10);
parseInt(`${getComputedStyle(node).paddingTop}`, 10) +
parseInt(`${getComputedStyle(node).paddingBottom}`, 10);
return totalHeight - padding;
}
function getAutoHeight(n: HTMLDivElement) {
function getAutoHeight(n: HTMLDivElement | undefined) {
if (!n) {
return 0;
}
......@@ -30,24 +31,25 @@ function getAutoHeight(n: HTMLDivElement) {
return height;
}
interface IAutoHeightProps {
interface AutoHeightProps {
height?: number;
}
function autoHeight() {
return function<P extends IAutoHeightProps>(
return <P extends AutoHeightProps>(
WrappedComponent: React.ComponentClass<P> | React.SFC<P>,
): React.ComponentClass<P> {
class AutoHeightComponent extends React.Component<P & IAutoHeightProps> {
): React.ComponentClass<P> => {
class AutoHeightComponent extends React.Component<P & AutoHeightProps> {
state = {
computedHeight: 0,
};
root!: HTMLDivElement;
root: HTMLDivElement | undefined = undefined;
componentDidMount() {
const { height } = this.props;
if (!height) {
let h = getAutoHeight(this.root);
// eslint-disable-next-line
this.setState({ computedHeight: h });
if (h < 1) {
h = getAutoHeight(this.root);
......@@ -55,9 +57,11 @@ function autoHeight() {
}
}
}
handleRoot = (node: HTMLDivElement) => {
this.root = node;
};
render() {
const { height } = this.props;
const { computedHeight } = this.state;
......
import { Axis, Chart, Coord, Geom, Tooltip } from 'bizcharts';
import { Col, Row } from 'antd';
import React, { Component } from 'react';
import { Chart, Tooltip, Geom, Coord, Axis } from 'bizcharts';
import { Row, Col } from 'antd';
import autoHeight from './autoHeight';
import styles from './index.less';
export interface IRadarProps {
export interface RadarProps {
title?: React.ReactNode;
height?: number;
padding?: [number, number, number, number];
hasLegend?: boolean;
data: Array<{
data: {
name: string;
label: string;
value: string | number;
}>;
}[];
colors?: string[];
animate?: boolean;
forceFit?: boolean;
tickCount?: number;
style?: React.CSSProperties;
}
interface IRadarState {
legendData: Array<{
interface RadarState {
legendData: {
checked: boolean;
name: string;
color: string;
percent: number;
value: string;
}>;
}[];
}
/* eslint react/no-danger:0 */
class Radar extends Component<IRadarProps, IRadarState> {
state: IRadarState = {
class Radar extends Component<RadarProps, RadarState> {
state: RadarState = {
legendData: [],
};
chart: G2.Chart | undefined;
node: HTMLDivElement | undefined;
chart: G2.Chart | undefined = undefined;
node: HTMLDivElement | undefined = undefined;
componentDidMount() {
this.getLegendData();
}
componentDidUpdate(preProps: IRadarProps) {
componentDidUpdate(preProps: RadarProps) {
const { data } = this.props;
if (data !== preProps.data) {
this.getLegendData();
......@@ -57,10 +60,10 @@ class Radar extends Component<IRadarProps, IRadarState> {
if (!this.chart) return;
const geom = this.chart.getAllGeoms()[0]; // 获取所有的图形
if (!geom) return;
const items = geom.get('dataArray') || []; // 获取图形对应的
const items = (geom as any).get('dataArray') || []; // 获取图形对应的
const legendData = items.map((item: { color: any; _origin: any }[]) => {
// eslint-disable-next-line
// eslint-disable-next-line no-underscore-dangle
const origins = item.map(t => t._origin);
const result = {
name: origins[0].name,
......@@ -97,7 +100,7 @@ class Radar extends Component<IRadarProps, IRadarState> {
const filteredLegendData = legendData.filter(l => l.checked).map(l => l.name);
if (this.chart) {
this.chart.filter('name', val => filteredLegendData.indexOf(val + '') > -1);
this.chart.filter('name', val => filteredLegendData.indexOf(`${val}`) > -1);
this.chart.repaint();
}
......
export interface ITag {
export interface TagType {
key: string;
label: string;
}
export interface IProvince {
export interface ProvinceType {
label: string;
key: string;
}
export interface ICity {
export interface CityType {
label: string;
key: string;
}
export interface IGeographic {
province: IProvince;
city: ICity;
export interface GeographicType {
province: ProvinceType;
city: CityType;
}
export interface INotice {
export interface NoticeType {
id: string;
title: string;
logo: string;
......@@ -29,30 +29,30 @@ export interface INotice {
memberLink: string;
}
export interface ICurrentUser {
export interface CurrentUser {
name: string;
avatar: string;
userid: string;
notice: INotice[];
notice: NoticeType[];
email: string;
signature: string;
title: string;
group: string;
tags: ITag[];
tags: TagType[];
notifyCount: number;
unreadCount: number;
country: string;
geographic: IGeographic;
geographic: GeographicType;
address: string;
phone: string;
}
export interface IMember {
export interface Member {
avatar: string;
name: string;
id: string;
}
export interface IActivities {
export interface ActivitiesType {
id: string;
updatedAt: string;
user: {
......@@ -71,7 +71,7 @@ export interface IActivities {
template: string;
}
export interface IRadarData {
export interface RadarDataType {
label: string;
name: string;
value: number;
......
import { Avatar, Card, Col, List, Row } from 'antd';
import React, { PureComponent } from 'react';
import moment from 'moment';
import { connect } from 'dva';
import Link from 'umi/link';
import { Row, Col, Card, List, Avatar } from 'antd';
import { Dispatch } from 'redux';
import EditableLinkGroup from './components/EditableLinkGroup';
import { Dispatch } from 'redux';
import Link from 'umi/link';
import { PageHeaderWrapper } from '@ant-design/pro-layout';
import { connect } from 'dva';
import moment from 'moment';
import Radar from './components/Radar';
import { ModalState } from './model';
import { ICurrentUser, IActivities, IRadarData, INotice } from './data';
import { PageHeaderWrapper } from '@ant-design/pro-layout';
import EditableLinkGroup from './components/EditableLinkGroup';
import styles from './style.less';
import { ActivitiesType, CurrentUser, NoticeType, RadarDataType } from './data.d';
const links = [
{
......@@ -41,10 +40,10 @@ const links = [
];
interface BLOCK_NAME_CAMEL_CASEProps {
currentUser: ICurrentUser;
projectNotice: INotice[];
activities: IActivities[];
radarData: IRadarData[];
currentUser: CurrentUser;
projectNotice: NoticeType[];
activities: ActivitiesType[];
radarData: RadarDataType[];
dispatch: Dispatch<any>;
currentUserLoading: boolean;
projectLoading: boolean;
......@@ -83,7 +82,7 @@ class PAGE_NAME_UPPER_CAMEL_CASE extends PureComponent<BLOCK_NAME_CAMEL_CASEProp
});
}
renderActivities(item: IActivities) {
renderActivities = (item: ActivitiesType) => {
const events = item.template.split(/@\{([^{}]*)\}/gi).map(key => {
if (item[key]) {
return (
......@@ -113,7 +112,7 @@ class PAGE_NAME_UPPER_CAMEL_CASE extends PureComponent<BLOCK_NAME_CAMEL_CASEProp
/>
</List.Item>
);
}
};
render() {
const {
......@@ -207,11 +206,9 @@ class PAGE_NAME_UPPER_CAMEL_CASE extends PureComponent<BLOCK_NAME_CAMEL_CASEProp
title="动态"
loading={activitiesLoading}
>
<List<IActivities>
<List<ActivitiesType>
loading={activitiesLoading}
renderItem={item => {
return this.renderActivities(item);
}}
renderItem={item => this.renderActivities(item)}
dataSource={activities}
className={styles.activitiesList}
size="large"
......
import { AnyAction, Reducer } from 'redux';
import { EffectsCommandMap } from 'dva';
import { Reducer, AnyAction } from 'redux';
import { queryCurrent, queryProjectNotice, queryActivities, fakeChartData } from './service';
import { CurrentUser, Notice, Activeties, RadarData } from './data';
import { ActivitiesType, CurrentUser, NoticeType, RadarDataType } from './data.d';
import { fakeChartData, queryActivities, queryCurrent, queryProjectNotice } from './service';
export interface ModalState {
currentUser: Partial<CurrentUser>;
projectNotice: Notice[];
activities: Activeties[];
radarData: RadarData[];
projectNotice: NoticeType[];
activities: ActivitiesType[];
radarData: RadarDataType[];
}
export type Effect = (
......
......@@ -7,6 +7,7 @@ flow
```sh
umi block add ant-design-pro/flow
```
## SNAPSHOT
![SNAPSHOT](./snapshot.png)
......
......@@ -12,6 +12,7 @@
"dev": "umi dev"
},
"dependencies": {
"@ant-design/pro-layout": "^4.5.5",
"@antv/data-set": "^0.10.2",
"antd": "^3.16.3",
"bizcharts": "^3.5.3-beta.0",
......@@ -22,13 +23,13 @@
"numeral": "^2.0.6",
"react": "^16.6.3",
"react-fittext": "^1.0.0",
"umi": "^2.6.9",
"umi-plugin-react": "^1.7.2",
"umi-request": "^1.0.0"
},
"devDependencies": {
"umi": "^2.6.9",
"umi-plugin-block-dev": "^1.1.0",
"umi-plugin-react": "^1.7.2",
"@types/numeral": "^0.0.25"
"@types/numeral": "^0.0.25",
"umi-plugin-block-dev": "^1.1.0"
},
"blockConfig": {
"specVersion": "0.1"
......
import { CanvasMenu, ContextMenu, EdgeMenu, GroupMenu, MultiMenu, NodeMenu } from 'gg-editor';
import React from 'react';
import { NodeMenu, EdgeMenu, GroupMenu, MultiMenu, CanvasMenu, ContextMenu } from 'gg-editor';
import MenuItem from './MenuItem';
import styles from './index.less';
const FlowContextMenu = () => {
return (
const FlowContextMenu = () => (
<ContextMenu className={styles.contextMenu}>
<NodeMenu>
<MenuItem command="copy" />
......@@ -30,7 +30,6 @@ const FlowContextMenu = () => {
<MenuItem command="pasteHere" icon="paste" text="Paste Here" />
</CanvasMenu>
</ContextMenu>
);
};
);
export default FlowContextMenu;
import React from 'react';
import { Command } from 'gg-editor';
import React from 'react';
import IconFont from '../../common/IconFont';
import styles from './index.less';
const upperFirst = (str: string) => {
return str.toLowerCase().replace(/( |^)[a-z]/g, (l: string) => l.toUpperCase());
};
const upperFirst = (str: string) =>
str.toLowerCase().replace(/( |^)[a-z]/g, (l: string) => l.toUpperCase());
interface MenuItemProps {
command: string;
......
import { CanvasMenu, ContextMenu, NodeMenu } from 'gg-editor';
import React from 'react';
import { NodeMenu, CanvasMenu, ContextMenu } from 'gg-editor';
import MenuItem from './MenuItem';
import styles from './index.less';
const MindContextMenu = () => {
return (
const MindContextMenu = () => (
<ContextMenu className={styles.contextMenu}>
<NodeMenu>
<MenuItem command="append" text="Topic" />
......@@ -18,7 +18,6 @@ const MindContextMenu = () => {
<MenuItem command="redo" />
</CanvasMenu>
</ContextMenu>
);
};
);
export default MindContextMenu;
import FlowContextMenu from './FlowContextMenu';
import MindContextMenu from './MindContextMenu';
import KoniContextMenu from './KoniContextMenu';
import MindContextMenu from './MindContextMenu';
export { FlowContextMenu, MindContextMenu, KoniContextMenu };
import React, { Fragment } from 'react';
import { Card, Form, Input, Select } from 'antd';
import { withPropsAPI } from 'gg-editor';
import React, { Fragment } from 'react';
import { FormComponentProps } from 'antd/es/form';
import { withPropsAPI } from 'gg-editor';
const upperFirst = (str: string) => {
return str.toLowerCase().replace(/( |^)[a-z]/g, (l: string) => l.toUpperCase());
};
const upperFirst = (str: string) =>
str.toLowerCase().replace(/( |^)[a-z]/g, (l: string) => l.toUpperCase());
const { Item } = Form;
const { Option } = Select;
......@@ -60,15 +60,13 @@ class DetailForm extends React.Component<DetailFormProps> {
}, 0);
};
renderEdgeShapeSelect = () => {
return (
renderEdgeShapeSelect = () => (
<Select onChange={this.handleSubmit}>
<Option value="flow-smooth">Smooth</Option>
<Option value="flow-polyline">Polyline</Option>
<Option value="flow-polyline-round">Polyline Round</Option>
</Select>
);
};
renderNodeDetail = () => {
const { form } = this.props;
......
import React from 'react';
import { CanvasPanel, DetailPanel, EdgePanel, GroupPanel, MultiPanel, NodePanel } from 'gg-editor';
import { Card } from 'antd';
import { NodePanel, EdgePanel, GroupPanel, MultiPanel, CanvasPanel, DetailPanel } from 'gg-editor';
import React from 'react';
import DetailForm from './DetailForm';
import styles from './index.less';
const FlowDetailPanel = () => {
return (
const FlowDetailPanel = () => (
<DetailPanel className={styles.detailPanel}>
<NodePanel>
<DetailForm type="node" />
......@@ -23,7 +23,6 @@ const FlowDetailPanel = () => {
<Card type="inner" size="small" title="Canvas" bordered={false} />
</CanvasPanel>
</DetailPanel>
);
};
);
export default FlowDetailPanel;
import React from 'react';
import { CanvasPanel, DetailPanel, NodePanel } from 'gg-editor';
import { Card } from 'antd';
import { NodePanel, CanvasPanel, DetailPanel } from 'gg-editor';
import React from 'react';
import DetailForm from './DetailForm';
import styles from './index.less';
const MindDetailPanel = () => {
return (
const MindDetailPanel = () => (
<DetailPanel className={styles.detailPanel}>
<NodePanel>
<DetailForm type="node" />
......@@ -14,7 +14,6 @@ const MindDetailPanel = () => {
<Card type="inner" size="small" title="Canvas" bordered={false} />
</CanvasPanel>
</DetailPanel>
);
};
);
export default MindDetailPanel;
import FlowDetailPanel from './FlowDetailPanel';
import MindDetailPanel from './MindDetailPanel';
import KoniDetailPanel from './KoniDetailPanel';
import MindDetailPanel from './MindDetailPanel';
export { FlowDetailPanel, MindDetailPanel, KoniDetailPanel };
import React from 'react';
import { Item, ItemPanel } from 'gg-editor';
import { Card } from 'antd';
import { ItemPanel, Item } from 'gg-editor';
import React from 'react';
import styles from './index.less';
const FlowItemPanel = () => {
return (
const FlowItemPanel = () => (
<ItemPanel className={styles.itemPanel}>
<Card bordered={false}>
<Item
......@@ -49,7 +49,6 @@ const FlowItemPanel = () => {
/>
</Card>
</ItemPanel>
);
};
);
export default FlowItemPanel;
import React from 'react';
import { Item, ItemPanel } from 'gg-editor';
import { Card } from 'antd';
import { ItemPanel, Item } from 'gg-editor';
import React from 'react';
import styles from './index.less';
const KoniItemPanel = () => {
return (
const KoniItemPanel = () => (
<ItemPanel className={styles.itemPanel}>
<Card bordered={false}>
<Item
......@@ -48,7 +48,6 @@ const KoniItemPanel = () => {
/>
</Card>
</ItemPanel>
);
};
);
export default KoniItemPanel;
import React from 'react';
import { Card } from 'antd';
import { Minimap } from 'gg-editor';
import React from 'react';
const EditorMinimap = () => {
return (
const EditorMinimap = () => (
<Card type="inner" size="small" title="Minimap" bordered={false}>
<Minimap height={200} />
</Card>
);
};
);
export default EditorMinimap;
import React from 'react';
import { Divider } from 'antd';
import React from 'react';
import { Toolbar } from 'gg-editor';
import ToolbarButton from './ToolbarButton';
import styles from './index.less';
const FlowToolbar = () => {
return (
const FlowToolbar = () => (
<Toolbar className={styles.toolbar}>
<ToolbarButton command="undo" />
<ToolbarButton command="redo" />
......@@ -26,7 +25,6 @@ const FlowToolbar = () => {
<ToolbarButton command="addGroup" icon="group" text="Add Group" />
<ToolbarButton command="unGroup" icon="ungroup" text="Ungroup" />
</Toolbar>
);
};
);
export default FlowToolbar;
import React from 'react';
import { Divider } from 'antd';
import React from 'react';
import { Toolbar } from 'gg-editor';
import ToolbarButton from './ToolbarButton';
import styles from './index.less';
const FlowToolbar = () => {
return (
const FlowToolbar = () => (
<Toolbar className={styles.toolbar}>
<ToolbarButton command="undo" />
<ToolbarButton command="redo" />
......@@ -21,7 +20,6 @@ const FlowToolbar = () => {
<ToolbarButton command="collapse" text="Fold" />
<ToolbarButton command="expand" text="Unfold" />
</Toolbar>
);
};
);
export default FlowToolbar;
import { Command } from 'gg-editor';
import React from 'react';
import { Tooltip } from 'antd';
import { Command } from 'gg-editor';
import IconFont from '../../common/IconFont';
import styles from './index.less';
const upperFirst = (str: string) => {
return str.toLowerCase().replace(/( |^)[a-z]/g, (l: string) => l.toUpperCase());
};
const upperFirst = (str: string) =>
str.toLowerCase().replace(/( |^)[a-z]/g, (l: string) => l.toUpperCase());
interface ToolbarButtonProps {
command: string;
......
import FlowToolbar from './FlowToolbar';
import MindToolbar from './MindToolbar';
import KoniToolbar from './KoniToolbar';
import MindToolbar from './MindToolbar';
export { FlowToolbar, MindToolbar, KoniToolbar };
import React from 'react';
import { Row, Col } from 'antd';
import { Col, Row } from 'antd';
import GGEditor, { Flow } from 'gg-editor';
import { PageHeaderWrapper } from '@ant-design/pro-layout';
import React from 'react';
import { formatMessage } from 'umi-plugin-react/locale';
import EditorMinimap from './components/EditorMinimap';
import { FlowContextMenu } from './components/EditorContextMenu';
import { FlowToolbar } from './components/EditorToolbar';
import { FlowItemPanel } from './components/EditorItemPanel';
import { FlowDetailPanel } from './components/EditorDetailPanel';
import { FlowItemPanel } from './components/EditorItemPanel';
import { FlowToolbar } from './components/EditorToolbar';
import styles from './index.less';
import { PageHeaderWrapper } from '@ant-design/pro-layout';
import { formatMessage } from 'umi-plugin-react/locale';
GGEditor.setTrackable(false);
export default () => {
return (
export default () => (
<PageHeaderWrapper
content={formatMessage({
id: 'BLOCK_NAME.description',
......@@ -41,5 +41,4 @@ export default () => {
<FlowContextMenu />
</GGEditor>
</PageHeaderWrapper>
);
};
);
......@@ -7,6 +7,7 @@ flow
```sh
umi block add ant-design-pro/flow
```
## SNAPSHOT
![SNAPSHOT](./snapshot.png)
......
......@@ -12,6 +12,7 @@
"dev": "umi dev"
},
"dependencies": {
"@ant-design/pro-layout": "^4.5.5",
"@antv/data-set": "^0.10.2",
"antd": "^3.16.3",
"bizcharts": "^3.5.3-beta.0",
......@@ -22,13 +23,14 @@
"numeral": "^2.0.6",
"react": "^16.6.3",
"react-fittext": "^1.0.0",
"umi-request": "^1.0.0"
"umi-request": "^1.0.0",
"umi-plugin-react": "^1.7.2",
"umi-plugin-block-dev": "^1.1.0"
},
"devDependencies": {
"umi": "^2.6.9",
"umi-plugin-block-dev": "^1.1.0",
"umi-plugin-react": "^1.7.2",
"@types/numeral": "^0.0.25"
"@types/numeral": "^0.0.25",
"umi": "^2.6.9"
},
"blockConfig": {
"specVersion": "0.1"
......
import { CanvasMenu, ContextMenu, EdgeMenu, GroupMenu, MultiMenu, NodeMenu } from 'gg-editor';
import React from 'react';
import { NodeMenu, EdgeMenu, GroupMenu, MultiMenu, CanvasMenu, ContextMenu } from 'gg-editor';
import MenuItem from './MenuItem';
import styles from './index.less';
const FlowContextMenu = () => {
return (
const FlowContextMenu = () => (
<ContextMenu className={styles.contextMenu}>
<NodeMenu>
<MenuItem command="copy" />
......@@ -30,7 +30,6 @@ const FlowContextMenu = () => {
<MenuItem command="pasteHere" icon="paste" text="Paste Here" />
</CanvasMenu>
</ContextMenu>
);
};
);
export default FlowContextMenu;
import React from 'react';
import { Command } from 'gg-editor';
import React from 'react';
import IconFont from '../../common/IconFont';
import styles from './index.less';
const upperFirst = (str: string) => {
return str.toLowerCase().replace(/( |^)[a-z]/g, (l: string) => l.toUpperCase());
};
const upperFirst = (str: string) =>
str.toLowerCase().replace(/( |^)[a-z]/g, (l: string) => l.toUpperCase());
interface MenuItemProps {
command: string;
......
import { CanvasMenu, ContextMenu, NodeMenu } from 'gg-editor';
import React from 'react';
import { NodeMenu, CanvasMenu, ContextMenu } from 'gg-editor';
import MenuItem from './MenuItem';
import styles from './index.less';
const MindContextMenu = () => {
return (
const MindContextMenu = () => (
<ContextMenu className={styles.contextMenu}>
<NodeMenu>
<MenuItem command="append" text="Topic" />
......@@ -18,7 +18,6 @@ const MindContextMenu = () => {
<MenuItem command="redo" />
</CanvasMenu>
</ContextMenu>
);
};
);
export default MindContextMenu;
import FlowContextMenu from './FlowContextMenu';
import MindContextMenu from './MindContextMenu';
import KoniContextMenu from './KoniContextMenu';
import MindContextMenu from './MindContextMenu';
export { FlowContextMenu, MindContextMenu, KoniContextMenu };
import React, { Fragment } from 'react';
import { Card, Form, Input, Select } from 'antd';
import { withPropsAPI } from 'gg-editor';
import React, { Fragment } from 'react';
import { FormComponentProps } from 'antd/es/form';
import { withPropsAPI } from 'gg-editor';
const upperFirst = (str: string) => {
return str.toLowerCase().replace(/( |^)[a-z]/g, (l: string) => l.toUpperCase());
};
const upperFirst = (str: string) =>
str.toLowerCase().replace(/( |^)[a-z]/g, (l: string) => l.toUpperCase());
const { Item } = Form;
const { Option } = Select;
......@@ -60,15 +60,13 @@ class DetailForm extends React.Component<DetailFormProps> {
}, 0);
};
renderEdgeShapeSelect = () => {
return (
renderEdgeShapeSelect = () => (
<Select onChange={this.handleSubmit}>
<Option value="flow-smooth">Smooth</Option>
<Option value="flow-polyline">Polyline</Option>
<Option value="flow-polyline-round">Polyline Round</Option>
</Select>
);
};
renderNodeDetail = () => {
const { form } = this.props;
......
import React from 'react';
import { CanvasPanel, DetailPanel, EdgePanel, GroupPanel, MultiPanel, NodePanel } from 'gg-editor';
import { Card } from 'antd';
import { NodePanel, EdgePanel, GroupPanel, MultiPanel, CanvasPanel, DetailPanel } from 'gg-editor';
import React from 'react';
import DetailForm from './DetailForm';
import styles from './index.less';
const FlowDetailPanel = () => {
return (
const FlowDetailPanel = () => (
<DetailPanel className={styles.detailPanel}>
<NodePanel>
<DetailForm type="node" />
......@@ -23,7 +23,6 @@ const FlowDetailPanel = () => {
<Card type="inner" size="small" title="Canvas" bordered={false} />
</CanvasPanel>
</DetailPanel>
);
};
);
export default FlowDetailPanel;
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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