@ant-design/icons#UploadOutlined TypeScript Examples

The following examples show how to use @ant-design/icons#UploadOutlined. 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: FileUpload.tsx    From jmix-frontend with Apache License 2.0 6 votes vote down vote up
function FileUploadDropArea(props: FileUploadDropAreaProps) {
  return props.fileRef
    ? (
      <div className={styles.fileDropArea}>
        <UploadOutlined className={styles.replaceIcon} />
        <span className={styles.replaceText}>
          <FormattedMessage id='jmix.fileUpload.replace'/>
        </span>
      </div>
    )
    : (
      <div className={styles.fileDropArea}>
        <UploadOutlined className={styles.uploadIcon} />
        <div className={styles.uploadText}>
          <FormattedMessage id='jmix.fileUpload.upload'/>
        </div>
      </div>
    );
}
Example #2
Source File: UploadField.tsx    From posthog-foss with MIT License 6 votes vote down vote up
export function UploadField({
    value,
    onChange,
}: {
    value?: UploadFile | null
    onChange?: (file?: UploadFile | null) => void
}): JSX.Element {
    return (
        <Upload
            multiple={false}
            fileList={value?.size ? [value] : []}
            beforeUpload={(file) => {
                onChange?.(file)
                return false
            }}
            onRemove={() => {
                onChange?.(null)
                return false
            }}
            className="ph-ignore-input"
        >
            <Button icon={<UploadOutlined />}>Click to upload</Button>
        </Upload>
    )
}
Example #3
Source File: MultipleFilesForm.tsx    From next-basics with GNU General Public License v3.0 6 votes vote down vote up
export function LegacyMultipleFilesForm(
  { fieldList, onFinish, onFinishFailed }: MultipleFilesFormProps,
  ref: React.Ref<FormInstance>
): React.ReactElement {
  const [form] = Form.useForm();

  useImperativeHandle(ref, () => form);

  const handleFinish = (data: UploadFormData): void => {
    const formData = processFileData(data);
    onFinish?.(formData);
  };

  return (
    <Form
      form={form}
      name="filesForm"
      data-testid="files-form"
      onFinish={handleFinish}
      onFinishFailed={onFinishFailed}
    >
      {fieldList?.map((item) => (
        <Form.Item key={item.name} name={item.name} label={item.name}>
          <Upload
            maxCount={isMultipleFiles(item.type) ? null : 1}
            beforeUpload={() => false}
          >
            <Button icon={<UploadOutlined />}>upload</Button>
          </Upload>
        </Form.Item>
      ))}
    </Form>
  );
}
Example #4
Source File: index.tsx    From scorpio-h5-design with MIT License 6 votes vote down vote up
export default function() {
  useEffect(()=>{
    //
  }, []);
  const props = {
    name: 'file',
    async onChange(info: any) {
      if (info.file.status === 'done') {
        message.success(`${info.file.name} file uploaded successfully`);
        const uploadResult = await ossClient.put(`design/${info.file.name}`, info.file.originFileObj);
      } else if (info.file.status === 'error') {
        message.error(`${info.file.name} file upload failed.`);
      }
    },
  };
  return (
    <Upload {...props} className="aliyun-upload">
      <Button icon={<UploadOutlined />}>上传</Button>
    </Upload>
  );
}
Example #5
Source File: InputWithUpload.tsx    From jitsu with MIT License 6 votes vote down vote up
InputWithUpload: React.FC<InputWithUploadProps> = ({ value, onChange }) => {
  const triggerChange = e => {
    onChange?.(e.target.value)
  }

  const beforeUpload = file => {
    const reader = new FileReader()

    reader.onload = e => {
      const content: string = e.target.result as string
      onChange?.(content)
    }
    reader.readAsText(file)

    // Prevent upload
    return false
  }

  return value === "" ? (
    <Upload showUploadList={true} beforeUpload={beforeUpload}>
      <Button icon={<UploadOutlined />}>Click to Upload</Button>
    </Upload>
  ) : (
    <Input.TextArea autoSize={{ minRows: 1, maxRows: 5 }} value={value} autoComplete="off" onChange={triggerChange} />
  )
}
Example #6
Source File: index.tsx    From ii-admin-base with MIT License 5 votes vote down vote up
export default function IUpload(props: IUpload) {
  const {
    multiple = true,
    iconFontSize = 28,
    iconFontStyle,
    describe,
    extra,
    icon,
    uploadType = 'dragger',
    children,
    ...restProps
  } = props;

  if (!restProps.beforeUpload) {
    restProps.beforeUpload = beforeUpload;
  }

  if (uploadType === 'dragger') {
    return (
      <Dragger multiple={multiple} {...restProps}>
        {children}
        <p className="myupload-iconpart">
          {!icon && (
            <UploadOutlined
              style={{
                fontSize: `${iconFontSize}px`,
                color: '#3079FF',
                ...iconFontStyle,
              }}
            />
          )}
          {icon}
        </p>
        <p className="myupload-describe">
          {describe instanceof Array
            ? describe.map((item, index: number) => (
                <div key={`index${index}`}>{item}</div>
              ))
            : describe}
        </p>
        <p className="myupload-extra">
          {extra instanceof Array
            ? extra.map((item, index: number) => (
                <div key={`index${index}`}>{item}</div>
              ))
            : extra}
        </p>
      </Dragger>
    );
  }
  return (
    <Upload multiple={multiple} {...restProps}>
      {children}
    </Upload>
  );
}
Example #7
Source File: FileUpload.tsx    From datart with Apache License 2.0 5 votes vote down vote up
export function FileUpload({
  form,
  sourceId,
  loading,
  onTest,
}: FileUploadProps) {
  const [uploadFileLoading, setUploadFileLoading] = useState(false);
  const t = useI18NPrefix('source');

  const normFile = useCallback(e => {
    if (Array.isArray(e)) {
      return e;
    }
    return e && e.fileList;
  }, []);

  const uploadChange = useCallback(
    async ({ file }) => {
      if (file.status === 'done') {
        const format = file.name
          .substr(file.name.lastIndexOf('.') + 1)
          .toUpperCase();
        const response = file.response as APIResponse<string>;
        if (response.success) {
          form &&
            form.setFieldsValue({ config: { path: response.data, format } });
          onTest && onTest();
        }
        setUploadFileLoading(false);
      } else {
        setUploadFileLoading(true);
      }
    },
    [form, onTest],
  );

  return (
    <>
      <Form.Item
        label={t('form.file')}
        valuePropName="fileList"
        getValueFromEvent={normFile}
      >
        <Upload
          accept=".xlsx,.xls,.csv"
          method="post"
          action={`${BASE_API_URL}/files/datasource/?sourceId=${sourceId}`}
          headers={{ authorization: getToken()! }}
          showUploadList={false}
          onChange={uploadChange}
        >
          <Button
            icon={<UploadOutlined />}
            loading={uploadFileLoading || loading}
          >
            {t('form.selectFile')}
          </Button>
        </Upload>
      </Form.Item>
      <Form.Item
        name={['config', 'path']}
        css={`
          display: none;
        `}
      >
        <Input />
      </Form.Item>
      <Form.Item
        name={['config', 'format']}
        css={`
          display: none;
        `}
      >
        <Input />
      </Form.Item>
    </>
  );
}
Example #8
Source File: index.tsx    From jetlinks-ui-antd with MIT License 4 votes vote down vote up
Save: React.FC<Props> = props => {
    const { form: { getFieldsValue, getFieldDecorator }, data } = props;
    const [photoUrl, setPhotoUrl] = useState(data?.photoUrl);

    const uploadProps: UploadProps = {
        action: '/jetlinks/file/static',
        headers: {
            'X-Access-Token': getAccessToken(),
        },
        showUploadList: false,
        onChange(info) {
            if (info.file.status === 'done') {
                setPhotoUrl(info.file.response.result);
                message.success('上传成功');
            }
        },
    };
    return (
        <Modal
            title={data.id ? `编辑` : '新增'}
            visible
            onCancel={() => { props.close() }}
            onOk={() => {
                const formData = getFieldsValue();
                if (props.data.id) {
                    apis.edgeProduct.update({...formData, photoUrl}).then(res => {
                        if (res.status === 200) {
                            props.save();
                            message.success('更新成功');
                        }
                    })
                } else {
                    apis.edgeProduct.save({...formData, photoUrl}).then(res => {
                        if (res.status === 200) {
                            props.save();
                            message.success('新增成功');
                        }
                    })
                }
            }}
        >
            <Form
                labelCol={{ span: 4 }}
                wrapperCol={{ span: 20 }}
            >
                <Form.Item label="ID">
                    {getFieldDecorator('id', {
                        rules: [{ required: true }],
                        initialValue: data?.id,
                    })(
                        <Input readOnly={!!data.id} />
                    )}
                </Form.Item>
                <Form.Item label="名称">
                    {getFieldDecorator('name', {
                        rules: [{ required: true }],
                        initialValue: data?.name,
                    })(
                        <Input />
                    )}
                </Form.Item>
                <Form.Item label="厂家">
                    {getFieldDecorator('manufacturer', {
                        rules: [{ required: true }],
                        initialValue: data?.manufacturer,
                    })(
                        <Input />
                    )}
                </Form.Item>
                <Form.Item label="型号">
                    {getFieldDecorator('model', {
                        rules: [{ required: true }],
                        initialValue: data?.model,
                    })(
                        <Input />
                    )}
                </Form.Item>
                <Form.Item label='图标'>
                    <>
                        <div>
                            <Avatar size={80} src={photoUrl || data?.photoUrl} />
                        </div>
                        <Upload {...uploadProps} showUploadList={false}>
                            <Button>
                                <UploadOutlined />
                                更换图片
                            </Button>
                        </Upload>
                    </>
                </Form.Item>
                <Form.Item label="说明">
                    {getFieldDecorator('description', {
                        initialValue: data?.description,
                    })(
                        <Input.TextArea rows={3} placeholder="请输入" />
                    )}
                </Form.Item>
            </Form>
        </Modal>
    )
}
Example #9
Source File: FileManager.tsx    From anew-server with MIT License 4 votes vote down vote up
FileManager: React.FC<FileManagerProps> = (props) => {
    const { modalVisible, handleChange, connectId } = props;
    const [columnData, setColumnData] = useState<API.SSHFileList[]>([]);
    const [showHidden, setShowHidden] = useState<boolean>(false);
    const [childrenDrawer, setChildrenDrawer] = useState<boolean>(false);
    const [currentPathArr, setCurrentPathArr] = useState<string[]>([]);
    const [initPath, setInitPath] = useState<string>('');

    const _dirSort = (item: API.SSHFileList) => {
        return item.isDir;
    };

    const getFileData = (key: string, path: string) => {
        querySSHFile(key, path).then((res) => {
            const obj = lds.orderBy(res.data, [_dirSort, 'name'], ['desc', 'asc']);
            showHidden ? setColumnData(obj) : setColumnData(obj.filter((x) => !x.name.startsWith('.')));
            try {
                // 获取服务器的当前路径
                let pathb = obj[0].path;
                const index = pathb.lastIndexOf('/');
                pathb = pathb.substring(0, index + 1);
                setCurrentPathArr(pathb.split('/').filter((x: any) => x !== ''));
                setInitPath(pathb); // 保存当前路径,刷新用
            } catch (exception) {
                setCurrentPathArr(path.split('/').filter((x) => x !== ''));
                setInitPath(path);
            }
        });
    };

    const getChdirDirData = (key: string, path: string) => {
        const index = currentPathArr.indexOf(path);
        const currentDir = '/' + currentPathArr.splice(0, index + 1).join('/');
        getFileData(key, currentDir);
    };

    const handleDelete = (key: string, path: string) => {
        if (!path) return;
        const index = path.lastIndexOf('/');
        const currentDir = path.substring(0, index + 1);
        const currentFile = path.substring(index + 1, path.length);
        const content = `您是否要删除 ${currentFile}?`;
        Modal.confirm({
            title: '注意',
            content,
            onOk: () => {
                deleteSSHFile(key, path).then((res) => {
                    if (res.code === 200 && res.status === true) {
                        message.success(res.message);
                        getFileData(key, currentDir);
                    }
                });
            },
            onCancel() { },
        });
    };

    const handleDownload = (key: string, path: string) => {
        if (!path) return;
        const index = path.lastIndexOf('/');
        const currentFile = path.substring(index + 1, path.length);
        const content = `您是否要下载 ${currentFile}?`;
        Modal.confirm({
            title: '注意',
            content,
            onOk: () => {
                const token = localStorage.getItem('token');
                const link = document.createElement('a');
                link.href = `/api/v1/host/ssh/download?key=${key}&path=${path}&token=${token}`;
                document.body.appendChild(link);
                const evt = document.createEvent('MouseEvents');
                evt.initEvent('click', false, false);
                link.dispatchEvent(evt);
                document.body.removeChild(link);
            },
            onCancel() { },
        });
    };

    const uploadProps = {
        name: 'file',
        action: `/api/v1/host/ssh/upload?key=${connectId}&path=${initPath}`,
        multiple: true,
        headers: {
            Authorization: `Bearer ${localStorage.getItem('token')}`,
        },
        // showUploadList: {
        //   removeIcon: false,
        //   showRemoveIcon: false,
        // },
        onChange(info: any) {
            // if (info.file.status !== 'uploading') {
            //   console.log(info.file, info.fileList);
            // }
            //console.log(info);
            if (info.file.status === 'done') {
                message.success(`${info.file.name} file uploaded successfully`);
                getFileData(connectId, initPath as string); // 刷新数据
            } else if (info.file.status === 'error') {
                message.error(`${info.file.name} file upload failed.`);
            }
        },
        progress: {
            strokeColor: {
                '0%': '#108ee9',
                '100%': '#87d068',
            },
            strokeWidth: 3,
            format: (percent: any) => `${parseFloat(percent.toFixed(2))}%`,
        },
    };


    const columns: ProColumns<API.SSHFileList>[] = [
        {
            title: '名称',
            dataIndex: 'name',
            render: (_, record) =>
                record.isDir ? (
                    <div onClick={() => getFileData(connectId, record.path)} style={{ cursor: 'pointer' }}>
                        <FolderTwoTone />
                        <span style={{ color: '#1890ff', paddingLeft: 5 }}>{record.name}</span>
                    </div>
                ) : (
                    <React.Fragment>
                        {record.isLink ? (
                            <div>
                                <LinkOutlined />
                                <Tooltip title="Is Link">
                                    <span style={{ color: '#3cb371', paddingLeft: 5 }}>{record.name}</span>
                                </Tooltip>
                            </div>
                        ) : (
                            <div>
                                <FileOutlined />
                                <span style={{ paddingLeft: 5 }}>{record.name}</span>
                            </div>
                        )}
                    </React.Fragment>
                ),
        },
        {
            title: '大小',
            dataIndex: 'size',
        },
        {
            title: '修改时间',
            dataIndex: 'mtime',
        },
        {
            title: '属性',
            dataIndex: 'mode',
        },
        {
            title: '操作',
            dataIndex: 'option',
            valueType: 'option',
            render: (_, record) =>
                !record.isDir && !record.isLink ? (
                    <>
                        <Tooltip title="下载文件">
                            <DownloadOutlined
                                style={{ fontSize: '17px', color: 'blue' }}
                                onClick={() => handleDownload(connectId, record.path)}
                            />
                        </Tooltip>
                        <Divider type="vertical" />
                        <Tooltip title="删除文件">
                            <DeleteOutlined
                                style={{ fontSize: '17px', color: 'red' }}
                                onClick={() => handleDelete(connectId, record.path)}
                            />
                        </Tooltip>
                    </>
                ) : null,
        },
    ];

    useEffect(() => {
        // 是否显示隐藏文件
        getFileData(connectId, initPath as string); // 刷新数据
    }, [showHidden]);

    const { Dragger } = Upload;
    return (
        <Drawer
            title="文件管理器"
            placement="right"
            width={800}
            visible={modalVisible}
            onClose={()=>handleChange(false)}
            getContainer={false}
        >
            {/* <input style={{ display: 'none' }} type="file" ref={(ref) => (this.input = ref)} /> */}
            <div className={styles.drawerHeader}>
                <Breadcrumb>
                    <Breadcrumb.Item href="#" onClick={() => getFileData(connectId, '/')}>
                        <ApartmentOutlined />
                    </Breadcrumb.Item>
                    <Breadcrumb.Item href="#" onClick={() => getFileData(connectId, '')}>
                        <HomeOutlined />
                    </Breadcrumb.Item>
                    {currentPathArr.map((item) => (
                        <Breadcrumb.Item key={item} href="#" onClick={() => getChdirDirData(connectId, item)}>
                            <span>{item}</span>
                        </Breadcrumb.Item>
                    ))}
                </Breadcrumb>
                <div style={{ display: 'flex', alignItems: 'center' }}>
                    <span>显示隐藏文件:</span>
                    <Switch
                        checked={showHidden}
                        checkedChildren="开启"
                        unCheckedChildren="关闭"
                        onChange={(v) => {
                            setShowHidden(v);
                        }}
                    />

                    <Button
                        style={{ marginLeft: 10 }}
                        size="small"
                        type="primary"
                        icon={<UploadOutlined />}
                        onClick={() => setChildrenDrawer(true)}
                    >
                        上传文件
                    </Button>
                </div>
            </div>
            <Drawer
                title="上传文件"
                width={320}
                closable={false}
                onClose={() => setChildrenDrawer(false)}
                visible={childrenDrawer}
            >
                <div style={{ height: 150 }}>
                    <Dragger {...uploadProps}>
                        <p className="ant-upload-drag-icon">
                            <InboxOutlined />
                        </p>
                        <p className="ant-upload-text">单击或拖入上传</p>
                        <p className="ant-upload-hint">支持多文件</p>
                    </Dragger>
                </div>
            </Drawer>
            <ProTable
                pagination={false}
                search={false}
                toolBarRender={false}
                rowKey="name"
                dataSource={columnData}
                columns={columns}
            />
        </Drawer>
    );
}
Example #10
Source File: index.tsx    From anew-server with MIT License 4 votes vote down vote up
Settings: React.FC = () => {
    const { initialState, setInitialState } = useModel('@@initialState');

    if (!initialState || !initialState.currentUser) {
        return null;
    }
    const { currentUser } = initialState;

    const beforeUpload = (file: RcFile) => {
        const isJpgOrPng =
            file.type === 'image/jpeg' || file.type === 'image/png' || file.type === 'image/gif';
        if (!isJpgOrPng) {
            message.error('只可以上传JPG/PNG/GIF图片!');
        }
        const isLt2M = file.size / 1024 / 1024 < 2;
        if (!isLt2M) {
            message.error('图片必须小于2MB!');
        }
        return isJpgOrPng && isLt2M;
    };

    const handleChange = (info: UploadChangeParam) => {
        if (info.file.status === 'uploading') {
            //setUploadLoading(true);
            return;
        }
        if (info.file.status === 'done') {
            message.success('上传成功');
            let userInfo = {};
            Object.assign(userInfo, initialState?.currentUser);
            (userInfo as API.UserInfo).avatar = info.file.response.data.url;
            setInitialState({ ...initialState, currentUser: userInfo as API.UserInfo });
        }
    };

    const tokenHeaders = {
        Authorization: 'Bearer ' + localStorage.getItem('token'),
    };
    return (
        <GridContent>
            {currentUser.username && (
                <Row gutter={24}>
                    <Col span={10}>
                        <Card
                            title="关于我"
                            bordered={false}
                            style={{
                                marginBottom: 14,
                            }}
                        >
                            <div>
                                <div className={styles.avatarHolder}>
                                    <img alt="" src={currentUser.avatar} />
                                    <Upload
                                        name="avatar"
                                        headers={tokenHeaders}
                                        accept=".jpg,.jpeg,.png,.gif"
                                        className="avatar-uploader"
                                        showUploadList={false}
                                        action="/api/v1/user/info/uploadImg"
                                        beforeUpload={beforeUpload}
                                        onChange={handleChange}
                                    >
                                        <div className={styles.button_view}>
                                            <Button>
                                                <UploadOutlined /> 更换头像
                                            </Button>
                                        </div>
                                    </Upload>
                                </div>
                                <div className={styles.detail}>
                                    <div>
                                        <p style={{ marginRight: '15px' }}>
                                            <IconFont
                                                type="icon-yonghuming"
                                                style={{ fontSize: '16px', marginRight: 8 }}
                                            />
                                            用户名
                                        </p>
                                        {currentUser.username}
                                    </div>
                                    <div>
                                        <p style={{ marginRight: '29px' }}>
                                            <IconFont
                                                type="icon-xingming"
                                                style={{ fontSize: '16px', marginRight: 8 }}
                                            />
                                            姓名
                                        </p>
                                        {currentUser.name}
                                    </div>
                                    <div>
                                        <p style={{ marginRight: '29px' }}>
                                            <IconFont
                                                type="icon-youxiang"
                                                style={{ fontSize: '16px', marginRight: 8 }}
                                            />
                                            邮箱
                                        </p>
                                        {currentUser.email}
                                    </div>
                                    <div>
                                        <p style={{ marginRight: '29px' }}>
                                            <IconFont
                                                type="icon-shouji54"
                                                style={{ fontSize: '16px', marginRight: 8 }}
                                            />
                                            手机
                                        </p>
                                        {currentUser.mobile}
                                    </div>
                                    <div>
                                        <p style={{ marginRight: '29px' }}>
                                            <IconFont
                                                type="icon-jiaose"
                                                style={{ fontSize: '16px', marginRight: 8 }}
                                            />
                                            角色
                                        </p>
                                        {currentUser.role?.name}
                                    </div>
                                    <div>
                                        <p style={{ marginRight: '29px' }}>
                                            <IconFont
                                                type="icon-bumen"
                                                style={{ fontSize: '16px', marginRight: 8 }}
                                            />
                                            部门
                                        </p>
                                        {currentUser.dept?.name}
                                    </div>
                                </div>
                            </div>
                        </Card>
                    </Col>
                    <Col span={14}>
                        <Card title="个人设置" bordered={false} >
                            <Tabs tabPosition="right" onChange={() => { }}>
                                <Tabs.TabPane tab="基本信息" key="baseInfo">
                                    <BaseForm values={currentUser} />
                                </Tabs.TabPane>
                                <Tabs.TabPane tab="修改密码" key="changePwd">
                                    <ChangePasswordFrom />
                                </Tabs.TabPane>
                            </Tabs>
                        </Card>
                    </Col>
                </Row>
            )}
        </GridContent>
    );
}
Example #11
Source File: SettingsPage.tsx    From office-hours with GNU General Public License v3.0 4 votes vote down vote up
export default function SettingsPage({
  defaultPage,
}: SettingsPageProps): ReactElement {
  const {
    data: profile,
    error,
    mutate,
  } = useSWR(`api/v1/profile`, async () => API.profile.index());
  const router = useRouter();
  const { cid } = router.query;
  const role = useRoleInCourse(Number(cid));
  const isTAOrProfessor = role === Role.TA || role === Role.PROFESSOR;

  const [currentSettings, setCurrentSettings] = useState(
    defaultPage || SettingsOptions.PROFILE
  );
  const [uploading, setUploading] = useState(false);
  const isMobile = useIsMobile();
  const windowWidth = useWindowWidth();
  const [avatarSize, setAvatarSize] = useState(windowWidth / 2);

  useEffect(() => {
    const widthDivider = isMobile ? 6 : 10;
    setAvatarSize(windowWidth / widthDivider);
  });

  const beforeUpload = (file) => {
    const isJpgOrPng = file.type === "image/jpeg" || file.type === "image/png";

    if (!isJpgOrPng) {
      message.error("You can only upload JPGs or PNGs!");
    }

    const isLt1M = file.size / 1024 / 1024 < 1;
    if (!isLt1M) {
      message.error("Image must smaller than 1MB!");
    }

    return isJpgOrPng && isLt1M;
  };

  if (error) {
    message.error(error);
  }

  const AvatarSettings = () => (
    <Col>
      {avatarSize ? (
        <Row
          style={{
            marginTop: avatarSize / 6,
            justifyContent: `${isMobile ? "left" : "center"}`,
          }}
        >
          {uploading ? (
            <Skeleton.Avatar
              active={true}
              size={avatarSize}
              shape="circle"
              style={{
                marginTop: avatarSize / 6,
                marginBottom: avatarSize / 12,
                marginLeft: avatarSize / 6,
                marginRight: avatarSize / 6,
              }}
            />
          ) : (
            <SettingsPanelAvatar avatarSize={avatarSize} />
          )}
          <Col>
            {profile && (
              <h2>
                {profile.firstName} {profile.lastName}
              </h2>
            )}
            <Upload
              action={"/api/v1/profile/upload_picture"}
              beforeUpload={beforeUpload}
              showUploadList={false}
              onChange={(info) => {
                setUploading(info.file.status === "uploading");
                mutate();
              }}
            >
              <ProfilePicButton icon={<UploadOutlined />}>
                Edit photo
              </ProfilePicButton>
            </Upload>
            {profile?.photoURL && (
              <ProfilePicButton
                icon={<DeleteOutlined />}
                style={{ marginTop: "10px" }}
                onClick={async () => {
                  try {
                    await API.profile.deleteProfilePicture();
                    message.success(
                      "You've successfully deleted your profile picture"
                    );
                    mutate();
                  } catch (e) {
                    message.error(
                      "There was an error with deleting your profile picture, please contact the Khoury Office Hours team for assistance"
                    );
                    throw e;
                  }
                }}
              >
                Delete my Profile Picture
              </ProfilePicButton>
            )}
          </Col>
        </Row>
      ) : null}
    </Col>
  );

  const SettingsMenu = () => (
    <>
      {isMobile ? (
        <Collapse accordion style={{ marginTop: "10px" }}>
          <Panel header="Personal Information" key="profile">
            <ProfileSettings />
          </Panel>
          {isTAOrProfessor && (
            <Panel header="Teams Settings" key="teams_settings">
              <TeamsSettings />
            </Panel>
          )}
          <Panel header="Notifications" key="notifications">
            <NotificationsSettings />
          </Panel>
          <Panel header="Course Preferences" key="preferences">
            <CoursePreferenceSettings />
          </Panel>
        </Collapse>
      ) : (
        <Menu
          style={{ background: "none", marginTop: "10px" }}
          defaultSelectedKeys={[currentSettings]}
          onClick={(e) => setCurrentSettings(e.key as SettingsOptions)}
        >
          <Menu.Item key={SettingsOptions.PROFILE} icon={<UserOutlined />}>
            Personal Information
          </Menu.Item>
          {isTAOrProfessor && (
            <Menu.Item
              key={SettingsOptions.TEAMS_SETTINGS}
              icon={<WindowsOutlined />}
            >
              Teams Settings
            </Menu.Item>
          )}
          <Menu.Item
            key={SettingsOptions.NOTIFICATIONS}
            icon={<BellOutlined />}
          >
            Notifications
          </Menu.Item>
          <Menu.Item key={SettingsOptions.PREFERENCES} icon={<BookOutlined />}>
            Course Preferences
          </Menu.Item>
        </Menu>
      )}
    </>
  );

  const DesktopSettingsSubpage = () => (
    <Col>
      {currentSettings === SettingsOptions.PROFILE && <ProfileSettings />}
      {currentSettings === SettingsOptions.NOTIFICATIONS && (
        <NotificationsSettings />
      )}
      {currentSettings === SettingsOptions.TEAMS_SETTINGS && <TeamsSettings />}
      {currentSettings === SettingsOptions.PREFERENCES && (
        <CoursePreferenceSettings />
      )}
    </Col>
  );

  return (
    <div>
      {isMobile ? (
        <Col>
          <AvatarSettings />
          <SettingsMenu />
        </Col>
      ) : (
        <Row>
          <Col span={5} style={{ textAlign: "center" }}>
            <AvatarSettings />
            <SettingsMenu />
          </Col>
          <VerticalDivider />
          <Space direction="vertical" size={40} style={{ flexGrow: 1 }}>
            <DesktopSettingsSubpage />
          </Space>
        </Row>
      )}
    </div>
  );
}
Example #12
Source File: index.tsx    From Aragorn with MIT License 4 votes vote down vote up
FileManage = () => {
  const {
    state: {
      uploaderProfiles,
      configuration: { defaultUploaderProfileId }
    }
  } = useAppContext();

  const [windowHeight, setWindowHeight] = useState(window.innerHeight);

  useEffect(() => {
    function handleResize() {
      setWindowHeight(window.innerHeight);
    }
    window.addEventListener('resize', handleResize);

    return () => {
      window.removeEventListener('resize', handleResize);
    };
  }, []);

  const { id } = useParams<{ id: string }>();

  const [hasFileManageFeature, setHasFileManageFeature] = useState(false);

  const [uploaderProfile, setUploaderProfile] = useState({} as UploaderProfile);

  useEffect(() => {
    const currentId = id || defaultUploaderProfileId;
    setCurrentProfile(currentId as string);
  }, []);

  useEffect(() => {
    if (uploaderProfile?.id) {
      getList();
    }
  }, [uploaderProfile]);

  const [list, setList] = useState([] as ListFile[]);
  const [listLoading, setListLoading] = useState(false);

  const getList = (directoryPath?: string) => {
    setListLoading(true);
    ipcRenderer.send('file-list-get', uploaderProfile.id, directoryPath);
  };

  const [dirPath, setDirPath] = useState([] as string[]);

  useEffect(() => {
    function handleListGetReply(_, res?: FileListResponse) {
      setListLoading(false);
      if (res === undefined) {
        setHasFileManageFeature(false);
        setList([]);
        message.info(`${uploaderProfile.uploaderName}暂不支持文件管理功能`);
        return;
      }
      setHasFileManageFeature(true);
      if (res.success) {
        setList(res.data);
      } else {
        message.error(`文件列表获取失败 ${res.desc || ''}`);
      }
    }

    function handleFileDeleteReply(_, res?: DeleteFileResponse) {
      if (res === undefined) {
        return;
      }
      if (res.success) {
        message.success({ content: '文件删除成功', key: 'file-manage-delete' });
        getList(dirPath.join('/'));
      } else {
        message.error({ content: `文件删除失败 ${res.desc || ''}`, key: 'file-manage-delete' });
      }
    }

    function handleFileUploadReply() {
      getList(dirPath.join('/'));
    }

    function handleDirectoryCreateReply(_, res?: CreateDirectoryResponse) {
      if (res === undefined) {
        return;
      }
      if (res.success) {
        message.success('目录创建成功');
        setModalVisible(false);
        getList(dirPath.join('/'));
      } else {
        message.error(`目录创建失败 ${res.desc || ''}`);
      }
    }

    function handleExportReplay(_, res) {
      setExportLoading(false);
      if (res) {
        shell.showItemInFolder(res);
        setRowKeys([]);
        setSelectRows([]);
      }
    }

    ipcRenderer.on('file-list-get-reply', handleListGetReply);
    ipcRenderer.on('file-delete-reply', handleFileDeleteReply);
    ipcRenderer.on('file-upload-reply', handleFileUploadReply);
    ipcRenderer.on('directory-create-reply', handleDirectoryCreateReply);
    ipcRenderer.on('export-reply', handleExportReplay);

    return () => {
      ipcRenderer.removeListener('file-list-get-reply', handleListGetReply);
      ipcRenderer.removeListener('file-delete-reply', handleFileDeleteReply);
      ipcRenderer.removeListener('file-upload-reply', handleFileUploadReply);
      ipcRenderer.removeListener('directory-create-reply', handleDirectoryCreateReply);
      ipcRenderer.removeListener('export-reply', handleExportReplay);
    };
  }, [uploaderProfile, dirPath]);

  const handleNameClick = (record: ListFile) => {
    if (record.type === 'directory') {
      const newPath = [...dirPath, formatFileName(record.name)];
      setDirPath(newPath);
      getList(newPath.join('/'));
    } else {
      clipboard.writeText(record.url as string);
      message.success('链接已复制到粘贴板');
    }
  };

  const handlePathClick = (index: number) => {
    if (index === -1) {
      setDirPath([]);
      getList();
    } else {
      const newPath = dirPath.slice(0, index + 1);
      setDirPath(newPath);
      getList(newPath.join('/'));
    }
  };

  const setCurrentProfile = (uploaderProfileId: string) => {
    setDirPath([]);
    const uploaderProfile = uploaderProfiles.find(item => item.id === uploaderProfileId);
    setUploaderProfile(uploaderProfile as UploaderProfile);
  };

  const formatFileName = (name: string) => {
    if (dirPath.length > 0) {
      const pathPrefix = dirPath.join('/') + '/';
      return name.split(pathPrefix).pop() || '';
    } else {
      return name;
    }
  };

  const [selectRowKeys, setRowKeys] = useState([] as string[]);
  const [selectRows, setSelectRows] = useState([] as ListFile[]);

  const handleTableRowChange = (selectedRowKeys, selectedRows: ListFile[]) => {
    setRowKeys(selectedRowKeys);
    setSelectRows(selectedRows);
  };

  const handleRefresh = () => {
    getList(dirPath.join('/'));
  };

  const handleBatchDelete = () => {
    Modal.confirm({
      title: '确认删除',
      onOk: () => {
        const names = selectRows.map(item => [...dirPath, formatFileName(item.name)].join('/'));
        message.info({ content: '正在删除,请稍后...', key: 'file-manage-delete' });
        ipcRenderer.send('file-delete', uploaderProfile.id, names);
      }
    });
  };

  const handleDelete = (record: ListFile) => {
    let name = record.name;
    Modal.confirm({
      title: '确认删除',
      content: name,
      onOk: () => {
        let name = record.name;
        if (record.type === 'directory') {
          name = `${[...dirPath, record.name].join('/')}/`;
        } else {
          name = [...dirPath, formatFileName(record.name)].join('/');
        }
        message.info({ content: '正在删除,请稍后...', key: 'file-manage-delete' });
        ipcRenderer.send('file-delete', uploaderProfile.id, [name]);
      }
    });
  };

  const uploadRef = useRef<HTMLInputElement>(null);

  const handleFileUpload = (event: React.FormEvent<HTMLInputElement>) => {
    const fileList = event.currentTarget.files || [];
    const filesPath = Array.from(fileList).map(file => file.path);
    const pathPrefix = dirPath.join('/');
    ipcRenderer.send('file-upload', uploaderProfile.id, filesPath, pathPrefix);
    event.currentTarget.value = '';
  };

  const [modalVisible, setModalVisible] = useState(false);

  const [form] = Form.useForm();

  const handleCreateDirectory = () => {
    form.validateFields().then(values => {
      ipcRenderer.send('directory-create', uploaderProfile.id, values?.directoryPath || '');
    });
  };

  const handleDownload = (record: ListFile) => {
    ipcRenderer.send('file-download', record.name, record.url);
  };

  const [exportLoading, setExportLoading] = useState(false);

  const handleExport = () => {
    const data = selectRows.map(item => {
      const fileNameArr = item.name.split('.');
      fileNameArr.pop();
      return {
        name: fileNameArr.join('.'),
        url: item.url
      };
    });
    setExportLoading(true);
    ipcRenderer.send('export', data);
  };

  const columns: ColumnsType<ListFile> = [
    {
      title: '文件名',
      dataIndex: 'name',
      ellipsis: true,
      render: (val: string, record: ListFile) => (
        <div style={{ display: 'flex', alignItems: 'center' }}>
          {record.type === 'directory' ? (
            <FolderFilled style={{ fontSize: 16 }} />
          ) : (
            <FileOutlined style={{ fontSize: 16 }} />
          )}
          {record.type === 'directory' ? (
            <a
              title={val}
              onClick={() => handleNameClick(record)}
              className="table-filename"
              style={{ marginLeft: 10, overflow: 'hidden', textOverflow: 'ellipsis' }}
            >
              {formatFileName(val)}
            </a>
          ) : (
            <Popover
              placement="topLeft"
              content={() =>
                /(jpg|png|gif|jpeg)$/.test(val) ? (
                  <Image
                    style={{ maxWidth: 500 }}
                    src={record.url}
                    fallback="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMIAAADDCAYAAADQvc6UAAABRWlDQ1BJQ0MgUHJvZmlsZQAAKJFjYGASSSwoyGFhYGDIzSspCnJ3UoiIjFJgf8LAwSDCIMogwMCcmFxc4BgQ4ANUwgCjUcG3awyMIPqyLsis7PPOq3QdDFcvjV3jOD1boQVTPQrgSkktTgbSf4A4LbmgqISBgTEFyFYuLykAsTuAbJEioKOA7DkgdjqEvQHEToKwj4DVhAQ5A9k3gGyB5IxEoBmML4BsnSQk8XQkNtReEOBxcfXxUQg1Mjc0dyHgXNJBSWpFCYh2zi+oLMpMzyhRcASGUqqCZ16yno6CkYGRAQMDKMwhqj/fAIcloxgHQqxAjIHBEugw5sUIsSQpBobtQPdLciLEVJYzMPBHMDBsayhILEqEO4DxG0txmrERhM29nYGBddr//5/DGRjYNRkY/l7////39v///y4Dmn+LgeHANwDrkl1AuO+pmgAAADhlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAAqACAAQAAAABAAAAwqADAAQAAAABAAAAwwAAAAD9b/HnAAAHlklEQVR4Ae3dP3PTWBSGcbGzM6GCKqlIBRV0dHRJFarQ0eUT8LH4BnRU0NHR0UEFVdIlFRV7TzRksomPY8uykTk/zewQfKw/9znv4yvJynLv4uLiV2dBoDiBf4qP3/ARuCRABEFAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghgg0Aj8i0JO4OzsrPv69Wv+hi2qPHr0qNvf39+iI97soRIh4f3z58/u7du3SXX7Xt7Z2enevHmzfQe+oSN2apSAPj09TSrb+XKI/f379+08+A0cNRE2ANkupk+ACNPvkSPcAAEibACyXUyfABGm3yNHuAECRNgAZLuYPgEirKlHu7u7XdyytGwHAd8jjNyng4OD7vnz51dbPT8/7z58+NB9+/bt6jU/TI+AGWHEnrx48eJ/EsSmHzx40L18+fLyzxF3ZVMjEyDCiEDjMYZZS5wiPXnyZFbJaxMhQIQRGzHvWR7XCyOCXsOmiDAi1HmPMMQjDpbpEiDCiL358eNHurW/5SnWdIBbXiDCiA38/Pnzrce2YyZ4//59F3ePLNMl4PbpiL2J0L979+7yDtHDhw8vtzzvdGnEXdvUigSIsCLAWavHp/+qM0BcXMd/q25n1vF57TYBp0a3mUzilePj4+7k5KSLb6gt6ydAhPUzXnoPR0dHl79WGTNCfBnn1uvSCJdegQhLI1vvCk+fPu2ePXt2tZOYEV6/fn31dz+shwAR1sP1cqvLntbEN9MxA9xcYjsxS1jWR4AIa2Ibzx0tc44fYX/16lV6NDFLXH+YL32jwiACRBiEbf5KcXoTIsQSpzXx4N28Ja4BQoK7rgXiydbHjx/P25TaQAJEGAguWy0+2Q8PD6/Ki4R8EVl+bzBOnZY95fq9rj9zAkTI2SxdidBHqG9+skdw43borCXO/ZcJdraPWdv22uIEiLA4q7nvvCug8WTqzQveOH26fodo7g6uFe/a17W3+nFBAkRYENRdb1vkkz1CH9cPsVy/jrhr27PqMYvENYNlHAIesRiBYwRy0V+8iXP8+/fvX11Mr7L7ECueb/r48eMqm7FuI2BGWDEG8cm+7G3NEOfmdcTQw4h9/55lhm7DekRYKQPZF2ArbXTAyu4kDYB2YxUzwg0gi/41ztHnfQG26HbGel/crVrm7tNY+/1btkOEAZ2M05r4FB7r9GbAIdxaZYrHdOsgJ/wCEQY0J74TmOKnbxxT9n3FgGGWWsVdowHtjt9Nnvf7yQM2aZU/TIAIAxrw6dOnAWtZZcoEnBpNuTuObWMEiLAx1HY0ZQJEmHJ3HNvGCBBhY6jtaMoEiJB0Z29vL6ls58vxPcO8/zfrdo5qvKO+d3Fx8Wu8zf1dW4p/cPzLly/dtv9Ts/EbcvGAHhHyfBIhZ6NSiIBTo0LNNtScABFyNiqFCBChULMNNSdAhJyNSiECRCjUbEPNCRAhZ6NSiAARCjXbUHMCRMjZqBQiQIRCzTbUnAARcjYqhQgQoVCzDTUnQIScjUohAkQo1GxDzQkQIWejUogAEQo121BzAkTI2agUIkCEQs021JwAEXI2KoUIEKFQsw01J0CEnI1KIQJEKNRsQ80JECFno1KIABEKNdtQcwJEyNmoFCJAhELNNtScABFyNiqFCBChULMNNSdAhJyNSiECRCjUbEPNCRAhZ6NSiAARCjXbUHMCRMjZqBQiQIRCzTbUnAARcjYqhQgQoVCzDTUnQIScjUohAkQo1GxDzQkQIWejUogAEQo121BzAkTI2agUIkCEQs021JwAEXI2KoUIEKFQsw01J0CEnI1KIQJEKNRsQ80JECFno1KIABEKNdtQcwJEyNmoFCJAhELNNtScABFyNiqFCBChULMNNSdAhJyNSiECRCjUbEPNCRAhZ6NSiAARCjXbUHMCRMjZqBQiQIRCzTbUnAARcjYqhQgQoVCzDTUnQIScjUohAkQo1GxDzQkQIWejUogAEQo121BzAkTI2agUIkCEQs021JwAEXI2KoUIEKFQsw01J0CEnI1KIQJEKNRsQ80JECFno1KIABEKNdtQcwJEyNmoFCJAhELNNtScABFyNiqFCBChULMNNSdAhJyNSiEC/wGgKKC4YMA4TAAAAABJRU5ErkJggg=="
                  />
                ) : (
                  val
                )
              }
              trigger="hover"
            >
              <a
                title={val}
                onClick={() => handleNameClick(record)}
                className="table-filename"
                style={{ marginLeft: 10, overflow: 'hidden', textOverflow: 'ellipsis' }}
              >
                {formatFileName(val)}
              </a>
            </Popover>
          )}
        </div>
      )
    },
    {
      title: '文件大小',
      dataIndex: 'size',
      ellipsis: true,
      width: 120,
      render: val => (val ? filesize(val) : '-')
    },
    {
      title: '更新时间',
      dataIndex: 'lastModified',
      ellipsis: true,
      width: 200,
      render: val => (val ? dayjs(val).format('YYYY-MM-DD HH:mm:ss') : '-')
    },
    {
      title: '操作',
      width: 120,
      render: (_, record) => (
        <Space>
          {record.type !== 'directory' && (
            <>
              <DownloadOutlined onClick={() => handleDownload(record)} />
              <CopyOutlined onClick={() => handleNameClick(record)} />
            </>
          )}
          <DeleteOutlined onClick={() => handleDelete(record)} />
        </Space>
      )
    }
  ];

  return (
    <div className="storage-page">
      <header>
        <span>文件管理</span>
        <Divider />
      </header>
      <Space style={{ marginBottom: 10 }}>
        <Select style={{ minWidth: 120 }} value={uploaderProfile?.id} onChange={setCurrentProfile}>
          {uploaderProfiles.map(item => (
            <Select.Option key={item.name} value={item.id}>
              {item.name}
            </Select.Option>
          ))}
        </Select>
        <Button
          title="上传"
          icon={<UploadOutlined />}
          disabled={!hasFileManageFeature}
          type="primary"
          onClick={() => {
            uploadRef.current?.click();
          }}
        />
        <Button title="刷新" icon={<ReloadOutlined />} disabled={!hasFileManageFeature} onClick={handleRefresh} />
        <Button
          title="创建文件夹"
          icon={<FolderAddOutlined />}
          disabled={!hasFileManageFeature}
          onClick={() => {
            setModalVisible(true);
          }}
        />
        <Button
          title="导出"
          icon={<ExportOutlined />}
          disabled={selectRows.length === 0}
          onClick={handleExport}
          loading={exportLoading}
        />
        <Button title="删除" icon={<DeleteOutlined />} disabled={selectRows.length === 0} onClick={handleBatchDelete} />
      </Space>
      <Breadcrumb style={{ marginBottom: 10 }}>
        <Breadcrumb.Item>
          <a onClick={() => handlePathClick(-1)}>全部文件</a>
        </Breadcrumb.Item>
        {dirPath.map((item, index) => (
          <Breadcrumb.Item key={item}>
            <a onClick={() => handlePathClick(index)}>{item}</a>
          </Breadcrumb.Item>
        ))}
      </Breadcrumb>
      <div className="table-wrapper">
        <Table
          size="small"
          rowKey="name"
          scroll={{ y: windowHeight - 270 }}
          dataSource={list}
          columns={columns}
          pagination={{
            size: 'small',
            defaultPageSize: 100,
            pageSizeOptions: ['50', '100', '200'],
            hideOnSinglePage: true
          }}
          loading={listLoading}
          rowSelection={{
            onChange: handleTableRowChange,
            selectedRowKeys: selectRowKeys,
            getCheckboxProps: record => ({ disabled: record?.type === 'directory' })
          }}
        />
      </div>
      <input ref={uploadRef} type="file" multiple hidden onChange={handleFileUpload} />
      <Modal
        title="创建目录"
        visible={modalVisible}
        onCancel={() => setModalVisible(false)}
        onOk={handleCreateDirectory}
        destroyOnClose={true}
      >
        <Form form={form} preserve={false}>
          <Form.Item
            label="目录名称"
            name="directoryPath"
            rules={[{ required: true }, { pattern: domainPathRegExp, message: '目录名不能以 / 开头或结尾' }]}
          >
            <Input autoFocus />
          </Form.Item>
        </Form>
      </Modal>
    </div>
  );
}
Example #13
Source File: index.tsx    From Aragorn with MIT License 4 votes vote down vote up
Dashboard = () => {
  const {
    state: {
      uploaderProfiles,
      configuration: { defaultUploaderProfileId },
      uploadedFiles
    }
  } = useAppContext();

  const history = useHistory();

  const [selectRowKeys, setRowKeys] = useState([]);
  const [selectRows, setSelectRows] = useState([] as UploadedFileInfo[]);

  const handleProfileAdd = () => {
    history.push('/uploader');
  };

  const handleProfileClick = id => {
    if (id === defaultUploaderProfileId) {
      history.push(`/profile/${id}`);
    } else {
      ipcRenderer.send('set-default-uploader-profile', id);
    }
  };

  const handleCopy = url => {
    clipboard.writeText(url);
    message.success('已复制到粘贴板');
  };

  const handleOpen = path => {
    shell.showItemInFolder(path);
  };

  const handleTableRowChange = (selectedRowKeys, selectedRows) => {
    setRowKeys(selectedRowKeys);
    setSelectRows(selectedRows);
  };

  const handleClear = () => {
    const ids = selectRows.map(item => item.id);
    ipcRenderer.send('clear-upload-history', ids);
    setRowKeys([]);
  };

  const handleReUpload = () => {
    const data = selectRows.map(item => {
      return { id: item.uploaderProfileId, path: item.path };
    });
    ipcRenderer.send('file-reupload', data);
    setRowKeys([]);
  };

  const columns: ColumnsType<UploadedFileInfo> = [
    {
      title: '文件名',
      dataIndex: 'name',
      ellipsis: true,
      render: (val, record) => (
        <Popover
          placement="topLeft"
          content={() =>
            /(jpg|png|gif|jpeg)$/.test(val) ? (
              <Image
                style={{ maxWidth: 500 }}
                src={record.url}
                fallback="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMIAAADDCAYAAADQvc6UAAABRWlDQ1BJQ0MgUHJvZmlsZQAAKJFjYGASSSwoyGFhYGDIzSspCnJ3UoiIjFJgf8LAwSDCIMogwMCcmFxc4BgQ4ANUwgCjUcG3awyMIPqyLsis7PPOq3QdDFcvjV3jOD1boQVTPQrgSkktTgbSf4A4LbmgqISBgTEFyFYuLykAsTuAbJEioKOA7DkgdjqEvQHEToKwj4DVhAQ5A9k3gGyB5IxEoBmML4BsnSQk8XQkNtReEOBxcfXxUQg1Mjc0dyHgXNJBSWpFCYh2zi+oLMpMzyhRcASGUqqCZ16yno6CkYGRAQMDKMwhqj/fAIcloxgHQqxAjIHBEugw5sUIsSQpBobtQPdLciLEVJYzMPBHMDBsayhILEqEO4DxG0txmrERhM29nYGBddr//5/DGRjYNRkY/l7////39v///y4Dmn+LgeHANwDrkl1AuO+pmgAAADhlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAAqACAAQAAAABAAAAwqADAAQAAAABAAAAwwAAAAD9b/HnAAAHlklEQVR4Ae3dP3PTWBSGcbGzM6GCKqlIBRV0dHRJFarQ0eUT8LH4BnRU0NHR0UEFVdIlFRV7TzRksomPY8uykTk/zewQfKw/9znv4yvJynLv4uLiV2dBoDiBf4qP3/ARuCRABEFAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghgg0Aj8i0JO4OzsrPv69Wv+hi2qPHr0qNvf39+iI97soRIh4f3z58/u7du3SXX7Xt7Z2enevHmzfQe+oSN2apSAPj09TSrb+XKI/f379+08+A0cNRE2ANkupk+ACNPvkSPcAAEibACyXUyfABGm3yNHuAECRNgAZLuYPgEirKlHu7u7XdyytGwHAd8jjNyng4OD7vnz51dbPT8/7z58+NB9+/bt6jU/TI+AGWHEnrx48eJ/EsSmHzx40L18+fLyzxF3ZVMjEyDCiEDjMYZZS5wiPXnyZFbJaxMhQIQRGzHvWR7XCyOCXsOmiDAi1HmPMMQjDpbpEiDCiL358eNHurW/5SnWdIBbXiDCiA38/Pnzrce2YyZ4//59F3ePLNMl4PbpiL2J0L979+7yDtHDhw8vtzzvdGnEXdvUigSIsCLAWavHp/+qM0BcXMd/q25n1vF57TYBp0a3mUzilePj4+7k5KSLb6gt6ydAhPUzXnoPR0dHl79WGTNCfBnn1uvSCJdegQhLI1vvCk+fPu2ePXt2tZOYEV6/fn31dz+shwAR1sP1cqvLntbEN9MxA9xcYjsxS1jWR4AIa2Ibzx0tc44fYX/16lV6NDFLXH+YL32jwiACRBiEbf5KcXoTIsQSpzXx4N28Ja4BQoK7rgXiydbHjx/P25TaQAJEGAguWy0+2Q8PD6/Ki4R8EVl+bzBOnZY95fq9rj9zAkTI2SxdidBHqG9+skdw43borCXO/ZcJdraPWdv22uIEiLA4q7nvvCug8WTqzQveOH26fodo7g6uFe/a17W3+nFBAkRYENRdb1vkkz1CH9cPsVy/jrhr27PqMYvENYNlHAIesRiBYwRy0V+8iXP8+/fvX11Mr7L7ECueb/r48eMqm7FuI2BGWDEG8cm+7G3NEOfmdcTQw4h9/55lhm7DekRYKQPZF2ArbXTAyu4kDYB2YxUzwg0gi/41ztHnfQG26HbGel/crVrm7tNY+/1btkOEAZ2M05r4FB7r9GbAIdxaZYrHdOsgJ/wCEQY0J74TmOKnbxxT9n3FgGGWWsVdowHtjt9Nnvf7yQM2aZU/TIAIAxrw6dOnAWtZZcoEnBpNuTuObWMEiLAx1HY0ZQJEmHJ3HNvGCBBhY6jtaMoEiJB0Z29vL6ls58vxPcO8/zfrdo5qvKO+d3Fx8Wu8zf1dW4p/cPzLly/dtv9Ts/EbcvGAHhHyfBIhZ6NSiIBTo0LNNtScABFyNiqFCBChULMNNSdAhJyNSiECRCjUbEPNCRAhZ6NSiAARCjXbUHMCRMjZqBQiQIRCzTbUnAARcjYqhQgQoVCzDTUnQIScjUohAkQo1GxDzQkQIWejUogAEQo121BzAkTI2agUIkCEQs021JwAEXI2KoUIEKFQsw01J0CEnI1KIQJEKNRsQ80JECFno1KIABEKNdtQcwJEyNmoFCJAhELNNtScABFyNiqFCBChULMNNSdAhJyNSiECRCjUbEPNCRAhZ6NSiAARCjXbUHMCRMjZqBQiQIRCzTbUnAARcjYqhQgQoVCzDTUnQIScjUohAkQo1GxDzQkQIWejUogAEQo121BzAkTI2agUIkCEQs021JwAEXI2KoUIEKFQsw01J0CEnI1KIQJEKNRsQ80JECFno1KIABEKNdtQcwJEyNmoFCJAhELNNtScABFyNiqFCBChULMNNSdAhJyNSiECRCjUbEPNCRAhZ6NSiAARCjXbUHMCRMjZqBQiQIRCzTbUnAARcjYqhQgQoVCzDTUnQIScjUohAkQo1GxDzQkQIWejUogAEQo121BzAkTI2agUIkCEQs021JwAEXI2KoUIEKFQsw01J0CEnI1KIQJEKNRsQ80JECFno1KIABEKNdtQcwJEyNmoFCJAhELNNtScABFyNiqFCBChULMNNSdAhJyNSiEC/wGgKKC4YMA4TAAAAABJRU5ErkJggg=="
              />
            ) : (
              val
            )
          }
          trigger="hover"
        >
          <span onClick={() => handleCopy(record.url)} className="row-item">
            {val}
          </span>
        </Popover>
      )
    },
    {
      title: '类型',
      dataIndex: 'type',
      ellipsis: true,
      width: 120
    },
    {
      title: '上传器配置',
      dataIndex: 'uploaderProfileId',
      ellipsis: true,
      width: 120,
      render: val => (
        <a onClick={() => handleProfileClick(val)}>
          {uploaderProfiles.find(item => item.id === val)?.name || '未找到'}
        </a>
      )
    },
    {
      title: '状态',
      dataIndex: 'url',
      ellipsis: true,
      width: 80,
      render: val => (
        <>
          <Badge status={val ? 'success' : 'error'} />
          {val ? '成功' : '失败'}
        </>
      )
    },
    {
      title: '上传时间',
      dataIndex: 'date',
      width: 180,
      ellipsis: true,
      render: val => dayjs(val).format('YYYY-MM-DD HH:mm:ss')
    },
    {
      title: '操作',
      width: 80,
      render: (_, record) => (
        <Space>
          <FolderOpenOutlined onClick={() => handleOpen(record.path)} />
          <CopyOutlined onClick={() => handleCopy(record.url)} />
        </Space>
      )
    }
  ];

  return (
    <div className="dashboard-page">
      <header>
        <span>控制台</span>
        <Divider />
      </header>
      <main>
        <div className="profile-wrapper">
          <div className="title">上传器配置</div>
          <div className="card-wrapper">
            {uploaderProfiles.map(item => (
              <div
                key={item.id}
                className={item.id === defaultUploaderProfileId ? 'card card-active' : 'card'}
                onClick={() => handleProfileClick(item.id)}
              >
                <Box className="card-icon" />
                <span>{item.name}</span>
              </div>
            ))}
            <div className="card" onClick={handleProfileAdd}>
              <Plus className="card-icon" />
            </div>
          </div>
        </div>
        <div className="history-wrapper">
          <div className="title">最近上传</div>
          <div className="card-wrapper">
            {selectRowKeys.length > 0 && (
              <Space style={{ marginBottom: 10 }}>
                <Button icon={<DeleteOutlined />} onClick={handleClear}>
                  清除
                </Button>
                <Button icon={<UploadOutlined />} onClick={handleReUpload}>
                  重新上传
                </Button>
              </Space>
            )}
            <Table
              size="small"
              rowKey="id"
              dataSource={uploadedFiles}
              columns={columns}
              rowSelection={{ onChange: handleTableRowChange, selectedRowKeys: selectRowKeys }}
            />
          </div>
        </div>
      </main>
    </div>
  );
}
Example #14
Source File: index.tsx    From fe-v5 with Apache License 2.0 4 votes vote down vote up
Indicator: React.FC = () => {
  const { t } = useTranslation();
  // 数据定义
  const [form] = Form.useForm();
  const tableRef = useRef(null as any);
  const exportTextRef = useRef(null as any);
  const [modal, setModal] = useState<boolean>(false);
  const [modalType, setModalType] = useState('create');
  const [exportList, setExportList] = useState([] as string[]);
  const [editingKey, setEditingKey] = useState<Partial<InterfaceItem>>({});
  const [query, setQuery] = useState<string>('');
  const history = useHistory();
  const moreOperations: MoreOptions = {
    导入指标: 'import',
    导出指标: 'export',
  };
  const optMap = {
    import: t('导入'),
    edit: t('编辑'),
    export: t('导出'),
    create: t('创建'),
  }; // 弹窗操作

  const handleOpen = (type: string = 'create') => {
    setModalType(type);
    setModal(true);
  };

  const handleCancel = () => {
    setModal(false);
  }; // 接口操作

  const handleEdit = (item: InterfaceItem) => {
    setEditingKey(item);
  };

  const handleDelete = (item) => {
    deleteIndicator([item.id]).then(async (res) => {
      await tableRef.current.refreshList();
      message.success(t('删除指标成功'));
    });
  };

  const handleAdd = async () => {
    try {
      const values = await form.validateFields();
      addIndicator(values.metrics || '').then(async (res) => {
        if (res && res.success) {
          await tableRef.current.refreshList();
          setModal(false);
          message.success(t('创建指标成功'));
        }
      });
    } catch (e) {}
  }; // 更多操作

  const [oType, setOType] = useState<string>(t('更多操作'));

  const onSelect = (val: string): void => {
    switch (val) {
      case 'import':
        setModal(true);
        setModalType('import');
        break;

      case 'export':
        if (exportList.length <= 0) {
          message.warning(t('请勾选需要导出的指标'));
        } else {
          setModal(true);
          setModalType('export');
          setTimeout(() => {
            exportTextRef.current && exportTextRef.current.focus();
          });
        }

        break;

      default:
        break;
    }

    setOType(val);
  }; // table

  const handleEditChange = (e, record, index, field) => {
    let targetCol = Object.assign({}, record);
    targetCol[field] = e.target.value;
    setEditingKey(targetCol);
  };

  const renderInput = (text, record, index, field) => {
    if (record.id === editingKey.id) {
      return (
        <Input
          defaultValue={text}
          onPressEnter={() => handleEditOption('save')}
          onChange={(e) => handleEditChange(e, record, index, field)}
        />
      );
    } else {
      return <span>{text}</span>;
    }
  };

  const handleEditOption = async (type = '') => {
    if (type === 'save') {
      let id = editingKey.id || -1;
      await editIndicator(id, {
        description: editingKey.description,
        metric: editingKey.metric,
      });
      message.success(t('编辑成功'));
      tableRef.current.refreshList();
    }

    setEditingKey({} as any);
  };

  const columns = [
    {
      title: t('指标名称'),
      dataIndex: 'metric',
      key: 'metric',
      render: (text: string, record: InterfaceItem) => {
        return (
          <a
            onClick={() => {
              let path = {
                pathname: `/metric/explorer`,
                state: { name: text, description: record.description },
              };
              history.push(path);
            }}
          >
            {text}
          </a>
        );
      },
    },
    {
      title: t('释义'),
      dataIndex: 'description',
      width: '40%',
      key: 'description',
      render: (text: string, record: InterfaceItem, index: number) => {
        return renderInput(text, record, index, 'description');
      },
    },
    {
      title: t('操作'),
      dataIndex: '',
      key: 'operations',
      width: '15%',
      render: (_: any, item: any) => {
        return (
          <div className='operations'>
            {item.id !== editingKey.id ? (
              <div>
                <span
                  className='operation-item edit'
                  onClick={() => handleEdit(item)}
                >
                  {t('编辑')}
                </span>
                {/* <Popconfirm
             title='确定删除该指标?'
             onConfirm={() => handleDelete(item)}
             okText='确定'
             cancelText='取消'
            >
             <span className='operation-item delete'>删除</span>
            </Popconfirm> */}
                <div
                  className='table-operator-area-warning'
                  style={{
                    display: 'inline-block',
                    marginLeft: 10,
                  }}
                  onClick={() => {
                    confirm({
                      title: t('确定删除该指标?'),
                      icon: <ExclamationCircleOutlined />,
                      onOk: () => {
                        handleDelete(item);
                      },
                    });
                  }}
                >
                  {t('删除')}
                </div>
              </div>
            ) : (
              <div>
                <span
                  className='operation-item edit-save'
                  onClick={() => handleEditOption('save')}
                >
                  {t('保存')}
                </span>
                <span
                  className='operation-item edit-cancel'
                  onClick={() => handleEditOption('cancel')}
                >
                  {t('取消')}
                </span>
              </div>
            )}
          </div>
        );
      },
    },
  ];

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

  const rowSelection = {
    onChange: (selectedRowKeys, selectedRows) => {
      let list: string[] = [];
      selectedRows.map((item) => {
        list.push(`${item.metric}:${item.description}`);
      });
      setExportList(list);
    },
  };

  const handleExportTxt = () => {
    download(exportList);
  };

  return (
    <PageLayout title={t('指标释义')} icon={<BulbOutlined />}>
      <div className='indicator-index'>
        <div className='indicator-operations'>
          <Input
            className={'searchInput'}
            onPressEnter={onSearchQuery}
            prefix={<SearchOutlined />}
            placeholder={t('指标名称或释义')}
          />
          <div className='operations'>
            <Button.Group>
              <Button
                size='middle'
                type='default'
                icon={<DownloadOutlined />}
                onClick={() => onSelect('import')}
              >
                {t('导入')}
              </Button>
              <Button
                size='middle'
                type='default'
                icon={<UploadOutlined />}
                onClick={() => onSelect('export')}
              >
                {t('导出')}
              </Button>
            </Button.Group>
          </div>
        </div>
        <div className='indicator-main'>
          <BaseTable
            fetchHandle={getIndicatorList}
            ref={tableRef}
            fetchParams={{
              query: query,
            }}
            rowSelection={{ ...rowSelection }}
            rowKey={(record: { id: number }) => {
              return record.id;
            }}
            columns={columns}
          />
        </div>
      </div>
      <Modal
        title={optMap[modalType]}
        destroyOnClose={true}
        footer={
          modalType !== 'export' && [
            <Button key='delete' onClick={handleCancel}>
              {t('取消')}
            </Button>,
            <Button key='submit' type='primary' onClick={handleAdd}>
              {t('确定')}
            </Button>,
          ]
        }
        onCancel={handleCancel}
        visible={modal}
      >
        <p
          style={{
            color: '#999',
          }}
        >
          {modalType === 'export' ? (
            <a onClick={handleExportTxt}>Download.txt</a>
          ) : (
            <span>{t('一行一个')}</span>
          )}
        </p>
        {(() => {
          switch (modalType) {
            case 'export':
              return (
                <div
                  contentEditable='true'
                  suppressContentEditableWarning={true}
                  ref={exportTextRef}
                  style={{
                    height: '200px',
                    border: '1px solid #d9d9d9',
                    overflow: 'auto',
                    padding: '10px',
                  }}
                >
                  {exportList.map((item, index) => {
                    return <div key={index}>{item}</div>;
                  })}
                </div>
              );
              break;

            case 'import':
            case 'create':
              return (
                <Form name={modalType + '-dialog'} form={form} preserve={false}>
                  <Form.Item
                    name={'metrics'}
                    key={'metrics'}
                    rules={[
                      {
                        required: true,
                        message: t('不能为空'),
                        validateTrigger: 'trigger',
                      },
                    ]}
                  >
                    <TextArea
                      placeholder={'name:description'}
                      rows={4}
                    ></TextArea>
                  </Form.Item>
                </Form>
              );
              break;
          }
        })()}
      </Modal>
    </PageLayout>
  );
}
Example #15
Source File: index.tsx    From jetlinks-ui-antd with MIT License 4 votes vote down vote up
BasicInfo = (props: Props) => {
  const { data } = props;
  const [loading, setLoading] = useState(false);

  const [photo, setPhoto] = useState(data?.photo);
  const {
    form: { getFieldDecorator, getFieldsValue },
  } = props;
  const service = new Service('tenant');
  const uploadProps: UploadProps = {
    // accept: ,
    action: '/jetlinks/file/static',
    headers: {
      'X-Access-Token': getAccessToken(),
    },
    showUploadList: false,
    onChange(info) {
      if (info.file.status === 'uploading') {
        setLoading(true);
      }
      if (info.file.status === 'done') {
        setPhoto(info.file.response.result);
        message.success('上传成功');
        setLoading(false);
      }
    },
  };

  const updateInfo = () => {
    setLoading(true);
    const temp = getFieldsValue();
    service.update({ ...data, ...temp, photo }).subscribe(
      response => {
        setLoading(false);
      },
      () => {},
      () => message.success('保存成功'),
    );
  };
  const formLayout = {
    labelCol: { span: 9 },
    wrapperCol: { span: 15 },
  };
  return (
    <div className={styles.right}>
      <Spin spinning={loading}>
        <div className={styles.baseView}>
          <div className={styles.left}>
            <Form {...formLayout}>
              <Form.Item label="租户名称">
                {getFieldDecorator('name', {
                  initialValue: data?.name,
                })(<Input />)}
              </Form.Item>
              <Form.Item label="状态">
                <Tag>{data?.state?.text}</Tag>
              </Form.Item>
              <Form.Item label="创建时间">
                {moment(data?.createTime).format('YYYY-MM-DD HH:mm:ss')}
              </Form.Item>

              <Form.Item label="说明">
                {getFieldDecorator('description', {
                  initialValue: data?.description,
                })(<Input.TextArea placeholder="说明" rows={4} />)}
              </Form.Item>
              <Form.Item>
                <Button
                  style={{ marginLeft: 200 }}
                  htmlType="submit"
                  type="primary"
                  onClick={updateInfo}
                >
                  更新基本信息
                </Button>
              </Form.Item>
            </Form>
          </div>
          <div className={styles.right}>
            <>
              <div className={styles.avatar_title}>头像</div>
              <div className={styles.avatar}>
                <img src={photo || data?.photo || defaultimg} alt="avatar" />
              </div>
              <Upload {...uploadProps} showUploadList={false}>
                <div className={styles.button_view}>
                  <Button>
                    <UploadOutlined />
                    更换图片
                  </Button>
                </div>
              </Upload>
            </>
          </div>
        </div>
      </Spin>
    </div>
  );
}
Example #16
Source File: index.tsx    From jetlinks-ui-antd with MIT License 4 votes vote down vote up
Config: React.FC<Props> = props => {
    const [loading, setLoading] = useState(false);

    const { form: { getFieldDecorator, getFieldsValue }, settings } = props;
    const [titleIcon, setTitleIcon] = useState(settings.titleIcon);
    const updateSetting = () => {
        const { dispatch } = props;
        dispatch({
            type: 'settings/settingData',
            payload: { ...settings, ...getFieldsValue(), titleIcon },
            // callback:()=>{message.success('保存成功')}
            callback:(response:any)=>{
                if(response.status === 200){
                    message.success('更新成功');
                }else{
                    message.success('更新失败');
                }
            }

        })


    }


    const uploadProps: UploadProps = {
        // accept: ,
        action: '/jetlinks/file/static',
        headers: {
            'X-Access-Token': getAccessToken(),
        },
        showUploadList: false,
        onChange(info) {
            if (info.file.status === 'uploading') {
                setLoading(true);
            }
            if (info.file.status === 'done') {
                setTitleIcon(info.file.response.result);
                message.success('上传成功');
                setLoading(false);
            }
        },
    };

    return (
        <GridContent>
            <div
                className={styles.main}
            >

                <div className={styles.leftMenu}>
                    <Menu
                        mode='inline'
                        selectedKeys={['basic']}
                    >
                        <Menu.Item key="basic">系统配置</Menu.Item>
                        {/* <Menu.Item key="advance">高级</Menu.Item> */}

                    </Menu>
                </div>
                <Spin spinning={loading}>
                    <div className={styles.right}>
                        <div className={styles.title}>系统配置</div>
                        <div className={styles.baseView}>
                            <div className={styles.left}>
                                <Form
                                    layout="vertical"
                                    hideRequiredMark
                                >
                                    <Form.Item
                                        label="系统名称"
                                    >
                                        {getFieldDecorator('title', {
                                            initialValue: settings.title,
                                        })(
                                            <Input />
                                        )}
                                    </Form.Item>
                                    <Form.Item
                                        label="主题色"
                                    >
                                        {getFieldDecorator('navTheme', {
                                            initialValue: settings.navTheme
                                        })(
                                            <Select onChange={(e: string) => { localStorage.setItem('theme', e) }}>
                                                <Select.Option value="light">light</Select.Option>
                                                <Select.Option value="dark">dark</Select.Option>
                                            </Select>
                                        )}
                                    </Form.Item>
                                    {/* <Form.Item
                                        label="系统简介"
                                    >
                                        <Input.TextArea
                                            placeholder="系统简介"
                                            rows={4}
                                        />
                                    </Form.Item> */}
                                    <Form.Item>
                                        <Button htmlType="submit" type="primary" onClick={updateSetting}>
                                            更新基本信息
                                    </Button>
                                    </Form.Item>
                                </Form>
                            </div>
                            <div className={styles.right}>
                                <>
                                    <div className={styles.avatar_title}>
                                        系统LOGO
                                </div>
                                    <div className={styles.avatar}>
                                       <img src={titleIcon||logo} alt='default'/>
                                    </div>
                                    <Upload {...uploadProps} showUploadList={false}>
                                        <div className={styles.button_view}>
                                            <Button>
                                                <UploadOutlined />
                                            更换LOGO
                                            </Button>
                                        </div>
                                    </Upload>
                                </>
                            </div>
                        </div>
                    </div>
                </Spin>

            </div>
        </GridContent>
    );
}
Example #17
Source File: palette.tsx    From jmix-frontend with Apache License 2.0 4 votes vote down vote up
palette = () => (
  <Palette>
    <Category name="Text">
      <Component name="Formatted Message">
        <Variant>
          <FormattedMessage />
        </Variant>
      </Component>
      <Component name="Heading">
        <Variant name="h1">
          <Typography.Title></Typography.Title>
        </Variant>
        <Variant name="h2">
          <Typography.Title level={2}></Typography.Title>
        </Variant>
        <Variant name="h3">
          <Typography.Title level={3}></Typography.Title>
        </Variant>
        <Variant name="h4">
          <Typography.Title level={4}></Typography.Title>
        </Variant>
        <Variant name="h5">
          <Typography.Title level={5}></Typography.Title>
        </Variant>
      </Component>
      <Component name="Text">
        <Variant>
          <Typography.Text></Typography.Text>
        </Variant>
        <Variant name="Secondary">
          <Typography.Text type="secondary"></Typography.Text>
        </Variant>
        <Variant name="Success">
          <Typography.Text type="success"></Typography.Text>
        </Variant>
        <Variant name="Warning">
          <Typography.Text type="warning"></Typography.Text>
        </Variant>
        <Variant name="Danger">
          <Typography.Text type="danger"></Typography.Text>
        </Variant>
        <Variant name="Disabled">
          <Typography.Text disabled></Typography.Text>
        </Variant>
      </Component>
    </Category>
    <Category name="Layout">
      <Component name="Divider">
        <Variant>
          <Divider />
        </Variant>
      </Component>

      <Component name="Grid">
        <Variant name="Simple Row">
          <Row></Row>
        </Variant>
        <Variant name="Two columns">
          <Row>
            <Col span={12}></Col>
            <Col span={12}></Col>
          </Row>
        </Variant>
        <Variant name="Three columns">
          <Row>
            <Col span={8}></Col>
            <Col span={8}></Col>
            <Col span={8}></Col>
          </Row>
        </Variant>
      </Component>

      <Component name="Space">
        <Variant>
          <Space />
        </Variant>
        <Variant name="Small">
          <Space size={"small"} />
        </Variant>
        <Variant name="Large">
          <Space size={"large"} />
        </Variant>
      </Component>
    </Category>
    <Category name="Controls">
      <Component name="Autocomplete">
        <Variant>
          <AutoComplete placeholder="input here" />
        </Variant>
      </Component>

      <Component name="Button">
        <Variant>
          <Button></Button>
        </Variant>
        <Variant name="Primary">
          <Button type="primary"></Button>
        </Variant>
        <Variant name="Link">
          <Button type="link"></Button>
        </Variant>
        <Variant name="Dropdown">
          <Dropdown
            trigger={["click"]}
            overlay={
              <Menu>
                <Menu.Item></Menu.Item>
                <Menu.Item></Menu.Item>
                <Menu.Item></Menu.Item>
              </Menu>
            }
          >
            <Button></Button>
          </Dropdown>
        </Variant>
      </Component>

      <Component name="Checkbox">
        <Variant>
          <Checkbox />
        </Variant>
      </Component>

      <Component name="Switch">
        <Variant>
          <Switch />
        </Variant>
      </Component>

      <Component name="Radio Group">
        <Variant>
          <Radio.Group>
            <Radio value={1}>A</Radio>
            <Radio value={2}>B</Radio>
            <Radio value={3}>C</Radio>
            <Radio value={4}>D</Radio>
          </Radio.Group>
        </Variant>
        <Variant name="Button">
          <Radio.Group>
            <Radio.Button value={1}>A</Radio.Button>
            <Radio.Button value={2}>B</Radio.Button>
            <Radio.Button value={3}>C</Radio.Button>
            <Radio.Button value={4}>D</Radio.Button>
          </Radio.Group>
        </Variant>
      </Component>

      <Component name="DatePicker">
        <Variant>
          <DatePicker />
        </Variant>
        <Variant name="Range">
          <DatePicker.RangePicker />
        </Variant>
      </Component>

      <Component name="TimePicker">
        <Variant>
          <TimePicker />
        </Variant>
        <Variant name="Range">
          <TimePicker.RangePicker />
        </Variant>
      </Component>

      <Component name="Input">
        <Variant>
          <Input />
        </Variant>
        <Variant name="Number">
          <InputNumber />
        </Variant>
      </Component>

      <Component name="Select">
        <Variant>
          <Select defaultValue="1">
            <Select.Option value="1">1</Select.Option>
            <Select.Option value="2">2</Select.Option>
          </Select>
        </Variant>
        <Variant name="Multiple">
          <Select defaultValue={["1"]} mode="multiple" allowClear>
            <Select.Option value="1">1</Select.Option>
            <Select.Option value="2">2</Select.Option>
          </Select>
        </Variant>
      </Component>

      <Component name="Link">
        <Variant>
          <Typography.Link href="" target="_blank"></Typography.Link>
        </Variant>
      </Component>

      <Component name="Slider">
        <Variant>
          <Slider defaultValue={30} />
        </Variant>
        <Variant name="Range">
          <Slider range defaultValue={[20, 50]} />
        </Variant>
      </Component>
    </Category>
    <Category name="Data Display">
      <Component name="Field">
        <Variant>
          <Field
            entityName={ENTITY_NAME}
            disabled={readOnlyMode}
            propertyName=""
            formItemProps={{
              style: { marginBottom: "12px" }
            }}
          />
        </Variant>
      </Component>
      <Component name="Card">
        <Variant>
          <Card />
        </Variant>
        <Variant name="With Title">
          <Card>
            <Card title="Card title">
              <p>Card content</p>
            </Card>
          </Card>
        </Variant>
        <Variant name="My custom card">
          <Card>
            <Card title="Card title">
              <p>Card content</p>
              <Avatar />
            </Card>
          </Card>
        </Variant>
      </Component>
      <Component name="Tabs">
        <Variant>
          <Tabs defaultActiveKey="1">
            <Tabs.TabPane tab="Tab 1" key="1">
              Content of Tab Pane 1
            </Tabs.TabPane>
            <Tabs.TabPane tab="Tab 2" key="2">
              Content of Tab Pane 2
            </Tabs.TabPane>
            <Tabs.TabPane tab="Tab 3" key="3">
              Content of Tab Pane 3
            </Tabs.TabPane>
          </Tabs>
        </Variant>
        <Variant name="Tab Pane">
          <Tabs.TabPane></Tabs.TabPane>
        </Variant>
      </Component>
      <Component name="Collapse">
        <Variant>
          <Collapse defaultActiveKey="1">
            <Collapse.Panel
              header="This is panel header 1"
              key="1"
            ></Collapse.Panel>
            <Collapse.Panel
              header="This is panel header 2"
              key="2"
            ></Collapse.Panel>
            <Collapse.Panel
              header="This is panel header 3"
              key="3"
            ></Collapse.Panel>
          </Collapse>
        </Variant>
      </Component>
      <Component name="Image">
        <Variant>
          <Image width={200} src="" />
        </Variant>
      </Component>
      <Component name="Avatar">
        <Variant>
          <Avatar icon={<UserOutlined />} />
        </Variant>
        <Variant name="Image">
          <Avatar src="https://joeschmoe.io/api/v1/random" />
        </Variant>
      </Component>
      <Component name="Badge">
        <Variant>
          <Badge count={1}></Badge>
        </Variant>
      </Component>
      <Component name="Statistic">
        <Variant>
          <Statistic title="Title" value={112893} />
        </Variant>
      </Component>
      <Component name="Alert">
        <Variant name="Success">
          <Alert message="Text" type="success" />
        </Variant>
        <Variant name="Info">
          <Alert message="Text" type="info" />
        </Variant>
        <Variant name="Warning">
          <Alert message="Text" type="warning" />
        </Variant>
        <Variant name="Error">
          <Alert message="Text" type="error" />
        </Variant>
      </Component>
      <Component name="List">
        <Variant>
          <List
            bordered
            dataSource={[]}
            renderItem={item => <List.Item></List.Item>}
          />
        </Variant>
      </Component>
    </Category>
    <Category name="Icons">
      <Component name="Arrow">
        <Variant name="Up">
          <ArrowUpOutlined />
        </Variant>
        <Variant name="Down">
          <ArrowDownOutlined />
        </Variant>
        <Variant name="Left">
          <ArrowLeftOutlined />
        </Variant>
        <Variant name="Right">
          <ArrowRightOutlined />
        </Variant>
      </Component>
      <Component name="Question">
        <Variant>
          <QuestionOutlined />
        </Variant>
        <Variant name="Circle">
          <QuestionCircleOutlined />
        </Variant>
      </Component>
      <Component name="Plus">
        <Variant>
          <PlusOutlined />
        </Variant>
        <Variant name="Circle">
          <PlusCircleOutlined />
        </Variant>
      </Component>
      <Component name="Info">
        <Variant>
          <InfoOutlined />
        </Variant>
        <Variant name="Circle">
          <InfoCircleOutlined />
        </Variant>
      </Component>
      <Component name="Exclamation">
        <Variant>
          <ExclamationOutlined />
        </Variant>
        <Variant name="Circle">
          <ExclamationCircleOutlined />
        </Variant>
      </Component>
      <Component name="Close">
        <Variant>
          <CloseOutlined />
        </Variant>
        <Variant name="Circle">
          <CloseCircleOutlined />
        </Variant>
      </Component>
      <Component name="Check">
        <Variant>
          <CheckOutlined />
        </Variant>
        <Variant name="Circle">
          <CheckCircleOutlined />
        </Variant>
      </Component>
      <Component name="Edit">
        <Variant>
          <EditOutlined />
        </Variant>
      </Component>
      <Component name="Copy">
        <Variant>
          <CopyOutlined />
        </Variant>
      </Component>
      <Component name="Delete">
        <Variant>
          <DeleteOutlined />
        </Variant>
      </Component>
      <Component name="Bars">
        <Variant>
          <BarsOutlined />
        </Variant>
      </Component>
      <Component name="Bell">
        <Variant>
          <BellOutlined />
        </Variant>
      </Component>
      <Component name="Clear">
        <Variant>
          <ClearOutlined />
        </Variant>
      </Component>
      <Component name="Download">
        <Variant>
          <DownloadOutlined />
        </Variant>
      </Component>
      <Component name="Upload">
        <Variant>
          <UploadOutlined />
        </Variant>
      </Component>
      <Component name="Sync">
        <Variant>
          <SyncOutlined />
        </Variant>
      </Component>
      <Component name="Save">
        <Variant>
          <SaveOutlined />
        </Variant>
      </Component>
      <Component name="Search">
        <Variant>
          <SearchOutlined />
        </Variant>
      </Component>
      <Component name="Settings">
        <Variant>
          <SettingOutlined />
        </Variant>
      </Component>
      <Component name="Paperclip">
        <Variant>
          <PaperClipOutlined />
        </Variant>
      </Component>
      <Component name="Phone">
        <Variant>
          <PhoneOutlined />
        </Variant>
      </Component>
      <Component name="Mail">
        <Variant>
          <MailOutlined />
        </Variant>
      </Component>
      <Component name="Home">
        <Variant>
          <HomeOutlined />
        </Variant>
      </Component>
      <Component name="Contacts">
        <Variant>
          <ContactsOutlined />
        </Variant>
      </Component>
      <Component name="User">
        <Variant>
          <UserOutlined />
        </Variant>
        <Variant name="Add">
          <UserAddOutlined />
        </Variant>
        <Variant name="Remove">
          <UserDeleteOutlined />
        </Variant>
      </Component>
      <Component name="Team">
        <Variant>
          <TeamOutlined />
        </Variant>
      </Component>
    </Category>
    <Category name="Screens">
      <Component name="ExampleCustomScreen">
        <Variant>
          <ExampleCustomScreen />
        </Variant>
      </Component>
      <Component name="CustomEntityFilterTest">
        <Variant>
          <CustomEntityFilterTest />
        </Variant>
      </Component>
      <Component name="CustomFormControls">
        <Variant>
          <CustomFormControls />
        </Variant>
      </Component>
      <Component name="CustomDataDisplayComponents">
        <Variant>
          <CustomDataDisplayComponents />
        </Variant>
      </Component>
      <Component name="CustomAppLayouts">
        <Variant>
          <CustomAppLayouts />
        </Variant>
      </Component>
      <Component name="CustomControls">
        <Variant>
          <CustomControls />
        </Variant>
      </Component>
      <Component name="ErrorBoundaryTests">
        <Variant>
          <ErrorBoundaryTests />
        </Variant>
      </Component>
      <Component name="TestBlankScreen">
        <Variant>
          <TestBlankScreen />
        </Variant>
      </Component>
      <Component name="CarEditor">
        <Variant>
          <CarEditor />
        </Variant>
      </Component>
      <Component name="CarBrowserCards">
        <Variant>
          <CarBrowserCards />
        </Variant>
      </Component>
      <Component name="CarBrowserList">
        <Variant>
          <CarBrowserList />
        </Variant>
      </Component>
      <Component name="CarBrowserTable">
        <Variant>
          <CarBrowserTable />
        </Variant>
      </Component>
      <Component name="CarCardsGrid">
        <Variant>
          <CarCardsGrid />
        </Variant>
      </Component>
      <Component name="FavoriteCars">
        <Variant>
          <FavoriteCars />
        </Variant>
      </Component>
      <Component name="CarCardsWithDetails">
        <Variant>
          <CarCardsWithDetails />
        </Variant>
      </Component>
      <Component name="CarTableWithFilters">
        <Variant>
          <CarTableWithFilters />
        </Variant>
      </Component>
      <Component name="CarMasterDetail">
        <Variant>
          <CarMasterDetail />
        </Variant>
      </Component>
      <Component name="FormWizardCompositionO2O">
        <Variant>
          <FormWizardCompositionO2O />
        </Variant>
      </Component>
      <Component name="FormWizardEditor">
        <Variant>
          <FormWizardEditor />
        </Variant>
      </Component>
      <Component name="FormWizardBrowserTable">
        <Variant>
          <FormWizardBrowserTable />
        </Variant>
      </Component>
      <Component name="CarMultiSelectionTable">
        <Variant>
          <CarMultiSelectionTable />
        </Variant>
      </Component>
      <Component name="DatatypesTestEditor">
        <Variant>
          <DatatypesTestEditor />
        </Variant>
      </Component>
      <Component name="DatatypesTestBrowserCards">
        <Variant>
          <DatatypesTestBrowserCards />
        </Variant>
      </Component>
      <Component name="DatatypesTestBrowserList">
        <Variant>
          <DatatypesTestBrowserList />
        </Variant>
      </Component>
      <Component name="DatatypesTestBrowserTable">
        <Variant>
          <DatatypesTestBrowserTable />
        </Variant>
      </Component>
      <Component name="DatatypesTestCards">
        <Variant>
          <DatatypesTestCards />
        </Variant>
      </Component>
      <Component name="AssociationO2OEditor">
        <Variant>
          <AssociationO2OEditor />
        </Variant>
      </Component>
      <Component name="AssociationO2OBrowserTable">
        <Variant>
          <AssociationO2OBrowserTable />
        </Variant>
      </Component>
      <Component name="AssociationO2MEditor">
        <Variant>
          <AssociationO2MEditor />
        </Variant>
      </Component>
      <Component name="AssociationO2MBrowserTable">
        <Variant>
          <AssociationO2MBrowserTable />
        </Variant>
      </Component>
      <Component name="AssociationM2OEditor">
        <Variant>
          <AssociationM2OEditor />
        </Variant>
      </Component>
      <Component name="AssociationM2OBrowserTable">
        <Variant>
          <AssociationM2OBrowserTable />
        </Variant>
      </Component>
      <Component name="AssociationM2MEditor">
        <Variant>
          <AssociationM2MEditor />
        </Variant>
      </Component>
      <Component name="AssociationM2MBrowserTable">
        <Variant>
          <AssociationM2MBrowserTable />
        </Variant>
      </Component>
      <Component name="CompositionO2OEditor">
        <Variant>
          <CompositionO2OEditor />
        </Variant>
      </Component>
      <Component name="CompositionO2OBrowserTable">
        <Variant>
          <CompositionO2OBrowserTable />
        </Variant>
      </Component>
      <Component name="CompositionO2MEditor">
        <Variant>
          <CompositionO2MEditor />
        </Variant>
      </Component>
      <Component name="CompositionO2MBrowserTable">
        <Variant>
          <CompositionO2MBrowserTable />
        </Variant>
      </Component>
      <Component name="DeeplyNestedTestEntityEditor">
        <Variant>
          <DeeplyNestedTestEntityEditor />
        </Variant>
      </Component>
      <Component name="DeeplyNestedO2MTestEntityTable">
        <Variant>
          <DeeplyNestedO2MTestEntityTable />
        </Variant>
      </Component>
      <Component name="DeeplyNestedO2MTestEntityEditor">
        <Variant>
          <DeeplyNestedO2MTestEntityEditor />
        </Variant>
      </Component>
      <Component name="IntIdEditor">
        <Variant>
          <IntIdEditor />
        </Variant>
      </Component>
      <Component name="IntIdBrowserTable">
        <Variant>
          <IntIdBrowserTable />
        </Variant>
      </Component>
      <Component name="IntIdBrowserCards">
        <Variant>
          <IntIdBrowserCards />
        </Variant>
      </Component>
      <Component name="IntIdBrowserList">
        <Variant>
          <IntIdBrowserList />
        </Variant>
      </Component>
      <Component name="IntIdentityIdCards">
        <Variant>
          <IntIdentityIdCards />
        </Variant>
      </Component>
      <Component name="IntIdentityIdEditor">
        <Variant>
          <IntIdentityIdEditor />
        </Variant>
      </Component>
      <Component name="IntIdentityIdBrowserTable">
        <Variant>
          <IntIdentityIdBrowserTable />
        </Variant>
      </Component>
      <Component name="IntIdentityIdBrowserCards">
        <Variant>
          <IntIdentityIdBrowserCards />
        </Variant>
      </Component>
      <Component name="IntIdentityIdBrowserList">
        <Variant>
          <IntIdentityIdBrowserList />
        </Variant>
      </Component>
      <Component name="StringIdCards">
        <Variant>
          <StringIdCards />
        </Variant>
      </Component>
      <Component name="StringIdMgtCardsEdit">
        <Variant>
          <StringIdMgtCardsEdit />
        </Variant>
      </Component>
      <Component name="StringIdBrowserCards">
        <Variant>
          <StringIdBrowserCards />
        </Variant>
      </Component>
      <Component name="StringIdBrowserList">
        <Variant>
          <StringIdBrowserList />
        </Variant>
      </Component>
      <Component name="StringIdBrowserTable">
        <Variant>
          <StringIdBrowserTable />
        </Variant>
      </Component>
      <Component name="WeirdStringIdEditor">
        <Variant>
          <WeirdStringIdEditor />
        </Variant>
      </Component>
      <Component name="WeirdStringIdBrowserCards">
        <Variant>
          <WeirdStringIdBrowserCards />
        </Variant>
      </Component>
      <Component name="WeirdStringIdBrowserList">
        <Variant>
          <WeirdStringIdBrowserList />
        </Variant>
      </Component>
      <Component name="WeirdStringIdBrowserTable">
        <Variant>
          <WeirdStringIdBrowserTable />
        </Variant>
      </Component>
      <Component name="BoringStringIdEditor">
        <Variant>
          <BoringStringIdEditor />
        </Variant>
      </Component>
      <Component name="BoringStringIdBrowserTable">
        <Variant>
          <BoringStringIdBrowserTable />
        </Variant>
      </Component>
      <Component name="TrickyIdEditor">
        <Variant>
          <TrickyIdEditor />
        </Variant>
      </Component>
      <Component name="TrickyIdBrowserTable">
        <Variant>
          <TrickyIdBrowserTable />
        </Variant>
      </Component>
    </Category>
  </Palette>
)
Example #18
Source File: index.tsx    From jetlinks-ui-antd with MIT License 4 votes vote down vote up
BaseView: React.FC<Props> = (props) => {
    const { form: { getFieldDecorator, getFieldsValue }, dispatch } = props;
    const service = new Service('user/detail');
    const [user, setUser] = useState<Partial<UserDetail>>({});
    const [loading, setLoading] = useState<boolean>(false);
    const [avatar, setAvatar] = useState<string>('');
    useEffect(() => {
        service.get().subscribe(data => {
            setUser(data);
            setAvatar(data.avatar);
        });
    }, []);

    const uploadProps: UploadProps = {
        // accept: ,
        action: '/jetlinks/file/static',
        headers: {
            'X-Access-Token': getAccessToken(),
        },
        showUploadList: false,
        onChange(info) {
            if (info.file.status === 'uploading') {
                setLoading(true);
            }
            if (info.file.status === 'done') {
                setAvatar(info.file.response.result);
                message.success('上传成功');
                setLoading(false);
            }
        },
    };

    const update = (e: React.FormEvent<HTMLFormElement>) => {
        e.preventDefault();
        const data: any = { ...getFieldsValue(), avatar };
        if (data && data.mainTenant) {
            service.setMainTenant(data.mainTenant).subscribe();
        }
        service.save(data).subscribe(() => {
            message.success('保存成功!');
            if (dispatch) {
                dispatch({
                    type: 'user/saveCurrentUser',
                    payload: {
                        avatar: avatar,
                    }
                });
            }
        }, () => {
            message.error('保存失败');
        })
    }
    return (
        <Spin spinning={loading}>
            <div className={styles.baseView}>
                <div className={styles.left}>
                    <Form
                        layout="vertical"
                        onSubmit={update}
                    >
                        <Form.Item label="姓名">
                            {getFieldDecorator('name', {
                                initialValue: user.name,
                            })(
                                <Input />
                            )}
                        </Form.Item>
                        {
                            user.tenants && user.tenants?.length > 0 && (
                                <Form.Item label="主租户">
                                    {getFieldDecorator('mainTenant', {
                                        initialValue: user.tenants.find((i: any) => i.mainTenant === true)?.tenantId,
                                    })(
                                        <Select allowClear>
                                            {user.tenants.map((item: any) => <Select.Option key={item.tenantId} value={item.tenantId}>{item.tenantName}</Select.Option>)}
                                        </Select>
                                    )}
                                </Form.Item>
                            )
                        }
                        <Form.Item label="邮箱">
                            {getFieldDecorator('email', {
                                initialValue: user.email,
                            })(
                                <Input />
                            )}
                        </Form.Item>
                        <Form.Item label="联系电话">
                            {getFieldDecorator('telephone', {
                                initialValue: user.telephone,
                            })(
                                <Input />
                            )}
                        </Form.Item>
                        <Form.Item label="说明">
                            {getFieldDecorator('description', {
                                initialValue: user.description
                            })(
                                <Input.TextArea rows={3} />
                            )}
                        </Form.Item>

                        <Form.Item>
                            <Button htmlType="submit" type="primary">更新信息</Button>
                        </Form.Item>
                    </Form>
                </div>
                <div className={styles.right}>
                    <div className={styles.avatar_title}>
                        头像
                </div>
                    <div className={styles.avatar}>
                        <img src={avatar || defaultImg} alt="avatar" />
                    </div>
                    <Upload {...uploadProps} showUploadList={false}>
                        <div className={styles.button_view}>
                            <Button>
                                <UploadOutlined />更换头像
                            </Button>
                        </div>
                    </Upload>
                </div>
            </div>
        </Spin>

    )
}
Example #19
Source File: TemplateInfoModal.tsx    From yugong with MIT License 4 votes vote down vote up
TemplateInfoModal: React.FC<Props> = ({ visible, onOk, onCancel }) => {
    const [tags, setTags] = useState<queryTagParams[]>([]);
    const pageData = useSelector((state: RootState) => state.pageData);
    const [defaultValue, setDefaultValue] = useState<AnyObject>();

    const [csrfToken] = useCookie('csrfToken')

    const getTags = useCallback(async () => {
        const tagsResult = await queryTag();
        setTags(tagsResult);
    }, []);

    useEffect(() => {
        const { template = {}, pageTitle } = pageData;
        const { title, cove, tag, describe, terminal, isPublic } = template;
        const defaultParams: TemplateInfo = {
            title: title || pageTitle,
            cove: !!cove ? [{thumbUrl: cove}] : [],
            tag: !!tag ? tag.split(',') : [],
            isPublic: (isPublic === 1),
            describe,
            terminal,
        };
        setDefaultValue(defaultParams);
        
    }, [pageData, pageData.template, visible]);

    useEffect(() => {
        getTags();
    }, [getTags]);

    const handleSubmit = useCallback(
        (data: AnyObject) => {
            if (!isType(data, 'Object')) return;
            data.describe = data.describe || '';
            if (onOk instanceof Function) onOk(data);
        },
        [onOk]
    );

    return (
        <Modal
            key={`${visible}`}
            title="模版信息"
            visible={visible}
            onCancel={onCancel}
            okText={'确定'}
            cancelText={'取消'}
            footer={null}
        >
            <Form
                name="templateInfo"
                labelCol={{ span: 5 }}
                wrapperCol={{ span: 19 }}
                initialValues={defaultValue}
                onFinish={handleSubmit}
            >
                <Form.Item
                    label="模板标题"
                    name="title"
                    rules={[{ required: true, message: '请填写模板标题' }]}
                >
                    <Input />
                </Form.Item>
                <Form.Item
                    label="终端"
                    name="terminal"
                    rules={[{ required: true, message: '请选择终端' }]}
                >
                    <Select placeholder="请选择">
                        <Select.Option value="mobile">移动端</Select.Option>
                        <Select.Option value="pc">PC端</Select.Option>
                    </Select>
                </Form.Item>
                <Form.Item
                    name="cove"
                    label="封面图片"
                    valuePropName="fileList"
                    getValueFromEvent={normFile}
                    extra="模版封面图片"
                    rules={[{ required: true, message: '请上传封面图片' }]}
                >
                    <Upload
                        action="/api/upload"
                        listType="picture"
                        maxCount={1}
                        headers={{
                          'x-csrf-token': csrfToken || ''
                        }}
                    >
                        <Button icon={<UploadOutlined />}>上传图片</Button>
                    </Upload>

                </Form.Item>
                <Form.Item label="描述" name="describe">
                    <Input.TextArea rows={3} />
                </Form.Item>
                <Form.Item
                    label="标签"
                    name="tag"
                    rules={[{ required: true, message: '请选择标签' }]}
                >
                    <Select mode="multiple" allowClear placeholder="标签">
                        {tags.map((item) => (
                            <Select.Option key={item.id} value={`${item.id}`}>
                                {item.name}
                            </Select.Option>
                        ))}
                    </Select>
                </Form.Item>

                <Form.Item
                    name="isPublic"
                    valuePropName="checked"
                    wrapperCol={{ offset: 9, span: 17 }}
                >
                    <Checkbox>发布为公共模板</Checkbox>
                </Form.Item>

                <Form.Item wrapperCol={{ offset: 10, span: 14 }}>
                    <Button type="primary" htmlType="submit">
                        确定
                    </Button>
                </Form.Item>
            </Form>
        </Modal>
    );
}
Example #20
Source File: UploadImg.tsx    From next-basics with GNU General Public License v3.0 4 votes vote down vote up
export function RealUploadImg(
  props: UploadImgProps,
  ref: any
): React.ReactElement {
  const { t } = useTranslation(NS_FORMS);
  const action = `api/gateway/object_store.object_store.PutObject/api/v1/objectStore/bucket/${props.bucketName}/object`;
  const [value, setValue] = React.useState(props.value);
  const [imageList, setImageList] = useState(transformToImageList(props.value));
  const [previewImage, setPreviewImage] = useState("");
  const [previewVisible, setPreviewVisible] = useState(false);
  const [disabled, setDisabled] = useState(false);
  const [allUser, serAllUser] = useState<UserInfo[]>();
  const theme = useCurrentTheme();

  const buttonIcon: MenuIcon = {
    lib: "easyops",
    category: "colored-common",
    icon: theme == "dark-v2" ? "upload-dark" : "upload-light",
  };

  React.useEffect(() => {
    setValue(props.value);
    const isDifferent = compareValues(props.value?.images, imageList);
    if (isDifferent) {
      setImageList(transformToImageList(props.value));
    }
  }, [props.value]);

  React.useEffect(() => {
    const getAllUser = async () => {
      const userMap = await getRuntime().getAllUserMapAsync();
      serAllUser([...userMap.values()]);
    };
    if (props.showMentions) {
      getAllUser();
    }
  }, [props.showMentions]);

  const transformResponseToUrl = (objectName: string) => {
    const url = `api/gateway/object_store.object_store.GetObject/api/v1/objectStore/bucket/${props.bucketName}/object/${objectName}`;
    return props.useFullUrlPath ? `/next/${url}` : `${url}`;
  };

  const handleValueChange = (v: UploadImgValue) => {
    let newValue = { ...value, ...v };
    if (
      (newValue.text === "" || isNil(newValue.text)) &&
      isEmpty(newValue.images)
    ) {
      newValue = null;
    }
    setValue(newValue);
    props.onChange?.(newValue);
  };

  const handleFilesChange = async (
    newFile: ImageItem,
    newFileList: ImageItem[],
    isDone: boolean
  ): Promise<void> => {
    if (isDone) {
      if (props.maxNumber === 1) {
        newFile.preview =
          newFile.preview || (await getBase64(newFile.originFileObj));
        setImageList([
          {
            ...newFile,
          },
        ]);

        handleValueChange({
          images: [
            {
              ...(props.getPreview ? { preview: newFile.preview } : {}),
              url: newFile.url,
              name: newFile.name,
            },
          ],
        });
      } else {
        setImageList(
          update(newFileList, {
            [newFileList.length - 1]: { $set: newFile },
          })
        );

        handleValueChange({
          images: update(value?.images || [], {
            $push: [
              {
                ...(props.getPreview ? { preview: newFile.preview } : {}),
                url: newFile.url,
                name: newFile.name,
              },
            ],
          }),
        });
      }
    } else {
      if (props.maxNumber === 1) {
        setImageList([{ ...newFile }]);
      } else {
        setImageList(newFileList);
      }
    }
  };

  const handlePreview = async (file: any): Promise<void> => {
    if (!file.preview && file.originFileObj) {
      file.preview = await getBase64(file.originFileObj);
    }
    setPreviewImage(file.preview || file.url);
    setPreviewVisible(true);
  };

  const handleChange = ({
    file,
    fileList,
  }: {
    file: UploadFile;
    fileList: UploadFile[];
  }): void => {
    if (some(fileList, ["status", "uploading"])) {
      setDisabled(true);
    } else {
      setDisabled(false);
    }
    if (file.status === "removed") {
      const index = findIndex(imageList, ["uid", file.uid]);
      handleValueChange({
        images: update(value.images, { $splice: [[index, 1]] }),
      });

      setImageList(fileList);
    } else if (file.status === "error") {
      setDisabled(false);
      const index = findIndex(imageList, ["uid", file.uid]);
      if (index !== -1) {
        setImageList(update(imageList, { $splice: [[index, 1]] }));
      }
      message.error("上传文件失败");
    } else {
      if (file?.type.startsWith("image/")) {
        handleFilesChange(file, [...fileList], false);
        if (file.response && file.status === "done") {
          file.url = transformResponseToUrl(file.response.data.objectName);
          handleFilesChange(file, [...fileList], true);
        }
      } else {
        setDisabled(false);
      }
    }
  };

  const handleCancel = (): void => {
    setPreviewVisible(false);
  };

  const uploadButton = (): React.ReactElement => {
    if (props.hideUploadButton && !props.uploadDraggable) {
      return null;
    }
    if (props.uploadDraggable) {
      return (
        <>
          <p className="ant-upload-drag-icon">
            <GeneralIcon icon={buttonIcon} />
          </p>
          <p className="ant-upload-text">
            {props.draggableUploadText ?? t(K.DRAGGABLE_UPLOAD_TEXT)}
          </p>
          <p className="ant-upload-hint">
            {props.draggableUploadHint ?? t(K.DRAGGABLE_UPLOAD_HINT)}
          </p>
        </>
      );
    }
    if (props.listType === "picture-card") {
      return (
        <div>
          {props.maxNumber === 1 && disabled ? (
            <LoadingOutlined />
          ) : theme === "dark-v2" ? (
            <ImageUploadDark />
          ) : (
            <ImageUpload />
          )}

          <div className="ant-upload-text" style={{ marginTop: "-8px" }}>
            上传图片
          </div>
        </div>
      );
    } else {
      return (
        <Button>
          <UploadOutlined /> Upload
        </Button>
      );
    }
  };

  const uploadNode = (): React.ReactElement => {
    return !props.maxNumber || imageList?.length < props.maxNumber
      ? uploadButton()
      : null;
  };

  const filesPasted = (e): void => {
    const items = e.clipboardData.items;
    forEach(items, async (item) => {
      const file = item.getAsFile();
      if (file?.type.startsWith("image/")) {
        if (
          props.maxNumber &&
          imageList?.length >= props.maxNumber &&
          props.maxNumber !== 1
        ) {
          message.error(`仅支持上传 ${props.maxNumber} 张图片`);
          return;
        }
        if (disabled) {
          message.error("还有附件正在上传,请稍候再试。");
          return;
        }
        const fileInfo: any = {
          originFileObj: file,
          type: file.type,
          name: file.name,
          size: file.size,
          lastModified: file.lastModified,
          lastModifiedDate: file.lastModifiedDate,
          uid: uniqueId("-img"),
          status: "uploading",
          percent: 0,
        };

        const oldList = cloneDeep(imageList);
        handleFilesChange(fileInfo, [...oldList, fileInfo], false);
        const reader = new FileReader();
        reader.readAsDataURL(file);
        reader.onload = () => {
          fileInfo.preview = reader.result as string;
          fileInfo.percent = 100;
        };
        // 上传文件
        setDisabled(true);
        try {
          const response = await ObjectStoreApi_putObject(props.bucketName, {
            file: file,
          });

          fileInfo.status = "done";
          fileInfo.url = transformResponseToUrl(response.objectName);
          handleFilesChange(fileInfo, [...oldList, fileInfo], true);
          setDisabled(false);
        } catch (err) {
          message.error("上传失败");
          setImageList(oldList);
          setDisabled(false);
        }
      }
    });
  };

  const handleTextChange = (e: any): void => {
    handleValueChange({
      text: e.target.value,
    });
  };
  const handleMentionsChange = (value: string): void => {
    handleValueChange({
      text: value,
    });
  };

  const handleRemove = (e: any): void => {
    props.onRemove?.(e);
  };

  const handleBeforeUpload = (file: RcFile): Promise<RcFile> => {
    return new Promise((resolve, reject) => {
      if (!file.type?.startsWith("image/")) {
        message.error("仅支持上传图片文件");
        reject(new Error("仅支持上传图片文件"));
      }
      if (FileUtils.sizeCompare(file, props.limitSize ?? 10)) {
        message.error(`上传文件体积大于限定体积`);
        reject(new Error("上传文件体积大于限定体积"));
      }
      resolve(file);
    });
  };

  const fileInfoNode = (file: UploadFile): ReactNode => (
    <>
      <div className={styles["upload-file-main-info"]}>
        <span className={styles["upload-file-name"]}>{file.name}</span>
        <span className={styles["upload-file-size"]}>
          {file.size &&
            (file.status === "uploading"
              ? `${sizeFormat(file.size)} (${Math.floor(file.percent)}%Done)`
              : sizeFormat(file.size))}
        </span>
      </div>
      <div className={styles["upload-file-else-info"]}>
        {(file.status === "error" || file.status === "uploading") && (
          <span className={styles["upload-file-error-info"]}>
            {file.status === "error" && "Wrong!"}
          </span>
        )}
      </div>
    </>
  );

  const cloneFileItemNode = (
    node: ReactElement,
    file: UploadFile
  ): ReactNode => {
    const nodeChildren = React.Children.map(node?.props?.children, (child) => {
      if (
        child?.props?.className
          ?.split(" ")
          ?.includes("ant-upload-list-item-name")
      ) {
        return React.cloneElement(child, null, fileInfoNode(file));
      }
      return cloneFileItemNode(child, file);
    });
    if (React.isValidElement(node)) {
      // children是function额外处理
      if (node?.props?.children instanceof Function)
        return React.cloneElement(node, null, node.props.children);
      return React.cloneElement(node, null, nodeChildren);
    }
    return node;
  };

  const textProps = {
    progress: {
      strokeColor: "#2FC25B",
      trailColor: "var(--theme-gray-background)",
      strokeWidth: "1px",
      showInfo: false,
    },

    showUploadList: {
      // eslint-disable-next-line react/display-name
      removeIcon: (file: UploadFile): ReactNode =>
        file.status === "error" ? (
          <GeneralIcon
            icon={{
              lib: "antd",
              theme: "outlined",
              icon: "close",
            }}
          />
        ) : (
          <GeneralIcon
            icon={{
              lib: "easyops",
              category: "default",
              icon: "delete",
            }}
          />
        ),
    },

    // eslint-disable-next-line react/display-name
    iconRender: (file: UploadFile): ReactNode =>
      file.status === "uploading" ? (
        <LoadingOutlined />
      ) : (
        <GeneralIcon
          icon={{
            lib: "antd",
            icon: "file-text",
            theme: "outlined",
          }}
        />
      ),
  };

  const pictureProps = {
    progress: {
      strokeColor: "var(--color-brand)",
      trailColor: "#FFF",
      strokeWidth: "4px",
      showInfo: false,
    },

    showUploadList: {
      // eslint-disable-next-line react/display-name
      removeIcon: (file: UploadFile): ReactNode =>
        file.status === "error" ? (
          <GeneralIcon
            icon={{
              lib: "antd",
              theme: "outlined",
              icon: "close",
            }}
          />
        ) : (
          <GeneralIcon
            icon={{
              lib: "easyops",
              category: "default",
              icon: "delete",
            }}
          />
        ),
    },

    // eslint-disable-next-line react/display-name
    itemRender: (originNode: ReactElement, file: UploadFile): ReactNode => {
      return cloneFileItemNode(originNode, file);
    },
  };

  let typeProps = {};
  if (props.listType === "picture") {
    typeProps = pictureProps;
  } else if (props.listType === "text") {
    typeProps = textProps;
  }

  const uploadProps = {
    className: classNames({
      [styles.uploadContainerDisplayNone]:
        props.uploadDraggable &&
        props.maxNumber &&
        imageList?.length >= props.maxNumber,
    }),

    method: "put",
    action,
    listType: props.listType,
    fileList: imageList,
    onPreview: handlePreview,
    onChange: handleChange,
    onRemove: handleRemove,
    beforeUpload: handleBeforeUpload,
    supportServerRender: true,
    disabled,
  };

  return (
    <div ref={ref} className={styles.uploadContainer}>
      {props.showTextarea && (
        <Input.TextArea
          onPaste={(e) => filesPasted(e)}
          onChange={handleTextChange}
          className={styles.textContainer}
          value={value?.text || ""}
          placeholder={props.placeholder}
          autoSize={props.autoSize}
        />
      )}
      {props.showMentions && !props.showTextarea && (
        <Mentions
          rows={2}
          onChange={handleMentionsChange}
          value={value?.text || ""}
          autoSize={props.autoSize}
          className={styles.textContainer}
          onPaste={(e) => filesPasted(e)}
          placeholder={props.placeholder}
        >
          {allUser &&
            allUser.map((item) => (
              <Mentions.Option value={item.name} key={item.name}>
                <Avatar
                  src={item.user_icon}
                  size={24}
                  className={classNames(styles.avatar, {
                    [styles.defaultIcon]: !item.user_icon,
                  })}
                >
                  {!item.user_icon && item.name?.slice(0, 2)}
                </Avatar>
                {item.name}
              </Mentions.Option>
            ))}
        </Mentions>
      )}

      {props.uploadDraggable ? (
        <Upload.Dragger {...uploadProps}>{uploadNode()}</Upload.Dragger>
      ) : (
        <Upload {...uploadProps} {...typeProps}>
          {uploadNode()}
        </Upload>
      )}

      <Modal visible={previewVisible} footer={null} onCancel={handleCancel}>
        <img alt="example" style={{ width: "100%" }} src={previewImage} />
      </Modal>
    </div>
  );
}
Example #21
Source File: CreateNewDashboardPage.tsx    From iot-center-v2 with MIT License 4 votes vote down vote up
CreateNewDashboardPage: FunctionComponent<{
  onEdit: () => void
  clientId: string
}> = ({onEdit, clientId}) => {
  const [helpText, setHelpText] = useState('')
  useEffect(() => {
    // load markdown from file
    const fetchMarkdown = async () => {
      try {
        const [txt, dir] = await Promise.all([
          // TODO: update document
          fetch('/help/DynamicDashboardPage.md').then((x) => x.text()),
          fetch('/api/dynamic/dir').then((x) => x.text()),
        ])
        setHelpText(
          (txt ?? '').startsWith('<!')
            ? 'HELP NOT FOUND'
            : txt.replace('{Dynamic Dir}', dir)
        )
      } catch (e) {
        console.error(e)
      }
    }

    fetchMarkdown()
  }, [])

  const [newPageName, setNewPageName] = useState<string>()

  const history = useHistory()

  const onFileUpload = useCallback(
    (file: RcFile) => {
      const reader = new FileReader()
      reader.onload = async (e) => {
        const text = (e?.target?.result as string | undefined) ?? ''
        await upload(file.name, text).then(onEdit)
        const ext = path.extname(file.name).substring(1)
        const name = file.name.split('.').slice(0, -1).join('.')

        if (ext === 'json')
          // TODO: make this different. this way isn't stable
          setTimeout(() => history.push(`/dynamic/${clientId}/${name}`), 1000)
      }
      reader.readAsText(file)

      // cancel default behaviour of file upload
      return false
    },
    [clientId, history, onEdit]
  )

  return (
    <>
      <Modal
        visible={typeof newPageName === 'string'}
        onCancel={() => setNewPageName(undefined)}
        onOk={() => {
          if (newPageName === '') return
          upload(`${newPageName}.json`, `{"cells":[]}`).then(() => {
            setNewPageName(undefined)
            onEdit()
            // TODO: make this different. this way isn't stable
            setTimeout(
              () => history.push(`/dynamic/${clientId}/${newPageName}`),
              1000
            )
          })
        }}
      >
        <Input
          value={newPageName}
          onChange={(e) => setNewPageName(e.target.value)}
        />
      </Modal>
      <Card
        title="How to create new dynamic dashboard"
        extra={
          <>
            <Button onClick={() => setNewPageName('')}>Empty</Button>

            <Upload
              accept=".json,.svg"
              multiple={true}
              beforeUpload={onFileUpload}
            >
              <Button icon={<UploadOutlined />}>Upload</Button>
            </Upload>
          </>
        }
      >
        <Markdown source={helpText} />
      </Card>
    </>
  )
}
Example #22
Source File: index.tsx    From antdp with MIT License 4 votes vote down vote up
QuickForm: QuickFormComponent = (props, ref) => {
  const {
    collapseAttributes,
    panelAttributes,
    visible = false,
    type = 'cardform',
    extra,
    formDatas,
    colspan = 3,
    header,
    defaultFormLayout = 'vertical',
    defaultFormItemLayout = formDefaultFormItemLayout,
    size = 'default',
    formHide,
    initialHide,
    ...otherProps
  } = props;

  const [hide] = useFormItemHide(formHide)
  hide.setInitialValues(initialHide || {}, true)

  const HideFormItemDoM = []; // 隐藏的表单
  const FormItemDoM = [];
  let rowcolspan: string | any; // col 里的布局
  let formitemlayout: string | any; // formitem 的布局

  for (var i = 0; i < formDatas.length; i++) {
    if (formDatas[i].hideInForm) {
      HideFormItemDoM.push(formDatas[i]);
    } else {
      FormItemDoM.push(formDatas[i]);
    }
  }
  // 计算一个row里排几个表单;
  const result = [];
  for (let i = 0, j = FormItemDoM.length; i < j; i++) {
    if (FormItemDoM[i].full) {
      result.push(FormItemDoM.slice(i, i + 1));
    } else {
      if (FormItemDoM[i + 1] && FormItemDoM[i + 1].full) {
        result.push(FormItemDoM.slice(i, i + 1));
      } else if (FormItemDoM[i].defaultcolspan) {
        result.push(FormItemDoM.slice(i, i + FormItemDoM[i].defaultcolspan));
        i = i + FormItemDoM[i].defaultcolspan - 1;
      } else {
        result.push(FormItemDoM.slice(i, i + colspan));
        i = i + colspan - 1;
      }
    }
  }
  // 渲染成表单;
  const CollapseFormDoM = (item: any, idx: React.Key | null | undefined) => {
    const {
      label,
      name,
      attributes,
      type,
      options,
      onlyimg,
      defaultFormItemLayout,
      full,
      defaultRowColspan,
      hideInForm,
      descItem,
      render,
      // 用于判断是否需要进行隐藏显示 (在组件外层包裹一层组件用于控制item显示和隐藏)
      isHide,
      ...otherts
    } = item;
    const dataList = options || [];
    const optionDatas =
      dataList &&
      dataList.length > 0 &&
      dataList.map(
        (
          { value, label, ...others }: any,
          _idx: React.Key | null | undefined,
        ) => {
          if (type === 'select' || type === 'Select') {
            return (
              <Option value={value} key={_idx} {...others}>
                {label}
              </Option>
            );
          } else if (type === 'radio' || type === 'Radio') {
            return (
              <Radio.Button value={value} key={_idx} {...others}>
                {label}
              </Radio.Button>
            );
          }
        },
      );
    const selectOption = optionDatas ? optionDatas : [];
    const rowcolspan_num = [
      colLayout_one,
      colLayout_two,
      colLayout_third,
      colLayout_fourth,
    ];
    const formitemlayout_num = [
      fromItemLayout_conspan_one,
      fromItemLayout_conspan_two,
      fromItemLayout_conspan_third,
      fromItemLayout_conspan_fourth,
    ];
    if (colspan && full) {
      rowcolspan = colLayout_one;
      if (colspan === 3 || colspan === 4) {
        if (props.defaultFormItemLayout) {
          // 如果FormCollapse组件上带有defaulFormItemLayout参数
          formitemlayout = props.defaultFormItemLayout;
          // eslint-disable-next-line max-depth
          if (item.defaultFormItemLayout || item.defaultRowColspan) {
            // 如果FormCollapse组件内部的某个小组件带有defaulFormItemLayout参数
            formitemlayout = item.defaultFormItemLayout;
            rowcolspan = item.defaultRowColspan; // 单独的表单col 布局
          }
        } else if (item.defaultFormItemLayout || item.defaultRowColspan) {
          //FormCollapse组件内部只有某个小组件带了defaulFormItemLayout参数
          formitemlayout = item.defaultFormItemLayout;
          rowcolspan = item.defaultRowColspan; // 单独的表单col 布局
        } else {
          formitemlayout = fromItemLayout_third_row;
        }
      } else {
        formitemlayout = fromItemLayout_two_row;
      }
    } else {
      rowcolspan = rowcolspan_num[colspan - 1];
      if (props.defaultFormItemLayout) {
        formitemlayout = props.defaultFormItemLayout;
        if (item.defaultFormItemLayout || item.defaultRowColspan) {
          // 如果FormCollapse组件内部的某个小组件带有defaultFormItemLayout参数
          formitemlayout = item.defaultFormItemLayout;
          rowcolspan = item.defaultRowColspan; // 单独的表单col 布局
        }
      } else if (item.defaultFormItemLayout || item.defaultRowColspan) {
        formitemlayout =
          item.defaultFormItemLayout || formitemlayout_num[colspan - 1];
        rowcolspan = item.defaultRowColspan; // 单独的表单col 布局
      } else {
        formitemlayout = formitemlayout_num[colspan - 1];
      }
    }

    // 上传图片的按钮展示
    const uploadButtonDom = () => {
      if (item.attributes.listType === 'picture-card') {
        if (item.attributes.imageUrl && item.attributes.imageUrl !== '') {
          return (
            <img
              src={item.attributes.imageUrl}
              alt="avatar"
              style={{ width: '100%' }}
            />
          );
        } else if (item.attributes.fileList) {
          // 上传的图片大于或等于8张时 并且 没有onlyimg参数,显示icon上传按钮
          if (item.attributes.fileList.length >= 8 && !onlyimg) {
            return (
              <div>
                {item.attributes.loading === 'loading' ? (
                  <LoadingOutlined />
                ) : (
                  <PlusOutlined />
                )}
                <div className="ant-upload-text">上传</div>
              </div>
            );
            // 上传的图片大于或等于maxCount张时 并且 有onlyimg参数,不显示上传按钮
          } else if (item.attributes.maxCount && item.attributes.fileList.length >= item.attributes.maxCount && onlyimg) {
            return null;
          }
          return (
            <div>
              {item.attributes.loading === 'loading' ? (
                <LoadingOutlined />
              ) : (
                <PlusOutlined />
              )}
              <div className="ant-upload-text">上传</div>
            </div>
          );
        }
      } else {
        return (
          <div>
            <Button>
              <UploadOutlined />
              上传
            </Button>
          </div>
        );
      }
    };
    let renderItem = (
      <Col
        key={idx}
        style={{
          display: item.hideInForm ? 'none' : 'block',
          padding:
            defaultFormLayout && defaultFormLayout === 'vertical'
              ? '0px 12px 8px 12px'
              : '0',
        }}
        className={
          defaultFormLayout && defaultFormLayout === 'vertical'
            ? 'antdp-FormCol'
            : ''
        }
        {...rowcolspan}
      >
        <FormItem
          className="antdp-FormItem"
          colon={false}
          label={label}
          name={name}
          {...(defaultFormLayout && defaultFormLayout === 'vertical'
            ? null
            : formitemlayout)}
          {...otherts}
        >
          {name ? (
            (() => {
              // 组件基础参数
              const componentprams = {
                size: size ? size : 'small',
                ...attributes,
              };
              if (type === 'select' || type === 'Select') {
                return (
                  <Select
                    dropdownMatchSelectWidth={false}
                    allowClear
                    placeholder={
                      attributes && attributes.disabled ? '' : `请选择${label} `
                    }
                    {...componentprams}
                  >
                    {selectOption}
                  </Select>
                );
              } else if (type === 'radio' || type === 'Radio') {
                return (
                  <Radio.Group size={size ? size : 'small'} {...attributes}>
                    {selectOption}
                  </Radio.Group>
                );
              } else if (type === 'datePicker' || type === 'DatePicker') {
                return (
                  <DatePicker
                    locale={locale}
                    style={{ width: '100%' }}
                    placeholder={
                      attributes && attributes.disabled ? '' : `请选择${label} `
                    }
                    {...componentprams}
                  />
                );
              } else if (type === 'monthPicker' || type === 'MonthPicker') {
                return (
                  <MonthPicker
                    locale={locale}
                    style={{ width: '100%' }}
                    placeholder={
                      attributes && attributes.disabled ? '' : `请选择${label} `
                    }
                    {...componentprams}
                  />
                );
              } else if (type === 'rangePicker' || type === 'RangePicker') {
                return (
                  <RangePicker
                    locale={locale}
                    style={{ width: '100%' }}
                    {...componentprams}
                  />
                );
              } else if (
                type === 'timepicker' ||
                type === 'timePicker' ||
                type === 'TimePicker'
              ) {
                return (
                  <TimePicker
                    locale={locale}
                    style={{ width: '100%' }}
                    placeholder={
                      attributes && attributes.disabled ? '' : `请选择${label} `
                    }
                    {...componentprams}
                  />
                );
              } else if (type === 'cascader' || type === 'Cascader') {
                return (
                  <Cascader
                    placeholder={
                      attributes && attributes.disabled ? '' : `请选择${label} `
                    }
                    {...componentprams}
                  />
                );
              } else if (type === 'textarea' || type === 'TextArea') {
                return (
                  <Input.TextArea
                    placeholder={
                      attributes && attributes.disabled ? '' : `请输入${label} `
                    }
                    {...componentprams}
                  />
                );
              } else if (type === 'inputNumber' || type === 'InputNumber') {
                return (
                  <InputNumber
                    placeholder={
                      attributes && attributes.disabled ? '' : `请输入${label} `
                    }
                    style={{ width: '100%' }}
                    {...componentprams}
                  />
                );
              } else if (type === 'treeSelect' || type === 'TreeSelect') {
                return (
                  <TreeSelect
                    placeholder={
                      attributes && attributes.disabled ? '' : `请选择${label} `
                    }
                    {...componentprams}
                  />
                );
              } else if (type === 'checkbox' || type === 'Checkbox') {
                if (
                  (item.options && item.options.length > 0) ||
                  (item.option && item.option.length > 0)
                ) {
                  return (
                    <Checkbox.Group
                      options={item.options || item.option}
                      {...attributes}
                    />
                  );
                }
                return (
                  <Checkbox {...attributes}>
                    {label || item.checkboxLable}
                  </Checkbox>
                );
              } else if (type === 'UploadGrid' || type === 'uploadGrid') {
                return (
                  <UploadGrid {...attributes}>{uploadButtonDom()}</UploadGrid>
                );
              } else if (type === 'autoComplete' || type === 'AutoComplete') {
                return (
                  <AutoComplete
                    placeholder={
                      attributes && attributes.disabled ? '' : `请输入${label} `
                    }
                    {...componentprams}
                  />
                );
              } else if (type === 'Password') {
                return (
                  <Input.Password
                    placeholder={
                      attributes && attributes.disabled ? '' : `请输入${label} `
                    }
                    {...componentprams}
                  />
                );
              } else if (type === 'inputCount' || type === 'InputCount') {
                return (
                  <InputCount
                    placeholder={
                      attributes && attributes.disabled ? '' : `请输入${label} `
                    }
                    {...attributes}
                  />
                );
              } else if (type === 'render') {
                return render && render
              } else {
                if (
                  (attributes && attributes.type === 'Search') ||
                  type === 'InputSearch'
                ) {
                  const suffix = (
                    <AudioOutlined
                      style={{
                        fontSize: 16,
                        color: '#fff',
                      }}
                    />
                  );
                  return (
                    <Search
                      suffix={suffix}
                      placeholder={
                        attributes && attributes.disabled
                          ? ''
                          : `请输入${label} `
                      }
                      {...componentprams}
                    />
                  );
                }
                return (
                  <Input
                    placeholder={
                      attributes && attributes.disabled ? '' : `请输入${label} `
                    }
                    {...componentprams}
                  />
                );
              }
            })()
          ) : (
            <Input
              placeholder={
                attributes && attributes.disabled ? '' : `请输入${label} `
              }
              size={size}
              {...attributes}
            />
          )}
        </FormItem>
      </Col>
    )

    if (isHide && name) {
      return (
        <Hide key={idx} name={name}>
          {renderItem}
        </Hide>
      );
    }


    return renderItem;
  };
  // 隐藏的表单集合
  const hideCollapseForm = HideFormItemDoM.map((item, idx) =>
    CollapseFormDoM(item, idx),
  );
  // 表单集合
  const CollapseForm = result.map((it, indix) => {
    return (
      <Row key={indix}>
        {it.map((item, idx) => {
          return CollapseFormDoM(item, idx);
        })}
      </Row>
    );
  });
  // Form+表单集合
  const FormDom = (
    <HideContext.Provider value={hide} >
      <ConfigProvider locale={zhCN}>
        <Form
          layout={defaultFormLayout ? defaultFormLayout : 'horizontal'}
          ref={ref}
          {...(defaultFormLayout && defaultFormLayout === 'vertical'
            ? null
            : formitemlayout)}
          {...otherProps}
        >
          <Row>{hideCollapseForm}</Row>
          <div>{CollapseForm}</div>
        </Form>
      </ConfigProvider>
    </HideContext.Provider>
  );
  // type 为 modal时没有折叠,没有标题,直接显示form表单内容
  if (type === 'modal') {
    return <div style={{ margin: -10 }}>{FormDom}</div>
  }
  // type 为CardPro  带标题
  if (type === 'CardPro') {
    return (
      <CardPro title={header}>
        <div className="antdp-FormBox">{FormDom}</div>
      </CardPro>
    );
  }
  // type 为cardform 时 显示表单,分割线 分离每个表单
  if (type === 'cardform') {
    return (
      <div>
        <h3 className="antdp-FormTitle">{header}</h3>
        {FormDom}
        <Divider type="horizontal" className="antdp-FormDivider" />
      </div>
    );
  }
  return (
    <Collapse
      defaultActiveKey={!visible ? ['1'] : ''}
      {...collapseAttributes}
      className="antdp-mb10"
    >
      <Panel header={header} key="1" {...panelAttributes} extra={extra}>
        {FormDom}
      </Panel>
    </Collapse>
  );
}
Example #23
Source File: Icon.tsx    From html2sketch with MIT License 4 votes vote down vote up
IconSymbol: FC = () => {
  return (
    <Row>
      {/*<CaretUpOutlined*/}
      {/*  className="icon"*/}
      {/*  symbolName={'1.General/2.Icons/1.CaretUpOutlined'}*/}
      {/*/>*/}
      {/*  className="icon"*/}
      {/*  symbolName={'1.General/2.Icons/2.MailOutlined'}*/}
      {/*/>*/}
      {/*<StepBackwardOutlined*/}
      {/*  className="icon"*/}
      {/*  symbolName={'1.General/2.Icons/2.StepBackwardOutlined'}*/}
      {/*/>*/}
      {/*<StepForwardOutlined*/}
      {/*  className="icon"*/}
      {/*  symbolName={'1.General/2.Icons/2.StepBackwardOutlined'}*/}
      {/*/>*/}
      <StepForwardOutlined />
      <ShrinkOutlined />
      <ArrowsAltOutlined />
      <DownOutlined />
      <UpOutlined />
      <LeftOutlined />
      <RightOutlined />
      <CaretUpOutlined />
      <CaretDownOutlined />
      <CaretLeftOutlined />
      <CaretRightOutlined />
      <VerticalAlignTopOutlined />
      <RollbackOutlined />
      <FastBackwardOutlined />
      <FastForwardOutlined />
      <DoubleRightOutlined />
      <DoubleLeftOutlined />
      <VerticalLeftOutlined />
      <VerticalRightOutlined />
      <VerticalAlignMiddleOutlined />
      <VerticalAlignBottomOutlined />
      <ForwardOutlined />
      <BackwardOutlined />
      <EnterOutlined />
      <RetweetOutlined />
      <SwapOutlined />
      <SwapLeftOutlined />
      <SwapRightOutlined />
      <ArrowUpOutlined />
      <ArrowDownOutlined />
      <ArrowLeftOutlined />
      <ArrowRightOutlined />
      <LoginOutlined />
      <LogoutOutlined />
      <MenuFoldOutlined />
      <MenuUnfoldOutlined />
      <BorderBottomOutlined />
      <BorderHorizontalOutlined />
      <BorderInnerOutlined />
      <BorderOuterOutlined />
      <BorderLeftOutlined />
      <BorderRightOutlined />
      <BorderTopOutlined />
      <BorderVerticleOutlined />
      <PicCenterOutlined />
      <PicLeftOutlined />
      <PicRightOutlined />
      <RadiusBottomleftOutlined />
      <RadiusBottomrightOutlined />
      <RadiusUpleftOutlined />
      <RadiusUprightOutlined />
      <FullscreenOutlined />
      <FullscreenExitOutlined />
      <QuestionOutlined />
      <PauseOutlined />
      <MinusOutlined />
      <PauseCircleOutlined />
      <InfoOutlined />
      <CloseOutlined />
      <ExclamationOutlined />
      <CheckOutlined />
      <WarningOutlined />
      <IssuesCloseOutlined />
      <StopOutlined />
      <EditOutlined />
      <CopyOutlined />
      <ScissorOutlined />
      <DeleteOutlined />
      <SnippetsOutlined />
      <DiffOutlined />
      <HighlightOutlined />
      <AlignCenterOutlined />
      <AlignLeftOutlined />
      <AlignRightOutlined />
      <BgColorsOutlined />
      <BoldOutlined />
      <ItalicOutlined />
      <UnderlineOutlined />
      <StrikethroughOutlined />
      <RedoOutlined />
      <UndoOutlined />
      <ZoomInOutlined />
      <ZoomOutOutlined />
      <FontColorsOutlined />
      <FontSizeOutlined />
      <LineHeightOutlined />
      <SortAscendingOutlined />
      <SortDescendingOutlined />
      <DragOutlined />
      <OrderedListOutlined />
      <UnorderedListOutlined />
      <RadiusSettingOutlined />
      <ColumnWidthOutlined />
      <ColumnHeightOutlined />
      <AreaChartOutlined />
      <PieChartOutlined />
      <BarChartOutlined />
      <DotChartOutlined />
      <LineChartOutlined />
      <RadarChartOutlined />
      <HeatMapOutlined />
      <FallOutlined />
      <RiseOutlined />
      <StockOutlined />
      <BoxPlotOutlined />
      <FundOutlined />
      <SlidersOutlined />
      <AndroidOutlined />
      <AppleOutlined />
      <WindowsOutlined />
      <IeOutlined />
      <ChromeOutlined />
      <GithubOutlined />
      <AliwangwangOutlined />
      <DingdingOutlined />
      <WeiboSquareOutlined />
      <WeiboCircleOutlined />
      <TaobaoCircleOutlined />
      <Html5Outlined />
      <WeiboOutlined />
      <TwitterOutlined />
      <WechatOutlined />
      <AlipayCircleOutlined />
      <TaobaoOutlined />
      <SkypeOutlined />
      <FacebookOutlined />
      <CodepenOutlined />
      <CodeSandboxOutlined />
      <AmazonOutlined />
      <GoogleOutlined />
      <AlipayOutlined />
      <AntDesignOutlined />
      <AntCloudOutlined />
      <ZhihuOutlined />
      <SlackOutlined />
      <SlackSquareOutlined />
      <BehanceSquareOutlined />
      <DribbbleOutlined />
      <DribbbleSquareOutlined />
      <InstagramOutlined />
      <YuqueOutlined />
      <AlibabaOutlined />
      <YahooOutlined />
      <RedditOutlined />
      <SketchOutlined />
      <AccountBookOutlined />
      <AlertOutlined />
      <ApartmentOutlined />
      <ApiOutlined />
      <QqOutlined />
      <MediumWorkmarkOutlined />
      <GitlabOutlined />
      <MediumOutlined />
      <GooglePlusOutlined />
      <AppstoreAddOutlined />
      <AppstoreOutlined />
      <AudioOutlined />
      <AudioMutedOutlined />
      <AuditOutlined />
      <BankOutlined />
      <BarcodeOutlined />
      <BarsOutlined />
      <BellOutlined />
      <BlockOutlined />
      <BookOutlined />
      <BorderOutlined />
      <BranchesOutlined />
      <BuildOutlined />
      <BulbOutlined />
      <CalculatorOutlined />
      <CalendarOutlined />
      <CameraOutlined />
      <CarOutlined />
      <CarryOutOutlined />
      <CiCircleOutlined />
      <CiOutlined />
      <CloudOutlined />
      <ClearOutlined />
      <ClusterOutlined />
      <CodeOutlined />
      <CoffeeOutlined />
      <CompassOutlined />
      <CompressOutlined />
      <ContactsOutlined />
      <ContainerOutlined />
      <ControlOutlined />
      <CopyrightCircleOutlined />
      <CopyrightOutlined />
      <CreditCardOutlined />
      <CrownOutlined />
      <CustomerServiceOutlined />
      <DashboardOutlined />
      <DatabaseOutlined />
      <DeleteColumnOutlined />
      <DeleteRowOutlined />
      <DisconnectOutlined />
      <DislikeOutlined />
      <DollarCircleOutlined />
      <DollarOutlined />
      <DownloadOutlined />
      <EllipsisOutlined />
      <EnvironmentOutlined />
      <EuroCircleOutlined />
      <EuroOutlined />
      <ExceptionOutlined />
      <ExpandAltOutlined />
      <ExpandOutlined />
      <ExperimentOutlined />
      <ExportOutlined />
      <EyeOutlined />
      <FieldBinaryOutlined />
      <FieldNumberOutlined />
      <FieldStringOutlined />
      <DesktopOutlined />
      <DingtalkOutlined />
      <FileAddOutlined />
      <FileDoneOutlined />
      <FileExcelOutlined />
      <FileExclamationOutlined />
      <FileOutlined />
      <FileImageOutlined />
      <FileJpgOutlined />
      <FileMarkdownOutlined />
      <FilePdfOutlined />
      <FilePptOutlined />
      <FileProtectOutlined />
      <FileSearchOutlined />
      <FileSyncOutlined />
      <FileTextOutlined />
      <FileUnknownOutlined />
      <FileWordOutlined />
      <FilterOutlined />
      <FireOutlined />
      <FlagOutlined />
      <FolderAddOutlined />
      <FolderOutlined />
      <FolderOpenOutlined />
      <ForkOutlined />
      <FormatPainterOutlined />
      <FrownOutlined />
      <FunctionOutlined />
      <FunnelPlotOutlined />
      <GatewayOutlined />
      <GifOutlined />
      <GiftOutlined />
      <GlobalOutlined />
      <GoldOutlined />
      <GroupOutlined />
      <HddOutlined />
      <HeartOutlined />
      <HistoryOutlined />
      <HomeOutlined />
      <HourglassOutlined />
      <IdcardOutlined />
      <ImportOutlined />
      <InboxOutlined />
      <InsertRowAboveOutlined />
      <InsertRowBelowOutlined />
      <InsertRowLeftOutlined />
      <InsertRowRightOutlined />
      <InsuranceOutlined />
      <InteractionOutlined />
      <KeyOutlined />
      <LaptopOutlined />
      <LayoutOutlined />
      <LikeOutlined />
      <LineOutlined />
      <LinkOutlined />
      <Loading3QuartersOutlined />
      <LoadingOutlined />
      <LockOutlined />
      <MailOutlined />
      <ManOutlined />
      <MedicineBoxOutlined />
      <MehOutlined />
      <MenuOutlined />
      <MergeCellsOutlined />
      <MessageOutlined />
      <MobileOutlined />
      <MoneyCollectOutlined />
      <MonitorOutlined />
      <MoreOutlined />
      <NodeCollapseOutlined />
      <NodeExpandOutlined />
      <NodeIndexOutlined />
      <NotificationOutlined />
      <NumberOutlined />
      <PaperClipOutlined />
      <PartitionOutlined />
      <PayCircleOutlined />
      <PercentageOutlined />
      <PhoneOutlined />
      <PictureOutlined />
      <PoundCircleOutlined />
      <PoundOutlined />
      <PoweroffOutlined />
      <PrinterOutlined />
      <ProfileOutlined />
      <ProjectOutlined />
      <PropertySafetyOutlined />
      <PullRequestOutlined />
      <PushpinOutlined />
      <QrcodeOutlined />
      <ReadOutlined />
      <ReconciliationOutlined />
      <RedEnvelopeOutlined />
      <ReloadOutlined />
      <RestOutlined />
      <RobotOutlined />
      <RocketOutlined />
      <SafetyCertificateOutlined />
      <SafetyOutlined />
      <ScanOutlined />
      <ScheduleOutlined />
      <SearchOutlined />
      <SecurityScanOutlined />
      <SelectOutlined />
      <SendOutlined />
      <SettingOutlined />
      <ShakeOutlined />
      <ShareAltOutlined />
      <ShopOutlined />
      <ShoppingCartOutlined />
      <ShoppingOutlined />
      <SisternodeOutlined />
      <SkinOutlined />
      <SmileOutlined />
      <SolutionOutlined />
      <SoundOutlined />
      <SplitCellsOutlined />
      <StarOutlined />
      <SubnodeOutlined />
      <SyncOutlined />
      <TableOutlined />
      <TabletOutlined />
      <TagOutlined />
      <TagsOutlined />
      <TeamOutlined />
      <ThunderboltOutlined />
      <ToTopOutlined />
      <ToolOutlined />
      <TrademarkCircleOutlined />
      <TrademarkOutlined />
      <TransactionOutlined />
      <TrophyOutlined />
      <UngroupOutlined />
      <UnlockOutlined />
      <UploadOutlined />
      <UsbOutlined />
      <UserAddOutlined />
      <UserDeleteOutlined />
      <UserOutlined />
      <UserSwitchOutlined />
      <UsergroupAddOutlined />
      <UsergroupDeleteOutlined />
      <VideoCameraOutlined />
      <WalletOutlined />
      <WifiOutlined />
      <BorderlessTableOutlined />
      <WomanOutlined />
      <BehanceOutlined />
      <DropboxOutlined />
      <DeploymentUnitOutlined />
      <UpCircleOutlined />
      <DownCircleOutlined />
      <LeftCircleOutlined />
      <RightCircleOutlined />
      <UpSquareOutlined />
      <DownSquareOutlined />
      <LeftSquareOutlined />
      <RightSquareOutlined />
      <PlayCircleOutlined />
      <QuestionCircleOutlined />
      <PlusCircleOutlined />
      <PlusSquareOutlined />
      <MinusSquareOutlined />
      <MinusCircleOutlined />
      <InfoCircleOutlined />
      <ExclamationCircleOutlined />
      <CloseCircleOutlined />
      <CloseSquareOutlined />
      <CheckCircleOutlined />
      <CheckSquareOutlined />
      <ClockCircleOutlined />
      <FormOutlined />
      <DashOutlined />
      <SmallDashOutlined />
      <YoutubeOutlined />
      <CodepenCircleOutlined />
      <AliyunOutlined />
      <PlusOutlined />
      <LinkedinOutlined />
      <AimOutlined />
      <BugOutlined />
      <CloudDownloadOutlined />
      <CloudServerOutlined />
      <CloudSyncOutlined />
      <CloudUploadOutlined />
      <CommentOutlined />
      <ConsoleSqlOutlined />
      <EyeInvisibleOutlined />
      <FileGifOutlined />
      <DeliveredProcedureOutlined />
      <FieldTimeOutlined />
      <FileZipOutlined />
      <FolderViewOutlined />
      <FundProjectionScreenOutlined />
      <FundViewOutlined />
      <MacCommandOutlined />
      <PlaySquareOutlined />
      <OneToOneOutlined />
      <RotateLeftOutlined />
      <RotateRightOutlined />
      <SaveOutlined />
      <SwitcherOutlined />
      <TranslationOutlined />
      <VerifiedOutlined />
      <VideoCameraAddOutlined />
      <WhatsAppOutlined />

      {/*</Col>*/}
    </Row>
  );
}
Example #24
Source File: palette.tsx    From jmix-frontend with Apache License 2.0 4 votes vote down vote up
palette = () =>
  <Palette>
    <Category name="Text">
      <Component name="Formatted Message">
        <Variant>
          <FormattedMessage />
        </Variant>
      </Component>
      <Component name="Heading">
        <Variant name='h1'>
          <Typography.Title></Typography.Title>
        </Variant>
        <Variant name='h2'>
          <Typography.Title level = {2}></Typography.Title>
        </Variant>
        <Variant name='h3'>
          <Typography.Title level = {3}></Typography.Title>
        </Variant>
        <Variant name='h4'>
          <Typography.Title level = {4}></Typography.Title>
        </Variant>
        <Variant name='h5'>
          <Typography.Title level = {5}></Typography.Title>
        </Variant>
      </Component>
      <Component name='Text'>
        <Variant>
          <Typography.Text></Typography.Text>
        </Variant>
        <Variant name = 'Secondary'>
          <Typography.Text type="secondary"></Typography.Text>
        </Variant>
        <Variant name = 'Success'>
          <Typography.Text type="success"></Typography.Text>
        </Variant>
        <Variant name = 'Warning'>
          <Typography.Text type="warning"></Typography.Text>
        </Variant>
        <Variant name = 'Danger'>
          <Typography.Text type="danger"></Typography.Text>
        </Variant>
        <Variant name = 'Disabled'>
          <Typography.Text disabled></Typography.Text>
        </Variant>
      </Component>
    </Category>
    <Category name="Layout">
      <Component name="Divider">
        <Variant>
          <Divider />
        </Variant>
      </Component>

      <Component name="Grid">
        <Variant name="Simple Row">
          <Row></Row>
        </Variant>
        <Variant name="Two columns">
          <Row>
            <Col span={12}></Col>
            <Col span={12}></Col>
          </Row>
        </Variant>
        <Variant name="Three columns">
          <Row>
            <Col span={8}></Col>
            <Col span={8}></Col>
            <Col span={8}></Col>
          </Row>
        </Variant>
      </Component>

      <Component name="Space">
        <Variant>
          <Space />
        </Variant>
        <Variant name="Small">
          <Space size={"small"} />
        </Variant>
        <Variant name="Large">
          <Space size={"large"} />
        </Variant>
      </Component>
    </Category>
    <Category name="Controls">
      <Component name="Autocomplete">
        <Variant>
          <AutoComplete placeholder="input here" />
        </Variant>
      </Component>

      <Component name="Button">
        <Variant>
          <Button></Button>
        </Variant>
        <Variant name="Primary">
          <Button type="primary" ></Button>
        </Variant>
        <Variant name="Link">
          <Button type="link" ></Button>
        </Variant>
        <Variant name="Dropdown">
          <Dropdown
            trigger={['click']}
            overlay={<Menu>
              <Menu.Item>
              </Menu.Item>
              <Menu.Item>
              </Menu.Item>
              <Menu.Item>
              </Menu.Item>
            </Menu>}
          >
            <Button></Button>
          </Dropdown>
        </Variant>
      </Component>

      <Component name="Checkbox">
        <Variant>
          <Checkbox />
        </Variant>
      </Component>

      <Component name='Switch'>
        <Variant>
          <Switch />
        </Variant>
      </Component>

      <Component name='Radio Group'>
        <Variant>
          <Radio.Group>
            <Radio value={1}>A</Radio>
            <Radio value={2}>B</Radio>
            <Radio value={3}>C</Radio>
            <Radio value={4}>D</Radio>
          </Radio.Group>
        </Variant>
        <Variant name = 'Button'>
          <Radio.Group>
            <Radio.Button value={1}>A</Radio.Button>
            <Radio.Button value={2}>B</Radio.Button>
            <Radio.Button value={3}>C</Radio.Button>
            <Radio.Button value={4}>D</Radio.Button>
          </Radio.Group>
        </Variant>
      </Component>

      <Component name="DatePicker">
        <Variant>
          <DatePicker />
        </Variant>
        <Variant name="Range">
          <DatePicker.RangePicker />
        </Variant>
      </Component>

      <Component name="TimePicker">
        <Variant>
          <TimePicker />
        </Variant>
        <Variant name="Range">
          <TimePicker.RangePicker />
        </Variant>
      </Component>

      <Component name="Input">
        <Variant>
          <Input />
        </Variant>
        <Variant name='Number'>
          <InputNumber />
        </Variant>
      </Component>

      <Component name='Select'>
        <Variant>
          <Select defaultValue="1">
            <Select.Option value="1">1</Select.Option>
            <Select.Option value="2">2</Select.Option>
          </Select>
        </Variant>
        <Variant name='Multiple'>
          <Select
            defaultValue={["1"]}
            mode="multiple"
            allowClear
          >
            <Select.Option value="1">1</Select.Option>
            <Select.Option value="2">2</Select.Option>
          </Select>
        </Variant>
      </Component>

      <Component name="Link">
        <Variant>
          <Typography.Link href="" target="_blank">
          </Typography.Link>
        </Variant>
      </Component>

      <Component name='Slider'>
        <Variant>
          <Slider defaultValue={30} />
        </Variant>
        <Variant name = 'Range'>
          <Slider range defaultValue={[20, 50]}/>
        </Variant>
      </Component>
    </Category>
    <Category name="Data Display">
    <Component name="Field">
        <Variant>
          <Field
            entityName={ENTITY_NAME}
            disabled={readOnlyMode}
            propertyName=''
            formItemProps={{
              style: { marginBottom: "12px" }
            }}
          />
        </Variant>
      </Component>
      <Component name="Card">
        <Variant>
          <Card />
        </Variant>
        <Variant name="With Title">
          <Card>
            <Card title="Card title">
              <p>Card content</p>
            </Card>
          </Card>
        </Variant>
        <Variant name="My custom card">
          <Card>
            <Card title="Card title">
              <p>Card content</p>
              <Avatar />
            </Card>
          </Card>
        </Variant>
      </Component>
      <Component name="Tabs">
        <Variant>
          <Tabs defaultActiveKey="1">
            <Tabs.TabPane tab="Tab 1" key="1">
              Content of Tab Pane 1
            </Tabs.TabPane>
            <Tabs.TabPane tab="Tab 2" key="2">
              Content of Tab Pane 2
            </Tabs.TabPane>
            <Tabs.TabPane tab="Tab 3" key="3">
              Content of Tab Pane 3
            </Tabs.TabPane>
          </Tabs>
        </Variant>
        <Variant name = "Tab Pane">
          <Tabs.TabPane>
          </Tabs.TabPane>
        </Variant>
      </Component>
      <Component name="Collapse">
        <Variant>
          <Collapse defaultActiveKey='1'>
            <Collapse.Panel header="This is panel header 1" key="1">
            </Collapse.Panel>
            <Collapse.Panel header="This is panel header 2" key="2">
            </Collapse.Panel>
            <Collapse.Panel header="This is panel header 3" key="3">
            </Collapse.Panel>
          </Collapse>
        </Variant>
      </Component>
      <Component name="Image">
        <Variant>
          <Image
            width={200}
            src=""
          />
        </Variant>
      </Component>
      <Component name="Avatar">
        <Variant>
          <Avatar icon={<UserOutlined />} />
        </Variant>
        <Variant name="Image">
          <Avatar src="https://joeschmoe.io/api/v1/random" />
        </Variant>
      </Component>
      <Component name="Badge">
        <Variant>
          <Badge count={1}>
          </Badge>
        </Variant>
      </Component>
      <Component name="Statistic">
        <Variant>
          <Statistic title="Title" value={112893} />
        </Variant>
      </Component>
      <Component name="Alert">
        <Variant name="Success">
          <Alert message="Text" type="success" />
        </Variant>
        <Variant name="Info">
          <Alert message="Text" type="info" />
        </Variant>
        <Variant name="Warning">
          <Alert message="Text" type="warning" />
        </Variant>
        <Variant name="Error">
          <Alert message="Text" type="error" />
        </Variant>
      </Component>
      <Component name='List'>
        <Variant>
          <List
            bordered
            dataSource={[]}
            renderItem={item => (
              <List.Item>
              </List.Item>
            )}
          />
        </Variant>
      </Component>
    </Category>
    <Category name="Icons">
      <Component name="Arrow">
        <Variant name = 'Up'>
          <ArrowUpOutlined />
        </Variant>
        <Variant name = 'Down'>
          <ArrowDownOutlined />
        </Variant>
        <Variant name = 'Left'>
          <ArrowLeftOutlined />
        </Variant>
        <Variant name = 'Right'>
          <ArrowRightOutlined />
        </Variant>
      </Component>
      <Component name = 'Question'>
        <Variant>
          <QuestionOutlined />
        </Variant>
        <Variant name = 'Circle'>
          <QuestionCircleOutlined />
        </Variant>
      </Component>
      <Component name = 'Plus'>
        <Variant>
          <PlusOutlined />
        </Variant>
        <Variant name = 'Circle'>
          <PlusCircleOutlined />
        </Variant>
      </Component>
      <Component name = 'Info'>
        <Variant>
          <InfoOutlined />
        </Variant>
        <Variant name = 'Circle'>
          <InfoCircleOutlined />
        </Variant>
      </Component>
      <Component name = 'Exclamation'>
        <Variant>
          <ExclamationOutlined />
        </Variant>
        <Variant name = 'Circle'>
          <ExclamationCircleOutlined />
        </Variant>
      </Component>
      <Component name = 'Close'>
        <Variant>
          <CloseOutlined />
        </Variant>
        <Variant name = 'Circle'>
          <CloseCircleOutlined />
        </Variant>
      </Component>
      <Component name = 'Check'>
        <Variant>
          <CheckOutlined />
        </Variant>
        <Variant name = 'Circle'>
          <CheckCircleOutlined />
        </Variant>
      </Component>
      <Component name = 'Edit'>
        <Variant>
          <EditOutlined />
        </Variant>
      </Component>
      <Component name = 'Copy'>
        <Variant>
          <CopyOutlined />
        </Variant>
      </Component>
      <Component name = 'Delete'>
        <Variant>
          <DeleteOutlined />
        </Variant>
      </Component>
      <Component name = 'Bars'>
        <Variant>
          <BarsOutlined />
        </Variant>
      </Component>
      <Component name = 'Bell'>
        <Variant>
          <BellOutlined />
        </Variant>
      </Component>
      <Component name = 'Clear'>
        <Variant>
          <ClearOutlined />
        </Variant>
      </Component>
      <Component name = 'Download'>
        <Variant>
          <DownloadOutlined />
        </Variant>
      </Component>
      <Component name = 'Upload'>
        <Variant>
          <UploadOutlined />
        </Variant>
      </Component>
      <Component name = 'Sync'>
        <Variant>
          <SyncOutlined />
        </Variant>
      </Component>
      <Component name = 'Save'>
        <Variant>
          <SaveOutlined />
        </Variant>
      </Component>
      <Component name = 'Search'>
        <Variant>
          <SearchOutlined />
        </Variant>
      </Component>
      <Component name = 'Settings'>
        <Variant>
          <SettingOutlined />
        </Variant>
      </Component>
      <Component name = 'Paperclip'>
        <Variant>
          <PaperClipOutlined />
        </Variant>
      </Component>
      <Component name = 'Phone'>
        <Variant>
          <PhoneOutlined />
        </Variant>
      </Component>
      <Component name = 'Mail'>
        <Variant>
          <MailOutlined />
        </Variant>
      </Component>
      <Component name = 'Home'>
        <Variant>
          <HomeOutlined />
        </Variant>
      </Component>
      <Component name = 'Contacts'>
        <Variant>
          <ContactsOutlined />
        </Variant>
      </Component>
      <Component name = 'User'>
        <Variant>
          <UserOutlined />
        </Variant>
        <Variant name = 'Add'>
          <UserAddOutlined />
        </Variant>
        <Variant name = 'Remove'>
          <UserDeleteOutlined />
        </Variant>
      </Component>
      <Component name = 'Team'>
        <Variant>
          <TeamOutlined />
        </Variant>
      </Component>
    </Category>
  </Palette>