antd#Empty JavaScript Examples

The following examples show how to use antd#Empty. 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: PromptList.js    From video-journal-for-teams-fe with MIT License 6 votes vote down vote up
PromptList = ({ createPrompt, teamPromptsAndVideos, teamId, fetchTeamVideos, teamMembersEmail}) => {
	const [showModal, setShowModal] = useState(false);
	const { userRole } = useContext(UserContext)

	return (
		<Content className="prompts-list">
			<div className="dashboard-header">
				<h2>Prompts ({teamPromptsAndVideos.length})</h2>
				{userRole === 1 ? null : (
					// <Button
					// 	icon="plus"
					// 	className="adding-button"
					// 	style={{backgroundColor:"#6954EA", color:"white", border:"none"}}
					// 	onClick={() => setShowModal(true)}>
					// 	Add Prompt
					// </Button>
					<PlusOutlined onClick={() => setShowModal(true)} style={{fontSize:"1.6rem", color:"#6954EA"}}/>
				)}
			</div>
			<AddPromptModal
				isVisible={showModal}
				setVisibility={setShowModal}
				createPrompt={createPrompt}
				teamId={teamId}
				teamMembersEmail={teamMembersEmail}
			/>
			{teamPromptsAndVideos.length > 0
			? teamPromptsAndVideos.map((prompt, index) => (<PromptCard key={prompt.id} data={prompt} index={index} />))
			: <Empty />
		}
		</Content>
	);
}
Example #2
Source File: EmptyPlot.jsx    From ui with MIT License 6 votes vote down vote up
EmptyPlot = ({ mini }) => {
  if (mini) {
    return (
      <Empty
        style={{ width: 102 }}
        image={Empty.PRESENTED_IMAGE_SIMPLE}
        description={<></>}
      />
    );
  }

  return (
    <Empty
      description={(
        <>
          <Text type='primary'>
            Nothing to show yet
          </Text>
          <br />
          <Text type='secondary'>
            Results will appear here when they&apos;re available.
          </Text>
        </>
      )}
    />
  );
}
Example #3
Source File: release_branch_detail.js    From art-dashboard-ui with Apache License 2.0 6 votes vote down vote up
render() {

        return(
            <div>

                <Title style={{paddingLeft: "20px", paddingTop: "40px"}} level={2}><Text code>{this.state.branch}</Text></Title>

                {this.state.loading_cards && <Empty/>}
                {!this.state.loading_cards && <Title style={{paddingLeft: "40px", paddingTop: "40px"}} level={4}><Text code>{"Current Advisories"}</Text></Title>}
                {!this.state.loading_cards && <Release_branch_detail_table data={this.state.advisory_details}/>}
                <br/>
                {!this.state.loading_cards && <Title style={{paddingLeft: "40px", paddingTop: "40px"}} level={4}><Text code>{"Previous Advisories"}</Text></Title>}
                {!this.state.loading_cards && <Release_branch_detail_table data={this.state.advisory_details_previous}/>}
            </div>
        )
    }
Example #4
Source File: Card.js    From ncovis-2020 with MIT License 6 votes vote down vote up
function State({ type, width, height }) {
  return (
    <Box width={width} height={height} type={type}>
      {type === "loading" ? (
        <MiddleSpin />
      ) : (
        <MiddleEmpty
          description="暂无数据"
          image={Empty.PRESENTED_IMAGE_SIMPLE}
        />
      )}
    </Box>
  );
}
Example #5
Source File: customize.jsx    From virtuoso-design-system with MIT License 6 votes vote down vote up
storiesOf('antd/empty', module).add('customize', () => 
  <Empty
    image="https://gw.alipayobjects.com/zos/antfincdn/ZHrcdLPrvN/empty.svg"
    imageStyle={{
      height: 60,
    }}
    description={
      <span>
        Customize <a href="#API">Description</a>
      </span>
    }
  >
    <Button type="primary">Create Now</Button>
  </Empty>,
  { docs: { page: () => (<><h1 id="enus">en-US</h1>
<p>Customize image source, image size, description and extra content.</p></>) } });
Example #6
Source File: Carousel.js    From video-journal-for-teams-fe with MIT License 5 votes vote down vote up
function Carousel({ component: Component, ...props }) {
	const [axis, setAxis] = useState(0);
	const [width, setWidth] = useState(window.innerWidth);
	const carouselList = useRef(null);

	useEffect(() => {
		function handleResize() {
			setWidth(window.innerWidth);
		}

		window.addEventListener("resize", handleResize);

		return function cleanup() {
			window.removeEventListener("resize", handleResize);
		};
	}, [width]);

	const scroll = (direction) => {
		let newAxis;
		const scrollAmount = carouselList.current.scrollWidth / carouselList.current.childElementCount;
		const maxScrollWidth = carouselList.current.scrollWidth - carouselList.current.clientWidth;

		if (axis + direction * scrollAmount > maxScrollWidth) {
			newAxis = maxScrollWidth;
		} else if (axis + direction * scrollAmount < 0) {
			newAxis = 0;
		} else {
			newAxis = axis + direction * scrollAmount;
		}

		carouselList.current.scrollTo({
			top: 0,
			left: newAxis,
			behavior: "smooth",
		});
		setAxis(newAxis);
	};

	return (
		<Content className="carousel">
			<Button
				onClick={() => {
					scroll(-1);
				}}
				disabled={axis === 0 ? true : false}
				className="leftButton">
				<Icon type="left" />
			</Button>
			<div className="carouselItems" ref={carouselList}>
				{props.children}
				{props.data.length > 0 ? props.data.map((item) => <Component key={item.id} data={item} />) : <Empty />}
			</div>
			<Button
				onClick={() => {
					scroll(1);
				}}
				disabled={
					carouselList.current && axis === carouselList.current.scrollWidth - carouselList.current.clientWidth
						? true
						: false
				}
				className="rightButton">
				<Icon type="right" />
			</Button>
		</Content>
	);
}
Example #7
Source File: MyAutoComplete.jsx    From react-sendbird-messenger with GNU General Public License v3.0 5 votes vote down vote up
export function MyAutoComplete({
    style,
    options = [],
    value = '',
    onSelect = () => {},
    onSearch = () => {},
    onChange = () => {},
    placeholder = 'Search for people',
}) {
    return (
        <div style={style}>
            <AutoComplete
                options={options}
                style={{ width: '100%' }}
                onSelect={onSelect}
                onSearch={onSearch}
                filterOption={(inputValue, option) =>
                    option.value
                        .toUpperCase()
                        .indexOf(inputValue.toUpperCase()) !== -1
                }
                notFoundContent={<Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />}
                allowClear={true}
                backfill={true}
                // autoFocus={true}
            >
                <Input
                    value={value}
                    onChange={onChange}
                    placeholder={placeholder}
                    prefix={
                        <SearchOutlined
                            style={{
                                fontSize: 16,
                                color: '#d9d9d9',
                            }}
                        />
                    }
                />
            </AutoComplete>
        </div>
    )
}
Example #8
Source File: index.js    From react-drag with MIT License 5 votes vote down vote up
IndexView = props => {
  const { dispatch, personalList, publicList, orginzationList } = props;

  useEffect(() => {
    // 首次执行

    dispatch({
      type: 'components/getPersonalComponents',
    });
    dispatch({
      type: 'components/getPublicComponents',
    });
    dispatch({
      type: 'components/getOrginzationComponents',
    });
  }, []);

  const renderList = list => {
    if (list && list.length > 0) {
      return (
        <div style={{ display: 'flex', flexWrap: 'wrap' }}>
          {list.map(item => {
            return <MyCard info={item} key={item.id} />;
          })}
        </div>
      );
    } else {
      return (
        <div
          style={{
            display: 'flex',
            justifyContent: 'center',
            alignItems: 'center',
            height: '50vh'
          }}
        >
          <Empty description="暂无组件"/>
        </div>
      );
    }
  };

  return (
    <div className={styles.content}>
      <div className={styles.editRegion}>
        <div className={styles.dragRegion}>
          <Tabs>
            <TabPane tab="个人组件" key="1">
              {renderList(personalList)}
            </TabPane>
            <TabPane tab="公共组件" key="2">
              {renderList(publicList)}
            </TabPane>
            <TabPane tab="组织组件" key="3">
              {renderList(orginzationList)}
            </TabPane>
          </Tabs>
        </div>
      </div>
    </div>
  );
}
Example #9
Source File: applog.jsx    From juno with Apache License 2.0 5 votes vote down vote up
render() {
    const { zoneCode, appName, env, url, loading, typ } = this.state;
    const colSpan = {
      xxl: 6,
      xl: 6,
      lg: 6,
      md: 6,
      xs: 6,
    };

    if (!env) {
      return (
        <div style={{ marginTop: 10 }}>
          <Empty description={'请选择环境和可用区'} style={{ padding: '100px' }} />
        </div>
      );
    }

    return (
      <div className={styles.applog} style={{ backgroundColor: '#f7f8fa' }}>
        <div
          style={{
            marginTop: 5,
            height: '100%',
          }}
        >
          <Card
            style={{ height: '100%', display: 'flex', flexDirection: 'column' }}
            bodyStyle={{ height: '100%', flex: 1, display: 'flex', flexDirection: 'column' }}
            title={
              <Row>
                <Col {...colSpan}>
                  <Select
                    showSearch
                    style={{ width: '90%' }}
                    placeholder="选择查询日志类型"
                    optionFilterProp="children"
                    value={typ}
                    onSelect={this.onSelectLogTyp}
                  >
                    <Select.Option key="console" value="console">
                      启动日志
                    </Select.Option>
                    <Select.Option key="biz" value="biz">
                      业务日志
                    </Select.Option>
                    <Select.Option key="jupiter" value="jupiter">
                      框架日志
                    </Select.Option>
                  </Select>
                </Col>

                <Button
                  type="primary"
                  onClick={this.getList}
                  style={{ marginRight: `16px` }}
                  htmlType={`button`}
                >
                  查询
                </Button>
              </Row>
            }
          >
            <Spin style={{ flex: 1 }} spinning={loading}>
              {url && <Pannel url={url} />}
            </Spin>
          </Card>
        </div>
      </div>
    );
  }
