@ant-design/icons#SyncOutlined JavaScript Examples

The following examples show how to use @ant-design/icons#SyncOutlined. 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: ShowWarehouseCapacity.jsx    From schema-plugin-flow with MIT License 6 votes vote down vote up
ShowWarehouseCapacity = props => {
  const [counts, setCount] = useState({});
  const refreshCount = () => setTimeout(() => {
    const newCounts = { ...counts };
    (props.options || []).forEach(item => {
      newCounts[item.value] = Math.ceil(Math.random() * 100);
    });
    setCount(newCounts);
  }, 50);
  useEffect(() => {
    refreshCount();
  }, []);
  const {
    style = {}, options = [], onChange, value
  } = props;
  return (
    <div style={style}>
      <SyncOutlined className="capacity-refresh" onClick={refreshCount} />
      <div className="capacity-select">
        {
          options.map(item => {
            const cls = item.value === value ? 'capacity-item selected' : 'capacity-item';
            return (
              <div
                className={cls}
                onClick={() => onChange(item.value)}
              >
                {`${item.label} 库存:${counts[item.value] || ''}`}
              </div>
            );
          })
        }
      </div>
    </div>
  );
}
Example #2
Source File: status.jsx    From virtuoso-design-system with MIT License 6 votes vote down vote up
storiesOf('antd/tag', module).add('status', () => 
  <>
    <Divider orientation="left">Without icon</Divider>
    <div>
      <Tag color="success">success</Tag>
      <Tag color="processing">processing</Tag>
      <Tag color="error">error</Tag>
      <Tag color="warning">warning</Tag>
      <Tag color="default">default</Tag>
    </div>
    <Divider orientation="left">With icon</Divider>
    <div>
      <Tag icon={<CheckCircleOutlined />} color="success">
        success
      </Tag>
      <Tag icon={<SyncOutlined spin />} color="processing">
        processing
      </Tag>
      <Tag icon={<CloseCircleOutlined />} color="error">
        error
      </Tag>
      <Tag icon={<ExclamationCircleOutlined />} color="warning">
        warning
      </Tag>
      <Tag icon={<ClockCircleOutlined />} color="default">
        waiting
      </Tag>
      <Tag icon={<MinusCircleOutlined />} color="default">
        stop
      </Tag>
    </div>
  </>,
  { docs: { page: () => (<><h1 id="enus">en-US</h1>
<p>We preset five different colors, you can set color property such as <code>success</code>,<code>processing</code>,<code>error</code>,<code>default</code> and <code>warning</code> to indicate specific status.</p></>) } });
Example #3
Source File: basic.jsx    From virtuoso-design-system with MIT License 6 votes vote down vote up
storiesOf('antd/Icon', module).add('basic', () => 
  <div className="icons-list">
    <HomeOutlined />
    <SettingFilled />
    <SmileOutlined />
    <SyncOutlined spin />
    <SmileOutlined rotate={180} />
    <LoadingOutlined />
  </div>,
  { docs: { page: () => (<><h1 id="enus">en-US</h1>
<p>Import icons from <code>@ant-design/icons</code>, component name of icons with different theme is the icon name suffixed by the theme name. Specify the <code>spin</code> property to show spinning animation.</p></>) } });
Example #4
Source File: index.js    From gobench with Apache License 2.0 6 votes vote down vote up
render() {
    return (
      <div>
        <h5 className="mb-3">
          <strong>Icons Usage</strong>
        </h5>
        <div className="mb-5">
          <HomeOutlined className="mr-3 mb-3 font-size-24" />
          <SettingFilled className="mr-3 mb-3 font-size-24" />
          <SmileOutlined className="mr-3 mb-3 font-size-24" />
          <SyncOutlined spin className="mr-3 mb-3 font-size-24" />
          <SmileOutlined rotate={180} className="mr-3 mb-3 font-size-24" />
          <LoadingOutlined className="mr-3 mb-3 font-size-24" />
        </div>
      </div>
    )
  }
Example #5
Source File: settings.js    From hashcat.launcher with MIT License 5 votes vote down vote up
render() {
		return (
			<>
				<PageHeader
					title="Settings"
				/>
				<Content style={{ padding: '16px 24px' }}>
					<Row gutter={[16, 14]}>
						<Col span={12}>
							<Statistic title="Hashes" value={this.state._hashes.length} />
						</Col>
						<Col span={12}>
							<Statistic title="Algorithms" value={Object.keys(this.state._algorithms).length} />
						</Col>
						<Col span={12}>
							<Statistic title="Dictionaries" value={this.state._dictionaries.length} />
						</Col>
						<Col span={12}>
							<Statistic title="Rules" value={this.state._rules.length} />
						</Col>
						<Col span={12}>
							<Statistic title="Masks" value={this.state._masks.length} />
						</Col>
						<Col span={24}>
							<Button
								icon={<SyncOutlined />}
								type="primary"
								onClick={this.onClickRescan}
								loading={this.state.isLoadingRescan}
							>
								Rescan
							</Button>
						</Col>
					</Row>
					<Row style={{ marginTop: "2rem" }} gutter={[16, 14]}>
						<Col span={24}>
							<Statistic
								title="Task counter"
								value={this.state.taskCounter}
							/>
							<Space>
							<Button
								style={{ marginTop: 16 }}
								type="default"
								onClick={this.onClickRefreshTaskCounter}
								loading={this.state.isLoadingRefreshTaskCounter}
							>
								Refresh
							</Button>
							<Popconfirm
								placement="topRight"
								title="Are you sure you want to reset the task counter?"
								onConfirm={this.onClickResetTaskCounter}
								okText="Yes"
								cancelText="No"
							>
								<Button
									style={{ marginTop: 16 }}
									type="danger"
									loading={this.state.isLoadingResetTaskCounter}
								>
									Reset counter
								</Button>
							</Popconfirm>
							</Space>
						</Col>
					</Row>
				</Content>
			</>
		)
	}
Example #6
Source File: ExampleUI.jsx    From nft-e2e-example with MIT License 4 votes vote down vote up
export default function ExampleUI({
  purpose,
  setPurposeEvents,
  address,
  mainnetProvider,
  userProvider,
  localProvider,
  yourLocalBalance,
  price,
  tx,
  readContracts,
  writeContracts,
}) {
  const [newPurpose, setNewPurpose] = useState("loading...");

  return (
    <div>
      {/*
        ⚙️ Here is an example UI that displays and sets the purpose in your smart contract:
      */}
      <div style={{ border: "1px solid #cccccc", padding: 16, width: 400, margin: "auto", marginTop: 64 }}>
        <h2>Example UI:</h2>
        <h4>purpose: {purpose}</h4>
        <Divider />
        <div style={{ margin: 8 }}>
          <Input
            onChange={e => {
              setNewPurpose(e.target.value);
            }}
          />
          <Button
            onClick={() => {
              console.log("newPurpose", newPurpose);
              /* look how you call setPurpose on your contract: */
              tx(writeContracts.YourContract.setPurpose(newPurpose));
            }}
          >
            Set Purpose
          </Button>
        </div>
        <Divider />
        Your Address:
        <Address address={address} ensProvider={mainnetProvider} fontSize={16} />
        <Divider />
        ENS Address Example:
        <Address
          address="0x34aA3F359A9D614239015126635CE7732c18fDF3" /* this will show as austingriffith.eth */
          ensProvider={mainnetProvider}
          fontSize={16}
        />
        <Divider />
        {/* use formatEther to display a BigNumber: */}
        <h2>Your Balance: {yourLocalBalance ? formatEther(yourLocalBalance) : "..."}</h2>
        <div>OR</div>
        <Balance address={address} provider={localProvider} price={price} />
        <Divider />
        <div>? Example Whale Balance:</div>
        <Balance balance={parseEther("1000")} provider={localProvider} price={price} />
        <Divider />
        {/* use formatEther to display a BigNumber: */}
        <h2>Your Balance: {yourLocalBalance ? formatEther(yourLocalBalance) : "..."}</h2>
        <Divider />
        Your Contract Address:
        <Address
          address={readContracts ? readContracts.YourContract.address : readContracts}
          ensProvider={mainnetProvider}
          fontSize={16}
        />
        <Divider />
        <div style={{ margin: 8 }}>
          <Button
            onClick={() => {
              /* look how you call setPurpose on your contract: */
              tx(writeContracts.YourContract.setPurpose("? Cheers"));
            }}
          >
            Set Purpose to &quot;? Cheers&quot;
          </Button>
        </div>
        <div style={{ margin: 8 }}>
          <Button
            onClick={() => {
              /*
              you can also just craft a transaction and send it to the tx() transactor
              here we are sending value straight to the contract's address:
            */
              tx({
                to: writeContracts.YourContract.address,
                value: parseEther("0.001"),
              });
              /* this should throw an error about "no fallback nor receive function" until you add it */
            }}
          >
            Send Value
          </Button>
        </div>
        <div style={{ margin: 8 }}>
          <Button
            onClick={() => {
              /* look how we call setPurpose AND send some value along */
              tx(
                writeContracts.YourContract.setPurpose("? Paying for this one!", {
                  value: parseEther("0.001"),
                }),
              );
              /* this will fail until you make the setPurpose function payable */
            }}
          >
            Set Purpose With Value
          </Button>
        </div>
        <div style={{ margin: 8 }}>
          <Button
            onClick={() => {
              /* you can also just craft a transaction and send it to the tx() transactor */
              tx({
                to: writeContracts.YourContract.address,
                value: parseEther("0.001"),
                data: writeContracts.YourContract.interface.encodeFunctionData("setPurpose(string)", [
                  "? Whoa so 1337!",
                ]),
              });
              /* this should throw an error about "no fallback nor receive function" until you add it */
            }}
          >
            Another Example
          </Button>
        </div>
      </div>

      {/*
        ? Maybe display a list of events?
          (uncomment the event and emit line in YourContract.sol! )
      */}
      <div style={{ width: 600, margin: "auto", marginTop: 32, paddingBottom: 32 }}>
        <h2>Events:</h2>
        <List
          bordered
          dataSource={setPurposeEvents}
          renderItem={item => {
            return (
              <List.Item key={item.blockNumber + "_" + item.sender + "_" + item.purpose}>
                <Address address={item[0]} ensProvider={mainnetProvider} fontSize={16} /> =&gt
                {item[1]}
              </List.Item>
            );
          }}
        />
      </div>

      <div style={{ width: 600, margin: "auto", marginTop: 32, paddingBottom: 256 }}>
        <Card>
          Check out all the{" "}
          <a
            href="https://github.com/austintgriffith/scaffold-eth/tree/master/packages/react-app/src/components"
            target="_blank"
            rel="noopener noreferrer"
          >
            ? components
          </a>
        </Card>

        <Card style={{ marginTop: 32 }}>
          <div>
            There are tons of generic components included from{" "}
            <a href="https://ant.design/components/overview/" target="_blank" rel="noopener noreferrer">
              ? ant.design
            </a>{" "}
            too!
          </div>

          <div style={{ marginTop: 8 }}>
            <Button type="primary">Buttons</Button>
          </div>

          <div style={{ marginTop: 8 }}>
            <SyncOutlined spin /> Icons
          </div>

          <div style={{ marginTop: 8 }}>
            Date Pickers?
            <div style={{ marginTop: 2 }}>
              <DatePicker onChange={() => {}} />
            </div>
          </div>

          <div style={{ marginTop: 32 }}>
            <Slider range defaultValue={[20, 50]} onChange={() => {}} />
          </div>

          <div style={{ marginTop: 32 }}>
            <Switch defaultChecked onChange={() => {}} />
          </div>

          <div style={{ marginTop: 32 }}>
            <Progress percent={50} status="active" />
          </div>

          <div style={{ marginTop: 32 }}>
            <Spin />
          </div>
        </Card>
      </div>
    </div>
  );
}
Example #7
Source File: ExampleUI.jsx    From Tai-Shang-NFT-Wallet with MIT License 4 votes vote down vote up
export default function ExampleUI({
  purpose,
  setPurposeEvents,
  address,
  mainnetProvider,
  localProvider,
  yourLocalBalance,
  price,
  tx,
  readContracts,
  writeContracts,
}) {
  const [newPurpose, setNewPurpose] = useState("loading...");

  return (
    <div>
      {/*
        ⚙️ Here is an example UI that displays and sets the purpose in your smart contract:
      */}
      <div style={{ border: "1px solid #cccccc", padding: 16, width: 400, margin: "auto", marginTop: 64 }}>
        <h2>Example UI:</h2>
        <h4>purpose: {purpose}</h4>
        <Divider />
        <div style={{ margin: 8 }}>
          <Input
            onChange={e => {
              setNewPurpose(e.target.value);
            }}
          />
          <Button
            style={{ marginTop: 8 }}
            onClick={async () => {
              /* look how you call setPurpose on your contract: */
              /* notice how you pass a call back for tx updates too */
              const result = tx(writeContracts.YourContract.setPurpose(newPurpose), update => {
                console.log("? Transaction Update:", update);
                if (update && (update.status === "confirmed" || update.status === 1)) {
                  console.log(" ? Transaction " + update.hash + " finished!");
                  console.log(
                    " ⛽️ " +
                      update.gasUsed +
                      "/" +
                      (update.gasLimit || update.gas) +
                      " @ " +
                      parseFloat(update.gasPrice) / 1000000000 +
                      " gwei",
                  );
                }
              });
              console.log("awaiting metamask/web3 confirm result...", result);
              console.log(await result);
            }}
          >
            Set Purpose!
          </Button>
        </div>
        <Divider />
        Your Address:
        <Address address={address} ensProvider={mainnetProvider} fontSize={16} />
        <Divider />
        ENS Address Example:
        <Address
          address="0x34aA3F359A9D614239015126635CE7732c18fDF3" /* this will show as austingriffith.eth */
          ensProvider={mainnetProvider}
          fontSize={16}
        />
        <Divider />
        {/* use utils.formatEther to display a BigNumber: */}
        <h2>Your Balance: {yourLocalBalance ? utils.formatEther(yourLocalBalance) : "..."}</h2>
        <div>OR</div>
        <Balance address={address} provider={localProvider} price={price} />
        <Divider />
        <div>? Example Whale Balance:</div>
        <Balance balance={utils.parseEther("1000")} provider={localProvider} price={price} />
        <Divider />
        {/* use utils.formatEther to display a BigNumber: */}
        <h2>Your Balance: {yourLocalBalance ? utils.formatEther(yourLocalBalance) : "..."}</h2>
        <Divider />
        Your Contract Address:
        <Address
          address={readContracts && readContracts.YourContract ? readContracts.YourContract.address : null}
          ensProvider={mainnetProvider}
          fontSize={16}
        />
        <Divider />
        <div style={{ margin: 8 }}>
          <Button
            onClick={() => {
              /* look how you call setPurpose on your contract: */
              tx(writeContracts.YourContract.setPurpose("? Cheers"));
            }}
          >
            Set Purpose to &quot;? Cheers&quot;
          </Button>
        </div>
        <div style={{ margin: 8 }}>
          <Button
            onClick={() => {
              /*
              you can also just craft a transaction and send it to the tx() transactor
              here we are sending value straight to the contract's address:
            */
              tx({
                to: writeContracts.YourContract.address,
                value: utils.parseEther("0.001"),
              });
              /* this should throw an error about "no fallback nor receive function" until you add it */
            }}
          >
            Send Value
          </Button>
        </div>
        <div style={{ margin: 8 }}>
          <Button
            onClick={() => {
              /* look how we call setPurpose AND send some value along */
              tx(
                writeContracts.YourContract.setPurpose("? Paying for this one!", {
                  value: utils.parseEther("0.001"),
                }),
              );
              /* this will fail until you make the setPurpose function payable */
            }}
          >
            Set Purpose With Value
          </Button>
        </div>
        <div style={{ margin: 8 }}>
          <Button
            onClick={() => {
              /* you can also just craft a transaction and send it to the tx() transactor */
              tx({
                to: writeContracts.YourContract.address,
                value: utils.parseEther("0.001"),
                data: writeContracts.YourContract.interface.encodeFunctionData("setPurpose(string)", [
                  "? Whoa so 1337!",
                ]),
              });
              /* this should throw an error about "no fallback nor receive function" until you add it */
            }}
          >
            Another Example
          </Button>
        </div>
      </div>

      {/*
        ? Maybe display a list of events?
          (uncomment the event and emit line in YourContract.sol! )
      */}
      <div style={{ width: 600, margin: "auto", marginTop: 32, paddingBottom: 32 }}>
        <h2>Events:</h2>
        <List
          bordered
          dataSource={setPurposeEvents}
          renderItem={item => {
            return (
              <List.Item key={item.blockNumber + "_" + item.sender + "_" + item.purpose}>
                <Address address={item[0]} ensProvider={mainnetProvider} fontSize={16} />
                {item[1]}
              </List.Item>
            );
          }}
        />
      </div>

      <div style={{ width: 600, margin: "auto", marginTop: 32, paddingBottom: 256 }}>
        <Card>
          Check out all the{" "}
          <a
            href="https://github.com/austintgriffith/scaffold-eth/tree/master/packages/react-app/src/components"
            target="_blank"
            rel="noopener noreferrer"
          >
            ? components
          </a>
        </Card>

        <Card style={{ marginTop: 32 }}>
          <div>
            There are tons of generic components included from{" "}
            <a href="https://ant.design/components/overview/" target="_blank" rel="noopener noreferrer">
              ? ant.design
            </a>{" "}
            too!
          </div>

          <div style={{ marginTop: 8 }}>
            <Button type="primary">Buttons</Button>
          </div>

          <div style={{ marginTop: 8 }}>
            <SyncOutlined spin /> Icons
          </div>

          <div style={{ marginTop: 8 }}>
            Date Pickers?
            <div style={{ marginTop: 2 }}>
              <DatePicker onChange={() => {}} />
            </div>
          </div>

          <div style={{ marginTop: 32 }}>
            <Slider range defaultValue={[20, 50]} onChange={() => {}} />
          </div>

          <div style={{ marginTop: 32 }}>
            <Switch defaultChecked onChange={() => {}} />
          </div>

          <div style={{ marginTop: 32 }}>
            <Progress percent={50} status="active" />
          </div>

          <div style={{ marginTop: 32 }}>
            <Spin />
          </div>
        </Card>
      </div>
    </div>
  );
}
Example #8
Source File: main.js    From ant-simple-pro with MIT License 4 votes vote down vote up
LayoutTable = memo(function LayoutTable({ btnGrounp,
  iconGrounp, tableTitle, tableProps, pagaTionProps, loading, receive, children }) {

  const [tableSize, setTableSize] = useState('middle');

  const [pagaTionSize, setPagaTionSize] = useState('default');

  const [columns, setColumns] = useState(tableProps.columns);

  const elemet = useRef(null);

  const tableSizeFunc = (size) => {
    setTableSize(size)
    setPagaTionSize(size === "small" ? 'small' : 'default')
  }

  const filterColunsFunc = (val) => { // 动态控制colum
    setColumns(val);
  }

  const defauluIcon = [
    {
      component: <Tooltip title='刷新' placement="bottom">
        <SyncOutlined onClick={(event) => receive(event)} className='svg-fontSize' />
      </Tooltip>
    }, {
      component: <Filter tablecolumns={tableProps.columns} filterColunsFunc={filterColunsFunc} className='svg-fontSize' />
    }, {
      component: <TableSize tableSize={tableSizeFunc} className='svg-fontSize' />
    }, {
      component: <FullScreeOut elementObj={elemet.current} className='svg-fontSize' />
    }
  ];
  return (
    <ConfigProvider getPopupContainer={() => (elemet.current || document.body)}>
      <div className={style.layoutTable} ref={elemet}>
        {
          // 占位,可以是select或者其他外传的组件
          children ? <div className={style['header-others']}>{children}</div> : null
        }
        <div className={style['header-option']}>
          <div className={style['header-option-title']}>{tableTitle}</div>
          <div className={style['header-option-func']}>
            <div className={style['option-btn']}>
              {
                btnGrounp?.length ? btnGrounp.map((item, index) => (
                  <div key={index}>
                    {
                      item.component ? <>{item.component}</> : (<Buttons
                        title={item.title}
                        iconClass={item.iconClass}
                        {...item}
                      />
                      )
                    }
                  </div>
                )) : null
              }
            </div>
            <div className={style['option-icon']}>
              {(btnGrounp?.length) ? <Line /> : null}
              <div className={style['icon-grounp']}>
                {
                  defauluIcon.map((item, index) => <div className={style['icon-data']} key={index}>
                    <div>{item.component}</div>
                  </div>)
                }
                {
                  iconGrounp ? iconGrounp.map((item, index) => (
                    (<div className={style['icon-data']} key={index}>
                      {
                        item.component ? <div>{item.component}</div> : (
                          <Tooltip title={item.title} placement="bottom">
                            <div>{item.icon}</div>
                          </Tooltip>
                        )
                      }
                    </div>))) : null
                }
              </div>
            </div>
          </div>
        </div>
        <Table loading={loading} size={tableSize} {...tableProps} columns={columns} />
        <Pagination {...pagaTionProps} className='view-pagitaion' size={pagaTionSize} />
      </div>
    </ConfigProvider>
  )
})
Example #9
Source File: UserShareSelectedAsset.js    From next-terminal with GNU Affero General Public License v3.0 4 votes vote down vote up
render() {

        const columns = [{
            title: '序号',
            dataIndex: 'id',
            key: 'id',
            render: (id, record, index) => {
                return index + 1;
            }
        }, {
            title: '资产名称',
            dataIndex: 'name',
            key: 'name',
            render: (name, record) => {
                let short = name;
                if (short && short.length > 15) {
                    short = short.substring(0, 15) + " ...";
                }
                return (
                    <Tooltip placement="topLeft" title={name}>
                        {short}
                    </Tooltip>
                );
            }
        }, {
            title: '协议',
            dataIndex: 'protocol',
            key: 'protocol',
            render: (text, record) => {
                const title = `${record['ip'] + ':' + record['port']}`
                return (
                    <Tooltip title={title}>
                        <Tag color={PROTOCOL_COLORS[text]}>{text}</Tag>
                    </Tooltip>
                )
            }
        }, {
            title: '标签',
            dataIndex: 'tags',
            key: 'tags',
            render: tags => {
                if (!isEmpty(tags)) {
                    let tagDocuments = []
                    let tagArr = tags.split(',');
                    for (let i = 0; i < tagArr.length; i++) {
                        if (tags[i] === '-') {
                            continue;
                        }
                        tagDocuments.push(<Tag key={tagArr[i]}>{tagArr[i]}</Tag>)
                    }
                    return tagDocuments;
                }
            }
        }, {
            title: '状态',
            dataIndex: 'active',
            key: 'active',
            render: text => {

                if (text) {
                    return (
                        <Tooltip title='运行中'>
                            <Badge status="processing" text='运行中'/>
                        </Tooltip>
                    )
                } else {
                    return (
                        <Tooltip title='不可用'>
                            <Badge status="error" text='不可用'/>
                        </Tooltip>
                    )
                }
            }
        }, {
            title: '所有者',
            dataIndex: 'ownerName',
            key: 'ownerName'
        }, {
            title: '创建日期',
            dataIndex: 'created',
            key: 'created',
            render: (text, record) => {
                return (
                    <Tooltip title={text}>
                        {dayjs(text).fromNow()}
                    </Tooltip>
                )
            }
        },
        ];

        const selectedRowKeys = this.state.selectedRowKeys;
        const rowSelection = {
            selectedRowKeys: this.state.selectedRowKeys,
            onChange: (selectedRowKeys, selectedRows) => {
                this.setState({selectedRowKeys, selectedRows});
            },
            getCheckboxProps: (record) => ({
                disabled: record['disabled'],
            }),
        };
        let hasSelected = false;
        if (selectedRowKeys.length > 0) {
            let totalSelectedRows = this.state.totalSelectedRows;
            let allSelectedRowKeys = totalSelectedRows.map(item => item['id']);
            for (let i = 0; i < selectedRowKeys.length; i++) {
                let selectedRowKey = selectedRowKeys[i];
                if (!allSelectedRowKeys.includes(selectedRowKey)) {
                    hasSelected = true;
                    break;
                }
            }
        }

        const renderStatus = (text) => {
            if (text === '1') {
                return <Tag color={'green'}>允许</Tag>
            } else {
                return <Tag color={'red'}>禁止</Tag>
            }
        }

        return (
            <>
                <Row gutter={16}>
                    <Col span={6}>
                        <Title level={3}>授权策略</Title>
                        <Select style={{minWidth: 200}} onChange={(strategyId) => {
                            this.setState({
                                'strategyId': strategyId
                            })
                        }}>
                            {this.state.strategies.map(item => {
                                return (
                                    <Select.Option key={item.id}>{item.name}</Select.Option>
                                );
                            })}
                        </Select>
                    </Col>
                    <Col span={18}>
                        <Title level={3}>已授权资产列表</Title>
                        <div>
                            {
                                this.state.totalSelectedRows.map(item => {
                                    let strategyName = '「未配置策略」';
                                    let content = '';
                                    if (item['strategy'] !== undefined) {
                                        strategyName = item['strategy']['name'];
                                        content = (
                                            <div>
                                                <p>上传:{renderStatus(item['strategy']['upload'])}</p>
                                                <p>下载:{renderStatus(item['strategy']['download'])}</p>
                                                <p>编辑:{renderStatus(item['strategy']['edit'])}</p>
                                                <p>删除:{renderStatus(item['strategy']['delete'])}</p>
                                                <p>重命名:{renderStatus(item['strategy']['rename'])}</p>
                                                <p>复制:{renderStatus(item['strategy']['copy'])}</p>
                                                <p>粘贴:{renderStatus(item['strategy']['paste'])}</p>
                                            </div>
                                        );
                                    }

                                    return (
                                        <Popover content={content} title={strategyName}>
                                            <Tag color={PROTOCOL_COLORS[item['protocol']]} closable
                                                 onClose={(e) => {
                                                     e.preventDefault()
                                                     this.unSelectRow(item['id'])
                                                 }}
                                                 key={item['id']}>{[item['name'], strategyName].join(':')}</Tag>
                                        </Popover>
                                    );
                                })
                            }
                        </div>
                    </Col>
                </Row>
                <Divider/>

                <Content key='page-content' className="site-layout-background">
                    <div style={{marginBottom: 20}}>
                        <Row justify="space-around" align="middle" gutter={24}>
                            <Col span={4} key={1}>
                                <Title level={3}>全部资产列表</Title>
                            </Col>
                            <Col span={20} key={2} style={{textAlign: 'right'}}>
                                <Space>

                                    <Search
                                        ref={this.inputRefOfName}
                                        placeholder="资产名称"
                                        allowClear
                                        onSearch={this.handleSearchByName}
                                        style={{width: 200}}
                                    />

                                    <Search
                                        ref={this.inputRefOfIp}
                                        placeholder="资产IP"
                                        allowClear
                                        onSearch={this.handleSearchByIp}
                                        style={{width: 200}}
                                    />

                                    <Select mode="multiple"
                                            allowClear
                                            placeholder="资产标签" onChange={this.handleTagsChange}
                                            style={{minWidth: 150}}>
                                        {this.state.tags.map(tag => {
                                            if (tag === '-') {
                                                return undefined;
                                            }
                                            return (<Select.Option key={tag}>{tag}</Select.Option>)
                                        })}
                                    </Select>

                                    <Select onChange={this.handleSearchByProtocol}
                                            value={this.state.queryParams.protocol ? this.state.queryParams.protocol : ''}
                                            style={{width: 100}}>
                                        <Select.Option value="">全部协议</Select.Option>
                                        <Select.Option value="rdp">rdp</Select.Option>
                                        <Select.Option value="ssh">ssh</Select.Option>
                                        <Select.Option value="vnc">vnc</Select.Option>
                                        <Select.Option value="telnet">telnet</Select.Option>
                                    </Select>

                                    <Tooltip title='重置查询'>

                                        <Button icon={<UndoOutlined/>} onClick={() => {
                                            this.inputRefOfName.current.setValue('');
                                            this.inputRefOfIp.current.setValue('');
                                            this.loadTableData({
                                                ...this.state.queryParams,
                                                pageIndex: 1,
                                                pageSize: 10,
                                                protocol: ''
                                            })
                                        }}>

                                        </Button>
                                    </Tooltip>

                                    <Divider type="vertical"/>

                                    <Tooltip title="刷新列表">
                                        <Button icon={<SyncOutlined/>} onClick={() => {
                                            this.loadTableData(this.state.queryParams)
                                        }}>

                                        </Button>
                                    </Tooltip>

                                    <Tooltip title="添加授权">
                                        <Button type="primary" disabled={!hasSelected} icon={<PlusOutlined/>}
                                                onClick={async () => {
                                                    let totalSelectedRows = this.state.totalSelectedRows;
                                                    let totalSelectedRowKeys = totalSelectedRows.map(item => item['id']);

                                                    let selectedRows = this.state.selectedRows;
                                                    let newRowKeys = []
                                                    for (let i = 0; i < selectedRows.length; i++) {
                                                        let selectedRow = selectedRows[i];
                                                        if (totalSelectedRowKeys.includes(selectedRow['id'])) {
                                                            continue;
                                                        }
                                                        selectedRow['strategy'] = this.getStrategyByAssetId(this.state.strategies, this.state.sharers, selectedRow['id'], this.state.strategyId);
                                                        totalSelectedRows.push(selectedRow);
                                                        newRowKeys.push(selectedRow['id']);
                                                    }

                                                    let userId = this.state.sharer;
                                                    let userGroupId = this.state.userGroupId;
                                                    let strategyId = this.state.strategyId;
                                                    let result = await request.post(`/resource-sharers/add-resources`, {
                                                        userGroupId: userGroupId,
                                                        userId: userId,
                                                        strategyId: strategyId,
                                                        resourceType: 'asset',
                                                        resourceIds: newRowKeys
                                                    });
                                                    if (result['code'] === 1) {
                                                        message.success('操作成功', 3);
                                                        this.setState({
                                                            totalSelectedRows: totalSelectedRows
                                                        })
                                                        await this.loadTableData();
                                                    } else {
                                                        message.error(result['message'], 10);
                                                    }
                                                }}>
                                        </Button>
                                    </Tooltip>
                                </Space>
                            </Col>
                        </Row>
                    </div>

                    <Table key='assets-table'

                           rowSelection={rowSelection}
                           dataSource={this.state.items}
                           columns={columns}
                           position={'both'}
                           pagination={{
                               showSizeChanger: true,
                               current: this.state.queryParams.pageIndex,
                               pageSize: this.state.queryParams.pageSize,
                               onChange: this.handleChangPage,
                               onShowSizeChange: this.handleChangPage,
                               total: this.state.total,
                               showTotal: total => `总计 ${total} 条`
                           }}
                           loading={this.state.loading}
                    />
                </Content>
            </>
        );
    }
