antd#Drawer TypeScript Examples
The following examples show how to use
antd#Drawer.
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: LogsDrawer.tsx From posthog-foss with MIT License | 6 votes |
export function LogsDrawer(): JSX.Element {
const { showingLogsPlugin, lastShownLogsPlugin } = useValues(pluginsLogic)
const { hidePluginLogs } = useActions(pluginsLogic)
return (
<Drawer
visible={!!showingLogsPlugin}
onClose={hidePluginLogs}
width={'min(90vw, 80rem)'}
title={`Viewing Plugin Logs: ${lastShownLogsPlugin?.name}`}
placement="left"
destroyOnClose
>
{!!lastShownLogsPlugin && (
<PluginLogs
pluginConfigId={lastShownLogsPlugin.pluginConfig.id!} // eslint-disable-line
/>
)}
</Drawer>
)
}
Example #2
Source File: traffic-audit-drawer.tsx From erda-ui with GNU Affero General Public License v3.0 | 6 votes |
TrafficAuditDrawer = ({ visible, onClose, queries }: IProps) => {
const [query, setQuery] = React.useState({});
React.useEffect(() => {
if (visible) {
setQuery(queries);
}
}, [queries, visible]);
const handleClose = () => {
onClose();
};
return (
<Drawer title={i18n.t('traffic audit')} visible={visible} width={1000} onClose={handleClose} destroyOnClose>
<CommonChart type="apim_client" extraQuery={query} />
</Drawer>
);
}
Example #3
Source File: index.tsx From jetlinks-ui-antd with MIT License | 6 votes |
GroupOnDeviceInfo: React.FC<Props> = props => {
return (
<Drawer visible width='60%' title='设备详情'
onClose={() => props.close()}
>
<DeviceInfo location={{
pathname: `/device/instance/save/${props.deviceId}`,
search: '',
hash: "",
query: {},
state: undefined,
}}/>
</Drawer>
);
}
Example #4
Source File: NotificationsWidget.tsx From jitsu with MIT License | 6 votes |
NotificationsWidgetComponent: React.FC = () => {
const hasNotifications = inAppNotificationsStore.hasNotifications
const [showDrawer, setShowDrawer] = useState<boolean>(false)
const handleOpenDrawer = useCallback<(...args: any) => void>(() => setShowDrawer(true), [])
const handleCloseDrawer = useCallback<(...args: any) => void>(() => setShowDrawer(false), [])
return (
<>
<Button
type="text"
shape="circle"
icon={
<Badge dot={hasNotifications} className="text-lg">
<BellOutlined className={hasNotifications && styles.iconRed} />
</Badge>
}
onClick={handleOpenDrawer}
/>
<Drawer
visible={showDrawer}
closable={false}
className={styles.drawer}
onClose={handleCloseDrawer}
contentWrapperStyle={{ width: "80%", maxWidth: "300px" }}
bodyStyle={{ padding: 0 }}
>
<div className="h-full overflow-y-auto">
<div className="box-border px-4 py-2">
<Notifications handleCloseContainer={handleCloseDrawer} />
</div>
</div>
</Drawer>
</>
)
}
Example #5
Source File: index.tsx From config-generator with MIT License | 6 votes |
public render() {
const { destinationDefsListStore } = this.props;
const { selected, filteredDestinationDefs } = this.state;
if (destinationDefsListStore && filteredDestinationDefs) {
return (
<div>
<Drawer
visible={this.state.modalVisible}
onClose={this.handleCancel}
width={'40%'}
>
<DestinationConfigure destinationDef={selected} />
</Drawer>
<Heading>
<HeaderDiv color={theme.color.primary}>Destinations</HeaderDiv>
<LabelMedium color={theme.color.grey300}>
{destinationDefsListStore!.destinationDefs.filter(dest => !dest.config.preview).length}
Available
</LabelMedium>
</Heading>
<IconCardList
type="destination"
selectionMode="none"
icons={filteredDestinationDefs.map((destinationDef: any) => ({
id: destinationDef.id,
type: destinationDef.name,
title: destinationDef.displayName,
onClick: () => this.onClick(destinationDef),
}))}
onSelectionChange={() => {}}
/>
</div>
);
}
}
Example #6
Source File: index.tsx From memex with MIT License | 6 votes |
render() {
const { layout, selectedDoc, resetSelectedDoc } = this.props;
const { width } = layout.drawer;
let readerWidth = '50%';
if (width) {
readerWidth = window.innerWidth - width - 48;
}
return (
<div>
<Drawer
title="Reader"
width={readerWidth}
height="100%"
closable
style={{ zIndex: 1001 }}
onClose={() => {
resetSelectedDoc();
}}
placement="right"
mask={false}
visible={!!Object.keys(selectedDoc).length}
>
<SelectedDocument />
</Drawer>
</div>
);
}
Example #7
Source File: showModal.tsx From yakit with GNU Affero General Public License v3.0 | 6 votes |
BaseDrawer: React.FC<BaseDrawerProp> = (props) => {
const [visible, setVisible] = useState(false);
useEffect(() => {
setVisible(true)
}, [])
useEffect(() => {
if (visible) {
if (props.afterVisible) props.afterVisible(setVisible);
}
}, [visible])
const close = () => {
setVisible(false)
if (props.afterInvisible) props.afterInvisible(setVisible);
setTimeout(() => {
if (props.afterClose) props.afterClose(setVisible);
}, 1000)
}
return <Drawer
visible={visible}
destroyOnClose={true}
onClose={close}
closable={true} width={"50%"} maskClosable={true}
{...props}
>
</Drawer>
}
Example #8
Source File: index.tsx From landy-react-template with MIT License | 5 votes |
Header = ({ t }: any) => {
const [visible, setVisibility] = useState(false);
const showDrawer = () => {
setVisibility(!visible);
};
const onClose = () => {
setVisibility(!visible);
};
const MenuItem = () => {
const scrollTo = (id: string) => {
const element = document.getElementById(id) as HTMLDivElement;
element.scrollIntoView({
behavior: "smooth",
});
setVisibility(false);
};
return (
<>
<CustomNavLinkSmall onClick={() => scrollTo("about")}>
<Span>{t("About")}</Span>
</CustomNavLinkSmall>
<CustomNavLinkSmall onClick={() => scrollTo("mission")}>
<Span>{t("Mission")}</Span>
</CustomNavLinkSmall>
<CustomNavLinkSmall onClick={() => scrollTo("product")}>
<Span>{t("Product")}</Span>
</CustomNavLinkSmall>
<CustomNavLinkSmall
style={{ width: "180px" }}
onClick={() => scrollTo("contact")}
>
<Span>
<Button>{t("Contact")}</Button>
</Span>
</CustomNavLinkSmall>
</>
);
};
return (
<HeaderSection>
<Container>
<Row justify="space-between">
<LogoContainer to="/" aria-label="homepage">
<SvgIcon src="logo.svg" width="101px" height="64px" />
</LogoContainer>
<NotHidden>
<MenuItem />
</NotHidden>
<Burger onClick={showDrawer}>
<Outline />
</Burger>
</Row>
<Drawer closable={false} visible={visible} onClose={onClose}>
<Col style={{ marginBottom: "2.5rem" }}>
<Label onClick={onClose}>
<Col span={12}>
<Menu>Menu</Menu>
</Col>
<Col span={12}>
<Outline />
</Col>
</Label>
</Col>
<MenuItem />
</Drawer>
</Container>
</HeaderSection>
);
}
Example #9
Source File: edit-policy-access-drawe.tsx From shippo with MIT License | 5 votes |
Component: React.ForwardRefRenderFunction<
EditPolicyAccessDrawerRef,
EditPolicyAccessDrawerProps
> = (props, ref) => {
const { onClose } = props
const [policy, setPolicy] = useState<IPermissionPolicy>(__defaultPolicy)
const [dataSource, setDataSource] = useState<IPermissionAccess[]>([])
const [visible, setVisible] = useState(false)
const [selectedRowKeys, setSelectedRowKeys] = useState<number[]>([])
// ref
useImperativeHandle(ref, () => {
return {
// 打开抽屉
open: (policy: IPermissionPolicy) => {
services.permissionAccess.find_all_ext_status({ id: policy.id }).then((hr) => {
setDataSource(hr.data.resource)
setSelectedRowKeys(hr.data.resource.filter((item) => item.status).map((item) => item.id))
})
setPolicy(policy)
setVisible(true)
},
}
})
// 关闭抽屉
const closeDrawer = useCallback(() => {
onClose && onClose()
setVisible(false)
}, [onClose])
const handleSave = useCallback(async () => {
console.log(policy)
services.permissionPolicy.update_access({ id: policy.id, access: selectedRowKeys })
closeDrawer()
}, [policy, selectedRowKeys, closeDrawer])
return (
<Drawer
title="访问规则配置"
width={720}
onClose={closeDrawer}
visible={visible}
bodyStyle={{ paddingBottom: 80 }}
>
<Form layout="vertical" requiredMark={false}>
<Form.Item>
<Table
rowKey="id"
rowSelection={{
selectedRowKeys,
onChange: (keys) => setSelectedRowKeys(keys as number[]),
}}
columns={columns}
dataSource={dataSource}
size="small"
/>
</Form.Item>
<Form.Item>
<Space>
<Button onClick={closeDrawer}>关闭</Button>
<Button onClick={handleSave} type="primary">
保存
</Button>
</Space>
</Form.Item>
</Form>
</Drawer>
)
}
Example #10
Source File: Layout.tsx From nodestatus with MIT License | 5 votes |
Layout: FC = () => {
const [collapsed, setCollapsed] = useState(false);
const toggleCollapsed = () => setCollapsed(state => !state);
return (
<AntdLayout className="min-h-screen">
{/* Desktop SideBar */}
<AntdLayout.Sider
collapsible
collapsed={collapsed}
onCollapse={toggleCollapsed}
trigger={null}
className="hidden lg:block"
>
<Sider isCollapsed={collapsed} />
</AntdLayout.Sider>
{/* Mobile SideBar */}
<Drawer
placement="left"
className="block lg:hidden"
visible={collapsed}
onClose={() => setCollapsed(false)}
width={208}
bodyStyle={{ padding: 0 }}
headerStyle={{ display: 'none' }}
closeIcon={null}
>
<Sider isCollapsed={collapsed} />
</Drawer>
<AntdLayout>
<AntdLayout.Header className="bg-white py-2 pl-6 shadow">
<Header collapsed={{ isCollapsed: collapsed, toggleCollapsed }} />
</AntdLayout.Header>
<AntdLayout.Content>
<div className="container mx-auto px-6 max-w-screen-xl">
<StatusContextProvider>
<AdminRoutes />
</StatusContextProvider>
</div>
</AntdLayout.Content>
<AntdLayout.Footer>
<Footer />
</AntdLayout.Footer>
</AntdLayout>
</AntdLayout>
);
}
Example #11
Source File: index.tsx From erda-ui with GNU Affero General Public License v3.0 | 5 votes |
FilterGroupDrawer = ({
visible,
onClose,
list,
onSearch,
onChange,
onReset,
syncUrlOnSearch,
}: IIFilterDrawerProps) => {
return (
<Drawer
width="520"
onClose={onClose}
visible={visible}
destroyOnClose
title={i18n.t('common:advanced filter')}
className="dice-drawer advanced-filter-drawer"
>
<FilterCore
list={list}
onSearch={onSearch}
onChange={onChange}
onReset={onReset}
syncUrlOnSearch={syncUrlOnSearch}
>
{({ CompList, search }: IFilterReturnProps) => {
return (
<div className="filter-group-drawer">
{CompList.length === 1 ? (
<div>
<div className="filter-label">{list[0].label}</div>
{CompList[0]}
</div>
) : (
CompList.map((item, i: number) => {
if (i % 2 === 1) {
return null;
}
const hasSecond = !!list[i + 1];
return (
<Row key={list[i].name} gutter={12}>
<Col span={12}>
<div className="filter-label">{list[i].label}</div>
{item}
</Col>
{hasSecond ? (
<Col span={12}>
<div className="filter-label">{list[i + 1].label}</div>
{CompList[i + 1]}
</Col>
) : null}
</Row>
);
})
)}
<div className="drawer-footer ml-3-group">
<Button
onClick={() => {
onClose();
}}
>
{i18n.t('Cancel')}
</Button>
<Button type="primary" ghost onClick={search}>
{i18n.t('Filter')}
</Button>
</div>
</div>
);
}}
</FilterCore>
</Drawer>
);
}
Example #12
Source File: index.tsx From jetlinks-ui-antd with MIT License | 5 votes |
RuleFlow: React.FC<Props> = props => {
// const initState: State = {
// modelData: props.data
// }
// const [modelData] = useState(initState.modelData);
const saveModel = (item: any) => {
const flowData = window.editor.getData();
props.save({
...item,
modelMeta: JSON.stringify({ ...item, ...flowData }),
modelType: 'antv.g6',
});
};
const renderTitle = () => {
const action = props.data.option;
switch (action) {
case 'update':
return '编辑规则模型';
case 'copy':
return '复制规则模型';
default:
return '新增规则模型';
}
};
return (
<Drawer
title={renderTitle()}
width="80vw"
placement="right"
visible
onClose={() => props.close()}
>
<GGEditor className={styles.editor}>
<Row type="flex" className={styles.editorHd}>
<Col span={24}>
<FlowToolbar />
</Col>
</Row>
<Row type="flex" className={styles.editorBd}>
<Col span={4} className={styles.editorSidebar}>
<RuleItemPanel />
</Col>
<Col span={16} className={styles.editorContent}>
<Flow
// onClick={() => { message.success('点击1') }}
className={styles.flow}
data={props.data}
// data={{ "nodes": [{ "type": "node", "size": "120*48", "shape": "flow-rect", "color": "#1890FF", "label": "短信通知", "executor": "sms-sender", "x": 90.625, "y": 167.5, "id": "9c4991a5", "nodeId": "9c4991a5", "config": { "senderId": "test", "sendTo": "18502314099", "templateId": "1193111382586462208", "text": "", "senderName": "测试", "templateName": "测试" }, "index": 6, "executorName": "短信通知" }, { "type": "node", "size": "150*48", "shape": "flow-rect", "color": "#1890FF", "label": "接收平台发往设备到消息", "executor": "device-operation", "x": 117.25, "y": 376, "id": "beab3173", "executorName": "操作设备", "nodeId": "beab3173", "config": { "operation": "HANDLE_MESSAGE", "transport": "MQTT", "deviceId": "" }, "index": 7 }, { "type": "node", "size": "120*48", "shape": "flow-rect", "color": "#1890FF", "label": "编码消息", "executor": "device-operation", "x": 326.625, "y": 376, "id": "b689f759", "executorName": "操作设备", "nodeId": "b689f759", "config": { "operation": "ENCODE", "transport": "MQTT", "deviceId": "${#deviceId}" }, "index": 10 }, { "type": "node", "size": "120*48", "shape": "flow-rect", "color": "#1890FF", "label": "发送MQTT消息", "executor": "mqtt-client", "x": 517.75, "y": 375.5, "id": "82405a9a", "executorName": "MQTT客户端", "nodeId": "82405a9a", "config": { "clientId": "1193833468349403136", "clientName": "测试MQTT客户端", "clientType": "producer", "payloadType": "JSON", "topics": "/test", "topicVariables": "" }, "index": 11 }, { "type": "node", "size": "120*48", "shape": "flow-rect", "color": "#1890FF", "label": "订阅MQTT", "executor": "mqtt-client", "x": 265.625, "y": 41.5, "id": "58fc116d", "nodeId": "58fc116d", "config": { "clientId": "1193833468349403136", "clientName": "测试MQTT客户端", "clientType": "consumer", "payloadType": "JSON", "topics": "/chiefdata/push/#", "topicVariables": "/chiefdata/push/fire_alarm/department/{department}/area/{areaId}/dev/{deviceId}" }, "index": 13, "executorName": "订阅MQTT" }, { "type": "node", "size": "120*48", "shape": "flow-rect", "color": "#1890FF", "label": "解码消息", "executor": "device-operation", "x": 524.125, "y": 42.5, "id": "2f35bf4a", "nodeId": "2f35bf4a", "config": { "operation": "DECODE", "transport": "MQTT", "deviceId": "${#payload[devid]}" }, "index": 14, "executorName": "解码消息" }, { "type": "node", "size": "120*48", "shape": "flow-rect", "color": "#1890FF", "label": "处理默认消息", "executor": "spring-event", "x": 706.125, "y": 42.5, "id": "3a4088d8", "nodeId": "3a4088d8", "config": { "publishClass": "org.jetlinks.core.message.Message", "subscribeClass": "" }, "index": 15, "executorName": "处理默认消息" }, { "type": "node", "size": "120*48", "shape": "flow-rect", "color": "#1890FF", "label": "测试发送消息", "executor": "mqtt-client", "x": 855.125, "y": 177.5, "id": "c9a2d7fd", "executorName": "MQTT客户端", "nodeId": "c9a2d7fd", "config": { "clientId": "test", "clientName": "测试", "clientType": "producer", "payloadType": "JSON", "topics": "/chiefdata/push/fire_alarm/department/1/area/2/dev/3", "topicVariables": "" }, "index": 18 }, { "type": "node", "size": "120*48", "shape": "flow-rect", "color": "#1890FF", "label": "设置设备在线", "executor": "device-operation", "x": 178.25, "y": 281.5, "id": "96670420", "executorName": "操作设备", "nodeId": "96670420", "config": { "operation": "ONLINE", "transport": "MQTT", "deviceId": "${#payload[dno]}" }, "index": 19 }, { "type": "node", "size": "120*48", "shape": "flow-rect", "color": "#1890FF", "label": "判断设备状态", "executor": "route", "x": 265.125, "y": 168, "id": "e21c7c7c", "executorName": "路由", "nodeId": "e21c7c7c", "config": {}, "index": 20 }, { "type": "node", "size": "120*48", "shape": "flow-rect", "color": "#1890FF", "label": "回复平台", "executor": "device-operation", "x": 472.625, "y": 168.5, "id": "5fbc182d", "executorName": "操作设备", "nodeId": "5fbc182d", "config": { "operation": "REPLY_MESSAGE", "transport": "MQTT", "deviceId": "${#deviceId}" }, "index": 21 }, { "type": "node", "size": "120*48", "shape": "flow-rect", "color": "#1890FF", "label": "设置设备离线", "executor": "device-operation", "x": 368.625, "y": 282, "id": "5dd3eac9", "executorName": "操作设备", "nodeId": "5dd3eac9", "config": { "operation": "OFFLINE", "transport": "MQTT", "deviceId": "${#payload[dno]}" }, "index": 22 }, { "type": "node", "size": "120*48", "shape": "flow-rect", "color": "#1890FF", "label": "模拟回复数据", "executor": "script", "x": 551.625, "y": 281, "id": "1a8f85ed", "executorName": "动态脚本", "nodeId": "1a8f85ed", "config": { "script": "handler.onMessage({ruleData ->\n \n \n return [\n \"messageType\":\"READ_PROPERTY_REPLY\",\n \"deviceId\":ruleData.data.payload.deviceId,\n \"messageId\":ruleData.data.payload.messageId,\n \"success\":true,\n \"properties\":[name:\"test\"]\n ]\n});", "lang": "groovy" }, "index": 23 }, { "type": "node", "size": "140*48", "shape": "flow-rect", "color": "#1890FF", "label": "订阅平台发往设备的消息", "executor": "mqtt-client", "x": 784.125, "y": 281, "id": "41531d76", "executorName": "MQTT客户端", "nodeId": "41531d76", "config": { "clientId": "1193833468349403136", "clientName": "测试MQTT客户端", "clientType": "consumer", "payloadType": "JSON", "topics": "/test", "topicVariables": "" }, "index": 24 }], "edges": [{ "source": "58fc116d", "sourceAnchor": 1, "target": "2f35bf4a", "id": "97d2b81b", "targetAnchor": 3, "_type": "link", "label": "全部设备事件", "type": "", "description": "", "event": "", "script": "return !data.topic.startsWith(\"/chiefdata/push/device_online_status\");", "index": 0, "condition": { "type": "script", "configuration": { "lang": "js", "script": "return !data.topic.startsWith(\"/chiefdata/push/device_online_status\");" } } }, { "source": "2f35bf4a", "sourceAnchor": 1, "target": "3a4088d8", "targetAnchor": 3, "id": "ffb3f335", "index": 1, "_type": "link", "label": "", "type": "", "description": "", "event": "", "script": "" }, { "source": "58fc116d", "sourceAnchor": 2, "target": "9c4991a5", "id": "a811edd8", "_type": "link", "label": "火警消息", "type": "", "description": "", "event": "", "script": "return data.topic.startsWith(\"/chiefdata/push/fire_alarm\");", "condition": { "type": "script", "configuration": { "lang": "js", "script": "return data.topic.startsWith(\"/chiefdata/push/fire_alarm\");" } }, "targetAnchor": 0, "index": 2, "color": "red" }, { "source": "58fc116d", "sourceAnchor": 2, "target": "e21c7c7c", "id": "7e388436", "_type": "link", "label": "设备状态变更消息", "type": "", "description": "", "event": "", "script": "return data.topic.startsWith(\"/chiefdata/push/device_online_status\");", "condition": { "type": "script", "configuration": { "lang": "js", "script": "return data.topic.startsWith(\"/chiefdata/push/device_online_status\");" } }, "targetAnchor": 0, "index": 3 }, { "source": "e21c7c7c", "sourceAnchor": 2, "target": "96670420", "targetAnchor": 0, "id": "a4a05fe5", "_type": "link", "label": "设备上线", "type": "", "description": "", "event": "", "script": "return data.payload.status==1;", "condition": { "type": "script", "configuration": { "lang": "js", "script": "return data.payload.status==1;" } }, "index": 4 }, { "source": "e21c7c7c", "sourceAnchor": 2, "target": "5dd3eac9", "targetAnchor": 0, "id": "28db78d7", "_type": "link", "label": "设备离线", "type": "", "description": "", "event": "", "script": "return data.payload.status!=1;", "condition": { "type": "script", "configuration": { "lang": "js", "script": "return data.payload.status!=1;" } }, "index": 5 }, { "source": "beab3173", "sourceAnchor": 1, "target": "b689f759", "id": "873b9dec", "targetAnchor": 3, "index": 8 }, { "source": "b689f759", "sourceAnchor": 1, "target": "82405a9a", "targetAnchor": 3, "id": "859cf98d", "index": 9 }, { "source": "58fc116d", "sourceAnchor": 2, "target": "5fbc182d", "id": "ffecc6ba", "_type": "link", "label": "回复消息", "type": "", "description": "", "event": "", "script": "return data.topic.startsWith(\"/chiefdata/push/reply\");", "condition": { "type": "script", "configuration": { "lang": "js", "script": "return data.topic.startsWith(\"/chiefdata/push/reply\");" } }, "index": 12, "targetAnchor": 0 }, { "source": "41531d76", "sourceAnchor": 3, "target": "1a8f85ed", "id": "cf161a39", "targetAnchor": 1, "index": 16 }, { "source": "1a8f85ed", "sourceAnchor": 3, "target": "5fbc182d", "targetAnchor": 2, "id": "9c6f952e", "index": 17 }, { "source": "1a8f85ed", "sourceAnchor": 0, "target": "3a4088d8", "targetAnchor": 2, "id": "961c9613", "index": 25 }], "id": "test", "name": "新建模型", "description": "", "runMode": "CLUSTER" }}
// data={{ "nodes": [{ "type": "node", "size": "72*72", "shape": "flow-circle", "color": "#FA8C16", "label": "启动任务", "executor": "timer", "x": 423.84375, "y": 167, "id": "67a26f33", "remark": "测试Timer", "config": { "cron": "0 1-2 * * * ? ", "defaultData": "dsfsfs" }, "index": 0 }, { "type": "node", "size": "80*48", "shape": "flow-capsule", "color": "#B37FEB", "label": "Querys", "executor": "sql", "x": 419.84375, "y": 296, "id": "c289e872", "remark": "测试查询sdf", "config": { "dataSourcedId": "mysql", "stream": true, "transaction": true, "script": "select * from table;" }, "index": 1 }, { "type": "node", "size": "120*48", "shape": "flow-rect", "color": "#1890FF", "label": "数据转换", "executor": "dataMapping", "x": 576.84375, "y": 353, "id": "cdd8828a", "index": 3, "remark": "sdfs", "config": { "mappings": [{ "key": "0", "source": "12312", "target": "31231", "type": "132" }], "keepSourceData": true } }], "edges": [{ "source": "67a26f33", "sourceAnchor": 2, "target": "c289e872", "targetAnchor": 0, "id": "9e1baa72", "index": 2 }, { "source": "c289e872", "sourceAnchor": 1, "target": "cdd8828a", "targetAnchor": 0, "id": "501d68ca", "index": 4 }] }}
/>
</Col>
<Col span={4} className={styles.editorSidebar}>
<FlowDetailPanel
data={props.data}
save={(item: any) => {
saveModel(item);
}}
/>
{/* <EditorMinimap /> */}
<SaveFlow
// 不能注释掉。页面不显示,。只用于加载Flow方法,此处只使用了保存方法。
/>
</Col>
</Row>
<Col span={24}>
<EditorConsole />
</Col>
<FlowContextMenu />
</GGEditor>
</Drawer>
);
}
Example #13
Source File: ApiKeys.tsx From jitsu with MIT License | 5 votes |
ApiKeysComponent: React.FC = () => {
const keys = apiKeysStore.list
const services = useServices()
services.storageService.table("api_keys")
const [loading, setLoading] = useState<LoadingState>(null)
const [documentationDrawerKey, setDocumentationDrawerKey] = useState<ApiKey>(null)
return (
<>
<div className="flex flex-row mb-5 items-start justify between">
<div className="flex-grow flex text-secondaryText">
Jitsu supports many{" "}
<Popover
trigger="click"
placement="bottom"
title={null}
content={
<div className="w-96 flex-wrap flex justify-center">
{Object.values(jitsuClientLibraries).map(props => (
<div className="mx-3 my-4" key={props.name}>
<JitsuClientLibraryCard {...props} />
</div>
))}
</div>
}
>
{"\u00A0"}
<a>languages and frameworks</a>
{"\u00A0"}
</Popover>
!
</div>
<div className="flex-shrink">
<ProjectLink to={"/api-keys/new"}>
<Button type="primary" size="large" icon={<PlusOutlined />} loading={"NEW" === loading}>
Generate New Key
</Button>
</ProjectLink>
</div>
</div>
<div className="flex flex-wrap justify-center">
{keys
.slice()
.reverse()
.map(key => (
<ApiKeyCard apiKey={key} key={key.uid} showDocumentation={() => setDocumentationDrawerKey(key)} />
))}
</div>
<Drawer width="70%" visible={!!documentationDrawerKey} onClose={() => setDocumentationDrawerKey(null)}>
{documentationDrawerKey && <KeyDocumentation token={documentationDrawerKey} />}
</Drawer>
</>
)
}
Example #14
Source File: index.tsx From visual-layout with MIT License | 5 votes |
Code: React.FC<{ project: ProjectService }> = ({ project }) => {
const [codeConfig, setCodeConfig] = useState<CodeConfig>(
getInitCodeConfig(project),
);
return (
<Visible>
{({ visible, setVisible }) => (
<>
<Drawer
title="代码"
placement="right"
width={'calc(100% - 420px)'}
onClose={() => setVisible(false)}
visible={visible}
destroyOnClose
>
<div className={styles.container}>
<div className={styles.leftContainer}>
<div className={styles.download}>
<Button
type="primary"
shape="round"
icon={<DownloadOutlined />}
onClick={() => exportCode(project, codeConfig)}
>
导出
</Button>
</div>
<BaseInfo project={project} />
<Config setCodeConfig={setCodeConfig} codeConfig={codeConfig} />
</div>
<div className={styles.rightContainer}>
<CodeEdit project={project} codeConfig={codeConfig} />
</div>
</div>
</Drawer>
<Tooltip placement="top" title="代码">
<CodeOutlined
style={{ fontSize: 20 }}
onClick={() => setVisible(true)}
/>
</Tooltip>
</>
)}
</Visible>
);
}
Example #15
Source File: index.tsx From scorpio-h5-design with MIT License | 5 votes |
export default function(props: IProps) {
const { type, onCancel, onSubmit, formSchema, formData, visible, loading } = props;
const title = TITLE_MAP[type];
const form = useForm();
useEffect(() => {
if (visible) {
if (formData) {
form.setValues(formData);
} else {
form.resetFields();
}
}
}, [visible]);
const onFinish = (formData: Record<string, unknown>, valid: Error[]) => {
if (valid.length === 0) {
onSubmit(formData);
}
};
return (
<Drawer
className="form-render-drawer"
title={title}
width={500}
maskClosable={true}
visible={visible}
onClose={onCancel}
footer={
<div
style={{
textAlign: 'right',
}}
>
<Button style={{ marginRight: 8 }} onClick={onCancel}>
取消
</Button>
<Button type="primary" onClick={form.submit} loading={loading}>
确定
</Button>
</div>
}
>
<FormRender
form={form}
onFinish={onFinish}
widgets={{ ImageUpload, BraftEditor }}
{...formSchema}
/>
</Drawer>
);
}
Example #16
Source File: index.tsx From memex with MIT License | 5 votes |
render() {
const { handleClose, layout, selectedDoc } = this.props;
const { data, loading } = this.state;
const { visible, width, title, closeMask = false } = layout.drawer;
return (
<div>
<Drawer
width={width}
title={title}
style={{ left: 48 }}
placement="left"
closable
mask={!closeMask}
onClose={() => {
handleClose();
this.resetSelectedDoc();
}}
visible={visible}
>
{loading ? (
<div className="loading-screen">
<Spin />
</div>
) : null}
<div className="inbox-drawer-header">
<div>
<Checkbox />
</div>
<div>
<Tooltip placement="left" title="Commit">
<Button
style={{ border: 'none' }}
onClick={() => {
this.confirmCommitDocs();
}}
shape="circle"
icon={<FileAddOutlined style={{ fontSize: 14 }} />}
/>
</Tooltip>
<Tooltip placement="left" title="Refresh">
<Button
style={{ border: 'none' }}
onClick={() => {
this.getInbox();
}}
shape="circle"
icon={<ReloadOutlined style={{ fontSize: 14 }} />}
/>
</Tooltip>
</div>
</div>
<div style={{ padding: '0px 16px' }}>
<Tabs defaultActiveKey="1">
<TabPane tab="Uncommitted" key="uncommitted">
{data.map((item: any) => {
if (!item.doc.committed) {
return this.renderInboxItem(item);
}
})}
</TabPane>
<TabPane tab="Committed" key="committed">
{data.map((item: any) => {
if (item.doc.committed) {
return this.renderInboxItem(item);
}
})}
</TabPane>
</Tabs>
</div>
</Drawer>
</div>
);
}
Example #17
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 #18
Source File: edit-access-drawer.tsx From shippo with MIT License | 4 votes |
Component: React.ForwardRefRenderFunction<EditAccessDrawerRef, EditAccessDrawerProps> = (
props,
ref
) => {
const { onClose } = props
const [access, setAccess] = useState<IPermissionAccess>(__defaultAccess)
const [visible, setVisible] = useState(false)
const isUpdate = useMemo(() => {
return access.id !== 0
}, [access])
// ref
useImperativeHandle(ref, () => {
return {
// 打开抽屉
open: (access?: IPermissionAccess) => {
if (access) {
setAccess({ ...access })
} else {
setAccess(__permissionAccess())
}
setVisible(true)
},
}
})
// 关闭抽屉
const closeDrawer = useCallback(() => {
onClose && onClose()
setVisible(false)
}, [onClose])
// 更改access
const changeAccess = useCallback((access: Partial<IPermissionAccess>) => {
setAccess((old) => ({ ...old, ...access }))
}, [])
const handleSave = useCallback(async () => {
console.log(access)
if (isUpdate) {
const hr = await services.permissionAccess.update({
id: access.id,
accessRule: access.accessRule,
accessType: access.accessType,
remark: access.remark,
})
if (hr.data.success) {
message.success('成功')
closeDrawer()
} else {
message.success('失败')
}
} else {
const hr = await services.permissionAccess.create({
accessRule: access.accessRule,
accessType: access.accessType,
remark: access.remark,
})
if (hr.data.success) {
message.success('成功')
closeDrawer()
} else {
message.success('失败')
}
}
}, [isUpdate, access, closeDrawer])
return (
<Drawer
title={isUpdate ? '编辑访问规则' : '新增访问规则'}
width={720}
onClose={closeDrawer}
visible={visible}
bodyStyle={{ paddingBottom: 80 }}
>
<Form layout="vertical" requiredMark={false}>
<Row gutter={16}>
<Col span={12}>
<Form.Item
label="访问规则表达式"
rules={[{ required: true, message: '请输入访问规则表达式' }]}
>
<Input
placeholder="请输入访问规则表达式"
value={access.accessRule}
onChange={(event) => {
changeAccess({ accessRule: event.currentTarget.value })
}}
/>
</Form.Item>
</Col>
<Col span={12}>
<Form.Item label="描述" rules={[{ required: true, message: '请输入描述' }]}>
<Input
placeholder="请输入描述"
value={access.remark}
onChange={(event) => {
changeAccess({ remark: event.currentTarget.value })
}}
/>
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="访问规则类型"
rules={[{ required: true, message: '请输入访问规则类型' }]}
>
<Input
placeholder="请输入访问规则类型"
value={access.accessType}
onChange={(event) => {
changeAccess({ accessType: event.currentTarget.value })
}}
/>
</Form.Item>
</Col>
</Row>
<Form.Item>
<Space>
<Button onClick={closeDrawer}>关闭</Button>
<Button onClick={handleSave} type="primary">
保存
</Button>
</Space>
</Form.Item>
</Form>
</Drawer>
)
}
Example #19
Source File: Dashboards.tsx From posthog-foss with MIT License | 4 votes |
export function Dashboards(): JSX.Element {
const { dashboardsLoading } = useValues(dashboardsModel)
const { deleteDashboard, unpinDashboard, pinDashboard, addDashboard, duplicateDashboard } =
useActions(dashboardsModel)
const { setNewDashboardDrawer, setSearchTerm, setCurrentTab } = useActions(dashboardsLogic)
const { dashboards, newDashboardDrawer, searchTerm, currentTab } = useValues(dashboardsLogic)
const { hasAvailableFeature } = useValues(userLogic)
const columns: LemonTableColumns<DashboardType> = [
{
width: 0,
dataIndex: 'pinned',
render: function Render(pinned, { id }) {
return pinned ? (
<PushpinFilled
onClick={() => unpinDashboard(id, DashboardEventSource.DashboardsList)}
style={{ cursor: 'pointer' }}
/>
) : (
<PushpinOutlined
onClick={() => pinDashboard(id, DashboardEventSource.DashboardsList)}
style={{ cursor: 'pointer' }}
/>
)
},
},
{
title: 'Name',
dataIndex: 'name',
width: '40%',
render: function Render(name, { id, description, _highlight, is_shared }) {
return (
<div className={_highlight ? 'highlighted' : undefined} style={{ display: 'inline-block' }}>
<div className="row-name">
<Link data-attr="dashboard-name" to={urls.dashboard(id)}>
{name || 'Untitled'}
</Link>
{is_shared && (
<Tooltip title="This dashboard is shared publicly.">
<ShareAltOutlined style={{ marginLeft: 6 }} />
</Tooltip>
)}
</div>
{hasAvailableFeature(AvailableFeature.DASHBOARD_COLLABORATION) && description && (
<span className="row-description">{description}</span>
)}
</div>
)
},
sorter: (a, b) => (a.name ?? 'Untitled').localeCompare(b.name ?? 'Untitled'),
},
...(hasAvailableFeature(AvailableFeature.DASHBOARD_COLLABORATION)
? [
{
title: 'Tags',
dataIndex: 'tags' as keyof DashboardType,
render: function Render(tags: DashboardType['tags']) {
return <ObjectTags tags={tags} staticOnly />
},
} as LemonTableColumn<DashboardType, keyof DashboardType | undefined>,
]
: []),
createdByColumn<DashboardType>() as LemonTableColumn<DashboardType, keyof DashboardType | undefined>,
createdAtColumn<DashboardType>() as LemonTableColumn<DashboardType, keyof DashboardType | undefined>,
{
width: 0,
render: function RenderActions(_, { id, name }: DashboardType) {
return (
<More
overlay={
<>
<LemonButton
type="stealth"
to={urls.dashboard(id)}
onClick={() => {
dashboardLogic({ id }).mount()
dashboardLogic({ id }).actions.setDashboardMode(
null,
DashboardEventSource.DashboardsList
)
}}
fullWidth
>
View
</LemonButton>
<LemonButton
type="stealth"
to={urls.dashboard(id)}
onClick={() => {
dashboardLogic({ id }).mount()
dashboardLogic({ id }).actions.setDashboardMode(
DashboardMode.Edit,
DashboardEventSource.DashboardsList
)
}}
fullWidth
>
Edit
</LemonButton>
<LemonButton type="stealth" onClick={() => duplicateDashboard({ id, name })} fullWidth>
Duplicate
</LemonButton>
<LemonSpacer />
<LemonButton
type="stealth"
style={{ color: 'var(--danger)' }}
onClick={() => deleteDashboard({ id, redirect: false })}
fullWidth
>
Delete dashboard
</LemonButton>
</>
}
/>
)
},
},
]
return (
<div>
<PageHeader
title="Dashboards"
buttons={
<Button
data-attr={'new-dashboard'}
onClick={() => setNewDashboardDrawer(true)}
type="primary"
icon={<PlusOutlined />}
>
New Dashboard
</Button>
}
/>
<Tabs
activeKey={currentTab}
style={{ borderColor: '#D9D9D9' }}
onChange={(tab) => setCurrentTab(tab as DashboardsTab)}
>
<Tabs.TabPane tab="All Dashboards" key={DashboardsTab.All} />
<Tabs.TabPane tab="Pinned" key={DashboardsTab.Pinned} />
<Tabs.TabPane tab="Shared" key={DashboardsTab.Shared} />
</Tabs>
<div>
<Input.Search
allowClear
enterButton
placeholder="Search for dashboards"
style={{ width: 240 }}
value={searchTerm}
onChange={(e) => {
setSearchTerm(e.target.value)
}}
/>
</div>
<LemonSpacer large />
<Drawer
title="New Dashboard"
width={400}
onClose={() => setNewDashboardDrawer(false)}
destroyOnClose={true}
visible={newDashboardDrawer}
>
<NewDashboard />
</Drawer>
{dashboardsLoading ? (
<div className="flex-center" style={{ flexDirection: 'column' }}>
<Spinner />
<div className="mt">
<b>Loading dashboards</b>
</div>
</div>
) : dashboards.length > 0 || searchTerm || currentTab !== DashboardsTab.All ? (
<LemonTable
dataSource={dashboards}
rowKey="id"
columns={columns}
defaultSorting={{ columnKey: 'name', order: 1 }}
emptyState={
searchTerm ? (
`No ${
currentTab === DashboardsTab.Pinned
? 'pinned '
: currentTab === DashboardsTab.Shared
? 'shared '
: ''
}dashboards matching "${searchTerm}"!`
) : currentTab === DashboardsTab.Pinned ? (
<>
No dashboards have been pinned for quick access yet.{' '}
<Link onClick={() => setCurrentTab(DashboardsTab.All)}>
Go to All Dashboards to pin one.
</Link>
</>
) : currentTab === DashboardsTab.Shared ? (
<>
No dashboards have been shared yet.{' '}
<Link onClick={() => setCurrentTab(DashboardsTab.All)}>
Go to All Dashboards to share one.
</Link>
</>
) : undefined
}
nouns={['dashboard', 'dashboards']}
/>
) : (
<div className="mt">
<p>Create your first dashboard:</p>
<Row gutter={[16, 16]}>
<Col xs={24} xl={6}>
<Card
title="Empty"
size="small"
style={{ cursor: 'pointer' }}
onClick={() =>
addDashboard({
name: 'New Dashboard',
show: true,
useTemplate: '',
})
}
>
<div style={{ textAlign: 'center', fontSize: 40 }}>
<AppstoreAddOutlined />
</div>
</Card>
</Col>
<Col xs={24} xl={6}>
<Card
title="App Default"
size="small"
style={{ cursor: 'pointer' }}
onClick={() =>
addDashboard({
name: 'Web App Dashboard',
show: true,
useTemplate: 'DEFAULT_APP',
})
}
>
<div style={{ textAlign: 'center', fontSize: 40 }}>
<AppstoreAddOutlined />
</div>
</Card>
</Col>
</Row>
</div>
)}
</div>
)
}
Example #20
Source File: Attributes.tsx From dnde with GNU General Public License v3.0 | 4 votes |
OnlyAttributesDrawer = () => {
const { mjmlJson } = useEditor();
const { active, setActive } = useHtmlWrapper();
const [isDisabled, setIsDisabled] = useState(false);
const [visible, setVisible] = useState(false);
const [init, setInit] = useState(false);
const onClose = () => {
setVisible(false);
};
useEffect(() => {
// wierd bug in antd
if (active && !init) {
setInit(true);
}
if (
active &&
((active.classList && active.className.includes('mj-column')) ||
(active.classList && active.className.includes('mj-body')))
) {
setIsDisabled(true);
} else {
isDisabled && setIsDisabled(false);
}
}, [active]);
useEffect(() => {
if (!isDisabled && active) {
setVisible(true);
} else {
setVisible(false);
}
}, [isDisabled, active]);
return init ? (
<Drawer
destroyOnClose={true}
width={'100%'}
getContainer={false}
title={
<div style={{ textAlign: 'center' }}>
<span>Attributes</span>
</div>
}
style={{ position: 'absolute', height: '100%' }}
onClose={onClose}
visible={visible}
maskClosable={false}
mask={false}
bodyStyle={{
padding: '8px 0px',
}}
>
<Scrollbars style={{ height: '100%' }} autoHide={true}>
<div
className={css.mods}
onMouseDown={(e) => {
UNDOREDO.newAction(mjmlJson);
}}
onBlur={(e) => {
UNDOREDO.newAction(mjmlJson);
}}
>
<Width />
<Height />
<Align />
<VerticalAlign />
<Content />
<LineHeight />
<FontSize />
<FontFamily />
<Padding />
<InnerPadding />
<ContainerBackground />
<Background />
<BackgroundImage />
<Border />
<Border label="Border Width" attribute_name="border-width" />
<Border label="Border Style" attribute_name="border-style" />
<Background label="Border Color" overrideAttribute="border-color" />
{/* <CordinalBorder /> */}
<BorderRadius />
<Link />
<Img />
</div>
</Scrollbars>
</Drawer>
) : null;
}
Example #21
Source File: GeneralDrawer.tsx From next-basics with GNU General Public License v3.0 | 4 votes |
export function GeneralDrawer(props: GeneralDrawerProps): React.ReactElement {
const { scrollToTopWhenOpen } = props;
const contentRef = useRef<HTMLDivElement>();
const findDrawerBody = (ele: HTMLElement): HTMLElement => {
if (ele) {
if (ele.classList.contains("ant-drawer-body")) return ele;
return findDrawerBody(ele.parentElement);
}
};
useEffect(() => {
scrollToTopWhenOpen &&
props.visible &&
findDrawerBody(contentRef.current)?.scrollTo(0, 0);
}, [props.visible]);
const title = (
<div className="header">
{props.title ? (
<span>{props.title}</span>
) : (
<div className="flexContainer">
<slot id="headerLeft" name="headerLeft"></slot>
</div>
)}
<div className="flexContainer">
<slot id="headerRight" name="headerRight"></slot>
</div>
</div>
);
const footer = props.hasFooter && (
<div className="footer">
<div className="footer-inner">
<slot id="footer" name="footer"></slot>
</div>
</div>
);
const classNameList = [];
if (props.isFloat) {
classNameList.push("floatDrawer");
}
if (
props.hasOuterSwitch &&
(!props.configProps ||
!props.configProps.placement ||
props.configProps.placement === "right")
) {
classNameList.push("switch");
}
// istanbul ignore next
const getOuterSwitchNode = () => {
if (!props.useBigOuterSwitch) {
const outerIcon = props.visible
? { lib: "antd", icon: "right", theme: "outlined" }
: { lib: "antd", icon: "left", theme: "outlined" };
return <GeneralIcon icon={outerIcon} />;
} else {
if (!props.customSwitchConfig) return;
const outerIcon = props.visible
? props.customSwitchConfig.openIcon
: props.customSwitchConfig.closeIcon;
const outerText = props.visible
? props.customSwitchConfig.openText
: props.customSwitchConfig.closeText;
return outerIcon ? (
<GeneralIcon icon={outerIcon} />
) : (
<span className="outerText">{outerText?.slice(0, 4)}</span>
);
}
};
return (
<>
<Drawer
{...props.configProps}
title={title}
footer={footer}
width={props.width}
visible={props.visible}
getContainer={props.getContainer}
closable={props.closable}
bodyStyle={props.bodyStyle}
drawerStyle={props.drawerStyle}
mask={props.mask}
headerStyle={props.headerStyle}
forceRender={!!props.hasOuterSwitch}
className={classNameList.join(" ")}
>
{props.hasOuterSwitch && (
<div
className={
props.useBigOuterSwitch
? "outerBtn bigOuterBtn"
: "outerBtn defaultOuterBtn"
}
style={{
top: props.useBigOuterSwitch
? props.customSwitchConfig?.top
: null,
}}
>
{getOuterSwitchNode()}
</div>
)}
<Spin spinning={props.loading} tip="Loading...">
<div className="content" ref={contentRef}>
<slot id="content" name="content"></slot>
</div>
</Spin>
</Drawer>
</>
);
}
Example #22
Source File: Responsive.tsx From yugong with MIT License | 4 votes |
Responsive: React.FC<Props> = () => {
useEffect(() => {
trackPageView('/首页');
}, []);
/**
* ----------
* 定义编辑模式
* ----------
*/
const { isEditing, auth } = useSelector(
(state: RootState) => state.controller,
);
const history = useHistory();
const appData = useSelector((state: RootState) => state.appData);
const activationItem = useSelector(
(state: RootState) => state.activationItem,
);
const stateTag = useSelector((state: RootState) => state.controller.stateTag);
const forceUpdateByStateTag =
useDispatch<Dispatch>().controller.forceUpdateByStateTag;
const setIsEditing = useDispatch<Dispatch>().controller.setIsEditing;
const updateAppData = useDispatch<Dispatch>().appData.updateAppData;
const updatePageData = useDispatch<Dispatch>().pageData.updatePage;
const setWindowHeight = useDispatch<Dispatch>().pageData.setWindowHeight;
const setWindowWidth = useDispatch<Dispatch>().pageData.setWindowWidth;
const updateActivationItem =
useDispatch<Dispatch>().activationItem.updateActivationItem;
const removeActivationItem =
useDispatch<Dispatch>().activationItem.removeActivationItem;
const setRunningTimes = useDispatch<Dispatch>().runningTimes.setRunningTimes;
const ref = useRef(null);
const pageData = useSelector((state: RootState) => state.pageData);
const runningTimes = useSelector((state: RootState) => state.runningTimes);
const setIsReady = useDispatch<Dispatch>().record.setIsReady;
const [, setLocalPageData] = useLocalStorage('pageData', null);
const [showDrawer, setShowDrawer] = useState(false);
const [showPageDrawer, setShowPageDrawer] = useState(false);
const [isCreate, setIsCreate] = useState(true);
const [showTemplateModal, setShowTemplateModal] = useState(false);
const [hideIframe, sethideIframe] = useState(true);
const [visibleQrcode, setVisibleQrcode] = useState(false);
// 创建postmessage通信 usePostMessage收集数据 redux 更新数据
const sendMessage = usePostMessage(({ tag, value }) => {
switch (tag) {
case 'setIsEditing':
setIsEditing(value);
break;
case 'updateAppData':
updateAppData(value);
// 同步更新被选模块的属性
if (activationItem.moduleId === undefined) return;
const asynAcactivationItem = (value as AppDataListTypes).find(
(item) => item.moduleId === activationItem.moduleId,
);
if (asynAcactivationItem?.moduleId) {
updateActivationItem(asynAcactivationItem);
}
break;
case 'updateRunningTimes':
setRunningTimes(value);
break;
case 'updatePage':
updatePageData(value);
break;
case 'id':
// 设置当前项正在被编辑
// 禁止重复设置当前编辑项
if (activationItem.moduleId === value) return;
for (let index = 0; index < appData.length; index++) {
const element = appData[index];
if (element.moduleId === value) {
updateActivationItem({ ...element });
break;
}
}
setShowDashboard(true);
break;
case 'record':
saveRecord(value)
break
default:
break;
}
});
// 收发处理,子窗口onload时向子窗口发送信息, 通知当前正处于编辑模式下,
const win: Window | null = ref.current
? (ref.current as any).contentWindow
: null;
useEffect(() => {
const windows = (document.getElementById('wrapiframe') as any)
?.contentWindow;
if (windows && !isCreate) {
windows.onload = () => {
sendMessage({ tag: 'setIsEditing', value: true }, windows);
setIsEditing(true);
setIsReady(true);
sethideIframe(false);
};
}
}, [sendMessage, setIsEditing, isCreate, setIsReady]);
useEffect(() => {
sendMessage({ tag: 'setIsEditing', value: true }, win);
setIsEditing(true);
}, [sendMessage, setIsEditing, win]);
const toggleEdit = useCallback(() => {
const states = !isEditing;
sendMessage({ tag: 'setIsEditing', value: states }, win);
setIsEditing(states);
}, [isEditing, sendMessage, setIsEditing, win]);
const toggleCreate = useCallback(() => {
setIsCreate(!isCreate);
}, [isCreate]);
// 收发处理,编辑完数据后通过sendMessage向子窗口发送最新数据。
useEffect(() => {
sendMessage(
{
tag: 'updateAppData',
value: appData,
},
win,
);
}, [sendMessage, win, appData]);
const onChangeRule = (
width: number,
height: number = window.innerHeight - 140,
) => {
setWindowWidth(width);
setWindowHeight(height);
const optPageData = { ...pageData };
optPageData.windowWidth = width;
optPageData.windowHeight = height;
setLocalPageData(optPageData);
if (win) {
sendMessage({ tag: 'updatePage', value: true }, win);
sendMessage({ tag: 'setIsEditing', value: isEditing }, win);
}
setIsEditing(true);
forceUpdateByStateTag();
};
const [showDashboard, setShowDashboard] = useState(false);
const [opacity, setOpacity] = useState('1');
// 无激活模块时隐藏设置面板
useEffect(() => {
if (!activationItem.moduleId) {
setShowDashboard(false);
}
}, [activationItem]);
const hideDashboard = useCallback(() => {
setShowDashboard(false);
removeActivationItem();
if (win) {
sendMessage({ tag: 'removeActivationItem', value: undefined }, win);
}
}, [removeActivationItem, sendMessage, win]);
const updateProject = useCallback(
(data: Template) => {
data.id = pageData.template?.id;
return updateTemplate(data);
},
[pageData],
);
interface TemplateAll extends Template {
pageData: string;
appData: string;
}
// 保存或更新项目
const onSaveProject = useCallback(
async ({
cove = [],
terminal,
isPublic,
describe,
tag,
title,
id,
}: TemplateInfo) => {
if (!auth?.isLogin) {
history.push('/login');
return;
}
// copy
const pageDataCopy = cloneDeep(pageData);
// template数据
const templateData: Template = {
title: title || pageData.pageTitle,
terminal,
cove: cove[0]?.thumbUrl,
describe,
tag: tag?.join(','),
isPublic: isPublic === true ? 1 : 0,
};
// 存入模板信息到pageData
if (!pageDataCopy.template) {
pageDataCopy.template = templateData;
}
// 完整数据
/**
* 完整数据包含页面数据、组件数据与模板信息三个部分,
* 页面数据同时也包含一份模板信息供页面处理
*/
const params: TemplateAll = {
pageData: JSON.stringify(pageData),
appData: JSON.stringify(appData),
id,
userId: auth.session?.id,
...templateData,
};
try {
loading.show();
// 更新
if (!!pageData.template?.id) {
await updateProject(params);
} else {
// 新增
const newId = await createTemplate(params);
pageDataCopy.template.id = newId;
}
message.success('已发布');
// 更新
updatePageData(pageDataCopy);
// 关闭弹窗
setShowTemplateModal(false);
// todo 展示二维码与模板访问链接,支持扫码访问
setVisibleQrcode(true);
loading.hide();
} catch (error) {
console.error(error);
loading.hide();
}
},
[
appData,
auth?.isLogin,
auth?.session?.id,
history,
pageData,
updatePageData,
updateProject,
],
);
const showPublishModal = useCallback(() => {
if (!auth?.isLogin) {
history.push('/login');
}
setShowTemplateModal(true);
}, [auth?.isLogin, history]);
const pageSearch = stringify({ tpl: pageData.template?.id, ...runningTimes.search });
const codeViewUrl = `${process.env.REACT_APP_SITE_PATH || ''}${pageSearch ? `?${pageSearch}` : ''}`;
const viewUrl = `${process.env.REACT_APP_SITE_PATH || ''}${window.location.search || '?isediting'
}`
return (
<>
{isCreate ? (
<CreateProject goBack={() => toggleCreate()} />
) : (
<div className={s.main}>
{showDashboard && isEditing ? (
<Draggable
axis="both"
handle={`.${s.header}`}
onDrag={() => setOpacity('0.5')}
onStop={() => setOpacity('1')}
>
<div className={s.dashboard} style={{ opacity }}>
<div className={s.header}>
<h3>设置面板</h3>
<CloseOutlined className={s.icon} onClick={hideDashboard} />
</div>
<MiniDashboard />
</div>
</Draggable>
) : null}
<div className={s.topmenu}>
<div className={s.create}>
<Button
type="primary"
onClick={toggleCreate}
icon={<FileAddOutlined />}
/>
{!isEditing ? (
<Button
type="default"
className={s.toggle}
onClick={toggleEdit}
icon={<EditOutlined />}
/>
) : null}
{isEditing ? (
<Button
type="default"
className={s.toggle}
onClick={toggleEdit}
icon={<EyeOutlined />}
/>
) : null}
<Button
type="default"
icon={<SettingOutlined />}
onClick={() => setShowPageDrawer(true)}
>
页面
</Button>
<Button
type="default"
icon={<PlusOutlined />}
onClick={() => setShowDrawer(true)}
>
组件
</Button>
<Undo />
<a href="https://github.com/eightfeet/yugong">
<Button type="default" icon={<GithubOutlined />}>
github
</Button>
</a>
</div>
<div className={s.save}>
<Button
type="primary"
icon={<CloudUploadOutlined />}
onClick={showPublishModal}
>
{pageData.template?.id ? '修改' : '发布'}
</Button>
{pageData.template?.id ? <>
<Button
icon={<QrcodeOutlined />}
onClick={() => setVisibleQrcode(true)}
/>
</> : null}
</div>
</div>
<Ruler onChange={onChangeRule} />
<Drawer
className={s.drawer}
title="页面设置"
width={580}
onClose={() => setShowPageDrawer(false)}
visible={showPageDrawer}
bodyStyle={{ padding: '0', overflow: 'auto' }}
maskStyle={{ backgroundColor: 'transparent' }}
footer={null}
>
{showPageDrawer ? <PageSetting /> : null}
</Drawer>
<Drawer
className={s.drawer}
title="组件库"
width={580}
onClose={() => setShowDrawer(false)}
visible={showDrawer}
bodyStyle={{ padding: '0px' }}
maskStyle={{ backgroundColor: 'transparent' }}
footer={null}
>
<Repository />
</Drawer>
<div className={s.box}>
<div
className={classNames({
[s.viewbg]: !isEditing,
})}
style={{ transition: 'all 0.5s' }}
/>
{!stateTag ? (
<div
className={s.iframebox}
style={{
width:
pageData.windowWidth === -1
? `100%`
: `${pageData.windowWidth}px`,
height: `${pageData.windowHeight}px`,
}}
>
<LoadingAnimate />
<iframe
ref={ref}
id="wrapiframe"
title="wrapiframe"
src={viewUrl}
style={{
border: 'none',
opacity: hideIframe ? 0 : 1,
minWidth: '100%',
minHeight: `${pageData.windowHeight}px`,
}}
/>
</div>
) : null}
</div>
</div>
)}
<TemplateInfoModal
visible={showTemplateModal}
onOk={onSaveProject}
onCancel={() => setShowTemplateModal(false)}
/>
<QrcodeModal
visible={visibleQrcode}
onCancel={() => setVisibleQrcode(false)}
sourceData={codeViewUrl}
title="请扫码访问"
info={<div className={s.viewurl}>访问地址:<a href={codeViewUrl} target={'_blank'} rel="noreferrer">{codeViewUrl}</a></div>}
options={{
width: 122,
margin: 1
}}
/>
</>
);
}
Example #23
Source File: message.tsx From erda-ui with GNU Affero General Public License v3.0 | 4 votes |
MessageCenter = ({ show }: { show: boolean }) => {
const params = routeInfoStore.useStore((s) => s.params);
const { orgName = '-' } = params || {};
const hasOrgRef = React.useRef(orgName !== '-');
hasOrgRef.current = orgName !== '-';
const [list, detail, msgPaging, unreadCount] = messageStore.useStore((s) => [
s.list,
s.detail,
s.msgPaging,
s.unreadCount,
]);
const { getMessageList, getMessageStats, readOneMessage, clearAll } = messageStore.effects;
const { resetDetail } = messageStore.reducers;
const [loadingList] = useLoading(messageStore, ['getMessageList']);
const { switchMessageCenter } = layoutStore.reducers;
const boxRef = React.useRef<HTMLElement>();
const loopUnreadCountTimer = React.useRef(0 as any);
React.useEffect(() => {
if (hasOrgRef.current) {
getMessageStats();
if (show) {
getMessageList({ pageNo: 1 });
}
}
return () => {
messageStore.reducers.resetAll();
};
}, [getMessageList, getMessageStats, show, orgName]);
const viewMsg = () => {
switchMessageCenter(true);
};
useEffectOnce(() => {
const cycle = 10 * 60 * 1000;
// 每隔5min检查一次
const interval = 5 * 60 * 1000;
checkPermission();
const loop = () => {
let timers = Number(sessionStorage.getItem('message_timer') || 0);
if (!timers) {
timers = Date.now();
sessionStorage.setItem('message_timer', `${timers}`);
}
if (loopUnreadCountTimer.current) {
clearTimeout(loopUnreadCountTimer.current);
}
loopUnreadCountTimer.current = setTimeout(() => {
const now = Date.now();
if (now - timers > cycle) {
sessionStorage.setItem('message_timer', `${now}`);
if (hasOrgRef.current) {
getMessageStats().then((res) => {
if (res?.hasNewUnread) {
if (show) {
// resetDetail();
getMessageList({ pageNo: 1 });
}
notifyMe(i18n.t('default:you have new site message, please pay attention to check'), viewMsg);
}
});
}
}
loop();
}, interval);
};
loop();
return () => {
clearTimeout(loopUnreadCountTimer.current);
};
});
if (!show) {
return null;
}
const handleClick = (item: LAYOUT.IMsg) => {
readOneMessage(item.id, item.status === MSG_STATUS.READ);
};
let curDate = '';
const groupList: Array<{ date: string; list: LAYOUT.IMsg[] }> = [];
list.forEach((item) => {
const date = moment(item.createdAt).format('YYYY-MM-DD');
if (date !== curDate) {
groupList.push({ date, list: [item] });
curDate = date;
} else {
groupList[groupList.length - 1].list.push(item);
}
});
const clearAllMessage = () => {
Modal.confirm({
title: i18n.t('confirm to read all'),
onOk() {
return clearAll().then(() => message.success(i18n.t('operated successfully')));
},
});
};
return (
<div className="message-center" ref={boxRef as React.RefObject<HTMLDivElement>}>
<div className="header">
<CustomIcon type="arrow-left" onClick={() => layoutStore.reducers.switchMessageCenter(null)} />
{i18n.t('Site message')}
</div>
<div className="content">
<div className="summary flex justify-between">
{i18n.t('{unreadCount} messages unread', {
unreadCount,
})}
<a className="mr-6 cursor-pointer" onClick={() => clearAllMessage()}>
{i18n.t('one key all read')}
</a>
</div>
<Holder when={!list.length}>
<Timeline>
{map(groupList, (group) => {
return (
<Timeline.Item key={group.date}>
<div>{group.date}</div>
<div className="message-list">
{group.list.map((item) => {
const isUnRead = item.status === MSG_STATUS.UNREAD;
return (
<div key={item.id} className="message-item" onClick={() => handleClick(item)}>
<div className="message-item-content flex items-center" title={item.title}>
<span className="status">{isUnRead ? <Badge color="red" /> : null}</span>
<ErdaIcon className="mr-1" type="remind" size="16px" />
<span>{item.title}</span>
</div>
<div>
{item.unreadCount > 1 && (
<span className="unread-count mr-3">
<span className="unread-count-text">
{item.unreadCount > 99 ? '99+' : item.unreadCount}
</span>
</span>
)}
<span className="message-time">{moment(item.createdAt).format('HH:mm:ss')}</span>
</div>
</div>
);
})}
</div>
</Timeline.Item>
);
})}
</Timeline>
<LoadMore
getContainer={() => boxRef.current}
load={() => getMessageList({ pageNo: msgPaging.pageNo + 1 })}
hasMore={msgPaging.hasMore}
isLoading={loadingList}
/>
<Drawer
width="60%"
visible={!!detail}
title={detail && detail.title}
onClose={() => resetDetail()}
destroyOnClose
className="site-message-drawer"
>
<MarkdownRender value={(detail && detail.content) || ''} />
</Drawer>
</Holder>
</div>
</div>
);
}
Example #24
Source File: index.tsx From gant-design with MIT License | 4 votes |
IconHouse: React.FC<IconHouseProps<string>> = ({
onChange,
value,
onBlur = undefined,
addonAfter,
allowEdit,
onEnter,
perfix,
size = 'normal',
controlMode,
...props
}) => {
const prefixCls = 'gant-icon-selector';
// 图标抽屉
const [visible, setvisible] = useState(false);
// 图标id
const [IDs, setIDs] = useState([] as string[]);
// 搜索框
const [text, settext] = useState('');
// 当前icon
const [currentId, setCurrentId] = useState(value);
// 当前显示的图标类型
const iconTypes = useMemo(() => {
let iconTypeArr = [IconTypes.AntIcon];
if (!_.isEmpty(IDs)) {
iconTypeArr.push(IconTypes.IconFont);
}
return iconTypeArr;
}, [IDs]);
const [iconType, seticonType] = useState(iconTypes[0]);
const icons = useMemo(
() => ({
IconFont: IDs,
AntIcon: outline,
}),
[IDs],
);
useEffect(() => {
setCurrentId(value);
}, [value]);
const toggleVisible = useCallback(() => {
if (!visible) {
// 打开
settext('');
}
setvisible(!visible);
}, [visible]);
const onSelectIcon = useCallback((id: string) => {
setCurrentId(id);
if (onChange) onChange(id);
toggleVisible();
}, []);
// 获取图标id
useState(() => {
// const tag = queryIconHouse(iconWareHouse)
const tag = document.querySelector('svg');
if (!tag) return;
const iconIds = [].slice
.call(tag.querySelectorAll('symbol'))
.map((symbol: Element) => symbol.id);
setIDs(iconIds);
});
// 切换图标
const handleTypeChange = useCallback(e => {
seticonType(e.target.value);
}, []);
const iconsWithFilter = useMemo(
() =>
icons[iconType].filter(id => {
return id.includes(text);
}),
[icons, iconType, text],
);
return (
<>
<div className={classnames('gant-icon-select', size)} onClick={toggleVisible}>
{currentId ? (
<Icon type={currentId} title={tr('点击切换')} perfix={perfix} {...props} />
) : (
<span className={prefixCls + '-btn'}>{tr('点击选择')}</span>
)}
</div>
<Drawer
width={visible ? 500 : 0}
title={tr('请选择图标')}
destroyOnClose
placement="right"
onClose={toggleVisible}
visible={visible}
bodyStyle={bodyStyle}
className={drawerClassname}
>
<div className={classnames(prefixCls + '-search')}>
<Radio.Group value={iconType} onChange={handleTypeChange}>
{iconTypes.map(type => (
<Radio.Button key={type} value={type}>
{type}
</Radio.Button>
))}
</Radio.Group>
<div style={{ flex: 1, marginLeft: 10 }}>
<Input
edit={EditStatus.EDIT}
value={text}
onChange={settext}
placeholder={tr('搜索')}
allowClear
/>
</div>
</div>
<div className={classnames(prefixCls + '-scroll')}>
{iconsWithFilter.length ? null : (
<Empty
image={Empty.PRESENTED_IMAGE_SIMPLE}
description={tr('没有匹配图标')}
style={{ margin: '30px auto 0' }}
/>
)}
<div className={classnames(prefixCls + '-content')}>
{iconsWithFilter.map(id => (
<div
className={prefixCls + '-content-item'}
title={id}
key={id}
onClick={() => onSelectIcon(id)}
>
<Icon perfix={perfix} type={id} className={prefixCls + '-content-item-iconitem'} />
<div style={{ width: '100%' }}>{id}</div>
</div>
))}
</div>
</div>
</Drawer>
</>
);
}
Example #25
Source File: index.tsx From ant-design-pro-V4 with MIT License | 4 votes |
TableList: React.FC = () => {
/**
* @en-US Pop-up window of new window
* @zh-CN 新建窗口的弹窗
* */
const [createModalVisible, handleModalVisible] = useState<boolean>(false);
/**
* @en-US The pop-up window of the distribution update window
* @zh-CN 分布更新窗口的弹窗
* */
const [updateModalVisible, handleUpdateModalVisible] = useState<boolean>(false);
const [showDetail, setShowDetail] = useState<boolean>(false);
const actionRef = useRef<ActionType>();
const [currentRow, setCurrentRow] = useState<TableListItem>();
const [selectedRowsState, setSelectedRows] = useState<TableListItem[]>([]);
/**
* @en-US International configuration
* @zh-CN 国际化配置
* */
const intl = useIntl();
const columns: ProColumns<TableListItem>[] = [
{
title: (
<FormattedMessage
id="pages.searchTable.updateForm.ruleName.nameLabel"
defaultMessage="Rule name"
/>
),
dataIndex: 'name',
tip: 'The rule name is the unique key',
render: (dom, entity) => {
return (
<a
onClick={() => {
setCurrentRow(entity);
setShowDetail(true);
}}
>
{dom}
</a>
);
},
},
{
title: <FormattedMessage id="pages.searchTable.titleDesc" defaultMessage="Description" />,
dataIndex: 'desc',
valueType: 'textarea',
},
{
title: (
<FormattedMessage
id="pages.searchTable.titleCallNo"
defaultMessage="Number of service calls"
/>
),
dataIndex: 'callNo',
sorter: true,
hideInForm: true,
renderText: (val: string) =>
`${val}${intl.formatMessage({
id: 'pages.searchTable.tenThousand',
defaultMessage: ' 万 ',
})}`,
},
{
title: <FormattedMessage id="pages.searchTable.titleStatus" defaultMessage="Status" />,
dataIndex: 'status',
hideInForm: true,
valueEnum: {
0: {
text: (
<FormattedMessage
id="pages.searchTable.nameStatus.default"
defaultMessage="Shut down"
/>
),
status: 'Default',
},
1: {
text: (
<FormattedMessage id="pages.searchTable.nameStatus.running" defaultMessage="Running" />
),
status: 'Processing',
},
2: {
text: (
<FormattedMessage id="pages.searchTable.nameStatus.online" defaultMessage="Online" />
),
status: 'Success',
},
3: {
text: (
<FormattedMessage
id="pages.searchTable.nameStatus.abnormal"
defaultMessage="Abnormal"
/>
),
status: 'Error',
},
},
},
{
title: (
<FormattedMessage
id="pages.searchTable.titleUpdatedAt"
defaultMessage="Last scheduled time"
/>
),
sorter: true,
dataIndex: 'updatedAt',
valueType: 'dateTime',
renderFormItem: (item, { defaultRender, ...rest }, form) => {
const status = form.getFieldValue('status');
if (`${status}` === '0') {
return false;
}
if (`${status}` === '3') {
return (
<Input
{...rest}
placeholder={intl.formatMessage({
id: 'pages.searchTable.exception',
defaultMessage: 'Please enter the reason for the exception!',
})}
/>
);
}
return defaultRender(item);
},
},
{
title: <FormattedMessage id="pages.searchTable.titleOption" defaultMessage="Operating" />,
dataIndex: 'option',
valueType: 'option',
render: (_, record) => [
<a
key="config"
onClick={() => {
handleUpdateModalVisible(true);
setCurrentRow(record);
}}
>
<FormattedMessage id="pages.searchTable.config" defaultMessage="Configuration" />
</a>,
<a key="subscribeAlert" href="https://procomponents.ant.design/">
<FormattedMessage
id="pages.searchTable.subscribeAlert"
defaultMessage="Subscribe to alerts"
/>
</a>,
],
},
];
return (
<PageContainer>
<ProTable<TableListItem>
headerTitle={intl.formatMessage({
id: 'pages.searchTable.title',
defaultMessage: 'Enquiry form',
})}
actionRef={actionRef}
rowKey="key"
search={{
labelWidth: 120,
}}
toolBarRender={() => [
<Button
type="primary"
key="primary"
onClick={() => {
handleModalVisible(true);
}}
>
<PlusOutlined /> <FormattedMessage id="pages.searchTable.new" defaultMessage="New" />
</Button>,
]}
request={(params, sorter, filter) => queryRule({ ...params, sorter, filter })}
columns={columns}
rowSelection={{
onChange: (_, selectedRows) => {
setSelectedRows(selectedRows);
},
}}
/>
{selectedRowsState?.length > 0 && (
<FooterToolbar
extra={
<div>
<FormattedMessage id="pages.searchTable.chosen" defaultMessage="Chosen" />{' '}
<a style={{ fontWeight: 600 }}>{selectedRowsState.length}</a>{' '}
<FormattedMessage id="pages.searchTable.item" defaultMessage="项" />
<span>
<FormattedMessage
id="pages.searchTable.totalServiceCalls"
defaultMessage="Total number of service calls"
/>{' '}
{selectedRowsState.reduce((pre, item) => pre + item.callNo, 0)}{' '}
<FormattedMessage id="pages.searchTable.tenThousand" defaultMessage="万" />
</span>
</div>
}
>
<Button
onClick={async () => {
await handleRemove(selectedRowsState);
setSelectedRows([]);
actionRef.current?.reloadAndRest?.();
}}
>
<FormattedMessage
id="pages.searchTable.batchDeletion"
defaultMessage="Batch deletion"
/>
</Button>
<Button type="primary">
<FormattedMessage
id="pages.searchTable.batchApproval"
defaultMessage="Batch approval"
/>
</Button>
</FooterToolbar>
)}
<ModalForm
title={intl.formatMessage({
id: 'pages.searchTable.createForm.newRule',
defaultMessage: 'New rule',
})}
width="400px"
visible={createModalVisible}
onVisibleChange={handleModalVisible}
onFinish={async (value) => {
const success = await handleAdd(value as TableListItem);
if (success) {
handleModalVisible(false);
if (actionRef.current) {
actionRef.current.reload();
}
}
}}
>
<ProFormText
rules={[
{
required: true,
message: (
<FormattedMessage
id="pages.searchTable.ruleName"
defaultMessage="Rule name is required"
/>
),
},
]}
width="md"
name="name"
/>
<ProFormTextArea width="md" name="desc" />
</ModalForm>
<UpdateForm
onSubmit={async (value) => {
const success = await handleUpdate(value);
if (success) {
handleUpdateModalVisible(false);
setCurrentRow(undefined);
if (actionRef.current) {
actionRef.current.reload();
}
}
}}
onCancel={() => {
handleUpdateModalVisible(false);
setCurrentRow(undefined);
}}
updateModalVisible={updateModalVisible}
values={currentRow || {}}
/>
<Drawer
width={600}
visible={showDetail}
onClose={() => {
setCurrentRow(undefined);
setShowDetail(false);
}}
closable={false}
>
{currentRow?.name && (
<ProDescriptions<TableListItem>
column={2}
title={currentRow?.name}
request={async () => ({
data: currentRow || {},
})}
params={{
id: currentRow?.name,
}}
columns={columns as ProDescriptionsItemProps<TableListItem>[]}
/>
)}
</Drawer>
</PageContainer>
);
}
Example #26
Source File: Home.tsx From react-ts-antd with MIT License | 4 votes |
AddEditTaskForm: React.FC<IProps> = ({
title,
textBtn,
visible,
currentRowData,
onSubmitDrawer,
onCloseDrawer
}) => {
const [form] = Form.useForm();
console.log('currentRowData===', currentRowData)
setTimeout(() => {
form.setFieldsValue(currentRowData);
}, 100)
const onSubmit = () => {
form.validateFields()
.then((values: any) => {
if (title === '添加任务') {
onSubmitDrawer(values, 1);
} else {
onSubmitDrawer(values, 2);
}
})
.catch(info => {
console.log('Validate Failed:', info);
})
}
const onReset = () => {
form.resetFields();
}
const onClose = () => {
form.resetFields();
onCloseDrawer();
}
return (
<Drawer
forceRender
title={ title }
width={ 600 }
onClose={ onClose }
visible={ visible }
bodyStyle={{ paddingBottom: 80 }}
maskClosable={ false }
footer={
<div style={{display: 'flex', justifyContent: 'space-around'}}>
<Button onClick={ onSubmit } type="primary">{ textBtn }</Button>
<Button onClick={ onReset }>重置</Button>
<Button onClick={ onClose } danger>取消</Button>
</div>
}
>
<Form
form={ form }
layout="vertical"
name="form_in_modal"
>
<Form.Item
label="任务名称"
name="title"
rules={[{ required: true, message: '请输入任务名称' }]}
>
<Input placeholder="请输入任务名称" />
</Form.Item>
<Form.Item
label="截止日期"
name="date"
rules={[{ required: true, message: '请选择截止日期' }]}
>
<DatePicker inputReadOnly={ true } placeholder="请选择截止日期" style={{ width: '100%' }} />
</Form.Item>
<Form.Item
label="任务内容"
name="content"
rules={[{ required: true, message: '请输入任务内容' }]}
>
<Input.TextArea rows={ 7 } placeholder="请输入任务内容" className="textarea" />
</Form.Item>
</Form>
</Drawer>
)
}
Example #27
Source File: index.tsx From jetlinks-ui-antd with MIT License | 4 votes |
DataAccess: React.FC<Props> = (props) => {
const { checkPermission } = props;
const { form: { getFieldDecorator }, form } = props;
const dataAccesses = (checkPermission.autz || {}).dataAccesses || [];
const saveDataAccess = () => {
//组合数据,反向获取未勾选的数据
const data = form.getFieldsValue();
const tempFieldAccess = data.fieldAccess;
const tempDataAccess = data.dataAccess;
let permissionId = checkPermission.id;
let fieldAccess: any[] = [];
let dataAccess: any[] = [];
for (const key in tempFieldAccess) {
const tempAction = (checkPermission.actions).filter((item: any) =>
((item.properties || {}).supportDataAccess || '').indexOf('DENY_FIELDS') > -1)
.map((e: { action: string, name: string }) => e.action);
if (tempFieldAccess.hasOwnProperty(key)) {
const element = tempFieldAccess[key];
const action = subtract(tempAction, element);
if (action.size > 0) {
fieldAccess.push({ name: key, action: [...action] });
}
}
}
for (const key in tempDataAccess) {
// const tempAction = (checkPermission.actions || [])
// .filter((item: any) =>
// ((item.properties || {}).supportDataAccess || '').indexOf('org') > -1)
// .map((e: { action: string, name: string }) => e.action)
if (tempDataAccess.hasOwnProperty(key)) {
const element = tempDataAccess[key];
// const action = subtract(tempAction, element);
// if (action.size > 0) {
dataAccess.push({ type: key, action: [...element] });
// }
}
}
props.save({ permissionId, fieldAccess, dataAccess });
}
return (
<Drawer
visible
title="数据权限配置"
onClose={() => { props.close() }}
width={'30VW'}
>
<div id="permission-drawer">
<Tabs defaultActiveKey="field">
<Tabs.TabPane tab="字段权限" key="field" forceRender={true}>
<Table
rowKey={'name'}
pagination={false}
style={{ height: '70vh', overflow: 'auto' }}
columns={[
{
dataIndex: 'name',
title: '字段名称',
},
{
title: '操作',
render: (record: any) => {
//禁用的操作,(UI中取消勾选的操作)
let tempItem = (dataAccesses as any[])
.filter(item => item.type !== 'DENY-FIELDS')
.filter(item => (item.config.fields || [])
.some((e: string) => e === record.name))
.map(i => i.action);
//所有操作
let tempInit = (checkPermission.actions).filter((item: any) =>
((item.properties || {}).supportDataAccess || '').indexOf('DENY_FIELDS') > -1)
.map((e: { action: string, name: string }) => e.action);
return (
<div className={styles.permissionForm}>
<Form.Item >
{getFieldDecorator(`fieldAccess.${record.name}`, {
initialValue: [...subtract(tempInit, tempItem)],
})(
<Checkbox.Group
options={
(checkPermission.actions || [])
.filter((item: any) =>
((item.properties || {}).supportDataAccess || '').indexOf('DENY_FIELDS') > -1)
.map((e: { action: string, name: string }) => { return { 'label': e.name, 'value': e.action } })
} />
)}
</Form.Item>
</div>
)
}
}
]}
dataSource={checkPermission.optionalFields}
/>
</Tabs.TabPane>
<Tabs.TabPane tab="数据权限" key="data" forceRender={true}>
<Table
rowKey='name'
columns={[
{
dataIndex: 'name',
title: '名称'
}, {
title: '操作',
render: (record) => {
//禁用的操作,(UI中取消勾选的操作)
let tempItem = (dataAccesses as any[])
.filter(item => (item.config || {}).scopeType === 'org')
.map(i => i.action);
// let tempInit = (checkPermission.actions || [])
// .filter((item: any) =>
// ((item.properties || {}).supportDataAccess || '').indexOf('org') > -1)
// .map((e: { action: string, name: string }) => e.action)
return (
<div className={styles.permissionForm}>
<Form.Item>
{getFieldDecorator(`dataAccess.org`, {
initialValue: tempItem
})(
<Checkbox.Group
options={
(checkPermission.actions || [])
.filter((item: any) =>
((item.properties || {}).supportDataAccess || '').indexOf('org') > -1)
.map((e: { action: string, name: string }) => { return { 'label': e.name, 'value': e.action } })
}
/>
)}
</Form.Item>
</div>
)
}
}
]}
dataSource={
checkPermission.properties.supportDataAccessTypes.some((e: string) => e === 'org') ? [
{ name: '仅限所在机构的数据' }
] : []
}
/>
</Tabs.TabPane>
</Tabs>
<div
style={{
position: 'absolute',
right: 0,
bottom: 0,
width: '100%',
borderTop: '1px solid #e9e9e9',
padding: '10px 16px',
background: '#fff',
textAlign: 'right',
}}
>
<Button onClick={() => { props.close() }} style={{ marginRight: 8 }}>
关闭
</Button>
<Button onClick={() => { saveDataAccess() }} type="primary">
确认
</Button>
</div>
</div>
</Drawer>
)
}