@ant-design/icons#FileDoneOutlined JavaScript Examples

The following examples show how to use @ant-design/icons#FileDoneOutlined. 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: confgo.jsx    From juno with Apache License 2.0 4 votes vote down vote up
render() {
    const that = this;
    const {
      appId = 0,
      app = {},
      apps = [],
      configList = [],
      configText,
      commonText,
      appConfigList = [],
      configChangeList = [],
      statusList = [],
      configHistoryList = [],
      resourceData = {},
      appInfo: { aid, appName },
      msg,
      idcList,
      file_path = '',
      zoneCode,
    } = this.props;
    console.log('render -> configText', configText);

    const { users = [] } = app;
    const appInfo = appConfigList[0] || {};
    const {
      caid,
      file_name,
      format,
      env,
      filterKey,
      selectItemID,
      selectKey,
      selectValue,
      selectComment,
      selectIsResource,
      selectResourceID,
      selectIsPublic,
      fileDelModalVisible: showFileManage,
      fileDelConfirmLoading,
      result_list = [],
    } = this.state;
    const changeNum = configList.filter((v) => v.status * 1 !== 1).length;

    const leftCardStyle = {
      borderRadius: '4px',
      marginTop: '4px',
      marginLeft: '4px',
    };
    const statusMap = (t, status) => {
      const map = {
        1: <span></span>,
        2: <span>{getOpSapn('new')}</span>,
        3: <span>{getOpSapn('update')}</span>,
        4: <span>{getOpSapn('del')}</span>,
      };
      return map[status];
    };

    const changListCols = [
      {
        key: 'key',
        dataIndex: 'key',
        title: 'Block',
        width: 120,
        render(t, r) {
          return <span style={{ wordBreak: 'break-word' }}>{t}</span>;
        },
      },
      {
        key: 'op_type',
        dataIndex: 'op_type',
        title: '操作',
        width: 80,
        render(t) {
          const opMap = {
            1: getOpSapn('new', '新增'),
            2: getOpSapn('update', '更新'),
            3: getOpSapn('del', '删除'),
          };
          return <span>{opMap[t]}</span>;
        },
      },
      {
        key: 'old_value',
        dataIndex: 'old_value',
        title: '旧值',
        render(t) {
          let tmp = t;
          if (t.length > 200) {
            tmp = tmp.substring(0, 200) + '...';
          }
          return <span style={{ wordBreak: 'break-word' }}>{tmp}</span>;
        },
      },
      {
        key: 'new_value',
        dataIndex: 'new_value',
        title: '新值',
        render(t) {
          let tmp = t;
          if (t.length > 200) {
            tmp = tmp.substring(0, 200) + '...';
          }
          return <span style={{ wordBreak: 'break-word' }}>{tmp}</span>;
        },
      },
      {
        key: 'update_time',
        dataIndex: 'update_time',
        title: '时间',
        width: 180,
        render(t) {
          return moment(t * 1000).format('YYYY-MM-DD HH:mm:ss');
        },
      },
      {
        key: 'op_name',
        dataIndex: 'op_name',
        width: 180,
        title: '操作人',
      },
    ];

    const statusCol = [
      {
        key: 'is_use',
        dataIndex: 'is_use',
        title: (
          <span>
            配置状态
            <Tooltip
              title={`当前实例上的systemd配置文件项是否接入配置中心\n。若显示未接入,则需要修改systemd下发配置,路径改为配置中心提供的路径\n。若已经修改下发过,点击【同步实例状态】刷新。`}
            >
              <QuestionCircleOutlined style={{ marginLeft: '6px' }} />
            </Tooltip>
          </span>
        ),
        render(t) {
          return t ? getOpSapn('new', '已接入') : <div>{getOpSapn('del', '未接入')}</div>;
        },
      },
      {
        key: 'is_latest',
        dataIndex: 'is_latest',
        title: (
          <span>
            文件状态
            <Tooltip
              title={`当前实例上的配置文件是否为最新发布\n。若显示未同步,点击【刷新文件状态】。若刷新无效则需要【重新发布】一次。`}
            >
              <QuestionCircleOutlined style={{ marginLeft: '6px' }} />
            </Tooltip>
          </span>
        ),
        render(t) {
          return t ? getOpSapn('new', '已同步') : getOpSapn('del', '未同步');
        },
      },
      {
        key: 'is_effect',
        dataIndex: 'is_effect',
        title: (
          <span>
            配置状态
            <Tooltip title={`重启之后应用配置是否生效`}>
              <QuestionCircleOutlined style={{ marginLeft: '6px' }} />
            </Tooltip>
          </span>
        ),
        render(t) {
          return t ? getOpSapn('new', '已生效') : <div>{getOpSapn('del', '未生效')}</div>;
        },
      },
      {
        key: 'hostname',
        dataIndex: 'hostname',
        title: '实例名称',
      },
      {
        key: 'message',
        dataIndex: 'message',
        title: '提交日志',
      },
      {
        key: 'timestamp',
        dataIndex: 'timestamp',
        title: '文件同步时间/进程启动时间',
        render(t, r) {
          const { process_start_time = 0, is_latest, is_use } = r;
          if (process_start_time !== 0) {
            const syncTime = t * 1000;
            const startTime = process_start_time * 1000;
            //进程生效状态
            let process_start_status = null;
            if (syncTime > startTime) {
              //配置未完全生效
              process_start_status = (
                <Tooltip title={'配置文件已经同步完成,进程尚未重启生效'}>
                  <Icon type="clock-circle" style={{ color: 'orange' }} />
                </Tooltip>
              );
            } else if (is_latest && is_use) {
              // 配置文件已同步,进程已重启,生效
              process_start_status = (
                <Tooltip title={'最新配置已经生效'}>
                  <Icon type="check-circle" style={{ color: 'green' }} />
                </Tooltip>
              );
            }
            return (
              <div>
                <p>{moment(syncTime).format('YYYY-MM-DD HH:mm:ss')}</p>
                <p>
                  {moment(startTime).format('YYYY-MM-DD HH:mm:ss')} {process_start_status}
                </p>
              </div>
            );
          }
          return (
            <div>
              <p>{moment(t * 1000).format('YYYY-MM-DD HH:mm:ss')}</p>
            </div>
          );
        },
      },
      {
        key: 'params',
        dataIndex: 'params',
        title: (
          <span>
            启动参数
            <Tooltip
              title={
                '当前实例上的systemd配置中的启动参数, ${ConfigDir}变量为配置中心默认下发路径。启动时间为进程启动时间。'
              }
            >
              <Icon style={{ marginLeft: '6px' }} type="question-circle" />
            </Tooltip>
          </span>
        ),
        render(t, r) {
          const paramsArr = t.split('/bin/%(program_name)s');
          if (paramsArr.length !== 2) {
            return t;
          }
          const params = paramsArr[1];
          return (
            <div>
              <p style={{ margin: 0 }}>{params}</p>
            </div>
          );
        },
      },
      {
        key: 'op',
        dataIndex: 'op',
        title: '操作',
        render(t, r) {
          const { pub_id, is_latest } = r;
          if (is_latest) {
            return (
              <div>
                <Button
                  style={{ color: 'black' }}
                  onClick={(e) => {
                    that.showConfirm('restart', this.state.zone_code, r.hostname);
                  }}
                >
                  重启
                </Button>
              </div>
            );
          }
        },
      },
    ];

    const customPanelStyle = {
      background: '#f7f7f7',
      borderRadius: 4,
      marginBottom: 8,
      border: 0,
      overflow: 'hidden',
    };

    //文本编辑器options
    const options = {
      lineNumbers: true, //显示行号
      mode: { name: 'text/html' }, //定义mode
      theme: 'ambiance', //选中的theme
      lineWrapping: true,
    };

    if (msg === '权限错误') {
      return (
        <div style={{ marginTop: 10 }}>
          <Alert
            message="权限不足"
            description="对线上配置操作需要管理员权限"
            type="error"
            showIcon
          />
        </div>
      );
    }
    let idcArr = [];
    let zone_codeMap = [];

    idcList.forEach((element) => {
      idcArr.push(element.zone_code);
      zone_codeMap[element.zone_code] = element.zone_name;
    });

    const genHeader = (record) => (
      <div>
        <div className={'cube'}>
          {record.is_public == 0 && <Tag color="#2db7f5">私有</Tag>}
          {record.is_public == 1 && <Tag color="#f50">公有</Tag>}
          {record.is_public == 2 && <Tag color="#87d068">关联</Tag>}
        </div>
        <div className={'cube-title'}>
          <h3>{record.key}</h3>
        </div>
      </div>
    );

    const genExtra = (record) => (
      <div>
        {statusMap(record.key, record.status)}
        <Divider type="vertical" />
        {record.status != 4 && (
          <Tag
            color={'blue'}
            onClick={(event) => {
              event.stopPropagation();
              that.setState({
                selectItemID: record.id,
                selectKey: record.key,
                selectValue: record.value,
                selectComment: record.comment,
                selectIsResource: record.is_resource,
                selectResourceID: record.resource_id,
                selectIsPublic: record.is_public,
                showUpdateItem: true,
              });
              that.getEnvResource();
            }}
          >
            编辑
          </Tag>
        )}
        {record.status != 4 && (
          <Popconfirm
            title="确定删除吗?"
            onConfirm={() => {
              that.delItem({ id: record.id });
            }}
          >
            <Tag color={'red'}>删除</Tag>
          </Popconfirm>
        )}
      </div>
    );

    let configItemList = [];
    configList.forEach((element) => {
      configItemList.push(
        <Panel
          header={genHeader(element)}
          key={element.key}
          className="site-collapse-custom-panel"
          extra={genExtra(element)}
        >
          <ReactCodeMirror
            ref="editor"
            value={element.value}
            options={{
              mode: 'text/x-toml',
              lineNumbers: true,
              autoMatchParens: true,
              lineWrapping: false,
              readOnly: this.state.readOnly,
              scrollbarStyle: null,
            }}
          />
        </Panel>,
      );
    });

    return (
      <Layout>
        <Sider width={250} style={{ backgroundColor: 'transparent' }}>
          <Card style={leftCardStyle}>
            <p style={{ textAlign: 'left' }}>
              配置文件列表
              <Button
                style={{ marginLeft: '8px' }}
                size={'small'}
                type={'primary'}
                icon={<PlusCircleOutlined />}
                onClick={() => {
                  this.setState({ showConfigFile: true });
                }}
              >
                添加配置
              </Button>
            </p>
            {appInfo && appInfo.configs ? (
              <Menu
                selectedKeys={[caid + '_' + env + '_' + format]}
                mode="inline"
                style={{ height: '50%', borderRight: 0 }}
                defaultOpenKeys={idcArr}
                onClick={this.changeAppConfig}
              >
                {Object.keys(this.sortObj(appInfo.files, idcArr)).map((zone_code) => {
                  if (zoneCode == 'all' || zoneCode == zone_code) {
                    return (
                      <Menu.SubMenu key={zone_code} title={<h4>{`${zone_codeMap[zone_code]}`}</h4>}>
                        {appInfo.files[zone_code].map((v) => {
                          console.log('this.state.zone_code', this.state.zone_code);
                          return (
                            <Menu.Item
                              style={{ paddingLeft: '20px' }}
                              key={v.id + '_' + v.env + '_' + v.format}
                            >
                              {v.file_name}
                            </Menu.Item>
                          );
                        })}
                      </Menu.SubMenu>
                    );
                  }
                })}
              </Menu>
            ) : (
              <div style={{ textAlign: 'left' }}>
                <Button type={'primary'} onClick={() => this.setState({ showConfigFile: true })}>
                  添加配置文件
                </Button>
              </div>
            )}
          </Card>
          <Card style={leftCardStyle}>
            <p style={{ textAlign: 'left' }}>文件管理</p>
            <Button type="primary" onClick={this.handleFileManage} style={{ marginLeft: '4px' }}>
              文件管理
            </Button>
            <Button type="primary" onClick={this.handleFileDiff} style={{ marginLeft: '4px' }}>
              文件对比
            </Button>
          </Card>
        </Sider>
        <Content>
          <div>
            {caid !== 0 && (
              <Row style={{ marginTop: '4px', marginLeft: '4px', marginRight: '4px' }}>
                <Col span={4} style={{ textAlign: 'left' }}>
                  <Button
                    style={{ float: 'left', marginRight: '6px' }}
                    onClick={(e) => {
                      //加载节点数据
                      this.getAppList().then((_) => {
                        //获取配置列表
                        this.autoChangeConfig(); //自动选择第一个配置文件
                        message.success('数据已更新');
                      });
                    }}
                  >
                    <Icon type="sync" />
                    刷新数据
                  </Button>
                  <Tooltip
                    title={`当前页面为静态页面,修改配置前需要刷新获取最新配置数据,以免覆盖其他人的配置数据`}
                  >
                    <QuestionCircleOutlined />
                  </Tooltip>
                </Col>
                <Col span={20} style={{ textAlign: 'right' }}>
                  <Button.Group>
                    <Button
                      type={'primary'}
                      onClick={() => {
                        that.setState({ showPublish: true });
                      }}
                    >
                      发布配置
                    </Button>
                    <Button
                      type={'danger'}
                      onClick={(e) => {
                        that.changeTab('status');
                      }}
                    >
                      重启列表
                    </Button>
                    <Button
                      type={'primary'}
                      onClick={(e) => {
                        that.setState({ showRollback: true });
                      }}
                    >
                      配置回滚
                    </Button>
                    <Button
                      onClick={() => {
                        that.getHistoryList();
                        that.setState({ showHistory: true });
                      }}
                    >
                      发布历史
                    </Button>
                  </Button.Group>
                </Col>
              </Row>
            )}
            {caid !== 0 && (
              <Tabs
                style={{
                  backgroundColor: '#fff',
                  marginTop: '5px',
                  marginLeft: '5px',
                  marginRight: '5px',
                }}
                activeKey={this.state.tab}
                onChange={this.changeTab}
              >
                <TabPane
                  tab={
                    <span>
                      <div style={{ marginLeft: 10 }}>
                        <TableOutlined />
                        配置编辑
                      </div>
                    </span>
                  }
                  key="table"
                >
                  <Row>
                    <Col style={{ marginTop: '-5px' }}>
                      <Button.Group>
                        <Button
                          style={{ marginLeft: '10px' }}
                          type="primary"
                          onClick={() => {
                            that.setState({ showAddItem: true });
                            that.getEnvResource();
                          }}
                        >
                          添加 Block
                        </Button>
                      </Button.Group>
                    </Col>
                  </Row>
                  <Row gutter={24}>
                    <Col span={24} style={{ marginTop: '10px' }}>
                      <Collapse
                        bordered={false}
                        defaultActiveKey={['application']}
                        expandIcon={({ isActive }) => (
                          <CaretRightOutlined rotate={isActive ? 90 : 0} />
                        )}
                        className="site-collapse-custom-collapse"
                        expandIconPosition="right"
                      >
                        {configItemList}
                      </Collapse>
                    </Col>
                  </Row>
                </TabPane>
                <TabPane
                  tab={
                    <span>
                      <FileOutlined />
                      发布预览
                    </span>
                  }
                  key="text"
                >
                  <Spin spinning={this.state.loading} />
                  <Row>
                    <Col
                      style={{
                        textAlign: 'left',
                        marginLeft: '8px',
                        marginBottom: '8px',
                        fontSize: '18px',
                      }}
                      span={12}
                    >
                      {file_name}
                    </Col>
                    <Col
                      style={{
                        textAlign: 'right',
                        marginRight: '8px',
                        marginBottom: '8px',
                      }}
                      span={11}
                    >
                      <Button.Group>
                        <span>
                          <Button
                            onClick={(e) => {
                              copy(configText);
                              message.success('已复制到剪切板');
                            }}
                          >
                            复制
                          </Button>
                        </span>
                      </Button.Group>
                    </Col>
                  </Row>
                  <div className={'configEditor'}>
                    <ReactCodeMirror
                      ref="editor"
                      value={configText}
                      options={{
                        mode: 'text/x-toml',
                        lineNumbers: true,
                        autoMatchParens: true,
                        lineWrapping: true,
                        readOnly: this.state.readOnly,
                      }}
                      onChange={(editor, data, value) => {
                        this.configInputText = editor.getValue();
                      }}
                    />
                  </div>
                </TabPane>
                <TabPane
                  tab={
                    <span>
                      <FileDoneOutlined />
                      <Badge count={changeNum} overflowCount={9999} offset={[0, 18]}>
                        变更历史
                      </Badge>
                    </span>
                  }
                  key="history"
                >
                  <Table
                    columns={changListCols}
                    dataSource={configChangeList}
                    size={'small'}
                    pagination={false}
                    rowKey={'id'}
                  />
                </TabPane>
                <TabPane
                  tab={
                    <span>
                      <HddOutlined />
                      实例列表
                    </span>
                  }
                  key="status"
                >
                  <Spin spinning={this.state.showStatusSync} />
                  <div style={{ marginLeft: '10px' }}>
                    配置文件路径:
                    <span
                      style={{
                        marginLeft: '8px',
                        marginRight: '8px',
                        fontSize: '16px',
                      }}
                    >{`${file_path}`}</span>
                    <a
                      onClick={(e) => {
                        copy(`${file_path}`);
                        message.success('已复制,请重新下发配置文件生效');
                      }}
                    >
                      点击复制
                    </a>
                    <Tooltip
                      title={`修改systemd下发的配置文件路径,由原来的项目相对路径改为配置中心的路径`}
                    >
                      <Icon style={{ marginLeft: '6px' }} type="question-circle" />
                    </Tooltip>
                    <span
                      style={{
                        float: 'right',
                        marginRight: '8px',
                        marginBottom: '8px',
                      }}
                    >
                      <Button
                        type={'primary'}
                        onClick={(e) => {
                          that.setState({
                            showStatusSync: true,
                          });
                          SyncConfigNodes({ caid: caid })
                            .then((rs) => {
                              that.getConfigStatusList();
                              message.success('同步成功');
                              that.setState({
                                showStatusSync: false,
                              });
                            })
                            .catch((err) => {
                              that.setState({
                                showStatusSync: false,
                              });
                            });
                        }}
                      >
                        刷新实例状态
                      </Button>
                    </span>
                    <Table
                      size="small"
                      columns={statusCol}
                      dataSource={statusList}
                      pagination={false}
                    />
                  </div>
                </TabPane>
              </Tabs>
            )}

            <NewItemForm
              show={this.state.showAddItem}
              cancel={() => {
                this.setState({ showAddItem: false });
              }}
              item={{
                resourceData: resourceData,
              }}
              env={this.state.env}
              zone_code={this.state.zone_code}
              submit={this.addItem}
              caid={this.state.caid}
              zone_codeMap={zone_codeMap}
            />

            <UpdateItemForm
              show={this.state.showUpdateItem}
              env={this.state.env}
              zone_code={this.state.zone_code}
              cancel={() => {
                this.setState({ showUpdateItem: false });
              }}
              changeResource={(e) => {
                that.setState({
                  selectIsResource: e,
                });
              }}
              changeResourceID={(e) => {
                that.setState({
                  selectResourceID: e * 1,
                });
              }}
              caid={this.state.caid}
              submit={this.updateItem}
              item={{
                id: selectItemID,
                key: selectKey,
                value: selectValue,
                comment: selectComment,
                is_resource: selectIsResource,
                resource_id: selectResourceID,
                resourceData: resourceData,
                is_public: selectIsPublic,
              }}
              zone_codeMap={zone_codeMap}
            />

            <PublishForm
              show={this.state.showPublish}
              publish_loading={this.state.publish_loading}
              file_name={file_name}
              item={{ caid }}
              cancel={() => {
                this.setState({ showPublish: false });
              }}
              submit={this.publishItem}
            />

            <NewConfigFile
              show={this.state.showConfigFile}
              cancel={() => {
                this.setState({ showConfigFile: false });
              }}
              submit={this.AddConfigFile}
              zoneList={this.props.zoneList}
            />

            <HistoryList
              show={this.state.showHistory}
              cancel={() => {
                this.setState({ showHistory: false });
                this.props.dispatch({
                  type: 'confuNew/setPublishChangeData',
                  payload: {},
                });
              }}
              list={configHistoryList}
            />

            <Preview
              oldCode={configText}
              newCode={this.configInputText}
              show={this.state.showPreview}
              cancel={() => {
                this.setState({ showPreview: false });
              }}
            />

            {this.state.showRollback && (
              <RollbackView
                caid={caid}
                show={this.state.showRollback}
                rollback={() => {
                  that.getConfigList();
                }}
                cancel={() => {
                  this.setState({ showRollback: false });
                }}
              />
            )}
            <FileManageView
              show={this.state.showFileManage}
              app_name={appName}
              app_id={aid}
              env={env}
              zone_code={this.state.zone_code}
              cancel={() => {
                this.setState({ showFileManage: false }, () => {
                  this.autoChangeConfig;
                });
              }}
            />
            <FileDiffView
              show={this.state.showFileDiff}
              originCid={this.state.caid}
              rafeCid={0}
              appConfigList={this.props.appConfigList}
              cancel={() => {
                this.setState({ showFileDiff: false });
              }}
            />
          </div>
        </Content>
        <Modal
          title="操作面板"
          visible={this.state.visible}
          onOk={(e) => {
            this.refreshState();
            this.setState({ visible: false, result_list: [] });
          }}
          okText={'确定'}
          onCancel={(e) => {
            this.refreshState();
            this.setState({ visible: false, result_list: [] });
          }}
          cancelText={'关闭'}
        >
          <div>
            <Spin spinning={this.state.loading} />
          </div>
          <div style={{ backgroundColor: 'black', borderRadius: '5px' }}>
            {result_list.map((v, i) => {
              const { name, content } = v;
              return (
                <p key={i} style={{ color: 'green' }}>
                  {content}
                </p>
              );
            })}
          </div>
        </Modal>
      </Layout>
    );
  }