Example #10
Source File: UserGroup.js    From next-terminal with GNU Affero General Public License v3.0 4 votes vote down vote up
render() {

        const columns = [{
            title: '序号',
            dataIndex: 'id',
            key: 'id',
            render: (id, record, index) => {
                return index + 1;
            }
        }, {
            title: '名称',
            dataIndex: 'name',
            sorter: true,
            render: (name, record, index) => {
                return (
                    <Button type="link" size='small'
                            loading={this.state.items[index].updateBtnLoading}
                            onClick={() => this.showModal('更新用户组', record['id'], index)}>{name}</Button>
                );
            }
        }, {
            title: '授权资产',
            dataIndex: 'assetCount',
            key: 'assetCount',
            render: (text, record) => {
                return <Button type='link' onClick={async () => {
                    this.setState({
                        assetVisible: true,
                        userGroupId: record['id']
                    })
                }}>{text}</Button>
            }
        }, {
            title: '创建日期',
            dataIndex: 'created',
            key: 'created',
            render: (text) => {
                return (
                    <Tooltip title={text}>
                        {dayjs(text).fromNow()}
                    </Tooltip>
                )
            },
            sorter: true,
        },
            {
                title: '操作',
                key: 'action',
                render: (text, record, index) => {
                    return (
                        <div>
                            <Button type="link" size='small'
                                    loading={this.state.items[index].updateBtnLoading}
                                    onClick={() => this.showModal('更新用户组', record['id'], index)}>编辑</Button>
                            <Button type="link" size='small'
                                    onClick={() => {
                                        this.setState({
                                            assetVisible: true,
                                            userGroupId: record['id']
                                        })
                                    }}>资产授权</Button>
                            <Button type="link" size='small' danger
                                    onClick={() => this.showDeleteConfirm(record.id, record.name)}>删除</Button>
                        </div>
                    )
                },
            }
        ];

        const selectedRowKeys = this.state.selectedRowKeys;
        const rowSelection = {
            selectedRowKeys: this.state.selectedRowKeys,
            onChange: (selectedRowKeys) => {
                this.setState({selectedRowKeys});
            },
        };
        const hasSelected = selectedRowKeys.length > 0;

        return (
            <>
                <Content className="site-layout-background page-content">
                    <div style={{marginBottom: 20}}>
                        <Row justify="space-around" align="middle" gutter={24}>
                            <Col span={8} key={1}>
                                <Title level={3}>用户组列表</Title>
                            </Col>
                            <Col span={16} key={2} style={{textAlign: 'right'}}>
                                <Space>

                                    <Search
                                        ref={this.inputRefOfName}
                                        placeholder="名称"
                                        allowClear
                                        onSearch={this.handleSearchByName}
                                    />

                                    <Tooltip title='重置查询'>

                                        <Button icon={<UndoOutlined/>} onClick={() => {
                                            this.inputRefOfName.current.setValue('');
                                            this.loadTableData({pageIndex: 1, pageSize: 10})
                                        }}>

                                        </Button>
                                    </Tooltip>

                                    <Divider type="vertical"/>

                                    <Tooltip title="新增">
                                        <Button type="dashed" icon={<PlusOutlined/>}
                                                onClick={() => this.showModal('新增用户组')}>

                                        </Button>
                                    </Tooltip>

                                    <Tooltip title="刷新列表">
                                        <Button icon={<SyncOutlined/>} onClick={() => {
                                            this.loadTableData(this.state.queryParams)
                                        }}>

                                        </Button>
                                    </Tooltip>

                                    <Tooltip title="批量删除">
                                        <Button type="primary" danger disabled={!hasSelected} icon={<DeleteOutlined/>}
                                                loading={this.state.delBtnLoading}
                                                onClick={() => {
                                                    const content = <div>
                                                        您确定要删除选中的<Text style={{color: '#1890FF'}}
                                                                       strong>{this.state.selectedRowKeys.length}</Text>条记录吗?
                                                    </div>;
                                                    confirm({
                                                        icon: <ExclamationCircleOutlined/>,
                                                        content: content,
                                                        onOk: () => {
                                                            this.batchDelete()
                                                        },
                                                        onCancel() {

                                                        },
                                                    });
                                                }}>

                                        </Button>
                                    </Tooltip>

                                </Space>
                            </Col>
                        </Row>
                    </div>

                    <Table rowSelection={rowSelection}
                           rowKey='id'
                           dataSource={this.state.items}
                           columns={columns}
                           position={'both'}
                           pagination={{
                               showSizeChanger: true,
                               current: this.state.queryParams.pageIndex,
                               pageSize: this.state.queryParams.pageSize,
                               onChange: this.handleChangPage,
                               onShowSizeChange: this.handleChangPage,
                               total: this.state.total,
                               showTotal: total => `总计 ${total} 条`
                           }}
                           loading={this.state.loading}
                           onChange={this.handleTableChange}
                    />

                    {/* 为了屏蔽ant modal 关闭后数据仍然遗留的问题*/}
                    {this.state.modalVisible ?
                        <UserGroupModal
                            visible={this.state.modalVisible}
                            title={this.state.modalTitle}
                            handleOk={this.handleOk}
                            handleCancel={this.handleCancelModal}
                            confirmLoading={this.state.modalConfirmLoading}
                            model={this.state.model}
                            users={this.state.users}
                        >
                        </UserGroupModal> : undefined
                    }

                    <Drawer
                        title="资产授权"
                        placement="right"
                        closable={true}
                        destroyOnClose={true}
                        onClose={() => {
                            this.loadTableData(this.state.queryParams);
                            this.setState({
                                assetVisible: false
                            })
                        }}
                        visible={this.state.assetVisible}
                        width={window.innerWidth * 0.8}
                    >
                        <UserShareSelectedAsset
                            userGroupId={this.state.userGroupId}
                        >
                        </UserShareSelectedAsset>
                    </Drawer>

                </Content>
            </>
        );
    }
Example #11
Source File: User.js    From next-terminal with GNU Affero General Public License v3.0 4 votes vote down vote up
render() {

        const columns = [{
            title: '序号',
            dataIndex: 'id',
            key: 'id',
            render: (id, record, index) => {
                return index + 1;
            }
        }, {
            title: '登录账号',
            dataIndex: 'username',
            key: 'username',
            sorter: true,
            render: (username, record) => {
                return (
                    <Button type="link" size='small'
                            onClick={async () => {
                                let result = await request.get(`/users/${record['id']}`);
                                if (result['code'] !== 1) {
                                    message.error(result['message']);
                                    return;
                                }
                                this.showModal('更新用户', result['data']);
                            }}>{username}</Button>
                );
            }
        }, {
            title: '用户昵称',
            dataIndex: 'nickname',
            key: 'nickname',
            sorter: true,
        }, {
            title: '用户类型',
            dataIndex: 'type',
            key: 'type',
            render: (text) => {

                if (text === 'user') {
                    return (
                        <Tag>普通用户</Tag>
                    );
                } else if (text === 'admin') {
                    return (
                        <Tag color="blue">管理用户</Tag>
                    );
                } else {
                    return text;
                }
            }
        }, {
            title: '邮箱',
            dataIndex: 'mail',
            key: 'mail',
        }, {
            title: '状态',
            dataIndex: 'status',
            key: 'status',
            render: (status, record, index) => {
                return <Switch checkedChildren="启用" unCheckedChildren="停用"
                               disabled={getCurrentUser()['id'] === record['id']}
                               loading={record['statusLoading']}
                               checked={status !== 'disabled'}
                               onChange={checked => {
                                   this.changeUserStatus(record['id'], checked, index);
                               }}/>
            }
        }, {
            title: '双因素认证',
            dataIndex: 'totpSecret',
            key: 'totpSecret',
            render: (text) => {

                if (text === '1') {
                    return <Tag icon={<InsuranceOutlined/>} color="success">已开启</Tag>;
                } else {
                    return <Tag icon={<FrownOutlined />} color="warning">未开启</Tag>;
                }
            }
        }, {
            title: '在线状态',
            dataIndex: 'online',
            key: 'online',
            render: text => {
                if (text) {
                    return (<Badge status="success" text="在线"/>);
                } else {
                    return (<Badge status="default" text="离线"/>);
                }
            }
        }, {
            title: '授权资产',
            dataIndex: 'sharerAssetCount',
            key: 'sharerAssetCount',
            render: (text, record) => {
                return <Button type='link' onClick={async () => {
                    this.setState({
                        assetVisible: true,
                        sharer: record['id']
                    })
                }}>{text}</Button>
            }
        }, {
            title: '创建日期',
            dataIndex: 'created',
            key: 'created',
            render: (text) => {
                return (
                    <Tooltip title={text}>
                        {dayjs(text).fromNow()}
                    </Tooltip>
                )
            },
            sorter: true,
        }, {
            title: '来源',
            dataIndex: 'source',
            key: 'source',
            render: (text) => {
                if (text === 'ldap') {
                    return (
                        <Tag color="gold">域同步</Tag>
                    );
                }
            }
        },
            {
                title: '操作',
                key: 'action',
                render: (text, record, index) => {

                    const menu = (
                        <Menu>
                            <Menu.Item key="1">
                                <Button type="text" size='small'
                                        disabled={record['source'] === 'ldap'}
                                        onClick={() => {
                                            this.setState({
                                                changePasswordVisible: true,
                                                selectedRow: record
                                            })
                                        }}>修改密码</Button>
                            </Menu.Item>

                            <Menu.Item key="2">
                                <Button type="text" size='small'
                                        loading={record['resetTOTPLoading']}
                                        onClick={() => {
                                            confirm({
                                                title: '您确定要重置此用户的双因素认证吗?',
                                                content: record['name'],
                                                okText: '确定',
                                                cancelText: '取消',
                                                onOk: async () => {
                                                    this.resetTOTP(record['id'], index);
                                                }
                                            });
                                        }}>重置双因素认证</Button>
                            </Menu.Item>

                            <Menu.Item key="3">
                                <Button type="text" size='small'
                                        onClick={() => {
                                            this.setState({
                                                assetVisible: true,
                                                sharer: record['id']
                                            })
                                        }}>资产授权</Button>
                            </Menu.Item>

                            <Menu.Divider/>
                            <Menu.Item key="5">
                                <Button type="text" size='small' danger
                                        disabled={getCurrentUser()['id'] === record['id']}
                                        loading={record['delLoading']}
                                        onClick={() => this.showDeleteConfirm(record.id, record.name, index)}>删除</Button>
                            </Menu.Item>
                        </Menu>
                    );

                    return (
                        <div>
                            <Button type="link" size='small'
                                    disabled={getCurrentUser()['id'] === record['id']}
                                    onClick={async () => {
                                        let result = await request.get(`/users/${record['id']}`);
                                        if (result['code'] !== 1) {
                                            message.error(result['message']);
                                            return;
                                        }
                                        this.showModal('更新用户', result['data']);
                                    }}>编辑</Button>
                            <Dropdown overlay={menu}>
                                <Button type="link" size='small'>
                                    更多 <DownOutlined/>
                                </Button>
                            </Dropdown>
                        </div>
                    )
                },
            }
        ];

        const selectedRowKeys = this.state.selectedRowKeys;
        const rowSelection = {
            selectedRowKeys: this.state.selectedRowKeys,
            onChange: (selectedRowKeys) => {
                this.setState({selectedRowKeys});
            },
        };
        const hasSelected = selectedRowKeys.length > 0;

        return (
            <>
                <Content className="site-layout-background page-content">
                    <div style={{marginBottom: 20}}>
                        <Row justify="space-around" align="middle" gutter={24}>
                            <Col span={8} key={1}>
                                <Title level={3}>用户列表</Title>
                            </Col>
                            <Col span={16} key={2} style={{textAlign: 'right'}}>
                                <Space>

                                    <Search
                                        ref={this.inputRefOfNickname}
                                        placeholder="用户昵称"
                                        allowClear
                                        onSearch={this.handleSearchByNickname}
                                    />

                                    <Search
                                        ref={this.inputRefOfUsername}
                                        placeholder="登录账号"
                                        allowClear
                                        onSearch={this.handleSearchByUsername}
                                    />

                                    <Search
                                        ref={this.inputRefOfMail}
                                        placeholder="邮箱"
                                        allowClear
                                        onSearch={this.handleSearchByMail}
                                    />

                                    <Tooltip title='重置查询'>

                                        <Button icon={<UndoOutlined/>} onClick={() => {
                                            this.inputRefOfUsername.current.setValue('');
                                            this.inputRefOfNickname.current.setValue('');
                                            this.inputRefOfMail.current.setValue('');
                                            this.loadTableData({pageIndex: 1, pageSize: 10})
                                        }}>

                                        </Button>
                                    </Tooltip>

                                    <Divider type="vertical"/>

                                    <Tooltip title="新增">
                                        <Button type="dashed" icon={<PlusOutlined/>}
                                                onClick={() => this.showModal('新增用户', {})}>

                                        </Button>
                                    </Tooltip>

                                    <Tooltip title="刷新列表">
                                        <Button icon={<SyncOutlined/>} onClick={() => {
                                            this.loadTableData(this.state.queryParams)
                                        }}>

                                        </Button>
                                    </Tooltip>

                                    <Tooltip title="批量删除">
                                        <Button type="primary" danger disabled={!hasSelected} icon={<DeleteOutlined/>}
                                                loading={this.state.delBtnLoading}
                                                onClick={() => {
                                                    const content = <div>
                                                        您确定要删除选中的<Text style={{color: '#1890FF'}}
                                                                       strong>{this.state.selectedRowKeys.length}</Text>条记录吗?
                                                    </div>;
                                                    confirm({
                                                        icon: <ExclamationCircleOutlined/>,
                                                        content: content,
                                                        onOk: () => {
                                                            this.batchDelete()
                                                        },
                                                        onCancel() {

                                                        },
                                                    });
                                                }}>

                                        </Button>
                                    </Tooltip>

                                </Space>
                            </Col>
                        </Row>
                    </div>

                    <Table rowSelection={rowSelection}
                           rowKey='id'
                           dataSource={this.state.items}
                           columns={columns}
                           position={'both'}
                           pagination={{
                               showSizeChanger: true,
                               current: this.state.queryParams.pageIndex,
                               pageSize: this.state.queryParams.pageSize,
                               onChange: this.handleChangPage,
                               onShowSizeChange: this.handleChangPage,
                               total: this.state.total,
                               showTotal: total => `总计 ${total} 条`
                           }}
                           loading={this.state.loading}
                           onChange={this.handleTableChange}
                    />

                    {/* 为了屏蔽ant modal 关闭后数据仍然遗留的问题*/}
                    {
                        this.state.modalVisible ?
                            <UserModal
                                visible={this.state.modalVisible}
                                title={this.state.modalTitle}
                                handleOk={this.handleOk}
                                handleCancel={this.handleCancelModal}
                                confirmLoading={this.state.modalConfirmLoading}
                                model={this.state.model}
                            >
                            </UserModal> : undefined
                    }

                    <Drawer
                        title="资产授权"
                        placement="right"
                        closable={true}
                        destroyOnClose={true}
                        onClose={() => {
                            this.loadTableData(this.state.queryParams);
                            this.setState({
                                assetVisible: false
                            })
                        }}
                        visible={this.state.assetVisible}
                        width={window.innerWidth * 0.8}
                    >
                        <UserShareSelectedAsset
                            sharer={this.state.sharer}
                            userGroupId={undefined}
                        >
                        </UserShareSelectedAsset>
                    </Drawer>

                    {
                        this.state.changePasswordVisible ?
                            <Modal title="修改密码" visible={this.state.changePasswordVisible}
                                   confirmLoading={this.state.changePasswordConfirmLoading}
                                   maskClosable={false}
                                   onOk={() => {
                                       this.changePasswordFormRef.current
                                           .validateFields()
                                           .then(values => {
                                               this.changePasswordFormRef.current.resetFields();
                                               this.handleChangePassword(values);
                                           });
                                   }}
                                   onCancel={() => {
                                       this.setState({
                                           changePasswordVisible: false
                                       })
                                   }}>

                                <Form ref={this.changePasswordFormRef}>

                                    <Form.Item name='password' rules={[{required: true, message: '请输入新密码'}]}>
                                        <Input prefix={<LockOutlined/>} placeholder="请输入新密码"/>
                                    </Form.Item>
                                </Form>
                            </Modal> : undefined
                    }

                </Content>
            </>
        );
    }
