github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/dm/ui/src/components/CreateOrUpdateTask/SourceInfo.tsx (about)

     1  import React, { useState } from 'react'
     2  import { useTranslation } from 'react-i18next'
     3  
     4  import {
     5    Button,
     6    Collapse,
     7    Form,
     8    Input,
     9    InputNumber,
    10    Select,
    11    Card,
    12  } from '~/uikit'
    13  import { FileAddOutlined, CloseOutlined, RetweetOutlined } from '~/uikit/icons'
    14  import { useDmapiGetSourceListQuery } from '~/models/source'
    15  import { StepCompnent } from '~/components/CreateOrUpdateTask/shared'
    16  import { TaskMigrateConsistencyLevel, TaskMode } from '~/models/task'
    17  
    18  const formLayout = {
    19    labelCol: { span: 6 },
    20    wrapperCol: { span: 18 },
    21  }
    22  
    23  const itemLayout = {
    24    labelCol: { span: 4 },
    25    wrapperCol: { span: 20 },
    26  }
    27  
    28  const SourceInfo: StepCompnent = ({ prev, initialValues }) => {
    29    const [t] = useTranslation()
    30    const { data, isFetching } = useDmapiGetSourceListQuery({
    31      with_status: false,
    32    })
    33    const disableGtidOrBinlog = initialValues?.task_mode !== TaskMode.INCREMENTAL
    34    const [gtidOrBinlogStatus, setGtidOrBinlogStatus] = useState<
    35      Map<number, boolean>
    36    >(new Map())
    37  
    38    const toggle = (id: number) => {
    39      setGtidOrBinlogStatus(prev => {
    40        const newMap = new Map(prev)
    41        newMap.set(id, !prev.get(id))
    42        return newMap
    43      })
    44    }
    45  
    46    return (
    47      <Form {...formLayout} name="sourceInfo" initialValues={initialValues}>
    48        <Collapse>
    49          <Collapse.Panel header={t('sync config')} key="1">
    50            <div className="flex">
    51              <div className="flex-1">
    52                <h3 className="max-w-[33%] text-right font-bold mb-8">
    53                  {t('full migrate config')}
    54                </h3>
    55                <Form.Item
    56                  label={t('export concurrency')}
    57                  tooltip={t('create task export_threads tooltip')}
    58                  name={['source_config', 'full_migrate_conf', 'export_threads']}
    59                >
    60                  <InputNumber className="!w-[100%]" placeholder="4" />
    61                </Form.Item>
    62                <Form.Item
    63                  label={t('import concurrency')}
    64                  tooltip={t('create task import_threads tooltip')}
    65                  name={['source_config', 'full_migrate_conf', 'import_threads']}
    66                >
    67                  <InputNumber className="!w-[100%]" placeholder="4" />
    68                </Form.Item>
    69  
    70                <Form.Item
    71                  label={t('consistency requirement')}
    72                  name={['source_config', 'full_migrate_conf', 'consistency']}
    73                >
    74                  <Select placeholder={TaskMigrateConsistencyLevel.Auto}>
    75                    {Object.values(TaskMigrateConsistencyLevel).map(
    76                      consistency => (
    77                        <Select.Option key={consistency} value={consistency}>
    78                          {consistency}
    79                        </Select.Option>
    80                      )
    81                    )}
    82                  </Select>
    83                </Form.Item>
    84              </div>
    85              <div className="flex-1">
    86                <h3 className="max-w-[33%] text-right font-bold mb-8">
    87                  {t('incremental migrate config')}
    88                </h3>
    89                <Form.Item
    90                  label={t('synchronous concurrency')}
    91                  tooltip={t('create task repl_threads tooltip')}
    92                  name={['source_config', 'incr_migrate_conf', 'repl_threads']}
    93                >
    94                  <InputNumber className="!w-[100%]" placeholder="32" />
    95                </Form.Item>
    96                <Form.Item
    97                  label={t('transaction batch')}
    98                  tooltip={t('create task repl_batch tooltip')}
    99                  name={['source_config', 'incr_migrate_conf', 'repl_batch']}
   100                >
   101                  <InputNumber className="!w-[100%]" placeholder="100" />
   102                </Form.Item>
   103              </div>
   104            </div>
   105          </Collapse.Panel>
   106        </Collapse>
   107  
   108        <div className="grid grid-cols-2 gap-4 auto-rows-fr my-4">
   109          <Form.List name={['source_config', 'source_conf']}>
   110            {(fields, { add, remove }) => (
   111              <>
   112                {fields.map(field => (
   113                  <Card
   114                    hoverable
   115                    key={field.key}
   116                    className="!h-200px relative !border-[#d9d9d9] group"
   117                  >
   118                    <CloseOutlined
   119                      onClick={() => remove(field.name)}
   120                      className="!text-gray-500 absolute top-2 right-2 group-hover:opacity-100 opacity-0 transition"
   121                    />
   122                    <Form.Item
   123                      {...itemLayout}
   124                      label={t('source name')}
   125                      name={[field.name, 'source_name']}
   126                      rules={[
   127                        { required: true, message: t('source name is required') },
   128                      ]}
   129                    >
   130                      <Select placeholder="mysql-01" loading={isFetching}>
   131                        {data?.data.map(source => (
   132                          <Select.Option
   133                            key={source.source_name}
   134                            value={source.source_name}
   135                          >
   136                            {source.source_name}
   137                          </Select.Option>
   138                        ))}
   139                      </Select>
   140                    </Form.Item>
   141  
   142                    <div className="relative">
   143                      <Form.Item
   144                        className="flex-1"
   145                        {...itemLayout}
   146                        hidden={gtidOrBinlogStatus.get(field.name)}
   147                        label={t('binlog')}
   148                        tooltip={t('create task binlog_name tooltip')}
   149                      >
   150                        <Input.Group compact>
   151                          <Form.Item noStyle name={[field.name, 'binlog_name']}>
   152                            <Input
   153                              className="!mr-4"
   154                              disabled={disableGtidOrBinlog}
   155                              style={{ maxWidth: '45%' }}
   156                              placeholder="name"
   157                            />
   158                          </Form.Item>
   159  
   160                          <Form.Item noStyle name={[field.name, 'binlog_pos']}>
   161                            <InputNumber
   162                              style={{ width: '40%' }}
   163                              disabled={disableGtidOrBinlog}
   164                              placeholder="position"
   165                            />
   166                          </Form.Item>
   167                        </Input.Group>
   168                      </Form.Item>
   169  
   170                      <Form.Item
   171                        className="flex-1"
   172                        {...itemLayout}
   173                        hidden={!gtidOrBinlogStatus.get(field.name)}
   174                        label={t('gtid')}
   175                        name={[field.name, 'binlog_gtid']}
   176                      >
   177                        <Input
   178                          className="max-w-[90%]"
   179                          disabled={disableGtidOrBinlog}
   180                        />
   181                      </Form.Item>
   182  
   183                      <Button
   184                        className="!absolute ml-2 top-0 right-0"
   185                        onClick={() => toggle(field.name)}
   186                      >
   187                        <RetweetOutlined />
   188                      </Button>
   189                    </div>
   190                  </Card>
   191                ))}
   192  
   193                <Button
   194                  className="!h-200px"
   195                  type="dashed"
   196                  icon={<FileAddOutlined />}
   197                  onClick={() => add()}
   198                >
   199                  {t('add source config')}
   200                </Button>
   201              </>
   202            )}
   203          </Form.List>
   204        </div>
   205  
   206        <Form.Item>
   207          <Button className="mr-4" onClick={prev}>
   208            {t('previous')}
   209          </Button>
   210          <Button type="primary" htmlType="submit">
   211            {t('next')}
   212          </Button>
   213        </Form.Item>
   214      </Form>
   215    )
   216  }
   217  
   218  export default SourceInfo