Example #10
Source File: sourceImage.js    From camel-store-admin with Apache License 2.0 5 votes vote down vote up
render(){
    const { fileList, type } = this.conversionObject();
    const { previewImage, previewVisible } = this.state
    const { restprops, onhandleEdit, onChange } = this.props
    const wh = window.screen.height

    return(
      <Fragment>
        <span>
        { type !== 'video'
          ? fileList.map((item,index) =>
            <BodyRow
              key={index}
              item={item}
              handlePreview={this.handlePreview}
              handleDelete={onChange ? (item) => this.handleDelete(item) : undefined}
              handleEdit={onhandleEdit ? (item) => onhandleEdit(item) : undefined}
              handleItem={(item) => restprops && restprops.onSelectItem(item)}
              className={restprops && restprops.className || undefined}
              isSelect={restprops && restprops.selectList && restprops.selectList.includes(item.url)}
            /> )
          : null
        }
        </span>
        { type !== 'video' && fileList.length === 0 && <Empty /> }
        <Modal
          centered
          destroyOnClose
          zIndex={1010}
          footer={null}
          visible={previewVisible}
          onCancel={this.handleCancel}
          bodyStyle={{maxHeight: `${wh-200}px`, textAlign: 'center', overflowY: 'auto', paddingTop: 56}}>
          { previewImage && ['mp4','mp3'].includes(previewImage.split('.').reverse()[0])
            ? <video src={previewImage}  style={{ maxHeight: `${wh-360}px` }} controls="controls"/>
            : <img alt="example" style={{ width: '100%' }} src={previewImage} />
          }
        </Modal>
      </Fragment>
    )
  }
Example #11
Source File: Dialog.js    From label-studio-frontend with Apache License 2.0 5 votes vote down vote up
HtxDialogView = inject("store")(
  observer(({ store, item }) => {
    if (!store.task || !store.task.dataObj) {
      return <Empty />;
    }

    const result = [];
    let name = item.value;

    if (name.charAt(0) === "$") {
      name = name.substr(1);
    }

    store.task.dataObj[name].forEach((item, ind) => {
      let bgColor;

      if (item.name) {
        bgColor = convertToRGBA(stringToColor(item.name), 0.1);
      }

      result.push(
        <DialogView
          key={ind}
          name={item.name}
          hint={item.hint}
          text={item.text}
          selected={item.selected}
          date={item.date}
          id={item.id}
          bg={bgColor}
        />,
      );
    });

    return (
      <div>
        <div
          style={{
            display: "flex",
            flexFlow: "column",
            maxHeight: "500px",
            overflowY: "scroll",
            paddingRight: "10px",
            marginTop: "10px",
          }}
        >
          {result}
        </div>
        <Divider dashed={true} />
      </div>
    );
  }),
)
Example #12
Source File: FilterResultTable.test.jsx    From ui with MIT License 5 votes vote down vote up
describe('FilterResultTable', () => {
  it('Should show Empty if passed empty or incorrect input', () => {
    const emptyInput = [];

    let component = mount(
      <FilterResultTable tableData={emptyInput} />,
    );

    let table = component.find(Table);
    let empty = component.find(Empty);

    // No table, and show an empty component
    expect(table.length).toBe(0);
    expect(empty.length).toBe(1);

    const incorrectInput = {
      key1: {},
      key2: {},
    };

    component = mount(
      <FilterResultTable tableData={incorrectInput} />,
    );

    table = component.find(Table);
    empty = component.find(Empty);

    // No table, and show an empty component
    expect(table.length).toBe(0);
    expect(empty.length).toBe(1);
  });

  it('Should show a Table if passed the correct input', () => {
    const component = mount(
      <FilterResultTable tableData={correctInput} />,
    );

    const table = component.find(Table);

    // Check that table exists
    expect(table.length).toBe(1);
  });

  it('The table should have 4 columns, and n + 1 number of rows', () => {
    const component = mount(
      <FilterResultTable tableData={correctInput} />,
    );

    const numRows = Object.keys(correctInput.after).length;
    const table = component.find(Table);

    const headerRow = table.find('HeaderRow');
    const columns = headerRow.find('Cell');
    const bodyRow = table.find('BodyRow');

    // 4 columns : title, before, after, percent removed
    expect(columns.length).toBe(4);
    expect(headerRow.length + bodyRow.length).toBe(numRows + 1);
  });
});
Example #13
Source File: slideNav.js    From ant-simple-pro with MIT License 5 votes vote down vote up
render() {
    const { Sider } = Layout;
    const { getMenuTree, collapsed, location, loadingMenuTree } = this.props;
    const { openKeys , theme } = this.state;
    const defaultProps = collapsed ? {} : { openKeys };
    const defaultSelectedKeys = location.pathname;
    return (
        <Sider trigger={null} collapsible collapsed={collapsed} collapsedWidth={collapsed ? 80 : 200} className={theme === 'light' ? 'ant-layout-sider-light' : 'ant-layout-sider-dark'}>
          <div className={theme === 'light' ?`${style.logon} ${style.Shadow}`:`${style.logon}`}>
            <Link to="/home">
              <SvgIcon iconClass='logon' fontSize='30px' />
              <CSSTransition in={!collapsed} classNames="fade" timeout={200} unmountOnExit>
                 <h2>Ant Simple Pro</h2>
               </CSSTransition>
            </Link>
          </div>
          <div className={style.menuContainer}>
            {
              loadingMenuTree ?
                (getMenuTree.length ? (<Menu mode="inline"
                  onOpenChange={this.onOpenChange}
                  defaultSelectedKeys={[defaultSelectedKeys]}
                  selectedKeys={[defaultSelectedKeys]}
                  defaultOpenKeys={openKeys}
                  {...defaultProps}
                  theme={theme}
                  className={style.menu}>
                    {this.rednerMenu(getMenuTree)}
                </Menu>) : <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} className={style.empty} />) : <LoadingData />
            }
          </div>
          <div className={style.switchThem}>
            <CSSTransition in={!collapsed} classNames="fade" timeout={200} unmountOnExit>
              <Tooltip placement="leftTop" title='主题'>
                <BulbOutlined />
              </Tooltip>
            </CSSTransition>
            <Switch checkedChildren="dark" unCheckedChildren="light" checked={theme === 'dark'} onChange={this.changeTheme}/>
          </div>
        </Sider>
    );
  }