Example #12
Source File: Strategy.js    From next-terminal with GNU Affero General Public License v3.0 4 votes vote down vote up
render() {

        const renderStatus = (text) => {
            if (text === '1') {
                return <Tag color={'green'}>开启</Tag>
            } else {
                return <Tag color={'red'}>关闭</Tag>
            }
        }

        const columns = [{
            title: '序号',
            dataIndex: 'id',
            key: 'id',
            render: (id, record, index) => {
                return index + 1;
            }
        }, {
            title: '名称',
            dataIndex: 'name',
            key: 'name',
            sorter: true,
        }, {
            title: '上传',
            dataIndex: 'upload',
            key: 'upload',
            render: (text) => {
                return renderStatus(text);
            }
        }, {
            title: '下载',
            dataIndex: 'download',
            key: 'download',
            render: (text) => {
                return renderStatus(text);
            }
        }, {
            title: '编辑',
            dataIndex: 'edit',
            key: 'edit',
            render: (text) => {
                return renderStatus(text);
            }
        }, {
            title: '删除',
            dataIndex: 'delete',
            key: 'delete',
            render: (text) => {
                return renderStatus(text);
            }
        }, {
            title: '重命名',
            dataIndex: 'rename',
            key: 'rename',
            render: (text) => {
                return renderStatus(text);
            }
        }, {
            title: '复制',
            dataIndex: 'copy',
            key: 'copy',
            render: (text) => {
                return renderStatus(text);
            }
        }, {
            title: '粘贴',
            dataIndex: 'paste',
            key: 'paste',
            render: (text) => {
                return renderStatus(text);
            }
        }, {
            title: '创建时间',
            dataIndex: 'created',
            key: 'created',
        }, {
            title: '操作',
            key: 'action',
            render: (text, record, index) => {

                return (
                    <div>
                        <Button type="link" size='small' loading={this.state.items[index]['execLoading']}
                                onClick={() => this.showModal('更新授权策略', record)}>编辑</Button>

                        <Button type="text" size='small' danger
                                onClick={() => this.showDeleteConfirm(record.id, record.name)}>删除</Button>

                    </div>
                )
            },
        }
        ];

        const selectedRowKeys = this.state.selectedRowKeys;
        const rowSelection = {
            selectedRowKeys: this.state.selectedRowKeys,
            onChange: (selectedRowKeys, selectedRows) => {
                this.setState({selectedRowKeys});
            },
        };
        const hasSelected = selectedRowKeys.length > 0;

        return (
            <>
                <Content className="site-layout-background page-content">

                    <div style={{marginBottom: 20}}>
                        <Row justify="space-around" align="middle" gutter={24}>
                            <Col span={12} key={1}>
                                <Title level={3}>授权策略</Title>
                            </Col>
                            <Col span={12} key={2} style={{textAlign: 'right'}}>
                                <Space>
                                    <Search
                                        ref={this.inputRefOfName}
                                        placeholder="名称"
                                        allowClear
                                        onSearch={this.handleSearchByName}
                                    />

                                    <Tooltip title='重置查询'>

                                        <Button icon={<UndoOutlined/>} onClick={() => {
                                            this.inputRefOfName.current.setValue('');
                                            this.loadTableData({pageIndex: 1, pageSize: 10, name: '', content: ''})
                                        }}>

                                        </Button>
                                    </Tooltip>

                                    <Divider type="vertical"/>

                                    <Tooltip title="新增">
                                        <Button type="dashed" icon={<PlusOutlined/>}
                                                onClick={() => this.showModal('新增授权策略')}>

                                        </Button>
                                    </Tooltip>


                                    <Tooltip title="刷新列表">
                                        <Button icon={<SyncOutlined/>} onClick={() => {
                                            this.loadTableData(this.state.queryParams)
                                        }}>

                                        </Button>
                                    </Tooltip>


                                    <Tooltip title="批量删除">
                                        <Button type="primary" danger disabled={!hasSelected} icon={<DeleteOutlined/>}
                                                loading={this.state.delBtnLoading}
                                                onClick={() => {
                                                    const content = <div>
                                                        您确定要删除选中的<Text style={{color: '#1890FF'}}
                                                                       strong>{this.state.selectedRowKeys.length}</Text>条记录吗?
                                                    </div>;
                                                    confirm({
                                                        icon: <ExclamationCircleOutlined/>,
                                                        content: content,
                                                        onOk: () => {
                                                            this.batchDelete()
                                                        },
                                                        onCancel() {

                                                        },
                                                    });
                                                }}>

                                        </Button>
                                    </Tooltip>

                                </Space>
                            </Col>
                        </Row>
                    </div>

                    <Table
                        rowSelection={rowSelection}
                        dataSource={this.state.items}
                        columns={columns}
                        position={'both'}
                        pagination={{
                            showSizeChanger: true,
                            current: this.state.queryParams.pageIndex,
                            pageSize: this.state.queryParams.pageSize,
                            onChange: this.handleChangPage,
                            onShowSizeChange: this.handleChangPage,
                            total: this.state.total,
                            showTotal: total => `总计 ${total} 条`
                        }}
                        loading={this.state.loading}
                        onChange={this.handleTableChange}
                    />

                    {
                        this.state.modalVisible ?
                            <StrategyModal
                                visible={this.state.modalVisible}
                                title={this.state.modalTitle}
                                handleOk={this.handleOk}
                                handleCancel={this.handleCancelModal}
                                confirmLoading={this.state.modalConfirmLoading}
                                model={this.state.model}
                            >
                            </StrategyModal> : undefined
                    }
                </Content>
            </>
        );
    }
Example #13
Source File: OnlineSession.js    From next-terminal with GNU Affero General Public License v3.0 4 votes vote down vote up
render() {

        const columns = [{
            title: '序号',
            dataIndex: 'id',
            key: 'id',
            render: (id, record, index) => {
                return index + 1;
            }
        }, {
            title: '来源IP',
            dataIndex: 'clientIp',
            key: 'clientIp'
        }, {
            title: '接入方式',
            dataIndex: 'mode',
            key: 'mode',
            render: (text) => {
                return (
                    <Tag color={MODE_COLORS[text]}>{text}</Tag>
                )
            }
        }, {
            title: '用户昵称',
            dataIndex: 'creatorName',
            key: 'creatorName'
        }, {
            title: '资产名称',
            dataIndex: 'assetName',
            key: 'assetName'
        }, {
            title: '连接协议',
            dataIndex: 'protocol',
            key: 'protocol',
            render: (text, record) => {
                const title = `${record.username}@${record.ip}:${record.port}`;
                return (
                    <Tooltip title={title}>
                        <Tag color={PROTOCOL_COLORS[text]}>{text}</Tag>
                    </Tooltip>
                )
            }
        }, {
            title: '接入时间',
            dataIndex: 'connectedTime',
            key: 'connectedTime',
            render: (text, record) => {
                return (
                    <Tooltip title={text}>
                        {dayjs(text).fromNow()}
                    </Tooltip>
                )
            }
        }, {
            title: '接入时长',
            dataIndex: 'connectedTime',
            key: 'connectedTime',
            render: (text, record) => {
                return differTime(new Date(record['connectedTime']), new Date());
            }
        },
            {
                title: '操作',
                key: 'action',
                render: (text, record) => {

                    return (
                        <div>
                            <Button type="link" size='small' onClick={() => {
                                this.showMonitor(record)
                            }}>监控</Button>
                            <Button type="link" size='small' onClick={async () => {

                                confirm({
                                    title: '您确定要断开此会话吗?',
                                    content: '',
                                    okText: '确定',
                                    okType: 'danger',
                                    cancelText: '取消',
                                    onOk() {
                                        dis(record.id)
                                    }
                                });

                                const dis = async (id) => {
                                    const result = await request.post(`/sessions/${id}/disconnect`);
                                    if (result.code === 1) {
                                        notification['success']({
                                            message: '提示',
                                            description: '断开成功',
                                        });
                                        this.loadTableData();
                                    } else {
                                        notification['success']({
                                            message: '提示',
                                            description: result.message,
                                        });
                                    }
                                }

                            }}>断开</Button>
                        </div>
                    )
                },
            }
        ];

        const selectedRowKeys = this.state.selectedRowKeys;
        const rowSelection = {
            selectedRowKeys: selectedRowKeys,
            onChange: (selectedRowKeys, selectedRows) => {
                this.setState({selectedRowKeys});
            },
        };
        const hasSelected = selectedRowKeys.length > 0;

        const userOptions = this.state.users.map(d => <Select.Option key={d.id}
                                                                     value={d.id}>{d.nickname}</Select.Option>);
        const assetOptions = this.state.assets.map(d => <Select.Option key={d.id}
                                                                       value={d.id}>{d.name}</Select.Option>);

        return (
            <>
                <Content className="site-layout-background page-content">

                    <div style={{marginBottom: 20}}>
                        <Row justify="space-around" align="middle" gutter={24}>
                            <Col span={8} key={1}>
                                <Title level={3}>在线会话列表</Title>
                            </Col>
                            <Col span={16} key={2} style={{textAlign: 'right'}}>
                                <Space>

                                    <Search
                                        ref={this.inputRefOfClientIp}
                                        placeholder="来源IP"
                                        allowClear
                                        onSearch={this.handleSearchByClientIp}
                                    />

                                    <Select
                                        style={{width: 150}}
                                        showSearch
                                        value={this.state.queryParams.userId}
                                        placeholder='用户昵称'
                                        onSearch={this.handleSearchByNickname}
                                        onChange={this.handleChangeByUserId}
                                        filterOption={false}
                                        allowClear
                                    >
                                        {userOptions}
                                    </Select>

                                    <Select
                                        style={{width: 150}}
                                        showSearch
                                        value={this.state.queryParams.assetId}
                                        placeholder='资产名称'
                                        onSearch={this.handleSearchByAssetName}
                                        onChange={this.handleChangeByAssetId}
                                        filterOption={false}
                                    >
                                        {assetOptions}
                                    </Select>

                                    <Select onChange={this.handleChangeByProtocol}
                                            value={this.state.queryParams.protocol ? this.state.queryParams.protocol : ''}
                                            style={{width: 100}}>
                                        <Select.Option value="">全部协议</Select.Option>
                                        <Select.Option value="rdp">rdp</Select.Option>
                                        <Select.Option value="ssh">ssh</Select.Option>
                                        <Select.Option value="vnc">vnc</Select.Option>
                                        <Select.Option value="telnet">telnet</Select.Option>
                                        <Select.Option value="kubernetes">kubernetes</Select.Option>
                                    </Select>

                                    <Tooltip title='重置查询'>

                                        <Button icon={<UndoOutlined/>} onClick={() => {
                                            this.inputRefOfClientIp.current.setValue('');
                                            this.loadTableData({
                                                pageIndex: 1,
                                                pageSize: 10,
                                                protocol: '',
                                                userId: undefined,
                                                assetId: undefined
                                            })
                                        }}>

                                        </Button>
                                    </Tooltip>

                                    <Divider type="vertical"/>

                                    <Tooltip title="刷新列表">
                                        <Button icon={<SyncOutlined/>} onClick={() => {
                                            this.loadTableData(this.state.queryParams)
                                        }}>

                                        </Button>
                                    </Tooltip>

                                    <Tooltip title="批量断开">
                                        <Button type="primary" danger disabled={!hasSelected}
                                                icon={<DisconnectOutlined/>}
                                                loading={this.state.delBtnLoading}
                                                onClick={() => {
                                                    const content = <div>
                                                        您确定要断开选中的<Text style={{color: '#1890FF'}}
                                                                       strong>{this.state.selectedRowKeys.length}</Text>个会话吗?
                                                    </div>;
                                                    confirm({
                                                        icon: <ExclamationCircleOutlined/>,
                                                        content: content,
                                                        onOk: () => {
                                                            this.batchDis()
                                                        },
                                                        onCancel() {

                                                        },
                                                    });
                                                }}>

                                        </Button>
                                    </Tooltip>

                                </Space>
                            </Col>
                        </Row>
                    </div>

                    <Table rowSelection={rowSelection}
                           dataSource={this.state.items}
                           columns={columns}
                           position={'both'}
                           pagination={{
                               showSizeChanger: true,
                               current: this.state.queryParams.pageIndex,
                               pageSize: this.state.queryParams.pageSize,
                               onChange: this.handleChangPage,
                               total: this.state.total,
                               showTotal: total => `总计 ${total} 条`
                           }}
                           loading={this.state.loading}
                    />

                    {
                        this.state.accessVisible ?
                            <Modal
                                className='modal-no-padding'
                                title={this.state.sessionTitle}

                                maskClosable={false}
                                visible={this.state.accessVisible}
                                footer={null}
                                width={window.innerWidth * 0.8}
                                height={window.innerWidth * 0.8 / this.state.sessionWidth * this.state.sessionHeight}
                                onCancel={() => {
                                    message.destroy();
                                    this.setState({accessVisible: false})
                                }}
                            >
                                {
                                    this.state.sessionMode === 'guacd' ?
                                        <AccessMonitor sessionId={this.state.sessionId}
                                                       width={this.state.sessionWidth}
                                                       height={this.state.sessionHeight}
                                                       protocol={this.state.sessionProtocol}
                                                       rate={window.innerWidth * 0.8 / this.state.sessionWidth}>

                                        </AccessMonitor> :
                                        <TermMonitor sessionId={this.state.sessionId}
                                                     width={this.state.sessionWidth}
                                                     height={this.state.sessionHeight}>

                                        </TermMonitor>
                                }


                            </Modal> : undefined
                    }

                </Content>
            </>
        );
    }
