antd#TimePicker TypeScript Examples

The following examples show how to use antd#TimePicker. 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: utils.tsx    From antdp with MIT License 6 votes vote down vote up
getItem = ({ attr, type, inputNode }: {
  attr?: Partial<ItemChildAttr<any, any>>;
  type?: ItemChildType;
  inputNode?: ((...arg: any[]) => React.ReactNode) | React.ReactNode;
}) => {
  let renderItem = undefined;
  if (type === 'Input') {
    const inputAttr = attr as InputProps;
    renderItem = <Input {...inputAttr} />;
  } else if (type === 'TextArea') {
    const inputAttr = attr as TextAreaProps;
    renderItem = <Input.TextArea {...inputAttr} />;
  } else if (type === 'InputNumber') {
    const inputAttr = attr as InputNumberProps;
    renderItem = <InputNumber {...inputAttr} />;
  } else if (type === 'AutoComplete') {
    const inputAttr = attr as AutoCompleteProps;
    renderItem = <AutoComplete {...inputAttr} />;
  } else if (type === 'Cascader') {
    const inputAttr = attr as CascaderProps;
    renderItem = <Cascader {...inputAttr} />;
  } else if (type === 'DatePicker') {
    const inputAttr = attr as DatePickerProps;
    renderItem = <DatePicker {...inputAttr} />;
  } else if (type === 'Rate') {
    const inputAttr = attr as RateProps;
    renderItem = <Rate {...inputAttr} />;
  } else if (type === 'Slider') {
    const inputAttr = attr as SliderSingleProps;
    renderItem = <Slider {...inputAttr} />;
  } else if (type === 'TreeSelect') {
    const inputAttr = attr as TreeSelectProps<any>;
    renderItem = <TreeSelect {...inputAttr} />;
  } else if (type === 'Select') {
    const inputAttr = attr as SelectProps<any>;
    renderItem = <Select {...inputAttr} />;
  } else if (type === 'Checkbox') {
    const inputAttr = attr as CheckboxGroupProps;
    renderItem = <Checkbox.Group {...inputAttr} />;
  } else if (type === 'Mentions') {
    const inputAttr = attr as MentionProps;
    renderItem = <Mentions {...inputAttr} />;
  } else if (type === 'Radio') {
    const inputAttr = attr as RadioProps;
    renderItem = <Radio.Group {...inputAttr} />;
  } else if (type === 'Switch') {
    const inputAttr = attr as SwitchProps;
    renderItem = <Switch {...inputAttr} />;
  } else if (type === 'TimePicker') {
    const inputAttr = attr as TimePickerProps;
    renderItem = <TimePicker {...inputAttr} />;
  } else if (type === 'Upload') {
    const inputAttr = attr as UploadProps;
    renderItem = <Upload {...inputAttr} />;
  } else if (type === 'RangePicker') {
    const inputAttr = attr as RangePickerProps;
    renderItem = <RangePicker {...inputAttr} />;
  } else if (type === 'Custom') {
    renderItem = inputNode;
  }
  return renderItem;
}
Example #2
Source File: GeneralTimePicker.tsx    From next-basics with GNU General Public License v3.0 6 votes vote down vote up
export function GeneralTimePicker(
  props: GeneralTimePickerProps
): React.ReactElement {
  const format = props.configProps?.format ?? "HH:mm:ss";

  const handleChange = (time: moment.Moment, timeString: string): void => {
    props.onChange?.(timeString);
  };

  const handleOpenChange = (flag: boolean): void => {
    props.onOpenChange?.(flag, props.value);
  };

  return (
    <FormItemWrapper {...props}>
      <TimePicker
        {...props.configProps}
        value={
          props.name && props.formElement
            ? undefined
            : props.value && moment(props.value, format)
        }
        onChange={handleChange}
        onOpenChange={handleOpenChange}
      />
    </FormItemWrapper>
  );
}
Example #3
Source File: TimeRangePicker.spec.tsx    From next-basics with GNU General Public License v3.0 6 votes vote down vote up
describe("RefTimeRangePicker", () => {
  it("should work", () => {
    const changeFn = jest.fn();
    const wrapper = mount(
      <RefTimeRangePicker
        format="HH:mm:ss"
        onChange={changeFn}
        emitChangeOnInit={true}
      />
    );
    expect(wrapper.find(TimePicker)).toHaveLength(2);
    expect(changeFn).toBeCalled();

    let startTimePicker = wrapper.find(TimePicker).first();
    startTimePicker.invoke("onChange")(
      moment("00:24:00", "HH:mm:ss"),
      // eslint-disable-next-line
      // @ts-ignore
      "00:24:00"
    );
    startTimePicker = wrapper.find(TimePicker).first();

    let endTimePicker = wrapper.find(TimePicker).last();
    endTimePicker.invoke("onChange")(
      moment("23:59:00", "HH:mm:ss"),
      // eslint-disable-next-line
      // @ts-ignore
      "23:59:00"
    );
    endTimePicker = wrapper.find(TimePicker).last();
    expect(endTimePicker.prop("value")).toBeUndefined();

    wrapper.setProps({ value: { startTime: "01:23:45", endTime: "23:59:59" } });
  });
});
Example #4
Source File: GeneralTimePicker.spec.tsx    From next-basics with GNU General Public License v3.0 5 votes vote down vote up
describe("GeneralTimePicker", () => {
  let clock: InstalledClock;

  beforeEach(() => {
    clock = install({ now: +new Date("2019-10-17 17:20:00") });
  });
  afterEach(() => {
    clock.uninstall();
  });

  it("should work", async () => {
    const handleChange = jest.fn();
    const handleOpenChange = jest.fn();

    const wrapper = shallow(
      <GeneralTimePicker
        name="time"
        label="hello"
        placeholder="when"
        value="09:14:30"
        onChange={handleChange}
        onOpenChange={handleOpenChange}
      />
    );
    wrapper.find(TimePicker).invoke("onChange")(
      moment("18:01:00", "HH:mm:ss"),
      "18:01:00"
    );
    await Promise.resolve();
    expect(handleChange).toBeCalledWith("18:01:00");

    wrapper.setProps({ value: "18:01:00" });
    wrapper.find(TimePicker).invoke("onOpenChange")(true);

    expect(handleOpenChange).toBeCalledWith(true, "18:01:00");
  });

  it("should update value", () => {
    const wrapper = mount(<GeneralTimePicker value="09:14:30" />);
    expect(
      wrapper
        .find(TimePicker)
        .prop("value")
        .format("HH:mm:ss")
    ).toBe("09:14:30");

    wrapper.setProps({
      value: "18:01:00"
    });
    wrapper.update();
    expect(
      wrapper
        .find(TimePicker)
        .prop("value")
        .format("HH:mm:ss")
    ).toBe("18:01:00");
  });
});
Example #5
Source File: BrickTimePicker.tsx    From next-basics with GNU General Public License v3.0 5 votes vote down vote up
export function LegacyBrickTimePicker({
  configProps,
  onChange
}: LegacyBrickTimePickerProps): React.ReactElement {
  return (
    <TimePicker {...configProps} onChange={e => handleChange(e, onChange)} />
  );
}
Example #6
Source File: index.tsx    From metaplex with Apache License 2.0 5 votes vote down vote up
DateTimePicker = (props: IDateTimePicker) => {
  const {
    momentObj,
    setMomentObj,
    datePickerProps = {},
    timePickerProps = {},
  } = props;
  return (
    <>
      <DatePicker
        className="field-date"
        size="large"
        value={momentObj}
        onChange={value => {
          if (!value) return;
          if (!momentObj) return setMomentObj(value);

          const currentMoment = momentObj.clone();
          currentMoment.year(value.year());
          currentMoment.month(value.month());
          currentMoment.date(value.date());
          setMomentObj(currentMoment);
        }}
        {...datePickerProps}
      />
      <TimePicker
        className="field-date"
        size="large"
        value={momentObj}
        onChange={value => {
          if (!value) return;
          if (!momentObj) return setMomentObj(value);

          const currentMoment = momentObj.clone();
          currentMoment.hour(value.hour());
          currentMoment.minute(value.minute());
          currentMoment.second(value.second());
          setMomentObj(currentMoment);
        }}
        {...timePickerProps}
      />
    </>
  );
}
Example #7
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 #8
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>
Example #9
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 #10
Source File: TimeRangePicker.spec.tsx    From next-basics with GNU General Public License v3.0 4 votes vote down vote up
describe("TimeRangePicker", () => {
  it("should work", () => {
    const wrapper = mount(<TimeRangePicker format="HH:mm:ss" />);
    expect(wrapper.find(TimePicker)).toHaveLength(2);
  });

  it("should work with init value", () => {
    const wrapper = mount(
      <TimeRangePicker
        format="HH:mm:ss"
        value={{ startTime: "01:23:45", endTime: "12:34:56" }}
      />
    );
    expect(wrapper.find(TimePicker)).toHaveLength(2);
    let startTimePicker = wrapper.find(TimePicker).first();
    startTimePicker.invoke("onChange")(
      moment("00:24:00", "HH:mm:ss"),
      // eslint-disable-next-line
      // @ts-ignore
      "00:24:00"
    );
    startTimePicker = wrapper.find(TimePicker).first();
    expect(startTimePicker.prop("value").format("HH:mm:ss")).toBe("00:24:00");

    let endTimePicker = wrapper.find(TimePicker).last();
    endTimePicker.invoke("onChange")(
      moment("23:59:00", "HH:mm:ss"),
      // eslint-disable-next-line
      // @ts-ignore
      "23:59:00"
    );
    endTimePicker = wrapper.find(TimePicker).last();
    expect(endTimePicker.prop("value").format("HH:mm:ss")).toBe("23:59:00");
  });

  it("should update value", () => {
    const wrapper = mount(<TimeRangePicker format="HH:mm:ss" />);
    expect(wrapper.find(TimePicker).first().prop("value")).toBeUndefined();

    wrapper.setProps({
      value: { startTime: "01:23:45", endTime: "12:34:56" },
    });
    wrapper.update();
    expect(
      wrapper.find(TimePicker).first().prop("value").format("HH:mm:ss")
    ).toBe("01:23:45");
  });

  it("date range should work", () => {
    const fn = jest.fn();
    const wrapper = mount(
      <TimeRangePicker
        format="YYYY-MM-DD HH:mm:ss"
        rangeType="dateTime"
        onChange={fn}
        value={{
          startTime: "2020-03-16 01:23:45",
          endTime: "2020-03-16 12:34:56",
        }}
        emitChangeOnInit={true}
      />
    );
    expect(wrapper.find(DatePicker.RangePicker)).toHaveLength(1);
    const rangePicker = wrapper.find(DatePicker.RangePicker).first();
    rangePicker.invoke("onChange")([moment(), moment()], ["", ""]);
    rangePicker.invoke("onOk")([moment(), moment()]);
    rangePicker.invoke("onOpenChange")(true);
    rangePicker.invoke("onOpenChange")(false);
    expect(fn).toBeCalled();
  });

  it("date range should work when startTime or endTime undefined", () => {
    const fn = jest.fn();
    const wrapper = mount(
      <TimeRangePicker
        format="YYYY-MM-DD HH:mm:ss"
        rangeType="dateTime"
        onChange={fn}
        value={{
          startTime: undefined,
          endTime: undefined,
        }}
      />
    );
    expect(wrapper.find(DatePicker.RangePicker)).toHaveLength(1);
    const rangePicker = wrapper.find(DatePicker.RangePicker).first();
    rangePicker.invoke("onChange")([moment(), moment()], ["", ""]);
    rangePicker.invoke("onOk")([moment(), moment()]);
    rangePicker.invoke("onOpenChange")(true);
    rangePicker.invoke("onOpenChange")(false);
    expect(fn).toBeCalled();
  });

  it("date range should work when default value is null", () => {
    let mountValue;
    const fn = jest.fn((args) => (mountValue = args));
    const wrapper = mount(
      <TimeRangePicker
        rangeType="dateTime"
        format="YYYY-MM-DD HH:mm:ss"
        onChange={fn}
        value={null}
        emitChangeOnInit={true}
      />
    );
    expect(wrapper.find(DatePicker.RangePicker)).toHaveLength(1);
    expect(mountValue).toMatchObject({
      startTime: moment().format("YYYY-MM-DD ") + "00:00:00",
      endTime: moment().format("YYYY-MM-DD ") + "23:59:59",
    });
  });
});
Example #11
Source File: TimeRangePicker.tsx    From next-basics with GNU General Public License v3.0 4 votes vote down vote up
export function RealTimeRangePicker(
  props: RealTimeRangePickerProps,
  ref: any
): React.ReactElement {
  const times = ["time", "hmTime"];
  const rangeType = props.rangeType ?? "time";
  const today = times.includes(rangeType) ? "" : moment().format("YYYY-MM-DD ");
  const initRange = {
    startTime: today + INIT_TIME_RANGE.startTime,
    endTime: today + INIT_TIME_RANGE.endTime,
  };

  const { t } = useTranslation(NS_FORMS);
  const initValue =
    !isEmpty(props.value?.startTime) || !isEmpty(props.value?.endTime)
      ? props.value
      : initRange;

  const [startTime, setStartTime] = React.useState(
    moment(initValue.startTime, props.format)
  );
  const [prevStartTime, setPrevStartTime] = React.useState(startTime?.clone());
  const [endTime, setEndTime] = React.useState(
    moment(initValue.endTime, props.format)
  );
  const [prevEndTime, setPrevEndTime] = React.useState(endTime?.clone());

  const onStartTimeChange = (time: moment.Moment, timeString: string) => {
    setStartTime(time);
    props.onChange?.({
      startTime: timeString,
      endTime: endTime?.format(props.format),
    });
  };

  const onEndTimeChange = (time: moment.Moment, timeString: string) => {
    setEndTime(time);
    props.onChange?.({
      endTime: timeString,
      startTime: startTime?.format(props.format),
    });
  };

  React.useEffect(() => {
    if (props.emitChangeOnInit && !props.value && props.onChange) {
      times.includes(rangeType)
        ? props.onChange(INIT_TIME_RANGE)
        : props.onChange(initRange);
    }
  }, []);

  React.useEffect(() => {
    if (props.value?.startTime) {
      const start = moment(props.value.startTime, props.format);
      setStartTime(start);
      setPrevStartTime(start);
    }
    if (props.value?.endTime) {
      const end = moment(props.value.endTime, props.format);
      setEndTime(end);
      setPrevEndTime(end);
    }
  }, [props.value]);

  const timeRange = (
    <Input.Group compact className={styles.timeRange}>
      <TimePicker
        {...{ id: uniqueId("start-time-") }}
        onChange={onStartTimeChange}
        value={!isEmpty(props.value?.startTime) ? startTime : undefined}
        format={props.format}
      />
      <Input disabled className={styles.timeRangeSplit} value="~" />
      <TimePicker
        {...{ id: uniqueId("end-time-") }}
        onChange={onEndTimeChange}
        value={!isEmpty(props.value?.endTime) ? endTime : undefined}
        format={props.format}
      />
    </Input.Group>
  );

  const rangeChange = (
    dates: RangeValue<moment.Moment>,
    dateStrings: [string, string]
  ) => {
    setStartTime(dates?.[0]);
    setEndTime(dates?.[1]);
    props.onChange?.({
      startTime: dates?.[0].format(props.format),
      endTime: dates?.[1].format(props.format),
    });
  };

  const needConfirm = React.useRef(false);
  const onOpenChange = (open: boolean) => {
    if (!open && needConfirm.current) {
      setStartTime(prevStartTime);
      setEndTime(prevEndTime);
    } else {
      needConfirm.current = true;
    }
  };

  const rangeOk = (selectedTime: RangeValue<moment.Moment>) => {
    needConfirm.current = false;
    const dates = selectedTime;
    setPrevStartTime(dates?.[0].clone());
    setPrevEndTime(dates?.[1].clone());
    props.onChange?.({
      startTime: dates?.[0].format(props.format),
      endTime: dates?.[1].format(props.format),
    });
  };

  const dateRange = (
    <DatePicker.RangePicker
      style={{ width: 400 }}
      showTime={rangeType === "dateTime"}
      value={
        !isEmpty(props.value?.startTime) || !isEmpty(props.value?.endTime)
          ? [startTime, endTime]
          : []
      }
      format={props.format}
      onChange={rangeChange}
      onOpenChange={onOpenChange}
      onOk={rangeOk}
      separator={"~"}
      suffixIcon={<Icon component={() => <BrickIcon icon="calendar" />} />}
    />
  );
  const range = times.includes(rangeType) ? timeRange : dateRange;

  return <div ref={ref}>{range}</div>;
}
Example #12
Source File: index.tsx    From imove with MIT License 4 votes vote down vote up
SchemaForm: React.FC<IProps> = (props) => {
  const { schema, configData, changeConfigData } = props;
  const [form] = Form.useForm();
  const onClickSave = (): void => {
    changeConfigData(form.getFieldsValue());
    message.success('保存成功!');
  };

  return schema && Object.keys(schema).length > 0 ? (
    <Form form={form} initialValues={configData} {...formLayout}>
      {schema?.properties &&
        Object.keys(schema.properties).map((key: string) => {
          const obj = schema.properties[key];
          const options: INum[] = obj.enum
            ? obj.enum.map((item: string, idx: number) => {
                return { label: item, value: obj.enumNames[idx] };
              })
            : [];
          let ele = null;
          // 输入框
          if (
            obj.type === 'string' &&
            !obj.hasOwnProperty('format') &&
            !obj.hasOwnProperty('enum')
          ) {
            ele = <Input />;
          }
          // 编辑框
          if (obj.type === 'string' && obj.format === 'textarea') {
            ele = <Input.TextArea />;
          }
          // switch
          if (obj.type === 'boolean' && obj['ui:widget'] === 'switch') {
            ele = <Switch />;
          }
          // 下拉单选
          if (
            obj.type === 'string' &&
            obj.hasOwnProperty('enum') &&
            !obj.hasOwnProperty('ui:widget')
          ) {
            ele = (
              <Select allowClear>
                {options.map((item) => (
                  <Option key={item.value} value={item.value}>
                    {item.label}
                  </Option>
                ))}
              </Select>
            );
          }
          // 下拉多选
          if (
            obj.type === 'array' &&
            obj.hasOwnProperty('enum') &&
            obj['ui:widget'] === 'multiSelect'
          ) {
            ele = (
              <Select allowClear mode="multiple">
                {options.map((item) => (
                  <Option key={item.value} value={item.value}>
                    {item.label}
                  </Option>
                ))}
              </Select>
            );
          }
          // 点击多选
          if (
            obj.type === 'array' &&
            obj.hasOwnProperty('enum') &&
            !obj.hasOwnProperty('ui:widget')
          ) {
            ele = <Checkbox.Group options={options} />;
          }
          // 时间选择
          if (obj.type === 'string' && obj.format === 'time') {
            ele = <TimePicker defaultValue={moment('00:00:00', 'HH:mm:ss')} />;
          }
          // 日期范围
          if (obj.type === 'range' && obj.format === 'date') {
            ele = <DatePicker />;
          }
          // 日期选择
          if (obj.type === 'string' && obj.format === 'date') {
            ele = <RangePicker />;
          }
          return (
            <FormItem label={obj.title} name={key} key={key}>
              {ele}
            </FormItem>
          );
        })}
      <div className={styles.btnWrap}>
        <Button
          size="small"
          className={styles.btn}
          type={'primary'}
          onClick={onClickSave}
        >
          保存
        </Button>
      </div>
    </Form>
  ) : (
    <Empty
      description={'请编辑投放配置schema'}
      image={Empty.PRESENTED_IMAGE_SIMPLE}
    />
  );
}
Example #13
Source File: editModal.tsx    From fe-v5 with Apache License 2.0 4 votes vote down vote up
editModal: React.FC<Props> = ({ isModalVisible, editModalFinish }) => {
  const { t, i18n } = useTranslation();

  const [form] = Form.useForm();
  const { clusters: clusterList } = useSelector<RootState, CommonStoreState>((state) => state.common);

  const [contactList, setInitContactList] = useState([]);
  const [notifyGroups, setNotifyGroups] = useState([]);

  const [field, setField] = useState<string>('cluster');
  const [refresh, setRefresh] = useState(true);

  useEffect(() => {
    getNotifyChannel();
    getGroups('');

    return () => {};
  }, []);

  const enableDaysOfWeekOptions = [t('周日'), t('周一'), t('周二'), t('周三'), t('周四'), t('周五'), t('周六')].map((v, i) => {
    return <Option value={String(i)} key={i}>{`${v}`}</Option>;
  });

  const contactListCheckboxes = contactList.map((c: { key: string; label: string }) => (
    <Checkbox value={c.key} key={c.label}>
      {c.label}
    </Checkbox>
  ));

  const notifyGroupsOptions = notifyGroups.map((ng: any) => (
    <Option value={ng.id} key={ng.id}>
      {ng.name}
    </Option>
  ));

  const getNotifyChannel = async () => {
    const res = await getNotifiesList();
    let contactList = res || [];
    setInitContactList(contactList);
  };

  const getGroups = async (str) => {
    const res = await getTeamInfoList({ query: str });
    const data = res.dat || res;
    setNotifyGroups(data || []);
  };

  const debounceFetcher = useCallback(debounce(getGroups, 800), []);

  const modelOk = () => {
    form.validateFields().then(async (values) => {
      const data = { ...values };
      switch (values.field) {
        case 'enable_time':
          data.enable_stime = values.enable_time[0].format('HH:mm');
          data.enable_etime = values.enable_time[1].format('HH:mm');
          delete data.enable_time;
          break;
        case 'disabled':
          data.disabled = !values.enable_status ? 1 : 0;
          delete data.enable_status;
          break;
        case 'enable_in_bg':
          data.enable_in_bg = values.enable_in_bg ? 1 : 0;
          break;
        case 'callbacks':
          data.callbacks = values.callbacks.map((item) => item.url);
          break;
        case 'notify_recovered':
          data.notify_recovered = values.notify_recovered ? 1 : 0;
          break;
        default:
          break;
      }
      delete data.field;
      Object.keys(data).forEach((key) => {
        // 因为功能上有清除备注的需求,需要支持传空
        if (data[key] === undefined) {
          data[key] = '';
        }
        if (Array.isArray(data[key])) {
          data[key] = data[key].join(' ');
        }
      });
      editModalFinish(true, data);
    });
  };

  const editModalClose = () => {
    editModalFinish(false);
  };

  const fieldChange = (val) => {
    setField(val);
  };

  return (
    <>
      <Modal
        title={t('批量更新')}
        visible={isModalVisible}
        onOk={modelOk}
        onCancel={() => {
          editModalClose();
        }}
      >
        <Form
          {...layout}
          form={form}
          className='strategy-form'
          layout={refresh ? 'horizontal' : 'horizontal'}
          initialValues={{
            prom_eval_interval: 15,
            disabled: 0, // 0:立即启用 1:禁用
            enable_status: true, // true:立即启用 false:禁用
            notify_recovered: 1, // 1:启用
            enable_time: [moment('00:00', 'HH:mm'), moment('23:59', 'HH:mm')],
            cluster: clusterList[0] || 'Default', // 生效集群
            enable_days_of_week: ['1', '2', '3', '4', '5', '6', '0'],
            field: 'cluster',
          }}
        >
          <Form.Item
            label={t('字段:')}
            name='field'
            rules={[
              {
                required: false,
              },
            ]}
          >
            <Select suffixIcon={<CaretDownOutlined />} style={{ width: '100%' }} onChange={fieldChange}>
              {fields.map((item) => (
                <Option key={item.id} value={item.field}>
                  {item.name}
                </Option>
              ))}
            </Select>
          </Form.Item>
          {(() => {
            switch (field) {
              case 'note':
                return (
                  <>
                    <Form.Item
                      label={t('改为:')}
                      name='note'
                      rules={[
                        {
                          required: false,
                        },
                      ]}
                    >
                      <Input placeholder={t('请输入规则备注')} />
                    </Form.Item>
                  </>
                );
              case 'runbook_url':
                return (
                  <>
                    <Form.Item label={t('改为:')} name='runbook_url'>
                      <Input />
                    </Form.Item>
                  </>
                );

              case 'cluster':
                return (
                  <>
                    <Form.Item
                      label={t('改为:')}
                      name='cluster'
                      rules={[
                        {
                          required: false,
                          message: t('生效集群不能为空'),
                        },
                      ]}
                    >
                      <Select suffixIcon={<CaretDownOutlined />}>
                        {clusterList?.map((item) => (
                          <Option value={item} key={item}>
                            {item}
                          </Option>
                        ))}
                      </Select>
                    </Form.Item>
                  </>
                );
              case 'severity':
                return (
                  <>
                    <Form.Item
                      label={t('改为:')}
                      name='severity'
                      initialValue={2}
                      rules={[
                        {
                          required: false,
                          message: t('告警级别不能为空'),
                        },
                      ]}
                    >
                      <Radio.Group>
                        <Radio value={1}>{t('一级报警')}</Radio>
                        <Radio value={2}>{t('二级报警')}</Radio>
                        <Radio value={3}>{t('三级报警')}</Radio>
                      </Radio.Group>
                    </Form.Item>
                  </>
                );
              case 'disabled':
                return (
                  <>
                    <Form.Item
                      label={t('改为:')}
                      name='enable_status'
                      rules={[
                        {
                          required: false,
                          message: t('立即启用不能为空'),
                        },
                      ]}
                      valuePropName='checked'
                    >
                      <Switch />
                    </Form.Item>
                  </>
                );
              case 'enable_in_bg':
                return (
                  <>
                    <Form.Item label={t('改为:')} name='enable_in_bg' valuePropName='checked'>
                      <SwitchWithLabel label='根据告警事件中的ident归属关系判断' />
                    </Form.Item>
                  </>
                );
              case 'prom_eval_interval':
                return (
                  <>
                    <Form.Item
                      label={t('改为:')}
                      rules={[
                        {
                          required: false,
                          message: t('执行频率不能为空'),
                        },
                      ]}
                    >
                      <Space>
                        <Form.Item style={{ marginBottom: 0 }} name='prom_eval_interval' initialValue={15} wrapperCol={{ span: 10 }}>
                          <InputNumber
                            min={1}
                            onChange={(val) => {
                              setRefresh(!refresh);
                            }}
                          />
                        </Form.Item>
                        秒
                        <Tooltip title={t(`每隔${form.getFieldValue('prom_eval_interval')}秒,把PromQL作为查询条件,去查询后端存储,如果查到了数据就表示当次有监控数据触发了规则`)}>
                          <QuestionCircleFilled />
                        </Tooltip>
                      </Space>
                    </Form.Item>
                  </>
                );
              case 'prom_for_duration':
                return (
                  <>
                    <Form.Item
                      label={t('改为:')}
                      rules={[
                        {
                          required: false,
                          message: t('持续时长不能为空'),
                        },
                      ]}
                    >
                      <Space>
                        <Form.Item style={{ marginBottom: 0 }} name='prom_for_duration' initialValue={60} wrapperCol={{ span: 10 }}>
                          <InputNumber min={0} />
                        </Form.Item>
                        秒
                        <Tooltip
                          title={t(
                            `通常持续时长大于执行频率,在持续时长内按照执行频率多次执行PromQL查询,每次都触发才生成告警;如果持续时长置为0,表示只要有一次PromQL查询触发阈值,就生成告警`,
                          )}
                        >
                          <QuestionCircleFilled />
                        </Tooltip>
                      </Space>
                    </Form.Item>
                  </>
                );
              case 'notify_channels':
                return (
                  <>
                    <Form.Item label={t('改为:')} name='notify_channels'>
                      <Checkbox.Group>{contactListCheckboxes}</Checkbox.Group>
                    </Form.Item>
                  </>
                );
              case 'notify_groups':
                return (
                  <>
                    <Form.Item label={t('改为:')} name='notify_groups'>
                      <Select mode='multiple' showSearch optionFilterProp='children' filterOption={false} onSearch={(e) => debounceFetcher(e)} onBlur={() => getGroups('')}>
                        {notifyGroupsOptions}
                      </Select>
                    </Form.Item>
                  </>
                );
              case 'notify_recovered':
                return (
                  <>
                    <Form.Item label={t('改为:')} name='notify_recovered' valuePropName='checked'>
                      <Switch />
                    </Form.Item>
                  </>
                );
              case 'recover_duration':
                return (
                  <>
                    <Form.Item label={t('改为:')}>
                      <Space>
                        <Form.Item
                          style={{ marginBottom: 0 }}
                          name='recover_duration'
                          initialValue={0}
                          wrapperCol={{ span: 10 }}
                          rules={[
                            {
                              required: false,
                              message: t('留观时长不能为空'),
                            },
                          ]}
                        >
                          <InputNumber
                            min={0}
                            onChange={(val) => {
                              setRefresh(!refresh);
                            }}
                          />
                        </Form.Item>
                        秒
                        <Tooltip title={t(`持续${form.getFieldValue('recover_duration') || 0}秒没有再次触发阈值才发送恢复通知`)}>
                          <QuestionCircleFilled />
                        </Tooltip>
                      </Space>
                    </Form.Item>
                  </>
                );
              case 'notify_repeat_step':
                return (
                  <>
                    <Form.Item label={t('改为:')}>
                      <Space>
                        <Form.Item
                          style={{ marginBottom: 0 }}
                          name='notify_repeat_step'
                          initialValue={60}
                          wrapperCol={{ span: 10 }}
                          rules={[
                            {
                              required: false,
                              message: t('重复发送频率不能为空'),
                            },
                          ]}
                        >
                          <InputNumber
                            min={0}
                            onChange={(val) => {
                              setRefresh(!refresh);
                            }}
                          />
                        </Form.Item>
                        分钟
                        <Tooltip title={t(`如果告警持续未恢复,间隔${form.getFieldValue('notify_repeat_step')}分钟之后重复提醒告警接收组的成员`)}>
                          <QuestionCircleFilled />
                        </Tooltip>
                      </Space>
                    </Form.Item>
                  </>
                );
              case 'callbacks':
                return (
                  <>
                    <Form.Item label={t('改为:')}>
                      <Form.List name='callbacks' initialValue={[{}]}>
                        {(fields, { add, remove }, { errors }) => (
                          <>
                            {fields.map((field, index) => (
                              <Row gutter={[10, 0]} key={field.key}>
                                <Col span={22}>
                                  <Form.Item name={[field.name, 'url']}>
                                    <Input />
                                  </Form.Item>
                                </Col>

                                <Col span={1}>
                                  <MinusCircleOutlined className='control-icon-normal' onClick={() => remove(field.name)} />
                                </Col>
                              </Row>
                            ))}
                            <PlusCircleOutlined className='control-icon-normal' onClick={() => add()} />
                          </>
                        )}
                      </Form.List>
                    </Form.Item>
                  </>
                );
              case 'append_tags':
                return (
                  <>
                    <Form.Item label='附加标签' name='append_tags' rules={[{ required: false, message: '请填写至少一项标签!' }, isValidFormat]}>
                      <Select mode='tags' tokenSeparators={[' ']} open={false} placeholder={'标签格式为 key=value ,使用回车或空格分隔'} tagRender={tagRender} />
                    </Form.Item>
                  </>
                );
              case 'enable_time':
                return (
                  <>
                    <Form.Item
                      label={t('改为:')}
                      name='enable_days_of_week'
                      rules={[
                        {
                          required: false,
                          message: t('生效时间不能为空'),
                        },
                      ]}
                    >
                      <Select mode='tags'>{enableDaysOfWeekOptions}</Select>
                    </Form.Item>
                    <Form.Item
                      name='enable_time'
                      {...tailLayout}
                      rules={[
                        {
                          required: false,
                          message: t('生效时间不能为空'),
                        },
                      ]}
                    >
                      <TimePicker.RangePicker
                        format='HH:mm'
                        onChange={(val, val2) => {
                          form.setFieldsValue({
                            enable_stime: val2[0],
                            enable_etime: val2[1],
                          });
                        }}
                      />
                    </Form.Item>
                  </>
                );
              default:
                return null;
            }
          })()}
        </Form>
      </Modal>
    </>
  );
}
Example #14
Source File: operateForm.tsx    From fe-v5 with Apache License 2.0 4 votes vote down vote up
operateForm: React.FC<Props> = ({ type, detail = {} }) => {
  const { t, i18n } = useTranslation();
  const history = useHistory(); // 创建的时候默认选中的值

  const [form] = Form.useForm();
  const { clusters: clusterList } = useSelector<RootState, CommonStoreState>((state) => state.common);
  const { curBusiItem } = useSelector<RootState, CommonStoreState>((state) => state.common);

  const [contactList, setInitContactList] = useState([]);
  const [notifyGroups, setNotifyGroups] = useState<any[]>([]);
  const [initVal, setInitVal] = useState<any>({});
  const [refresh, setRefresh] = useState(true);
  useEffect(() => {
    getNotifyChannel();
    getGroups('');

    return () => {};
  }, []);

  useEffect(() => {
    const data = {
      ...detail,
      enable_time: detail?.enable_stime ? [detail.enable_stime, detail.enable_etime] : [],
      enable_status: detail?.disabled === undefined ? true : !detail?.disabled,
    };
    setInitVal(data);
    if (type == 1) {
      const groups = (detail.notify_groups_obj ? detail.notify_groups_obj.filter((item) => !notifyGroups.find((i) => item.id === i.id)) : []).concat(notifyGroups);
      setNotifyGroups(groups);
    }
  }, [JSON.stringify(detail)]);

  const enableDaysOfWeekOptions = [t('周日'), t('周一'), t('周二'), t('周三'), t('周四'), t('周五'), t('周六')].map((v, i) => {
    return <Option value={String(i)} key={i}>{`${v}`}</Option>;
  });

  const contactListCheckboxes = contactList.map((c: { key: string; label: string }) => (
    <Checkbox value={c.key} key={c.label}>
      {c.label}
    </Checkbox>
  ));

  const notifyGroupsOptions = notifyGroups.map((ng: any) => (
    <Option value={String(ng.id)} key={ng.id}>
      {ng.name}
    </Option>
  ));

  const getNotifyChannel = async () => {
    const res = await getNotifiesList();
    let contactList = res || [];
    setInitContactList(contactList);
  };

  const getGroups = async (str) => {
    const res = await getTeamInfoList({ query: str });
    const data = res.dat || res;
    const combineData = (detail.notify_groups_obj ? detail.notify_groups_obj.filter((item) => !data.find((i) => item.id === i.id)) : []).concat(data);
    setNotifyGroups(combineData || []);
  };

  const addSubmit = () => {
    form.validateFields().then(async (values) => {
      const res = await prometheusQuery({ query: values.prom_ql }, values.cluster);
      if (res.error) {
        notification.error({
          message: res.error,
        });
        return false;
      }
      const callbacks = values.callbacks.map((item) => item.url);
      const data = {
        ...values,
        enable_stime: values.enable_time[0].format('HH:mm'),
        enable_etime: values.enable_time[1].format('HH:mm'),
        disabled: !values.enable_status ? 1 : 0,
        notify_recovered: values.notify_recovered ? 1 : 0,
        enable_in_bg: values.enable_in_bg ? 1 : 0,
        callbacks,
      };
      let reqBody,
        method = 'Post';
      if (type === 1) {
        reqBody = data;
        method = 'Put';
        const res = await EditStrategy(reqBody, curBusiItem.id, detail.id);
        if (res.err) {
          message.error(res.error);
        } else {
          message.success(t('编辑成功!'));
          history.push('/alert-rules');
        }
      } else {
        reqBody = [data];
        const { dat } = await addOrEditStrategy(reqBody, curBusiItem.id, method);
        let errorNum = 0;
        const msg = Object.keys(dat).map((key) => {
          dat[key] && errorNum++;
          return dat[key];
        });

        if (!errorNum) {
          message.success(`${type === 2 ? t('告警规则克隆成功') : t('告警规则创建成功')}`);
          history.push('/alert-rules');
        } else {
          message.error(t(msg));
        }
      }
    });
  };

  const debounceFetcher = useCallback(debounce(getGroups, 800), []);
  return (
    <div className='operate_con'>
      <Form
        {...layout}
        form={form}
        className='strategy-form'
        layout={refresh ? 'horizontal' : 'horizontal'}
        initialValues={{
          prom_eval_interval: 15,
          prom_for_duration: 60,
          severity: 2,
          disabled: 0, // 0:立即启用 1:禁用  待修改
          // notify_recovered: 1, // 1:启用
          cluster: clusterList[0] || 'Default', // 生效集群
          enable_days_of_week: ['1', '2', '3', '4', '5', '6', '0'],
          ...detail,
          enable_in_bg: detail?.enable_in_bg === 1,
          enable_time: detail?.enable_stime ? [moment(detail.enable_stime, 'HH:mm'), moment(detail.enable_etime, 'HH:mm')] : [moment('00:00', 'HH:mm'), moment('23:59', 'HH:mm')],
          enable_status: detail?.disabled === undefined ? true : !detail?.disabled,
          notify_recovered: detail?.notify_recovered === 1 || detail?.notify_recovered === undefined ? true : false, // 1:启用 0:禁用
          recover_duration: detail?.recover_duration || 0,
          callbacks: !!detail?.callbacks
            ? detail.callbacks.map((item) => ({
                url: item,
              }))
            : [{}],
        }}
      >
        <Space direction='vertical' style={{ width: '100%' }}>
          <Card title={t('基本配置')}>
            <Form.Item
              label={t('规则标题:')}
              name='name'
              rules={[
                {
                  required: true,
                  message: t('规则标题不能为空'),
                },
              ]}
            >
              <Input placeholder={t('请输入规则标题')} />
            </Form.Item>
            <Form.Item
              label={t('规则备注:')}
              name='note'
              rules={[
                {
                  required: false,
                },
              ]}
            >
              <Input placeholder={t('请输入规则备注')} />
            </Form.Item>
            <Form.Item
              label={t('告警级别')}
              name='severity'
              rules={[
                {
                  required: true,
                  message: t('告警级别不能为空'),
                },
              ]}
            >
              <Radio.Group>
                <Radio value={1}>{t('一级报警')}</Radio>
                <Radio value={2}>{t('二级报警')}</Radio>
                <Radio value={3}>{t('三级报警')}</Radio>
              </Radio.Group>
            </Form.Item>
            <Form.Item
              label={t('生效集群')}
              name='cluster'
              rules={[
                {
                  required: true,
                  message: t('生效集群不能为空'),
                },
              ]}
            >
              <Select suffixIcon={<CaretDownOutlined />}>
                {clusterList?.map((item) => (
                  <Option value={item} key={item}>
                    {item}
                  </Option>
                ))}
              </Select>
            </Form.Item>
            <AdvancedWrap>
              <AbnormalDetection form={form} />
            </AdvancedWrap>
            <Form.Item noStyle shouldUpdate={(prevValues, curValues) => prevValues.cluster !== curValues.cluster}>
              {() => {
                return (
                  <Form.Item label='PromQL' className={'Promeql-content'} required>
                    <Form.Item name='prom_ql' validateTrigger={['onBlur']} trigger='onChange' rules={[{ required: true, message: t('请输入PromQL') }]}>
                      <PromQLInput
                        url='/api/n9e/prometheus'
                        headers={{
                          'X-Cluster': form.getFieldValue('cluster'),
                          Authorization: `Bearer ${localStorage.getItem('access_token') || ''}`,
                        }}
                      />
                    </Form.Item>
                  </Form.Item>
                );
              }}
            </Form.Item>
            <Form.Item required label={t('执行频率')}>
              <Space>
                <Form.Item
                  style={{ marginBottom: 0 }}
                  name='prom_eval_interval'
                  initialValue={15}
                  wrapperCol={{ span: 10 }}
                  rules={[
                    {
                      required: true,
                      message: t('执行频率不能为空'),
                    },
                  ]}
                >
                  <InputNumber
                    min={1}
                    onChange={(val) => {
                      setRefresh(!refresh);
                    }}
                  />
                </Form.Item>
                秒
                <Tooltip title={t(`每隔${form.getFieldValue('prom_eval_interval')}秒,把PromQL作为查询条件,去查询后端存储,如果查到了数据就表示当次有监控数据触发了规则`)}>
                  <QuestionCircleFilled />
                </Tooltip>
              </Space>
            </Form.Item>
            <Form.Item
              required
              label={t('持续时长')}
              rules={[
                {
                  required: true,
                  message: t('持续时长不能为空'),
                },
              ]}
            >
              <Space>
                <Form.Item style={{ marginBottom: 0 }} name='prom_for_duration' wrapperCol={{ span: 10 }}>
                  <InputNumber min={0} />
                </Form.Item>
                秒
                <Tooltip
                  title={t(
                    `通常持续时长大于执行频率,在持续时长内按照执行频率多次执行PromQL查询,每次都触发才生成告警;如果持续时长置为0,表示只要有一次PromQL查询触发阈值,就生成告警`,
                  )}
                >
                  <QuestionCircleFilled />
                </Tooltip>
              </Space>
            </Form.Item>
            <Form.Item label='附加标签' name='append_tags' rules={[{ required: false, message: '请填写至少一项标签!' }, isValidFormat]}>
              <Select mode='tags' tokenSeparators={[' ']} open={false} placeholder={'标签格式为 key=value ,使用回车或空格分隔'} tagRender={tagRender} />
            </Form.Item>
            <Form.Item label={t('预案链接')} name='runbook_url'>
              <Input />
            </Form.Item>
          </Card>
          <Card title={t('生效配置')}>
            <Form.Item
              label={t('立即启用')}
              name='enable_status'
              rules={[
                {
                  required: true,
                  message: t('立即启用不能为空'),
                },
              ]}
              valuePropName='checked'
            >
              <Switch />
            </Form.Item>
            <Form.Item
              label={t('生效时间')}
              name='enable_days_of_week'
              rules={[
                {
                  required: true,
                  message: t('生效时间不能为空'),
                },
              ]}
            >
              <Select mode='tags'>{enableDaysOfWeekOptions}</Select>
            </Form.Item>
            <Form.Item
              name='enable_time'
              {...tailLayout}
              rules={[
                {
                  required: true,
                  message: t('生效时间不能为空'),
                },
              ]}
            >
              <TimePicker.RangePicker
                format='HH:mm'
                onChange={(val, val2) => {
                  form.setFieldsValue({
                    enable_stime: val2[0],
                    enable_etime: val2[1],
                  });
                }}
              />
            </Form.Item>
            <Form.Item label={t('仅在本业务组生效')} name='enable_in_bg' valuePropName='checked'>
              <SwitchWithLabel label='根据告警事件中的ident归属关系判断' />
            </Form.Item>
          </Card>
          <Card title={t('通知配置')}>
            <Form.Item label={t('通知媒介')} name='notify_channels'>
              <Checkbox.Group>{contactListCheckboxes}</Checkbox.Group>
            </Form.Item>
            <Form.Item label={t('告警接收组')} name='notify_groups'>
              <Select mode='multiple' showSearch optionFilterProp='children' filterOption={false} onSearch={(e) => debounceFetcher(e)} onBlur={() => getGroups('')}>
                {notifyGroupsOptions}
              </Select>
            </Form.Item>
            <Form.Item label={t('启用恢复通知')}>
              <Space>
                <Form.Item name='notify_recovered' valuePropName='checked' style={{ marginBottom: 0 }}>
                  <Switch />
                </Form.Item>
                <Tooltip title={t(`告警恢复时也发送通知`)}>
                  <QuestionCircleFilled />
                </Tooltip>
              </Space>
            </Form.Item>
            <Form.Item label={t('留观时长')} required>
              <Space>
                <Form.Item style={{ marginBottom: 0 }} name='recover_duration' initialValue={0} wrapperCol={{ span: 10 }}>
                  <InputNumber
                    min={0}
                    onChange={(val) => {
                      setRefresh(!refresh);
                    }}
                  />
                </Form.Item>
                秒
                <Tooltip title={t(`持续${form.getFieldValue('recover_duration')}秒没有再次触发阈值才发送恢复通知`)}>
                  <QuestionCircleFilled />
                </Tooltip>
              </Space>
            </Form.Item>
            <Form.Item label={t('重复发送频率')} required>
              <Space>
                <Form.Item
                  style={{ marginBottom: 0 }}
                  name='notify_repeat_step'
                  initialValue={60}
                  wrapperCol={{ span: 10 }}
                  rules={[
                    {
                      required: true,
                      message: t('重复发送频率不能为空'),
                    },
                  ]}
                >
                  <InputNumber
                    min={0}
                    onChange={(val) => {
                      setRefresh(!refresh);
                    }}
                  />
                </Form.Item>
                分钟
                <Tooltip title={t(`如果告警持续未恢复,间隔${form.getFieldValue('notify_repeat_step')}分钟之后重复提醒告警接收组的成员`)}>
                  <QuestionCircleFilled />
                </Tooltip>
              </Space>
            </Form.Item>
            <Form.Item label={t('回调地址')}>
              <Form.List name='callbacks' initialValue={[{}]}>
                {(fields, { add, remove }) => (
                  <>
                    {fields.map((field) => (
                      <Row gutter={[10, 0]} key={field.key}>
                        <Col span={22}>
                          <Form.Item name={[field.name, 'url']} fieldKey={[field.fieldKey, 'url']}>
                            <Input />
                          </Form.Item>
                        </Col>

                        <Col span={1}>
                          <MinusCircleOutlined className='control-icon-normal' onClick={() => remove(field.name)} />
                        </Col>
                      </Row>
                    ))}
                    <PlusCircleOutlined className='control-icon-normal' onClick={() => add()} />
                  </>
                )}
              </Form.List>
            </Form.Item>
          </Card>
          <Form.Item
            // {...tailLayout}
            style={{
              marginTop: 20,
            }}
          >
            <Button type='primary' onClick={addSubmit} style={{ marginRight: '8px' }}>
              {type === 1 ? t('编辑') : type === 2 ? t('克隆') : t('创建')}
            </Button>
            {type === 1 && (
              <Button
                danger
                style={{ marginRight: '8px' }}
                onClick={() => {
                  Modal.confirm({
                    title: t('是否删除该告警规则?'),
                    onOk: () => {
                      deleteStrategy([detail.id], curBusiItem.id).then(() => {
                        message.success(t('删除成功'));
                        history.push('/alert-rules');
                      });
                    },

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

            <Button
              onClick={() => {
                history.push('/alert-rules');
              }}
            >
              {t('取消')}
            </Button>
          </Form.Item>
        </Space>
      </Form>
    </div>
  );
}