Example #2
Source File: newtask.js    From hashcat.launcher with MIT License 4 votes vote down vote up
render() {
		return (
			<>
				<PageHeader
					title="New Task"
					extra={[
						<Upload
							key="Import Config"
							accept=".json"
							maxCount={1}
							showUploadList={false}
							onChange={this.onClickImportConfig}
							beforeUpload={() => {return false;}}
						>
							<Button
								type="text"
								icon={<ImportOutlined />}
								loading={this.state.isLoadingImportConfig}
							>
								Import Config
							</Button>
						</Upload>,
						<Button
							key="Export Config"
							type="text"
							icon={<ExportOutlined />}
							onClick={this.onClickExportConfig}
							loading={this.state.isLoadingExportConfig}
						>
							Export Config
						</Button>
					]}
				/>
				<Content style={{ padding: '16px 24px' }}>
					<Row gutter={[16]}>
						<Col span={4}>
							<Steps direction="vertical" current={this.state.step} onChange={this.onChangeStep}>
								<Step title="Target" icon={<AimOutlined />} description="Select Target" />
								<Step title="Attack" icon={<ToolOutlined />} description="Configure Attack" />
								<Step title="Advanced" icon={<ExperimentOutlined />} description="Advanced Options" />
								<Step title="Output" icon={<ExportOutlined />} description="Set Output" />
								<Step title="Finalize" icon={<FileDoneOutlined />} description="Review and Finalize" />
							</Steps>
						</Col>
						<Col span={20}>
							<div className="steps-content">
								{this.state.step === 0 ? (
									<Form layout="vertical">
										<Form.Item
											label="Hash"
										>
											<Select
												showSearch
												style={{ width: "100%" }}
												size="large"
												placeholder="Select Hash"
												value={this.state.hash}
												onChange={this.onChangeHash}
												filterOption={(input, option) =>
													String(option.value).toLowerCase().indexOf(input.toLowerCase()) >= 0 ||
													String(option.children).toLowerCase().indexOf(input.toLowerCase()) >= 0
												}
											>
												{this.state._hashes.map(hash =>
													<Option value={hash} key={hash} title={hash}>{filename(hash)}</Option>
												)}
											</Select>
										</Form.Item>
										<Form.Item
											label="Algorithm"
										>
											<Select
												showSearch
												style={{ width: "100%" }}
												size="large"
												placeholder="Select Algorithm"
												value={this.state.algorithm}
												onChange={this.onChangeAlgorithm}
												filterOption={(input, option) =>
													String(option.value).toLowerCase().indexOf(input.toLowerCase()) >= 0 ||
													String(option.children).toLowerCase().indexOf(input.toLowerCase()) >= 0
												}
											>
												{Object.keys(this.state._algorithms).map(key =>
													<Option value={Number(key)} key={Number(key)}>{key + " - " + this.state._algorithms[key]}</Option>
												)}
											</Select>
										</Form.Item>
									</Form>
								) : this.state.step === 1 ? (
									<Form layout="vertical" requiredMark="optional">
										<Form.Item
											label="Attack Mode"
											required
										>
											<Radio.Group value={this.state.attackMode} onChange={this.onChangeAttackMode}>
												<Radio value={0}>Dictionary Attack</Radio>
												<Radio value={1}>Combinator Attack</Radio>
												<Radio value={3}>Mask Attack</Radio>
												<Radio value={6}>Hybrid1 (Dictionary + Mask)</Radio>
												<Radio value={7}>Hybrid2 (Mask + Dictionary)</Radio>
											</Radio.Group>
										</Form.Item>
											{this.state.attackMode === 0 ? (
												<>
													<Form.Item
														label="Dictionaries"
														required
													>
														<Select
															mode="multiple"
															allowClear
															style={{ width: '100%' }}
															placeholder="Select Dictionaries"
															size="large"
															onChange={this.onChangeDictionaries}
															value={this.state.dictionaries}
															filterOption={(input, option) =>
																String(option.value).toLowerCase().indexOf(input.toLowerCase()) >= 0 ||
																String(option.children).toLowerCase().indexOf(input.toLowerCase()) >= 0
															}
														>
															{this.state._dictionaries.map(dictionary =>
																<Option value={dictionary} key={dictionary} title={dictionary}>{filename(dictionary)}</Option>
															)}
														</Select>
													</Form.Item>
													<Form.Item
														label="Rules"
													>
														<Select
															mode="multiple"
															allowClear
															style={{ width: '100%' }}
															placeholder={"Select Rules [max. "+maxRules+"]"}
															size="large"
															onChange={this.onChangeRules}
															value={this.state.rules}
															filterOption={(input, option) =>
																String(option.value).toLowerCase().indexOf(input.toLowerCase()) >= 0 ||
																String(option.children).toLowerCase().indexOf(input.toLowerCase()) >= 0
															}
														>
															{this.state._rules.map(rule =>
																<Option value={rule} key={rule} title={rule}>{filename(rule)}</Option>
															)}
														</Select>
													</Form.Item>
												</>
											) : this.state.attackMode === 1 ? (
												<Row gutter={[18, 16]}>
													<Col span={12}>
														<Row>
															<Col span={24}>
																<Form.Item
																	label="Left Dictionary"
																	required
																>
																	<Select
																		showSearch
																		allowClear
																		style={{ width: '100%' }}
																		placeholder="Select Left Dictionary"
																		size="large"
																		onChange={this.onChangeLeftDictionary}
																		value={this.state.leftDictionary}
																		filterOption={(input, option) =>
																			String(option.value).toLowerCase().indexOf(input.toLowerCase()) >= 0 ||
																			String(option.children).toLowerCase().indexOf(input.toLowerCase()) >= 0
																		}
																	>
																		{this.state._dictionaries.map(dictionary =>
																			<Option value={dictionary} key={dictionary} title={dictionary}>{filename(dictionary)}</Option>
																		)}
																	</Select>
																</Form.Item>
															</Col>
															<Col span={24}>
																<Form.Item
																	label="Left Rule"
																>
																	<Input
																		allowClear
																		style={{ width: '100%' }}
																		placeholder="Set Left Rule"
																		size="large"
																		onChange={this.onChangeLeftRule}
																		value={this.state.leftRule}
																	/>
																</Form.Item>
															</Col>
														</Row>
													</Col>
													<Col span={12}>
														<Row>
															<Col span={24}>
																<Form.Item
																	label="Right Dictionary"
																	required
																>
																	<Select
																		showSearch
																		allowClear
																		style={{ width: '100%' }}
																		placeholder="Select Right Dictionary"
																		size="large"
																		onChange={this.onChangeRightDictionary}
																		value={this.state.rightDictionary}
																		filterOption={(input, option) =>
																			String(option.value).toLowerCase().indexOf(input.toLowerCase()) >= 0 ||
																			String(option.children).toLowerCase().indexOf(input.toLowerCase()) >= 0
																		}
																	>
																		{this.state._dictionaries.map(dictionary =>
																			<Option value={dictionary} key={dictionary} title={dictionary}>{filename(dictionary)}</Option>
																		)}
																	</Select>
																</Form.Item>
															</Col>
															<Col span={24}>
																<Form.Item
																	label="Right Rule"
																>
																	<Input
																		allowClear
																		style={{ width: '100%' }}
																		placeholder="Set Right Rule"
																		size="large"
																		onChange={this.onChangeRightRule}
																		value={this.state.rightRule}
																	/>
																</Form.Item>
															</Col>
														</Row>
													</Col>
												</Row>
											) : this.state.attackMode === 3 ? (
												<Row gutter={[18, 16]}>
													<Col span={12}>
														{this.state.maskInputType === "text" ? (
															<Form.Item
																label="Mask"
																required
															>
																<Input
																	allowClear
																	style={{ width: '100%' }}
																	placeholder="Set Mask"
																	size="large"
																	onChange={this.onChangeMask}
																	value={this.state.mask}
																	suffix={
																		this.state.mask ? maskLength(this.state.mask) : undefined
																	}
																/>
																<Button
																	type="link"
																	style={{ padding: '0' }}
																	onClick={() => this.onChangeMaskInputType({type: "file"})}
																>
																	Use .hcmask file instead
																</Button>
															</Form.Item>
														) : this.state.maskInputType === "file" ? (
															<Form.Item
																label="Mask"
																required
															>
																<Select
																	allowClear
																	style={{ width: '100%' }}
																	placeholder="Select Mask"
																	size="large"
																	onChange={this.onChangeMaskFile}
																	value={this.state.maskFile}
																	filterOption={(input, option) =>
																		String(option.value).toLowerCase().indexOf(input.toLowerCase()) >= 0 ||
																		String(option.children).toLowerCase().indexOf(input.toLowerCase()) >= 0
																	}
																>
																	{this.state._masks.map(mask =>
																		<Option value={mask} key={mask} title={mask}>{filename(mask)}</Option>
																	)}
																</Select>
																<Button
																	type="link"
																	style={{ padding: '0' }}
																	onClick={() => this.onChangeMaskInputType({type: "text"})}
																>
																	Use mask text instead
																</Button>
															</Form.Item>
														) : "unsupported mask input type" }
														<Form.Item
															label="Mask increment mode"
														>
															<Checkbox
																checked={this.state.enableMaskIncrementMode}
																onChange={this.onChangeEnableMaskIncrementMode}
															>
																Enable
															</Checkbox>
															<InputNumber
																disabled={!this.state.enableMaskIncrementMode}
																min={maskIncrementMin}
																max={maskIncrementMax}
																value={this.state.maskIncrementMin}
																onChange={this.onChangeMaskIncrementMin}
															/>
															<InputNumber
																disabled={!this.state.enableMaskIncrementMode}
																min={maskIncrementMin}
																max={maskIncrementMax}
																value={this.state.maskIncrementMax}
																onChange={this.onChangeMaskIncrementMax}
															/>
														</Form.Item>
													</Col>
													<Col span={12}>
														<Form.Item
															label="Custom charset 1"
														>
															<Input
																allowClear
																style={{ width: '100%' }}
																placeholder="Set Custom charset 1"
																size="large"
																onChange={this.onChangeCustomCharset1}
																value={this.state.customCharset1}
															/>
														</Form.Item>
														<Form.Item
															label="Custom charset 2"
														>
															<Input
																allowClear
																style={{ width: '100%' }}
																placeholder="Set Custom charset 2"
																size="large"
																onChange={this.onChangeCustomCharset2}
																value={this.state.customCharset2}
															/>
														</Form.Item>
														<Form.Item
															label="Custom charset 3"
														>
															<Input
																allowClear
																style={{ width: '100%' }}
																placeholder="Set Custom charset 3"
																size="large"
																onChange={this.onChangeCustomCharset3}
																value={this.state.customCharset3}
															/>
														</Form.Item>
														<Form.Item
															label="Custom charset 4"
														>
															<Input
																allowClear
																style={{ width: '100%' }}
																placeholder="Set Custom charset 4"
																size="large"
																onChange={this.onChangeCustomCharset4}
																value={this.state.customCharset4}
															/>
														</Form.Item>
													</Col>
												</Row>
											) : this.state.attackMode === 6 ? (
												<Row gutter={[18, 16]}>
													<Col span={24}>
														<Row gutter={[18, 16]}>
															<Col span={12}>
																<Form.Item
																	label="Dictionary"
																	required
																>
																	<Select
																		showSearch
																		allowClear
																		style={{ width: '100%' }}
																		placeholder="Select Dictionary"
																		size="large"
																		onChange={this.onChangeLeftDictionary}
																		value={this.state.leftDictionary}
																		filterOption={(input, option) =>
																			String(option.value).toLowerCase().indexOf(input.toLowerCase()) >= 0 ||
																			String(option.children).toLowerCase().indexOf(input.toLowerCase()) >= 0
																		}
																	>
																		{this.state._dictionaries.map(dictionary =>
																			<Option value={dictionary} key={dictionary} title={dictionary}>{filename(dictionary)}</Option>
																		)}
																	</Select>
																</Form.Item>
															</Col>
															<Col span={12}>
																<Form.Item
																	label="Rule"
																>
																	<Input
																		allowClear
																		style={{ width: '100%' }}
																		placeholder="Set Rule"
																		size="large"
																		onChange={this.onChangeLeftRule}
																		value={this.state.leftRule}
																	/>
																</Form.Item>
															</Col>
														</Row>
													</Col>
													<Col span={12}>
														{this.state.maskInputType === "text" ? (
															<Form.Item
																label="Mask"
																required
															>
																<Input
																	allowClear
																	style={{ width: '100%' }}
																	placeholder="Set Mask"
																	size="large"
																	onChange={this.onChangeMask}
																	value={this.state.mask}
																	suffix={
																		this.state.mask ? maskLength(this.state.mask) : undefined
																	}
																/>
																<Button
																	type="link"
																	style={{ padding: '0' }}
																	onClick={() => this.onChangeMaskInputType({type: "file"})}
																>
																	Use .hcmask file instead
																</Button>
															</Form.Item>
														) : this.state.maskInputType === "file" ? (
															<Form.Item
																label="Mask"
																required
															>
																<Select
																	allowClear
																	style={{ width: '100%' }}
																	placeholder="Select Mask"
																	size="large"
																	onChange={this.onChangeMaskFile}
																	value={this.state.maskFile}
																	filterOption={(input, option) =>
																		String(option.value).toLowerCase().indexOf(input.toLowerCase()) >= 0 ||
																		String(option.children).toLowerCase().indexOf(input.toLowerCase()) >= 0
																	}
																>
																	{this.state._masks.map(mask =>
																		<Option value={mask} key={mask} title={mask}>{filename(mask)}</Option>
																	)}
																</Select>
																<Button
																	type="link"
																	style={{ padding: '0' }}
																	onClick={() => this.onChangeMaskInputType({type: "text"})}
																>
																	Use mask text instead
																</Button>
															</Form.Item>
														) : "unsupported mask input type" }
														<Form.Item
															label="Mask increment mode"
														>
															<Checkbox
																checked={this.state.enableMaskIncrementMode}
																onChange={this.onChangeEnableMaskIncrementMode}
															>
																Enable
															</Checkbox>
															<InputNumber
																disabled={!this.state.enableMaskIncrementMode}
																min={maskIncrementMin}
																max={maskIncrementMax}
																value={this.state.maskIncrementMin}
																onChange={this.onChangeMaskIncrementMin}
															/>
															<InputNumber
																disabled={!this.state.enableMaskIncrementMode}
																min={maskIncrementMin}
																max={maskIncrementMax}
																value={this.state.maskIncrementMax}
																onChange={this.onChangeMaskIncrementMax}
															/>
														</Form.Item>
													</Col>
													<Col span={12}>
														<Form.Item
															label="Custom charset 1"
														>
															<Input
																allowClear
																style={{ width: '100%' }}
																placeholder="Set Custom charset 1"
																size="large"
																onChange={this.onChangeCustomCharset1}
																value={this.state.customCharset1}
															/>
														</Form.Item>
														<Form.Item
															label="Custom charset 2"
														>
															<Input
																allowClear
																style={{ width: '100%' }}
																placeholder="Set Custom charset 2"
																size="large"
																onChange={this.onChangeCustomCharset2}
																value={this.state.customCharset2}
															/>
														</Form.Item>
														<Form.Item
															label="Custom charset 3"
														>
															<Input
																allowClear
																style={{ width: '100%' }}
																placeholder="Set Custom charset 3"
																size="large"
																onChange={this.onChangeCustomCharset3}
																value={this.state.customCharset3}
															/>
														</Form.Item>
														<Form.Item
															label="Custom charset 4"
														>
															<Input
																allowClear
																style={{ width: '100%' }}
																placeholder="Set Custom charset 4"
																size="large"
																onChange={this.onChangeCustomCharset4}
																value={this.state.customCharset4}
															/>
														</Form.Item>
													</Col>
												</Row>
											) : this.state.attackMode === 7 ? (
												<Row gutter={[18, 16]}>
													<Col span={12}>
														{this.state.maskInputType === "text" ? (
															<Form.Item
																label="Mask"
																required
															>
																<Input
																	allowClear
																	style={{ width: '100%' }}
																	placeholder="Set Mask"
																	size="large"
																	onChange={this.onChangeMask}
																	value={this.state.mask}
																	suffix={
																		this.state.mask ? maskLength(this.state.mask) : undefined
																	}
																/>
																<Button
																	type="link"
																	style={{ padding: '0' }}
																	onClick={() => this.onChangeMaskInputType({type: "file"})}
																>
																	Use .hcmask file instead
																</Button>
															</Form.Item>
														) : this.state.maskInputType === "file" ? (
															<Form.Item
																label="Mask"
																required
															>
																<Select
																	allowClear
																	style={{ width: '100%' }}
																	placeholder="Select Mask"
																	size="large"
																	onChange={this.onChangeMaskFile}
																	value={this.state.maskFile}
																	filterOption={(input, option) =>
																		String(option.value).toLowerCase().indexOf(input.toLowerCase()) >= 0 ||
																		String(option.children).toLowerCase().indexOf(input.toLowerCase()) >= 0
																	}
																>
																	{this.state._masks.map(mask =>
																		<Option value={mask} key={mask} title={mask}>{filename(mask)}</Option>
																	)}
																</Select>
																<Button
																	type="link"
																	style={{ padding: '0' }}
																	onClick={() => this.onChangeMaskInputType({type: "text"})}
																>
																	Use mask text instead
																</Button>
															</Form.Item>
														) : "unsupported mask input type" }
														<Form.Item
															label="Mask increment mode"
														>
															<Checkbox
																checked={this.state.enableMaskIncrementMode}
																onChange={this.onChangeEnableMaskIncrementMode}
															>
																Enable
															</Checkbox>
															<InputNumber
																disabled={!this.state.enableMaskIncrementMode}
																min={maskIncrementMin}
																max={maskIncrementMax}
																value={this.state.maskIncrementMin}
																onChange={this.onChangeMaskIncrementMin}
															/>
															<InputNumber
																disabled={!this.state.enableMaskIncrementMode}
																min={maskIncrementMin}
																max={maskIncrementMax}
																value={this.state.maskIncrementMax}
																onChange={this.onChangeMaskIncrementMax}
															/>
														</Form.Item>
													</Col>
													<Col span={12}>
														<Form.Item
															label="Custom charset 1"
														>
															<Input
																allowClear
																style={{ width: '100%' }}
																placeholder="Set Custom charset 1"
																size="large"
																onChange={this.onChangeCustomCharset1}
																value={this.state.customCharset1}
															/>
														</Form.Item>
														<Form.Item
															label="Custom charset 2"
														>
															<Input
																allowClear
																style={{ width: '100%' }}
																placeholder="Set Custom charset 2"
																size="large"
																onChange={this.onChangeCustomCharset2}
																value={this.state.customCharset2}
															/>
														</Form.Item>
														<Form.Item
															label="Custom charset 3"
														>
															<Input
																allowClear
																style={{ width: '100%' }}
																placeholder="Set Custom charset 3"
																size="large"
																onChange={this.onChangeCustomCharset3}
																value={this.state.customCharset3}
															/>
														</Form.Item>
														<Form.Item
															label="Custom charset 4"
														>
															<Input
																allowClear
																style={{ width: '100%' }}
																placeholder="Set Custom charset 4"
																size="large"
																onChange={this.onChangeCustomCharset4}
																value={this.state.customCharset4}
															/>
														</Form.Item>
													</Col>
													<Col span={24}>
														<Row gutter={[18, 16]}>
															<Col span={12}>
																<Form.Item
																	label="Dictionary"
																	required
																>
																	<Select
																		showSearch
																		allowClear
																		style={{ width: '100%' }}
																		placeholder="Select Dictionary"
																		size="large"
																		onChange={this.onChangeRightDictionary}
																		value={this.state.rightDictionary}
																		filterOption={(input, option) =>
																			String(option.value).toLowerCase().indexOf(input.toLowerCase()) >= 0 ||
																			String(option.children).toLowerCase().indexOf(input.toLowerCase()) >= 0
																		}
																	>
																		{this.state._dictionaries.map(dictionary =>
																			<Option value={dictionary} key={dictionary} title={dictionary}>{filename(dictionary)}</Option>
																		)}
																	</Select>
																</Form.Item>
															</Col>
															<Col span={12}>
																<Form.Item
																	label="Rule"
																>
																	<Input
																		allowClear
																		style={{ width: '100%' }}
																		placeholder="Set Rule"
																		size="large"
																		onChange={this.onChangeRightRule}
																		value={this.state.rightRule}
																	/>
																</Form.Item>
															</Col>
														</Row>
													</Col>
												</Row>
											) : (
												"Select Attack Mode"
											)}
									</Form>
								) : this.state.step === 2 ? (
									<Form layout="vertical">
										<Collapse ghost onChange={this.onChangeAdvancedOptionsCollapse} activeKey={this.state.advancedOptionsCollapse}>
											<Panel header="General" key="General">
												<Row gutter={[18, 16]}>
													<Col>
														<Checkbox
															checked={this.state.quiet}
															onChange={this.onChangeQuiet}
														>
															Quiet
														</Checkbox>
													</Col>
													<Col>
														<Checkbox
															checked={this.state.disablePotFile}
															onChange={this.onChangeDisablePotFile}
														>
															Disable Pot File
														</Checkbox>
													</Col>
													<Col>
														<Checkbox
															checked={this.state.disableLogFile}
															onChange={this.onChangeDisableLogFile}
														>
															Disable Log File
														</Checkbox>
													</Col>
													<Col>
														<Checkbox
															checked={this.state.enableOptimizedKernel}
															onChange={this.onChangeEnableOptimizedKernel}
														>
															Enable optimized kernel
														</Checkbox>
													</Col>
													<Col>
														<Checkbox
															checked={this.state.enableSlowerCandidateGenerators}
															onChange={this.onChangeEnableSlowerCandidateGenerators}
														>
															Enable slower candidate generators
														</Checkbox>
													</Col>
													<Col>
														<Checkbox
															checked={this.state.removeFoundHashes}
															onChange={this.onChangeRemoveFoundHashes}
														>
															Remove found hashes
														</Checkbox>
													</Col>
													<Col>
														<Checkbox
															checked={this.state.ignoreUsernames}
															onChange={this.onChangeIgnoreUsernames}
														>
															Ignore Usernames
														</Checkbox>
													</Col>
													<Col>
														<Checkbox
															checked={this.state.disableSelfTest}
															onChange={this.onChangeDisableSelfTest}
														>
															Disable self-test (Not Recommended)
														</Checkbox>
													</Col>
													<Col>
														<Checkbox
															checked={this.state.ignoreWarnings}
															onChange={this.onChangeIgnoreWarnings}
														>
															Ignore warnings (Not Recommended)
														</Checkbox>
													</Col>
												</Row>
											</Panel>
											<Panel header="Devices" key="Devices">
												<Row gutter={[18, 16]}>
													<Col span={8}>
														<Form.Item
															label="Devices IDs"
														>
															<Select
																mode="multiple"
																allowClear
																style={{ width: '100%' }}
																placeholder="Select Devices IDs"
																size="large"
																onChange={this.onChangeDevicesIDs}
																value={this.state.devicesIDs}
																filterOption={(input, option) =>
																	String(option.value).toLowerCase().indexOf(input.toLowerCase()) >= 0 ||
																	String(option.children).toLowerCase().indexOf(input.toLowerCase()) >= 0
																}
															>
																{Array.from(Array(16)).map((x,i) =>
																	<Option value={i+1} key={i+1}>{"Device #"+(i+1)}</Option>
																)}
															</Select>
														</Form.Item>
													</Col>
													<Col span={8}>
														<Form.Item
															label="Devices Types"
														>
															<Select
																mode="multiple"
																allowClear
																style={{ width: '100%' }}
																placeholder="Select Devices Types"
																size="large"
																onChange={this.onChangeDevicesTypes}
																value={this.state.devicesTypes}
																filterOption={(input, option) =>
																	String(option.value).toLowerCase().indexOf(input.toLowerCase()) >= 0 ||
																	String(option.children).toLowerCase().indexOf(input.toLowerCase()) >= 0
																}
															>
																<Option value={1} key={1}>CPU</Option>
																<Option value={2} key={2}>GPU</Option>
																<Option value={3} key={3}>FPGA, DSP, Co-Processor</Option>
															</Select>
														</Form.Item>
													</Col>
													<Col span={8}>
														<Form.Item
															label="Workload Profile"
															tooltip={
																<Table
																	columns={[
																		{
																			title: 'Performance',
																			dataIndex: 'performance',
																			key: 'Performance'
																		},
																		{
																			title: 'Runtime',
																			dataIndex: 'runtime',
																			key: 'Runtime'
																		},
																		{
																			title: 'Power Consumption',
																			dataIndex: 'powerConsumption',
																			key: 'Power Consumption'
																		},
																		{
																			title: 'Desktop Impact',
																			dataIndex: 'desktopImpact',
																			key: 'Desktop Impact'
																		}
																	]}
																	dataSource={[
																		{
																			key: '1',
																			performance: 'Low',
																			runtime: '2 ms',
																			powerConsumption: 'Low',
																			desktopImpact: 'Minimal'
																		},
																		{
																			key: '2',
																			performance: 'Default',
																			runtime: '12 ms',
																			powerConsumption: 'Economic',
																			desktopImpact: 'Noticeable'
																		},
																		{
																			key: '3',
																			performance: 'High',
																			runtime: '96 ms',
																			powerConsumption: 'High',
																			desktopImpact: 'Unresponsive'
																		},
																		{
																			key: '4',
																			performance: 'Nightmare',
																			runtime: '480 ms',
																			powerConsumption: 'Insane',
																			desktopImpact: 'Headless'
																		}
																	]}
																	size="small"
																	pagination={false}
																	style={{ overflow: 'auto' }}
																/>
															}
														>
															<Select
																allowClear
																style={{ width: '100%' }}
																placeholder="Select Workload Profile"
																size="large"
																onChange={this.onChangeWorkloadProfile}
																value={this.state.workloadProfile}
																filterOption={(input, option) =>
																	String(option.value).toLowerCase().indexOf(input.toLowerCase()) >= 0 ||
																	String(option.children).toLowerCase().indexOf(input.toLowerCase()) >= 0
																}
															>
																<Option value={1} key={1}>Low</Option>
																<Option value={2} key={2}>Default</Option>
																<Option value={3} key={3}>High</Option>
																<Option value={4} key={4}>Nightmare</Option>
															</Select>
														</Form.Item>
													</Col>
												</Row>
												<Row gutter={[18, 16]}>
													<Col>
														<Button
															loading={this.state.isLoadingDevicesInfo}
															onClick={this.onClickDevicesInfo}
														>
															Devices Info
														</Button>
													</Col>
													<Col>
														<Button
															loading={this.state.isLoadingBenchmark}
															onClick={this.onClickBenchmark}
														>
															Benchmark
														</Button>
													</Col>
												</Row>
											</Panel>
											<Panel header="Markov" key="Markov">
												<Row gutter={[18, 16]}>
													<Col>
														<Checkbox
															checked={this.state.markovDisable}
															onChange={this.onChangeMarkovDisable}
														>
															Disables markov-chains, emulates classic brute-force
														</Checkbox>
													</Col>
													<Col>
														<Checkbox
															checked={this.state.markovClassic}
															onChange={this.onChangeMarkovClassic}
														>
															Enables classic markov-chains, no per-position
														</Checkbox>
													</Col>
													<Col span={24}>
														<Row gutter={[18, 16]}>
															<Col span={8}>
																<Form.Item
																	label="Threshold X when to stop accepting new markov-chains"
																>
																	<InputNumber
																		value={this.state.markovThreshold}
																		onChange={this.onChangeMarkovThreshold}
																	/>
																</Form.Item>
															</Col>
														</Row>
													</Col>
												</Row>
											</Panel>
											<Panel header="Monitor" key="Monitor">
												<Row gutter={[18, 16]}>
													<Col>
														<Checkbox
															checked={this.state.disableMonitor}
															onChange={this.onChangeDisableMonitor}
														>
															Disable Monitor
														</Checkbox>
													</Col>
													<Col span={24}>
														<Row gutter={[18, 16]}>
															<Col span={8}>
																<Form.Item
																	label="Temp Abort (°C)"
																>
																	<Select
																		allowClear
																		style={{ width: '100%' }}
																		placeholder="Select Temp Abort (°C)"
																		size="large"
																		onChange={this.onChangeTempAbort}
																		value={this.state.tempAbort}
																		disabled={this.state.disableMonitor}
																		filterOption={(input, option) =>
																			String(option.value).toLowerCase().indexOf(input.toLowerCase()) >= 0 ||
																			String(option.children).toLowerCase().indexOf(input.toLowerCase()) >= 0
																		}
																	>
																		<Option value={60} key={60}>60 °C</Option>
																		<Option value={65} key={65}>65 °C</Option>
																		<Option value={70} key={70}>70 °C</Option>
																		<Option value={75} key={75}>75 °C</Option>
																		<Option value={80} key={80}>80 °C</Option>
																		<Option value={85} key={85}>85 °C</Option>
																		<Option value={90} key={90}>90 °C</Option>
																		<Option value={95} key={95}>95 °C</Option>
																		<Option value={100} key={100}>100 °C</Option>
																	</Select>
																</Form.Item>
															</Col>
														</Row>
													</Col>
												</Row>
											</Panel>
											<Panel header="Extra Arguments" key="Extra Arguments">
												<Form.Item
													label="Extra Arguments"
												>
													<Input
														allowClear
														style={{ width: '100%' }}
														placeholder="Set Extra Arguments"
														size="large"
														onChange={this.onChangeExtraArguments}
														value={this.state.extraArguments.join(" ")}
													/>
												</Form.Item>
											</Panel>
											<Panel header="Misc" key="Misc">
												<Form.Item
													label="Status Timer"
												>
													<Select
														allowClear
														style={{ width: '100%' }}
														placeholder="Select Status Timer"
														size="large"
														onChange={this.onChangeStatusTimer}
														value={this.state.statusTimer}
														filterOption={(input, option) =>
															String(option.value).toLowerCase().indexOf(input.toLowerCase()) >= 0 ||
															String(option.children).toLowerCase().indexOf(input.toLowerCase()) >= 0
														}
													>
														<Option value={10} key={10}>10 Seconds</Option>
														<Option value={20} key={20}>20 Seconds</Option>
														<Option value={30} key={30}>30 Seconds</Option>
														<Option value={45} key={45}>45 Seconds</Option>
														<Option value={60} key={60}>60 Seconds</Option>
														<Option value={90} key={90}>90 Seconds</Option>
														<Option value={120} key={120}>120 Seconds</Option>
														<Option value={300} key={300}>300 Seconds</Option>
													</Select>
												</Form.Item>
											</Panel>
										</Collapse>
									</Form>
								) : this.state.step === 3 ? (
									<Form layout="vertical">
										<Form.Item
											label="Output File"
											extra={this.state.outputFile ? this.state.outputFile : null}
										>
											<Button
												type="primary"
												onClick={this.onChangeOutputFile}
												loading={this.state.isLoadingSetOutputFile}
											>
												Set Output File
											</Button>
										</Form.Item>
										<Form.Item
											label="Output Format"
										>
											<Select
												mode="multiple"
												allowClear
												style={{ width: '100%' }}
												placeholder="Select Output Format"
												size="large"
												onChange={this.onChangeOutputFormat}
												value={this.state.outputFormat}
												filterOption={(input, option) =>
													String(option.value).toLowerCase().indexOf(input.toLowerCase()) >= 0 ||
													String(option.children).toLowerCase().indexOf(input.toLowerCase()) >= 0
												}
											>
												<Option value={1} key={1}>hash[:salt]</Option>
												<Option value={2} key={2}>plain</Option>
												<Option value={3} key={3}>hex_plain</Option>
												<Option value={4} key={4}>crack_pos</Option>
												<Option value={5} key={5}>timestamp absolute</Option>
												<Option value={6} key={6}>timestamp relative</Option>
											</Select>
										</Form.Item>
									</Form>
								) : this.state.step === 4 ? (
									<Space direction="vertical">
										<Form layout="vertical">
											<Form.Item
												label="Priority"
												tooltip={
													<Typography>
														Tasks are started automatically in a descending order of priority.
													<br />
														Set to -1 to disable auto-start.
													</Typography>
												}
											>
												<InputNumber
													min={-1}
													max={999}
													value={this.state.priority}
													onChange={this.onChangePriority}
													bordered={true}
												/>
											</Form.Item>
										</Form>
										<Space size="large" direction="horizontal">
											<Button
												type="primary"
												icon={<PlusOutlined />}
												onClick={this.onClickCreateTask}
												loading={this.state.isLoadingCreateTask}
											>
												Create Task
											</Button>
												<Checkbox
													checked={this.state.preserveTaskConfig}
													onChange={this.onChangePreserveTaskConfig}
												>
													Preserve task config
												</Checkbox>
										</Space>
									</Space>
								) : null }
							</div>
						</Col>
					</Row>
				</Content>
			</>
		)
	}