antd/lib/table#ColumnType TypeScript Examples

The following examples show how to use antd/lib/table#ColumnType. 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: Table.tsx    From posthog-foss with MIT License 6 votes vote down vote up
export function createdAtColumn<T extends Record<string, any> = Record<string, any>>(): ColumnType<T> {
    return {
        title: normalizeColumnTitle('Created'),
        align: 'right',
        render: function RenderCreatedAt(_, item): JSX.Element | undefined | '' {
            return (
                item.created_at && (
                    <div style={{ whiteSpace: 'nowrap' }}>
                        <TZLabel time={item.created_at} />
                    </div>
                )
            )
        },
        sorter: (a, b) => (new Date(a.created_at) > new Date(b.created_at) ? 1 : -1),
    }
}
Example #2
Source File: Table.tsx    From posthog-foss with MIT License 5 votes vote down vote up
export function createdByColumn<T extends Record<string, any> = Record<string, any>>(items: T[]): ColumnType<T> {
    const { user } = useValues(userLogic)
    return {
        title: normalizeColumnTitle('Created by'),
        render: function Render(_: any, item: any) {
            return (
                <Row align="middle" wrap={false}>
                    {item.created_by && (
                        <ProfilePicture name={item.created_by.first_name} email={item.created_by.email} size="md" />
                    )}
                    <div style={{ maxWidth: 250, width: 'auto', verticalAlign: 'middle', marginLeft: 8 }}>
                        {item.created_by ? item.created_by.first_name || item.created_by.email : '-'}
                    </div>
                </Row>
            )
        },
        filters: uniqueBy(
            items.map((item: T) => {
                if (!item.created_by) {
                    return {
                        text: '(none)',
                        value: null,
                    }
                }
                return {
                    text: item.created_by?.first_name || item.created_by?.email,
                    value: item.created_by?.uuid,
                }
            }),
            (item) => item?.value
        ).sort((a, b) => {
            // Current user first
            if (a.value === user?.uuid) {
                return -10
            }
            if (b.value === user?.uuid) {
                return 10
            }
            return (a.text + '').localeCompare(b.text + '')
        }),
        onFilter: (value, item) => (value === null && item.created_by === null) || item.created_by?.uuid === value,
        sorter: (a, b) =>
            (a.created_by?.first_name || a.created_by?.email || '').localeCompare(
                b.created_by?.first_name || b.created_by?.email || ''
            ),
    }
}
Example #3
Source File: Invite.tsx    From tailchat with GNU General Public License v3.0 4 votes vote down vote up
GroupInvite: React.FC<{
  groupId: string;
}> = React.memo((props) => {
  const groupId = props.groupId;
  const { loading, value, refresh } = useAsyncRefresh(async () => {
    const list = await getAllGroupInviteCode(groupId);

    return list.reverse(); // 倒序返回
  }, [groupId]);

  const handleCreateInvite = useCallback(() => {
    openModal(
      <CreateGroupInvite
        groupId={groupId}
        onInviteCreated={() => {
          refresh();
        }}
      />
    );
  }, [groupId, refresh]);

  const handleCopyInviteCode = useCallback((inviteCode: string) => {
    copy(generateInviteCodeUrl(inviteCode));
    showToasts(t('邀请链接已复制到剪切板'), 'success');
  }, []);

  const handleDeleteInvite = useCallback(
    async (inviteId: string) => {
      if (await openReconfirmModalP()) {
        await deleteGroupInvite(groupId, inviteId);
        await refresh();
      }
    },
    [groupId, refresh]
  );

  const columns: ColumnType<GroupInviteType>[] = useMemo(
    () => [
      {
        title: t('邀请码'),
        dataIndex: 'code',
      },
      {
        title: t('创建时间'),
        dataIndex: 'createdAt',
        render: (date) => (
          <Tooltip title={formatFullTime(date)}>
            {datetimeFromNow(date)}
          </Tooltip>
        ),
      },
      {
        title: t('过期时间'),
        dataIndex: 'expiredAt',
        render: (date) => {
          if (!date) {
            return t('永不过期');
          }

          if (new Date(date).valueOf() < Date.now()) {
            return t('已过期');
          }

          return (
            <Tooltip title={formatFullTime(date)}>
              {datetimeFromNow(date)}
            </Tooltip>
          );
        },
      },
      {
        title: t('创建者'),
        dataIndex: 'creator',
        render: (userId) => <UserName userId={userId} />,
      },
      {
        title: t('操作'),
        dataIndex: '_id',
        render: (id: string, record) => {
          return (
            <Space>
              <IconBtn
                title={t('复制邀请链接')}
                shape="square"
                icon="mdi:content-copy"
                onClick={() => handleCopyInviteCode(record.code)}
              />
              <IconBtn
                title={t('删除')}
                shape="square"
                icon="mdi:delete-outline"
                danger={true}
                onClick={() => handleDeleteInvite(id)}
              />
            </Space>
          );
        },
      },
    ],
    [handleCopyInviteCode, handleDeleteInvite]
  );

  return (
    <LoadingOnFirst spinning={loading}>
      <div className="text-right mb-2">
        <Button type="primary" onClick={handleCreateInvite}>
          {t('创建邀请码')}
        </Button>
      </div>

      <Table
        columns={columns}
        dataSource={value}
        pagination={{
          hideOnSinglePage: true,
        }}
      />
    </LoadingOnFirst>
  );
})
Example #4
Source File: PageTable.tsx    From fe-v5 with Apache License 2.0 4 votes vote down vote up
PageTable: React.FC<Props> = ({ bgid }) => {
  const [severity, setSeverity] = useState<number>();
  const [clusters, setClusters] = useState<string[]>([]);
  const { t, i18n } = useTranslation();
  const history = useHistory();
  const [modalType, setModalType] = useState<ModalStatus>(ModalStatus.None);
  const [selectRowKeys, setSelectRowKeys] = useState<React.Key[]>([]);
  const [selectedRows, setSelectedRows] = useState<strategyItem[]>([]);
  const [exportData, setExportData] = useState<string>('');
  const { curBusiItem } = useSelector<RootState, CommonStoreState>((state) => state.common);

  const [query, setQuery] = useState<string>('');
  const [isModalVisible, setisModalVisible] = useState<boolean>(false);

  const [currentStrategyDataAll, setCurrentStrategyDataAll] = useState([]);
  const [currentStrategyData, setCurrentStrategyData] = useState([]);
  const [loading, setLoading] = useState(false);

  useEffect(() => {
    if (bgid) {
      getAlertRules();
    }
  }, [bgid, severity]);

  useEffect(() => {
    filterData();
  }, [query, clusters, currentStrategyDataAll]);

  const getAlertRules = async () => {
    if (!bgid) {
      return;
    }
    setLoading(true);
    const { success, dat } = await getStrategyGroupSubList({ id: bgid });
    if (success) {
      setCurrentStrategyDataAll(dat.filter((item) => !severity || item.severity === severity) || []);
      setLoading(false);
    }
  };

  const filterData = () => {
    const data = JSON.parse(JSON.stringify(currentStrategyDataAll));
    const res = data.filter((item) => {
      const lowerCaseQuery = query.toLowerCase();
      return (
        (item.name.toLowerCase().indexOf(lowerCaseQuery) > -1 || item.append_tags.join(' ').toLowerCase().indexOf(lowerCaseQuery) > -1) &&
        ((clusters && clusters?.indexOf(item.cluster) > -1) || clusters?.length === 0)
      );
    });
    setCurrentStrategyData(res || []);
  };

  const goToAddWarningStrategy = () => {
    curBusiItem?.id && history.push(`/alert-rules/add/${curBusiItem.id}`);
  };

  const handleClickEdit = (id, isClone = false) => {
    curBusiItem?.id && history.push(`/alert-rules/edit/${id}${isClone ? '?mode=clone' : ''}`);
  };

  const refreshList = () => {
    getAlertRules();
  };

  const columns: ColumnType<strategyItem>[] = [
    {
      title: t('集群'),
      dataIndex: 'cluster',
      render: (data) => {
        return <div>{data}</div>;
      },
    },
    {
      title: t('级别'),
      dataIndex: 'severity',
      render: (data) => {
        return <Tag color={priorityColor[data - 1]}>S{data}</Tag>;
      },
    },
    {
      title: t('名称'),
      dataIndex: 'name',
      render: (data, record) => {
        return (
          <div
            className='table-active-text'
            onClick={() => {
              handleClickEdit(record.id);
            }}
          >
            {data}
          </div>
        );
      },
    },
    {
      title: t('告警接收者'),
      dataIndex: 'notify_groups_obj',
      width: 100,
      render: (data, record) => {
        return (
          (data.length &&
            data.map(
              (
                user: {
                  nickname: string;
                  username: string;
                } & { name: string },
                index: number,
              ) => {
                return <ColorTag text={user.nickname || user.username || user.name} key={index}></ColorTag>;
              },
            )) || <div></div>
        );
      },
    },
    {
      title: t('附加标签'),
      dataIndex: 'append_tags',
      render: (data) => {
        const array = data || [];
        return (
          (array.length &&
            array.map((tag: string, index: number) => {
              return <ColorTag text={tag} key={index}></ColorTag>;
            })) || <div></div>
        );
      },
    },
    {
      title: t('更新时间'),
      dataIndex: 'update_at',
      width: 120,
      render: (text: string) => dayjs(Number(text) * 1000).format('YYYY-MM-DD HH:mm:ss'),
    },
    {
      title: t('启用'),
      dataIndex: 'disabled',
      render: (disabled, record) => (
        <Switch
          checked={disabled === strategyStatus.Enable}
          size='small'
          onChange={() => {
            const { id, disabled } = record;
            updateAlertRules(
              {
                ids: [id],
                fields: {
                  disabled: !disabled ? 1 : 0,
                },
              },
              curBusiItem.id,
            ).then(() => {
              refreshList();
            });
          }}
        />
      ),
    },
    {
      title: t('操作'),
      dataIndex: 'operator',
      width: 100,
      render: (data, record) => {
        return (
          <div className='table-operator-area'>
            <div
              className='table-operator-area-normal'
              onClick={() => {
                handleClickEdit(record.id, true);
              }}
            >
              {t('克隆')}
            </div>
            <div
              className='table-operator-area-warning'
              onClick={() => {
                confirm({
                  title: t('是否删除该告警规则?'),
                  onOk: () => {
                    deleteStrategy([record.id], curBusiItem.id).then(() => {
                      message.success(t('删除成功'));
                      refreshList();
                    });
                  },

                  onCancel() {},
                });
              }}
            >
              {t('删除')}
            </div>
          </div>
        );
      },
    },
  ];

  const toOneArr = (arr, res, name) => {
    arr.forEach((ele) => {
      if (Array.isArray(ele)) {
        toOneArr(ele, res, name);
      } else {
        res.push(ele[name]);
      }
    });
  };
  const openModel = (title, item) => {
    if (selectRowKeys.length == 0) {
      message.warning(t('请先选择策略'));
      return;
    }
    setisModalVisible(true);
  };

  const menu = useMemo(() => {
    return (
      <ul className='ant-dropdown-menu'>
        <li className='ant-dropdown-menu-item' onClick={() => setModalType(ModalStatus.BuiltIn)}>
          <span>{t('导入告警规则')}</span>
        </li>
        <li
          className='ant-dropdown-menu-item'
          onClick={() => {
            if (selectedRows.length) {
              const exportData = selectedRows.map((item) => {
                return { ...item, ...exportIgnoreAttrsObj };
              });
              setExportData(JSON.stringify(exportData, null, 2));
              setModalType(ModalStatus.Export);
            } else {
              message.warning(t('未选择任何规则'));
            }
          }}
        >
          <span>{t('导出告警规则')}</span>
        </li>
        <li
          className='ant-dropdown-menu-item'
          onClick={() => {
            if (selectRowKeys.length) {
              confirm({
                title: t('是否批量删除告警规则?'),
                onOk: () => {
                  deleteStrategy(selectRowKeys as number[], curBusiItem?.id).then(() => {
                    message.success(t('删除成功'));
                    refreshList();
                  });
                },

                onCancel() {},
              });
            } else {
              message.warning(t('未选择任何规则'));
            }
          }}
        >
          <span>{t('批量删除规则')}</span>
        </li>
        <li
          className='ant-dropdown-menu-item'
          onClick={() => {
            openModel(t('批量更新规则'), 1);
          }}
        >
          <span>{t('批量更新规则')}</span>
        </li>
      </ul>
    );
  }, [selectRowKeys, t]);

  const handleImportStrategy = async (data) => {
    const { dat } = await addOrEditStrategy(data, curBusiItem.id, 'Post');
    return dat || {};
  };

  const editModalFinish = async (isOk, fieldsData?) => {
    if (isOk) {
      const res = await updateAlertRules(
        {
          ids: selectRowKeys,
          fields: fieldsData,
        },
        curBusiItem.id,
      );
      if (!res.err) {
        message.success('修改成功!');
        refreshList();
        setisModalVisible(false);
      } else {
        message.error(res.err);
      }
    } else {
      setisModalVisible(false);
    }
  };

  return (
    <div className='strategy-table-content'>
      <div className='strategy-table-search table-handle'>
        <div className='strategy-table-search-left'>
          <RefreshIcon
            className='strategy-table-search-left-refresh'
            onClick={() => {
              refreshList();
            }}
          />
          <ColumnSelect noLeftPadding noRightPadding={false} onSeverityChange={(e) => setSeverity(e)} onClusterChange={(e) => setClusters(e)} />
          <SearchInput className={'searchInput'} placeholder={t('搜索名称或标签')} onSearch={setQuery} allowClear />
        </div>
        <div className='strategy-table-search-right'>
          <Button type='primary' onClick={goToAddWarningStrategy} className='strategy-table-search-right-create' ghost>
            {t('新增告警规则')}
          </Button>
          <div className={'table-more-options'}>
            <Dropdown overlay={menu} trigger={['click']}>
              <Button onClick={(e) => e.stopPropagation()}>
                {t('更多操作')}
                <DownOutlined
                  style={{
                    marginLeft: 2,
                  }}
                />
              </Button>
            </Dropdown>
          </div>
        </div>
      </div>

      <Table
        rowKey='id'
        // sticky
        pagination={{
          total: currentStrategyData.length,
          showQuickJumper: true,
          showSizeChanger: true,
          showTotal: (total) => {
            return `共 ${total} 条数据`;
          },
          pageSizeOptions: pageSizeOptionsDefault,
          defaultPageSize: 30,
        }}
        loading={loading}
        dataSource={currentStrategyData}
        rowSelection={{
          selectedRowKeys: selectedRows.map((item) => item.id),
          onChange: (selectedRowKeys: React.Key[], selectedRows: strategyItem[]) => {
            setSelectRowKeys(selectedRowKeys);
            setSelectedRows(selectedRows);
          },
        }}
        columns={columns}
      />
      <ImportAndDownloadModal
        bgid={bgid}
        status={modalType}
        fetchBuiltinFunc={getBuiltinAlerts}
        submitBuiltinFunc={createBuiltinAlerts}
        onClose={() => {
          setModalType(ModalStatus.None);
        }}
        onSuccess={() => {
          getAlertRules();
        }}
        onSubmit={handleImportStrategy}
        label='告警规则'
        title={
          ModalStatus.Export === modalType ? (
            '告警规则'
          ) : (
            <Tabs defaultActiveKey={ModalStatus.BuiltIn} onChange={(e: ModalStatus) => setModalType(e)} className='custom-import-alert-title'>
              <TabPane tab=' 导入内置告警规则' key={ModalStatus.BuiltIn}></TabPane>
              <TabPane tab='导入告警规则JSON' key={ModalStatus.Import}></TabPane>
            </Tabs>
          )
        }
        exportData={exportData}
      />
      {isModalVisible && <EditModal isModalVisible={isModalVisible} editModalFinish={editModalFinish} />}
    </div>
  );
}
Example #5
Source File: ruleModal.tsx    From fe-v5 with Apache License 2.0 4 votes vote down vote up
ruleModal: React.FC<props> = ({ visible, ruleModalClose, subscribe }) => {
  const { t } = useTranslation();
  const { curBusiItem } = useSelector<RootState, CommonStoreState>((state) => state.common);
  // const { busiGroups } = useSelector<RootState, CommonStoreState>((state) => state.common);
  const [busiGroups, setBusiGroups] = useState<{ id: number; name: string }[]>([]);
  const [currentStrategyDataAll, setCurrentStrategyDataAll] = useState([]);
  const [currentStrategyData, setCurrentStrategyData] = useState([]);
  const [bgid, setBgid] = useState(curBusiItem.id);
  const [query, setQuery] = useState<string>('');

  useEffect(() => {
    setBgid(curBusiItem.id);
  }, [curBusiItem]);

  useEffect(() => {
    getAlertRules();
  }, [bgid]);

  useEffect(() => {
    getTeamList('');
  }, []);

  useEffect(() => {
    filterData();
  }, [query, currentStrategyDataAll]);

  // 获取业务组列表
  const getTeamList = (query: string) => {
    console.log(111);
    let params = {
      all: 1,
      query,
      limit: 200,
    };
    getBusinessTeamList(params).then((data) => {
      setBusiGroups(data.dat || []);
    });
  };

  const debounceFetcher = useCallback(debounce(getTeamList, 400), []);

  const getAlertRules = async () => {
    const { success, dat } = await getStrategyGroupSubList({ id: bgid });
    if (success) {
      setCurrentStrategyDataAll(dat || []);
    }
  };

  const bgidChange = (val) => {
    setBgid(val);
  };

  const filterData = () => {
    const data = JSON.parse(JSON.stringify(currentStrategyDataAll));
    const res = data.filter((item) => {
      return item.name.indexOf(query) > -1 || item.append_tags.join(' ').indexOf(query) > -1;
    });
    setCurrentStrategyData(res || []);
  };

  const onSearchQuery = (e) => {
    let val = e.target.value;
    setQuery(val);
  };

  const columns: ColumnType<strategyItem>[] = [
    {
      title: t('集群'),
      dataIndex: 'cluster',
      render: (data) => {
        return <div>{data}</div>;
      },
    },
    {
      title: t('级别'),
      dataIndex: 'severity',
      render: (data) => {
        return <Tag color={priorityColor[data - 1]}>S{data}</Tag>;
      },
    },
    {
      title: t('名称'),
      dataIndex: 'name',
      render: (data, record) => {
        return (
          <div
            className='table-active-text'
            onClick={() => {
              // handleClickEdit(record.id);
            }}
          >
            {data}
          </div>
        );
      },
    },
    {
      title: t('告警接收者'),
      dataIndex: 'notify_groups_obj',
      render: (data, record) => {
        return (
          (data.length &&
            data.map(
              (
                user: {
                  nickname: string;
                  username: string;
                } & { name: string },
                index: number,
              ) => {
                return <ColorTag text={user.nickname || user.username || user.name} key={index}></ColorTag>;
              },
            )) || <div></div>
        );
      },
    },
    {
      title: t('附加标签'),
      dataIndex: 'append_tags',
      render: (data) => {
        const array = data || [];
        return (
          (array.length &&
            array.map((tag: string, index: number) => {
              return <ColorTag text={tag} key={index}></ColorTag>;
            })) || <div></div>
        );
      },
    },
    {
      title: t('更新时间'),
      dataIndex: 'update_at',
      render: (text: string) => dayjs(Number(text) * 1000).format('YYYY-MM-DD HH:mm:ss'),
    },
    {
      title: t('启用'),
      dataIndex: 'disabled',
      render: (disabled, record) => (
        <Switch
          checked={disabled === strategyStatus.Enable}
          disabled
          size='small'
          onChange={() => {
            const { id, disabled } = record;
            // updateAlertRules({
            //   ids: [id],
            //   fields: {
            //     disabled: !disabled ? 1 : 0
            //   }
            // }, curBusiItem.id
            // ).then(() => {
            //   refreshList();
            // });
          }}
        />
      ),
    },
    {
      title: t('操作'),
      dataIndex: 'operator',
      fixed: 'right',
      width: 100,
      render: (data, record) => {
        return (
          <div className='table-operator-area'>
            <div
              className='table-operator-area-normal'
              onClick={() => {
                handleSubscribe(record);
              }}
            >
              {t('订阅')}
            </div>
          </div>
        );
      },
    },
  ];

  const handleSubscribe = (record) => {
    subscribe(record);
  };

  const modalClose = () => {
    ruleModalClose();
  };

  return (
    <>
      <Modal
        title={t('订阅告警规则')}
        footer=''
        forceRender
        visible={visible}
        onCancel={() => {
          modalClose();
        }}
        width={'80%'}
      >
        <div>
          <Select
            style={{ width: '280px' }}
            value={bgid}
            onChange={bgidChange}
            showSearch
            optionFilterProp='children'
            filterOption={false}
            onSearch={(e) => debounceFetcher(e)}
            onBlur={() => getTeamList('')}
          >
            {busiGroups.map((item) => (
              <Option value={item.id} key={item.id}>
                {item.name}
              </Option>
            ))}
          </Select>
          <Input style={{ marginLeft: 10, width: '280px' }} onPressEnter={onSearchQuery} prefix={<SearchOutlined />} placeholder={t('规则名称、附加标签')} />
        </div>
        <div className='rule_modal_table'>
          <Table
            rowKey='id'
            pagination={{
              total: currentStrategyData.length,
              showQuickJumper: true,
              showSizeChanger: true,
              showTotal: (total) => {
                return `共 ${total} 条数据`;
              },
              pageSizeOptions: pageSizeOptionsDefault,
              defaultPageSize: 30,
            }}
            dataSource={currentStrategyData}
            columns={columns}
          />
        </div>
      </Modal>
    </>
  );
}