Example #14
Source File: OfflineSession.js    From next-terminal with GNU Affero General Public License v3.0 4 votes vote down vote up
render() {

        const columns = [{
            title: '序号',
            dataIndex: 'id',
            key: 'id',
            render: (id, record, index) => {
                return index + 1;
            },
        }, {
            title: '来源IP',
            dataIndex: 'clientIp',
            key: 'clientIp'
        }, {
            title: '接入方式',
            dataIndex: 'mode',
            key: 'mode',
            render: (text) => {
                return (
                    <Tag color={MODE_COLORS[text]}>{text}</Tag>
                )
            }
        }, {
            title: '用户昵称',
            dataIndex: 'creatorName',
            key: 'creatorName'
        }, {
            title: '资产名称',
            dataIndex: 'assetName',
            key: 'assetName'
        }, {
            title: '连接协议',
            dataIndex: 'protocol',
            key: 'protocol',
            render: (text, record) => {
                const title = `${record.username}@${record.ip}:${record.port}`;
                return (
                    <Tooltip title={title}>
                        <Tag color={PROTOCOL_COLORS[text]}>{text}</Tag>
                    </Tooltip>
                )
            }
        }, {
            title: '接入时间',
            dataIndex: 'connectedTime',
            key: 'connectedTime',
            render: (text, record) => {
                return (
                    <Tooltip title={text}>
                        {dayjs(text).fromNow()}
                    </Tooltip>
                )
            }
        }, {
            title: '接入时长',
            dataIndex: 'connectedTime',
            key: 'connectedTime',
            render: (text, record) => {
                return differTime(new Date(record['connectedTime']), new Date(record['disconnectedTime']));
            }
        },
            {
                title: '操作',
                key: 'action',
                render: (text, record) => {
                    let disabled = true;
                    if (record['recording'] && record['recording'] === '1') {
                        disabled = false
                    }

                    return (
                        <div>
                            <Button type="link" size='small'
                                    disabled={disabled}
                                    onClick={() => this.showPlayback(record)}>回放</Button>
                            <Button type="link" size='small'
                                    onClick={() => {
                                        confirm({
                                            title: '您确定要禁止该IP访问本系统吗?',
                                            content: '',
                                            okText: '确定',
                                            okType: 'danger',
                                            cancelText: '取消',
                                            onOk: async () => {
                                                // 向后台提交数据
                                                let formData = {
                                                    ip: record['clientIp'],
                                                    rule: 'reject',
                                                    priority: 99,
                                                }
                                                const result = await request.post('/securities', formData);
                                                if (result.code === 1) {
                                                    message.success('禁用成功');
                                                } else {
                                                    message.error(result.message, 10);
                                                }
                                            }
                                        });
                                    }}>禁用IP</Button>
                            <Button type="link" size='small' danger onClick={() => {
                                confirm({
                                    title: '您确定要删除此会话吗?',
                                    content: '',
                                    okText: '确定',
                                    okType: 'danger',
                                    cancelText: '取消',
                                    onOk: () => {
                                        this.del(record.id)
                                    }
                                });
                            }}>删除</Button>
                        </div>
                    )
                },
            }
        ];

        const selectedRowKeys = this.state.selectedRowKeys;
        const rowSelection = {
            selectedRowKeys: this.state.selectedRowKeys,
            onChange: (selectedRowKeys, selectedRows) => {
                this.setState({selectedRowKeys});
            },
        };
        const hasSelected = selectedRowKeys.length > 0;

        const userOptions = this.state.users.map(d => <Select.Option key={d.id}
                                                                     value={d.id}>{d.nickname}</Select.Option>);
        const assetOptions = this.state.assets.map(d => <Select.Option key={d.id}
                                                                       value={d.id}>{d.name}</Select.Option>);

        return (
            <>
                <Content className="site-layout-background page-content">
                    <div style={{marginBottom: 20}}>
                        <Row justify="space-around" align="middle" gutter={24}>
                            <Col span={4} key={1}>
                                <Title level={3}>离线会话列表</Title>
                            </Col>
                            <Col span={20} key={2} style={{textAlign: 'right'}}>
                                <Space>

                                    <Search
                                        ref={this.inputRefOfClientIp}
                                        placeholder="来源IP"
                                        allowClear
                                        onSearch={this.handleSearchByClientIp}
                                    />

                                    <Select
                                        style={{width: 140}}
                                        showSearch
                                        value={this.state.queryParams.userId}
                                        placeholder='用户昵称'
                                        onSearch={this.handleSearchByNickname}
                                        onChange={this.handleChangeByUserId}
                                        filterOption={false}
                                        allowClear
                                    >
                                        {userOptions}
                                    </Select>

                                    <Select
                                        style={{width: 140}}
                                        showSearch
                                        value={this.state.queryParams.assetId}
                                        placeholder='资产名称'
                                        onSearch={this.handleSearchByAssetName}
                                        onChange={this.handleChangeByAssetId}
                                        filterOption={false}
                                    >
                                        {assetOptions}
                                    </Select>

                                    <Select onChange={this.handleChangeByRead}
                                            value={this.state.queryParams.reviewed ? this.state.queryParams.reviewed : ''}
                                            style={{width: 100}}>
                                        <Select.Option value="">全部会话</Select.Option>
                                        <Select.Option value="true">只看已读</Select.Option>
                                        <Select.Option value="false">只看未读</Select.Option>
                                    </Select>

                                    <Select onChange={this.handleChangeByProtocol}
                                            value={this.state.queryParams.protocol ? this.state.queryParams.protocol : ''}
                                            style={{width: 100}}>
                                        <Select.Option value="">全部协议</Select.Option>
                                        <Select.Option value="rdp">rdp</Select.Option>
                                        <Select.Option value="ssh">ssh</Select.Option>
                                        <Select.Option value="vnc">vnc</Select.Option>
                                        <Select.Option value="telnet">telnet</Select.Option>
                                        <Select.Option value="kubernetes">kubernetes</Select.Option>
                                    </Select>

                                    <Tooltip title='重置查询'>

                                        <Button icon={<UndoOutlined/>} onClick={() => {
                                            this.inputRefOfClientIp.current.setValue('');
                                            this.loadTableData({
                                                pageIndex: 1,
                                                pageSize: 10,
                                                protocol: ''
                                            })
                                        }}>

                                        </Button>
                                    </Tooltip>

                                    <Divider type="vertical"/>

                                    <Tooltip title="刷新列表">
                                        <Button icon={<SyncOutlined/>} onClick={() => {
                                            this.loadTableData(this.state.queryParams)
                                        }}>

                                        </Button>
                                    </Tooltip>

                                    <Tooltip title="全部标为已阅">
                                        <Button icon={<CheckOutlined />}
                                                loading={this.state.reviewedAllBtnLoading}
                                                onClick={this.handleAllReviewed}>
                                        </Button>
                                    </Tooltip>

                                    <Tooltip title="标为已阅">
                                        <Button disabled={!hasSelected} icon={<EyeOutlined />}
                                                loading={this.state.reviewedBtnLoading}
                                                onClick={this.handleReviewed}>

                                        </Button>
                                    </Tooltip>

                                    <Tooltip title="标为未阅">
                                        <Button disabled={!hasSelected} icon={<EyeInvisibleOutlined />}
                                                loading={this.state.unreviewedBtnLoading}
                                                onClick={this.handleUnreviewed}>

                                        </Button>
                                    </Tooltip>

                                    <Tooltip title="批量删除">
                                        <Button type="primary" danger disabled={!hasSelected} icon={<DeleteOutlined/>}
                                                loading={this.state.delBtnLoading}
                                                onClick={() => {
                                                    const content = <div>
                                                        您确定要删除选中的<Text style={{color: '#1890FF'}}
                                                                       strong>{this.state.selectedRowKeys.length}</Text>条记录吗?
                                                    </div>;
                                                    confirm({
                                                        icon: <ExclamationCircleOutlined/>,
                                                        content: content,
                                                        onOk: () => {
                                                            this.batchDelete()
                                                        },
                                                        onCancel() {

                                                        },
                                                    });
                                                }}>
                                        </Button>
                                    </Tooltip>

                                    <Tooltip title="清空">
                                        <Button type="primary" danger icon={<ClearOutlined/>}
                                                loading={this.state.clearBtnLoading}
                                                onClick={() => {
                                                    const content = <Text style={{color: 'red'}}
                                                                          strong>您确定要清空全部的离线会话吗?</Text>;
                                                    confirm({
                                                        icon: <ExclamationCircleOutlined/>,
                                                        content: content,
                                                        okType: 'danger',
                                                        onOk: this.clearSession,
                                                        onCancel() {

                                                        },
                                                    });
                                                }}>

                                        </Button>
                                    </Tooltip>

                                </Space>
                            </Col>
                        </Row>
                    </div>

                    <Table rowSelection={rowSelection}
                           dataSource={this.state.items}
                           columns={columns}
                           position={'both'}
                           pagination={{
                               showSizeChanger: true,
                               current: this.state.queryParams.pageIndex,
                               pageSize: this.state.queryParams.pageSize,
                               onChange: this.handleChangPage,
                               total: this.state.total,
                               showTotal: total => `总计 ${total} 条`
                           }}
                           loading={this.state.loading}
                           rowClassName={(record, index) => {
                               return record['reviewed'] ? '' : 'unreviewed';
                           }}
                    />

                    {
                        this.state.playbackVisible ?
                            <Modal
                                className='modal-no-padding'
                                title={`会话回放 来源IP:${this.state.selectedRow['clientIp']} 用户昵称:${this.state.selectedRow['creatorName']} 资产名称:${this.state.selectedRow['assetName']} 网络:${this.state.selectedRow['username']}@${this.state.selectedRow['ip']}:${this.state.selectedRow['port']}`}
                                centered={true}
                                visible={this.state.playbackVisible}
                                onCancel={this.hidePlayback}
                                width={window.innerWidth * 0.8}
                                footer={null}
                                destroyOnClose
                                maskClosable={false}
                            >
                                {
                                    this.state.selectedRow['mode'] === 'native' || this.state.selectedRow['mode'] === 'terminal' ?
                                        <iframe
                                            title='recording'
                                            style={{
                                                width: '100%',
                                                // height: this.state.iFrameHeight,
                                                overflow: 'visible'
                                            }}
                                            onLoad={() => {
                                                // constant obj = ReactDOM.findDOMNode(this);
                                                // this.setState({
                                                //     "iFrameHeight": obj.contentWindow.document.body.scrollHeight + 'px'
                                                // });
                                            }}
                                            ref="iframe"
                                            src={'./asciinema.html?sessionId=' + this.state.selectedRow['id']}
                                            width="100%"
                                            height={window.innerHeight * 0.8}
                                            frameBorder="0"
                                        />
                                        : <Playback sessionId={this.state.selectedRow['id']}/>
                                }

                            </Modal> : undefined
                    }

                </Content>
            </>
        );
    }
Example #15
Source File: Storage.js    From next-terminal with GNU Affero General Public License v3.0 4 votes vote down vote up
render() {

        return (
            <div>
                <Content className="site-layout-background page-content">
                    <div>
                        <Row justify="space-around" align="middle" gutter={24}>
                            <Col span={12} key={1}>
                                <Title level={3}>磁盘空间</Title>
                            </Col>
                            <Col span={12} key={2} style={{textAlign: 'right'}}>
                                <Space>
                                    <Search
                                        ref={this.inputRefOfName}
                                        placeholder="名称"
                                        allowClear
                                        onSearch={this.handleSearchByName}
                                    />

                                    <Tooltip title='重置查询'>

                                        <Button icon={<UndoOutlined/>} onClick={() => {
                                            this.inputRefOfName.current.setValue('');
                                            this.loadTableData({pageIndex: 1, pageSize: 10, name: '', content: ''})
                                        }}>

                                        </Button>
                                    </Tooltip>

                                    <Divider type="vertical"/>

                                    <Tooltip title="新增">
                                        <Button type="dashed" icon={<PlusOutlined/>}
                                                onClick={() => this.showModal('新增磁盘空间')}>

                                        </Button>
                                    </Tooltip>


                                    <Tooltip title="刷新列表">
                                        <Button icon={<SyncOutlined/>} onClick={() => {
                                            this.loadTableData(this.state.queryParams)
                                        }}>

                                        </Button>
                                    </Tooltip>

                                </Space>
                            </Col>
                        </Row>
                    </div>

                </Content>

                <div style={{margin: '0 16px'}}>
                    <List
                        loading={this.state.loading}
                        grid={{gutter: 16, column: 4}}
                        dataSource={this.state.items}
                        renderItem={item => {
                            let delBtn;
                            if (item['isDefault']) {
                                delBtn = <DeleteOutlined key="delete" className={'disabled-icon'}/>
                            } else {
                                delBtn = <Popconfirm
                                    title="您确认要删除此空间吗?"
                                    onConfirm={() => {
                                        this.delete(item['id']);
                                    }}
                                    okText="是"
                                    cancelText="否"
                                >
                                    <DeleteOutlined key="delete"/>
                                </Popconfirm>
                            }
                            return (
                                <List.Item>
                                    <Card title={item['name']}
                                          hoverable
                                          actions={[
                                              <FolderOutlined key='file' onClick={() => {
                                                  this.setState({
                                                      fileSystemVisible: true,
                                                      storageId: item['id']
                                                  });
                                                  if (this.storageRef) {
                                                      this.storageRef.reSetStorageId(item['id']);
                                                  }
                                              }}/>,
                                              <EditOutlined key="edit" onClick={() => {
                                                  // 转换文件大小限制单位为MB
                                                  let model = cloneObj(item);
                                                  if(model['limitSize'] > 0){
                                                      model['limitSize'] = model['limitSize'] / 1024 / 1024;
                                                  }
                                                  this.showModal('修改磁盘空间', model);
                                              }}/>,
                                              delBtn
                                              ,
                                          ]}>
                                        <Descriptions title="" column={1}>
                                            <Descriptions.Item label={<div><TeamOutlined/> 是否共享</div>}>
                                                <strong>{item['isShare'] ? '是' : '否'}</strong>
                                            </Descriptions.Item>
                                            <Descriptions.Item label={<div><SafetyCertificateOutlined/> 是否默认</div>}>
                                                <strong>{item['isDefault'] ? '是' : '否'}</strong>
                                            </Descriptions.Item>
                                            <Descriptions.Item label={<div><FireOutlined/> 大小限制</div>}>
                                                <strong>{item['limitSize'] < 0 ? '无限制' : renderSize(item['limitSize'])}</strong>
                                            </Descriptions.Item>
                                            <Descriptions.Item label={<div><HeartOutlined/> 已用大小</div>}>
                                                <strong>{renderSize(item['usedSize'])}</strong>
                                            </Descriptions.Item>
                                            <Descriptions.Item label={<div><UserOutlined/> 所属用户</div>}>
                                                <strong>{item['ownerName']}</strong>
                                            </Descriptions.Item>
                                        </Descriptions>
                                    </Card>
                                </List.Item>
                            )
                        }}
                    />
                </div>

                <Drawer
                    title={'文件管理'}
                    placement="right"
                    width={window.innerWidth * 0.8}
                    closable={true}
                    maskClosable={true}
                    onClose={() => {
                        this.setState({
                            fileSystemVisible: false
                        });
                        this.loadTableData(this.state.queryParams);
                    }}
                    visible={this.state.fileSystemVisible}
                >
                    <FileSystem
                        storageId={this.state.storageId}
                        storageType={'storages'}
                        onRef={this.onRef}
                        upload={true}
                        download={true}
                        delete={true}
                        rename={true}
                        edit={true}
                        minHeight={window.innerHeight - 103}/>
                </Drawer>

                {
                    this.state.modalVisible ?
                        <StorageModal
                            visible={this.state.modalVisible}
                            title={this.state.modalTitle}
                            handleOk={this.handleOk}
                            handleCancel={() => {
                                this.setState({
                                    modalTitle: '',
                                    modalVisible: false
                                });
                            }}
                            confirmLoading={this.state.modalConfirmLoading}
                            model={this.state.model}
                        >
                        </StorageModal> : undefined
                }
            </div>
        );
    }
Example #16
Source File: Security.js    From next-terminal with GNU Affero General Public License v3.0 4 votes vote down vote up
render() {

        const columns = [{
            title: '序号',
            dataIndex: 'id',
            key: 'id',
            render: (id, record, index) => {
                return index + 1;
            }
        }, {
            title: 'IP',
            dataIndex: 'ip',
            key: 'ip',
            sorter: true,
        }, {
            title: '规则',
            dataIndex: 'rule',
            key: 'rule',
            render: (rule) => {
                if (rule === 'allow') {
                    return <Tag color={'green'}>允许</Tag>
                } else {
                    return <Tag color={'red'}>禁止</Tag>
                }
            }
        }, {
            title: '优先级',
            dataIndex: 'priority',
            key: 'priority',
            sorter: true,
        }, {
            title: '来源',
            dataIndex: 'source',
            key: 'source',
        }, {
            title: '操作',
            key: 'action',
            render: (text, record, index) => {

                return (
                    <div>
                        <Button type="link" size='small' loading={this.state.items[index]['execLoading']}
                                onClick={() => this.showModal('更新', record)}>编辑</Button>

                        <Button type="text" size='small' danger
                                onClick={() => this.showDeleteConfirm(record.id, record.name)}>删除</Button>

                    </div>
                )
            },
        }
        ];

        const selectedRowKeys = this.state.selectedRowKeys;
        const rowSelection = {
            selectedRowKeys: this.state.selectedRowKeys,
            onChange: (selectedRowKeys, selectedRows) => {
                this.setState({selectedRowKeys});
            },
        };
        const hasSelected = selectedRowKeys.length > 0;

        return (
            <>
                <Content className="site-layout-background page-content">

                    <div style={{marginBottom: 20}}>
                        <Row justify="space-around" align="middle" gutter={24}>
                            <Col span={12} key={1}>
                                <Title level={3}>IP访问规则列表</Title>
                            </Col>
                            <Col span={12} key={2} style={{textAlign: 'right'}}>
                                <Space>
                                    <Search
                                        ref={this.inputRefOfName}
                                        placeholder="IP"
                                        allowClear
                                        onSearch={this.handleSearchByName}
                                    />


                                    <Tooltip title='重置查询'>

                                        <Button icon={<UndoOutlined/>} onClick={() => {
                                            this.inputRefOfName.current.setValue('');
                                            this.loadTableData({pageIndex: 1, pageSize: 10, name: '', content: ''})
                                        }}>

                                        </Button>
                                    </Tooltip>

                                    <Divider type="vertical"/>

                                    <Tooltip title="新增">
                                        <Button type="dashed" icon={<PlusOutlined/>}
                                                onClick={() => this.showModal('新增安全访问规则', {})}>

                                        </Button>
                                    </Tooltip>

                                    <Tooltip title="刷新列表">
                                        <Button icon={<SyncOutlined/>} onClick={() => {
                                            this.loadTableData(this.state.queryParams)
                                        }}>

                                        </Button>
                                    </Tooltip>


                                    <Tooltip title="批量删除">
                                        <Button type="primary" danger disabled={!hasSelected} icon={<DeleteOutlined/>}
                                                loading={this.state.delBtnLoading}
                                                onClick={() => {
                                                    const content = <div>
                                                        您确定要删除选中的<Text style={{color: '#1890FF'}}
                                                                       strong>{this.state.selectedRowKeys.length}</Text>条记录吗?
                                                    </div>;
                                                    confirm({
                                                        icon: <ExclamationCircleOutlined/>,
                                                        content: content,
                                                        onOk: () => {
                                                            this.batchDelete()
                                                        },
                                                        onCancel() {

                                                        },
                                                    });
                                                }}>

                                        </Button>
                                    </Tooltip>

                                </Space>
                            </Col>
                        </Row>
                    </div>

                    <Table
                        rowSelection={rowSelection}
                        dataSource={this.state.items}
                        columns={columns}
                        position={'both'}
                        pagination={{
                            showSizeChanger: true,
                            current: this.state.queryParams.pageIndex,
                            pageSize: this.state.queryParams.pageSize,
                            onChange: this.handleChangPage,
                            onShowSizeChange: this.handleChangPage,
                            total: this.state.total,
                            showTotal: total => `总计 ${total} 条`
                        }}
                        loading={this.state.loading}
                        onChange={this.handleTableChange}
                    />

                    {
                        this.state.modalVisible ?
                            <SecurityModal
                                visible={this.state.modalVisible}
                                title={this.state.modalTitle}
                                handleOk={this.handleOk}
                                handleCancel={this.handleCancelModal}
                                confirmLoading={this.state.modalConfirmLoading}
                                model={this.state.model}
                            >
                            </SecurityModal> : undefined
                    }
                </Content>
            </>
        );
    }
Example #17
Source File: LoginLog.js    From next-terminal with GNU Affero General Public License v3.0 4 votes vote down vote up
render() {

        const columns = [{
            title: '序号',
            dataIndex: 'id',
            key: 'id',
            render: (id, record, index) => {
                return index + 1;
            }
        }, {
            title: '登录账号',
            dataIndex: 'username',
            key: 'username'
        }, {
            title: '登录IP',
            dataIndex: 'clientIp',
            key: 'clientIp'
        }, {
            title: '登录状态',
            dataIndex: 'state',
            key: 'state',
            render: text => {
                if (text === '0') {
                    return <Tag color="error">失败</Tag>
                } else {
                    return <Tag color="success">成功</Tag>
                }
            }
        }, {
            title: '失败原因',
            dataIndex: 'reason',
            key: 'reason'
        }, {
            title: '浏览器',
            dataIndex: 'clientUserAgent',
            key: 'clientUserAgent',
            render: (text, record) => {
                if (isEmpty(text)) {
                    return '未知';
                }
                return (
                    <Tooltip placement="topLeft" title={text}>
                        {text.split(' ')[0]}
                    </Tooltip>
                )
            }
        }, {
            title: '登录时间',
            dataIndex: 'loginTime',
            key: 'loginTime',
            render: (text, record) => {

                return formatDate(text, 'yyyy-MM-dd hh:mm:ss');
            }
        }, {
            title: '注销时间',
            dataIndex: 'logoutTime',
            key: 'logoutTime',
            render: (text, record) => {
                if (isEmpty(text) || text === '0001-01-01 00:00:00') {
                    return '';
                }
                return text;
            }
        },
            {
                title: '操作',
                key: 'action',
                render: (text, record) => {
                    return (
                        <div>
                            <Button type="link" size='small' onClick={() => {
                                confirm({
                                    title: '您确定要删除此条登录日志吗?',
                                    content: '删除用户未注销的登录日志将会强制用户下线',
                                    okText: '确定',
                                    okType: 'danger',
                                    cancelText: '取消',
                                    onOk() {
                                        del(record.id)
                                    }
                                });

                                const del = async (id) => {
                                    const result = await request.delete(`/login-logs/${id}`);
                                    if (result.code === 1) {
                                        notification['success']({
                                            message: '提示',
                                            description: '删除成功',
                                        });
                                        this.loadTableData();
                                    } else {
                                        notification['error']({
                                            message: '提示',
                                            description: result.message,
                                        });
                                    }

                                }
                            }}>删除</Button>
                        </div>
                    )
                },
            }
        ];

        const selectedRowKeys = this.state.selectedRowKeys;
        const rowSelection = {
            selectedRowKeys: this.state.selectedRowKeys,
            onChange: (selectedRowKeys, selectedRows) => {
                this.setState({selectedRowKeys});
            },
        };
        const hasSelected = selectedRowKeys.length > 0;

        return (
            <>
                <Content className="site-layout-background page-content">
                    <div style={{marginBottom: 20}}>
                        <Row justify="space-around" align="middle" gutter={24}>
                            <Col span={8} key={1}>
                                <Title level={3}>登录日志列表</Title>
                            </Col>
                            <Col span={16} key={2} style={{textAlign: 'right'}}>
                                <Space>

                                    <Search
                                        ref={this.inputRefOfClientIp}
                                        placeholder="登录账号"
                                        allowClear
                                        onSearch={this.handleSearchByUsername}
                                    />

                                    <Search
                                        ref={this.inputRefOfClientIp}
                                        placeholder="登录IP"
                                        allowClear
                                        onSearch={this.handleSearchByClientIp}
                                    />

                                    <Select
                                        style={{width: 100}}
                                        placeholder='用户昵称'
                                        onChange={this.handleChangeByState}
                                        defaultValue={''}
                                    >
                                        <Select.Option value=''>全部状态</Select.Option>
                                        <Select.Option value='1'>只看成功</Select.Option>
                                        <Select.Option value='0'>只看失败</Select.Option>
                                    </Select>

                                    <Tooltip title='重置查询'>

                                        <Button icon={<UndoOutlined/>} onClick={() => {
                                            this.inputRefOfClientIp.current.setValue('');
                                            this.loadTableData({
                                                pageIndex: 1,
                                                pageSize: 10,
                                                protocol: '',
                                                userId: undefined,
                                                assetId: undefined
                                            })
                                        }}>

                                        </Button>
                                    </Tooltip>

                                    <Divider type="vertical"/>

                                    <Tooltip title="刷新列表">
                                        <Button icon={<SyncOutlined/>} onClick={() => {
                                            this.loadTableData(this.state.queryParams)
                                        }}>

                                        </Button>
                                    </Tooltip>

                                    <Tooltip title="批量删除">
                                        <Button type="dashed" danger disabled={!hasSelected} icon={<DeleteOutlined/>}
                                                loading={this.state.delBtnLoading}
                                                onClick={() => {
                                                    const content = <div>
                                                        您确定要删除选中的<Text style={{color: '#1890FF'}}
                                                                       strong>{this.state.selectedRowKeys.length}</Text>条记录吗?
                                                    </div>;
                                                    confirm({
                                                        icon: <ExclamationCircleOutlined/>,
                                                        title: content,
                                                        content: '删除用户未注销的登录日志将会强制用户下线',
                                                        onOk: () => {
                                                            this.batchDelete()
                                                        },
                                                        onCancel() {

                                                        },
                                                    });
                                                }}>

                                        </Button>
                                    </Tooltip>

                                    <Tooltip title="清空">
                                        <Button type="primary" danger icon={<ClearOutlined/>}
                                                loading={this.state.clearBtnLoading}
                                                onClick={() => {
                                                    const title = <Text style={{color: 'red'}}
                                                                        strong>您确定要清空全部的登录日志吗?</Text>;
                                                    confirm({
                                                        icon: <ExclamationCircleOutlined/>,
                                                        title: title,
                                                        content: '删除用户未注销的登录日志将会强制用户下线,当前登录的用户也会退出登录。',
                                                        okType: 'danger',
                                                        onOk: this.clearLoginLogs,
                                                        onCancel() {

                                                        },
                                                    });
                                                }}>

                                        </Button>
                                    </Tooltip>
                                </Space>
                            </Col>
                        </Row>
                    </div>

                    <Table rowSelection={rowSelection}
                           dataSource={this.state.items}
                           columns={columns}
                           position={'both'}
                           pagination={{
                               showSizeChanger: true,
                               current: this.state.queryParams.pageIndex,
                               pageSize: this.state.queryParams.pageSize,
                               onChange: this.handleChangPage,
                               total: this.state.total,
                               showTotal: total => `总计 ${total} 条`
                           }}
                           loading={this.state.loading}
                    />
                </Content>
            </>
        );
    }
