@ant-design/icons#LeftOutlined TypeScript Examples
The following examples show how to use
@ant-design/icons#LeftOutlined.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: Storage.tsx From whiteboard-demo with MIT License | 6 votes |
private renderHeadView(downloader: DownloadLogic): React.ReactNode {
const { t } = this.props
const shouldDisplaySpaceTag = (
typeof this.state.space === "number" &&
typeof this.state.availableSpace === "number"
);
return (
<div className="page-history-head">
<div className="page-history-head-left">
<Link to={"/"}>
<div className="page-history-back">
<LeftOutlined /> <div>{t('back')}</div>
</div>
</Link>
{shouldDisplaySpaceTag && <Tag
color={"blue"}
style={{marginLeft: 8}}>{this.state.space}(mb) / {this.state.availableSpace}(mb)
</Tag>}
</div>
<div>
{this.renderAddTaskButton(downloader)}
{this.renderDownloadOneByOneButton(downloader)}
{this.renderCleanAllCacheButton(downloader)}
</div>
</div>
);
}
Example #2
Source File: ProviderGroupMenu.spec.tsx From next-basics with GNU General Public License v3.0 | 6 votes |
describe("ProviderGroupMenu", () => {
it("should work", () => {
const props = {
itemList: [
"providers-of-admin.nameservice-api-list-name-service",
"providers-of-admin.agent-management-api-get-agent-status",
"providers-of-admin.nameservice-api-get-name-service",
],
onFold: jest.fn(),
};
const wrapper = shallow(<ProviderGroupMenu {...props} />);
expect(wrapper.find(".item").length).toEqual(3);
expect(wrapper.find(LeftOutlined).length).toEqual(0);
wrapper.find(".customIcon").invoke("onClick")(null);
wrapper.update();
expect(wrapper.find(LeftOutlined).length).toEqual(1);
});
});
Example #3
Source File: HistoryPage.tsx From whiteboard-demo with MIT License | 6 votes |
public render(): React.ReactNode {
const { t } = this.props
return (
<div className="page-index-box">
<FloatLink />
<div className="page-index-mid-box">
<div className="page-history-head">
<Link to={"/"}>
<div className="page-history-back">
<LeftOutlined /> <div>{t('back')}</div>
</div>
</Link>
<Button
type="link"
size={"small"}
style={{ marginRight: 20, fontSize: 14 }}
onClick={() => {
localStorage.removeItem("rooms");
this.setState({ rooms: [] });
}}
>
{t('clear')}
</Button>
</div>
{this.state.rooms.length === 0 ? (
<div className="page-history-body-empty">
<img src={empty_box} alt={"empty_box"} />
</div>
) : (
<div className="page-history-body">{this.renderCells()}</div>
)}
</div>
</div>
);
}
Example #4
Source File: ProviderGroupMenu.tsx From next-basics with GNU General Public License v3.0 | 6 votes |
export function ProviderGroupMenu(
props: ProviderGroupMenuProps
): React.ReactElement {
const { itemList, onFold, containerStyle = {} } = props;
const [fold, setFold] = useState(false);
const handleClick = (): void => {
const curFold = !fold;
setFold(curFold);
onFold?.(curFold);
};
return (
<div style={{ position: "relative" }}>
<span
onClick={handleClick}
className={classNames(styles.customIcon, { [styles.fasten]: fold })}
>
{fold ? <LeftOutlined /> : <RightOutlined />}
</span>
<div
className={styles.container}
style={{
display: fold ? "none" : "block",
...containerStyle,
}}
>
{itemList?.map((name) => (
<div key={name} className={styles.itemWrapper} title={name}>
<HashLink to={`#${name}`} className={styles.item}>
{name}
</HashLink>
</div>
))}
</div>
</div>
);
}
Example #5
Source File: index.tsx From dashboard with Apache License 2.0 | 6 votes |
MemberDetailInfo = (props: any) => {
console.log(props.location.query)
return (
<PageContainer
onBack={() => history.goBack()}
backIcon={<LeftOutlined />}
header={{
title: '成员详情',
}}
>
</PageContainer>
)
}
Example #6
Source File: DesktopSideNav.tsx From condo with MIT License | 5 votes |
DesktopSideNav: React.FC<ISideNavProps> = (props) => {
const { onLogoClick, menuData } = props
const { link } = useOrganization()
const { isSmall, toggleCollapsed, isCollapsed } = useLayoutContext()
const isEmployeeBlocked = get(link, 'isBlocked', false)
if (isEmployeeBlocked) {
return null
}
// TODO: (Dimitreee) implement mobile nav later
if (isSmall) {
return null
}
return (
<>
<Layout.Sider
collapsed={isCollapsed}
theme='light'
css={SIDE_NAV_STYLES}
width={SIDE_MENU_WIDTH}
collapsedWidth={COLLAPSED_SIDE_MENU_WIDTH}
>
<LogoContainer>
<Logo onClick={onLogoClick} minified={isCollapsed}/>
</LogoContainer>
<LayoutTriggerWrapper>
<Button
onClick={toggleCollapsed}
size={'small'}
shape={'circle'}
icon={isCollapsed ? <RightOutlined style={{ fontSize: '13px' }} /> : <LeftOutlined style={{ fontSize: '13px' }}/>}
/>
</LayoutTriggerWrapper>
<ActionsContainer minified={isCollapsed}>
<ResidentActions minified={isCollapsed}/>
</ActionsContainer>
<MenuItemsContainer>
{menuData}
</MenuItemsContainer>
<ServiceSubscriptionIndicator/>
</Layout.Sider>
<Layout.Sider
collapsed={isCollapsed}
width={SIDE_MENU_WIDTH}
collapsedWidth={COLLAPSED_SIDE_MENU_WIDTH}
/>
</>
)
}
Example #7
Source File: create.tsx From dashboard with Apache License 2.0 | 5 votes |
CreateContactWay: React.FC = () => {
const [allStaffs, setAllStaffs] = useState<StaffOption[]>([]);
const [allTagGroups, setAllTagGroups] = useState<CustomerTagGroupItem[]>([]);
useEffect(() => {
QueryCustomerTagGroups({page_size: 5000}).then((res) => {
if (res.code === 0) {
setAllTagGroups(res?.data?.items);
} else {
message.error(res.message);
}
});
}, []);
useEffect(() => {
QuerySimpleStaffs({ page_size: 5000 }).then((res) => {
if (res.code === 0) {
setAllStaffs(
res?.data?.items?.map((item: SimpleStaffInterface) => {
return {
label: item.name,
value: item.ext_id,
...item,
};
}) || [],
);
} else {
message.error(res.message);
}
});
}, []);
return (
<PageContainer
onBack={() => history.goBack()}
backIcon={<LeftOutlined />}
header={{
title: '创建渠道活码',
}}
>
<ProCard>
<ContactWayForm
mode={'create'}
onFinish={async (values) => {
const params = { ...values };
const hide = message.loading('处理中');
const res: CommonResp = await Create(params);
hide();
if (res.code === 0) {
history.push('/staff-admin/customer-growth/contact-way');
message.success('添加成功');
return true;
}
if (res.message) {
message.error(res.message);
return false;
}
message.error('添加失败');
return false;
}}
staffs={allStaffs}
tagGroups={allTagGroups}
/>
</ProCard>
</PageContainer>
);
}
Example #8
Source File: index.tsx From fe-v5 with Apache License 2.0 | 5 votes |
LeftTree: React.FC<LeftTreeProps> = ({ clusterGroup = {}, busiGroup = {}, eventLevelGroup = {}, eventTypeGroup = {} }) => {
const history = useHistory();
const [collapse, setCollapse] = useState(localStorage.getItem('leftlist') === '1');
const groupItems: IGroupItemProps[] = [
clustersGroupContent(clusterGroup),
busiGroupContent(busiGroup),
{
title: '事件级别',
isShow: eventLevelGroup.isShow,
render() {
return (
<SelectList
dataSource={[
{ label: '一级告警', value: 1 },
{ label: '二级告警', value: 2 },
{ label: '三级告警', value: 3 },
]}
defaultSelect={eventLevelGroup.defaultSelect}
allowNotSelect={true}
onChange={eventLevelGroup?.onChange}
/>
);
},
},
{
title: '事件类别',
isShow: eventTypeGroup.isShow,
render() {
return (
<SelectList
dataSource={[
{ label: 'Triggered', value: 0 },
{ label: 'Recovered', value: 1 },
]}
defaultSelect={eventTypeGroup.defaultSelect}
allowNotSelect={true}
onChange={eventTypeGroup?.onChange}
/>
);
},
},
];
return (
<div className={collapse ? 'left-area collapse' : 'left-area'}>
<div
className='collapse-btn'
onClick={() => {
localStorage.setItem('leftlist', !collapse ? '1' : '0');
setCollapse(!collapse);
}}
>
{!collapse ? <LeftOutlined /> : <RightOutlined />}
</div>
{/* 遍历渲染左侧栏内容 */}
{groupItems.map(
({ title, isShow, shrink = false, render }: IGroupItemProps, i) =>
isShow && (
<div key={i} className={`left-area-group ${shrink ? 'group-shrink' : ''}`} style={typeof shrink === 'object' ? shrink.style : {}}>
<div className='left-area-group-title'>
{title}
{title === '业务组' && <SettingOutlined onClick={() => history.push(`/busi-groups`)} />}
</div>
{render()}
</div>
),
)}
</div>
);
}
Example #9
Source File: create.tsx From dashboard with Apache License 2.0 | 5 votes |
CreateCustomerMassMsg: React.FC = () => {
const [currentCustomerMassMsg] = useState<CustomerMassMsgItem>();
const formRef = useRef<FormInstance>();
return (
<PageContainer
onBack={() => history.goBack()}
backIcon={<LeftOutlined />}
header={{
title: '创建群发',
}}
>
<ProCard>
<CustomerMassMsgForm
formRef={formRef}
mode={'create'}
onFinish={async (values) => {
const params = { ...values };
const hide = message.loading('处理中');
const res: CommonResp = await Create(params);
hide();
if (res.code === 0) {
history.push('/staff-admin/customer-conversion/customer-mass-msg');
message.success('添加成功');
return true;
}
if (res.message) {
message.error(res.message);
return false;
}
message.error('添加失败');
return false;
}}
initialValues={currentCustomerMassMsg}
/>
</ProCard>
</PageContainer>
);
}
Example #10
Source File: SecondaryList.tsx From ant-simple-draw with MIT License | 5 votes |
SecondaryList: FC<SecondaryListType> = memo(({ data, fatherData }) => {
const [oneModuleAll, setOneModuleAll] = useSetState<oneModuleAllType>({
isShow: false,
componentInfo: {},
});
return (
<>
<div
className={styles.contentContainer}
style={{
display: !oneModuleAll.isShow ? 'block' : 'none',
}}
>
{data.map((child, k) => (
<React.Fragment key={k}>
<>
<div className={styles.head}>
<h2 className={styles.title}>{child.title}</h2>
<button
className={styles.more}
onClick={() => setOneModuleAll({ isShow: true, componentInfo: child })}
>
<span>全部</span>
<RightOutlined />
</button>
</div>
<Drag list={child.componentList} category={fatherData.category} />
</>
</React.Fragment>
))}
</div>
<div
className={styles.contentContainer}
style={{
display: oneModuleAll.isShow ? 'block' : 'none',
}}
>
<div className={styles.moreList}>
<button className={styles.more} onClick={() => setOneModuleAll({ isShow: false })}>
<LeftOutlined />
<span>{oneModuleAll.componentInfo.title}</span>
</button>
<Drag list={oneModuleAll.componentInfo.componentList!} category={fatherData.category} />
</div>
</div>
</>
);
})
Example #11
Source File: GeneralCarousel.tsx From next-basics with GNU General Public License v3.0 | 5 votes |
export function GeneralCarousel({
speed,
slidesToShow,
slidesToScroll,
autoplay,
dots,
components,
carouselStyle,
pauseOnDotsHover,
adaptiveHeight,
infinite,
responsive,
onHandleClick,
noDataDesc,
arrows,
dotsTheme,
useBrick,
dataSource,
autoplaySpeed,
}: GeneralCarouselProps): React.ReactElement {
const comps = Array.isArray(components) ? components : compact([components]);
const data = Array.isArray(dataSource) ? dataSource : compact([dataSource]);
const carousel = (
<Carousel
className={classNames({
"carousel-dots-dark": dotsTheme === "dark",
})}
style={carouselStyle}
autoplay={autoplay}
dots={dots}
speed={speed}
autoplaySpeed={autoplaySpeed}
slidesToShow={slidesToShow}
slidesToScroll={slidesToScroll}
pauseOnDotsHover={pauseOnDotsHover}
arrows={arrows}
infinite={infinite}
adaptiveHeight={adaptiveHeight}
responsive={responsive}
prevArrow={<LeftOutlined />}
nextArrow={<RightOutlined />}
>
{useBrick
? renderCustomBrick(useBrick, data, onHandleClick)
: renderCustomComp(comps, onHandleClick)}
</Carousel>
);
return (
<div className={style.generalCarousel}>
{useBrick ? (
data.length !== 0 ? (
carousel
) : (
<Empty description={noDataDesc} />
)
) : comps.length !== 0 ? (
carousel
) : (
<Empty description={noDataDesc} />
)}
</div>
);
}
Example #12
Source File: EditorHeader.tsx From datart with Apache License 2.0 | 5 votes |
EditorHeader: FC = memo(({ children }) => {
const dispatch = useDispatch();
const history = useHistory();
const t = useI18NPrefix(`viz.action`);
const { updateBoard } = useContext(BoardActionContext);
const { onEditClearActiveWidgets } = useContext(WidgetActionContext);
const { name, status } = useContext(BoardContext);
const { saving } = useContext(BoardInfoContext);
const title = useStatusTitle(name, status);
const onCloseBoardEditor = () => {
const pathName = history.location.pathname;
const prePath = pathName.split('/boardEditor')[0];
history.push(`${prePath}`);
dispatch(clearEditBoardState());
};
const onUpdateBoard = () => {
onEditClearActiveWidgets();
setImmediate(() => {
updateBoard?.(onCloseBoardEditor);
});
};
return (
<Wrapper onClick={onEditClearActiveWidgets}>
<h1 className={classnames({ disabled: status < 2 })}>
<LeftOutlined onClick={onCloseBoardEditor} />
{title}
</h1>
<Space>
{children}
<>
<Button
key="cancel"
icon={<CloseOutlined />}
onClick={onCloseBoardEditor}
>
{t('common.cancel')}
</Button>
<Button
key="update"
type="primary"
loading={saving}
icon={<SaveOutlined />}
onClick={onUpdateBoard}
>
{t('common.save')}
</Button>
</>
</Space>
</Wrapper>
);
})
Example #13
Source File: Pagination.tsx From wildduck-ui with MIT License | 5 votes |
Pagination: React.FC<IPagination> = ({
limit,
previous,
next,
page,
setLimit,
setPrevious,
setNext,
setPage,
}: IPagination) => {
return (
<Space>
<Tooltip title={'Previous'}>
<Button
className='ant-btn-icon'
disabled={_.isEmpty(previous)}
onClick={() => {
setPrevious(previous);
setPage(Math.max(page - 1, 1));
}}
>
<LeftOutlined className='blue-color' />
</Button>
</Tooltip>
<Select
style={{ width: 120 }}
defaultValue={limit}
onSelect={(value) => {
setLimit(value);
}}
>
{_.map([10, 20, 30, 50, 100, 250], (value) => (
<Select.Option key={value} value={value}>
{value + ' / page'}
</Select.Option>
))}
</Select>
<Tooltip title={'Next'}>
<Button
className='ant-btn-icon'
disabled={_.isEmpty(next)}
onClick={() => {
setNext(next);
setPage(page + 1);
}}
>
<RightOutlined className='blue-color' />
</Button>
</Tooltip>
</Space>
);
}
Example #14
Source File: header-renderer.tsx From electron-playground with MIT License | 5 votes |
AnchorRender = () => {
const [show, setShow] = useState<boolean>(false)
useEffect(() => {
return () => {
TOC = []
}
}, [])
const handleAnchor = (
e: React.MouseEvent<HTMLElement>,
link: { title: React.ReactNode; href: string },
) => {
const dom = document.getElementById(link.href)
if (dom) {
dom.scrollIntoView({ behavior: 'smooth' })
dom.scrollTop -= 60
}
e.preventDefault()
}
return (
<>
<div className={style.contents} onMouseOver={() => setShow(true)}>
<LeftOutlined className={style.icon} />
目录
</div>
<Drawer title={null} placement='right' closable={false} mask={false} visible={show}>
<div onMouseLeave={() => setShow(false)} style={{height:'100%'}}>
<Anchor onClick={handleAnchor} bounds={0}>
{TOC.map(({ content, level }) => (
<div key={content} style={{ marginLeft: (level - 1) * 10 }}>
<Link href={content} title={content} key={content} />
</div>
))}
</Anchor>
</div>
</Drawer>
</>
)
}
Example #15
Source File: Icon.tsx From html2sketch with MIT License | 4 votes |
IconSymbol: FC = () => {
return (
<Row>
{/*<CaretUpOutlined*/}
{/* className="icon"*/}
{/* symbolName={'1.General/2.Icons/1.CaretUpOutlined'}*/}
{/*/>*/}
{/* className="icon"*/}
{/* symbolName={'1.General/2.Icons/2.MailOutlined'}*/}
{/*/>*/}
{/*<StepBackwardOutlined*/}
{/* className="icon"*/}
{/* symbolName={'1.General/2.Icons/2.StepBackwardOutlined'}*/}
{/*/>*/}
{/*<StepForwardOutlined*/}
{/* className="icon"*/}
{/* symbolName={'1.General/2.Icons/2.StepBackwardOutlined'}*/}
{/*/>*/}
<StepForwardOutlined />
<ShrinkOutlined />
<ArrowsAltOutlined />
<DownOutlined />
<UpOutlined />
<LeftOutlined />
<RightOutlined />
<CaretUpOutlined />
<CaretDownOutlined />
<CaretLeftOutlined />
<CaretRightOutlined />
<VerticalAlignTopOutlined />
<RollbackOutlined />
<FastBackwardOutlined />
<FastForwardOutlined />
<DoubleRightOutlined />
<DoubleLeftOutlined />
<VerticalLeftOutlined />
<VerticalRightOutlined />
<VerticalAlignMiddleOutlined />
<VerticalAlignBottomOutlined />
<ForwardOutlined />
<BackwardOutlined />
<EnterOutlined />
<RetweetOutlined />
<SwapOutlined />
<SwapLeftOutlined />
<SwapRightOutlined />
<ArrowUpOutlined />
<ArrowDownOutlined />
<ArrowLeftOutlined />
<ArrowRightOutlined />
<LoginOutlined />
<LogoutOutlined />
<MenuFoldOutlined />
<MenuUnfoldOutlined />
<BorderBottomOutlined />
<BorderHorizontalOutlined />
<BorderInnerOutlined />
<BorderOuterOutlined />
<BorderLeftOutlined />
<BorderRightOutlined />
<BorderTopOutlined />
<BorderVerticleOutlined />
<PicCenterOutlined />
<PicLeftOutlined />
<PicRightOutlined />
<RadiusBottomleftOutlined />
<RadiusBottomrightOutlined />
<RadiusUpleftOutlined />
<RadiusUprightOutlined />
<FullscreenOutlined />
<FullscreenExitOutlined />
<QuestionOutlined />
<PauseOutlined />
<MinusOutlined />
<PauseCircleOutlined />
<InfoOutlined />
<CloseOutlined />
<ExclamationOutlined />
<CheckOutlined />
<WarningOutlined />
<IssuesCloseOutlined />
<StopOutlined />
<EditOutlined />
<CopyOutlined />
<ScissorOutlined />
<DeleteOutlined />
<SnippetsOutlined />
<DiffOutlined />
<HighlightOutlined />
<AlignCenterOutlined />
<AlignLeftOutlined />
<AlignRightOutlined />
<BgColorsOutlined />
<BoldOutlined />
<ItalicOutlined />
<UnderlineOutlined />
<StrikethroughOutlined />
<RedoOutlined />
<UndoOutlined />
<ZoomInOutlined />
<ZoomOutOutlined />
<FontColorsOutlined />
<FontSizeOutlined />
<LineHeightOutlined />
<SortAscendingOutlined />
<SortDescendingOutlined />
<DragOutlined />
<OrderedListOutlined />
<UnorderedListOutlined />
<RadiusSettingOutlined />
<ColumnWidthOutlined />
<ColumnHeightOutlined />
<AreaChartOutlined />
<PieChartOutlined />
<BarChartOutlined />
<DotChartOutlined />
<LineChartOutlined />
<RadarChartOutlined />
<HeatMapOutlined />
<FallOutlined />
<RiseOutlined />
<StockOutlined />
<BoxPlotOutlined />
<FundOutlined />
<SlidersOutlined />
<AndroidOutlined />
<AppleOutlined />
<WindowsOutlined />
<IeOutlined />
<ChromeOutlined />
<GithubOutlined />
<AliwangwangOutlined />
<DingdingOutlined />
<WeiboSquareOutlined />
<WeiboCircleOutlined />
<TaobaoCircleOutlined />
<Html5Outlined />
<WeiboOutlined />
<TwitterOutlined />
<WechatOutlined />
<AlipayCircleOutlined />
<TaobaoOutlined />
<SkypeOutlined />
<FacebookOutlined />
<CodepenOutlined />
<CodeSandboxOutlined />
<AmazonOutlined />
<GoogleOutlined />
<AlipayOutlined />
<AntDesignOutlined />
<AntCloudOutlined />
<ZhihuOutlined />
<SlackOutlined />
<SlackSquareOutlined />
<BehanceSquareOutlined />
<DribbbleOutlined />
<DribbbleSquareOutlined />
<InstagramOutlined />
<YuqueOutlined />
<AlibabaOutlined />
<YahooOutlined />
<RedditOutlined />
<SketchOutlined />
<AccountBookOutlined />
<AlertOutlined />
<ApartmentOutlined />
<ApiOutlined />
<QqOutlined />
<MediumWorkmarkOutlined />
<GitlabOutlined />
<MediumOutlined />
<GooglePlusOutlined />
<AppstoreAddOutlined />
<AppstoreOutlined />
<AudioOutlined />
<AudioMutedOutlined />
<AuditOutlined />
<BankOutlined />
<BarcodeOutlined />
<BarsOutlined />
<BellOutlined />
<BlockOutlined />
<BookOutlined />
<BorderOutlined />
<BranchesOutlined />
<BuildOutlined />
<BulbOutlined />
<CalculatorOutlined />
<CalendarOutlined />
<CameraOutlined />
<CarOutlined />
<CarryOutOutlined />
<CiCircleOutlined />
<CiOutlined />
<CloudOutlined />
<ClearOutlined />
<ClusterOutlined />
<CodeOutlined />
<CoffeeOutlined />
<CompassOutlined />
<CompressOutlined />
<ContactsOutlined />
<ContainerOutlined />
<ControlOutlined />
<CopyrightCircleOutlined />
<CopyrightOutlined />
<CreditCardOutlined />
<CrownOutlined />
<CustomerServiceOutlined />
<DashboardOutlined />
<DatabaseOutlined />
<DeleteColumnOutlined />
<DeleteRowOutlined />
<DisconnectOutlined />
<DislikeOutlined />
<DollarCircleOutlined />
<DollarOutlined />
<DownloadOutlined />
<EllipsisOutlined />
<EnvironmentOutlined />
<EuroCircleOutlined />
<EuroOutlined />
<ExceptionOutlined />
<ExpandAltOutlined />
<ExpandOutlined />
<ExperimentOutlined />
<ExportOutlined />
<EyeOutlined />
<FieldBinaryOutlined />
<FieldNumberOutlined />
<FieldStringOutlined />
<DesktopOutlined />
<DingtalkOutlined />
<FileAddOutlined />
<FileDoneOutlined />
<FileExcelOutlined />
<FileExclamationOutlined />
<FileOutlined />
<FileImageOutlined />
<FileJpgOutlined />
<FileMarkdownOutlined />
<FilePdfOutlined />
<FilePptOutlined />
<FileProtectOutlined />
<FileSearchOutlined />
<FileSyncOutlined />
<FileTextOutlined />
<FileUnknownOutlined />
<FileWordOutlined />
<FilterOutlined />
<FireOutlined />
<FlagOutlined />
<FolderAddOutlined />
<FolderOutlined />
<FolderOpenOutlined />
<ForkOutlined />
<FormatPainterOutlined />
<FrownOutlined />
<FunctionOutlined />
<FunnelPlotOutlined />
<GatewayOutlined />
<GifOutlined />
<GiftOutlined />
<GlobalOutlined />
<GoldOutlined />
<GroupOutlined />
<HddOutlined />
<HeartOutlined />
<HistoryOutlined />
<HomeOutlined />
<HourglassOutlined />
<IdcardOutlined />
<ImportOutlined />
<InboxOutlined />
<InsertRowAboveOutlined />
<InsertRowBelowOutlined />
<InsertRowLeftOutlined />
<InsertRowRightOutlined />
<InsuranceOutlined />
<InteractionOutlined />
<KeyOutlined />
<LaptopOutlined />
<LayoutOutlined />
<LikeOutlined />
<LineOutlined />
<LinkOutlined />
<Loading3QuartersOutlined />
<LoadingOutlined />
<LockOutlined />
<MailOutlined />
<ManOutlined />
<MedicineBoxOutlined />
<MehOutlined />
<MenuOutlined />
<MergeCellsOutlined />
<MessageOutlined />
<MobileOutlined />
<MoneyCollectOutlined />
<MonitorOutlined />
<MoreOutlined />
<NodeCollapseOutlined />
<NodeExpandOutlined />
<NodeIndexOutlined />
<NotificationOutlined />
<NumberOutlined />
<PaperClipOutlined />
<PartitionOutlined />
<PayCircleOutlined />
<PercentageOutlined />
<PhoneOutlined />
<PictureOutlined />
<PoundCircleOutlined />
<PoundOutlined />
<PoweroffOutlined />
<PrinterOutlined />
<ProfileOutlined />
<ProjectOutlined />
<PropertySafetyOutlined />
<PullRequestOutlined />
<PushpinOutlined />
<QrcodeOutlined />
<ReadOutlined />
<ReconciliationOutlined />
<RedEnvelopeOutlined />
<ReloadOutlined />
<RestOutlined />
<RobotOutlined />
<RocketOutlined />
<SafetyCertificateOutlined />
<SafetyOutlined />
<ScanOutlined />
<ScheduleOutlined />
<SearchOutlined />
<SecurityScanOutlined />
<SelectOutlined />
<SendOutlined />
<SettingOutlined />
<ShakeOutlined />
<ShareAltOutlined />
<ShopOutlined />
<ShoppingCartOutlined />
<ShoppingOutlined />
<SisternodeOutlined />
<SkinOutlined />
<SmileOutlined />
<SolutionOutlined />
<SoundOutlined />
<SplitCellsOutlined />
<StarOutlined />
<SubnodeOutlined />
<SyncOutlined />
<TableOutlined />
<TabletOutlined />
<TagOutlined />
<TagsOutlined />
<TeamOutlined />
<ThunderboltOutlined />
<ToTopOutlined />
<ToolOutlined />
<TrademarkCircleOutlined />
<TrademarkOutlined />
<TransactionOutlined />
<TrophyOutlined />
<UngroupOutlined />
<UnlockOutlined />
<UploadOutlined />
<UsbOutlined />
<UserAddOutlined />
<UserDeleteOutlined />
<UserOutlined />
<UserSwitchOutlined />
<UsergroupAddOutlined />
<UsergroupDeleteOutlined />
<VideoCameraOutlined />
<WalletOutlined />
<WifiOutlined />
<BorderlessTableOutlined />
<WomanOutlined />
<BehanceOutlined />
<DropboxOutlined />
<DeploymentUnitOutlined />
<UpCircleOutlined />
<DownCircleOutlined />
<LeftCircleOutlined />
<RightCircleOutlined />
<UpSquareOutlined />
<DownSquareOutlined />
<LeftSquareOutlined />
<RightSquareOutlined />
<PlayCircleOutlined />
<QuestionCircleOutlined />
<PlusCircleOutlined />
<PlusSquareOutlined />
<MinusSquareOutlined />
<MinusCircleOutlined />
<InfoCircleOutlined />
<ExclamationCircleOutlined />
<CloseCircleOutlined />
<CloseSquareOutlined />
<CheckCircleOutlined />
<CheckSquareOutlined />
<ClockCircleOutlined />
<FormOutlined />
<DashOutlined />
<SmallDashOutlined />
<YoutubeOutlined />
<CodepenCircleOutlined />
<AliyunOutlined />
<PlusOutlined />
<LinkedinOutlined />
<AimOutlined />
<BugOutlined />
<CloudDownloadOutlined />
<CloudServerOutlined />
<CloudSyncOutlined />
<CloudUploadOutlined />
<CommentOutlined />
<ConsoleSqlOutlined />
<EyeInvisibleOutlined />
<FileGifOutlined />
<DeliveredProcedureOutlined />
<FieldTimeOutlined />
<FileZipOutlined />
<FolderViewOutlined />
<FundProjectionScreenOutlined />
<FundViewOutlined />
<MacCommandOutlined />
<PlaySquareOutlined />
<OneToOneOutlined />
<RotateLeftOutlined />
<RotateRightOutlined />
<SaveOutlined />
<SwitcherOutlined />
<TranslationOutlined />
<VerifiedOutlined />
<VideoCameraAddOutlined />
<WhatsAppOutlined />
{/*</Col>*/}
</Row>
);
}
Example #16
Source File: GeneralSignup.tsx From next-basics with GNU General Public License v3.0 | 4 votes |
export function GeneralSignup(props: GeneralSignupProps): React.ReactElement {
const [form] = Form.useForm();
const runtime = getRuntime();
const brand = runtime.getBrandSettings();
const enabledFeatures = runtime.getFeatureFlags();
const { t } = useTranslation(NS_GENERAL_AUTH);
const [, setForceUpdate] = useState<any>();
const passwordConfigMap = {
default: {
regex: /^.{6,20}$/,
description: "请输入6至20位密码",
},
strong: {
regex: /^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[^a-zA-Z0-9]).{8,20}$/,
description: "请输入8至20位密码,且同时包含大小写字母、数字、特殊字符",
},
backend: {},
};
let passwordLevel: keyof typeof passwordConfigMap = "default"; //特性开关
useEffect(() => {
if (enabledFeatures["enable-backend-password-config"]) {
(async () => {
passwordLevel = "backend";
passwordConfigMap[passwordLevel] =
await UserAdminApi_getPasswordConfig();
})();
}
}, []);
const MIN_USERNAME_LENGTH = 3; //特性开关
const MAX_USERNAME_LENGTH = 32; //特性开关
const usernamePattern = new RegExp(
`^[A-Za-z0-9][A-Za-z0-9|_\\-\\.]{${MIN_USERNAME_LENGTH - 1},${
MAX_USERNAME_LENGTH - 1
}}$`
);
const iniviteCodePattern = /^[0-9a-zA-Z]{9}$/;
const hideInvite = iniviteCodePattern.test(getInviteCode());
const [isCommonSignup, setIsCommonSignup] = useState(true);
const [isTermsVisible, setIsTermsVisible] = useState(false);
function showTerms(): void {
setIsTermsVisible(true);
}
function hideTerms(): void {
setIsTermsVisible(false);
}
function agreeTerms(): void {
form.setFieldsValue({
terms: true,
});
hideTerms();
}
function disagreeTerms(): void {
form.setFieldsValue({
terms: false,
});
hideTerms();
}
const [imageHeight, setImageHeight] = useState(window.innerHeight);
const onWindowResized = () => {
if (imageHeight < window.innerHeight) {
setImageHeight(window.innerHeight);
}
};
useEffect(() => {
const handleWindowResized = debounce(onWindowResized, 500, {
leading: false,
});
window.addEventListener("resize", handleWindowResized);
return () => {
window.removeEventListener("resize", handleWindowResized);
};
}, []);
const timer = useRef<any>();
const count = useRef<number>(duration);
const [verifyBtnDisabled, setVerifyBtnDisabled] = useState(true);
const [content, setContent] = useState(t(K.GET_VERIFY_CODE));
const [messageId, setMessageId] = useState("");
const handleVerifyBtnClick = async (
e: React.MouseEvent<HTMLElement, MouseEvent>
) => {
if (timer.current) return;
count.current -= 1;
setContent(t(K.GET_VERIFY_CODE_TIPS, { count: count.current }));
setVerifyBtnDisabled(true);
timer.current = setInterval(() => {
count.current -= 1;
setContent(t(K.GET_VERIFY_CODE_TIPS, { count: count.current }));
if (count.current === 0) {
clearInterval(timer.current);
timer.current = null;
count.current = duration;
setVerifyBtnDisabled(false);
setContent(t(K.GET_VERIFY_CODE));
}
}, 1000);
const result = await CustomerApi_sendApplicationVerificationCode({
phone_number: form.getFieldValue("phone"),
});
result.message_id && setMessageId(result.message_id);
};
const redirect = async (result: Record<string, any>): Promise<void> => {
runtime.reloadSharedData();
await runtime.reloadMicroApps();
resetLegacyIframe();
authenticate({
org: result.org,
username: result.username,
userInstanceId: result.userInstanceId,
accessRule: result.accessRule,
});
const { state } = getHistory().location;
const from =
state && state.from
? state.from
: {
pathname: "/",
};
const redirect = createLocation(from);
getHistory().push(redirect);
};
const onFinish = async (values: Record<string, any>): Promise<void> => {
values.password = encryptValue(values.password);
try {
let result: Record<string, any>;
if (isCommonSignup && !hideInvite) {
result = await OrgApi_saaSOrgRegister(
assign(omit(values, ["terms", "password2"]), {
message_id: messageId,
}) as OrgApi_SaaSOrgRegisterRequestBody
);
} else {
result = await AuthApi_register(
assign(
omit(values, ["terms", "password2", "username"]),
hideInvite
? { invite: getInviteCode(), name: values["username"] }
: { name: values["username"] }
) as AuthApi_RegisterRequestBody
);
}
if (result.loggedIn) {
redirect(result);
}
message.success(t(K.REGISTER_SUCCESS));
} catch (error) {
Modal.error({
title: t(K.REGISTER_FAILED),
content:
isCommonSignup && !hideInvite
? t(K.WRONG_VERIFICATION_CODE)
: t(K.WRONG_INVITE_CODE),
});
}
};
return (
<>
<div className={styles.signupWrapper}>
<div className={styles.signupHeader}>
<div className={styles.logoBar}>
<Link to="/">
{brand.auth_logo_url ? (
<img
src={brand.auth_logo_url}
style={{ height: 32, verticalAlign: "middle" }}
/>
) : (
<Logo height={32} style={{ verticalAlign: "middle" }} />
)}
</Link>
</div>
</div>
<div className={styles.signupImg}>
<img src={loginPng} style={{ height: imageHeight }} />
</div>
<div className={styles.signupForm}>
<Card bordered={false}>
{!hideInvite &&
(isCommonSignup ? (
<a
onClick={() => {
setIsCommonSignup(false);
}}
style={{ alignSelf: "flex-end" }}
id="JumpToJoinFormLink"
>
{t(K.JOIN_THE_ORGANIZATION)} <RightOutlined />
</a>
) : (
<a
onClick={() => {
setIsCommonSignup(true);
}}
id="JumpToCommonFormLink"
>
<LeftOutlined /> {t(K.REGISTER_COMMONLY)}
</a>
))}
{!hideInvite && isCommonSignup ? (
<div className={styles.title}>{t(K.REGISTER_ACCOUNT)}</div>
) : (
<div className={styles.title}>{t(K.REGISTER_AND_JOIN)}</div>
)}
<Form name="signupForm" form={form} onFinish={onFinish}>
<Form.Item
validateFirst={true}
name="username"
rules={[
{
required: true,
message: t(K.USERNAME_TIPS, {
minLength: 3,
maxLength: 32,
}),
},
{
pattern: usernamePattern,
message: t(K.USERNAME_TIPS, {
minLength: 3,
maxLength: 32,
}),
},
{
validator: (
_: any,
value: any,
callback: (value?: string) => void
) =>
validateMap["airNameValidator"](
value,
callback,
setForceUpdate
),
},
]}
>
<Input
prefix={<UserOutlined className={styles.inputPrefixIcon} />}
placeholder={t(K.USERNAME)}
/>
</Form.Item>
{enabledFeatures["enable-nickname-config"] && hideInvite && (
<Form.Item validateFirst={false} name="nickname">
<Input
prefix={
<SolutionOutlined className={styles.inputPrefixIcon} />
}
placeholder={t(K.NICKNAME)}
/>
</Form.Item>
)}
<Form.Item
name="email"
validateFirst={true}
rules={[
{ required: true, message: t(K.PLEASE_ENTER_VALID_EMAIL) },
{ type: "email", message: t(K.PLEASE_ENTER_VALID_EMAIL) },
{
validator: (
_: any,
value: any,
callback: (value?: string) => void
) =>
validateMap["airEmailValidator"](
value,
callback,
setForceUpdate
),
},
]}
>
<Input
prefix={<MailOutlined className={styles.inputPrefixIcon} />}
type="email"
placeholder={t(K.EMAIL)}
/>
</Form.Item>
<Form.Item
validateFirst={true}
name="password"
rules={[
{ required: true, message: t(K.PLEASE_INPUT_PASSWORD) },
{
pattern: passwordConfigMap[passwordLevel].regex,
message: passwordConfigMap[passwordLevel].description,
},
]}
>
<Input
prefix={<LockOutlined className={styles.inputPrefixIcon} />}
type="password"
placeholder={t(K.PASSWORD)}
/>
</Form.Item>
<Form.Item
dependencies={["password"]}
name="password2"
rules={[
{ required: true, message: t(K.PLEASE_INPUT_PASSWORD) },
({ getFieldValue }) => ({
validator(_, value) {
if (!value || getFieldValue("password") === value) {
return Promise.resolve();
}
return Promise.reject(
new Error(t(K.TWO_PASSWORDS_ARE_INCONSISTENT))
);
},
}),
]}
>
<Input
prefix={<LockOutlined className={styles.inputPrefixIcon} />}
type="password"
placeholder={t(K.PASSWORD_CONFIRM)}
/>
</Form.Item>
{!hideInvite &&
(isCommonSignup ? (
<>
<Form.Item
validateFirst={true}
rules={[
{
required: true,
message: t(K.PLEASE_FILL_IN_VALID_PHONE_NUMBER),
},
{
validator: (_, value) => {
if (
/^(?=\d{11}$)^1(?:3\d|4[57]|5[^4\D]|7[^249\D]|8\d)\d{8}$/.test(
value
)
) {
setVerifyBtnDisabled(false);
return Promise.resolve();
}
setVerifyBtnDisabled(true);
return Promise.reject(
new Error(t(K.PLEASE_FILL_IN_VALID_PHONE_NUMBER))
);
},
},
]}
name="phone"
>
<Input
prefix={
<PhoneOutlined
className={styles.inputPrefixIcon}
rotate={90}
/>
}
suffix={
<Button
disabled={verifyBtnDisabled}
type="text"
onClick={handleVerifyBtnClick}
id="verifyBtn"
>
{content}
</Button>
}
placeholder={t(K.PHONE)}
/>
</Form.Item>
<Form.Item
rules={[
{
required: true,
message: t(K.PLEASE_INPUT_PHRASE),
},
{
pattern: /^\d{6}$/,
message: t(K.PLEASE_INPUT_VALID_PHRASE),
},
]}
name="verification_code"
>
<Input
prefix={
<SafetyOutlined className={styles.inputPrefixIcon} />
}
placeholder={t(K.VERIFY_CODE)}
></Input>
</Form.Item>
</>
) : (
<Form.Item
validateFirst={true}
name="invite"
rules={[
{
required: true,
message: t([K.PLEASE_FILL_IN_INVITE_CODE]),
},
{
pattern: iniviteCodePattern,
message: t([K.PLEASE_FILL_IN_INVITE_CODE]),
},
]}
>
<Input
prefix={
<GeneralIcon
icon={{
lib: "easyops",
icon: "release-management",
category: "menu",
color: "rgba(0,0,0,.25)",
}}
/>
}
type="text"
placeholder={t(K.INVITE_CODE)}
/>
</Form.Item>
))}
<Form.Item
name="terms"
valuePropName="checked"
rules={[
{
validator: (_, value) =>
value
? Promise.resolve()
: Promise.reject(new Error(t(K.AGREE_TERMS_TIPS))),
},
]}
>
<Checkbox>
{t(K.AGREE_TERMS)}
<a
onClick={() => {
showTerms();
}}
id="TermsLink"
>
{t(K.UWINTECH_TERMS)}
</a>
</Checkbox>
</Form.Item>
<Form.Item>
<Button
type="primary"
htmlType="submit"
style={{
width: "100%",
height: 34,
}}
id="submitBtn"
>
{t(K.REGISTER)}
</Button>
</Form.Item>
<Form.Item>
<div style={{ textAlign: "center" }}>
{t(K.ALREADY_HAVE_AN_ACCOUNT)}
<a
id="LogInLink"
onClick={() => {
getHistory().push(
createLocation({
pathname: props.loginUrl ?? "/auth/login",
})
);
}}
>
{t(K.LOGIN_IMMEDIATELY)}
</a>
</div>
</Form.Item>
</Form>
</Card>
<Modal
visible={isTermsVisible}
title={t(K.UWINTECH_TERMS)}
width={598}
okType="default"
cancelText={t(K.DISAGREE)}
okText={t(K.AGREE)}
closable={false}
onCancel={() => {
disagreeTerms();
}}
onOk={() => {
agreeTerms();
}}
>
<Terms />
</Modal>
</div>
</div>
</>
);
}
Example #17
Source File: SessionRecordingsTable.tsx From posthog-foss with MIT License | 4 votes |
export function SessionRecordingsTable({ personUUID, isPersonPage = false }: SessionRecordingsTableProps): JSX.Element {
const sessionRecordingsTableLogicInstance = sessionRecordingsTableLogic({ personUUID })
const {
sessionRecordings,
sessionRecordingsResponseLoading,
sessionRecordingId,
entityFilters,
propertyFilters,
hasNext,
hasPrev,
fromDate,
toDate,
durationFilter,
showFilters,
} = useValues(sessionRecordingsTableLogicInstance)
const {
openSessionPlayer,
closeSessionPlayer,
setEntityFilters,
setPropertyFilters,
loadNext,
loadPrev,
setDateRange,
setDurationFilter,
enableFilter,
} = useActions(sessionRecordingsTableLogicInstance)
const { preflight } = useValues(preflightLogic)
const columns: LemonTableColumns<SessionRecordingType> = [
{
title: 'Start time',
render: function RenderStartTime(_: any, sessionRecording: SessionRecordingType) {
return <TZLabel time={sessionRecording.start_time} formatString="MMMM DD, YYYY h:mm" />
},
},
{
title: 'Duration',
render: function RenderDuration(_: any, sessionRecording: SessionRecordingType) {
return <span>{humanFriendlyDuration(sessionRecording.recording_duration)}</span>
},
},
{
title: 'Person',
key: 'person',
render: function RenderPersonLink(_: any, sessionRecording: SessionRecordingType) {
return <PersonHeader withIcon person={sessionRecording.person} />
},
},
{
render: function RenderPlayButton(_: any, sessionRecording: SessionRecordingType) {
return (
<div className="play-button-container">
<Button
className={sessionRecording.viewed ? 'play-button viewed' : 'play-button'}
data-attr="session-recordings-button"
icon={<PlayCircleOutlined />}
>
Watch recording
</Button>
</div>
)
},
},
]
return (
<div className="session-recordings-table" data-attr="session-recordings-table">
<Row className="filter-row">
<div className="filter-container" style={{ display: showFilters ? undefined : 'none' }}>
<div>
<Typography.Text strong>
{`Filter by events and actions `}
<Tooltip title="Show recordings where all of the events or actions listed below happen.">
<InfoCircleOutlined className="info-icon" />
</Tooltip>
</Typography.Text>
<ActionFilter
fullWidth={true}
filters={entityFilters}
setFilters={(payload) => {
setEntityFilters(payload)
}}
typeKey={isPersonPage ? `person-${personUUID}` : 'session-recordings'}
hideMathSelector={true}
buttonCopy="Add another filter"
horizontalUI
stripeActionRow={false}
propertyFilterWrapperClassName="session-recording-action-property-filter"
customRowPrefix=""
hideRename
showOr
renderRow={(props) => <FilterRow {...props} />}
showNestedArrow={false}
actionsTaxonomicGroupTypes={[
TaxonomicFilterGroupType.Actions,
TaxonomicFilterGroupType.Events,
]}
propertiesTaxonomicGroupTypes={[
TaxonomicFilterGroupType.EventProperties,
TaxonomicFilterGroupType.Elements,
]}
/>
</div>
{!isPersonPage && preflight?.is_clickhouse_enabled && (
<div className="mt-2">
<Typography.Text strong>
{`Filter by persons and cohorts `}
<Tooltip title="Show recordings by persons who match the set criteria">
<InfoCircleOutlined className="info-icon" />
</Tooltip>
</Typography.Text>
<PropertyFilters
popoverPlacement="bottomRight"
pageKey={isPersonPage ? `person-${personUUID}` : 'session-recordings'}
taxonomicGroupTypes={[
TaxonomicFilterGroupType.PersonProperties,
TaxonomicFilterGroupType.Cohorts,
]}
propertyFilters={propertyFilters}
onChange={(properties) => {
setPropertyFilters(properties)
}}
/>
</div>
)}
</div>
<Button
style={{ display: showFilters ? 'none' : undefined }}
onClick={() => {
enableFilter()
if (isPersonPage) {
const entityFilterButtons = document.querySelectorAll('.entity-filter-row button')
if (entityFilterButtons.length > 0) {
;(entityFilterButtons[0] as HTMLElement).click()
}
}
}}
>
<FilterOutlined /> Filter recordings
</Button>
<Row className="time-filter-row">
<Row className="time-filter">
<DateFilter
makeLabel={(key) => (
<>
<CalendarOutlined />
<span> {key}</span>
</>
)}
defaultValue="Last 7 days"
bordered={true}
dateFrom={fromDate ?? undefined}
dateTo={toDate ?? undefined}
onChange={(changedDateFrom, changedDateTo) => {
setDateRange(changedDateFrom, changedDateTo)
}}
dateOptions={{
Custom: { values: [] },
'Last 24 hours': { values: ['-24h'] },
'Last 7 days': { values: ['-7d'] },
'Last 21 days': { values: ['-21d'] },
}}
/>
</Row>
<Row className="time-filter">
<Typography.Text className="filter-label">Duration</Typography.Text>
<DurationFilter
onChange={(newFilter) => {
setDurationFilter(newFilter)
}}
initialFilter={durationFilter}
pageKey={isPersonPage ? `person-${personUUID}` : 'session-recordings'}
/>
</Row>
</Row>
</Row>
<LemonTable
dataSource={sessionRecordings}
columns={columns}
loading={sessionRecordingsResponseLoading}
onRow={(sessionRecording) => ({
onClick: (e) => {
// Lets the link to the person open the person's page and not the session recording
if (!(e.target as HTMLElement).closest('a')) {
openSessionPlayer(sessionRecording.id, RecordingWatchedSource.RecordingsList)
}
},
})}
rowClassName="cursor-pointer"
data-attr="session-recording-table"
/>
{(hasPrev || hasNext) && (
<Row className="pagination-control">
<Button
type="link"
disabled={!hasPrev}
onClick={() => {
loadPrev()
window.scrollTo(0, 0)
}}
>
<LeftOutlined /> Previous
</Button>
<Button
type="link"
disabled={!hasNext}
onClick={() => {
loadNext()
window.scrollTo(0, 0)
}}
>
Next <RightOutlined />
</Button>
</Row>
)}
<div style={{ marginBottom: 64 }} />
{!!sessionRecordingId && <SessionPlayerDrawer isPersonPage={isPersonPage} onClose={closeSessionPlayer} />}
</div>
)
}
Example #18
Source File: SearchMsgView.tsx From dashboard with Apache License 2.0 | 4 votes |
SearchMsgView: React.FC<SearchMsgViewProps> = (props) => {
const {searchMsgList, setShowSearchMessageView, currentChatSession, currentStaff, total: msgTotal} = props
const [chatMessageList, setChatMessageList] = useState<ChatMessage.Item[]>([]) // 消息
const [showContextMsgList, setShowContextMsgList] = useState(false)
const [page, setPage] = useState(1)
const [loadingMoreEarlierData, setLoadingMoreEarlierData] = useState(false)
const [loadingMoreNearData, setLoadingMoreNearData] = useState(false)
const queryChatMessages = (action: string, min_id?: string, max_id?: string, pageSize?: number, pageNth?: number) => {
return QueryChatMessages({
page_size: pageSize,
page: pageNth,
ext_staff_id: currentStaff?.ext_staff_id || 'none',
receiver_id: currentChatSession.peer_ext_id || 'none',
max_id,
min_id
}).then(res => {
if (res?.code === 0) {
setChatMessageList([])
let newMsgList: any[] = []
if (action === 'getEarlier') {
newMsgList = [...res.data.items]?.concat([...chatMessageList]).filter((m: any) => m !== null)
setLoadingMoreEarlierData(false)
} else if (action === 'getNear') {
newMsgList = [...chatMessageList]?.concat([...res.data.items]).filter((m: any) => m !== null)
setLoadingMoreNearData(false)
}
newMsgList?.map((msg: any) => {
return {...msg, showTime: false}
})
for (let i = 0; i < newMsgList.length; i += 1) {
if (Math.floor(Number(newMsgList[i]?.msgtime) / 10800 / 1000) !== Math.floor(Number(newMsgList[i + 1]?.msgtime) / 10800 / 1000)) {
newMsgList[i].showTime = true
}
}
setChatMessageList(newMsgList || [])
setPage(() => page + 1)
} else {
message.error(res?.message)
}
})
}
// 下拉 min_id
const loadEarlierData = () => {
setLoadingMoreEarlierData(true)
queryChatMessages('getEarlier', chatMessageList?.[0]?.id, undefined, 10, page)
}
// 上拉 max_id
const loadNearData = () => {
setLoadingMoreNearData(true)
queryChatMessages('getNear', undefined, chatMessageList?.[chatMessageList?.length - 1]?.id, 10, page)
}
// 获取初始的上下文列表
const getInitialChatMessageList = (msg: SearchMessage.Item) => {
QueryChatMessages({
page_size: 10,
page: 1,
ext_staff_id: currentStaff?.ext_staff_id || 'none',
receiver_id: currentChatSession.peer_ext_id || 'none',
max_id: msg.id
}).then(maxRes => {
if (maxRes?.code === 0) {
QueryChatMessages({
page_size: 10,
page: 1,
ext_staff_id: currentStaff?.ext_staff_id || 'none',
receiver_id: currentChatSession.peer_ext_id || 'none',
min_id: msg.id
}).then(minRes => {
// 查询结果按时间从小到大排序。用min_id查询比目标时间更早的数据
if (minRes?.code === 0) {
const initialChatMessageList = [...minRes.data.items].concat([msg]).concat([...maxRes.data.items]).filter((m: any) => m !== null) || []
initialChatMessageList?.map((initialMsg: any) => {
return {...initialMsg, showTime: false}
})
for (let i = 0; i < initialChatMessageList.length; i += 1) {
if (Math.floor(Number(initialChatMessageList[i]?.msgtime) / 10800 / 1000) !== Math.floor(Number(initialChatMessageList[i + 1]?.msgtime) / 10800 / 1000)) {
initialChatMessageList[i].showTime = true
}
}
setChatMessageList(initialChatMessageList || [])
setPage(() => page + 1)
}
})
}
})
}
return (
<div className={styles.searchViewContainerOuter}>
<div className={styles.back}>
<Button type={'link'} onClick={() => {
if (showContextMsgList) {
setShowContextMsgList(false)
setPage(1)
} else {
setShowSearchMessageView(false)
}
}}><LeftOutlined/>返回</Button>
</div>
<div className={styles.searchViewContainer}>
<div className={styles.searchMessageView} style={{display: showContextMsgList ? 'none' : 'block'}}>
{
searchMsgList.map(msg => (
<div className={styles.msgItem}>
<img src={msg.sender_avatar}/>
<div className={styles.textBox}>
<div className={styles.nameAndTime}>
<span>{msg.sender_name}</span>
<span>{parseTime(msg.msgtime)}</span>
</div>
<div className={styles.textContent}>
<div>
{msg.content_text}
</div>
<Button type={'link'} onClick={() => {
getInitialChatMessageList(msg)
setShowContextMsgList(true)
}}>查看上下文</Button>
</div>
</div>
</div>
))
}
{
searchMsgList.length > 0 && <p className={styles.noMore}>没有更多了</p>
}
</div>
<div className={styles.contextMsgView} style={{display: showContextMsgList ? 'block' : 'none'}}>
<MessageView chatMessageList={chatMessageList || []} currentStaff={currentStaff}
loadEarlierData={loadEarlierData} loadNearData={loadNearData}
loadingMoreEarlierData={loadingMoreEarlierData}
loadingMoreNearData={loadingMoreNearData} currentChatSession={currentChatSession}
total={msgTotal} isContextView={true}/>
</div>
</div>
</div>
)
}
Example #19
Source File: HorizontalScrollable.tsx From oxen-website with GNU General Public License v3.0 | 4 votes |
function HorizontalScrollableInner(props: Props) {
const { onItemClick, children } = props;
const scrollRef = useRef(null);
const innerContentRef = useRef(null);
const { x } = useScroll(scrollRef);
const pageWidth = useWindowSize().width;
const scrollDistance = pageWidth > 1400 ? 450 : pageWidth / 3;
const [rightScrollHidden, setRightScrollHidden] = useState(false);
const { isDesktop } = useContext(ScreenContext);
const handleLeftScroll = () => {
scrollRef.current.scrollBy({
left: -scrollDistance,
behavior: 'smooth',
});
};
const handleRightScroll = () => {
scrollRef.current.scrollBy({
left: scrollDistance,
behavior: 'smooth',
});
};
function handleItemClick() {
if (onItemClick) {
onItemClick();
}
}
useEffect(() => {
const isFullRight =
scrollRef.current.scrollWidth - scrollRef.current.clientWidth ===
scrollRef.current.scrollLeft;
const tooSmallToScroll =
innerContentRef.current.clientWidth < scrollRef.current.clientWidth;
setRightScrollHidden(tooSmallToScroll || isFullRight);
}, [x, children]);
return (
<div className="relative flex w-full">
<div
className={classNames(
'absolute left-0 flex items-center justify-between h-full w-full',
!isDesktop && 'hidden',
)}
>
<div
className={classNames(
'flex flex-col justify-center h-full z-50 duration-300 -ml-8',
x <= 1 && 'opacity-0',
)}
>
<LeftOutlined
onClick={handleLeftScroll}
className={classNames('h-20 mt-1 cursor-pointer')}
/>
</div>
<div
className={classNames(
'flex flex-col justify-center h-full z-50 duration-300 -mr-8',
rightScrollHidden && 'opacity-0',
)}
>
<RightOutlined
onClick={handleRightScroll}
className="h-20 mt-1 cursor-pointer"
/>
</div>
</div>
<div
ref={scrollRef}
className={classNames(
'relative',
'w-full',
'hide_scroll',
'scrolling-touch hide-scroll',
isDesktop ? 'overflow-x-scroll' : 'overflow-x-scroll',
)}
>
<div
ref={innerContentRef}
className={classNames('flex space-x-8 overflow-y-visible')}
style={{
width: 'min-content',
marginLeft: `${!isDesktop ? UI.PAGE_CONTAINED_PADDING_VW : 0}vw`,
paddingRight: `${!isDesktop ? UI.PAGE_CONTAINED_PADDING_VW : 0}vw`,
}}
>
{children}
</div>
</div>
</div>
);
}
Example #20
Source File: index.tsx From datart with Apache License 2.0 | 4 votes |
export function ListTitle({
title,
subTitle,
search,
add,
more,
back,
className,
onSearch,
onPrevious,
onNext,
}: ListTitleProps) {
const [searchbarVisible, setSearchbarVisible] = useState(false);
const t = useI18NPrefix('components.listTitle');
const toggleSearchbar = useCallback(() => {
setSearchbarVisible(!searchbarVisible);
}, [searchbarVisible]);
const moreMenuClick = useCallback(
({ key }) => {
more?.callback(key, onPrevious, onNext);
},
[more, onPrevious, onNext],
);
const backClick = useCallback(() => {
onPrevious && onPrevious();
}, [onPrevious]);
return (
<Wrapper className={className}>
<Title className="title">
{back && (
<span className="back" onClick={backClick}>
<LeftOutlined />
</span>
)}
{title && <h3>{title}</h3>}
{subTitle && <h5>{subTitle}</h5>}
<Space size={SPACE_UNIT}>
{search && (
<Tooltip title={t('search')} placement="bottom">
<ToolbarButton
size="small"
icon={<SearchOutlined />}
color={searchbarVisible ? PRIMARY : void 0}
onClick={toggleSearchbar}
/>
</Tooltip>
)}
{add && <AddButton dataSource={add} />}
{more && (
<Popup
getPopupContainer={triggerNode =>
triggerNode.parentElement as HTMLElement
}
trigger={['click']}
placement="bottomRight"
content={
<MenuWrapper
prefixCls="ant-dropdown-menu"
selectable={false}
onClick={moreMenuClick}
>
{more.items.map(({ key, text, prefix, suffix }) => (
<MenuListItem
key={key}
{...(prefix && { prefix })}
{...(suffix && { suffix })}
>
{text}
</MenuListItem>
))}
</MenuWrapper>
}
>
<ToolbarButton size="small" icon={<MoreOutlined />} />
</Popup>
)}
</Space>
</Title>
<Searchbar visible={searchbarVisible}>
<Input
className="search-input"
prefix={<SearchOutlined className="icon" />}
placeholder={t('searchValue')}
bordered={false}
onChange={onSearch}
/>
</Searchbar>
</Wrapper>
);
}
Example #21
Source File: PopularTimes.tsx From office-hours with GNU General Public License v3.0 | 4 votes |
export default function PopularTimes({ heatmap }: HeatmapProps): ReactElement {
const [currentDayOfWeek, setCurrentDayOfWeek] = useState(new Date().getDay());
const [firstHour, lastHour] = findWeekMinAndMax(heatmap);
const dailyAvgWaitTimes: number[] = chunk(heatmap, 24).map((hours) => {
const filteredOfficeHours = hours.filter((v) => v !== -1);
return filteredOfficeHours.length > 0 ? mean(filteredOfficeHours) : -1;
});
return (
<div className="hide-in-percy">
<TitleRow>
<h2>Wait Times on</h2>
<Dropdown
trigger={["click"]}
overlay={
<Menu>
{DAYS_OF_WEEK.map((dayName, i) => (
<Menu.Item key={dayName}>
<a onClick={() => setCurrentDayOfWeek(i)}>{dayName}</a>
</Menu.Item>
))}
</Menu>
}
>
<WeekdayDropdown>
{DAYS_OF_WEEK[currentDayOfWeek]}
<DownOutlined />
</WeekdayDropdown>
</Dropdown>
</TitleRow>
<GraphWithArrow>
<GraphArrowButtons
onClick={() => setCurrentDayOfWeek((7 + currentDayOfWeek - 1) % 7)}
>
<LeftOutlined />
</GraphArrowButtons>
<GraphContainer>
<ParentSize>
{({ width }) => (
<TimeGraph
values={heatmap
.slice(currentDayOfWeek * 24, (currentDayOfWeek + 1) * 24 - 1)
.map((i) => (i < 0 ? 0 : Math.floor(i)))}
maxTime={Math.max(...heatmap)}
firstHour={firstHour}
lastHour={lastHour}
width={width}
height={220}
/>
)}
</ParentSize>
</GraphContainer>
<GraphArrowButtons
onClick={() => setCurrentDayOfWeek((currentDayOfWeek + 1) % 7)}
>
<RightOutlined />
</GraphArrowButtons>
</GraphWithArrow>
{dailyAvgWaitTimes[currentDayOfWeek] >= 0 && (
<GraphNotes>
<ClockCircleOutlined /> {DAYS_OF_WEEK[currentDayOfWeek]}s have{" "}
<strong>
{generateBusyText(currentDayOfWeek, dailyAvgWaitTimes)}
</strong>{" "}
wait times.
</GraphNotes>
)}
{new Date().getDay() === currentDayOfWeek &&
heatmap[currentDayOfWeek * 24 + new Date().getHours()] >= 0 && (
<GraphNotes>
<HourglassOutlined /> At {formatDateHour(new Date().getHours())},
people generally wait{" "}
<strong>
{formatWaitTime(
heatmap[currentDayOfWeek * 24 + new Date().getHours()]
)}
</strong>
.
</GraphNotes>
)}
</div>
);
}
Example #22
Source File: AddCustomNetwork.tsx From subscan-multisig-react with Apache License 2.0 | 4 votes |
AddCustomNetwork = (props: AddCustomNetworkProps) => {
const { t } = useTranslation();
const { network } = useApi();
const mainColor = useMemo(() => {
return getThemeColor(network);
}, [network]);
const [rpcName, setRpcName] = useState('');
const [rpcUrl, setRpcUrl] = useState('');
const [explorerHostName, setExplorerHostName] = useState('');
// const [explorerUrl, setExplorerUrl] = useState('');
const networks = useMemo(() => _.values(chains), []);
const [addNetworkLoading, setAddNetworkLoading] = useState(false);
const [addNetworkErrorDialogVisible, setAddNetworkErrorDialogVisible] = useState(false);
const [addNetworkErrorContent, setAddNetworkErrorContent] = useState('');
// eslint-disable-next-line complexity
useEffect(() => {
if (props.editNetwork) {
setRpcName(props.editNetwork?.displayName || '');
setRpcUrl(props.editNetwork?.rpc || '');
setExplorerHostName(props.editNetwork?.explorerHostName || '');
} else {
setRpcName('');
setRpcUrl('');
setExplorerHostName('');
}
}, [props.editNetwork]);
const saveNewCustomNetwork = () => {
if (!rpcName.trim() || !rpcUrl.trim()) {
return;
}
setAddNetworkLoading(true);
try {
const provider = new WsProvider(rpcUrl);
const api = new ApiPromise({
provider,
});
const onReady = async () => {
setAddNetworkLoading(false);
api.off('ready', onReady);
api.off('error', onError);
api.off('disconnected', onError);
if (!api.query.multisig) {
setAddNetworkErrorDialogVisible(true);
setAddNetworkErrorContent(t('network not supported'));
return;
}
const storage = readStorage();
const oldCustomNetworks = storage.addedCustomNetworks || [];
let duplicate = false;
networks.forEach((networkItem) => {
if (networkItem?.rpc === rpcUrl.trim()) {
duplicate = true;
return;
}
});
oldCustomNetworks.forEach((networkItem) => {
if (networkItem.rpc === rpcUrl.trim()) {
duplicate = true;
return;
}
});
if (duplicate) {
message.warn(t('custom.duplicate websocket url'));
return;
}
const newNetwork = {
name: rpcName.trim(),
displayName: rpcName.trim(),
rpc: rpcUrl.trim(),
explorerHostName: explorerHostName.trim(),
};
oldCustomNetworks.push(newNetwork);
updateStorage({ addedCustomNetworks: oldCustomNetworks });
setRpcName('');
setRpcUrl('');
selectCustomNetwork(newNetwork);
props.onCancel();
};
const onError = async () => {
setAddNetworkLoading(false);
setAddNetworkErrorDialogVisible(true);
setAddNetworkErrorContent(t('unavailable endpoint'));
api.disconnect();
api.off('ready', onReady);
api.off('error', onError);
api.off('disconnected', onError);
};
api.on('ready', onReady);
api.on('error', onError);
api.on('disconnected', onError);
} catch {
setAddNetworkLoading(false);
setAddNetworkErrorDialogVisible(true);
setAddNetworkErrorContent(t('unavailable endpoint'));
}
};
const updateCustomNetwork = () => {
if (!rpcName.trim() || !rpcUrl.trim()) {
return;
}
setAddNetworkLoading(true);
try {
const provider = new WsProvider(rpcUrl.trim());
const api = new ApiPromise({
provider,
});
const onReady = async () => {
setAddNetworkLoading(false);
if (!api.query.multisig) {
setAddNetworkErrorDialogVisible(true);
setAddNetworkErrorContent(t('network not supported'));
return;
}
api.off('ready', onReady);
const storage = readStorage();
const oldCustomNetworks = storage.addedCustomNetworks || [];
let duplicate = false;
networks.forEach((networkItem) => {
if (networkItem?.rpc === rpcUrl.trim()) {
duplicate = true;
return;
}
});
oldCustomNetworks.forEach((networkItem) => {
if (networkItem.rpc === rpcUrl.trim() && networkItem.rpc !== props.editNetwork?.rpc) {
duplicate = true;
return;
}
});
if (duplicate) {
message.warn(t('custom.duplicate websocket url'));
return;
}
const networkIndex = oldCustomNetworks.findIndex((networkItem) => networkItem.rpc === props.editNetwork?.rpc);
oldCustomNetworks.splice(networkIndex, 1, {
name: rpcName,
displayName: rpcName,
rpc: rpcUrl,
explorerHostName: explorerHostName.trim(),
});
updateStorage({ addedCustomNetworks: oldCustomNetworks });
props.onCancel();
};
api.on('ready', onReady);
} catch {
setAddNetworkLoading(false);
setAddNetworkErrorDialogVisible(true);
setAddNetworkErrorContent('unavailable endpoint');
}
};
const selectCustomNetwork = (netConfig: NetConfigV2) => {
if (!netConfig.displayName || !netConfig.rpc) {
return;
}
updateStorage({
customNetwork: {
name: netConfig.name,
displayName: netConfig.displayName,
rpc: netConfig.rpc,
},
});
props.onCancel();
changeUrlHash(netConfig.rpc);
updateStorage({
selectedRpc: netConfig.rpc,
});
};
return (
<div>
<div className="overflow-auto hide-scrollbar" style={{ maxHeight: '500px' }}>
<div className="flex items-center justify-center relative">
<div
className="font-bold capitalize text-black-800"
style={{ fontSize: '16px', textTransform: 'capitalize' }}
>
{props.editNetwork ? t('custom.edit custom endpoint') : t('custom.add custom endpoint')}
</div>
<LeftOutlined
className="absolute cursor-pointer left-0"
style={{ color: '#666666' }}
onClick={props.onCancel}
/>
</div>
<div className="mt-6 font-bold text-black-800">{t('remark')}</div>
<div className="mt-2">
<Input
value={rpcName}
onChange={(e) => {
setRpcName(e.target.value);
}}
/>
</div>
<div className="mt-6 font-bold text-black-800">{t('endpoint')}</div>
<div className="mt-2">
<Input
value={rpcUrl}
onChange={(e) => {
setRpcUrl(e.target.value);
}}
/>
</div>
<div className="mt-6 font-bold text-black-800">{t('explorer optional')}</div>
<div className="mt-2 flex items-center text-black-800">
<div>https://</div>
<div className="mx-1 w-24">
<Input
value={explorerHostName}
size="small"
onChange={(e) => {
setExplorerHostName(e.target.value);
}}
/>
</div>
<div>.subscan.io/</div>
</div>
<Row gutter={16} className={classNames('mt-10')}>
<Col span={24}>
<Button
loading={addNetworkLoading}
block
style={{
color: mainColor,
}}
onClick={props.editNetwork ? updateCustomNetwork : saveNewCustomNetwork}
>
{props.editNetwork ? t('save') : t('add')}
</Button>
</Col>
</Row>
</div>
<ConfirmDialog
title="Error"
content={addNetworkErrorContent}
visible={addNetworkErrorDialogVisible}
onCancel={() => setAddNetworkErrorDialogVisible(false)}
onConfirm={() => setAddNetworkErrorDialogVisible(false)}
/>
</div>
);
}
Example #23
Source File: HTTPFlowDetail.tsx From yakit with GNU Affero General Public License v3.0 | 4 votes |
HTTPFlowDetail: React.FC<HTTPFlowDetailProp> = (props) => {
const [flow, setFlow] = useState<HTTPFlow>();
const [loading, setLoading] = useState(false);
const actionFuzzer = [
{
id: 'send-fuzzer-info',
label: '发送到Fuzzer',
contextMenuGroupId: 'send-fuzzer-info',
run: () => {
ipcRenderer.invoke("send-to-tab", {
type: "fuzzer",
data: {
isHttps: flow?.IsHTTPS,
request: Buffer.from(flow?.Request || []).toString("utf8")
}
})
if (props.onClose) props.onClose()
}
},
{
id: 'send-to-plugin',
label: '发送到数据包扫描',
contextMenuGroupId: 'send-fuzzer-info',
run: () => ipcRenderer.invoke("send-to-packet-hack", {
request: flow?.Request,
ishttps: flow?.IsHTTPS,
response: flow?.Response
})
}
]
useEffect(() => {
if (!props.hash) {
return
}
//
// ipcRenderer.on(props.hash, (e: any, data: HTTPFlow) => {
// setFlow(data)
// setTimeout(() => setLoading(false), 300)
// })
// ipcRenderer.on(`ERROR:${props.hash}`, (e: any, details: any) => {
// failed(`查询该请求失败[${props.hash}]: ` + details)
// })
setLoading(true)
ipcRenderer.invoke("GetHTTPFlowByHash", {Hash: props.hash}).then((data: HTTPFlow) => {
setFlow(data)
}).catch(e => {
failed(`GetHTTPFlow ByHash[${props.hash}] failed`)
}).finally(() => setTimeout(() => setLoading(false), 300))
// ipcRenderer.invoke("get-http-flow", props.hash)
return () => {
// ipcRenderer.removeAllListeners(props.hash)
// ipcRenderer.removeAllListeners(`ERROR:${props.hash}`)
}
}, [props.hash])
return <Spin spinning={loading} style={{width: "100%", marginBottom: 24}}>
{flow ? <>
{props.noHeader ? undefined : <PageHeader
title={`请求详情`} subTitle={props.hash}
extra={
props.fetchRequest ?
<Space>
<Tooltip title={"上一个请求"}>
<Button type="link" disabled={!!props.isFront}
icon={<LeftOutlined/>} onClick={() => {
props?.fetchRequest!(1)
}}></Button>
</Tooltip>
<Tooltip title={"下一个请求"}>
<Button type="link" disabled={!!props.isBehind}
icon={<RightOutlined/>} onClick={() => {
props?.fetchRequest!(2)
}}></Button>
</Tooltip>
</Space>
:
<></>
}/>
}
<Space direction={"vertical"} style={{width: "100%"}}>
<Descriptions column={4} bordered={true} size={"small"}>
<Descriptions.Item key={"method"} span={1} label={"HTTP 方法"}><Tag color={"geekblue"}><Text
style={{maxWidth: 500}}>{flow.Method}</Text></Tag></Descriptions.Item>
<Descriptions.Item key={"url"} span={3} label={"请求 URL"}>
<Text style={{maxWidth: 500}} copyable={true}>{flow.Url}</Text>
</Descriptions.Item>
<Descriptions.Item key={"https"} span={1} label={"HTTPS"}><Tag color={"geekblue"}>
<div
style={{maxWidth: 500}}>{flow.IsHTTPS ? "True" : "False"}</div>
</Tag></Descriptions.Item>
<Descriptions.Item key={"status"} span={1} label={"StatusCode"}><Tag
color={"geekblue"}>{flow.StatusCode}</Tag></Descriptions.Item>
<Descriptions.Item key={"size"} span={1} label={"Body大小"}><Tag color={"geekblue"}>
<div style={{maxWidth: 500}}>{flow.BodySizeVerbose}</div>
</Tag></Descriptions.Item>
<Descriptions.Item key={"type"} span={1} label={"Content-Type"}><Tag color={"geekblue"}>
<div style={{maxWidth: 500}}>{flow.ContentType}</div>
</Tag></Descriptions.Item>
</Descriptions>
<div style={{width: "100%", overflow: "auto"}}>
{flow.GetParams.length > 0 || flow.PostParams.length > 0 || flow.CookieParams.length > 0 ? <Tabs>
{flow.GetParams.length > 0 && <Tabs.TabPane key={"get"} tab={"GET 参数"}>
<FuzzableParamList data={flow.GetParams} sendToWebFuzzer={() => {
if (props.onClose) props.onClose()
}}/>
</Tabs.TabPane>}
{flow.PostParams.length > 0 && <Tabs.TabPane key={"post"} tab={"POST 参数"}>
<FuzzableParamList data={flow.PostParams} sendToWebFuzzer={() => {
if (props.onClose) props.onClose()
}}/>
</Tabs.TabPane>}
{flow.CookieParams.length > 0 && <Tabs.TabPane key={"cookie"} tab={"Cookie 参数"}>
<FuzzableParamList data={flow.CookieParams} sendToWebFuzzer={() => {
if (props.onClose) props.onClose()
}}/>
</Tabs.TabPane>}
</Tabs> : ""}
</div>
<Row gutter={8}>
<Col span={12}>
<Card title={"原始 HTTP 请求"} size={"small"} bodyStyle={{padding: 0}}>
<div style={{height: 350}}>
<YakEditor readOnly={true} type={"http"}//theme={"fuzz-http-theme"}
value={new Buffer(flow.Request).toString("utf-8")}
actions={[...actionFuzzer]}/>
</div>
</Card>
</Col>
<Col span={12}>
<Card title={"原始 HTTP 响应"} size={"small"} bodyStyle={{padding: 0}}>
<div style={{height: 350}}>
<YakEditor readOnly={true} type={"http"}// theme={"fuzz-http-theme"}
value={new Buffer(flow.Response).toString("utf-8")}
/>
</div>
</Card>
</Col>
</Row>
{/*<Collapse>*/}
{/* <Collapse.Panel key={"request-raw"} header={"原始 HTTP 请求数据包内容"}>*/}
{/* </Collapse.Panel>*/}
{/* <Collapse.Panel key={"response-raw"} header={"原始 HTTP 响应数据包内容"}>*/}
{/* </Collapse.Panel>*/}
{/*</Collapse>*/}
<Row gutter={8}>
<Col span={12}>
<Collapse defaultActiveKey={"request"}>
<Collapse.Panel key={"request"} header={"Request Headers"}>
<Descriptions bordered={true} column={1} size={"small"}>
{(flow?.RequestHeader || []).sort((i, e) => {
return i.Header.localeCompare(e.Header)
}).map(i => {
return <Descriptions.Item key={i.Header} label={<Text style={{width: 240}}>
<Tag>{i.Header}</Tag>
</Text>}>
<Text
copyable={true}
style={{maxWidth: 500}}
ellipsis={{tooltip: true}}>{i.Value}</Text>
</Descriptions.Item>
})}
</Descriptions>
</Collapse.Panel>
</Collapse>
</Col>
<Col span={12}>
<Collapse defaultActiveKey={"response"}>
<Collapse.Panel key={"response"} header={"Response Headers"}>
<Descriptions bordered={true} column={1} size={"small"}>
{(flow?.ResponseHeader || []).sort((i, e) => {
return i.Header.localeCompare(e.Header)
}).map(i => {
return <Descriptions.Item key={i.Header} label={<Text style={{width: 240}}>
<Tag>{i.Header}</Tag>
</Text>}>
<Text
copyable={true}
style={{maxWidth: 500}}
ellipsis={{tooltip: true}}>{i.Value}</Text>
</Descriptions.Item>
})}
</Descriptions>
</Collapse.Panel>
</Collapse>
</Col>
</Row>
</Space>
</> : ""}
</Spin>
}
Example #24
Source File: App.tsx From pcap2socks-gui with MIT License | 4 votes |
render() {
return (
<Layout className="layout">
<Content className="content-wrapper">
<div className="content">
{(() => {
switch (this.state.stage) {
case STAGE_WELCOME:
return this.renderWelcome();
case STAGE_INTERFACE:
return this.renderInterface();
case STAGE_DEVICE:
return this.renderDevice();
case STAGE_PROXY:
return this.renderProxy();
case STAGE_RUNNING:
return this.renderRunning();
default:
return;
}
})()}
</div>
<div className="footer">
{(() => {
if (this.state.stage > STAGE_WELCOME && this.state.stage <= STAGE_PROXY) {
return (
<Button
className="button"
disabled={this.state.loading > 0}
icon={<LeftOutlined />}
onClick={() => this.setState({ stage: this.state.stage - 1 })}
>
上一步
</Button>
);
}
})()}
{(() => {
if (this.state.stage === STAGE_INTERFACE) {
return (
<Button
className="button"
disabled={this.state.loading > 0 && this.state.loading !== 1}
icon={<ReloadOutlined />}
onClick={this.updateInterfaces}
>
刷新网卡列表
</Button>
);
}
})()}
{(() => {
if (this.state.stage === STAGE_PROXY) {
return (
<Button
className="button"
disabled={this.state.loading > 0}
icon={<FolderOpenOutlined />}
onClick={() => {
const node = document.getElementById("open");
if (node) {
node.click();
}
}}
>
导入代理配置
<input id="open" type="file" onChange={this.import} style={{ display: "none" }} />
</Button>
);
}
})()}
{(() => {
if (this.state.stage === STAGE_PROXY) {
return (
<Button className="button" icon={<ExportOutlined />} onClick={this.export}>
导出代理配置
</Button>
);
}
})()}
{(() => {
if (this.state.stage === STAGE_PROXY) {
return (
<Button
className="button"
disabled={this.state.loading > 0 && this.state.loading !== 2}
loading={this.state.loading === 2}
icon={<ExperimentOutlined />}
onClick={this.test}
>
测试代理服务器
</Button>
);
}
})()}
{(() => {
if (this.state.stage === STAGE_WELCOME && this.state.ready) {
return (
<Tooltip title={this.state.destination}>
<Button
className="button"
type="primary"
disabled={this.state.loading > 0 && this.state.loading !== 3}
loading={this.state.loading === 3}
icon={<PlayCircleOutlined />}
onClick={this.run}
>
以上次的配置运行
</Button>
</Tooltip>
);
}
})()}
{(() => {
if (this.state.stage >= STAGE_WELCOME && this.state.stage < STAGE_PROXY) {
return (
<Button
className="button"
disabled={this.state.loading > 0}
icon={<RightOutlined />}
type="primary"
onClick={() => this.setState({ stage: this.state.stage + 1 })}
>
下一步
</Button>
);
}
})()}
{(() => {
if (this.state.stage === STAGE_PROXY) {
return (
<Button
className="button"
type="primary"
disabled={this.state.loading > 0 && this.state.loading !== 3}
loading={this.state.loading === 3}
icon={<PoweroffOutlined />}
onClick={this.run}
>
运行
</Button>
);
}
})()}
{(() => {
if (this.state.stage === STAGE_RUNNING) {
return (
<Button className="button" icon={<GlobalOutlined />} onClick={this.notifyNetwork}>
显示网络设置
</Button>
);
}
})()}
{(() => {
if (this.state.stage === STAGE_RUNNING) {
return (
<Button
className="button"
type="primary"
danger
disabled={this.state.loading > 0 && this.state.loading !== 4}
loading={this.state.loading === 4}
icon={<PoweroffOutlined />}
onClick={this.stopConfirm}
>
停止
</Button>
);
}
})()}
</div>
</Content>
</Layout>
);
}
Example #25
Source File: CarMultiSelectionTable.tsx From jmix-frontend with Apache License 2.0 | 4 votes |
CarMultiSelectionTable = observer((props: EntityListProps<Car>) => {
const { entityList, onEntityListChange } = props;
const onOpenScreenError = useOpenScreenErrorCallback();
const onEntityDelete = useEntityDeleteCallback();
const {
items,
count,
relationOptions,
executeListQuery,
listQueryResult: { loading, error },
handleSelectionChange,
handleFilterChange,
handleSortOrderChange,
handlePaginationChange,
handleDeleteBtnClick,
goToParentScreen,
entityListState,
multiSelectionTableStore
} = useMultiSelectionTable<Car>({
listQuery: SCR_CAR_LIST,
entityName: ENTITY_NAME,
routingPath: ROUTING_PATH,
entityList,
onEntityListChange,
onPagination: saveHistory,
onEntityDelete,
onOpenScreenError,
lazyLoading: true
});
if (error != null) {
console.error(error);
return <RetryDialog onRetry={executeListQuery} />;
}
const buttons = [
<EntityPermAccessControl
entityName={ENTITY_NAME}
operation="delete"
key="delete"
>
<Button
htmlType="button"
style={{ margin: "0 12px 12px 0" }}
disabled={
multiSelectionTableStore.selectedEntityIds == null ||
multiSelectionTableStore.selectedEntityIds.length === 0
}
onClick={handleDeleteBtnClick}
key="remove"
type="default"
>
<FormattedMessage id="common.remove" />
</Button>
</EntityPermAccessControl>
];
if (entityList != null) {
buttons.unshift(
<Tooltip title={<FormattedMessage id="common.back" />}>
<Button
htmlType="button"
style={{ margin: "0 12px 12px 0" }}
icon={<LeftOutlined />}
onClick={goToParentScreen}
key="back"
type="default"
shape="circle"
/>
</Tooltip>
);
}
return (
<DataTable
tableId={ROUTING_PATH + ENTITY_NAME}
items={items}
count={count}
relationOptions={relationOptions}
current={entityListState.pagination?.current}
pageSize={entityListState.pagination?.pageSize}
entityName={ENTITY_NAME}
loading={loading}
error={error}
enableFiltersOnColumns={entityList != null ? [] : undefined}
enableSortingOnColumns={entityList != null ? [] : undefined}
columnDefinitions={[
"manufacturer",
"model",
"regNumber",
"purchaseDate",
"manufactureDate",
"wheelOnRight",
"carType",
"ecoRank",
"maxPassengers",
"price",
"mileage",
"garage",
"technicalCertificate"
]}
rowSelectionMode="multi"
onRowSelectionChange={handleSelectionChange}
onFilterChange={handleFilterChange}
onSortOrderChange={handleSortOrderChange}
onPaginationChange={handlePaginationChange}
buttons={buttons}
executeListQuery={entityList == null ? executeListQuery : undefined}
/>
);
})