Skip to content

Commit

Permalink
feat(result): add component result (#2006)
Browse files Browse the repository at this point in the history
* feat(result): add component result

* feat(result): add component result

* feat(result): add component result & replace page to result
  • Loading branch information
gavin-hao committed May 10, 2022
1 parent 8582665 commit 2d81a37
Show file tree
Hide file tree
Showing 34 changed files with 2,794 additions and 37 deletions.
19 changes: 8 additions & 11 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,22 @@
"source.fixAll.eslint": true,
"source.fixAll.stylelint": true
},

//eslint -----settings start-----

"eslint.packageManager": "yarn",
"eslint.validate": ["javascript", "javascriptreact", "typescript", "typescriptreact"],

"eslint.validate": [
"javascript",
"javascriptreact",
"typescript",
"typescriptreact"
],
//eslint -----settings end-----

//prettier -----settings start-----

"prettier.useEditorConfig": false,
"prettier.requireConfig": true,

"prettier.configPath": "prettier.config.js",
//prettier -----settings end-----
//pretier -----settings end-----

//stylelint -----settings start-----

// 防止编辑器内置linter与插件冲突设置
"css.validate": false,
"less.validate": false,
Expand All @@ -46,6 +44,5 @@
"svelte"
],
"typescript.tsdk": "node_modules/typescript/lib"