Example #18
Source File: Job.js    From next-terminal with GNU Affero General Public License v3.0 4 votes vote down vote up
render() {

        const columns = [{
            title: '序号',
            dataIndex: 'id',
            key: 'id',
            render: (id, record, index) => {
                return index + 1;
            }
        }, {
            title: '任务名称',
            dataIndex: 'name',
            key: 'name',
            render: (name, record) => {
                let short = name;
                if (short && short.length > 20) {
                    short = short.substring(0, 20) + " ...";
                }
                return (
                    <Tooltip placement="topLeft" title={name}>
                        {short}
                    </Tooltip>
                );
            },
            sorter: true,
        }, {
            title: '状态',
            dataIndex: 'status',
            key: 'status',
            render: (status, record) => {
                return <Switch checkedChildren="开启" unCheckedChildren="关闭" checked={status === 'running'}
                               onChange={async (checked) => {
                                   let jobStatus = checked ? 'running' : 'not-running';
                                   let result = await request.post(`/jobs/${record['id']}/change-status?status=${jobStatus}`);
                                   if (result['code'] === 1) {
                                       message.success('操作成功');
                                       await this.loadTableData();
                                   } else {
                                       message.error(result['message']);
                                   }
                               }}
                />
            }
        }, {
            title: '任务类型',
            dataIndex: 'func',
            key: 'func',
            render: (func, record) => {
                switch (func) {
                    case "check-asset-status-job":
                        return <Tag color="green">资产状态检测</Tag>;
                    case "shell-job":
                        return <Tag color="volcano">Shell脚本</Tag>;
                    default:
                        return '';
                }
            }
        }, {
            title: 'cron表达式',
            dataIndex: 'cron',
            key: 'cron'
        }, {
            title: '创建日期',
            dataIndex: 'created',
            key: 'created',
            render: (text, record) => {
                return (
                    <Tooltip title={text}>
                        {dayjs(text).fromNow()}
                    </Tooltip>
                )
            },
            sorter: true,
        }, {
            title: '最后执行日期',
            dataIndex: 'updated',
            key: 'updated',
            render: (text, record) => {
                if (text === '0001-01-01 00:00:00') {
                    return '';
                }
                return (
                    <Tooltip title={text}>
                        {dayjs(text).fromNow()}
                    </Tooltip>
                )
            },
            sorter: true,
        }, {
            title: '操作',
            key: 'action',
            render: (text, record, index) => {

                const menu = (
                    <Menu>
                        <Menu.Item key="0">
                            <Button type="text" size='small'
                                    onClick={() => this.showModal('更新计划任务', record)}>编辑</Button>
                        </Menu.Item>

                        <Menu.Item key="2">
                            <Button type="text" size='small'
                                    onClick={async () => {
                                        this.setState({
                                            logVisible: true,
                                            logPending: true
                                        })

                                        let result = await request.get(`/jobs/${record['id']}/logs`);
                                        if (result['code'] === 1) {
                                            this.setState({
                                                logPending: false,
                                                logs: result['data'],
                                                selectedRow: record
                                            })
                                        }

                                    }}>日志</Button>
                        </Menu.Item>

                        <Menu.Divider/>
                        <Menu.Item key="3">
                            <Button type="text" size='small' danger
                                    onClick={() => this.showDeleteConfirm(record.id, record.name)}>删除</Button>
                        </Menu.Item>
                    </Menu>
                );

                return (
                    <div>
                        <Button type="link" size='small' loading={this.state.items[index]['execLoading']}
                                onClick={async () => {
                                    let items = this.state.items;
                                    items[index]['execLoading'] = true;
                                    this.setState({
                                        items: items
                                    });

                                    let result = await request.post(`/jobs/${record['id']}/exec`);
                                    if (result['code'] === 1) {
                                        message.success('执行成功');
                                        await this.loadTableData();
                                    } else {
                                        message.error(result['message']);
                                        items[index]['execLoading'] = false;
                                        this.setState({
                                            items: items
                                        });
                                    }
                                }}>执行</Button>

                        <Dropdown overlay={menu}>
                            <Button type="link" size='small'>
                                更多 <DownOutlined/>
                            </Button>
                        </Dropdown>

                    </div>
                )
            },
        }
        ];

        const selectedRowKeys = this.state.selectedRowKeys;
        const rowSelection = {
            selectedRowKeys: this.state.selectedRowKeys,
            onChange: (selectedRowKeys, selectedRows) => {
                this.setState({selectedRowKeys});
            },
        };
        const hasSelected = selectedRowKeys.length > 0;

        return (
            <>
                <Content className="site-layout-background page-content">

                    <div style={{marginBottom: 20}}>
                        <Row justify="space-around" align="middle" gutter={24}>
                            <Col span={12} key={1}>
                                <Title level={3}>任务列表</Title>
                            </Col>
                            <Col span={12} key={2} style={{textAlign: 'right'}}>
                                <Space>
                                    <Search
                                        ref={this.inputRefOfName}
                                        placeholder="任务名称"
                                        allowClear
                                        onSearch={this.handleSearchByName}
                                    />


                                    <Tooltip title='重置查询'>

                                        <Button icon={<UndoOutlined/>} onClick={() => {
                                            this.inputRefOfName.current.setValue('');
                                            this.loadTableData({pageIndex: 1, pageSize: 10, name: '', content: ''})
                                        }}>

                                        </Button>
                                    </Tooltip>

                                    <Divider type="vertical"/>

                                    <Tooltip title="新增">
                                        <Button type="dashed" icon={<PlusOutlined/>}
                                                onClick={() => this.showModal('新增计划任务', {})}>

                                        </Button>
                                    </Tooltip>


                                    <Tooltip title="刷新列表">
                                        <Button icon={<SyncOutlined/>} onClick={() => {
                                            this.loadTableData(this.state.queryParams)
                                        }}>

                                        </Button>
                                    </Tooltip>


                                    <Tooltip title="批量删除">
                                        <Button type="primary" danger disabled={!hasSelected} icon={<DeleteOutlined/>}
                                                loading={this.state.delBtnLoading}
                                                onClick={() => {
                                                    const content = <div>
                                                        您确定要删除选中的<Text style={{color: '#1890FF'}}
                                                                       strong>{this.state.selectedRowKeys.length}</Text>条记录吗?
                                                    </div>;
                                                    confirm({
                                                        icon: <ExclamationCircleOutlined/>,
                                                        content: content,
                                                        onOk: () => {
                                                            this.batchDelete()
                                                        },
                                                        onCancel() {

                                                        },
                                                    });
                                                }}>

                                        </Button>
                                    </Tooltip>

                                </Space>
                            </Col>
                        </Row>
                    </div>

                    <Table
                        rowSelection={rowSelection}
                        dataSource={this.state.items}
                        columns={columns}
                        position={'both'}
                        pagination={{
                            showSizeChanger: true,
                            current: this.state.queryParams.pageIndex,
                            pageSize: this.state.queryParams.pageSize,
                            onChange: this.handleChangPage,
                            onShowSizeChange: this.handleChangPage,
                            total: this.state.total,
                            showTotal: total => `总计 ${total} 条`
                        }}
                        loading={this.state.loading}
                        onChange={this.handleTableChange}
                    />

                    {
                        this.state.modalVisible ?
                            <JobModal
                                visible={this.state.modalVisible}
                                title={this.state.modalTitle}
                                handleOk={this.handleOk}
                                handleCancel={this.handleCancelModal}
                                confirmLoading={this.state.modalConfirmLoading}
                                model={this.state.model}
                            >
                            </JobModal> : undefined
                    }

                    {
                        this.state.logVisible ?
                            <Modal
                                className='modal-no-padding'
                                width={window.innerWidth * 0.8}
                                title={'日志'}
                                visible={true}
                                maskClosable={false}

                                onOk={async () => {
                                    let result = await request.delete(`/jobs/${this.state.selectedRow['id']}/logs`);
                                    if (result['code'] === 1) {
                                        this.setState({
                                            logVisible: false,
                                            selectedRow: undefined
                                        })
                                        message.success('日志清空成功');
                                    } else {
                                        message.error(result['message'], 10);
                                    }
                                }}
                                onCancel={() => {
                                    this.setState({
                                        logVisible: false,
                                        selectedRow: undefined
                                    })
                                }}
                                okText='清空'
                                okType={'danger'}
                                cancelText='取消'
                            >
                                <Spin tip='加载中...' spinning={this.state.logPending}>
                                    <pre className='cron-log'>
                                        {
                                            this.state.logs.map(item => {

                                                return <><Divider
                                                    orientation="left"
                                                    style={{color: 'white'}}>{item['timestamp']}</Divider>{item['message']}</>;
                                            })
                                        }
                                    </pre>
                                </Spin>
                            </Modal> : undefined
                    }
                </Content>
            </>
        );
    }
Example #19
Source File: Credential.js    From next-terminal with GNU Affero General Public License v3.0 4 votes vote down vote up
render() {

        const columns = [{
            title: '序号',
            dataIndex: 'id',
            key: 'id',
            render: (id, record, index) => {
                return index + 1;
            }
        }, {
            title: '凭证名称',
            dataIndex: 'name',
            key: 'name',
            render: (name, record, index) => {
                let short = name;
                if (short && short.length > 20) {
                    short = short.substring(0, 20) + " ...";
                }
                if (hasPermission(record['owner'])) {
                    return (
                        <Button type="link" size='small' loading={this.state.items[index].updateBtnLoading}
                                onClick={() => this.showModal('更新凭证', record.id, index)}>
                            <Tooltip placement="topLeft" title={name}>
                                {short}
                            </Tooltip>
                        </Button>
                    );
                } else {
                    return (
                        <Tooltip placement="topLeft" title={name}>
                            {short}
                        </Tooltip>
                    );
                }
            },
            sorter: true,
        }, {
            title: '凭证类型',
            dataIndex: 'type',
            key: 'type',
            render: (type, record) => {

                if (type === 'private-key') {
                    return (
                        <Tag color="green">密钥</Tag>
                    );
                } else {
                    return (
                        <Tag color="red">密码</Tag>
                    );
                }
            }
        }, {
            title: '授权账户',
            dataIndex: 'username',
            key: 'username',
        }, {
            title: '所有者',
            dataIndex: 'ownerName',
            key: 'ownerName',
        }, {
            title: '创建时间',
            dataIndex: 'created',
            key: 'created',
            render: (text, record) => {
                return (
                    <Tooltip title={text}>
                        {dayjs(text).fromNow()}
                    </Tooltip>
                )
            },
            sorter: true,
        },
            {
                title: '操作',
                key: 'action',
                render: (text, record, index) => {

                    const menu = (
                        <Menu>
                            <Menu.Item key="1">
                                <Button type="text" size='small'
                                        disabled={!hasPermission(record['owner'])}
                                        onClick={() => {
                                            this.handleSearchByNickname('')
                                                .then(() => {
                                                    this.setState({
                                                        changeOwnerModalVisible: true,
                                                        selected: record,
                                                    })
                                                    this.changeOwnerFormRef
                                                        .current
                                                        .setFieldsValue({
                                                            owner: record['owner']
                                                        })
                                                });

                                        }}>更换所有者</Button>
                            </Menu.Item>
                            <Menu.Divider/>
                            <Menu.Item key="3">
                                <Button type="text" size='small' danger
                                        disabled={!hasPermission(record['owner'])}
                                        onClick={() => this.showDeleteConfirm(record.id, record.name)}>删除</Button>
                            </Menu.Item>
                        </Menu>
                    );

                    return (
                        <div>
                            <Button type="link" size='small' loading={this.state.items[index].updateBtnLoading}
                                    disabled={!hasPermission(record['owner'])}
                                    onClick={() => this.showModal('更新凭证', record.id, index)}>编辑</Button>
                            <Dropdown overlay={menu}>
                                <Button type="link" size='small'>
                                    更多 <DownOutlined/>
                                </Button>
                            </Dropdown>
                        </div>
                    )
                },
            }
        ];

        const selectedRowKeys = this.state.selectedRowKeys;
        const rowSelection = {
            selectedRowKeys: this.state.selectedRowKeys,
            onChange: (selectedRowKeys, selectedRows) => {
                this.setState({selectedRowKeys});
            },
        };
        const hasSelected = selectedRowKeys.length > 0;

        return (
            <>
                <Content className="site-layout-background page-content">

                    <div style={{marginBottom: 20}}>

                        <Row justify="space-around" align="middle" gutter={24}>
                            <Col span={12} key={1}>
                                <Title level={3}>授权凭证列表</Title>
                            </Col>
                            <Col span={12} key={2} style={{textAlign: 'right'}}>
                                <Space>
                                    <Search
                                        ref={this.inputRefOfName}
                                        placeholder="凭证名称"
                                        allowClear
                                        onSearch={this.handleSearchByName}
                                    />

                                    <Tooltip title='重置查询'>

                                        <Button icon={<UndoOutlined/>} onClick={() => {
                                            this.inputRefOfName.current.setValue('');
                                            this.loadTableData({pageIndex: 1, pageSize: 10, name: ''})
                                        }}>

                                        </Button>
                                    </Tooltip>

                                    <Divider type="vertical"/>

                                    <Tooltip title="新增">
                                        <Button type="dashed" icon={<PlusOutlined/>}
                                                onClick={() => this.showModal('新增凭证')}>

                                        </Button>
                                    </Tooltip>


                                    <Tooltip title="刷新列表">
                                        <Button icon={<SyncOutlined/>} onClick={() => {
                                            this.loadTableData(this.state.queryParams)
                                        }}>

                                        </Button>
                                    </Tooltip>

                                    <Tooltip title="批量删除">
                                        <Button type="primary" danger disabled={!hasSelected} icon={<DeleteOutlined/>}
                                                loading={this.state.delBtnLoading}
                                                onClick={() => {
                                                    const content = <div>
                                                        您确定要删除选中的<Text style={{color: '#1890FF'}}
                                                                       strong>{this.state.selectedRowKeys.length}</Text>条记录吗?
                                                    </div>;
                                                    confirm({
                                                        icon: <ExclamationCircleOutlined/>,
                                                        content: content,
                                                        onOk: () => {
                                                            this.batchDelete()
                                                        },
                                                        onCancel() {

                                                        },
                                                    });
                                                }}>

                                        </Button>
                                    </Tooltip>

                                </Space>
                            </Col>
                        </Row>
                    </div>

                    <Table
                        rowSelection={rowSelection}
                        rowKey='id'
                        dataSource={this.state.items}
                        columns={columns}
                        position={'both'}
                        pagination={{
                            showSizeChanger: true,
                            current: this.state.queryParams.pageIndex,
                            pageSize: this.state.queryParams.pageSize,
                            onChange: this.handleChangPage,
                            onShowSizeChange: this.handleChangPage,
                            total: this.state.total,
                            showTotal: total => `总计 ${total} 条`
                        }}
                        loading={this.state.loading}
                        onChange={this.handleTableChange}
                    />

                    {
                        this.state.modalVisible ?
                            <CredentialModal
                                visible={this.state.modalVisible}
                                title={this.state.modalTitle}
                                handleOk={this.handleOk}
                                handleCancel={this.handleCancelModal}
                                confirmLoading={this.state.modalConfirmLoading}
                                model={this.state.model}
                            >

                            </CredentialModal>
                            : null
                    }

                    <Modal title={<Text>更换资源「<strong style={{color: '#1890ff'}}>{this.state.selected['name']}</strong>」的所有者
                    </Text>}
                           visible={this.state.changeOwnerModalVisible}
                           confirmLoading={this.state.changeOwnerConfirmLoading}

                           onOk={() => {
                               this.setState({
                                   changeOwnerConfirmLoading: true
                               });

                               let changeOwnerModalVisible = false;
                               this.changeOwnerFormRef
                                   .current
                                   .validateFields()
                                   .then(async values => {
                                       let result = await request.post(`/credentials/${this.state.selected['id']}/change-owner?owner=${values['owner']}`);
                                       if (result['code'] === 1) {
                                           message.success('操作成功');
                                           this.loadTableData();
                                       } else {
                                           message.error(result['message'], 10);
                                           changeOwnerModalVisible = true;
                                       }
                                   })
                                   .catch(info => {

                                   })
                                   .finally(() => {
                                       this.setState({
                                           changeOwnerConfirmLoading: false,
                                           changeOwnerModalVisible: changeOwnerModalVisible
                                       })
                                   });
                           }}
                           onCancel={() => {
                               this.setState({
                                   changeOwnerModalVisible: false
                               })
                           }}
                    >

                        <Form ref={this.changeOwnerFormRef}>
                            <Form.Item name='owner' rules={[{required: true, message: '请选择所有者'}]}>
                                <Select
                                    showSearch
                                    placeholder='请选择所有者'
                                    onSearch={this.handleSearchByNickname}
                                    filterOption={false}
                                >
                                    {this.state.users.map(d => <Select.Option key={d.id}
                                                                              value={d.id}>{d.nickname}</Select.Option>)}
                                </Select>
                            </Form.Item>
                        </Form>
                    </Modal>

                </Content>
            </>
        );
    }
