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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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}
              &nbsp;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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 />}
              />
              &nbsp;
              {!isEditing ? (
                <Button
                  type="default"
                  className={s.toggle}
                  onClick={toggleEdit}
                  icon={<EditOutlined />}
                />
              ) : null}
              {isEditing ? (
                <Button
                  type="default"
                  className={s.toggle}
                  onClick={toggleEdit}
                  icon={<EyeOutlined />}
                />
              ) : null}
              &nbsp;
              <Button
                type="default"
                icon={<SettingOutlined />}
                onClick={() => setShowPageDrawer(true)}
              >
                页面
              </Button>
              &nbsp;
              <Button
                type="default"
                icon={<PlusOutlined />}
                onClick={() => setShowDrawer(true)}
              >
                组件
              </Button>
              
              <Undo />
              &nbsp;
              <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 ? <>
                &nbsp;
                <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 vote down vote up
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 vote down vote up
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 vote down vote up
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="项" />
              &nbsp;&nbsp;
              <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 vote down vote up
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 vote down vote up
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>

    )
}