//stylelint -----settings end-----
}
}
2 changes: 1 addition & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export { default as List, ListProps } from './list';
export { default as Loading, LoadingProps } from './loading';
export { default as Menu, MenuProps, SubMenuProps, MenuItemProps, MenuMode } from './menu';
export { default as Modal, ModalProps } from './modal';
export { default as Page, PageProps } from './page';
export { default as Result, ResultProps } from './result';
export { default as Pagination, PaginationProps } from './pagination';
export { default as PopConfirm, PopConfirmProps } from './pop-confirm';
export { default as Popover, PopoverProps } from './popover';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import BasePicker from './components/base-picker';
import { PropertyPickerProps, PropertyTypes, PropertyItem, PropertyValue, PropertyInfo } from './interfaces';
import List from './components/list';
import { ListItemProps } from './components/list/interfaces';
import Page from '../../../../page'; // new
import Result from '../../../../result'; // new
import { renderExpandableItems } from './components/list/utils';
import PropertyCard from './PropertyCard';
import './style';
Expand Down Expand Up @@ -305,7 +305,7 @@ const PropertyPicker: React.FC<PropertyPickerProps> = (props: PropertyPickerProp
}
const renderItems = () => {
if (propertyItems?.length === 0) {
return <Page type="noData" size="small" />;
return <Result type="empty-result" size="small" />;
}
const recentlyNodes = recentlyPropertyItems?.length > 0 && (
<React.Fragment key="recentlyNodes">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* eslint-disable react/no-array-index-key */
import React from 'react';
import classnames from 'classnames';
import Page from '../../../../../../page';
import Result from '../../../../../../result';
import ItemGroup from './ItemGroup';
import ItemSubgroup from './ItemSubgroup';
import Item from './Item';
Expand All @@ -27,7 +27,7 @@ function InternalList({ className, style, children, items, expandable = false }:
} else if (children) {
content = children;
} else {
content = <Page size="small" type="noData" />;
content = <Result size="small" type="empty" />;
}

const cls = classnames(useRootPrefixCls(), className);
Expand Down
4 changes: 2 additions & 2 deletions src/list-picker/demos/List-picker.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import Tabs, { Tab } from '../../tabs';
import List from '../../list';
import Recent from '../Recent';
import Docs from './List-pickerPage';
import { Card, Divider, Popover, Skeleton, Table, Tag, Page } from '../..';
import { Card, Divider, Popover, Skeleton, Table, Tag, Result } from '../..';

interface Tmesurements {
id: string;
Expand Down Expand Up @@ -363,7 +363,7 @@ export const Default: Story<ListPickerProps> = (args: ListPickerProps) => {
<List
style={{ width: '240px' }}
options={[]}
empty={<Page type="noFind" description="暂无数据" size="small" />}
empty={<Result type="empty-data" description="暂无数据" size="small" />}
/>
</Tab>
</Tabs>
Expand Down
4 changes: 2 additions & 2 deletions src/list/Empty.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useLocale } from '@gio-design/utils';
import React from 'react';
import Page from '../page';
import Result from '../result';
import { collectOptions } from './util';
import defaultLocaleTextObject from './locales/zh-CN';

Expand All @@ -15,7 +15,7 @@ const Empty: React.FC<EmptyProps> = ({ children, emptyNode }) => {
if (options.length === 0) {
return (
<div style={{ width: '100%', padding: '30px 0' }}>
{emptyNode ?? <Page type="noData" description={localeTextObject.exptyText} size="small" />}
{emptyNode ?? <Result type="empty-data" title description={localeTextObject.exptyText} size="small" />}
</div>
);
}
Expand Down
4 changes: 4 additions & 0 deletions src/locales/en-US.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import listLocale from '../list/locales/en-US';
import basePickerLocale from '../legacy/filter-picker/components/property-selector/components/base-picker/locales/en-US';
import propertyPickerLocale from '../legacy/filter-picker/components/property-selector/locales/en-US';
import popConfirmLocale from '../pop-confirm/locales/en-US';
import resultLocale from '../result/locales/en-US';

export const locale: Locale = {
code: 'en-US',
Expand All @@ -29,6 +30,9 @@ export const locale: Locale = {
Page: {
...pageLocale,
},
Result: {
...resultLocale,
},
ListPicker: {
...listPickerLocale,
},
Expand Down
4 changes: 4 additions & 0 deletions src/locales/zh-CN.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import listLocale from '../list/locales/zh-CN';
import basePicker from '../legacy/filter-picker/components/property-selector/components/base-picker/locales/zh-CN';
import propertyPickerLocale from '../legacy/filter-picker/components/property-selector/locales/zh-CN';
import popConfirmLocale from '../pop-confirm/locales/zh-CN';
import resultLocale from '../result/locales/en-US';

export const locale: Locale = {
code: 'zh-CN',
Expand All @@ -29,6 +30,9 @@ export const locale: Locale = {
Page: {
...pageLocale,
},
Result: {
...resultLocale,
},
ListPicker: {
...listPickerLocale,
},
Expand Down
123 changes: 123 additions & 0 deletions src/result/Result.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
import React from 'react';
import classnames from 'classnames';
import { useLocale, usePrefixCls } from '@gio-design/utils';
import { isUndefined } from 'lodash';
import { ResultProps } from './interfaces';
import {
Forbidden,
NotFound,
Deleted,
Locked,
InternalServerError,
EmptyChart,
Empty,
EmptyData,
EmptyResult,
} from './images';
import Button from '../button';
import defaultLocale from './locales/zh-CN';
import { SizeContextProvider, SizeType } from '../utils/SizeContext';


/**
* http status codes
*/
const ExceptionImageMap = {
'404': NotFound,
'403': Forbidden,
'500': InternalServerError,
'410': Deleted,
'423': Locked
}
/**
* empty states
*/
const EmptyImageMap = {
'empty': Empty,
'empty-chart': EmptyChart,
'empty-data': EmptyData,
'empty-result': EmptyResult,
}
const TYPE_IMAGE_MAP = {
...EmptyImageMap,
...ExceptionImageMap,
};
function Result({ className: customizeClassName, style, children, extra, type = '404', image, title: propsTitle, description, cta, size = 'normal' }: ResultProps) {
const locale = useLocale('Result');
const localeContent: { [key: string]: string } = {
...defaultLocale,
...locale,
};
type TypeMapKey = keyof typeof TYPE_IMAGE_MAP;
const defaultTypeDescription: Record<TypeMapKey, string> = {
'empty-chart': localeContent.emptyChart,
'empty': localeContent.empty,
'empty-data': localeContent.emptyData,
"empty-result": localeContent.emptyResult,
"403": localeContent['403'],
"404": localeContent['404'],
"410": localeContent['410'],
"423": localeContent['423'],
"500": localeContent['500'],
};
const prefixCls = usePrefixCls('result');
const cls = classnames(prefixCls, `${prefixCls}-${size}`, { [`${prefixCls}-empty`]: Object.keys(EmptyImageMap).includes(type) }, `${prefixCls}-${type}`, customizeClassName);
// description
const defaultDesc = Object.keys(EmptyImageMap).includes(type) ? defaultTypeDescription[type] : null
const desc = !isUndefined(description) ? description : defaultDesc;

const img = image || (TYPE_IMAGE_MAP[type] ? React.createElement(TYPE_IMAGE_MAP[type]) : React.createElement(TYPE_IMAGE_MAP.empty));
// title
const defaultTitle = Object.keys(EmptyImageMap).includes(type) ? null : defaultTypeDescription[type];
const title = !isUndefined(propsTitle) ? propsTitle : defaultTitle;
// extra
const renderExtra = () => {
if (cta) {
return (<Button size={size} onClick={cta.onClick}>
{cta.text}
</Button>)
}
if (extra) {

return extra;
}
return null
}
return (
<div className={cls} style={style}>
<SizeContextProvider size={size as SizeType}>
<div className={`${prefixCls}__image ${prefixCls}__image-${type}`}>{img}</div>
<div className={`${prefixCls}__title ${prefixCls}__title-${size}`}>{title}</div>
<div className={classnames(`${prefixCls}__description`, `${prefixCls}__description-${size}`)}>{desc}</div>
<div className={`${prefixCls}__extra`}>
{renderExtra()}
</div>
{children && <div className={`${prefixCls}__content`}>{children}</div>}
</SizeContextProvider>
</div>
);
}

const ResultImage: {
ImgForbidden: React.ReactNode;
ImgNotFound: React.ReactNode;
ImgInternalServerError: React.ReactNode;
ImgDeleted: React.ReactNode;
ImgLocked: React.ReactNode;
ImgEmpty: React.ReactNode;
ImgEmptyChart: React.ReactNode;
ImgEmptyData: React.ReactNode;
ImgEmptyResult: React.ReactNode;
} = {
ImgForbidden: TYPE_IMAGE_MAP['403'],
ImgNotFound: TYPE_IMAGE_MAP['404'],
ImgInternalServerError: TYPE_IMAGE_MAP['500'],
ImgDeleted: TYPE_IMAGE_MAP['410'],
ImgLocked: TYPE_IMAGE_MAP['423'],
ImgEmpty: TYPE_IMAGE_MAP.empty,
ImgEmptyChart: TYPE_IMAGE_MAP['empty-chart'],
ImgEmptyData: TYPE_IMAGE_MAP['empty-data'],
ImgEmptyResult: TYPE_IMAGE_MAP['empty-result']
};
export { Result, ResultImage };

89 changes: 89 additions & 0 deletions src/result/demos/Result.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import { Meta, Story } from "@storybook/react/types-6-0";
import { action } from '@storybook/addon-actions';
import React from "react";
import { ArrowsLeftOutlined, ErrorFilled, ErrorOutlined, ReloadOutlined } from "@gio-design/icons";
import Result, { ResultProps } from "..";
import { Button, Card, Link } from "../..";
import Docs from './ResultPage'
import '../style'

export default {
title: 'upgraded/Result',
component: Result,
parameters: {
docs: {
page: Docs,
},
argTypes: {
description: {
control: { type: 'text' },
},
},
design: {
type: 'figma',
url: 'https://www.figma.com/file/kP3A6S2fLUGVVMBgDuUx0f/GIO-Design?node-id=4093%3A45839',
allowFullscreen: true,
},
},
} as Meta;
const DefaultTemplate: Story<ResultProps> = (args) => <Result {...args} />;
export const Default = DefaultTemplate.bind({});
Default.args = {
type: 'empty',
extra: <Button type="primary" >返回首页</Button>
}

export const NotFound = () => <Result type="404" extra={<Button prefix={<ArrowsLeftOutlined />} type="primary">Back Home</Button>} />;

export const Unauthorized = () => <Result type="403" extra={<Button type="primary" >返回首页</Button>} />;

export const ServerError = () => <Result type="500" title="Oooops!!!" description="Sorry, something went wrong." extra={<Button type="primary" prefix={<ArrowsLeftOutlined />}>返回首页</Button>} />;

export const Error = () => <Result

image={<ErrorFilled color="#ff688f" size="64" />}
title="Submission Failed"
description="Please check and modify the following information before resubmitting."
extra={<><Button type="primary" >Submit Again</Button><Button type="secondary">Back to list</Button></>}
>
<div className="error-list">
<div>
<h3 style={{ fontSize: '16px', lineHeight: '24px' }}>
The content you submitted has the following error:
</h3>
</div>
<p style={{ color: '#7b819c' }}>
<ErrorOutlined style={{ color: '#ff688f', marginRight: '8px' }} />
Verification fails and does not meet the template specifications. Please refill the template.
<Link href="#;">Reselect &gt;</Link>
</p>
<p style={{ color: '#7b819c' }}>
<ErrorOutlined style={{ color: '#ff688f', marginRight: '8px' }} />
Verification fails and does not meet the template specifications. Please refill the template.
<Link href="#;">Reselect &gt;</Link>
</p>
</div>
</Result>

export const Deleted: Story<ResultProps> = () => <Result type="410" title={<div>该单图已删除<Link style={{ marginLeft: '8px' }} href="#;" onClick={() => action('onClick:从当前看板中移除')}>从当前看板中移除</Link></div>} />;

export const Locked: Story<ResultProps> = () => <Result type="423" title="" extra={<div>此看板已取消与你共享<Link style={{ marginLeft: '8px' }} href="#;" onClick={() => action('onClick:取消订阅')}>取消订阅</Link></div>} />;

export const EmptyResult: Story<ResultProps> = () => <Result type="empty-result" description="没有搜索到相关结果" extra={<Button onClick={() => action('onClick:重新查询')}>重新查询</Button>} />;

export const Empty: Story<ResultProps> = () => <Result type="empty" description="你还没有创建内容,快去创建一个吧" extra={<Button onClick={() => action('onClick:新 建')}>新 建</Button>} />;

export const EmptyChart: Story<ResultProps> = () => <Result type="empty-chart" description="你还没有属于自己的看板,快去新建一个吧" extra={<Button onClick={() => action('onClick:新建看板')}>新建看板</Button>} />;

export const EmptyData: Story<ResultProps> = () => <Result type="empty-chart" description="当前查询条件下暂无数据" extra={<Button prefix={<ReloadOutlined />} onClick={() => action('onClick:刷新')}>刷新</Button>} />;

export const EmptySmallSize = () => <div>
<Card style={{ width: '320px' }}>
<Result type="empty" size="small" description="未创建相关内容" extra={<Button size="small" onClick={() => action('onClick:新 建')}>新 建</Button>} />
</Card>
</div>
export const ErrorPageSmallSize = () => <div>
<Card style={{ width: '320px' }}>
<Result type="410" size="small" title description extra={<div>该单图已删除<Link style={{ marginLeft: '8px' }} href="#;" onClick={() => action('onClick:从当前看板中移除')}>从当前看板中移除</Link></div>} />
</Card>
</div>

1 comment on commit 2d81a37

@vercel
Copy link

@vercel vercel bot commented on 2d81a37 May 10, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

gio-design – ./

gio-design-growingio.vercel.app
gio-design.vercel.app
gio-design-git-master-growingio.vercel.app

Please sign in to comment.