Example #20
Source File: DynamicCommand.js    From next-terminal with GNU Affero General Public License v3.0 4 votes vote down vote up
render() {

        const columns = [{
            title: '序号',
            dataIndex: 'id',
            key: 'id',
            render: (id, record, index) => {
                return index + 1;
            }
        }, {
            title: '指令名称',
            dataIndex: 'name',
            key: 'name',
            render: (name, record) => {
                let short = name;
                if (short && short.length > 20) {
                    short = short.substring(0, 20) + " ...";
                }
                if (hasPermission(record['owner'])) {
                    return (
                        <Button type="link" size='small' onClick={() => this.showModal('更新指令', record)}>
                            <Tooltip placement="topLeft" title={name}>
                                {short}
                            </Tooltip>
                        </Button>
                    );
                } else {
                    return (
                        <Tooltip placement="topLeft" title={name}>
                            {short}
                        </Tooltip>
                    );
                }
            },
            sorter: true,
        }, {
            title: '指令内容',
            dataIndex: 'content',
            key: 'content',
            render: (content, record) => {
                let short = content;
                if (short && short.length > 20) {
                    short = short.substring(0, 20) + " ...";
                }

                return (
                    <Tooltip placement="topLeft" title={content}>
                        {short}
                    </Tooltip>
                );
            }
        }, {
            title: '所有者',
            dataIndex: 'ownerName',
            key: 'ownerName'
        }, {
            title: '创建日期',
            dataIndex: 'created',
            key: 'created',
            render: (text, record) => {
                return (
                    <Tooltip title={text}>
                        {dayjs(text).fromNow()}
                    </Tooltip>
                )
            },
            sorter: true,
        }, {
            title: '操作',
            key: 'action',
            render: (text, record) => {

                const menu = (
                    <Menu>
                        <Menu.Item key="1">
                            <Button type="text" size='small'
                                    onClick={() => this.showModal('更新指令', record)}>编辑</Button>
                        </Menu.Item>

                        <Menu.Item key="2">
                            <Button type="text" size='small'
                                    onClick={() => {
                                        this.handleSearchByNickname('')
                                            .then(() => {
                                                this.setState({
                                                    changeOwnerModalVisible: true,
                                                    selected: record,
                                                })
                                                this.changeOwnerFormRef
                                                    .current
                                                    .setFieldsValue({
                                                        owner: record['owner']
                                                    })
                                            });

                                    }}>更换所有者</Button>
                        </Menu.Item>
                        <Menu.Divider/>
                        <Menu.Item key="3">
                            <Button type="text" size='small' danger
                                    onClick={() => this.showDeleteConfirm(record.id, record.name)}>删除</Button>
                        </Menu.Item>
                    </Menu>
                );

                let action;
                if (isAdmin()) {
                    action = (
                        <div>
                            <Button type="link" size='small' onClick={async () => {
                                this.setState({
                                    assetsVisible: true,
                                    commandId: record['id']
                                });
                            }}>执行</Button>

                            <Dropdown overlay={menu}>
                                <Button type="link" size='small'>
                                    更多 <DownOutlined/>
                                </Button>
                            </Dropdown>

                        </div>
                    )
                } else {
                    action = (
                        <div>
                            <Button type="link" size='small'
                                    disabled={!hasPermission(record['owner'])}
                                    onClick={() => this.showModal('更新指令', record)}>编辑</Button>

                            <Button type="link" size='small' danger
                                    disabled={!hasPermission(record['owner'])}
                                    onClick={() => this.showDeleteConfirm(record.id, record.name)}>删除</Button>

                        </div>
                    )
                }

                return action;
            },
        }
        ];

        const selectedRowKeys = this.state.selectedRowKeys;
        const rowSelection = {
            selectedRowKeys: this.state.selectedRowKeys,
            onChange: (selectedRowKeys, selectedRows) => {
                this.setState({selectedRowKeys});
            },
        };
        const hasSelected = selectedRowKeys.length > 0;

        let contentClassName = isAdmin() ? 'page-content' : 'page-content-user';

        return (
            <>
                <Content className={["site-layout-background", contentClassName]}>

                    <div style={{marginBottom: 20}}>
                        <Row justify="space-around" align="middle" gutter={24}>
                            <Col span={12} key={1}>
                                <Title level={3}>指令列表</Title>
                            </Col>
                            <Col span={12} key={2} style={{textAlign: 'right'}}>
                                <Space>
                                    <Search
                                        ref={this.inputRefOfName}
                                        placeholder="指令名称"
                                        allowClear
                                        onSearch={this.handleSearchByName}
                                    />

                                    <Search
                                        ref={this.inputRefOfContent}
                                        placeholder="指令内容"
                                        allowClear
                                        onSearch={this.handleSearchByContent}
                                    />

                                    <Tooltip title='重置查询'>

                                        <Button icon={<UndoOutlined/>} onClick={() => {
                                            this.inputRefOfName.current.setValue('');
                                            this.inputRefOfContent.current.setValue('');
                                            this.loadTableData({pageIndex: 1, pageSize: 10, name: '', content: ''})
                                        }}>

                                        </Button>
                                    </Tooltip>

                                    <Divider type="vertical"/>

                                    <Tooltip title="新增">
                                        <Button type="dashed" icon={<PlusOutlined/>}
                                                onClick={() => this.showModal('新增指令', {})}>

                                        </Button>
                                    </Tooltip>


                                    <Tooltip title="刷新列表">
                                        <Button icon={<SyncOutlined/>} onClick={() => {
                                            this.loadTableData(this.state.queryParams)
                                        }}>

                                        </Button>
                                    </Tooltip>


                                    <Tooltip title="批量删除">
                                        <Button type="primary" danger disabled={!hasSelected} icon={<DeleteOutlined/>}
                                                loading={this.state.delBtnLoading}
                                                onClick={() => {
                                                    const content = <div>
                                                        您确定要删除选中的<Text style={{color: '#1890FF'}}
                                                                       strong>{this.state.selectedRowKeys.length}</Text>条记录吗?
                                                    </div>;
                                                    confirm({
                                                        icon: <ExclamationCircleOutlined/>,
                                                        content: content,
                                                        onOk: () => {
                                                            this.batchDelete()
                                                        },
                                                        onCancel() {

                                                        },
                                                    });
                                                }}>

                                        </Button>
                                    </Tooltip>

                                </Space>
                            </Col>
                        </Row>
                    </div>

                    <Table
                        rowSelection={rowSelection}
                        dataSource={this.state.items}
                        columns={columns}
                        position={'both'}
                        pagination={{
                            showSizeChanger: true,
                            current: this.state.queryParams.pageIndex,
                            pageSize: this.state.queryParams.pageSize,
                            onChange: this.handleChangPage,
                            onShowSizeChange: this.handleChangPage,
                            total: this.state.total,
                            showTotal: total => `总计 ${total} 条`
                        }}
                        loading={this.state.loading}
                        onChange={this.handleTableChange}
                    />

                    {
                        this.state.modalVisible ?
                            <DynamicCommandModal
                                visible={this.state.modalVisible}
                                title={this.state.modalTitle}
                                handleOk={this.handleOk}
                                handleCancel={this.handleCancelModal}
                                confirmLoading={this.state.modalConfirmLoading}
                                model={this.state.model}
                            >

                            </DynamicCommandModal>
                            : null
                    }

                    <Modal
                        title="选择资产"
                        visible={this.state.assetsVisible}
                        width={window.innerWidth * 0.8}
                        centered={true}
                        onOk={this.executeCommand}
                        onCancel={() => {
                            this.setState({
                                assetsVisible: false
                            });
                        }}
                    >
                        <ChooseAsset
                            setCheckedAssets={this.setCheckedAssets}
                        >
                        </ChooseAsset>
                    </Modal>


                    <Modal title={<Text>更换资源「<strong style={{color: '#1890ff'}}>{this.state.selected['name']}</strong>」的所有者
                    </Text>}
                           visible={this.state.changeOwnerModalVisible}
                           confirmLoading={this.state.changeOwnerConfirmLoading}

                           onOk={() => {
                               this.setState({
                                   changeOwnerConfirmLoading: true
                               });

                               let changeOwnerModalVisible = false;
                               this.changeOwnerFormRef
                                   .current
                                   .validateFields()
                                   .then(async values => {
                                       let result = await request.post(`/commands/${this.state.selected['id']}/change-owner?owner=${values['owner']}`);
                                       if (result['code'] === 1) {
                                           message.success('操作成功');
                                           this.loadTableData();
                                       } else {
                                           message.error(result['message'], 10);
                                           changeOwnerModalVisible = true;
                                       }
                                   })
                                   .catch(info => {

                                   })
                                   .finally(() => {
                                       this.setState({
                                           changeOwnerConfirmLoading: false,
                                           changeOwnerModalVisible: changeOwnerModalVisible
                                       })
                                   });
                           }}
                           onCancel={() => {
                               this.setState({
                                   changeOwnerModalVisible: false
                               })
                           }}
                    >

                        <Form ref={this.changeOwnerFormRef}>

                            <Form.Item name='owner' rules={[{required: true, message: '请选择所有者'}]}>
                                <Select
                                    showSearch
                                    placeholder='请选择所有者'
                                    onSearch={this.handleSearchByNickname}
                                    filterOption={false}
                                >
                                    {this.state.users.map(d => <Select.Option key={d.id}
                                                                              value={d.id}>{d.nickname}</Select.Option>)}
                                </Select>
                            </Form.Item>
                        </Form>
                    </Modal>
                </Content>
            </>
        );
    }
Example #21
Source File: ChooseAsset.js    From next-terminal with GNU Affero General Public License v3.0 4 votes vote down vote up
render() {

        const columns = [{
            title: '序号',
            dataIndex: 'id',
            key: 'id',
            render: (id, record, index) => {
                return index + 1;
            }
        }, {
            title: '资产名称',
            dataIndex: 'name',
            key: 'name',
            render: (name, record) => {
                let short = name;
                if (short && short.length > 20) {
                    short = short.substring(0, 20) + " ...";
                }
                return (
                    <Tooltip placement="topLeft" title={name}>
                        {short}
                    </Tooltip>
                );
            }
        }, {
            title: '连接协议',
            dataIndex: 'protocol',
            key: 'protocol',
            render: (text, record) => {
                const title = `${record['ip'] + ':' + record['port']}`
                return (
                    <Tooltip title={title}>
                        <Tag color={PROTOCOL_COLORS[text]}>{text}</Tag>
                    </Tooltip>
                )
            }
        }, {
            title: '标签',
            dataIndex: 'tags',
            key: 'tags',
            render: tags => {
                if (!isEmpty(tags)) {
                    let tagDocuments = []
                    let tagArr = tags.split(',');
                    for (let i = 0; i < tagArr.length; i++) {
                        if (tags[i] === '-') {
                            continue;
                        }
                        tagDocuments.push(<Tag>{tagArr[i]}</Tag>)
                    }
                    return tagDocuments;
                }
            }
        }, {
            title: '状态',
            dataIndex: 'active',
            key: 'active',
            render: text => {

                if (text) {
                    return (
                        <Tooltip title='运行中'>
                            <Badge status="processing" text='运行中'/>
                        </Tooltip>
                    )
                } else {
                    return (
                        <Tooltip title='不可用'>
                            <Badge status="error" text='不可用'/>
                        </Tooltip>
                    )
                }
            }
        }, {
            title: '所有者',
            dataIndex: 'ownerName',
            key: 'ownerName'
        }, {
            title: '创建日期',
            dataIndex: 'created',
            key: 'created',
            render: (text, record) => {
                return (
                    <Tooltip title={text}>
                        {dayjs(text).fromNow()}
                    </Tooltip>
                )
            }
        },
        ];

        const selectedRowKeys = this.state.selectedRowKeys;
        const rowSelection = {
            selectedRowKeys: selectedRowKeys,
            onChange: (selectedRowKeys, selectedRows) => {
                this.setState({selectedRowKeys, selectedRows});

                let totalSelectedRows = this.state.totalSelectedRows;
                let totalSelectedRowKeys = totalSelectedRows.map(item => item['id']);
                for (let i = 0; i < selectedRows.length; i++) {
                    let selectedRow = selectedRows[i];
                    if (totalSelectedRowKeys.includes(selectedRow['id'])) {
                        continue;
                    }
                    totalSelectedRows.push(selectedRow);
                }

                this.setState({
                    totalSelectedRows: totalSelectedRows
                })
                if (this.checkedAssets) {
                    this.checkedAssets(totalSelectedRows);
                }
                console.log(totalSelectedRows);
            },
            getCheckboxProps: (record) => ({
                disabled: record['disabled'],
            }),
        };

        return (
            <>
                <Title level={3}>已选择资产列表</Title>
                <div>
                    {
                        this.state.totalSelectedRows.map(item => {
                            return <Tag color={PROTOCOL_COLORS[item['protocol']]} closable
                                        onClose={() => this.unSelectRow(item['id'])}
                                        key={item['id']}>{item['name']}</Tag>
                        })
                    }
                </div>

                <Divider/>
                <Content key='page-content' className="site-layout-background">
                    <div style={{marginBottom: 20}}>
                        <Row justify="space-around" align="middle" gutter={24}>
                            <Col span={4} key={1}>
                                <Title level={3}>全部资产列表</Title>
                            </Col>
                            <Col span={20} key={2} style={{textAlign: 'right'}}>
                                <Space>

                                    <Search
                                        ref={this.inputRefOfName}
                                        placeholder="资产名称"
                                        allowClear
                                        onSearch={this.handleSearchByName}
                                        style={{width: 200}}
                                    />

                                    <Search
                                        ref={this.inputRefOfIp}
                                        placeholder="资产IP"
                                        allowClear
                                        onSearch={this.handleSearchByIp}
                                        style={{width: 200}}
                                    />

                                    <Select mode="multiple"
                                            allowClear
                                            placeholder="资产标签" onChange={this.handleTagsChange}
                                            style={{minWidth: 150}}>
                                        {this.state.tags.map(tag => {
                                            if (tag === '-') {
                                                return undefined;
                                            }
                                            return (<Select.Option key={tag}>{tag}</Select.Option>)
                                        })}
                                    </Select>

                                    <Tooltip title='重置查询'>

                                        <Button icon={<UndoOutlined/>} onClick={() => {
                                            this.inputRefOfName.current.setValue('');
                                            this.inputRefOfIp.current.setValue('');
                                            this.loadTableData({
                                                ...this.state.queryParams,
                                                pageIndex: 1,
                                                pageSize: 10,
                                                protocol: 'ssh',
                                                name: '',
                                                ip: ''
                                            })
                                        }}>

                                        </Button>
                                    </Tooltip>

                                    <Divider type="vertical"/>

                                    <Tooltip title="刷新列表">
                                        <Button icon={<SyncOutlined/>} onClick={() => {
                                            this.loadTableData(this.state.queryParams)
                                        }}>

                                        </Button>
                                    </Tooltip>
                                </Space>
                            </Col>
                        </Row>
                    </div>

                    <Table key='assets-table'
                           rowSelection={rowSelection}
                           dataSource={this.state.items}
                           columns={columns}
                           position={'both'}
                           size="middle"
                           pagination={{
                               showSizeChanger: true,
                               current: this.state.queryParams.pageIndex,
                               pageSize: this.state.queryParams.pageSize,
                               onChange: this.handleChangPage,
                               onShowSizeChange: this.handleChangPage,
                               total: this.state.total,
                               showTotal: total => `总计 ${total} 条`
                           }}
                           loading={this.state.loading}
                    />
                </Content>
            </>
        );
    }
Example #22
Source File: MyAsset.js    From next-terminal with GNU Affero General Public License v3.0 4 votes vote down vote up
render() {
        return (
            <div style={{marginTop: 20}}>
                <Content style={{background: 'white', padding: 24}}>
                    <div>
                        <Row justify="space-around" align="middle" gutter={24}>
                            <Col span={4} key={1}>
                                <Title level={3}>我的资产</Title>
                            </Col>
                            <Col span={20} key={2} style={{textAlign: 'right'}}>
                                <Space>
                                    <Search
                                        ref={this.inputRefOfName}
                                        placeholder="资产名称"
                                        allowClear
                                        onSearch={this.handleSearchByName}
                                        style={{width: 200}}
                                    />

                                    <Select mode="multiple"
                                            allowClear
                                            value={this.state.selectedTags}
                                            placeholder="资产标签" onChange={this.handleTagsChange}
                                            style={{minWidth: 150}}>
                                        {this.state.tags.map(tag => {
                                            if (tag === '-') {
                                                return undefined;
                                            }
                                            return (<Select.Option key={tag}>{tag}</Select.Option>)
                                        })}
                                    </Select>

                                    <Select onChange={this.handleSearchByProtocol}
                                            value={this.state.queryParams.protocol ? this.state.queryParams.protocol : ''}
                                            style={{width: 100}}>
                                        <Select.Option value="">全部协议</Select.Option>
                                        <Select.Option value="rdp">rdp</Select.Option>
                                        <Select.Option value="ssh">ssh</Select.Option>
                                        <Select.Option value="vnc">vnc</Select.Option>
                                        <Select.Option value="telnet">telnet</Select.Option>
                                        <Select.Option value="kubernetes">kubernetes</Select.Option>
                                    </Select>

                                    <Tooltip title='重置查询'>

                                        <Button icon={<UndoOutlined/>} onClick={() => {
                                            this.inputRefOfName.current.setValue('');
                                            this.inputRefOfIp.current.setValue('');
                                            this.setState({
                                                selectedTags: []
                                            })
                                            this.loadTableData({pageIndex: 1, pageSize: 10, protocol: '', tags: ''})
                                        }}>

                                        </Button>
                                    </Tooltip>

                                    <Divider type="vertical"/>

                                    <Tooltip title="刷新列表">
                                        <Button icon={<SyncOutlined/>} onClick={() => {
                                            this.loadTableData(this.state.queryParams)
                                        }}>

                                        </Button>
                                    </Tooltip>

                                </Space>
                            </Col>
                        </Row>
                    </div>

                </Content>

                <div style={{marginTop: 20}}>
                    <List
                        loading={this.state.loading}
                        grid={{gutter: 16, column: 4}}
                        dataSource={this.state.items}
                        pagination={{
                            showSizeChanger: true,
                            current: this.state.queryParams.pageIndex,
                            pageSize: this.state.queryParams.pageSize,
                            onChange: this.handleChangPage,
                            onShowSizeChange: this.handleChangPage,
                            total: this.state.total,
                            showTotal: total => `总计 ${total} 条`,
                            pageSizeOptions: [8, 16, 32, 64, 128]
                        }}
                        renderItem={item => {

                            const id = item['id'];
                            const protocol = item['protocol'];
                            const name = item['name'];
                            const sshMode = item['sshMode'];
                            let url = '';
                            if (protocol === 'ssh' && sshMode === 'native') {
                                url = `#/term?assetId=${id}&assetName=${name}`;
                            } else {
                                url = `#/access?assetId=${id}&assetName=${name}&protocol=${protocol}`;
                            }

                            return (
                                <List.Item>
                                    <a target='_blank' href={url} rel='noreferrer noopener'>
                                        <Card title={item['name']}
                                              hoverable
                                              extra={item['active'] ?
                                                  <Tag icon={<CheckCircleOutlined/>} color="success">
                                                      运行中
                                                  </Tag> : <Tag icon={<ExclamationCircleOutlined/>} color="error">
                                                      不可用
                                                  </Tag>}
                                              actions={[]}>
                                            <Descriptions title="" column={1}>
                                                <Descriptions.Item label={<div><CodeOutlined/> 资产协议</div>}>
                                                    <strong>{item['protocol']}</strong>
                                                </Descriptions.Item>
                                                <Descriptions.Item label={<div><TagsOutlined/> 标签</div>}>
                                                    <strong>{this.renderTags(item['tags'])}</strong>
                                                </Descriptions.Item>
                                            </Descriptions>
                                        </Card>
                                    </a>
                                </List.Item>
                            )
                        }}
                    />
                </div>
            </div>
        );
    }
