@ant-design/icons#QuestionOutlined TypeScript Examples
The following examples show how to use
@ant-design/icons#QuestionOutlined.
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: FunctionDebuggerStatusbar.tsx From next-basics with GNU General Public License v3.0 | 5 votes |
export function FunctionDebuggerStatusbar({
coverage,
testStats,
}: FunctionDebuggerStatusbarProps): React.ReactElement {
const coverageIsOk = coverage && coverage.status !== "failed";
const totalCoverage = useMemo(
() => (coverageIsOk ? getTotalCoverage(coverage) : null),
[coverageIsOk, coverage]
);
const coverageStats = useMemo(
() => (coverageIsOk ? getCoverageStats(coverage) : null),
[coverageIsOk, coverage]
);
return (
<div className={styles.debuggerStatusbar} data-override-theme="dark">
<div className={styles.coverage}>
{coverage == null ? (
<span>
<span className={styles.coverageIcon}>
<QuestionOutlined />
</span>
<span>Coverage: expired</span>
</span>
) : testStats?.failed > 0 ? (
<span className={styles.hasFailedTests}>
<span className={styles.coverageIcon}>
<WarningOutlined />
</span>
<span>
{testStats.failed}/{testStats.total} tests failed!
</span>
</span>
) : coverageIsOk ? (
<>
<span
className={
totalCoverage < 60
? styles.coverageLow
: totalCoverage < 90
? styles.coverageMedium
: totalCoverage < 100
? styles.coverageHigh
: styles.coverageFull
}
>
<span className={styles.coverageIcon}>
{totalCoverage < 100 ? <WarningOutlined /> : <CheckOutlined />}
</span>
<span>Coverage: {totalCoverage}%</span>
</span>
{Object.entries(coverageStats).map(
([type, { covered, total, percentage }]) => (
<span key={type} className={styles.subCoverage}>
<span>{upperFirst(type)}: </span>
<span>
{percentage}% ({covered}/{total})
</span>
</span>
)
)}
</>
) : (
<span className={styles.coverageFailed}>
<span className={styles.coverageIcon}>
<CloseOutlined />
</span>
<span>{(coverage as RawCoverageFailed).error}</span>
</span>
)}
</div>
</div>
);
}
Example #2
Source File: TAQueueListItem.tsx From office-hours with GNU General Public License v3.0 | 5 votes |
export default function TAQueueListItem({
index,
selected,
question,
onClick,
showCheckbox,
}: {
index: number | false;
selected: boolean;
question: Question;
onClick: () => void;
showCheckbox?: boolean;
}): ReactElement {
const isDrafting = question.status === OpenQuestionStatus.Drafting;
const metaInfo: [ReactElement, string][] = [
[<HourglassOutlined key="h" />, getWaitTime(question)],
];
if (!isDrafting) {
metaInfo.push([<QuestionOutlined key="q" />, question.questionType]);
}
return (
<Container
selected={selected}
data-cy={`queue-list-item-${question.id}`}
onClick={onClick}
>
{showCheckbox && <StyledCheckbox checked={selected} />}
<BodyContainer>
<AvatarContainer>
<Badge
// 0 is not displayed, hide if no index
count={index ? `#${index}` : 0}
style={{ backgroundColor: "#3684c6" }}
offset={[-40, 0]}
>
<KOHAvatar
size={40}
name={question.creator.name}
photoURL={question.creator.photoURL}
/>
</Badge>
</AvatarContainer>
<QuestionInfoContainer>
<Name>{question.creator.name}</Name>
<QuestionText>
{isDrafting ? (
<i>Still Drafting...</i>
) : (
truncate(question.text, 80)
)}
</QuestionText>
<QuestionMetaRow info={metaInfo} />
</QuestionInfoContainer>
</BodyContainer>
</Container>
);
}
Example #3
Source File: palette.tsx From jmix-frontend with Apache License 2.0 | 4 votes |
palette = () => (
<Palette>
<Category name="Text">
<Component name="Formatted Message">
<Variant>
<FormattedMessage />
</Variant>
</Component>
<Component name="Heading">
<Variant name="h1">
<Typography.Title></Typography.Title>
</Variant>
<Variant name="h2">
<Typography.Title level={2}></Typography.Title>
</Variant>
<Variant name="h3">
<Typography.Title level={3}></Typography.Title>
</Variant>
<Variant name="h4">
<Typography.Title level={4}></Typography.Title>
</Variant>
<Variant name="h5">
<Typography.Title level={5}></Typography.Title>
</Variant>
</Component>
<Component name="Text">
<Variant>
<Typography.Text></Typography.Text>
</Variant>
<Variant name="Secondary">
<Typography.Text type="secondary"></Typography.Text>
</Variant>
<Variant name="Success">
<Typography.Text type="success"></Typography.Text>
</Variant>
<Variant name="Warning">
<Typography.Text type="warning"></Typography.Text>
</Variant>
<Variant name="Danger">
<Typography.Text type="danger"></Typography.Text>
</Variant>
<Variant name="Disabled">
<Typography.Text disabled></Typography.Text>
</Variant>
</Component>
</Category>
<Category name="Layout">
<Component name="Divider">
<Variant>
<Divider />
</Variant>
</Component>
<Component name="Grid">
<Variant name="Simple Row">
<Row></Row>
</Variant>
<Variant name="Two columns">
<Row>
<Col span={12}></Col>
<Col span={12}></Col>
</Row>
</Variant>
<Variant name="Three columns">
<Row>
<Col span={8}></Col>
<Col span={8}></Col>
<Col span={8}></Col>
</Row>
</Variant>
</Component>
<Component name="Space">
<Variant>
<Space />
</Variant>
<Variant name="Small">
<Space size={"small"} />
</Variant>
<Variant name="Large">
<Space size={"large"} />
</Variant>
</Component>
</Category>
<Category name="Controls">
<Component name="Autocomplete">
<Variant>
<AutoComplete placeholder="input here" />
</Variant>
</Component>
<Component name="Button">
<Variant>
<Button></Button>
</Variant>
<Variant name="Primary">
<Button type="primary"></Button>
</Variant>
<Variant name="Link">
<Button type="link"></Button>
</Variant>
<Variant name="Dropdown">
<Dropdown
trigger={["click"]}
overlay={
<Menu>
<Menu.Item></Menu.Item>
<Menu.Item></Menu.Item>
<Menu.Item></Menu.Item>
</Menu>
}
>
<Button></Button>
</Dropdown>
</Variant>
</Component>
<Component name="Checkbox">
<Variant>
<Checkbox />
</Variant>
</Component>
<Component name="Switch">
<Variant>
<Switch />
</Variant>
</Component>
<Component name="Radio Group">
<Variant>
<Radio.Group>
<Radio value={1}>A</Radio>
<Radio value={2}>B</Radio>
<Radio value={3}>C</Radio>
<Radio value={4}>D</Radio>
</Radio.Group>
</Variant>
<Variant name="Button">
<Radio.Group>
<Radio.Button value={1}>A</Radio.Button>
<Radio.Button value={2}>B</Radio.Button>
<Radio.Button value={3}>C</Radio.Button>
<Radio.Button value={4}>D</Radio.Button>
</Radio.Group>
</Variant>
</Component>
<Component name="DatePicker">
<Variant>
<DatePicker />
</Variant>
<Variant name="Range">
<DatePicker.RangePicker />
</Variant>
</Component>
<Component name="TimePicker">
<Variant>
<TimePicker />
</Variant>
<Variant name="Range">
<TimePicker.RangePicker />
</Variant>
</Component>
<Component name="Input">
<Variant>
<Input />
</Variant>
<Variant name="Number">
<InputNumber />
</Variant>
</Component>
<Component name="Select">
<Variant>
<Select defaultValue="1">
<Select.Option value="1">1</Select.Option>
<Select.Option value="2">2</Select.Option>
</Select>
</Variant>
<Variant name="Multiple">
<Select defaultValue={["1"]} mode="multiple" allowClear>
<Select.Option value="1">1</Select.Option>
<Select.Option value="2">2</Select.Option>
</Select>
</Variant>
</Component>
<Component name="Link">
<Variant>
<Typography.Link href="" target="_blank"></Typography.Link>
</Variant>
</Component>
<Component name="Slider">
<Variant>
<Slider defaultValue={30} />
</Variant>
<Variant name="Range">
<Slider range defaultValue={[20, 50]} />
</Variant>
</Component>
</Category>
<Category name="Data Display">
<Component name="Field">
<Variant>
<Field
entityName={ENTITY_NAME}
disabled={readOnlyMode}
propertyName=""
formItemProps={{
style: { marginBottom: "12px" }
}}
/>
</Variant>
</Component>
<Component name="Card">
<Variant>
<Card />
</Variant>
<Variant name="With Title">
<Card>
<Card title="Card title">
<p>Card content</p>
</Card>
</Card>
</Variant>
<Variant name="My custom card">
<Card>
<Card title="Card title">
<p>Card content</p>
<Avatar />
</Card>
</Card>
</Variant>
</Component>
<Component name="Tabs">
<Variant>
<Tabs defaultActiveKey="1">
<Tabs.TabPane tab="Tab 1" key="1">
Content of Tab Pane 1
</Tabs.TabPane>
<Tabs.TabPane tab="Tab 2" key="2">
Content of Tab Pane 2
</Tabs.TabPane>
<Tabs.TabPane tab="Tab 3" key="3">
Content of Tab Pane 3
</Tabs.TabPane>
</Tabs>
</Variant>
<Variant name="Tab Pane">
<Tabs.TabPane></Tabs.TabPane>
</Variant>
</Component>
<Component name="Collapse">
<Variant>
<Collapse defaultActiveKey="1">
<Collapse.Panel
header="This is panel header 1"
key="1"
></Collapse.Panel>
<Collapse.Panel
header="This is panel header 2"
key="2"
></Collapse.Panel>
<Collapse.Panel
header="This is panel header 3"
key="3"
></Collapse.Panel>
</Collapse>
</Variant>
</Component>
<Component name="Image">
<Variant>
<Image width={200} src="" />
</Variant>
</Component>
<Component name="Avatar">
<Variant>
<Avatar icon={<UserOutlined />} />
</Variant>
<Variant name="Image">
<Avatar src="https://joeschmoe.io/api/v1/random" />
</Variant>
</Component>
<Component name="Badge">
<Variant>
<Badge count={1}></Badge>
</Variant>
</Component>
<Component name="Statistic">
<Variant>
<Statistic title="Title" value={112893} />
</Variant>
</Component>
<Component name="Alert">
<Variant name="Success">
<Alert message="Text" type="success" />
</Variant>
<Variant name="Info">
<Alert message="Text" type="info" />
</Variant>
<Variant name="Warning">
<Alert message="Text" type="warning" />
</Variant>
<Variant name="Error">
<Alert message="Text" type="error" />
</Variant>
</Component>
<Component name="List">
<Variant>
<List
bordered
dataSource={[]}
renderItem={item => <List.Item></List.Item>}
/>
</Variant>
</Component>
</Category>
<Category name="Icons">
<Component name="Arrow">
<Variant name="Up">
<ArrowUpOutlined />
</Variant>
<Variant name="Down">
<ArrowDownOutlined />
</Variant>
<Variant name="Left">
<ArrowLeftOutlined />
</Variant>
<Variant name="Right">
<ArrowRightOutlined />
</Variant>
</Component>
<Component name="Question">
<Variant>
<QuestionOutlined />
</Variant>
<Variant name="Circle">
<QuestionCircleOutlined />
</Variant>
</Component>
<Component name="Plus">
<Variant>
<PlusOutlined />
</Variant>
<Variant name="Circle">
<PlusCircleOutlined />
</Variant>
</Component>
<Component name="Info">
<Variant>
<InfoOutlined />
</Variant>
<Variant name="Circle">
<InfoCircleOutlined />
</Variant>
</Component>
<Component name="Exclamation">
<Variant>
<ExclamationOutlined />
</Variant>
<Variant name="Circle">
<ExclamationCircleOutlined />
</Variant>
</Component>
<Component name="Close">
<Variant>
<CloseOutlined />
</Variant>
<Variant name="Circle">
<CloseCircleOutlined />
</Variant>
</Component>
<Component name="Check">
<Variant>
<CheckOutlined />
</Variant>
<Variant name="Circle">
<CheckCircleOutlined />
</Variant>
</Component>
<Component name="Edit">
<Variant>
<EditOutlined />
</Variant>
</Component>
<Component name="Copy">
<Variant>
<CopyOutlined />
</Variant>
</Component>
<Component name="Delete">
<Variant>
<DeleteOutlined />
</Variant>
</Component>
<Component name="Bars">
<Variant>
<BarsOutlined />
</Variant>
</Component>
<Component name="Bell">
<Variant>
<BellOutlined />
</Variant>
</Component>
<Component name="Clear">
<Variant>
<ClearOutlined />
</Variant>
</Component>
<Component name="Download">
<Variant>
<DownloadOutlined />
</Variant>
</Component>
<Component name="Upload">
<Variant>
<UploadOutlined />
</Variant>
</Component>
<Component name="Sync">
<Variant>
<SyncOutlined />
</Variant>
</Component>
<Component name="Save">
<Variant>
<SaveOutlined />
</Variant>
</Component>
<Component name="Search">
<Variant>
<SearchOutlined />
</Variant>
</Component>
<Component name="Settings">
<Variant>
<SettingOutlined />
</Variant>
</Component>
<Component name="Paperclip">
<Variant>
<PaperClipOutlined />
</Variant>
</Component>
<Component name="Phone">
<Variant>
<PhoneOutlined />
</Variant>
</Component>
<Component name="Mail">
<Variant>
<MailOutlined />
</Variant>
</Component>
<Component name="Home">
<Variant>
<HomeOutlined />
</Variant>
</Component>
<Component name="Contacts">
<Variant>
<ContactsOutlined />
</Variant>
</Component>
<Component name="User">
<Variant>
<UserOutlined />
</Variant>
<Variant name="Add">
<UserAddOutlined />
</Variant>
<Variant name="Remove">
<UserDeleteOutlined />
</Variant>
</Component>
<Component name="Team">
<Variant>
<TeamOutlined />
</Variant>
</Component>
</Category>
<Category name="Screens">
<Component name="ExampleCustomScreen">
<Variant>
<ExampleCustomScreen />
</Variant>
</Component>
<Component name="CustomEntityFilterTest">
<Variant>
<CustomEntityFilterTest />
</Variant>
</Component>
<Component name="CustomFormControls">
<Variant>
<CustomFormControls />
</Variant>
</Component>
<Component name="CustomDataDisplayComponents">
<Variant>
<CustomDataDisplayComponents />
</Variant>
</Component>
<Component name="CustomAppLayouts">
<Variant>
<CustomAppLayouts />
</Variant>
</Component>
<Component name="CustomControls">
<Variant>
<CustomControls />
</Variant>
</Component>
<Component name="ErrorBoundaryTests">
<Variant>
<ErrorBoundaryTests />
</Variant>
</Component>
<Component name="TestBlankScreen">
<Variant>
<TestBlankScreen />
</Variant>
</Component>
<Component name="CarEditor">
<Variant>
<CarEditor />
</Variant>
</Component>
<Component name="CarBrowserCards">
<Variant>
<CarBrowserCards />
</Variant>
</Component>
<Component name="CarBrowserList">
<Variant>
<CarBrowserList />
</Variant>
</Component>
<Component name="CarBrowserTable">
<Variant>
<CarBrowserTable />
</Variant>
</Component>
<Component name="CarCardsGrid">
<Variant>
<CarCardsGrid />
</Variant>
</Component>
<Component name="FavoriteCars">
<Variant>
<FavoriteCars />
</Variant>
</Component>
<Component name="CarCardsWithDetails">
<Variant>
<CarCardsWithDetails />
</Variant>
</Component>
<Component name="CarTableWithFilters">
<Variant>
<CarTableWithFilters />
</Variant>
</Component>
<Component name="CarMasterDetail">
<Variant>
<CarMasterDetail />
</Variant>
</Component>
<Component name="FormWizardCompositionO2O">
<Variant>
<FormWizardCompositionO2O />
</Variant>
</Component>
<Component name="FormWizardEditor">
<Variant>
<FormWizardEditor />
</Variant>
</Component>
<Component name="FormWizardBrowserTable">
<Variant>
<FormWizardBrowserTable />
</Variant>
</Component>
<Component name="CarMultiSelectionTable">
<Variant>
<CarMultiSelectionTable />
</Variant>
</Component>
<Component name="DatatypesTestEditor">
<Variant>
<DatatypesTestEditor />
</Variant>
</Component>
<Component name="DatatypesTestBrowserCards">
<Variant>
<DatatypesTestBrowserCards />
</Variant>
</Component>
<Component name="DatatypesTestBrowserList">
<Variant>
<DatatypesTestBrowserList />
</Variant>
</Component>
<Component name="DatatypesTestBrowserTable">
<Variant>
<DatatypesTestBrowserTable />
</Variant>
</Component>
<Component name="DatatypesTestCards">
<Variant>
<DatatypesTestCards />
</Variant>
</Component>
<Component name="AssociationO2OEditor">
<Variant>
<AssociationO2OEditor />
</Variant>
</Component>
<Component name="AssociationO2OBrowserTable">
<Variant>
<AssociationO2OBrowserTable />
</Variant>
</Component>
<Component name="AssociationO2MEditor">
<Variant>
<AssociationO2MEditor />
</Variant>
</Component>
<Component name="AssociationO2MBrowserTable">
<Variant>
<AssociationO2MBrowserTable />
</Variant>
</Component>
<Component name="AssociationM2OEditor">
<Variant>
<AssociationM2OEditor />
</Variant>
</Component>
<Component name="AssociationM2OBrowserTable">
<Variant>
<AssociationM2OBrowserTable />
</Variant>
</Component>
<Component name="AssociationM2MEditor">
<Variant>
<AssociationM2MEditor />
</Variant>
</Component>
<Component name="AssociationM2MBrowserTable">
<Variant>
<AssociationM2MBrowserTable />
</Variant>
</Component>
<Component name="CompositionO2OEditor">
<Variant>
<CompositionO2OEditor />
</Variant>
</Component>
<Component name="CompositionO2OBrowserTable">
<Variant>
<CompositionO2OBrowserTable />
</Variant>
</Component>
<Component name="CompositionO2MEditor">
<Variant>
<CompositionO2MEditor />
</Variant>
</Component>
<Component name="CompositionO2MBrowserTable">
<Variant>
<CompositionO2MBrowserTable />
</Variant>
</Component>
<Component name="DeeplyNestedTestEntityEditor">
<Variant>
<DeeplyNestedTestEntityEditor />
</Variant>
</Component>
<Component name="DeeplyNestedO2MTestEntityTable">
<Variant>
<DeeplyNestedO2MTestEntityTable />
</Variant>
</Component>
<Component name="DeeplyNestedO2MTestEntityEditor">
<Variant>
<DeeplyNestedO2MTestEntityEditor />
</Variant>
</Component>
<Component name="IntIdEditor">
<Variant>
<IntIdEditor />
</Variant>
</Component>
<Component name="IntIdBrowserTable">
<Variant>
<IntIdBrowserTable />
</Variant>
</Component>
<Component name="IntIdBrowserCards">
<Variant>
<IntIdBrowserCards />
</Variant>
</Component>
<Component name="IntIdBrowserList">
<Variant>
<IntIdBrowserList />
</Variant>
</Component>
<Component name="IntIdentityIdCards">
<Variant>
<IntIdentityIdCards />
</Variant>
</Component>
<Component name="IntIdentityIdEditor">
<Variant>
<IntIdentityIdEditor />
</Variant>
</Component>
<Component name="IntIdentityIdBrowserTable">
<Variant>
<IntIdentityIdBrowserTable />
</Variant>
</Component>
<Component name="IntIdentityIdBrowserCards">
<Variant>
<IntIdentityIdBrowserCards />
</Variant>
</Component>
<Component name="IntIdentityIdBrowserList">
<Variant>
<IntIdentityIdBrowserList />
</Variant>
</Component>
<Component name="StringIdCards">
<Variant>
<StringIdCards />
</Variant>
</Component>
<Component name="StringIdMgtCardsEdit">
<Variant>
<StringIdMgtCardsEdit />
</Variant>
</Component>
<Component name="StringIdBrowserCards">
<Variant>
<StringIdBrowserCards />
</Variant>
</Component>
<Component name="StringIdBrowserList">
<Variant>
<StringIdBrowserList />
</Variant>
</Component>
<Component name="StringIdBrowserTable">
<Variant>
<StringIdBrowserTable />
</Variant>
</Component>
<Component name="WeirdStringIdEditor">
<Variant>
<WeirdStringIdEditor />
</Variant>
</Component>
<Component name="WeirdStringIdBrowserCards">
<Variant>
<WeirdStringIdBrowserCards />
</Variant>
</Component>
<Component name="WeirdStringIdBrowserList">
<Variant>
<WeirdStringIdBrowserList />
</Variant>
</Component>
<Component name="WeirdStringIdBrowserTable">
<Variant>
<WeirdStringIdBrowserTable />
</Variant>
</Component>
<Component name="BoringStringIdEditor">
<Variant>
<BoringStringIdEditor />
</Variant>
</Component>
<Component name="BoringStringIdBrowserTable">
<Variant>
<BoringStringIdBrowserTable />
</Variant>
</Component>
<Component name="TrickyIdEditor">
<Variant>
<TrickyIdEditor />
</Variant>
</Component>
<Component name="TrickyIdBrowserTable">
<Variant>
<TrickyIdBrowserTable />
</Variant>
</Component>
</Category>
</Palette>
)
Example #4
Source File: palette.tsx From jmix-frontend with Apache License 2.0 | 4 votes |
palette = () =>
<Palette>
<Category name="Text">
<Component name="Formatted Message">
<Variant>
<FormattedMessage />
</Variant>
</Component>
<Component name="Heading">
<Variant name='h1'>
<Typography.Title></Typography.Title>
</Variant>
<Variant name='h2'>
<Typography.Title level = {2}></Typography.Title>
</Variant>
<Variant name='h3'>
<Typography.Title level = {3}></Typography.Title>
</Variant>
<Variant name='h4'>
<Typography.Title level = {4}></Typography.Title>
</Variant>
<Variant name='h5'>
<Typography.Title level = {5}></Typography.Title>
</Variant>
</Component>
<Component name='Text'>
<Variant>
<Typography.Text></Typography.Text>
</Variant>
<Variant name = 'Secondary'>
<Typography.Text type="secondary"></Typography.Text>
</Variant>
<Variant name = 'Success'>
<Typography.Text type="success"></Typography.Text>
</Variant>
<Variant name = 'Warning'>
<Typography.Text type="warning"></Typography.Text>
</Variant>
<Variant name = 'Danger'>
<Typography.Text type="danger"></Typography.Text>
</Variant>
<Variant name = 'Disabled'>
<Typography.Text disabled></Typography.Text>
</Variant>
</Component>
</Category>
<Category name="Layout">
<Component name="Divider">
<Variant>
<Divider />
</Variant>
</Component>
<Component name="Grid">
<Variant name="Simple Row">
<Row></Row>
</Variant>
<Variant name="Two columns">
<Row>
<Col span={12}></Col>
<Col span={12}></Col>
</Row>
</Variant>
<Variant name="Three columns">
<Row>
<Col span={8}></Col>
<Col span={8}></Col>
<Col span={8}></Col>
</Row>
</Variant>
</Component>
<Component name="Space">
<Variant>
<Space />
</Variant>
<Variant name="Small">
<Space size={"small"} />
</Variant>
<Variant name="Large">
<Space size={"large"} />
</Variant>
</Component>
</Category>
<Category name="Controls">
<Component name="Autocomplete">
<Variant>
<AutoComplete placeholder="input here" />
</Variant>
</Component>
<Component name="Button">
<Variant>
<Button></Button>
</Variant>
<Variant name="Primary">
<Button type="primary" ></Button>
</Variant>
<Variant name="Link">
<Button type="link" ></Button>
</Variant>
<Variant name="Dropdown">
<Dropdown
trigger={['click']}
overlay={<Menu>
<Menu.Item>
</Menu.Item>
<Menu.Item>
</Menu.Item>
<Menu.Item>
</Menu.Item>
</Menu>}
>
<Button></Button>
</Dropdown>
</Variant>
</Component>
<Component name="Checkbox">
<Variant>
<Checkbox />
</Variant>
</Component>
<Component name='Switch'>
<Variant>
<Switch />
</Variant>
</Component>
<Component name='Radio Group'>
<Variant>
<Radio.Group>
<Radio value={1}>A</Radio>
<Radio value={2}>B</Radio>
<Radio value={3}>C</Radio>
<Radio value={4}>D</Radio>
</Radio.Group>
</Variant>
<Variant name = 'Button'>
<Radio.Group>
<Radio.Button value={1}>A</Radio.Button>
<Radio.Button value={2}>B</Radio.Button>
<Radio.Button value={3}>C</Radio.Button>
<Radio.Button value={4}>D</Radio.Button>
</Radio.Group>
</Variant>
</Component>
<Component name="DatePicker">
<Variant>
<DatePicker />
</Variant>
<Variant name="Range">
<DatePicker.RangePicker />
</Variant>
</Component>
<Component name="TimePicker">
<Variant>
<TimePicker />
</Variant>
<Variant name="Range">
<TimePicker.RangePicker />
</Variant>
</Component>
<Component name="Input">
<Variant>
<Input />
</Variant>
<Variant name='Number'>
<InputNumber />
</Variant>
</Component>
<Component name='Select'>
<Variant>
<Select defaultValue="1">
<Select.Option value="1">1</Select.Option>
<Select.Option value="2">2</Select.Option>
</Select>
</Variant>
<Variant name='Multiple'>
<Select
defaultValue={["1"]}
mode="multiple"
allowClear
>
<Select.Option value="1">1</Select.Option>
<Select.Option value="2">2</Select.Option>
</Select>
</Variant>
</Component>
<Component name="Link">
<Variant>
<Typography.Link href="" target="_blank">
</Typography.Link>
</Variant>
</Component>
<Component name='Slider'>
<Variant>
<Slider defaultValue={30} />
</Variant>
<Variant name = 'Range'>
<Slider range defaultValue={[20, 50]}/>
</Variant>
</Component>
</Category>
<Category name="Data Display">
<Component name="Field">
<Variant>
<Field
entityName={ENTITY_NAME}
disabled={readOnlyMode}
propertyName=''
formItemProps={{
style: { marginBottom: "12px" }
}}
/>
</Variant>
</Component>
<Component name="Card">
<Variant>
<Card />
</Variant>
<Variant name="With Title">
<Card>
<Card title="Card title">
<p>Card content</p>
</Card>
</Card>
</Variant>
<Variant name="My custom card">
<Card>
<Card title="Card title">
<p>Card content</p>
<Avatar />
</Card>
</Card>
</Variant>
</Component>
<Component name="Tabs">
<Variant>
<Tabs defaultActiveKey="1">
<Tabs.TabPane tab="Tab 1" key="1">
Content of Tab Pane 1
</Tabs.TabPane>
<Tabs.TabPane tab="Tab 2" key="2">
Content of Tab Pane 2
</Tabs.TabPane>
<Tabs.TabPane tab="Tab 3" key="3">
Content of Tab Pane 3
</Tabs.TabPane>
</Tabs>
</Variant>
<Variant name = "Tab Pane">
<Tabs.TabPane>
</Tabs.TabPane>
</Variant>
</Component>
<Component name="Collapse">
<Variant>
<Collapse defaultActiveKey='1'>
<Collapse.Panel header="This is panel header 1" key="1">
</Collapse.Panel>
<Collapse.Panel header="This is panel header 2" key="2">
</Collapse.Panel>
<Collapse.Panel header="This is panel header 3" key="3">
</Collapse.Panel>
</Collapse>
</Variant>
</Component>
<Component name="Image">
<Variant>
<Image
width={200}
src=""
/>
</Variant>
</Component>
<Component name="Avatar">
<Variant>
<Avatar icon={<UserOutlined />} />
</Variant>
<Variant name="Image">
<Avatar src="https://joeschmoe.io/api/v1/random" />
</Variant>
</Component>
<Component name="Badge">
<Variant>
<Badge count={1}>
</Badge>
</Variant>
</Component>
<Component name="Statistic">
<Variant>
<Statistic title="Title" value={112893} />
</Variant>
</Component>
<Component name="Alert">
<Variant name="Success">
<Alert message="Text" type="success" />
</Variant>
<Variant name="Info">
<Alert message="Text" type="info" />
</Variant>
<Variant name="Warning">
<Alert message="Text" type="warning" />
</Variant>
<Variant name="Error">
<Alert message="Text" type="error" />
</Variant>
</Component>
<Component name='List'>
<Variant>
<List
bordered
dataSource={[]}
renderItem={item => (
<List.Item>
</List.Item>
)}
/>
</Variant>
</Component>
</Category>
<Category name="Icons">
<Component name="Arrow">
<Variant name = 'Up'>
<ArrowUpOutlined />
</Variant>
<Variant name = 'Down'>
<ArrowDownOutlined />
</Variant>
<Variant name = 'Left'>
<ArrowLeftOutlined />
</Variant>
<Variant name = 'Right'>
<ArrowRightOutlined />
</Variant>
</Component>
<Component name = 'Question'>
<Variant>
<QuestionOutlined />
</Variant>
<Variant name = 'Circle'>
<QuestionCircleOutlined />
</Variant>
</Component>
<Component name = 'Plus'>
<Variant>
<PlusOutlined />
</Variant>
<Variant name = 'Circle'>
<PlusCircleOutlined />
</Variant>
</Component>
<Component name = 'Info'>
<Variant>
<InfoOutlined />
</Variant>
<Variant name = 'Circle'>
<InfoCircleOutlined />
</Variant>
</Component>
<Component name = 'Exclamation'>
<Variant>
<ExclamationOutlined />
</Variant>
<Variant name = 'Circle'>
<ExclamationCircleOutlined />
</Variant>
</Component>
<Component name = 'Close'>
<Variant>
<CloseOutlined />
</Variant>
<Variant name = 'Circle'>
<CloseCircleOutlined />
</Variant>
</Component>
<Component name = 'Check'>
<Variant>
<CheckOutlined />
</Variant>
<Variant name = 'Circle'>
<CheckCircleOutlined />
</Variant>
</Component>
<Component name = 'Edit'>
<Variant>
<EditOutlined />
</Variant>
</Component>
<Component name = 'Copy'>
<Variant>
<CopyOutlined />
</Variant>
</Component>
<Component name = 'Delete'>
<Variant>
<DeleteOutlined />
</Variant>
</Component>
<Component name = 'Bars'>
<Variant>
<BarsOutlined />
</Variant>
</Component>
<Component name = 'Bell'>
<Variant>
<BellOutlined />
</Variant>
</Component>
<Component name = 'Clear'>
<Variant>
<ClearOutlined />
</Variant>
</Component>
<Component name = 'Download'>
<Variant>
<DownloadOutlined />
</Variant>
</Component>
<Component name = 'Upload'>
<Variant>
<UploadOutlined />
</Variant>
</Component>
<Component name = 'Sync'>
<Variant>
<SyncOutlined />
</Variant>
</Component>
<Component name = 'Save'>
<Variant>
<SaveOutlined />
</Variant>
</Component>
<Component name = 'Search'>
<Variant>
<SearchOutlined />
</Variant>
</Component>
<Component name = 'Settings'>
<Variant>
<SettingOutlined />
</Variant>
</Component>
<Component name = 'Paperclip'>
<Variant>
<PaperClipOutlined />
</Variant>
</Component>
<Component name = 'Phone'>
<Variant>
<PhoneOutlined />
</Variant>
</Component>
<Component name = 'Mail'>
<Variant>
<MailOutlined />
</Variant>
</Component>
<Component name = 'Home'>
<Variant>
<HomeOutlined />
</Variant>
</Component>
<Component name = 'Contacts'>
<Variant>
<ContactsOutlined />
</Variant>
</Component>
<Component name = 'User'>
<Variant>
<UserOutlined />
</Variant>
<Variant name = 'Add'>
<UserAddOutlined />
</Variant>
<Variant name = 'Remove'>
<UserDeleteOutlined />
</Variant>
</Component>
<Component name = 'Team'>
<Variant>
<TeamOutlined />
</Variant>
</Component>
</Category>
</Palette>
Example #5
Source File: ToolbarButton.tsx From posthog-foss with MIT License | 4 votes |
export function ToolbarButton(): JSX.Element {
const {
extensionPercentage,
heatmapInfoVisible,
toolbarListVerticalPadding,
helpButtonOnTop,
side,
closeDistance,
closeRotation,
inspectExtensionPercentage,
heatmapExtensionPercentage,
actionsExtensionPercentage,
actionsInfoVisible,
featureFlagsExtensionPercentage,
flagsVisible,
} = useValues(toolbarButtonLogic)
const {
setExtensionPercentage,
showHeatmapInfo,
hideHeatmapInfo,
showActionsInfo,
hideActionsInfo,
showFlags,
hideFlags,
} = useActions(toolbarButtonLogic)
const { buttonActionsVisible, showActionsTooltip } = useValues(actionsTabLogic)
const { hideButtonActions, showButtonActions } = useActions(actionsTabLogic)
const { actionCount, allActionsLoading } = useValues(actionsLogic)
const { enableInspect, disableInspect } = useActions(elementsLogic)
const { inspectEnabled, selectedElement } = useValues(elementsLogic)
const { enableHeatmap, disableHeatmap } = useActions(heatmapLogic)
const { heatmapEnabled, heatmapLoading, elementCount, showHeatmapTooltip } = useValues(heatmapLogic)
const { isAuthenticated } = useValues(toolbarLogic)
const { authenticate, logout } = useActions(toolbarLogic)
const globalMouseMove = useRef((e: MouseEvent) => {
e
})
useEffect(() => {
globalMouseMove.current = function (e: MouseEvent): void {
const buttonDiv = getShadowRoot()?.getElementById('button-toolbar')
if (buttonDiv) {
const rect = buttonDiv.getBoundingClientRect()
const x = rect.left + rect.width / 2
const y = rect.top + rect.height / 2
const distance = Math.sqrt((e.clientX - x) * (e.clientX - x) + (e.clientY - y) * (e.clientY - y))
const maxDistance = isAuthenticated ? 300 : 100
if (distance >= maxDistance && toolbarButtonLogic.values.extensionPercentage !== 0) {
setExtensionPercentage(0)
}
}
}
window.addEventListener('mousemove', globalMouseMove.current)
return () => window.removeEventListener('mousemove', globalMouseMove.current)
}, [isAuthenticated])
// using useLongPress for short presses (clicks) since it detects if the element was dragged (no click) or not (click)
const clickEvents = useLongPress(
(clicked) => {
if (clicked) {
if (isAuthenticated) {
setExtensionPercentage(extensionPercentage === 1 ? 0 : 1)
} else {
authenticate()
}
}
},
{
ms: undefined,
clickMs: 1,
touch: true,
click: true,
}
)
const borderRadius = 14
const buttonWidth = 42
let n = 0
return (
<Circle
rootNode
width={62}
className="floating-toolbar-button"
content={<HogLogo style={{ width: 45, cursor: 'pointer' }} />}
{...clickEvents}
onMouseOver={isAuthenticated ? undefined : () => setExtensionPercentage(1)}
style={{ borderRadius: 10, height: 46, marginTop: -23 }}
zIndex={3}
>
<Circle
width={26}
extensionPercentage={extensionPercentage}
distance={closeDistance}
rotation={closeRotation}
content={<Close style={{ width: 14, height: 14 }} />}
zIndex={extensionPercentage > 0.95 ? 5 : 2}
onClick={logout}
style={{
cursor: 'pointer',
background: '#393939',
borderRadius: 6,
color: 'white',
transform: `scale(${0.2 + 0.8 * extensionPercentage})`,
}}
/>
{isAuthenticated ? (
<>
<Circle
width={32}
extensionPercentage={extensionPercentage}
distance={helpButtonOnTop ? 75 : 55}
rotation={helpButtonOnTop ? (side === 'left' ? -95 + 360 : -95) : 90}
content={<QuestionOutlined style={{ fontSize: 22 }} />}
label="Help"
zIndex={2}
onClick={() => window.open(HELP_URL, '_blank')?.focus()}
labelStyle={{ opacity: extensionPercentage > 0.8 ? (extensionPercentage - 0.8) / 0.2 : 0 }}
style={{
cursor: 'pointer',
background: '#777',
color: 'white',
borderRadius: 10,
transform: `scale(${0.2 + 0.8 * extensionPercentage})`,
}}
/>
<Circle
width={buttonWidth}
x={side === 'left' ? 80 : -80}
y={toolbarListVerticalPadding + n++ * 60}
extensionPercentage={inspectExtensionPercentage}
rotationFixer={(r) => (side === 'right' && r < 0 ? 360 : 0)}
label="Inspect"
labelPosition={side === 'left' ? 'right' : 'left'}
labelStyle={{
opacity: inspectExtensionPercentage > 0.8 ? (inspectExtensionPercentage - 0.8) / 0.2 : 0,
}}
content={
<div style={{ position: 'relative' }}>
<Magnifier style={{ height: 34, paddingTop: 2 }} engaged={inspectEnabled} />
{inspectEnabled && selectedElement ? (
<div
style={{
position: 'absolute',
top: 8,
left: 9,
fontSize: 13,
color: 'white',
}}
>
<Close style={{ width: 10, height: 10 }} />
</div>
) : null}
</div>
}
zIndex={1}
onClick={inspectEnabled ? disableInspect : enableInspect}
style={{
cursor: 'pointer',
background: inspectEnabled ? '#8F98FF' : '#E7EAFD',
transition: 'transform 0.2s, color 0.2s, background: 0.2s',
transform: `scale(${0.2 + 0.8 * inspectExtensionPercentage})`,
borderRadius,
}}
/>
<Circle
width={buttonWidth}
x={side === 'left' ? 80 : -80}
y={toolbarListVerticalPadding + n++ * 60}
extensionPercentage={heatmapExtensionPercentage}
rotationFixer={(r) => (side === 'right' && r < 0 ? 360 : 0)}
label={heatmapEnabled && !heatmapLoading ? null : 'Heatmap'}
labelPosition={side === 'left' ? 'right' : 'left'}
labelStyle={{
opacity:
heatmapEnabled && !heatmapLoading
? 0
: heatmapExtensionPercentage > 0.8
? (heatmapExtensionPercentage - 0.8) / 0.2
: 0,
}}
content={<Fire style={{ height: 26 }} engaged={heatmapEnabled} animated={heatmapLoading} />}
zIndex={2}
onClick={heatmapEnabled ? disableHeatmap : enableHeatmap}
style={{
cursor: 'pointer',
background: heatmapEnabled ? '#FF9870' : '#FEE3DA',
transform: `scale(${0.2 + 0.8 * heatmapExtensionPercentage})`,
borderRadius,
}}
>
{heatmapEnabled && !heatmapLoading ? (
<Circle
width={26}
x={
(side === 'left' ? 50 : -50) *
heatmapExtensionPercentage *
heatmapExtensionPercentage
}
y={0}
content={
<Tooltip
visible={showHeatmapTooltip}
title="Click for details"
placement={side === 'left' ? 'right' : 'left'}
getPopupContainer={getShadowRootPopupContainer}
>
<div style={{ whiteSpace: 'nowrap', textAlign: 'center' }}>{elementCount}</div>
</Tooltip>
}
zIndex={4}
onClick={heatmapInfoVisible ? hideHeatmapInfo : showHeatmapInfo}
style={{
cursor: 'pointer',
background: heatmapInfoVisible ? 'hsla(17, 100%, 47%, 1)' : 'hsla(17, 84%, 95%, 1)',
color: heatmapInfoVisible ? '#FFEB3B' : 'hsl(17, 64%, 32%)',
width: 'auto',
minWidth: 26,
fontSize: '20px',
lineHeight: '26px',
padding: '0 4px',
transform: `scale(${0.2 + 0.8 * heatmapExtensionPercentage})`,
borderRadius: 7,
}}
/>
) : null}
</Circle>
<Circle
width={buttonWidth}
x={side === 'left' ? 80 : -80}
y={toolbarListVerticalPadding + n++ * 60}
extensionPercentage={actionsExtensionPercentage}
rotationFixer={(r) => (side === 'right' && r < 0 ? 360 : 0)}
label={buttonActionsVisible && (!allActionsLoading || actionCount > 0) ? null : 'Actions'}
labelPosition={side === 'left' ? 'right' : 'left'}
labelStyle={{
opacity: actionsExtensionPercentage > 0.8 ? (actionsExtensionPercentage - 0.8) / 0.2 : 0,
}}
content={
<AimOutlined
style={{ fontSize: '28px', color: buttonActionsVisible ? '#fef5e2' : '#f1aa04' }}
/>
}
zIndex={1}
onClick={buttonActionsVisible ? hideButtonActions : showButtonActions}
style={{
cursor: 'pointer',
transform: `scale(${0.2 + 0.8 * actionsExtensionPercentage})`,
background: buttonActionsVisible ? '#f1aa04' : '#fef5e2',
borderRadius,
}}
>
{buttonActionsVisible && (!allActionsLoading || actionCount > 0) ? (
<Circle
width={26}
x={
(side === 'left' ? 50 : -50) *
actionsExtensionPercentage *
actionsExtensionPercentage
}
y={0}
content={
<Tooltip
visible={showActionsTooltip}
title="Click for details"
placement={side === 'left' ? 'right' : 'left'}
getPopupContainer={getShadowRootPopupContainer}
>
<div style={{ whiteSpace: 'nowrap', textAlign: 'center' }}>{actionCount}</div>
</Tooltip>
}
zIndex={4}
onClick={actionsInfoVisible ? hideActionsInfo : showActionsInfo}
style={{
cursor: 'pointer',
background: actionsInfoVisible ? '#f1aa04' : '#fef5e2',
color: actionsInfoVisible ? '#fef5e2' : '#f1aa04',
width: 'auto',
minWidth: 26,
fontSize: '20px',
lineHeight: '26px',
padding: '0 4px',
transform: `scale(${0.2 + 0.8 * actionsExtensionPercentage})`,
borderRadius: 7,
}}
/>
) : null}
</Circle>
<Circle
width={buttonWidth}
x={side === 'left' ? 80 : -80}
y={toolbarListVerticalPadding + n++ * 60}
extensionPercentage={featureFlagsExtensionPercentage}
rotationFixer={(r) => (side === 'right' && r < 0 ? 360 : 0)}
label="Feature Flags"
labelPosition={side === 'left' ? 'right' : 'left'}
labelStyle={{
opacity:
featureFlagsExtensionPercentage > 0.8
? (featureFlagsExtensionPercentage - 0.8) / 0.2
: 0,
}}
content={<Flag style={{ height: 29 }} engaged={flagsVisible} />}
zIndex={1}
onClick={flagsVisible ? hideFlags : showFlags}
style={{
cursor: 'pointer',
transform: `scale(${0.2 + 0.8 * featureFlagsExtensionPercentage})`,
background: flagsVisible ? '#94D674' : '#D6EBCC',
borderRadius,
}}
/>
</>
) : null}
</Circle>
)
}
Example #6
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 #7
Source File: FunctionDebuggerSidebar.tsx From next-basics with GNU General Public License v3.0 | 4 votes |
export function FunctionDebuggerSidebar({
functionName,
functionModified,
activeTab,
tests,
onActiveTabSwitch,
onRunAllTests,
onAddTest,
}: FunctionDebuggerSidebarProps): React.ReactElement {
const [currentTab, setCurrentTab] = useState<string>(activeTab ?? "function");
useEffect(() => {
setCurrentTab(activeTab ?? "function");
}, [activeTab]);
const groups: SidebarGroup[] = useMemo(() => {
const refinedTests = Array.isArray(tests) ? tests : [];
return [
{
label: "Function",
value: "function",
items: [
{
label: functionName,
value: "function",
icon: <CodeOutlined />,
modified: functionModified,
},
],
},
{
label: "Debug",
value: "debug",
items: [
{
label: "Debug",
value: "debug",
icon: <BugOutlined />,
},
],
},
{
label: `Tests (${refinedTests.length})`,
value: "tests",
items: refinedTests.map((test, index) => ({
label: test.name ?? `Case ${index + 1}`,
value: `test:${String(index)}`,
modified: test.testModified,
...(test.testMatched
? {
icon: <CheckOutlined />,
className: styles.matched,
}
: test.testMatched === false
? {
icon: <CloseOutlined />,
className: styles.notMatched,
}
: {
icon: <QuestionOutlined />,
}),
})),
},
];
}, [functionModified, functionName, tests]);
const switchActiveTab = useCallback(
(tab: string) => {
if (currentTab !== tab) {
setCurrentTab(tab);
onActiveTabSwitch?.(tab);
}
},
[currentTab, onActiveTabSwitch]
);
return (
<div
className={`${styles.sidebarContainer} ${sharedStyles.customScrollbarContainer}`}
data-override-theme="dark"
>
<ul className={styles.sidebarGroups}>
{groups.map((group) => (
<li key={group.label}>
<div className={styles.sidebarGroupLabel}>
<span className={styles.groupText}>{group.label}</span>
{group.value === "tests" && (
<div className={styles.groupIconContainer}>
{group.items.length > 0 && (
<span
className={styles.groupIcon}
title="Run All Tests"
onClick={onRunAllTests}
>
<PlayCircleOutlined />
</span>
)}
<span
className={styles.groupIcon}
title="Add Test"
onClick={onAddTest}
>
<PlusCircleOutlined />
</span>
</div>
)}
</div>
<ul className={styles.sidebarItems}>
{group.items.map((item) => (
<li
key={item.label}
className={classNames({
[styles.active]: item.value === currentTab,
})}
onClick={() => switchActiveTab(item.value)}
>
<span className={classNames(styles.icon, item.className)}>
{item.icon}
</span>
<span className={styles.text}>{item.label}</span>
{item.modified && <span className={styles.modified}></span>}
</li>
))}
</ul>
</li>
))}
</ul>
</div>
);
}
Example #8
Source File: FunctionDebuggerStatusbar.spec.tsx From next-basics with GNU General Public License v3.0 | 4 votes |
describe("FunctionDebuggerStatusbar", () => {
const getCoverage = (coveredStatements: number): any => ({
statements: {
covered: coveredStatements,
total: 16,
},
branches: {
covered: 3,
total: 3,
},
functions: {
covered: 1,
total: 1,
},
lines: {
covered: 2,
total: 2,
counts: new Map(),
},
});
it("should work for nil coverage", () => {
const wrapper = shallow(<FunctionDebuggerStatusbar />);
expect(wrapper.find(".coverageIcon").childAt(0).type()).toBe(
QuestionOutlined
);
});
it("should work for empty coverage", () => {
const wrapper = shallow(
<FunctionDebuggerStatusbar
coverage={
{
statements: {
covered: 0,
total: 0,
},
branches: {
covered: 0,
total: 0,
},
functions: {
covered: 0,
total: 0,
},
lines: {
covered: 0,
total: 0,
},
} as any
}
/>
);
expect(wrapper.find(".coverageFull").childAt(1).text()).toBe(
"Coverage: 100%"
);
});
it("should work for 100% coverage", () => {
const wrapper = shallow(
<FunctionDebuggerStatusbar coverage={getCoverage(16)} />
);
expect(wrapper.find(".coverageFull").childAt(1).text()).toBe(
"Coverage: 100%"
);
});
it("should work for 95% coverage with nil test stats", () => {
const wrapper = shallow(
<FunctionDebuggerStatusbar
coverage={getCoverage(15)}
testStats={{
total: undefined,
failed: undefined,
}}
/>
);
expect(wrapper.find(".coverageHigh").childAt(1).text()).toBe(
"Coverage: 95%"
);
});
it("should work for 85% coverage with no failed tests", () => {
const wrapper = shallow(
<FunctionDebuggerStatusbar
coverage={getCoverage(13)}
testStats={{
total: 3,
failed: 0,
}}
/>
);
expect(wrapper.find(".coverageMedium").childAt(1).text()).toBe(
"Coverage: 85%"
);
});
it("should work for 55% coverage with failed tests", () => {
const wrapper = shallow(
<FunctionDebuggerStatusbar
coverage={getCoverage(7)}
testStats={{
total: 3,
failed: 2,
}}
/>
);
expect(wrapper.find(".hasFailedTests").childAt(1).text()).toBe(
"2/3 tests failed!"
);
});
it("should work for failed coverage", () => {
const wrapper = shallow(
<FunctionDebuggerStatusbar
coverage={{
status: "failed",
error: "oops",
}}
/>
);
expect(wrapper.find(".coverageFailed").childAt(1).text()).toBe("oops");
});
});
Example #9
Source File: FunctionDebuggerToolbar.tsx From next-basics with GNU General Public License v3.0 | 4 votes |
export function FunctionDebuggerToolbar({
type,
status,
saveDisabled,
onButtonClick,
}: FunctionDebuggerToolbarProps): React.ReactElement {
const refinedType = type ?? "input";
const isInput = refinedType === "input" || refinedType === "test-input";
const handleRunClick = useCallback(() => {
onButtonClick?.({ action: "run" });
}, [onButtonClick]);
const handleSaveClick = useCallback(() => {
if (!saveDisabled) {
onButtonClick?.({ action: "save" });
}
}, [onButtonClick, saveDisabled]);
const handleDeleteClick = useCallback(() => {
onButtonClick?.({ action: "delete" });
}, [onButtonClick]);
return (
<div
className={classNames(
styles.debuggerToolbar,
status && styles[status],
refinedType === "input" || refinedType === "output"
? styles.debug
: styles.test,
isInput ? styles.input : styles.output
)}
data-override-theme="dark"
>
<div className={styles.header}>
{refinedType === "input"
? "Input"
: refinedType === "test-input"
? "Test Input"
: refinedType === "test-output"
? "Expect Output"
: "Output"}
{isInput && (
<span className={styles.headerSuffix}>
(argument list in JSON format)
</span>
)}
</div>
{isInput ? (
<div className={styles.buttons}>
<Tooltip title="Run">
<div className={styles.debuggerButton} onClick={handleRunClick}>
<PlayCircleOutlined />
</div>
</Tooltip>
<Tooltip
title={refinedType === "input" ? "Add as a test case" : "Update"}
>
<div
className={classNames(styles.debuggerButton, {
[styles.disabled]: saveDisabled,
})}
onClick={handleSaveClick}
>
{refinedType === "input" ? (
<PlusCircleOutlined />
) : (
<SaveOutlined />
)}
</div>
</Tooltip>
{refinedType === "test-input" && (
<Tooltip title="Delete">
<div
className={styles.debuggerButton}
onClick={handleDeleteClick}
>
<DeleteOutlined />
</div>
</Tooltip>
)}
</div>
) : (
refinedType === "test-output" && (
<div className={styles.secondHeader}>
{status === "ok" ? (
<>
<span className={styles.secondHeaderIcon}>
<CheckOutlined />
</span>
<span>Test: passed</span>
</>
) : status === "failed" ? (
<>
<span className={styles.secondHeaderIcon}>
<CloseOutlined />
</span>
<span>Test: failed</span>
</>
) : (
<>
<span className={styles.secondHeaderIcon}>
<QuestionOutlined />
</span>
<span>Test: expired</span>
</>
)}
</div>
)
)}
</div>
);
}
Example #10
Source File: TAQueueDetailButtons.tsx From office-hours with GNU General Public License v3.0 | 4 votes |
export default function TAQueueDetailButtons({
courseId,
queueId,
question,
hasUnresolvedRephraseAlert,
}: {
courseId: number;
queueId: number;
question: Question;
hasUnresolvedRephraseAlert: boolean;
}): ReactElement {
const defaultMessage = useDefaultMessage();
const { mutateQuestions } = useQuestions(queueId);
const changeStatus = useCallback(
async (status: QuestionStatus) => {
await API.questions.update(question.id, { status });
mutateQuestions();
},
[question.id, mutateQuestions]
);
const { isCheckedIn, isHelping } = useTAInQueueInfo(queueId);
const openTeams = useTeams(queueId, question.creator.email, defaultMessage);
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const sendRephraseAlert = async () => {
const payload: RephraseQuestionPayload = {
queueId,
questionId: question.id,
courseId,
};
try {
await API.alerts.create({
alertType: AlertType.REPHRASE_QUESTION,
courseId,
payload,
targetUserId: question.creator.id,
});
await mutateQuestions();
message.success("Successfully asked student to rephrase their question.");
} catch (e) {
//If the ta creates an alert that already exists the error is caught and nothing happens
}
};
const helpStudent = () => {
changeStatus(OpenQuestionStatus.Helping);
openTeams();
};
const deleteQuestion = async () => {
await changeStatus(
question.status === OpenQuestionStatus.Drafting
? ClosedQuestionStatus.DeletedDraft
: LimboQuestionStatus.TADeleted
);
await API.questions.notify(question.id);
};
useHotkeys(
"shift+d",
() => {
if (isCheckedIn) {
deleteQuestion();
}
},
[question]
);
if (question.status === OpenQuestionStatus.Helping) {
return (
<>
<Popconfirm
title="Are you sure you want to send this student back to the queue?"
okText="Yes"
cancelText="No"
onConfirm={async () => {
message.success(PRORITY_QUEUED_MESSAGE_TEXT, 2);
await changeStatus(LimboQuestionStatus.ReQueueing);
}}
>
<Tooltip title="Requeue Student">
<RequeueButton
icon={<UndoOutlined />}
data-cy="requeue-student-button"
/>
</Tooltip>
</Popconfirm>
<Popconfirm
title="Are you sure you can't find this student?"
okText="Yes"
cancelText="No"
onConfirm={async () => {
message.success(PRORITY_QUEUED_MESSAGE_TEXT, 2);
await changeStatus(LimboQuestionStatus.CantFind);
await API.questions.notify(question.id);
}}
>
<Tooltip title="Can't Find">
<CantFindButton
shape="circle"
icon={<CloseOutlined />}
data-cy="cant-find-button"
/>
</Tooltip>
</Popconfirm>
<Tooltip title="Finish Helping">
<FinishHelpingButton
icon={<CheckOutlined />}
onClick={() => changeStatus(ClosedQuestionStatus.Resolved)}
data-cy="finish-helping-button"
/>
</Tooltip>
</>
);
} else {
const [canHelp, helpTooltip] = ((): [boolean, string] => {
if (!isCheckedIn) {
return [false, "You must check in to help students!"];
} else if (isHelping) {
return [false, "You are already helping a student"];
} else {
return [true, "Help Student"];
}
})();
const [canRephrase, rephraseTooltip] = ((): [boolean, string] => {
if (!isCheckedIn) {
return [
false,
"You must check in to ask this student to rephrase their question",
];
} else if (hasUnresolvedRephraseAlert) {
return [
false,
"The student has already been asked to rephrase their question",
];
} else if (question.status === OpenQuestionStatus.Drafting) {
return [
false,
"The student must finish drafting before they can be asked to rephrase their question",
];
} else {
return [true, "Ask the student to add more detail to their question"];
}
})();
return (
<>
<Popconfirm
title="Are you sure you want to delete this question from the queue?"
disabled={!isCheckedIn}
okText="Yes"
cancelText="No"
onConfirm={async () => {
await deleteQuestion();
}}
>
<Tooltip
title={
isCheckedIn
? "Remove From Queue"
: "You must check in to remove students from the queue"
}
>
<span>
{/* This span is a workaround for tooltip-on-disabled-button
https://github.com/ant-design/ant-design/issues/9581#issuecomment-599668648 */}
<BannerDangerButton
shape="circle"
icon={<DeleteOutlined />}
data-cy="remove-from-queue"
disabled={!isCheckedIn}
/>
</span>
</Tooltip>
</Popconfirm>
<Tooltip title={rephraseTooltip}>
<span>
<BannerOrangeButton
shape="circle"
icon={<QuestionOutlined />}
onClick={sendRephraseAlert}
data-cy="request-rephrase-question"
disabled={!canRephrase}
/>
</span>
</Tooltip>
<Tooltip title={helpTooltip}>
<span>
<BannerPrimaryButton
icon={<PhoneOutlined />}
onClick={() => helpStudent()}
disabled={!canHelp}
data-cy="help-student"
/>
</span>
</Tooltip>
</>
);
}
}
Example #11
Source File: ReportViewerPage.tsx From yakit with GNU Affero General Public License v3.0 | 4 votes |
ReportList: React.FC<ReportListProp> = React.memo((props) => {
const [response, setResponse] = useState<QueryGeneralResponse<Report>>({
Data: [],
Pagination: genDefaultPagination(20),
Total: 0
})
const [params, setParams] = useState<QueryReports>({
From: "",
Keyword: "",
Owner: "",
Pagination: genDefaultPagination(),
Title: ""
})
const [loading, setLoading] = useState(false);
const pagination = params.Pagination;
const total = response.Total;
const update = useMemoizedFn((page?: number, limit?: number) => {
const pagination = {...params.Pagination};
if (!!page) {
pagination.Page = page
}
if (!!limit) {
pagination.Limit = limit
}
setLoading(true)
ipcRenderer.invoke("QueryReports", {
...params,
Pagination: pagination
}).then((rsp: QueryGeneralResponse<Report>) => {
if (rsp) setResponse(rsp)
}).catch(e => {
failed("Query Reports Failed")
console.info(e)
}).finally(() => setTimeout(() => setLoading(false), 300))
})
useEffect(() => {
update()
}, [])
return <AutoCard
title={<Space>
报告列表
</Space>} size={"small"} loading={loading} bordered={false}
extra={<Space>
<Tooltip title={<>{`点击列表中的报告检查内容`}</>}><a href="#"><QuestionOutlined/></a></Tooltip>
<a href="#" onClick={() => {
update(1)
}}><ReloadOutlined/></a>
</Space>}
>
<List
renderItem={(item: Report) => {
return <AutoCard
onClick={() => {
props.onClick(item)
}}
style={{marginBottom: 8, backgroundColor: props.selectedId === item.Id ? "#cfdfff" : undefined}}
size="small"
title={item.Title}
extra={<Tag>{formatTimestamp(item.PublishedAt)}</Tag>}
hoverable={true}
>
<Space>
{item.Id && <Tag color={"red"}>ID:{item.Id}</Tag>}
{item.Owner && <Tag color={"green"}>发起人:{item.Owner}</Tag>}
{item.From && <Tag color={"orange"}>来源:{item.From}</Tag>}
</Space>
</AutoCard>
}}
dataSource={response.Data || []}
pagination={{
size: "small",
pageSize: pagination?.Limit || 10, simple: true,
total, showTotal: (i) => <Tag>共{i}条历史记录</Tag>,
onChange: (page: number, limit?: number) => {
update(page, limit)
}
}}>
</List>
</AutoCard>
})
Example #12
Source File: YakScriptParamsSetter.tsx From yakit with GNU Affero General Public License v3.0 | 4 votes |
YakScriptParamsSetter: React.FC<YakScriptParamsSetterProps> = (props) => {
// 新参数组件标记数组
const newParamCom: string[] = ["upload-path", "select"]
const [originParams, setOriginParams] = useState<YakScriptParam[]>(props.Params || []);
const [groupStates, setGroupStates] = useState<{ group: string, hidden: boolean }[]>([]);
// 参数组数据流
const [extraGroup, setExtraGroup] = useState<string[]>([])
const [requiredParams, setRequiredParams] = useState<YakScriptParam[]>([])
const groupToParams = useRef<Map<string, YakScriptParam[]>>(new Map<string, YakScriptParam[]>())
// 控制局部组件的加载状态
const [templateLoading, setTemplateLoading] = useState<boolean>(false)
// 上传组件多选时定时器和临时数据暂存点
const timerToData = useRef<{ time: any, data: string }>({time: undefined, data: ""})
// antd的Form表单验证,此变量非常重要,复制Form验证功能必须
const [form] = Form.useForm()
useEffect(() => {
if ((props.Params || []).length === 0) return
const cloneParams = props.Params.map(item => {
item.Value = item.DefaultValue ? item.DefaultValue : undefined
return item
})
setOriginParams(cloneParams)
form.resetFields()
form.setFieldsValue({originParams: cloneParams})
}, [props.Params])
useEffect(() => {
const groupToParam = new Map<string, YakScriptParam[]>();
const extraGroup: string[] = [];
for (let item of originParams) {
const group = item.Required ? "required" : (item.Group || "default");
if (group !== "required" && !extraGroup.includes(group)) {
extraGroup.push(group)
}
let params: YakScriptParam[] | undefined = groupToParam.get(group)
if (params === undefined) {
groupToParam.set(group, [])
params = groupToParam.get(group)
}
if (params) params.push(item)
}
const requiredParam: YakScriptParam[] = groupToParam.get("required") || [];
groupToParams.current = groupToParam
setRequiredParams(requiredParam)
setExtraGroup(extraGroup)
}, [originParams])
const yakScriptParamToNode = (i: YakScriptParam, required: boolean, key: string, disabled: boolean, formItemStyle?: React.CSSProperties) => {
let index = 0
for (let id in originParams) {
if (originParams[id].Field === i.Field) {
index = +id
break
}
}
return <Form.Item
labelCol={{span: 6}}
key={key}
style={{marginBottom: 8, ...formItemStyle}}
label={<Space size={2}>
<>{i.FieldVerbose ? `${i.FieldVerbose}` : `${i.Field}`}</>
{i.Help && <Tooltip title={i.Help}>
<Button icon={<QuestionOutlined/>} type={"link"} size={"small"}/>
</Tooltip>}
</Space>}
// help={i.Help || undefined}
required={required}
name={["originParams", `${index}`, "Value"]}
rules={[{
validator: async (rule, value) => {
if (i.TypeVerbose === "boolean") return
else if (i.TypeVerbose === "float") {
if (value === undefined || value === null) throw new Error('该参数为必填项!')
} else {
if (required && (value || []).length === 0) throw new Error('该参数为必填项!')
}
}
}]}
>
<TypeVerboseToInput
TypeVerbose={i.TypeVerbose}
value={i.Value || i.DefaultValue}
placeholder={i.DefaultValue}
defaultValue={i.DefaultValue}
disabled={disabled}
setValue={value => {
originParams[index].Value = value
setOriginParams([...originParams])
form.setFieldsValue({originParams: {...originParams}})
}}
/>
</Form.Item>
}
const yakScriptParamToNewNode = (
i: YakScriptParam,
required: boolean,
key: string,
disabled: boolean,
formItemStyle?: React.CSSProperties
) => {
let index = 0
for (let id in originParams) {
if (originParams[id].Field === i.Field) {
index = +id
break
}
}
let extraSetting: any = undefined
try {
extraSetting = JSON.parse(i.ExtraSetting || "{}")
} catch (error) {
failed("获取参数配置数据错误,请重新打开该页面")
}
if (i.TypeVerbose === "upload-path") {
const before = (f: any) => {
if (!timerToData.current.time) setTemplateLoading(true)
if (timerToData.current.time) {
clearTimeout(timerToData.current.time)
timerToData.current.time = null
}
timerToData.current.data = timerToData.current.data ? `${timerToData.current.data},${f.path}` : f.path
timerToData.current.time = setTimeout(() => {
for (let item of originParams) {
if (item.Field === i.Field) {
item.Value = item.Value ? `${item.Value},${timerToData.current.data}` : timerToData.current.data
break
}
}
setOriginParams([...originParams])
form.setFieldsValue({originParams: {...originParams}})
timerToData.current = {time: undefined, data: ""}
setTimeout(() => setTemplateLoading(false), 50)
}, 100);
return false
}
return (
<Spin key={key} spinning={templateLoading}>
<ContentUploadInput
type={extraSetting.isTextArea ? "textarea" : "input"}
beforeUpload={(f: any) => before(f)}
dragger={{
accept: "",
multiple: true,
disabled: disabled || templateLoading
}}
item={{
style: {marginBottom: 8, ...formItemStyle},
labelCol: {span: 6},
label: (
<Space size={2}>
<>{i.FieldVerbose ? `${i.FieldVerbose}` : `${i.Field}`}</>
{i.Help && (
<Tooltip title={i.Help}>
<Button icon={<QuestionOutlined/>} type={"link"} size={"small"}/>
</Tooltip>
)}
</Space>
),
required: required,
help: (
<div className='content-upload-input-help'>
点击此处
<Upload
// accept={"text/plain"}
accept={"*"}
multiple={true}
maxCount={1}
showUploadList={false}
beforeUpload={(f) => {
before(f)
return false
}}
>
<span className='help-hint-title'>上传文件</span>
</Upload>
<Divider style={{margin: "0 5px"}} type="vertical"/>
<Upload
directory
multiple={false}
maxCount={1}
showUploadList={false}
beforeUpload={(f) => {
before(f)
return false
}}
>
<span className='help-hint-title'>上传文件夹</span>
</Upload>
</div>
),
name: ["originParams", `${index}`, "Value"],
rules: [{
validator: async (rule, value) => {
if (required && (value || []).length === 0) throw new Error('该参数为必填项!')
}
}],
}}
input={{
isBubbing: true,
setValue: (value) => {
originParams[index].Value = value
setOriginParams([...originParams])
form.setFieldsValue({originParams: {...originParams}})
},
value: i.Value,
placeholder: "获取文件路径,支持多选文件,文件夹,路径以逗号分隔",
disabled: disabled
}}
textarea={{
isBubbing: true,
setValue: (value) => {
originParams[index].Value = value
setOriginParams([...originParams])
form.setFieldsValue({originParams: {...originParams}})
},
rows: 1,
value: i.Value,
placeholder: "获取文件路径,支持多选文件,文件夹,路径以逗号分隔",
disabled: disabled
}}
/>
</Spin>
)
}
if (i.TypeVerbose === "select") {
return (
<ItemSelects
key={key}
item={{
style: {marginBottom: 8, ...formItemStyle},
labelCol: {span: 6},
label: (
<Space size={2}>
<>{i.FieldVerbose ? `${i.FieldVerbose}` : `${i.Field}`}</>
{i.Help && (
<Tooltip title={i.Help}>
<Button icon={<QuestionOutlined/>} type={"link"} size={"small"}/>
</Tooltip>
)}
</Space>
),
name: ["originParams", `${index}`, "Value"],
required: required,
rules: [{
validator: async (rule, value) => {
if (required && (value || []).length === 0) throw new Error('该参数为必填项!')
}
}],
}}
select={{
tokenSeparators: [","],
allowClear: true,
data: extraSetting.data || [],
optText: "key",
value: (`${i.Value}` || "").split(",").filter(i => !!i),
setValue: (value) => {
originParams[index].Value = value
setOriginParams([...originParams])
form.setFieldsValue({originParams: {...originParams}})
},
mode: !!extraSetting.double ? 'tags' : undefined,
maxTagCount: !!extraSetting.double ? 'responsive' : undefined,
disabled: disabled
}}
/>
)
}
return <div style={{height: 0}}></div>
}
const setHideGroup = (group: string, hidden: boolean) => {
let newGroups: { group: string, hidden: boolean }[] = [
...groupStates.filter(i => i.group !== group),
{group, hidden: hidden}];
setGroupStates(newGroups)
};
const submit = () => {
if (props.onClearData) props.onClearData()
let params = originParams.filter(i => {
// 处理 Bool 的情况
if (isBoolean(i.TypeVerbose)) {
return !!i.Value
}
// 真实的为空值
if (!(i.Value || i.DefaultValue)) {
if (i.Required) {
i.Value = `${i.TypeVerbose}_undefined`
return true
} else {
return false
}
}
// 处理其他参数的情况
return true
})
props.onParamsConfirm(params.map(i => {
return {Key: i.Field, Value: i.Value || i.DefaultValue}
}))
}
const isGroupHidden = useMemoizedFn((group: string, defaultValue: boolean) => {
if (group === "default") return false
let res = defaultValue;
groupStates.filter(i => i.group === group).forEach(i => {
res = i.hidden
})
return res;
})
const renderExtraParams = (defaultExpand?: boolean) => {
return <>
{
(extraGroup.length <= 1 && extraGroup.length > 0) ? <>
{/*<Title level={5} style={{fontSize: 14}}>*/}
{/* <Space>*/}
{/* <span>*/}
{/* 默认参数组*/}
{/* </span>*/}
{/* <Switch*/}
{/* size={"small"}*/}
{/* defaultChecked={!isGroupHidden("default", !defaultExpand)}*/}
{/* onChange={(res) => {*/}
{/* setHideGroup('default', !res)*/}
{/* }}*/}
{/* />*/}
{/* </Space>*/}
{/*</Title>*/}
{!isGroupHidden(extraGroup[0] || "default", !defaultExpand) && <>
{(groupToParams.current.get(extraGroup[0] || "default") || []).map((i: YakScriptParam, index) => {
if (newParamCom.includes(i.TypeVerbose)) return yakScriptParamToNewNode(i, false, `defaultParamsGroup-${index}`, !!props.loading)
else return yakScriptParamToNode(i, false, `defaultParamsGroup-${index}`, !!props.loading)
})}
</>}
</> : <>
{extraGroup.map((i, index) => {
if ((groupToParams.current.get(i) || []).length <= 0) {
return <></>
}
return <div key={`${index}`}>
<Title level={5} style={{fontSize: 14}}>
<Space>
<span>
参数组:{i}
</span>
<Switch
size={"small"}
checked={!isGroupHidden(i, !defaultExpand)}
onChange={(res) => setHideGroup(i, !res)}
/>
</Space>
</Title>
{!isGroupHidden(i, !defaultExpand) && <>
{(groupToParams.current.get(i) || []).map((i: YakScriptParam, index) => {
if (newParamCom.includes(i.TypeVerbose)) return yakScriptParamToNewNode(i, false, `paramsGroup-${index}`, !!props.loading)
else return yakScriptParamToNode(i, false, `paramsGroup-${index}`, !!props.loading)
})}
</>}
</div>
})}
</>
}
</>
}
if (props.primaryParamsOnly) {
return (
<Form
form={form}
onFinish={(value) => {
form.validateFields()
.then(values => submit())
}}
// onSubmitCapture={(e) => {
// e.preventDefault()
// // submit()
// }}
{...{labelCol: {span: 7}, wrapperCol: {span: 15}}}
>
{requiredParams.length > 0 ? (
<>
<div style={{marginTop: 0}}>
{requiredParams.map((i, index) => {
if (newParamCom.includes(i.TypeVerbose)) return yakScriptParamToNewNode(i, true, `params-${index}`, !!props.loading)
else return yakScriptParamToNode(i, true, `params-${index}`, !!props.loading)
})}
</div>
<Form.Item
label={" "}
colon={false}
style={{width: "100%", textAlign: "right"}}
labelCol={{span: 6}}
>
<Space>
{!props.hideClearButton && (
<Button
type={"link"}
size={"small"}
danger={true}
onClick={() => {
if (props.onClearData) props.onClearData()
}}
>
清除缓存
</Button>
)}
{groupToParams.current.size > 0 &&
(groupToParams.current.size === 1 &&
(groupToParams.current.get("default") || []).length <= 0 ? (
""
) : (
<Popover
title={"设置额外参数"}
trigger={"click"}
content={<div style={{width: 700}}>{renderExtraParams(true)}</div>}
>
<Button size={"small"} type={"link"}>
额外参数
</Button>
</Popover>
))}
{props.loading ? (
<Button
style={{width: 120}}
danger={true}
onClick={() => {
if (props.onCanceled) props.onCanceled()
}}
type={"primary"}
>
{props.cancelVerbose ? props.cancelVerbose : "停止任务"}
</Button>
) : (
<Button style={{width: 120}} htmlType={"submit"} type={"primary"}>
{props.submitVerbose ? props.submitVerbose : "启动任务"}
</Button>
)}
</Space>
</Form.Item>
</>
) : (
<>
<Form.Item style={{width: "100%", textAlign: "right"}}>
<Space>
{props.loading ? (
<Button
style={{width: 200}}
danger={true}
onClick={() => {
if (props.onCanceled) props.onCanceled()
}}
type={"primary"}
>
停止任务
</Button>
) : (
<Button style={{width: 200}} htmlType={"submit"} type={"primary"}>
启动任务
</Button>
)}
{groupToParams.current.size > 0 && (
<Popover
title={"设置额外参数"}
trigger={"click"}
content={<div style={{width: 700}}>{renderExtraParams(true)}</div>}
>
<Button size={"small"} type={"link"}>
额外参数
</Button>
</Popover>
)}
</Space>
</Form.Item>
</>
)}
</Form>
)
}
return <div style={{
marginLeft: props.styleSize === "big" ? 80 : undefined,
marginRight: props.styleSize === "big" ? 100 : undefined,
}}>
<Card title={""} bodyStyle={{padding: 0}} bordered={false}>
<Form
onSubmitCapture={e => {
e.preventDefault()
submit()
}}
{...(props.styleSize !== "big" ? {
labelCol: {span: 7}, wrapperCol: {span: 14}
} : {
layout: "vertical",
})}
>
{/* 设置基础必须的参数,剩下其他参数不一定是必须的*/}
{requiredParams.length > 0 && <>
<Title level={5} style={{fontSize: 14}}>
<Space>
<span>
必要参数
</span>
<Tooltip title={'执行该脚本不可或缺的参数 / Necessary Params'}>
<Button icon={<QuestionOutlined/>} type={"link"} size={"small"}/>
</Tooltip>
</Space>
</Title>
{requiredParams.map((i, index) => {
if (newParamCom.includes(i.TypeVerbose)) return yakScriptParamToNewNode(i, true, `params-${index}`, !!props.loading)
else return yakScriptParamToNode(i, true, `params-${index}`, !!props.loading)
})}
</>}
{renderExtraParams()}
{originParams.length <= 0 && <Form.Item label={" "} colon={false}>
<h2>本模块无需设置额外参数</h2>
</Form.Item>}
<Form.Item colon={false} label={" "}>
<Button type="primary" loading={!!props.loading}
htmlType="submit"> {props.submitVerbose ? props.submitVerbose : "提交已设置的参数"} </Button>
</Form.Item>
</Form>
</Card>
</div>
}
Example #13
Source File: PluginOperator.tsx From yakit with GNU Affero General Public License v3.0 | 4 votes |
PluginOperator: React.FC<YakScriptOperatorProp> = (props) => {
const [script, setScript] = useState<YakScript>()
const [error, setError] = useState("")
const [loading, setLoading] = useState(false)
const [groups, setGroups] = useState<string[]>([])
const [markdown, setMarkdown] = useState("")
const [trigger, setTrigger] = useState(false)
const [extraParams, setExtraParams] = useState<YakExecutorParam[]>();
const [details, setDetails] = useState(true)
const [settingShow, setSettingShow] = useState<boolean>(false)
const updateGroups = () => {
ipcRenderer
.invoke("QueryGroupsByYakScriptId", {YakScriptId: props.yakScriptId})
.then((data: { Groups: string[] }) => {
setGroups(data.Groups)
})
.catch((e: any) => {
console.info(e)
})
.finally()
}
const update = () => {
if (props.yakScriptId <= 0) {
return
}
updateGroups()
setLoading(true)
ipcRenderer
.invoke("GetYakScriptById", {Id: props.yakScriptId})
.then((e: YakScript) => {
setScript(e)
// setDetails(!e.IsGeneralModule)
ipcRenderer
.invoke("GetMarkdownDocument", {
YakScriptId: e?.Id,
YakScriptName: e?.ScriptName
})
.then((data: { Markdown: string }) => {
setMarkdown(data.Markdown)
})
.catch((e: any) => {
setMarkdown("")
})
})
.catch((e: any) => {
failed("Query YakScript By ID failed")
})
.finally(() =>
setTimeout(() => {
setTrigger(!trigger)
setLoading(false)
}, 300)
)
}
useEffect(() => {
update()
}, [props.yakScriptId])
// 来源于菜单进入以及开启了插件选择的话,就打开
const enablePluginSelector = (!!script?.EnablePluginSelector) && props.fromMenu;
const executor = useMemoizedFn(() => {
return script && (
<PluginExecutor
subTitle={
<Space>
{script.Help && (
<Tooltip title={script.Help}>
<Button type={"link"} icon={<QuestionOutlined/>}/>
</Tooltip>
)}
<Space size={8}>
{/*{script?.ScriptName && (*/}
{/* <Tag>{formatTimestamp(script?.CreatedAt)}</Tag>*/}
{/*)}*/}
<p style={{color: "#999999", marginBottom: 0}}>作者:{script?.Author}</p>
{script?.Tags
? (script?.Tags || "")
.split(",")
.filter((i) => !!i)
.map((i) => {
return (
<Tag
style={{marginLeft: 2, marginRight: 0}}
key={`${i}`}
color={"geekblue"}
>
{i}
</Tag>
)
})
: "No Tags"}
</Space>
</Space>
}
extraNode={
!props.fromMenu && (
<Space>
<Tooltip placement='top' title={"插件管理"}>
<Button
type={"link"}
icon={<SettingOutlined/>}
onClick={() => setSettingShow(!settingShow)}
/>
</Tooltip>
<Tooltip placement='top' title={"编辑插件"}>
<Button
type={"link"}
icon={<EditOutlined/>}
style={{color: "#a7a7a7"}}
onClick={(e) => {
let m = showDrawer({
title: `修改插件: ${script?.ScriptName}`,
width: "100%",
content: (
<>
<YakScriptCreatorForm
modified={script}
onChanged={(i) => update()}
onCreated={() => {
m.destroy()
}}
/>
</>
),
keyboard: false
})
}}
/>
</Tooltip>
</Space>
)
}
script={script}
size={props.size}
extraYakExecutorParams={extraParams}
settingShow={settingShow}
settingNode={
<PluginManagement
style={{marginBottom: 10}}
script={script}
groups={groups}
update={() => {
setTimeout(() => props.setTrigger!(), 300)
}}
updateGroups={updateGroups}
setScript={props.setScript}
/>
}
/>
)
})
const defaultContent = () => {
return (
<Tabs className="plugin-store-info" style={{height: "100%"}} type={"card"} defaultValue={"runner"}
tabPosition={"right"}>
<Tabs.TabPane tab={"执行"} key={"runner"}>
{!enablePluginSelector && executor()}
{enablePluginSelector && <ResizeBox
firstNode={<SimplePluginList
pluginTypes={script?.PluginSelectorTypes || "mitm,port-scan"}
onSelected={names => {
setExtraParams([{Key: BUILDIN_PARAM_NAME_YAKIT_PLUGIN_NAMES, Value: names.join("|")}])
}}
/>}
firstMinSize={"300px"}
firstRatio={"320px"}
secondNode={executor()}
>
</ResizeBox>}
</Tabs.TabPane>
<Tabs.TabPane tab={"文档"} key={"docs"}>
{script && (
<div style={{textAlign: "right", marginBottom: 10}}>
<Button
onClick={(e) => {
let m = showDrawer({
title: "编辑文档",
keyboard: false,
width: "94%",
onClose: () => {
update()
m.destroy()
},
content: (
<>
<DocumentEditor
onFinished={() => {
m.destroy()
}}
markdown={markdown}
yakScript={script}
/>
</>
)
})
}}
>
编辑文档
</Button>
</div>
)}
{markdown ? (
<div>
<MDEditor.Markdown source={markdown}/>
</div>
) : (
<Empty style={{marginTop: 80}} description={"插件作者未添加文档"}/>
)}
</Tabs.TabPane>
<Tabs.TabPane tab={"源码"} key={"code"}>
<div style={{height: "100%"}}>
<YakEditor type={script?.Type || "yak"} value={script?.Content} readOnly={true}/>
</div>
</Tabs.TabPane>
<Tabs.TabPane tab={"历史"} key={"history"}>
{script && <PluginHistoryTable script={script} trigger={trigger}/>}
{/*<ExecHistoryTable mini={false} trigger={null as any}/>*/}
</Tabs.TabPane>
<Tabs.TabPane tab={"结果"} key={"results"}>
{script && <YakScriptExecResultTable YakScriptName={script.ScriptName} trigger={trigger}/>}
</Tabs.TabPane>
</Tabs>
)
}
const showContent = (module: YakScript): JSX.Element => {
if (!module) return <></>
const key = module.GeneralModuleKey
switch (key) {
default:
return defaultContent()
}
}
return <div style={{
marginLeft: 16,
height: "100%"
}}>{!!script && !!props.fromMenu ? showContent(script) : defaultContent()}</div>
}