Example #14
Source File: Competition.js    From 4IZ268-2021-2022-ZS with MIT License 5 votes vote down vote up
Competition = () => {

    const location = useLocation()

    const compId = location.pathname.slice(location.pathname.lastIndexOf('/') + 1)

    const setTitle = useStore((state) => state.setTitle)
    const setSubtitle = useStore((state) => state.setSubtitle)

    const [selected, setSelected] = useState({ type: 'class', value: '' });

    const classesQuery = useQuery(['classes', { comp: compId }], getClasses);

    const competitionQuery = useQuery(['competition', { comp: compId }], getCompetitionInfo);

    useSetInfiniteDataStore(compId);

    useEffect(() => {
        if (competitionQuery.data) {
            setTitle(competitionQuery.data.name)
            setSubtitle(competitionQuery.data.date)
        }
    }, [competitionQuery.data, setTitle, setSubtitle])

    useEffect(() => {
        if (!selected.value.length) {
            if (classesQuery.data?.classes) {
                if (classesQuery.data.classes.length) {
                    setSelected({ type: 'class', value: classesQuery.data.classes[0].className })
                }
            }
        }
    }, [classesQuery.data, selected.value.length])

    if (!selected.value.length) {
        return (
          <>
            <div className={'empty-wrapper'}>
              <Empty description='Ještě nebyla načtena žádná data.'/>
            </div>
          </>
        )
    }

    return (
        <>
            <div className={'container'}>
                <div className={'passings'}>
                    {selected !== undefined ?
                        <LastPassings
                            selectedResults={selected}
                            setSelectedResults={setSelected}
                        /> : null}
                </div>
                <div className={'sidebar'}>
                    <ClassPicker
                        classList={classesQuery.data?.classes}
                        selectedResults={selected}
                        setSelectedResults={setSelected}
                    />
                </div>
                <div className={'data'}>
                    {selected !== undefined ?
                        <ResultsTable
                            competitionId={compId}
                            selectedResults={selected}
                            setSelectedResults={setSelected}
                        /> : null}
                </div>
            </div>
        </>
    )
}
Example #15
Source File: Card.js    From ncovis-2020 with MIT License 5 votes vote down vote up
MiddleEmpty = styled(Empty)`
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  margin: 0;
`
Example #16
Source File: basic.jsx    From virtuoso-design-system with MIT License 5 votes vote down vote up
storiesOf('antd/empty', module).add('basic', () => <Empty />, { docs: { page: () => (<><h1 id="enus">en-US</h1>
<p>Simplest Usage.</p></>) } });
Example #17
Source File: ContactContainer.jsx    From ResoBin with MIT License 5 votes vote down vote up
ContactContainer = () => {
  const [loading, setLoading] = useState(false)
  const [form] = Form.useForm()

  const handleSubmit = async (payload) => {
    try {
      setLoading(true)
      await API.feedback.share({ payload })
      toast({ status: 'success', content: 'Feedback shared successfully' })
      form.resetFields()
    } catch (error) {
      toast({ status: 'error', content: error })
    } finally {
      setLoading(false)
    }
  }

  return (
    <>
      <PageHeading>
        <PageTitle>Contact us</PageTitle>
      </PageHeading>

      <StyledForm
        form={form}
        name="contact"
        onFinish={handleSubmit}
        layout="vertical"
        requiredMark={false}
      >
        <Form.Item
          name="subject"
          label="Subject"
          rules={[
            { required: true, message: 'Subject is required.' },
            { min: 3, message: 'Subject must be atleast 3 characters.' },
            { max: 100, message: 'Subject must be atmost 100 characters.' },
          ]}
        >
          <Input placeholder="Type something..." />
        </Form.Item>

        <Form.Item name="message" label="Message">
          <Input.TextArea
            autoSize={{ minRows: 1, maxRows: 10 }}
            placeholder="Type something..."
            rules={[
              { max: 1000, message: 'Message must be atmost 1000 characters.' },
            ]}
          />
        </Form.Item>

        <div style={{ display: 'inline' }}>
          <ButtonSquare type="primary" htmlType="submit" loading={loading}>
            Submit
          </ButtonSquare>
        </div>
      </StyledForm>

      {/* <DeveloperList /> */}
      <Aside title="Contributors">
        <Empty description={<PageSubtitle>Coming soon!</PageSubtitle>} />
      </Aside>
    </>
  )
}
Example #18
Source File: App.jsx    From notence with MIT License 5 votes vote down vote up
EmptyView = styled(Empty)`
  margin-top: 12em;
`
Example #19
Source File: profile.js    From ctf_platform with MIT License 4 votes vote down vote up
render() {
        return (
            <Layout className="layout-style">


                {this.state.loading && (
                    <div style={{ position: "absolute", left: "55%", transform: "translate(-55%, 0%)", zIndex: 10 }}>
                        <Ellipsis color="#177ddc" size={120} ></Ellipsis>
                    </div>
                )}
                {
                    !this.state.targetUser && !this.state.loading && (
                        <div style={{ height: "100%", width: "100%" }}>
                            <br /><br /><br />
                            <Empty
                                image={<FrownOutlined />}
                                imageStyle={{ fontSize: "500%", color: "#177ddc" }}
                                description={<h1>We were unable to find the user "{this.props.match.params.user}"</h1>}
                            />
                        </div>
                    )
                }
                {
                    this.state.targetUser && !this.state.loading && (
                        <Layout style={{ height: "100%", width: "100%", padding: "3%", backgroundColor: "rgba(0, 0, 0, 0)" }}>
                            <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center" }}>
                                <div style={{ display: "flex" }}>
                                    <div style={{ display: "flex", marginRight: "5ch", alignItems: "center", justifyItems: "center" }}>
                                        <Avatar style={{ backgroundColor: "transparent", marginRight: "3ch", width: "10ch", height: "10ch" }} size='large' src={"/static/profile/" + this.state.targetUser + ".webp"} />
                                        <h1 style={{ fontSize: "5ch" }}>{this.state.targetUser}</h1>
                                    </div>
                                    <div>
                                        <h1 style={{ fontSize: "5ch", color: "#faad14" }}><span style={{ color: "#d48806", fontSize: "1.5ch" }}><u>Score:</u> </span>{this.state.userScore}</h1>
                                    </div>
                                </div>
                            </div>
                            <Divider />
                            <h1 style={{ fontSize: "3ch" }}>Score History</h1>
                            <div style={{ height: 375, width: "100%", backgroundColor: "rgba(0, 0, 0, 0.3)", border: "5px solid transparent", borderRadius: "20px", padding: "10px", margin: "10px" }}>
                                <ResponsiveContainer width="90%" height={350}>
                                    <AreaChart height={350} data={this.state.graphData}
                                        margin={{ top: 10, right: 15, left: 15, bottom: 15 }}>

                                        <defs>
                                            <linearGradient id="color1" x1="0" y1="0" x2="0" y2="1">
                                                <stop offset="5%" stopColor="#791a1f" stopOpacity={0.3} />
                                                <stop offset="95%" stopColor="#f89f9a" stopOpacity={0.1} />
                                            </linearGradient>
                                        </defs>
                                        <XAxis dataKey="Time">
                                            <Label offset={-5} position="insideBottom" style={{ fill: 'rgba(207, 207, 207, 1)' }}>
                                                Time
                                            </Label>
                                        </XAxis>
                                        <YAxis >
                                            <Label offset={-10} position='insideLeft' style={{ fill: 'rgba(207, 207, 207, 1)' }}>
                                                Score
                                            </Label>
                                        </YAxis>
                                        <CartesianGrid strokeDasharray="3 3" />

                                        <Tooltip labelStyle={{ backgroundColor: "#1c2b3e" }} contentStyle={{ backgroundColor: "#1c2b3e" }} wrapperStyle={{ backgroundColor: "#1c2b3e" }} />
                                        <Area isAnimationActive={false} type="monotone" dataKey="Score" stroke="#d32029" fillOpacity={1} fill="url(#color1)" />
                                    </AreaChart>
                                </ResponsiveContainer>

                            </div>
                            <Table style={{ marginTop: "2vh" }} dataSource={this.state.scores} pagination={{ pageSize: 10 }} locale={{
                                emptyText: (
                                    <div style={{ display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", marginTop: "10vh" }}>
                                        <FileUnknownTwoTone style={{ color: "#177ddc", fontSize: "400%", zIndex: 1 }} />
                                        <h1 style={{ fontSize: "200%" }}>{this.state.targetUser} has not completed any challenges/bought any hints</h1>
                                    </div>
                                )
                            }}>
                                <Column width={1} title="Challenge/Hint" dataIndex="challenge" key="challenge"
                                    render={(text, row, index) => {
                                        if (row.challengeID !== "") return <Link to={"/Challenges/" + row.challengeID}><a style={{ fontWeight: 700 }}>{text}</a></Link>;
                                        else return (<span>{text}</span>);
                                    }} />
                                <Column width={30} title="Score Change" dataIndex="score" key="score" />
                                <Column width={30} title="Solved Timestamp" dataIndex="time" key="time" />
                            </Table>
                        </Layout>

                    )
                }
            </Layout>
        )
    }
Example #20
Source File: index.js    From crawel with MIT License 4 votes vote down vote up
export default function() {
  const [list, setList] = useState([
    'https://www.jd.com/',
    // 'https://zhuanlan.zhihu.com/p/67491524',
    'https://ai.taobao.com/'
  ]);
  const [fetchData, setFetchData] = useState([]);
  const [recentData, setRecentData] = useState(() => {
    try {
      let dataStr = localStorage.getItem('recent') || []
      return JSON.parse(dataStr)
    }catch(err) {
      return []
    }
  });
  const [isLoading, setLoading] = useState(false);
  const handleChange = (value) => {
    console.log(`selected ${value}`);
    data = value;
  }

  const crawel = () => {
    setLoading(true)
    data && fetch(`${SERVER_URL}/mz/fetch`, {
      method: 'POST',
      body: data
    }).then(res => res.json()).then(res => {
      if(res.state) {
        notification.success({
          message: '抓取完成',
          description: `已成功截取${data.length}张图和网页文本`
        })
        if(res.data) {
          // 求出数据增量
          let curAddItem = res.data.filter(item => !recentData.includes(item))
          setFetchData(curAddItem)
          // 更新最近爬取数据
          setRecentData(res.data)
          // 将爬取数据存入storage
          localStorage.setItem('recent', JSON.stringify(res.data))
        }
      }else {
        notification.error({
          message: '抓取失败',
          description: res.msg
        })
      }
      res && setLoading(false)
    })
  }

  useEffect(() => {
    
  }, [])
  return (
    <div className={styles.normal}>
      <Spin tip="正在疯狂爬取中..." spinning={isLoading}>
        <>
          <Select mode="tags" style={{ width: '50%', marginRight: '20px' }} placeholder="Tags Mode" onChange={handleChange}>
            {list.map(item => {
              return <Option key={item}>{ item }</Option>
            })}
          </Select>
          <Button type="primary" onClick={crawel}>爬取</Button>
          <h3>抓取结果</h3>
          <div className={styles.result}>
            {
              fetchData.length ? fetchData.map(item => {
                return <div className={styles.item} key={item}>
                  <div className={styles.bg} style={{backgroundImage: `url(${`http://192.168.31.123/${item}.jpg`})`}}></div>
                  <div className={styles.viewLink}>
                    <a href={`http://192.168.31.123/${item}.json`} download={`${item}.json`} target="_blank">下载数据</a>
                    <a href={`http://192.168.31.123/${item}.jpg`} target="_blank">查看图片</a>
                  </div>
                </div>
              }) :
              <Result
                status="404"
                title="赶快试试搜索你想要爬取的网站吧~"
                subTitle="在搜索框输入网址,即可自动抓取网页, 支持多选输入."
              />
            }
          </div>
        </>
      </Spin>
      <Drawer
          title="最近抓取"
          placement="right"
          closable={false}
          visible={true}
          mask={false}
          width={360}
        >
          {
              recentData.length ? recentData.map(item => {
                return <div className={classnames(styles.item, styles.recent)} key={item}>
                  <div className={styles.bg} style={{backgroundImage: `url(${`http://192.168.31.123/${item}.jpg`})`}}></div>
                  <div className={styles.viewLink}>
                    <a href={`http://192.168.31.123/${item}.json`} download={`${item}.json`} target="_blank">下载数据</a>
                    <a href={`http://192.168.31.123/${item}.jpg`} target="_blank">查看图片</a>
                  </div>
                </div>
              }) :
              <div style={{marginTop: '160px'}}><Empty description="还没有爬取数据哦~" /></div> 
            }
        </Drawer>
    </div>
  );
}
Example #21
Source File: index.js    From certificate-generator with MIT License 4 votes vote down vote up
function ListEvents(props) {

const { Meta } = Card;
	/*Recebe o organizador e o JSON de organizadores*/
	const { organizador, users } = props

	/*Trabalham para trocar a tela da lista de eventos com o formulário de edição/criação*/
	const [ toEditFormEvent, setToEditFormEvent] = useState(false);
	const [ toCreateFormEvent, setToCreateFormEvent] = useState(false);
	const [ toProfile, setProfile] = useState(false);
	const [ toList, setList] = useState(false);
	const [ toSeeEvents, setSeeEvents] = useState(false);

	/*Esta variavel guarda o evento referente quando o botão check participantes for acionado*/
	const [ eventChecked, setEventChecked] = useState('');

	/*JSON dos eventos*/
	const [ eventos, setEventos ] = useState(eventosData)

	/*Vaiável para saber qual evento foi editado*/
	const [ eventEdited, setEventEdited ] = useState('')
	  
	//Dados do evento:
	//Serão usados para editar no formulário
	const [ company, setCompany] = useState('');
	const [ course, setCourse ] = useState('');
	const [ startDate, setStartDate ] = useState('');
	const [ finishDate, setFinishDate ] = useState('');
	const [ workload, setWorkload ] = useState('');

	/*---------- Assinatura Digital ----------*/
	const [ imageURL, setImageURL ] = useState(null)

	const sigCanvas = useRef({})

	const clear = () => sigCanvas.current.clear();

	const save = () => {
		setImageURL(sigCanvas.current.getTrimmedCanvas().toDataURL("image/png"))
	}

	/*--------- Formulário para criar evento ---------*/
	const { RangePicker } = DatePicker;

	/*Constroi o layout do input de datas*/
	const formItemLayout = {
	  labelCol: {
	    xs: {
	      span: 24,
	    },
	    sm: {
	      span: 8,
	    },
	  },
	  wrapperCol: {
	    xs: {
	      span: 24,
	    },
	    sm: {
	      span: 16,
	    },
	  },
	};

	/*Constroi o layout do input de name/curso*/
	const formInputLayout = {
	  labelCol: {
	    span: 4,
	  },
	  wrapperCol: {
	    span: 8,
	  },
	};

	/*Define as regras para que a data seja aceita */
	const rangeConfig = {
	  rules: [
	    {
	      type: 'array',
	      required: true,
	      message: 'Este campo é obrigatório!',
	    },
	  ],
	};

	/*Define as regras para que os inputs de texto sejam aceitos */
	const rangeInputs = {
		rules: [
	    	{
	        	required: true,
	            message: 'Por favor, preencha esse campo',
	        },
		],
	};

	/*Função acionada quando um evento for ser criado*/
	/*Ela não é chamada caso os campos não forem preeenchidos*/
	const onFinish = fieldsValue => {

	    /*Dados do calendário*/
	    const rangeValue = fieldsValue['range-picker'];

	    if(imageURL === null) {
	    	message.error('Por favor, escreva sua assinatura digital')
	    } else {
	    	setEventos([
				...eventos, {
				user: organizador,
				company: fieldsValue.company, 
				course: fieldsValue.course,
				startDate: rangeValue[0].format('DD-MM-YYYY'), 
				finishDate: rangeValue[1].format('DD-MM-YYYY'), 
				workload: fieldsValue.workload, 
				logo: "https://miro.medium.com/max/478/1*jriufqYKgJTW4DKrBizU5w.png", 
				digitalSignature: imageURL
			}
		])

		message.success('Evento criado com sucesso')

		/*Retira o componente do formulário de eventos e volta para a lista*/
	    setToCreateFormEvent(false)
	    }  
	};

	/*Buscando os eventos do organizador*/

	let eventsOfOrganizer = []

	eventos.map(evento => {
		if(evento.user === organizador) {
			eventsOfOrganizer.push(evento)
		}
	})

	/*Verifica se existem eventos cadastrados para mostrar elemento do Antd 'No Data'*/
	let noEvents = true

	/* ------------- Deletando Eventos ---------------*/
	const deleteEvent = (eventToBeDeleted) => {

		message.success('O evento foi excluido')

		setEventos( eventsOfOrganizer.filter(evento => {
			if(evento.course !== eventToBeDeleted) {
				return evento
			}
		}))
	}

	/* -------------- Editando eventos ----------------*/
	const beforeEdit = () => {

		if( !company || !course || !startDate || !finishDate || ! workload || !imageURL){
			message.error('Por favor, não deixe seus dados vazios.')
			//quando o formulário aparece na tela, essa mensagem aparece, caso o campo não tenha sido preenchido.
		} else {
			setToEditFormEvent(!toEditFormEvent)
		}
	}

	//Ao salvar as informações editadas:
	const saveEditFormEvent = (e) => {
		e.preventDefault();
		//Os campos que devem ser preenchidos:
		if( !company || !course || !startDate || !finishDate || ! workload || !imageURL){
			message.error('Por favor, preencha todos os campos do formulário.')
			//quando o formulário aparece na tela, essa mensagem aparece, caso o campo não tenha sido preenchido.

		} else {
			/*Atualizando o evento do organizador*/
			setEventos(eventsOfOrganizer.map(evento => {
				
				/*Mudando somente o evento requerido*/
				if(eventEdited === evento.course) {
					evento['company'] = company
					evento['course'] = course
					evento['startDate'] = startDate
					evento['finishDate'] = finishDate
					evento['workload'] = workload
					evento['digitalSignature'] = imageURL

					return evento;
				} else {
					return evento;
				}
				
			}) )

			message.success('Os dados do evento foram atualizados com sucesso!')

			/*Voltando para a lista de eventos*/
			//setToEditFormEvent(!toEditFormEvent)
		}
		
	}

	const clickEditFormEvent = (eventToBeEdit) => {

		/*Trocando a lista de eventos pelo formulário de edição*/
		setToEditFormEvent(!toEditFormEvent)

		/*Guardando qual evento será editado*/
		setEventEdited(eventToBeEdit.course)

		setCompany(eventToBeEdit.company)
		setCourse(eventToBeEdit.course)
		setStartDate(eventToBeEdit.startDate)
		setFinishDate(eventToBeEdit.finishDate)
		setWorkload(eventToBeEdit.workload)
	}

	/*Esta função é acionada quando o botão para o check list é acionado*/
	const saveEventToList = (eventToList) => {
		setList(true)
		setEventChecked(eventToList)
	}

	/*Esta função é acionada quando o botão para mais infomações do evento*/
	const seeEvents = (eventToList) => {
		setSeeEvents(true)
		setEventChecked(eventToList)
	}

	return(
		<>
		
		<div style={{ display: ( toEditFormEvent || toCreateFormEvent || toProfile || toList || toSeeEvents )?  'none' : null }}>

			<h1 className="title-2-list-events"><UserOutlined onClick={() => setProfile(true)}/> {organizador}</h1>

			<Button className="button-add" onClick={() => setToCreateFormEvent(true)}><UsergroupAddOutlined/> Cadastrar mais um evento</Button>
			
			<br/>
			<h1 className="title">Eventos Cadastrados</h1>
			<div className="listEvents">
			{
				eventos.map(eventoJson => {

					if(eventoJson.user === organizador ){
						noEvents = false
						return(
							<Card 
								style={{ width: 300 }}
								    cover={
								     	<img
								   			alt="Poster do evento"
								    		src="https://jaquelinecramos.files.wordpress.com/2018/03/dyfqkqaw0aad5xm.jpg?w=776"
								      />
								    }
								    actions={[
								    	<>
								    	<Popover content={<h5>Ver mais info. do evento</h5>}>
								     		<Button style={{ borderColor: 'transparent'}} onClick={() => seeEvents(eventoJson) }><HeartOutlined key="edit" /></Button>
								     	</Popover>

								     	<Popover content={<h5>Editar evento</h5>}>
								     		<Button style={{ borderColor: 'transparent'}} onClick={() =>  clickEditFormEvent(eventoJson) } ><FormOutlined key="edit" /></Button>
								     	</Popover>

								     	<Popover content={<h5>Participantes</h5>}>
								     		<Button style={{ borderColor: 'transparent'}} onClick={() =>  saveEventToList(eventoJson)}><TeamOutlined key="ellipsis" /></Button>
								    	</Popover>

								     	<Popconfirm 
								     		title="Você tem certeza de que quer excluir este evento?"
								     		onConfirm={() => deleteEvent(eventoJson.course) }
								     		okText="Sim"
								     		cancelText="Não"
								     	>
								    		<Button style={{ borderColor: 'transparent'}} ><CloseOutlined key="edit" /></Button>
								    	</Popconfirm>
								    	</>
								    ]}
								  >
								    <Meta
								      avatar={<Avatar src="https://cdn-images-1.medium.com/max/1200/1*B8rGvo7fJ7qL4uFJ_II_-w.png" />}
								      title={<h4 style={{ color: '#C6255A'}}>{eventoJson.course}</h4>}
								      description={
								      		<>
								      			<h5 style={{ fontSize: '12px'}}>Inicio: &nbsp;{eventoJson.startDate}</h5>
								      			
								      			<h5 style={{ fontSize: '12px'}}>Encerramento: &nbsp;{eventoJson.finishDate}</h5>
								      		</>
								      	}
								    />
							</Card>
						)
					}
				})
			}
			{ noEvents && <Empty style={{marginTop: '5%'}}/> }
			</div>

		</div>
		{toEditFormEvent && 
		// Mostra na tela o formulário com os campos para serem editados
		//o value está trazendo as informações do último cadastrado "Lucas...."
		//quando eu troco o nome do course (Evento), altera o nome dos 3 eventos que estão sendo mostrados na tela
			<div className="edit-event"
				style={{ display: toEditFormEvent ?  'block' : 'none' }} >

				<h2 className="edit-event-title">Edite os dados do seu evento:</h2>
				<h4>Comunidade:</h4>
				<Input 
					className="edit-event-input" 
					placeholder="Comunidade" 
					value={company} 
					onChange={ newValue => setCompany(newValue.target.value) } />
				<br/>
				<h4>Evento:</h4>
				<Input 
					className="edit-event-input" 
					placeholder="Evento" 
					value={course} 
					onChange={ newValue => setCourse(newValue.target.value) }/>
				<br/>
				<h4>Data de Inicio:</h4>
				<Input 
					className="edit-event-input" 
					placeholder="Data de Início" 
					value={startDate} 
					onChange={ newValue => setStartDate(newValue.target.value) }/>
				<br/>
				<h4>Data de Encerramento:</h4>
				<Input 
					className="edit-event-input" 
					placeholder="Data de Fim" 
					value={finishDate} 
					onChange={ newValue => setFinishDate(newValue.target.value) }/>
				<br/>
				<h4>Carga Horaria:</h4>
				<Input 
					className="edit-event-input" 
					placeholder="Carga Horária" 
					value={workload} 
					onChange={ newValue => setWorkload(newValue.target.value) }/>
				<br/>
				<h4>Assinatura Digital:</h4>
				<div>
					<Popup modal trigger={<Button className="button-open-pad">Abrir Pad para assinar</Button>}>
						{ close => (
							<>
								<SignaturePad ref={sigCanvas}
											  canvasProps={{
											  	className: 'signatureCanvas'
											  }}
								/>
								<Button onClick={save} className="button-save">Salvar</Button>
								<Button onClick={clear} >Apagar Tudo</Button>
								<Button onClick={close} className="button-close" >Fechar</Button>
							</>
						)}
					</Popup>
					<br/>
					<br/>
					{ imageURL ? (
						<img
							src={imageURL}
							alt="Minha assinatura Digital"
							className="buttons-pad"

						/>
					) : null }
				</div>

				<Button 
					className="button-edit-event" type="primary" primary 
					onClick={saveEditFormEvent}>Atualizar dados</Button>
				<br/>

				<Button className="back-edit-event" onClick={beforeEdit}>Voltar para a lista de eventos</Button>
			</div>
		}

		{ toCreateFormEvent && 
			<>
				
				<Form name="time_related_controls" {...formItemLayout} onFinish={onFinish}>  
			      <div className="inputs-event">
			        <h1 className="h1-form-event">Criando um novo evento</h1>
			        <Form.Item
				        {...formInputLayout}
				        {...rangeInputs}
			          className="input-1-event"
				        name="company"
				        label="Comunidade" >

			          <Input placeholder="Digite a comunidade responsável pelo evento" />
			        </Form.Item>

			        <Form.Item
			          {...formInputLayout}
			          {...rangeInputs}
			          className="input-2-event"
			          name="course"
			          label="Curso/Evento">
			          <Input placeholder="Digite o nome do evento"  />
			        </Form.Item>

			        <Form.Item 
			          {...rangeInputs}
			          className="input-3-event"
			          label="Carga Horária" 
			          name="workload" >
			          <InputNumber /> 
			        </Form.Item>

			        <Form.Item 
			          name="range-picker" 
			          className="input-4-event"
			          label="Data de inicio/fim do evento" 
			          {...rangeConfig}>
			          <RangePicker />
			        </Form.Item>

			        <div className="upload-assinature">
			        	<h3 className="h3-form-event">Assinatura Digital:</h3>
			        	<div>
							<Popup modal trigger={<Button className="button-open-pad">Abrir Pad para assinar</Button>}>
								{ close => (
									<>
										<SignaturePad ref={sigCanvas}
													  canvasProps={{
													  	className: 'signatureCanvas'
													  }}
										/>
										<Button onClick={save} className="button-save">Salvar</Button>
										<Button onClick={clear} >Apagar Tudo</Button>
										<Button onClick={close} className="button-close" >Fechar</Button>
									</>
								)}
							</Popup>
							<br/>
							<br/>
							{ imageURL ? (
								<img
									src={imageURL}
									alt="Minha assinatura Digital"
									className="buttons-pad"
								/>
							) : <h4 style={{ color: 'red'}}>Sem assinatura</h4> }
						</div>
			        </div>


			        <Form.Item>
			        	<Button type="primary" htmlType="submit" className="button-events">
			        		Cadastrar Novo Evento
			        	</Button>
			            <br/>
			        </Form.Item>

			         
			      </div>
			    </Form>
				<Button 
					onClick={() => setToCreateFormEvent(false)} 
					className="button-back-from-create"
					>
	                Voltar para a lista de Eventos
	            </Button>
			</>
		}

		{ toProfile && 
			<>
				<ProfileCard organizador={organizador} users={users} assinatura={imageURL}/>
				<Button 
					onClick={() => setProfile(false)}
					className="button-back-of-profile" 
					>
	                Voltar para a lista de Eventos
	            </Button>
			</>
		}

		{ toList &&
			<>
				<ListOfPresents evento={eventChecked}/>
				<Button onClick={() => setList(false)} className="button-back-from-list" style={{ marginButtom: '-20%'}}>
	                Voltar para a lista de Eventos
	            </Button>
	        </>
		}

		{
			toSeeEvents && 
				<>
					<InfoEvent evento={eventChecked}/>
					<Button 
						onClick={() => setSeeEvents(false)}
						className="button-back-of-profile" 
						>
	                	Voltar para a lista de Eventos
	            	</Button>
	            </>
		}
		</>		
			
	);
}
Example #22
Source File: index.js    From website with MIT License 4 votes vote down vote up
Estado = regionWithStyle(({ uf, className }) => {
  const dispatch = useDispatch();
  const sectors = useSelector(getSectors);
  const events = useSelector(getEvents);
  const lastCheck = useSelector(getLastCheck);
  const loading = useSelector(createLoadingSelector([LOAD_SECTORS]));
  const selectedSectors = useSelector(getSelectedSectors);
  const regionInfo = useSelector(getRegions(uf));

  const [categoryFilter, setCategoryFilter] = useState(false);
  const currRegion =
    uf && regions.filter(item => item.initial === uf.toUpperCase())[0];

  const handleCategorySearch = ev => {
    const { value } = ev.target;
    setCategoryFilter(value);
  };

  useEffect(() => {
    ReactGA.initialize(process.env.NEXT_PUBLIC_GA_KEY);
    ReactGA.pageview(document.location.pathname);

    dispatch(loadRegions(uf));
    dispatch(
      loadSectors({
        ordering: 'events_count',
        region__initial: currRegion.initial,
        limit: 100
      })
    );

    return function cleanup() {
      dispatch(resetState());
    };
  }, [uf]);

  useEffect(() => {
    if (!sectors.length) return;

    if (!lastCheck) {
      for (let sectorId of Object.keys(selectedSectors).filter(
        key => !!selectedSectors[key]
      )) {
        dispatch(loadEvents(sectorId, currRegion?.initial));
      }
    }

    if (selectedSectors[lastCheck])
      dispatch(loadEvents(lastCheck, currRegion?.initial));
  }, [selectedSectors]);

  const categories = categoryFilter
    ? sectors.filter(item => {
        return normalizeSearch(item.name).includes(
          normalizeSearch(categoryFilter)
        );
      })
    : sectors;

  const categoriesList = categories.filter(item => selectedSectors[item.id]);

  // doesnt reverse array if the
  // category wasnt checked from the ui
  const checkedFromUi = useMemo(() => {
    return !!lastCheck;
  }, [selectedSectors]);
  const filteredCategories = checkedFromUi
    ? categoriesList.reverse()
    : categoriesList;

  const handleSectorCheck = sectorId => ev => {
    dispatch(selectSector(sectorId));
  };

  return (
    <div className={'estado-page ' + className}>
      <Reset />
      <Head>
        <HeadTags region={currRegion} />
        <title>
          Corona Brasil - {currRegion?.name} - Saiba o que está funcionando em
          sua cidade e estado
        </title>
        <link rel='icon' href='/favicon.ico' />
      </Head>

      <RegionProvider region={currRegion}>
        <Header />
        <div className='alert'>
          Você tem alguma informação sobre sua cidade/estado?{' '}
          <a href={EVENTS_FORM} target='__blank'>
            Ajude no combate à pandemia clicando aqui
          </a>
          !
        </div>

        <RegionOverview />

        <article className='description'>
          <div className='title-container'>
            <Title.h1>
              Acontecimentos - {currRegion?.name}
              <Dot type='dark' />
            </Title.h1>
            <SocialSharing message={sharing.whatsapp(currRegion?.name)} />
          </div>

          <div className='contact'>
            {regionInfo?.phone && (
              <div className='phone'>
                <span className='label'>Ouvidoria: </span>
                <a href={`tel:+55${regionInfo?.phone}`}>{regionInfo?.phone}</a>
              </div>
            )}
            <div className='social'>
              {regionInfo?.twitter && (
                <a target='__blank' href={regionInfo?.twitter}>
                  <TwitterOutlined />
                </a>
              )}
              {regionInfo?.instagram && (
                <a target='__blank' href={regionInfo?.instagram}>
                  <InstagramOutlined />
                </a>
              )}
              {regionInfo?.official_site && (
                <a target='__blank' href={regionInfo?.official_site}>
                  <GlobalOutlined />
                </a>
              )}
            </div>
          </div>
          <Text>
            O funcionamento de transportes públicos, bares, restaurantes,
            mercados, farmácias, padarias e outros estabelecimentos está mudando
            a cada semana, em cada estado ou cidade.
            <br /> Confira o que está funcionando no Brasil, até quando e por
            quê.
          </Text>
        </article>

        <section className='events'>
          <div className='events__menu'>
            <List
              header={
                <>
                  <div className='header'>
                    <h2>Categorias</h2>{' '}
                  </div>
                  <div className='search'>
                    <Input
                      prefix={<SearchOutlined />}
                      placeholder='Buscar categoria'
                      onChange={handleCategorySearch}
                    />
                  </div>
                </>
              }
              bordered
              loading={
                loading?.[LOAD_SECTORS]?.phase === 'LOADING' || !sectors.length
              }
            >
              <div className='list-container'>
                {categories.map(item => (
                  <List.Item key={JSON.stringify(item)}>
                    <Checkbox
                      checked={!!selectedSectors?.[item.id]}
                      onChange={handleSectorCheck(item.id)}
                    />
                    <SectorIcon sector={item.id} />

                    <span className='name'>{item.name}</span>
                    <Badge count={item.events_count} />
                  </List.Item>
                ))}
              </div>
            </List>
          </div>
          <div className='events__group'>
            {!filteredCategories.length && (
              <Empty description='Selecione uma categoria.' />
            )}
            {filteredCategories.map(item => (
              <Event
                key={JSON.stringify(item)}
                sector={item.id}
                title={item.name}
              >
                {events?.[item.id] && !events?.[item.id].results.length && (
                  <Empty
                    image={
                      <img width={150} src='/static/icons/loudspeaker.svg' />
                    }
                    description={
                      <div>
                        <p>
                          Ooops, nenhuma informação sobre{' '}
                          <strong>{item.name}</strong> encontrada :/
                        </p>{' '}
                        <a target='__blank' href={EVENTS_FORM}>
                          Você tem alguma informação? Ajude no combate à
                          pandemia clicando aqui!
                        </a>
                      </div>
                    }
                  />
                )}

                {events?.[item.id] &&
                  events?.[item.id].results.map(item => (
                    <Event.Item
                      key={JSON.stringify(item)}
                      event={item}
                      city={item?.city?.name}
                      status={item.status_type}
                      title={item.name}
                      description={item?.text || item?.source?.text}
                    ></Event.Item>
                  ))}
              </Event>
            ))}
          </div>
        </section>
      </RegionProvider>
      <Footer />
    </div>
  );
})
Example #23
Source File: etcd.jsx    From juno with Apache License 2.0 4 votes vote down vote up
render() {
    const { zoneCode, appName, env, records, showService, prefix, suffix } = this.state;

    const { etcd } = this.props.setting.settings;
    const colSpan = {
      xxl: 6,
      xl: 6,
      lg: 6,
      md: 6,
      xs: 6,
    };

    if (!env || !zoneCode) {
      return (
        <div style={{ marginTop: 10 }}>
          <Empty description={'请选择环境和可用区'} style={{ padding: '100px' }} />
        </div>
      );
    }
    if (zoneCode === 'all') {
      return (
        <div style={{ marginTop: 10 }}>
          <Empty description={'请选择可用区'} style={{ padding: '100px' }} />
        </div>
      );
    }

    return (
      <div style={{ backgroundColor: '#f7f8fa' }}>
        <div
          style={{
            marginLeft: 10,
            marginTop: 10,
            marginRight: 10,
            marginBottom: 10,
            paddingTop: 10,
            paddingBottom: 10,
          }}
        >
          <Card
            title={
              <Row>
                <Col {...colSpan}>
                  <Select
                    showSearch
                    style={{ width: '90%' }}
                    placeholder="选择查询前缀"
                    optionFilterProp="children"
                    value={prefix}
                    onSelect={this.onSelectPrefix}
                  >
                    {etcd
                      ?.filter((item) => item.prefix)
                      .map((item, idx) => {
                        return (
                          <Select.Option key={idx} value={item.prefix}>
                            {item.prefix}
                          </Select.Option>
                        );
                      })}
                  </Select>
                </Col>

                <Col {...colSpan}>
                  <Input
                    style={{ width: '90%' }}
                    value={suffix}
                    onChange={this.onChangeSuffix}
                    placeholder="输入查询后缀"
                  />
                </Col>
                <Button
                  type="primary"
                  onClick={this.getList}
                  style={{ marginRight: `16px` }}
                  htmlType={`button`}
                >
                  查询
                </Button>
                <Button onClick={this.reset}>清空条件</Button>
              </Row>
            }
          >
            <div>
              <Row>
                <Table rowKey="id" dataSource={records} columns={this.columns} />
              </Row>
            </div>
          </Card>
        </div>
      </div>
    );
  }
Example #24
Source File: tableDrag.js    From camel-store-admin with Apache License 2.0 4 votes vote down vote up
render() {
    const { columns, dataSource, restProps, total } = this.conversionObject()
    const { scroll, pagination } = restProps;
    const { pageSize, offsetWidthBody } = this.state
    const widthtable = scroll && scroll.x ? ( offsetWidthBody > scroll.x ? offsetWidthBody : scroll.x) : 'auto'

    return (
      <div className={styles.dragTable}>
      {/*<Table*/}
        {/*columns={columns}*/}
        {/*dataSource={dataSource}*/}
        {/*components={this.components}*/}
        {/*pagination={false}*/}
        {/*size='small'*/}
        {/*onRow={(record, index) => ({*/}
          {/*index,*/}
          {/*moveRow: this.moveRow,*/}
        {/*})}*/}
        {/*{...restProps}*/}
      {/*/>*/}
        <DragDropContext onDragEnd={this.onDragEnd}>
        <div className="ant-table-wrapper">
          <div className="ant-spin-nested-loading">
            <div className="ant-spin-container">
              <div className="ant-table ant-table-small ant-table-scroll-position-left">
                <div className="ant-table-content">
                  <div className="ant-table-body" id="tableDragbody" style={ scroll && scroll.x ? {overflowX: 'scroll'} : {}}>
                    <table style={isNaN(widthtable) ? {} : {width:widthtable + 'px'}} id="tableDrag">
                      <thead className="ant-table-thead">
                      <tr>
                        { columns.map(item => {
                          return (<th style={item.width ? { width: `${item.width}px`,userSelect:'none'} : {userSelect:'none'}}><div>{item.title}</div></th>)
                        })}
                      </tr></thead>
                      <Droppable droppableId="droppable">
                        {(provided, snapshot) => (
                          <tbody className="ant-table-tbody" ref={provided.innerRef}>
                            {dataSource.length > 0 && dataSource.map((item, index) => (
                              <Draggable key={item.key} draggableId={item.key} index={index}>
                                {(provided, snapshot) => (
                                  <tr className="ant-table-row ant-table-row-level-0" data-row-key={index}
                                    ref={provided.innerRef}
                                    {...provided.draggableProps}
                                    {...provided.dragHandleProps}
                                    style={getItemStyle(
                                      snapshot.isDragging,
                                      provided.draggableProps.style
                                    )}
                                  >
                                    {columns.map(item_in => {
                                      return (
                                        <td style={item_in.width ? { width: `${item_in.width}px`,userSelect:'none'} : {userSelect:'none'}}>
                                          {item_in.render && item_in.render(item[item_in.dataIndex],item) || item[item_in.dataIndex]}
                                        </td>
                                      )
                                    })}
                                  </tr>
                                )}
                              </Draggable>
                            ))}
                            {provided.placeholder}
                          </tbody>
                        )}
                      </Droppable>
                    </table>
                  </div>
                  {dataSource.length === 0 && <div className="ant-table-placeholder"><Empty /></div>}
                </div>
              </div>
            </div>
          </div>
        </div>
        </DragDropContext>
        { pagination &&
          <Row><Col style={{textAlign:'right', marginTop: 10, marginBottom: 10 }}>
            <Pagination pageSize={pageSize} size="small" total={total} showSizeChanger
                        onChange={this.pageChange} onShowSizeChange={this.pageSizeChange}/>
          </Col></Row> }
      </div>
    );
  }
Example #25
Source File: DiffExprResults.test.jsx    From ui with MIT License 4 votes vote down vote up
describe('DiffExprResults', () => {
  it('renders correctly', () => {
    const component = mount(
      <Provider store={withResultStore}>
        <DiffExprResults
          experimentId={experimentId}
          onGoBack={jest.fn()}
          width={100}
          height={200}
        />
      </Provider>,
    );

    const table = component.find('Table');
    const spin = component.find(Loader);
    expect(spin.length).toEqual(0);
    expect(table.length).toEqual(1);
    expect(table.getElement().props.columns.length).toEqual(7);
    expect(table.getElement().props.columns[0].key).toEqual('lookup');
    expect(table.getElement().props.columns[1].key).toEqual('gene_names');
    expect(table.getElement().props.columns[2].key).toEqual('logFC');
    expect(table.getElement().props.columns[3].key).toEqual('p_val_adj');
    expect(table.getElement().props.columns[4].key).toEqual('pct_1');
    expect(table.getElement().props.columns[5].key).toEqual('pct_2');
    expect(table.getElement().props.columns[6].key).toEqual('auc');

    expect(table.getElement().props.dataSource.length).toEqual(5);
    expect(table.getElement().props.data.length).toEqual(5);
  });

  it('is sorted by descending logFC by default', () => {
    const component = mount(
      <Provider store={withResultStore}>
        <DiffExprResults
          experimentId={experimentId}
          onGoBack={jest.fn()}
          width={100}
          height={200}
        />
      </Provider>,
    );

    const table = component.find('Table');
    expect(table.getElement().props.columns[1].sortOrder).toEqual(null);
    expect(table.getElement().props.columns[2].sortOrder).toEqual('descend');
    expect(table.getElement().props.columns[3].sortOrder).toEqual(null);
    expect(table.getElement().props.columns[4].sortOrder).toEqual(null);
    expect(table.getElement().props.columns[5].sortOrder).toEqual(null);
    expect(table.getElement().props.columns[6].sortOrder).toEqual(null);
  });

  it('can sort the gene names in alphabetical order', async () => {
    const newPagination = {
      current: 1,
      pageSize: 4,
      showSizeChanger: true,
      total: 4,
    };

    const newSorter = {
      column: {
        dataIndex: 'gene_names',
        key: 'gene_names',
      },
      render: jest.fn(),
      columnKey: 'gene_names',
      field: 'gene_names',
      order: 'ascend',
    };

    const component = mount(
      <Provider store={withResultStore}>
        <DiffExprResults
          experimentId={experimentId}
          onGoBack={jest.fn()}
          width={100}
          height={200}
        />
      </Provider>,
    );

    const table = component.find('Table');

    act(() => {
      table.getElement().props.onChange(newPagination, {}, newSorter);
    });

    // // Wait for side-effect to propagate (properties loading and loaded).
    await waitForActions(withResultStore, [DIFF_EXPR_ORDERING_SET, DIFF_EXPR_LOADING, DIFF_EXPR_LOADED]);

    expect(fetchWork).toHaveBeenCalledWith(
      '1234',
      {
        cellSet: 'cluster-a',
        compareWith: 'cluster-b',
        basis: 'scratchpad-a',
        comparisonType: 'between',
        experimentId: '1234',
        name: 'DifferentialExpression',
      },
      withResultStore.getState,
      {
        extras: {
          pagination: {
            limit: 4, offset: 0, orderBy: 'gene_names', orderDirection: 'ASC', responseKey: 0,
          },
        },
        timeout: 60,
      },
    );

    expect(withResultStore.getActions()[1]).toMatchSnapshot();
    expect(withResultStore.getActions()[2]).toMatchSnapshot();
  });

  it('Having a focused gene triggers focused view for `eye` button.', () => {
    // Redefine store from `beforeEach`.
    const component = mount(
      <Provider store={withResultStore}>
        <DiffExprResults
          experimentId={experimentId}
          onGoBack={jest.fn()}
          width={100}
          height={200}
        />
      </Provider>,
    );

    const table = component.find('Table');

    table.getElement().props.data.forEach((row) => {
      const lookupComponent = mount(
        <Provider store={withResultStore}>
          {row.lookup}
        </Provider>,
      );

      const focusButtonTooltip = lookupComponent.find('FocusButton Tooltip');

      if (row.gene_names === 'C') {
        expect(focusButtonTooltip.props().title).toContain('Hide');
      } else {
        expect(focusButtonTooltip.props().title).toContain('Show');
      }

      lookupComponent.unmount();
    });
  });

  it('Show comparison settings button works.', () => {
    const component = mount(
      <Provider store={withResultStore}>
        <DiffExprResults
          experimentId={experimentId}
          onGoBack={jest.fn()}
          width={100}
          height={200}
        />
      </Provider>,
    );
    const button = component.find('#settingsButton').first();
    expect(button.text()).toContain('Show');
    button.simulate('click');
    expect(button.text()).toContain('Hide');

    const div = component.find('#settingsText');
    // Should display name of cluster instead of ID
    expect(div.text()).toEqual('cluster a vs. cluster b in New Cluster');
    button.simulate('click');
    expect(button.childAt(0).text()).toEqual('Show settings');
    expect(!div);
  });

  it('Does not show loading indicator if there is no data returned', () => {
    const component = mount(
      <Provider store={noResultStore}>
        <DiffExprResults
          experimentId={experimentId}
        />
      </Provider>,
    );

    const spin = component.find(Loader);
    const empty = component.find(Empty);

    // There should be no loader
    expect(spin.length).toEqual(0);

    // Expect table to contain Empty component
    expect(empty.length).toEqual(1);
  });

  it('Advanced filter button opens and closes the modal', async () => {
    const component = mount(
      <Provider store={withResultStore}>
        <DiffExprResults
          experimentId={experimentId}
          onGoBack={jest.fn()}
          width={100}
          height={200}
        />
      </Provider>,
    );
    const buttons = component.find('Button');
    expect(buttons.at(2).text()).toEqual('Advanced filtering');

    // opening the modal
    buttons.at(2).simulate('click');
    expect(component.find(AdvancedFilteringModal).length).toEqual(1);

    // Adding a filter and applying it
    const dropdown = component.find('Dropdown');
    const menuInstance = shallow(dropdown.props().overlay);
    menuInstance.at(0).simulate('click');
    await waitForActions(withResultStore, [DIFF_EXPR_ORDERING_SET, DIFF_EXPR_LOADING, DIFF_EXPR_LOADED]);

    // closing the modal
    const closeButton = component.find('.ant-modal-close');
    closeButton.simulate('click');
    expect(component.find(AdvancedFilteringModal).length).toEqual(0);
  });

  it('Pathway analysis button opens and closes the modal and dispatches loadDifferentialExpression', async () => {
    const component = mount(
      <Provider store={withResultStore}>
        <DiffExprResults
          experimentId={experimentId}
          onGoBack={jest.fn()}
          width={100}
          height={200}
        />
      </Provider>,
    );

    // On clicking LaunchPathwayAnalysisModal button
    const buttons = component.find('span[children="Pathway analysis"]');
    expect(buttons.at(0).text()).toEqual('Pathway analysis');
    buttons.at(0).simulate('click');

    // Shows the modal
    expect(component.find('LaunchPathwayAnalysisModal').length).toEqual(1);

    // closing the modal
    const closeButton = component.find('.ant-modal-close');
    closeButton.simulate('click');
    expect(component.find('LaunchPathwayAnalysisModal').length).toEqual(0);
  });

  it('Columns without corresponding data are not shown', async () => {
    const component = mount(
      <Provider store={partialResultStore}>
        <DiffExprResults
          experimentId={experimentId}
          onGoBack={jest.fn()}
          width={100}
          height={200}
        />
      </Provider>,
    );

    const table = component.find('Table');
    expect(table.getElement().props.columns.length).toEqual(5);
    expect(table.getElement().props.columns[0].key).toEqual('lookup');
    expect(table.getElement().props.columns[1].key).toEqual('gene_names');
    expect(table.getElement().props.columns[2].key).toEqual('logFC');
    expect(table.getElement().props.columns[3].key).toEqual('p_val_adj');
    expect(table.getElement().props.columns[4].key).toEqual('auc');
  });

  it('Data without corresponding columns are not shown', async () => {
    const component = mount(
      <Provider store={extraResultStore}>
        <DiffExprResults
          experimentId={experimentId}
          onGoBack={jest.fn()}
          width={100}
          height={200}
        />
      </Provider>,
    );

    const table = component.find('Table');

    expect(table.getElement().props.columns.length).toEqual(7);
    expect(table.getElement().props.columns[0].key).toEqual('lookup');
    expect(table.getElement().props.columns[1].key).toEqual('gene_names');
    expect(table.getElement().props.columns[2].key).toEqual('logFC');
    expect(table.getElement().props.columns[3].key).toEqual('p_val_adj');
    expect(table.getElement().props.columns[4].key).toEqual('pct_1');
    expect(table.getElement().props.columns[5].key).toEqual('pct_2');
    expect(table.getElement().props.columns[6].key).toEqual('auc');
  });

  it('The export as CSV alert opens and closes properly', async () => {
    const component = mount(
      <Provider store={withResultStore}>
        <DiffExprResults
          experimentId={experimentId}
          onGoBack={jest.fn()}
          width={100}
          height={200}
        />
      </Provider>,
    );

    // Clicking the CSV button opens the modal
    const csvButton = component.find('span[children="Export as CSV"]');
    expect(csvButton.length).toEqual(1);

    act(() => {
      csvButton.simulate('click');
    });
    component.update();

    const csvModal = component.find('Alert');
    expect(csvModal.length).toEqual(1);

    // Clicking the close button closes the CSV modal
    const closeCsvModalButton = csvModal.find('button');
    expect(closeCsvModalButton.length).toEqual(1);

    act(() => {
      closeCsvModalButton.simulate('click');
    });
    component.update();

    // Expect CSV modal to not be shown anymore
    expect(component.find('Alert').length).toEqual(0);
  });
});
Example #26
Source File: SearchItem.jsx    From erp-crm with MIT License 4 votes vote down vote up
export default function Search({ config }) {
  let { entity, searchConfig } = config;

  const { displayLabels, searchFields, outputValue = '_id' } = searchConfig;
  const dispatch = useDispatch();
  const [value, setValue] = useState('');
  const [options, setOptions] = useState([]);

  const { erpContextAction } = useErpContext();
  const { panel, collapsedBox, readBox } = erpContextAction;

  const { result, isLoading, isSuccess } = useSelector(selectSearchedItems);

  const isTyping = useRef(false);

  let delayTimer = null;
  useEffect(() => {
    isLoading && setOptions([{ label: '... Searching' }]);
  }, [isLoading]);
  const onSearch = (searchText) => {
    isTyping.current = true;

    clearTimeout(delayTimer);
    delayTimer = setTimeout(function () {
      if (isTyping.current && searchText !== '') {
        dispatch(
          erp.search(entity, {
            question: searchText,
            fields: searchFields,
          })
        );
      }
      isTyping.current = false;
    }, 500);
  };

  const onSelect = (data) => {
    const currentItem = result.find((item) => {
      return item[outputValue] === data;
    });

    dispatch(erp.currentItem({ data: currentItem }));
    panel.open();
    collapsedBox.open();
    readBox.open();
  };

  const onChange = (data) => {
    const currentItem = options.find((item) => {
      return item.value === data;
    });
    const currentValue = currentItem ? currentItem.label : data;
    setValue(currentValue);
  };

  useEffect(() => {
    let optionResults = [];

    result.map((item) => {
      const labels = displayLabels.map((x) => item[x]).join(' ');
      optionResults.push({ label: labels, value: item[outputValue] });
    });

    setOptions(optionResults);
  }, [result]);

  return (
    <AutoComplete
      value={value}
      options={options}
      style={{
        width: '100%',
      }}
      onSelect={onSelect}
      onSearch={onSearch}
      onChange={onChange}
      notFoundContent={!isSuccess ? <Empty /> : ''}
      allowClear={true}
      placeholder="Your Search here"
    >
      <Input suffix={<SearchOutlined />} />
    </AutoComplete>
  );
}
Example #27
Source File: index.jsx    From starter-antd-admin-crud-auth-mern with MIT License 4 votes vote down vote up
export default function SearchItem({ config }) {
  let { entity, searchConfig } = config;

  const { displayLabels, searchFields, outputValue = "_id" } = searchConfig;
  const dispatch = useDispatch();
  const [value, setValue] = useState("");
  const [options, setOptions] = useState([]);

  const { crudContextAction } = useCrudContext();
  const { panel, collapsedBox, readBox } = crudContextAction;

  let source = request.source();
  const { result, isLoading, isSuccess } = useSelector(selectSearchedItems);

  const isTyping = useRef(false);

  let delayTimer = null;
  useEffect(() => {
    isLoading && setOptions([{ label: "... Searching" }]);
  }, [isLoading]);
  const onSearch = (searchText) => {
    isTyping.current = true;

    clearTimeout(delayTimer);
    delayTimer = setTimeout(function () {
      if (isTyping.current && searchText !== "") {
        dispatch(
          crud.search(entity, source, {
            question: searchText,
            fields: searchFields,
          })
        );
      }
      isTyping.current = false;
    }, 500);
  };

  const onSelect = (data) => {
    const currentItem = result.find((item) => {
      return item[outputValue] === data;
    });

    dispatch(crud.currentItem(currentItem));
    panel.open();
    collapsedBox.open();
    readBox.open();
  };

  const onChange = (data) => {
    const currentItem = options.find((item) => {
      return item.value === data;
    });
    const currentValue = currentItem ? currentItem.label : data;
    setValue(currentValue);
  };

  useEffect(() => {
    let optionResults = [];

    result.map((item) => {
      const labels = displayLabels.map((x) => item[x]).join(" ");
      optionResults.push({ label: labels, value: item[outputValue] });
    });

    setOptions(optionResults);
  }, [result]);

  return (
    <AutoComplete
      value={value}
      options={options}
      style={{
        width: "100%",
      }}
      onSelect={onSelect}
      onSearch={onSearch}
      onChange={onChange}
      notFoundContent={!isSuccess ? <Empty /> : ""}
      allowClear={true}
      placeholder="Your Search here"
    >
      <Input suffix={<SearchOutlined />} />
    </AutoComplete>
  );
}
Example #28
Source File: dropTarget.js    From ant-simple-pro with MIT License 4 votes vote down vote up
DropTarget = memo(function DropTarget(props) {

  const [reviceData, setReviceData] = useState([]);

  const [currentMoveData, setCurrentMoveData] = useState({});

  const [popModelVal, setPopModelVal] = useSetState({ visible: false, dropTarget: {} });

  const [collectProps, droper] = useDrop({
    accept: "Box",
    collect: (minoter) => ({
      isOver: minoter.isOver(),
      canDrop: minoter.canDrop(),
      item: minoter.getItem(),
    }),
    drop: (item, monitor) => {
      const parentDiv = document.getElementById("dropers");
      const pointRect = parentDiv.getBoundingClientRect();
      const dropX = (monitor.getSourceClientOffset().x - pointRect.x) / spacing;
      const dropY = (monitor.getSourceClientOffset().y - pointRect.y) / spacing;
      setReviceData((pre) => [
        ...pre,
        Object.assign({}, item, {
          x: dropX,
          y: dropY,
          id: getRandomStr(),
          w: item.w / spacing,
          h: item.h / spacing,
        }),
      ]);
    },
  });

  const { show } = useContextMenu({ id: "dropFloor" });

  const showMenu = (e) => {
    show(e);
  };

  const menuOption = (status) => {
    if (!isJsonVal(currentMoveData)) {
      toast(requestCode.failedCode, "请先点击或者选择画布中要拖拽的组件");
      return false;
    }
    if (status === 1) {
      const copyVal = reviceData.filter((item) => item.id === currentMoveData.i);
      setReviceData((pre) => [...pre, Object.assign({}, copyVal[0], { id: getRandomStr() })]);
    } else if (status === 2) {
      setReviceData((pre) => pre.filter((item) => item.id !== currentMoveData.i));
    } else {
      setReviceData([]);
      setCurrentMoveData({});
    }
  };

  const MyAwesomeMenu = useCallback(
    () => (
      <Menu id="dropFloor">
        <Item onClick={() => menuOption(1)}>复制</Item>
        <Item onClick={() => menuOption(2)}>删除</Item>
        <Item onClick={() => menuOption(3)}>清屏画布</Item>
      </Menu>
    ),
    [menuOption]
  );

  const handleDrag = useCallback((layout, oldItem, newItem) => {
    const currentVal = reviceData.filter((item) => item.id === newItem.i);
    setCurrentMoveData(newItem);
    setPopModelVal({ visible: true, dropTarget: Object.assign({}, currentVal[0] || {}, newItem) });
  });

  return (
    <div style={{ width: "100%", height: "100%" }} onContextMenu={showMenu}>
      <div ref={droper} className={style.dropTarget} id="dropers">
        {reviceData.length ? (
          <>
            <GridLayout
              onDragStop={handleDrag}
              onDragStart={handleDrag}
              onResizeStop={handleDrag}
              rowHeight={spacing}
              cols={24}
              width={clintWidth}
              margin={[0, 0]}
            >
              {reviceData.map((item, index) => (
                <div
                  key={item.id}
                  data-grid={{
                    i: item.id,
                    x: item.x,
                    y: item.y,
                    w: item.w,
                    h: item.h,
                    resizeHandles: ["se", "s", "e"],
                  }}
                  style={{ background: "#fff" }}
                  className={style.dropGridItem}
                >
                  <RenderTemplate type={item.type} />
                </div>
              ))}
            </GridLayout>
            <MyAwesomeMenu />
          </>
        ) : (
          <Empty
            style={{ height: "100%", paddingTop: "200px" }}
            image="https://gw.alipayobjects.com/zos/antfincdn/ZHrcdLPrvN/empty.svg"
            imageStyle={{
              height: 60,
            }}
            description="暂无数据,请添加组件到画布来吧"
          ></Empty>
        )}
      </div>
      <PopModel {...popModelVal} onClose={setPopModelVal} />
    </div>
  );
})
Example #29
Source File: ResultTable.js    From 4IZ268-2021-2022-ZS with MIT License 4 votes vote down vote up
ResultsTable = (props) => {

    const { selectedResults, setSelectedResults } = props

    const location = useLocation()

    const compId = location.pathname.slice(location.pathname.lastIndexOf('/') + 1)

    const highlightClub = usePersonalSettings((state) => state.highlightClub)
    const clubList = useDataStore((store) => store.clubList)
    const setClubList = useDataStore((store) => store.setClubList)
    const autoRefetch = usePersonalSettings((state) => state.autoRefetch)
    const refetchInterval = usePersonalSettings((state) => state.refetchInterval)

    const [nameFilter, setNameFilter] = useState('')
    const [clubFilter, setClubFilter] = useState('')

    const { data, isLoading, isError } = useQuery(
        ['class', { comp: compId, type: selectedResults.type, value: selectedResults.value }],
        getResults,
        {
            refetchInterval: autoRefetch ? refetchInterval || 15000 : undefined,
        }
    )

    useEffect(() => {
        if (Array.isArray(data?.results)) {
            const clubs = []
            data.results.forEach((record) => {
                if (!clubList.includes(record.club) && !clubs.includes(record.club)) {
                    clubs.push(record.club)
                }
            });
            if (clubs.length) {
                setClubList([...clubList, ...clubs])
            }
        }
    }, [data, clubList, setClubList])

    if (!selectedResults.value.length) {
        return <Empty />
    }

    if (isLoading) {
        return (
            <Skeleton active title />
        )
    }

    if (isError) {
        return (
            <div>Failed to fetch data</div>
        )
    }

    const columns = [
        {
            title: '#',
            dataIndex: 'place',
            key: '#',
            render: (text) => text,
            width: '35px',
            align: 'center'
        }, {
            title: 'Jméno',
            dataIndex: 'name',
            key: 'name',
            filterDropdown: () => {
                return (
                    <div className='filterWrapper'>
                        <span>Jméno: </span>
                        <FilterInput onChange={(val) => setNameFilter(val)} />
                    </div>
                )
            },
        }
    ]

    if (selectedResults.type === 'class') {
        columns.push({
            title: 'Klub',
            dataIndex: 'club',
            key: 'club',
            filterDropdown: () => {
                return (
                    <div className='filterWrapper'>
                        <span>Klub: </span>
                        <FilterInput onChange={(val) => setClubFilter(val)} />
                    </div>
                )
            },
            render: (text) => {
                return (
                    <button onClick={() => setSelectedResults({ type: 'club', value: text })}>{text}</button>
                )
            }
        })
    } else {
        columns.push({
            title: 'Kat.',
            dataIndex: 'class',
            key: 'class',
            render: (text) => {
                return (
                    <button onClick={() => setSelectedResults({ type: 'class', value: text })}>{text}</button>
                )
            }
        })
    }

    columns.push({
        title: 'Start',
        dataIndex: 'start',
        key: 'start',
        render: (text) => {
            return formatTime(text);
        }
    })

    if (data) {
        if (Array.isArray(data.splitcontrols)) {
            if (data.splitcontrols.length) {
                data.splitcontrols.forEach((obj) => {
                    columns.push({
                        title: obj.name,
                        dataIndex: obj.code,
                        key: obj.code,
                        render: (obj) => {
                            return (
                                formatSplitResult(obj))
                        }
                    })
                })
            }
        }
        columns.push({
            title: 'Cíl',
            dataIndex: 'result',
            key: 'result',
            render: (obj) => {
                return (
                    translateFinishTime(obj)
                )
            }
        })
        columns.push({
            title: 'Ztráta',
            dataIndex: 'timeplus',
            key: 'timeplus',
            render: (obj) => {
                return (
                    translateFinishTime(obj)
                )
            }
        })
    }

    const tableData = {...data}

    if (data?.splitcontrols?.length) {
        tableData.results = data.results.map((obj) => {
            const adjusted = { ...obj };
            data.splitcontrols.forEach((splitControl) => {
                adjusted[splitControl.code] = {
                    time: obj.splits[splitControl.code],
                    place: obj.splits[splitControl.code + '_place'],
                    timeplus: obj.splits[splitControl.code + '_timeplus']
                }
            })
            return adjusted;
        })
    }

    const keyData = tableData.results.map((obj, index) => {
        return { ...obj, key: index }
    })

    const getFilteredData = () => {
        if (Array.isArray(keyData)) {
            let filteredData = [...keyData]
            if (nameFilter.length) {
                filteredData = [...filteredData.filter(obj => obj.name.includes(nameFilter))]
            }
            if (clubFilter.length) {
                filteredData = [...filteredData.filter(obj => obj.club.includes(clubFilter))]
            }
            return filteredData
        }
        else return keyData
    }

    const getRowClassName = (record, index) => {
        const isOdd = (num) => {
            return num % 2
        }

        const classNames = []

        if (isOdd(index)) {
            classNames.push('odd')
        }

        if (highlightClub?.length && record.club?.toLowerCase() === highlightClub.toLowerCase()) {
            classNames.push('highlight')
        }

        return classNames.join(' ')
    }

    return (
        <Table
            columns={columns}
            dataSource={getFilteredData()}
            pagination={false}
            size='small'
            bordered
            rowClassName={(record, index) => getRowClassName(record, index)}
            scroll={{ y: 'calc(100vh - 270px - 2.55rem)', x: true }}
        />
    )
}