Example #23
Source File: Asset.js    From next-terminal with GNU Affero General Public License v3.0 4 votes vote down vote up
render() {

        const columns = [{
            title: '序号',
            dataIndex: 'id',
            key: 'id',
            render: (id, record, index) => {
                return index + 1;
            }
        }, {
            title: '资产名称',
            dataIndex: 'name',
            key: 'name',
            render: (name, record) => {
                let short = name;
                if (short && short.length > 15) {
                    short = short.substring(0, 15) + " ...";
                }

                if (hasPermission(record['owner'])) {
                    return (
                        <Button type="link" size='small' onClick={() => this.update(record.id)}>
                            <Tooltip placement="topLeft" title={name}>
                                {short}
                            </Tooltip>
                        </Button>
                    );
                } else {
                    return (
                        <Tooltip placement="topLeft" title={name}>
                            {short}
                        </Tooltip>
                    );
                }
            },
            sorter: true,
        }, {
            title: '协议',
            dataIndex: 'protocol',
            key: 'protocol',
            render: (text, record) => {
                const title = `${record['ip'] + ':' + record['port']}`
                return (
                    <Tooltip title={title}>
                        <Tag color={PROTOCOL_COLORS[text]}>{text}</Tag>
                    </Tooltip>
                )
            }
        }, {
            title: '网络',
            dataIndex: 'network',
            key: 'network',
            render: (text, record) => {
                return `${record['ip'] + ':' + record['port']}`;
            }
        }, {
            title: '标签',
            dataIndex: 'tags',
            key: 'tags',
            render: tags => {
                if (!isEmpty(tags)) {
                    return this.renderTags(tags);
                }
            }
        }, {
            title: '状态',
            dataIndex: 'active',
            key: 'active',
            render: text => {
                if (text) {
                    return (
                        <Tooltip title='运行中'>
                            <Badge status="processing" text='运行中'/>
                        </Tooltip>
                    )
                } else {
                    return (
                        <Tooltip title='不可用'>
                            <Badge status="error" text='不可用'/>
                        </Tooltip>
                    )
                }
            }
        }, {
            title: '所有者',
            dataIndex: 'ownerName',
            key: 'ownerName'
        }, {
            title: '创建日期',
            dataIndex: 'created',
            key: 'created',
            render: (text, record) => {
                return (
                    <Tooltip title={text}>
                        {dayjs(text).fromNow()}
                    </Tooltip>
                )
            },
            sorter: true,
        },
            {
                title: '操作',
                key: 'action',
                render: (text, record) => {

                    const menu = (
                        <Menu>
                            <Menu.Item key="1">
                                <Button type="text" size='small'
                                        onClick={() => this.update(record.id)}>编辑</Button>
                            </Menu.Item>

                            <Menu.Item key="2">
                                <Button type="text" size='small'
                                        onClick={() => this.copy(record.id)}>复制</Button>
                            </Menu.Item>
                            <Menu.Item key="3">
                                <Button type="text" size='small'
                                        onClick={() => this.connTest(record.id)}>连通性测试</Button>
                            </Menu.Item>
                            <Menu.Item key="4">
                                <Button type="text" size='small'
                                        disabled={!hasPermission(record['owner'])}
                                        onClick={() => {
                                            this.handleSearchByNickname('')
                                                .then(() => {
                                                    this.setState({
                                                        changeOwnerModalVisible: true,
                                                        selected: record,
                                                    })
                                                    this.changeOwnerFormRef
                                                        .current
                                                        .setFieldsValue({
                                                            owner: record['owner']
                                                        })
                                                });

                                        }}>更换所有者</Button>
                            </Menu.Item>
                            <Menu.Divider/>
                            <Menu.Item key="5">
                                <Button type="text" size='small' danger
                                        disabled={!hasPermission(record['owner'])}
                                        onClick={() => this.showDeleteConfirm(record.id, record.name)}>删除</Button>
                            </Menu.Item>
                        </Menu>
                    );

                    const id = record['id'];
                    const protocol = record['protocol'];
                    const name = record['name'];
                    const sshMode = record['sshMode'];
                    let url = '';
                    if (protocol === 'ssh' && (sshMode === 'native' || sshMode === 'naive')) {
                        url = `#/term?assetId=${id}&assetName=${name}`;
                    } else {
                        url = `#/access?assetId=${id}&assetName=${name}&protocol=${protocol}`;
                    }

                    return (
                        <div>
                            <Button type="link" size='small' href={url} target='_blank'>接入</Button>
                            <Dropdown overlay={menu}>
                                <Button type="link" size='small'>
                                    更多 <DownOutlined/>
                                </Button>
                            </Dropdown>
                        </div>
                    )
                },
            }
        ];

        const selectedRowKeys = this.state.selectedRowKeys;
        const rowSelection = {
            selectedRowKeys: this.state.selectedRowKeys,
            onChange: (selectedRowKeys, selectedRows) => {
                this.setState({selectedRowKeys});
            },
        };
        const hasSelected = selectedRowKeys.length > 0;

        return (
            <>
                <Content key='page-content' className="site-layout-background page-content">
                    <div style={{marginBottom: 20}}>
                        <Row justify="space-around" align="middle" gutter={24}>
                            <Col span={4} key={1}>
                                <Title level={3}>资产列表</Title>
                            </Col>
                            <Col span={20} key={2} style={{textAlign: 'right'}}>
                                <Space>

                                    <Search
                                        ref={this.inputRefOfName}
                                        placeholder="资产名称"
                                        allowClear
                                        onSearch={this.handleSearchByName}
                                        style={{width: 200}}
                                    />

                                    <Search
                                        ref={this.inputRefOfIp}
                                        placeholder="资产IP"
                                        allowClear
                                        onSearch={this.handleSearchByIp}
                                        style={{width: 200}}
                                    />

                                    <Select mode="multiple"
                                            allowClear
                                            value={this.state.selectedTags}
                                            placeholder="资产标签" onChange={this.handleTagsChange}
                                            style={{minWidth: 150}}>
                                        {this.state.tags.map(tag => {
                                            if (tag === '-') {
                                                return undefined;
                                            }
                                            return (<Select.Option key={tag}>{tag}</Select.Option>)
                                        })}
                                    </Select>

                                    <Select onChange={this.handleSearchByProtocol}
                                            value={this.state.queryParams.protocol ? this.state.queryParams.protocol : ''}
                                            style={{width: 100}}>
                                        <Select.Option value="">全部协议</Select.Option>
                                        <Select.Option value="rdp">rdp</Select.Option>
                                        <Select.Option value="ssh">ssh</Select.Option>
                                        <Select.Option value="vnc">vnc</Select.Option>
                                        <Select.Option value="telnet">telnet</Select.Option>
                                        <Select.Option value="kubernetes">kubernetes</Select.Option>
                                    </Select>

                                    <Tooltip title='重置查询'>

                                        <Button icon={<UndoOutlined/>} onClick={() => {
                                            this.inputRefOfName.current.setValue('');
                                            this.inputRefOfIp.current.setValue('');
                                            this.setState({
                                                selectedTags: []
                                            })
                                            this.loadTableData({pageIndex: 1, pageSize: 10, protocol: '', tags: ''})
                                        }}>

                                        </Button>
                                    </Tooltip>

                                    <Divider type="vertical"/>
                                    <Tooltip title="批量导入">
                                        <Button type="dashed" icon={<ImportOutlined/>}
                                                onClick={() => {
                                                    this.setState({
                                                        importModalVisible: true
                                                    })
                                                }}>
                                        </Button>
                                    </Tooltip>
                                    <Tooltip title="新增">
                                        <Button icon={<PlusOutlined/>}
                                                onClick={() => this.showModal('新增资产', {})}
                                        >
                                        </Button>
                                    </Tooltip>


                                    <Tooltip title="刷新列表">
                                        <Button icon={<SyncOutlined/>} onClick={() => {
                                            this.loadTableData(this.state.queryParams)
                                        }}>

                                        </Button>
                                    </Tooltip>

                                    <Tooltip title="批量删除">
                                        <Button type="primary" danger disabled={!hasSelected} icon={<DeleteOutlined/>}
                                                loading={this.state.delBtnLoading}
                                                onClick={() => {
                                                    const content = <div>
                                                        您确定要删除选中的<Text style={{color: '#1890FF'}}
                                                                       strong>{this.state.selectedRowKeys.length}</Text>条记录吗?
                                                    </div>;
                                                    confirm({
                                                        icon: <ExclamationCircleOutlined/>,
                                                        content: content,
                                                        onOk: () => {
                                                            this.batchDelete()
                                                        },
                                                        onCancel() {

                                                        },
                                                    });
                                                }}>

                                        </Button>
                                    </Tooltip>

                                </Space>
                            </Col>
                        </Row>
                    </div>

                    <Table key='assets-table'
                           rowSelection={rowSelection}
                           dataSource={this.state.items}
                           columns={columns}
                           position={'both'}
                           pagination={{
                               showSizeChanger: true,
                               current: this.state.queryParams.pageIndex,
                               pageSize: this.state.queryParams.pageSize,
                               onChange: this.handleChangPage,
                               onShowSizeChange: this.handleChangPage,
                               total: this.state.total,
                               showTotal: total => `总计 ${total} 条`
                           }}
                           loading={this.state.loading}
                           onChange={this.handleTableChange}
                    />

                    {
                        this.state.modalVisible ?
                            <AssetModal
                                visible={this.state.modalVisible}
                                title={this.state.modalTitle}
                                handleOk={this.handleOk}
                                handleCancel={this.handleCancelModal}
                                confirmLoading={this.state.modalConfirmLoading}
                                credentials={this.state.credentials}
                                tags={this.state.tags}
                                model={this.state.model}
                            />
                            : null
                    }

                    {
                        this.state.importModalVisible ?
                            <Modal title="资产导入" visible={true}
                                   onOk={() => {
                                       const formData = new FormData();
                                       formData.append("file", this.state.fileList[0]);

                                       let headers = getHeaders();
                                       headers['Content-Type'] = 'multipart/form-data';

                                       axios
                                           .post(server + "/assets/import", formData, {
                                               headers: headers
                                           })
                                           .then((resp) => {
                                               console.log("上传成功", resp);
                                               this.setState({
                                                   importModalVisible: false
                                               })
                                               let result = resp.data;
                                               if (result['code'] === 1) {
                                                   let data = result['data'];
                                                   let successCount = data['successCount'];
                                                   let errorCount = data['errorCount'];
                                                   if (errorCount === 0) {
                                                       notification['success']({
                                                           message: '导入资产成功',
                                                           description: '共导入成功' + successCount + '条资产。',
                                                       });
                                                   } else {
                                                       notification['info']({
                                                           message: '导入资产完成',
                                                           description: `共导入成功${successCount}条资产,失败${errorCount}条资产。`,
                                                       });
                                                   }
                                               } else {
                                                   notification['error']({
                                                       message: '导入资产失败',
                                                       description: result['message'],
                                                   });
                                               }
                                               this.loadTableData();
                                           });
                                   }}
                                   onCancel={() => {
                                       this.setState({
                                           importModalVisible: false
                                       })
                                   }}
                                   okButtonProps={{
                                       disabled: this.state.fileList.length === 0
                                   }}
                            >
                                <Space>
                                    <Upload
                                        maxCount={1}
                                        onRemove={file => {
                                            this.setState(state => {
                                                const index = state.fileList.indexOf(file);
                                                const newFileList = state.fileList.slice();
                                                newFileList.splice(index, 1);
                                                return {
                                                    fileList: newFileList,
                                                };
                                            });
                                        }}
                                        beforeUpload={(file) => {
                                            this.setState(state => ({
                                                fileList: [file],
                                            }));
                                            return false;
                                        }}
                                        fileList={this.state.fileList}
                                    >
                                        <Button icon={<UploadOutlined/>}>选择csv文件</Button>
                                    </Upload>

                                    <Button type="primary" onClick={() => {

                                        let csvString = 'name,ssh,127.0.0.1,22,username,password,privateKey,passphrase,description,tag1|tag2|tag3';
                                        //前置的"\uFEFF"为“零宽不换行空格”,可处理中文乱码问题
                                        const blob = new Blob(["\uFEFF" + csvString], {type: 'text/csv;charset=gb2312;'});
                                        let a = document.createElement('a');
                                        a.download = 'sample.csv';
                                        a.href = URL.createObjectURL(blob);
                                        a.click();
                                    }}>
                                        下载样本文件
                                    </Button>
                                </Space>

                            </Modal>
                            : undefined
                    }

                    <Modal title={<Text>更换资源「<strong style={{color: '#1890ff'}}>{this.state.selected['name']}</strong>」的所有者
                    </Text>}
                           visible={this.state.changeOwnerModalVisible}
                           confirmLoading={this.state.changeOwnerConfirmLoading}

                           onOk={() => {
                               this.setState({
                                   changeOwnerConfirmLoading: true
                               });

                               let changeOwnerModalVisible = false;
                               this.changeOwnerFormRef
                                   .current
                                   .validateFields()
                                   .then(async values => {
                                       let result = await request.post(`/assets/${this.state.selected['id']}/change-owner?owner=${values['owner']}`);
                                       if (result['code'] === 1) {
                                           message.success('操作成功');
                                           this.loadTableData();
                                       } else {
                                           message.error(result['message'], 10);
                                           changeOwnerModalVisible = true;
                                       }
                                   })
                                   .catch(info => {

                                   })
                                   .finally(() => {
                                       this.setState({
                                           changeOwnerConfirmLoading: false,
                                           changeOwnerModalVisible: changeOwnerModalVisible
                                       })
                                   });
                           }}
                           onCancel={() => {
                               this.setState({
                                   changeOwnerModalVisible: false
                               })
                           }}
                    >

                        <Form ref={this.changeOwnerFormRef}>

                            <Form.Item name='owner' rules={[{required: true, message: '请选择所有者'}]}>
                                <Select
                                    showSearch
                                    placeholder='请选择所有者'
                                    onSearch={this.handleSearchByNickname}
                                    filterOption={false}
                                >
                                    {this.state.users.map(d => <Select.Option key={d.id}
                                                                              value={d.id}>{d.nickname}</Select.Option>)}
                                </Select>
                            </Form.Item>
                            <Alert message="更换资产所有者不会影响授权凭证的所有者" type="info" showIcon/>

                        </Form>
                    </Modal>
                </Content>
            </>
        );
    }
Example #24
Source File: AccessGateway.js    From next-terminal with GNU Affero General Public License v3.0 4 votes vote down vote up
render() {

        const columns = [{
            title: '序号',
            dataIndex: 'id',
            key: 'id',
            render: (id, record, index) => {
                return index + 1;
            }
        }, {
            title: '名称',
            dataIndex: 'name',
            key: 'name',
            render: (name, record) => {
                let short = name;
                if (short && short.length > 20) {
                    short = short.substring(0, 20) + " ...";
                }

                if (hasPermission(record['owner'])) {
                    return (
                        <Button type="link" size='small' onClick={() => this.update(record['id'])}>
                            <Tooltip placement="topLeft" title={name}>
                                {short}
                            </Tooltip>
                        </Button>
                    );
                } else {
                    return (
                        <Tooltip placement="topLeft" title={name}>
                            {short}
                        </Tooltip>
                    );
                }
            },
            sorter: true,
        }, {
            title: 'IP',
            dataIndex: 'ip',
            key: 'ip',
            sorter: true,
        }, {
            title: '端口',
            dataIndex: 'port',
            key: 'port',
        }, {
            title: '账户类型',
            dataIndex: 'accountType',
            key: 'accountType',
            render: (accountType) => {
                if (accountType === 'private-key') {
                    return (
                        <Tag color="green">密钥</Tag>
                    );
                } else {
                    return (
                        <Tag color="red">密码</Tag>
                    );
                }
            }
        }, {
            title: '授权账户',
            dataIndex: 'username',
            key: 'username',
        }, {
            title: '状态',
            dataIndex: 'connected',
            key: 'connected',
            render: (text, record) => {
                if (text) {
                    return (
                        <Tooltip title='连接成功'>
                            <Badge status="success" text='已连接'/>
                        </Tooltip>
                    )
                } else {
                    return (
                        <Tooltip title={record['message']}>
                            <Badge status="error" text='已断开'/>
                        </Tooltip>
                    )
                }
            }
        }, {
            title: '创建时间',
            dataIndex: 'created',
            key: 'created',
            render: (text, record) => {
                return (
                    <Tooltip title={text}>
                        {dayjs(text).fromNow()}
                    </Tooltip>
                )
            },
            sorter: true,
        }, {
            title: '操作',
            key: 'action',
            render: (text, record, index) => {

                return (
                    <div>
                        <Button type="link" size='small'
                                onClick={() => this.update(record['id'])}>编辑</Button>

                        <Button type="text" size='small' danger
                                onClick={() => this.showDeleteConfirm(record.id, record.name)}>删除</Button>

                    </div>
                )
            },
        }
        ];

        const selectedRowKeys = this.state.selectedRowKeys;
        const rowSelection = {
            selectedRowKeys: this.state.selectedRowKeys,
            onChange: (selectedRowKeys, selectedRows) => {
                this.setState({selectedRowKeys});
            },
        };
        const hasSelected = selectedRowKeys.length > 0;

        return (
            <>
                <Content className="site-layout-background page-content">

                    <div style={{marginBottom: 20}}>
                        <Row justify="space-around" align="middle" gutter={24}>
                            <Col span={12} key={1}>
                                <Title level={3}>接入网关</Title>
                            </Col>
                            <Col span={12} key={2} style={{textAlign: 'right'}}>
                                <Space>
                                    <Search
                                        ref={this.inputRefOfName}
                                        placeholder="名称"
                                        allowClear
                                        onSearch={this.handleSearchByName}
                                    />

                                    <Search
                                        ref={this.inputRefOfIp}
                                        placeholder="IP"
                                        allowClear
                                        onSearch={this.handleSearchByIp}
                                    />

                                    <Tooltip title='重置查询'>

                                        <Button icon={<UndoOutlined/>} onClick={() => {
                                            this.inputRefOfName.current.setValue('');
                                            this.inputRefOfIp.current.setValue('');
                                            this.loadTableData({
                                                pageIndex: 1,
                                                pageSize: 10,
                                                name: '',
                                                ip: '',
                                                content: ''
                                            })
                                        }}>

                                        </Button>
                                    </Tooltip>

                                    <Divider type="vertical"/>

                                    <Tooltip title="新增">
                                        <Button type="dashed" icon={<PlusOutlined/>}
                                                onClick={() => this.showModal('新增接入网关', {})}>

                                        </Button>
                                    </Tooltip>

                                    <Tooltip title="刷新列表">
                                        <Button icon={<SyncOutlined/>} onClick={() => {
                                            this.loadTableData(this.state.queryParams)
                                        }}>

                                        </Button>
                                    </Tooltip>


                                    <Tooltip title="批量删除">
                                        <Button type="primary" danger disabled={!hasSelected} icon={<DeleteOutlined/>}
                                                loading={this.state.delBtnLoading}
                                                onClick={() => {
                                                    const content = <div>
                                                        您确定要删除选中的<Text style={{color: '#1890FF'}}
                                                                       strong>{this.state.selectedRowKeys.length}</Text>条记录吗?
                                                    </div>;
                                                    confirm({
                                                        icon: <ExclamationCircleOutlined/>,
                                                        content: content,
                                                        onOk: () => {
                                                            this.batchDelete()
                                                        },
                                                        onCancel() {

                                                        },
                                                    });
                                                }}>

                                        </Button>
                                    </Tooltip>

                                </Space>
                            </Col>
                        </Row>
                    </div>

                    <Table
                        rowSelection={rowSelection}
                        dataSource={this.state.items}
                        columns={columns}
                        position={'both'}
                        pagination={{
                            showSizeChanger: true,
                            current: this.state.queryParams.pageIndex,
                            pageSize: this.state.queryParams.pageSize,
                            onChange: this.handleChangPage,
                            onShowSizeChange: this.handleChangPage,
                            total: this.state.total,
                            showTotal: total => `总计 ${total} 条`
                        }}
                        loading={this.state.loading}
                        onChange={this.handleTableChange}
                    />

                    {
                        this.state.modalVisible ?
                            <AccessGatewayModal
                                visible={this.state.modalVisible}
                                title={this.state.modalTitle}
                                handleOk={this.handleOk}
                                handleCancel={this.handleCancelModal}
                                confirmLoading={this.state.modalConfirmLoading}
                                model={this.state.model}
                            >
                            </AccessGatewayModal> : undefined
                    }
                </Content>
            </>
        );
    }
Example #25
Source File: TopicConsumerGroupOffset.js    From kafka-map with Apache License 2.0 4 votes vote down vote up
render() {

        const columns = [{
            title: 'Partition',
            dataIndex: 'partition',
            key: 'partition',
            defaultSortOrder: 'ascend',
            sorter: (a, b) => a['partition'] - b['partition'],
        }, {
            title: 'Beginning Offset',
            dataIndex: 'beginningOffset',
            key: 'beginningOffset',
            sorter: (a, b) => a['beginningOffset'] - b['beginningOffset'],
        }, {
            title: 'End Offset',
            dataIndex: 'endOffset',
            key: 'endOffset',
            sorter: (a, b) => a['endOffset'] - b['endOffset'],
        }, {
            title: 'Consumer Offset',
            dataIndex: 'consumerOffset',
            key: 'consumerOffset',
            sorter: (a, b) => a['consumerOffset'] - b['consumerOffset'],
        }, {
            title: 'Lag',
            dataIndex: 'lag',
            key: 'lag',
            sorter: (a, b) => a['lag'] - b['lag'],
            render: (lag, record, index) => {
                return record['endOffset'] - record['consumerOffset']
            }
        }, {
            title: 'Operate',
            key: 'action',
            render: (text, record, index) => {
                return (
                    <div>
                        <Button type="link" size='small' onClick={() => {
                            this.setState({
                                resetOffsetVisible: true,
                                selectedRow: record
                            })
                        }}>Reset Offset</Button>
                    </div>
                )
            },
        }];

        return (
            <div>
                <div style={{marginBottom: 20}}>
                    <Row justify="space-around" align="middle" gutter={24}>
                        <Col span={20} key={1}>
                            <Title level={3}><FormattedMessage id="consume-detail" /></Title>
                        </Col>
                        <Col span={4} key={2} style={{textAlign: 'right'}}>
                            <Space>
                                <Tooltip title={<FormattedMessage id="refresh" />}>
                                    <Button icon={<SyncOutlined/>} onClick={() => {
                                        let clusterId = this.state.clusterId;
                                        let topic = this.state.topic;
                                        let groupId = this.state.groupId;
                                        this.loadItems(clusterId, topic, groupId);
                                    }}>

                                    </Button>
                                </Tooltip>
                            </Space>
                        </Col>
                    </Row>
                </div>

                <Table key='table'
                       dataSource={this.state.items}
                       columns={columns}
                       position={'both'}
                       pagination={{
                           showSizeChanger: true,
                           total: this.state.items.length,
                           showTotal: total => <FormattedMessage id="total-items" values={{total}}/>
                       }}
                       loading={this.state.loading}
                />

                <Drawer
                    title={'Partition: ' + this.state.selectedRow['partition']}
                    width={window.innerWidth * 0.3}
                    closable={true}
                    onClose={() => {
                        this.setState({
                            resetOffsetVisible: false
                        })
                    }}
                    visible={this.state.resetOffsetVisible}
                    footer={
                        <div
                            style={{
                                textAlign: 'right',
                            }}
                        >
                            <Button
                                loading={this.state.resetting}
                                onClick={() => {
                                    this.form.current
                                        .validateFields()
                                        .then(async values => {
                                            this.setState({
                                                resetting: true
                                            })
                                            let topic = this.state.topic;
                                            let groupId = this.state.groupId;
                                            let clusterId = this.state.clusterId;

                                            await request.put(`/topics/${topic}/consumerGroups/${groupId}/offset?clusterId=${clusterId}`, values);
                                            this.form.current.resetFields();
                                            this.setState({
                                                resetOffsetVisible: false
                                            })
                                            this.loadItems(clusterId, topic, groupId);
                                        })
                                        .catch(info => {

                                        }).finally(() => this.setState({resetting: false}));
                                }} type="primary">
                                重置
                            </Button>
                        </div>
                    }
                >
                    <Alert message={<FormattedMessage id="reset-warning" />} description={<FormattedMessage id="reset-warning-description" />} type="warning" showIcon
                           style={{marginBottom: 16}}/>

                    <Form ref={this.form}>
                        <Form.Item label={<FormattedMessage id="reset-partition" />} name='seek' rules={[{required: true}]}>
                            <Radio.Group onChange={(e) => {
                                let seek = e.target.value;
                                this.setState({
                                    'seek': seek
                                })
                            }}>
                                <Radio value={'end'}><FormattedMessage id="latest" /></Radio>
                                <Radio value={'beginning'}><FormattedMessage id="earliest" /></Radio>
                                <Radio value={'custom'}><FormattedMessage id="customization" /></Radio>
                            </Radio.Group>
                        </Form.Item>

                        {
                            this.state.seek === 'custom' ?
                                <Form.Item label="offset" name='offset' rules={[{required: true}]}>
                                    <InputNumber min={0}/>
                                </Form.Item> : undefined
                        }
                    </Form>
                </Drawer>
            </div>
        );
    }
Example #26
Source File: Topic.js    From kafka-map with Apache License 2.0 4 votes vote down vote up
render() {

        const columns = [{
                title: <FormattedMessage id="index" />,
                dataIndex: 'index',
                key: 'index',
                render: (id, record, index) => {
                    return index + 1;
                }
            }, {
                title: <FormattedMessage id="name" />,
                dataIndex: 'name',
                key: 'name',
                defaultSortOrder: 'ascend',
                sorter: (a, b) => a.name.localeCompare(b.name),
                width: window.innerWidth * 0.3,
                render: (name, record, index) => {
                    return <Link to={`/topic-info?clusterId=${record['clusterId']}&topic=${name}`}>
                        {name}
                    </Link>
                }
            }, {
                title: <FormattedMessage id="partitions" />,
                dataIndex: 'partitionsCount',
                key: 'partitionsCount',
                sorter: (a, b) => a['partitionsCount'] - b['partitionsCount'],
            }, {
                title: <FormattedMessage id="replicas" />,
                dataIndex: 'replicaCount',
                key: 'replicaCount',
                sorter: (a, b) => a['replicaCount'] - b['replicaCount'],
            }, {
                title: <FormattedMessage id="average-log-size" />,
                dataIndex: 'x',
                key: 'x',
                sorter: (a, b) => a['totalLogSize'] / a['replicaCount'] - b['totalLogSize'] / b['replicaCount'],
                render: (x, record) => {
                    if (record['totalLogSize'] < 0) {
                        return '不支持';
                    }
                    return renderSize(record['totalLogSize'] / record['replicaCount'])
                }
            }, {
                title: <FormattedMessage id="log-size" />,
                dataIndex: 'totalLogSize',
                key: 'totalLogSize',
                sorter: (a, b) => a['totalLogSize'] - b['totalLogSize'],
                render: (totalLogSize) => {
                    if (totalLogSize < 0) {
                        return '不支持';
                    } else {
                        return renderSize(totalLogSize);
                    }
                }
            },
                {
                    title: <FormattedMessage id="operate" />,
                    key: 'action',
                    render: (text, record, index) => {
                        return (
                            <div>

                                <Link to={`/topic-data?clusterId=${this.state.clusterId}&topic=${record['name']}`}>
                                    <Button key="1" type="link" size='small'>
                                        <FormattedMessage id="consume-message" />
                                    </Button>
                                </Link>

                                <Button type="link" size='small' onClick={() => {
                                    this.setState({
                                        createPartitionVisible: true,
                                        selectedRow: record
                                    })
                                }}><FormattedMessage id="topic-alter" /></Button>

                                <Popconfirm
                                    title={<FormattedMessage id="delete-confirm" />}
                                    onConfirm={() => this.delete(record['name'], index)}
                                >
                                    <Button type="text" size='small' danger
                                            loading={this.state.items[index]['deleting']}><FormattedMessage id="delete" /></Button>
                                </Popconfirm>

                            </div>
                        )
                    },
                }
            ]
        ;

        return (
            <div>
                <div className='kd-page-header'>
                    <PageHeader
                        className="site-page-header"
                        onBack={() => {
                            this.props.history.goBack();
                        }}
                        subTitle={<FormattedMessage id="topic-management" />}
                        title={this.state.clusterName}
                    />
                </div>

                <div className='kd-content'>
                    <div style={{marginBottom: 20}}>
                        <Row justify="space-around" align="middle" gutter={24}>
                            <Col span={4} key={1}>
                                <Title level={3}>Topic</Title>
                            </Col>
                            <Col span={20} key={2} style={{textAlign: 'right'}}>
                                <Space>
                                    <Search
                                        ref={this.inputRefOfName}
                                        placeholder="topic"
                                        allowClear
                                        onSearch={this.handleSearchByName}
                                    />
                                    <Tooltip title={<FormattedMessage id="reset" />}>

                                        <Button icon={<UndoOutlined/>} onClick={() => {
                                            this.inputRefOfName.current.setValue('');
                                            this.loadTableData({
                                                pageIndex: 1,
                                                pageSize: 10,
                                                clusterId: this.state.clusterId,
                                                name: ''
                                            })
                                        }}>

                                        </Button>
                                    </Tooltip>

                                    <Divider type="vertical"/>

                                    <Tooltip title={<FormattedMessage id="create-topic" />}>
                                        <Button type="dashed" icon={<PlusOutlined/>}
                                                onClick={() => this.showModal(<FormattedMessage id="create-topic" />)}>

                                        </Button>
                                    </Tooltip>

                                    <Tooltip title={<FormattedMessage id="refresh" />}>
                                        <Button icon={<SyncOutlined/>} onClick={() => {
                                            this.loadTableData(this.state.queryParams)
                                        }}>

                                        </Button>
                                    </Tooltip>

                                </Space>
                            </Col>
                        </Row>
                    </div>

                    <Table
                        rowKey='name'
                        dataSource={this.state.items}
                        columns={columns}
                        position={'both'}
                        size={'middle'}
                        loading={this.state.loading}
                        pagination={{
                            showSizeChanger: true,
                            total: this.state.items.length,
                            showTotal: total => <FormattedMessage id="total-items" values={{total}}/>
                        }}
                    />

                    {
                        this.state.modalVisible ?
                            <TopicModal
                                title={this.state.modalTitle}
                                handleOk={this.handleOk}
                                handleCancel={this.handleCancelModal}
                                confirmLoading={this.state.modalConfirmLoading}
                                model={null}
                                brokerCount={this.state.brokerCount}
                            /> : undefined
                    }

                    <Modal title={<FormattedMessage id="topic-alter" />}
                           visible={this.state.createPartitionVisible}
                           confirmLoading={this.state.createPartitionConfirmLoading}
                           onOk={() => {
                               this.form.current
                                   .validateFields()
                                   .then(async values => {
                                       this.setState({
                                           createPartitionConfirmLoading: true
                                       })
                                       let topic = this.state.selectedRow['name'];
                                       let clusterId = this.state.clusterId;

                                       await request.post(`/topics/${topic}/partitions?clusterId=${clusterId}&totalCount=${values['totalCount']}`);
                                       this.form.current.resetFields();
                                       this.setState({
                                           createPartitionVisible: false
                                       })
                                       this.loadTableData();
                                   })
                                   .catch(info => {

                                   }).finally(() => this.setState({createPartitionConfirmLoading: false}));
                           }}
                           onCancel={() => {
                               this.setState({
                                   createPartitionVisible: false
                               })
                           }}>
                        <Form ref={this.form} {...formItemLayout}>
                            <Form.Item label={<FormattedMessage id="numPartitions" />} name='totalCount' rules={[{required: true}]}>
                                <InputNumber min={this.state.selectedRow['partitionsCount']}
                                             placeholder={"Can't be less than the current: " + this.state.selectedRow["partitionsCount"]}
                                             style={{width: '100%'}}/>
                            </Form.Item>
                        </Form>
                    </Modal>

                </div>
            </div>

        );
    }
Example #27
Source File: ConsumerGroup.js    From kafka-map with Apache License 2.0 4 votes vote down vote up
render() {

        const columns = [{
                title: <FormattedMessage id="index"/>,
                dataIndex: 'id',
                key: 'id',
                render: (id, record, index) => {
                    return index + 1;
                }
            }, {
                title: <FormattedMessage id="name"/>,
                dataIndex: 'groupId',
                key: 'groupId',
                defaultSortOrder: 'ascend',
                sorter: (a, b) => a.groupId.localeCompare(b.groupId),
                width: window.innerWidth * 0.3,
                render: (groupId, record, index) => {
                    return <Link to={`/consumer-group-info?clusterId=${this.state.clusterId}&groupId=${groupId}`}>
                        {groupId}
                    </Link>
                }
            }, {
                title: <FormattedMessage id="topic-count"/>,
                dataIndex: 'topicCount',
                key: 'topicCount',
                sorter: (a, b) => a['topics'].length - b['topics'].length,
                render: (topicCount, record, index) => {
                    const content = <List
                        size="small"
                        dataSource={record['topics']}
                        renderItem={item => <List.Item><Link
                            to={`/topic-info?clusterId=${this.state.clusterId}&topic=${item}`}>{item}</Link></List.Item>}
                    />

                    return <Popover content={content} title={<FormattedMessage id="topic-list"/>}>
                        <Button type="link" size='small'>{record['topics'].length}</Button>
                    </Popover>
                }

            },
                {
                    title: <FormattedMessage id="operate"/>,
                    key: 'action',
                    render: (text, record, index) => {
                        return (
                            <div>
                                <Popconfirm
                                    title={<FormattedMessage id="delete-confirm"/>}
                                    onConfirm={() => this.delete(record['groupId'], index)}
                                >
                                    <Button type="text" size='small' danger
                                            loading={this.state.items[index]['deleting']}><FormattedMessage
                                        id="delete"/></Button>
                                </Popconfirm>


                            </div>
                        )
                    },
                }
            ]
        ;

        return (
            <div>
                <div className='kd-page-header'>
                    <PageHeader
                        className="site-page-header"
                        onBack={() => {
                            this.props.history.goBack();
                        }}
                        subTitle={<FormattedMessage id="consumer-group-management"/>}
                        title={this.state.clusterName}
                    />
                </div>

                <div className='kd-content'>
                    <div style={{marginBottom: 20}}>
                        <Row justify="space-around" align="middle" gutter={24}>
                            <Col span={8} key={1}>
                                <Title level={3}>Consumer Group</Title>
                            </Col>
                            <Col span={16} key={2} style={{textAlign: 'right'}}>
                                <Space>
                                    <Search
                                        ref={this.inputRefOfName}
                                        placeholder="Group ID"
                                        allowClear
                                        onSearch={this.handleSearchByName}
                                    />
                                    <Tooltip title={<FormattedMessage id="reset"/>}>

                                        <Button icon={<UndoOutlined/>} onClick={() => {
                                            this.inputRefOfName.current.setValue('');
                                            this.loadTableData({
                                                pageIndex: 1,
                                                pageSize: 10,
                                                clusterId: this.state.clusterId,
                                                name: ''
                                            })
                                        }}>

                                        </Button>
                                    </Tooltip>

                                    <Divider type="vertical"/>

                                    <Tooltip title={<FormattedMessage id="refresh"/>}>
                                        <Button icon={<SyncOutlined/>} onClick={() => {
                                            this.loadTableData(this.state.queryParams)
                                        }}>

                                        </Button>
                                    </Tooltip>
                                </Space>
                            </Col>
                        </Row>
                    </div>

                    <Table
                        rowKey='groupId'
                        dataSource={this.state.items}
                        columns={columns}
                        position={'both'}
                        size={'middle'}
                        loading={this.state.loading}
                        pagination={{
                            showSizeChanger: true,
                            total: this.state.items.length,
                            showTotal: total => <FormattedMessage id="total-items" values={{total}}/>
                        }}
                    />

                </div>
            </div>

        );
    }
Example #28
Source File: Cluster.js    From kafka-map with Apache License 2.0 4 votes vote down vote up
render() {

        const columns = [{
            title: <FormattedMessage id="index"/>,
            dataIndex: 'id',
            key: 'id',
            render: (id, record, index) => {
                return index + 1;
            }
        }, {
            title: <FormattedMessage id="name"/>,
            dataIndex: 'name',
            key: 'name',
            render: (name, record) => {
                let short = name;
                if (short && short.length > 30) {
                    short = short.substring(0, 30) + " ...";
                }
                return (
                    <Tooltip placement="topLeft" title={name}>
                        {short}
                    </Tooltip>
                );
            },
            sorter: true,
        }, {
            title: <FormattedMessage id="servers"/>,
            dataIndex: 'servers',
            key: 'servers',
        }, {
            title: <FormattedMessage id="delay-message"/>,
            dataIndex: 'delayMessageStatus',
            key: 'delayMessageStatus',
            render: (delayMessageStatus, record, index) => {
                return <Popover content={content}>
                    <Switch checked={delayMessageStatus === 'enabled'}
                            onChange={async (checked) => {
                                let url = `/clusters/${record['id']}/disableDelayMessage`;
                                if (checked) {
                                    url = `/clusters/${record['id']}/enableDelayMessage`;
                                }
                                await request.post(url);
                                this.loadTableData()
                            }
                            }/>
                </Popover>

            }
        }, {
            title: <FormattedMessage id="topic"/>,
            dataIndex: 'topicCount',
            key: 'topicCount',
            render: (topicCount, record, index) => {
                return <Link
                    to={`/topic?clusterId=${record['id']}&clusterName=${record['name']}&brokerCount=${record['brokerCount']}`}>
                    {topicCount}
                </Link>
            }
        }, {
            title: <FormattedMessage id="broker"/>,
            dataIndex: 'brokerCount',
            key: 'brokerCount',
            render: (brokerCount, record, index) => {
                return <Link to={`/broker?clusterId=${record['id']}&clusterName=${record['name']}`}>
                    {brokerCount}
                </Link>
            }
        }, {
            title: <FormattedMessage id="consumer-group"/>,
            dataIndex: 'consumerCount',
            key: 'consumerCount',
            render: (consumerCount, record, index) => {
                return <Link to={`/consumer-group?clusterId=${record['id']}&clusterName=${record['name']}`}>
                    {consumerCount}
                </Link>
            }
        }, {
            title: <FormattedMessage id="created"/>,
            dataIndex: 'created',
            key: 'created',
            render: (text, record) => {
                return (
                    <Tooltip title={text}>
                        {dayjs(text).fromNow()}
                    </Tooltip>
                )
            },
            sorter: true,
        },
            {
                title: <FormattedMessage id="operate"/>,
                key: 'action',
                render: (text, record, index) => {
                    return (
                        <div>
                            <Button type="link" size='small' onClick={() => {
                                this.showModal(<FormattedMessage id="edit"/>, record)
                            }}><FormattedMessage id="edit"/></Button>
                            <Popconfirm
                                title={<FormattedMessage id="delete-confirm"/>}
                                onConfirm={() => this.delete(record['id'])}
                            >
                                <Button type="text" size='small' danger><FormattedMessage id="delete"/></Button>
                            </Popconfirm>
                        </div>
                    )
                },
            }
        ];

        const selectedRowKeys = this.state.selectedRowKeys;
        const rowSelection = {
            selectedRowKeys: this.state.selectedRowKeys,
            onChange: (selectedRowKeys, selectedRows) => {
                this.setState({selectedRowKeys});
            },
        };
        const hasSelected = selectedRowKeys.length > 0;

        return (
            <div className='kd-content'>
                <div style={{marginBottom: 20}}>

                    <Row justify="space-around" align="middle" gutter={24}>
                        <Col span={12} key={1}>
                            <Title level={3}><FormattedMessage id="cluster"/></Title>
                        </Col>
                        <Col span={12} key={2} style={{textAlign: 'right'}}>
                            <Space>
                                <Search
                                    ref={this.inputRefOfName}
                                    placeholder={'name'}
                                    allowClear
                                    onSearch={this.handleSearchByName}
                                />

                                <Tooltip title={<FormattedMessage id="reset"/>}>

                                    <Button icon={<UndoOutlined/>} onClick={() => {
                                        this.inputRefOfName.current.setValue('');
                                        this.loadTableData({pageIndex: 1, pageSize: 10, name: ''})
                                    }}>

                                    </Button>
                                </Tooltip>

                                <Divider type="vertical"/>

                                <Tooltip title={<FormattedMessage id="import-cluster"/>}>
                                    <Button type="dashed" icon={<PlusOutlined/>}
                                            onClick={() => this.showModal(<FormattedMessage id="import-cluster"/>)}>

                                    </Button>
                                </Tooltip>

                                <Tooltip title={<FormattedMessage id="refresh"/>}>
                                    <Button icon={<SyncOutlined/>} onClick={() => {
                                        this.loadTableData(this.state.queryParams)
                                    }}>

                                    </Button>
                                </Tooltip>

                                <Tooltip title={<FormattedMessage id="batch-delete"/>}>
                                    <Button type="primary" danger disabled={!hasSelected} icon={<DeleteOutlined/>}
                                            loading={this.state.delBtnLoading}
                                            onClick={() => {
                                                const content = <div>
                                                    Are you sure delete <Text style={{color: '#1890FF'}}
                                                                              strong>{this.state.selectedRowKeys.length}</Text> items?
                                                </div>;
                                                confirm({
                                                    icon: <ExclamationCircleOutlined/>,
                                                    content: content,
                                                    onOk: () => {
                                                        this.batchDelete()
                                                    },
                                                    onCancel() {

                                                    },
                                                });
                                            }}>

                                    </Button>
                                </Tooltip>

                            </Space>
                        </Col>
                    </Row>
                </div>

                <Table
                    rowSelection={rowSelection}
                    rowKey='id'
                    dataSource={this.state.items}
                    columns={columns}
                    position={'both'}
                    pagination={{
                        showSizeChanger: true,
                        current: this.state.queryParams.pageIndex,
                        pageSize: this.state.queryParams.pageSize,
                        onChange: this.handleChangPage,
                        onShowSizeChange: this.handleChangPage,
                        total: this.state.total,
                        showTotal: total => {
                            return <FormattedMessage id="total-items" values={{total: total}}/>
                        }
                    }}
                    loading={this.state.loading}
                />

                {
                    this.state.modalVisible ?
                        <ClusterModal
                            title={this.state.modalTitle}
                            handleOk={this.handleOk}
                            handleCancel={this.handleCancelModal}
                            confirmLoading={this.state.modalConfirmLoading}
                            model={this.state.model}
                        /> : undefined
                }
            </div>
        );
    }
Example #29
Source File: ExampleUI.jsx    From moonshot with MIT License 4 votes vote down vote up
export default function ExampleUI({purpose, setPurposeEvents, address, mainnetProvider, userProvider, localProvider, yourLocalBalance, price, tx, readContracts, writeContracts }) {

  const [newPurpose, setNewPurpose] = useState("loading...");

  return (
    <div>
      {/*
        ⚙️ Here is an example UI that displays and sets the purpose in your smart contract:
      */}
      <div style={{border:"1px solid #cccccc", padding:16, width:400, margin:"auto",marginTop:64}}>
        <h2>Example UI:</h2>

        <h4>purpose: {purpose}</h4>

        <Divider/>

        <div style={{margin:8}}>
          <Input onChange={(e)=>{setNewPurpose(e.target.value)}} />
          <Button onClick={()=>{
            console.log("newPurpose",newPurpose)
            /* look how you call setPurpose on your contract: */
            tx( writeContracts.YourContract.setPurpose(newPurpose) )
          }}>Set Purpose</Button>
        </div>


        <Divider />

        Your Address:
        <Address
            address={address}
            ensProvider={mainnetProvider}
            fontSize={16}
        />

        <Divider />

        ENS Address Example:
        <Address
          address={"0x34aA3F359A9D614239015126635CE7732c18fDF3"} /* this will show as austingriffith.eth */
          ensProvider={mainnetProvider}
          fontSize={16}
        />

        <Divider/>

        {  /* use formatEther to display a BigNumber: */ }
        <h2>Your Balance: {yourLocalBalance?formatEther(yourLocalBalance):"..."}</h2>

        <div>OR</div>

        <Balance
          address={address}
          provider={localProvider}
          price={price}
        />

        <Divider/>

        <div>?  Example Whale Balance:</div>

        <Balance
          balance={parseEther("1000")}
          provider={localProvider}
          price={price}
        />

        <Divider/>


        {  /* use formatEther to display a BigNumber: */ }
        <h2>Your Balance: {yourLocalBalance?formatEther(yourLocalBalance):"..."}</h2>

        <Divider/>



        Your Contract Address:
        <Address
            address={readContracts?readContracts.YourContract.address:readContracts}
            ensProvider={mainnetProvider}
            fontSize={16}
        />

        <Divider />

        <div style={{margin:8}}>
          <Button onClick={()=>{
            /* look how you call setPurpose on your contract: */
            tx( writeContracts.YourContract.setPurpose("? Cheers") )
          }}>Set Purpose to "? Cheers"</Button>
        </div>

        <div style={{margin:8}}>
          <Button onClick={()=>{
            /*
              you can also just craft a transaction and send it to the tx() transactor
              here we are sending value straight to the contract's address:
            */
            tx({
              to: writeContracts.YourContract.address,
              value: parseEther("0.001")
            });
            /* this should throw an error about "no fallback nor receive function" until you add it */
          }}>Send Value</Button>
        </div>

        <div style={{margin:8}}>
          <Button onClick={()=>{
            /* look how we call setPurpose AND send some value along */
            tx( writeContracts.YourContract.setPurpose("? Paying for this one!",{
              value: parseEther("0.001")
            }))
            /* this will fail until you make the setPurpose function payable */
          }}>Set Purpose With Value</Button>
        </div>


        <div style={{margin:8}}>
          <Button onClick={()=>{
            /* you can also just craft a transaction and send it to the tx() transactor */
            tx({
              to: writeContracts.YourContract.address,
              value: parseEther("0.001"),
              data: writeContracts.YourContract.interface.encodeFunctionData("setPurpose(string)",["? Whoa so 1337!"])
            });
            /* this should throw an error about "no fallback nor receive function" until you add it */
          }}>Another Example</Button>
        </div>

      </div>

      {/*
        ? Maybe display a list of events?
          (uncomment the event and emit line in YourContract.sol! )
      */}
      <div style={{ width:600, margin: "auto", marginTop:32, paddingBottom:32 }}>
        <h2>Events:</h2>
        <List
          bordered
          dataSource={setPurposeEvents}
          renderItem={(item) => {
            return (
              <List.Item key={item.blockNumber+"_"+item.sender+"_"+item.purpose}>
                <Address
                    address={item[0]}
                    ensProvider={mainnetProvider}
                    fontSize={16}
                  /> =>
                {item[1]}
              </List.Item>
            )
          }}
        />
      </div>


      <div style={{ width:600, margin: "auto", marginTop:32, paddingBottom:256 }}>

        <Card>

          Check out all the <a href="https://github.com/austintgriffith/scaffold-eth/tree/master/packages/react-app/src/components" target="_blank" rel="noopener noreferrer">?  components</a>

        </Card>

        <Card style={{marginTop:32}}>

          <div>
            There are tons of generic components included from <a href="https://ant.design/components/overview/" target="_blank" rel="noopener noreferrer">?  ant.design</a> too!
          </div>

          <div style={{marginTop:8}}>
            <Button type="primary">
              Buttons
            </Button>
          </div>

          <div style={{marginTop:8}}>
            <SyncOutlined spin />  Icons
          </div>

          <div style={{marginTop:8}}>
            Date Pickers?
            <div style={{marginTop:2}}>
              <DatePicker onChange={()=>{}}/>
            </div>
          </div>

          <div style={{marginTop:32}}>
            <Slider range defaultValue={[20, 50]} onChange={()=>{}}/>
          </div>

          <div style={{marginTop:32}}>
            <Switch defaultChecked onChange={()=>{}} />
          </div>

          <div style={{marginTop:32}}>
            <Progress percent={50} status="active" />
          </div>

          <div style={{marginTop:32}}>
            <Spin />
          </div>


        </Card>




      </div>


    </div>
  );
}