@ant-design/icons#InfoCircleFilled TypeScript Examples

The following examples show how to use @ant-design/icons#InfoCircleFilled. 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: Alert.tsx    From amiya with MIT License 6 votes vote down vote up
export default function MyAlert(props: any) {
  return (
    <span
      style={{
        display: 'block',
        backgroundColor: '#e6f7ff',
        border: '1px solid #91d5ff',
        borderRadius: 2,
        padding: '8px 15px'
      }}
    >
      <InfoCircleFilled style={{ color: '#1890ff', marginRight: 8 }} />
      {props.children}
    </span>
  )
}
Example #2
Source File: TopNotifications.tsx    From condo with MIT License 5 votes vote down vote up
useTopNotificationsHook = (): ITopNotificationHookResult => {
    const [topNotifications, setTopNotifications] = useState<ITopNotification[]>([])
    const addNotification = (notification: ITopNotification) => {
        if (!topNotifications.find(existedNotification => existedNotification.id === notification.id)) {
            setTopNotifications([...topNotifications, notification])
        }
    }
    const removeNotification = (notificationId) => {
        setTopNotifications([...topNotifications.filter(notification => notification.id !== notificationId)])
    }

    const TopNotificationComponent: React.FC = () => {
        const { isSmall } = useLayoutContext()
        return (
            <>
                <Affix>{
                    topNotifications.map(notification => {
                        return (
                            <Alert
                                showIcon
                                icon={(<InfoCircleFilled />)}
                                message={notification.message}
                                type={notification.type}
                                key={notification.id}
                                css={notificationAlert({ isSmall })}
                                action={<Space size={20}>
                                    {
                                        notification.actions.map((action, idx) => {
                                            return (
                                                <Button
                                                    onClick={async () => {
                                                        await action.action()
                                                        removeNotification(notification.id)
                                                    }}
                                                    size={isSmall ? 'middle' : 'large'}
                                                    type={'sberPrimary'}
                                                    secondary={action.secondary}
                                                    key={idx}
                                                >
                                                    {action.title}
                                                </Button>
                                            )
                                        })}
                                </Space>}
                            />
                        )
                    })
                }
                </Affix>
            </>
        )
    }

    return {
        addNotification,
        TopNotificationComponent,
    }
}
Example #3
Source File: EditableTable.tsx    From amiya with MIT License 5 votes vote down vote up
RuleFormItem = ({ inputProps, input, extra, popoverProps }: RuleFormItemProps) => {
  const [visible, setVisible] = useState<boolean | undefined>(false)
  const [errorStringList, setErrorList] = useState<string[]>([])

  useEffect(() => {
    if (inputProps.validateStatus !== 'validating') {
      setErrorList(inputProps.errors)
    }
  }, [inputProps.errors, inputProps.validateStatus])

  return (
    <Popover
      key="popover"
      trigger="focus"
      placement="topRight"
      visible={errorStringList.length < 1 ? false : visible}
      onVisibleChange={value => {
        if (value !== visible) {
          setVisible(value)
        }
      }}
      content={
        <div className="ay-form-item-with-help">
          {inputProps.validateStatus === 'validating' ? <LoadingOutlined /> : null}
          {errorStringList.map(text => (
            <div key={text}>
              <Text type="danger">
                <Space>
                  <InfoCircleFilled />
                  {text}
                </Space>
              </Text>
            </div>
          ))}
        </div>
      }
      {...popoverProps}
    >
      <div>
        {input}
        {extra}
      </div>
    </Popover>
  )
}
Example #4
Source File: DashboardPage.tsx    From iot-center-v2 with MIT License 4 votes vote down vote up
DashboardPage: FunctionComponent<
  RouteComponentProps<PropsRoute> & Props
> = ({match, history, helpCollapsed}) => {
  const deviceId = match.params.deviceId ?? VIRTUAL_DEVICE
  const [loading, setLoading] = useState(true)
  const [message, setMessage] = useState<Message | undefined>()
  const [deviceData, setDeviceData] = useState<DeviceData | undefined>()
  const [dataStamp, setDataStamp] = useState(0)
  const [devices, setDevices] = useState<DeviceInfo[] | undefined>(undefined)
  const [timeStart, setTimeStart] = useState('-1d')
  const [xDomain, setXDomain] = useState<number[] | undefined>(undefined)

  const resetXDomain = () =>
    setXDomain(getXDomainFromTable(deviceData?.measurementsTable))

  const isVirtualDevice = deviceId === VIRTUAL_DEVICE
  const measurementsTable = deviceData?.measurementsTable

  // fetch device configuration and data
  useEffect(() => {
    const fetchDeviceLastValues = async (
      config: DeviceConfig,
      timeStart: string
    ) => {
      return Promise.all(
        measurementsDefinitions.map(async ({column}) => ({
          column,
          table: await fetchDeviceDataFieldLast(config, column, timeStart),
        }))
      )
    }

    const fetchData = async () => {
      setLoading(true)
      try {
        const config = await fetchDeviceConfig(deviceId)
        const deviceData: DeviceData = {config}
        const [table, lastValues] = await Promise.all([
          fetchDeviceMeasurements(config, timeStart),
          fetchDeviceLastValues(config, timeStart),
        ])
        deviceData.measurementsTable = table
        deviceData.measurementsLastValues = lastValues
        setDeviceData(deviceData)
      } catch (e) {
        console.error(e)
        setMessage({
          title: 'Cannot load device data',
          description: String(e),
          type: 'error',
        })
      }
      setLoading(false)
    }

    fetchData()
  }, [dataStamp, deviceId, timeStart])

  useEffect(() => {
    resetXDomain()
    // eslint-disable-next-line
  }, [deviceData])

  useEffect(() => {
    const fetchDevices = async () => {
      try {
        const response = await fetch('/api/devices')
        if (response.status >= 300) {
          const text = await response.text()
          throw new Error(`${response.status} ${text}`)
        }
        const data = await response.json()
        setDevices(data)
      } catch (e) {
        setMessage({
          title: 'Cannot fetch data',
          description: String(e),
          type: 'error',
        })
      }
    }

    fetchDevices()
  }, [])

  const renderGauge = (
    gaugeDefinition: Partial<GaugeLayerConfig>,
    table: GiraffeTable
  ) => {
    const gaugeDefaults: GaugeLayerConfig = {
      type: 'gauge',
      gaugeColors: [],
      gaugeSize: 4,
      gaugeTheme: {
        ...GAUGE_THEME_LIGHT,
        valuePositionYOffset: 1,
      },
    }

    return (
      <div style={{width: '100%', height: 150}}>
        <Plot
          config={{
            showAxes: false,
            layers: [{...gaugeDefaults, ...gaugeDefinition}],
            table,
          }}
        />
      </div>
    )
  }

  const gaugeLastTimeMessage = (time: number) => {
    const now = Date.now()
    const diff = now - time

    if (diff < 60_000) return 'just now'
    if (diff < 300_000) return 'less than 5 min ago'
    if (diff < 900_000) return 'more than 5 min ago'
    return 'long time ago'
  }

  const gaugeMissingValues: string[] = []
  const gauges = deviceData?.measurementsLastValues?.length ? (
    <>
      <Row gutter={[22, 22]}>
        {measurementsDefinitions.map(({gauge, title, column}) => {
          const lastValueTable = deviceData?.measurementsLastValues?.find(
            (x) => x.column === column
          )?.table

          if (!lastValueTable?.length) {
            gaugeMissingValues.push(title)
            return undefined
          }

          const [time] = lastValueTable.getColumn('_time') as number[]

          return (
            <Col
              sm={helpCollapsed ? 24 : 24}
              md={helpCollapsed ? 12 : 24}
              xl={helpCollapsed ? 6 : 12}
            >
              <Card
                title={title}
                extra={
                  <Tooltip title={new Date(time).toISOString()}>
                    <div style={{color: COLOR_TEXT}}>
                      {gaugeLastTimeMessage(time)}
                    </div>
                  </Tooltip>
                }
              >
                {renderGauge(gauge, lastValueTable)}
              </Card>
            </Col>
          )
        })}
      </Row>
      <Divider style={{color: 'rgba(0, 0, 0, .2)'}} orientation="right">
        {gaugeMissingValues.length
          ? `Gauge missing values: ${gaugeMissingValues.join(', ')}`
          : undefined}
      </Divider>
    </>
  ) : undefined

  const renderPlot = (
    lineDefinition: Partial<LineLayerConfig> | undefined,
    table: GiraffeTable,
    column: string
  ) => {
    const lineDefaults: LineLayerConfig = {
      type: 'line',
      x: '_time',
      y: column,
      interpolation: 'linear',
      colors: [COLOR_PRIMARY],
    }

    return (
      <div style={{width: '100%', height: 200}}>
        <Plot
          config={{
            xDomain: xDomain,
            onSetXDomain: setXDomain,
            onResetXDomain: resetXDomain,
            layers: [{...lineDefaults, ...lineDefinition}],
            table,
            valueFormatters: {
              _time: timeFormatter({
                timeZone: 'UTC',
                format: 'YYYY-MM-DD HH:mm:ss ZZ',
              }),
            },
          }}
        />
      </div>
    )
  }

  const plots =
    measurementsTable && measurementsTable?.length
      ? (() => {
          const measurementsWithValues = measurementsDefinitions.filter(
            ({column}) => measurementsTable.getColumn(column)
          )
          const measurementsNoValues = measurementsDefinitions.filter(
            ({column}) => !measurementsTable.getColumn(column)
          )

          return (
            <>
              <Row gutter={[0, 24]}>
                {measurementsWithValues.map(({line, title, column}, i) => (
                  <Col xs={24}>
                    <Collapse
                      defaultActiveKey={measurementsWithValues.map((_, i) => i)}
                    >
                      <CollapsePanel key={i} header={title}>
                        {renderPlot(line, measurementsTable, column)}
                      </CollapsePanel>
                    </Collapse>
                  </Col>
                ))}
              </Row>
              {measurementsNoValues.length ? (
                <Collapse>
                  {measurementsNoValues.map(({title}, i) => (
                    <CollapsePanel
                      key={i}
                      disabled={true}
                      header={`${title} - No data`}
                    />
                  ))}
                </Collapse>
              ) : undefined}
            </>
          )
        })()
      : undefined

  const timeOptions: {label: string; value: string}[] = [
    {label: 'Past 5m', value: '-5m'},
    {label: 'Past 15m', value: '-15m'},
    {label: 'Past 1h', value: '-1h'},
    {label: 'Past 6h', value: '-6h'},
    {label: 'Past 1d', value: '-1d'},
    {label: 'Past 3d', value: '-3d'},
    {label: 'Past 7d', value: '-7d'},
    {label: 'Past 30d', value: '-30d'},
  ]

  const pageControls = (
    <>
      <Tooltip title="Choose device" placement="left">
        <Select
          showSearch
          value={deviceId}
          placeholder={'select device to show'}
          showArrow={true}
          filterOption={true}
          onChange={(key) => history.push(`/dashboard/${key}`)}
          style={{minWidth: 200, width: 350, marginRight: 10}}
          loading={!devices}
          disabled={!devices}
        >
          {devices &&
            devices.map(({deviceId}) => (
              <Select.Option key={deviceId} value={deviceId}>
                {deviceId}
              </Select.Option>
            ))}
        </Select>
      </Tooltip>

      <Tooltip title="Choose time" placement="left">
        <Select
          value={timeStart}
          onChange={setTimeStart}
          style={{minWidth: 100}}
          loading={loading}
          disabled={loading}
        >
          {timeOptions.map(({label, value}) => (
            <Select.Option key={value} value={value}>
              {label}
            </Select.Option>
          ))}
        </Select>
      </Tooltip>

      <Tooltip title="Reload Device Data">
        <Button
          disabled={loading}
          loading={loading}
          onClick={() => setDataStamp(dataStamp + 1)}
          style={{marginLeft: 10}}
          icon={<IconRefresh />}
        />
      </Tooltip>
      <Tooltip title="Go to device settings" placement="topRight">
        <Button
          type="primary"
          icon={<IconSettings />}
          style={{marginLeft: 10}}
          href={`/devices/${deviceId}`}
        ></Button>
      </Tooltip>
    </>
  )

  return (
    <PageContent
      title={
        <>
          Dashboard
          {isVirtualDevice ? (
            <Tooltip title="This page writes temperature measurements for the last 7 days from an emulated device, the temperature is reported every minute.">
              <InfoCircleFilled style={{fontSize: '1em', marginLeft: 5}} />
            </Tooltip>
          ) : undefined}
        </>
      }
      titleExtra={pageControls}
      message={message}
      spin={loading}
      forceShowScroll={true}
    >
      {deviceData?.measurementsTable?.length ? (
        <>
          {gauges}
          {plots}
        </>
      ) : (
        <Card>
          <Empty />
        </Card>
      )}
    </PageContent>
  )
}
Example #5
Source File: DevicePage.tsx    From iot-center-v2 with MIT License 4 votes vote down vote up
DevicePage: FunctionComponent<
  RouteComponentProps<PropsRoute> & Props
> = ({match, location, helpCollapsed, mqttEnabled}) => {
  const deviceId = match.params.deviceId ?? VIRTUAL_DEVICE
  const [loading, setLoading] = useState(true)
  const [message, setMessage] = useState<Message | undefined>()
  const [deviceData, setDeviceData] = useState<DeviceData | undefined>()
  const [dataStamp, setDataStamp] = useState(0)
  const [progress, setProgress] = useState(-1)
  const writeAllowed =
    deviceId === VIRTUAL_DEVICE ||
    new URLSearchParams(location.search).get('write') === 'true'

  const isVirtualDevice = deviceId === VIRTUAL_DEVICE

  // fetch device configuration and data
  useEffect(() => {
    const fetchData = async () => {
      setLoading(true)
      try {
        const deviceConfig = await fetchDeviceConfig(deviceId)
        setDeviceData(await fetchDeviceData(deviceConfig))
      } catch (e) {
        console.error(e)
        setMessage({
          title: 'Cannot load device data',
          description: String(e),
          type: 'error',
        })
      } finally {
        setLoading(false)
      }
    }

    fetchData()
  }, [dataStamp, deviceId])

  async function writeData() {
    const onProgress: ProgressFn = (percent /*, current, total */) => {
      // console.log(
      //   `writeData ${current}/${total} (${Math.trunc(percent * 100) / 100}%)`
      // );
      setProgress(percent)
    }
    try {
      if (!deviceData) return
      const missingDataTimeStamps = mqttEnabled
        ? await fetchDeviceMissingDataTimeStamps(deviceData.config)
        : undefined
      const count = await writeEmulatedData(
        deviceData,
        onProgress,
        missingDataTimeStamps
      )
      if (count) {
        notification.success({
          message: (
            <>
              <b>{count}</b> measurement point{count > 1 ? 's were' : ' was'}{' '}
              written to InfluxDB.
            </>
          ),
        })
        setDataStamp(dataStamp + 1) // reload device data
      } else {
        notification.info({
          message: `No new data were written to InfluxDB, the current measurement is already written.`,
        })
      }
    } catch (e) {
      console.error(e)
      setMessage({
        title: 'Cannot write data',
        description: String(e),
        type: 'error',
      })
    } finally {
      setProgress(-1)
    }
  }

  const writeButtonDisabled = progress !== -1 || loading
  const pageControls = (
    <>
      {writeAllowed ? (
        <Tooltip title="Write Missing Data for the last 7 days" placement="top">
          <Button
            type="primary"
            onClick={writeData}
            disabled={writeButtonDisabled}
            icon={<IconWriteData />}
          />
        </Tooltip>
      ) : undefined}
      <Tooltip title="Reload" placement="topRight">
        <Button
          disabled={loading}
          loading={loading}
          onClick={() => setDataStamp(dataStamp + 1)}
          icon={<IconRefresh />}
        />
      </Tooltip>
      <Tooltip title="Go to device realtime dashboard" placement="topRight">
        <Button
          type={mqttEnabled ? 'default' : 'ghost'}
          icon={<PlayCircleOutlined />}
          href={`/realtime/${deviceId}`}
        ></Button>
      </Tooltip>
      <Tooltip title="Go to device dashboard" placement="topRight">
        <Button
          icon={<IconDashboard />}
          href={`/dashboard/${deviceId}`}
        ></Button>
      </Tooltip>
    </>
  )

  const columnDefinitions: ColumnsType<measurementSummaryRow> = [
    {
      title: 'Field',
      dataIndex: '_field',
    },
    {
      title: 'min',
      dataIndex: 'minValue',
      render: (val: number) => +val.toFixed(2),
      align: 'right',
    },
    {
      title: 'max',
      dataIndex: 'maxValue',
      render: (val: number) => +val.toFixed(2),
      align: 'right',
    },
    {
      title: 'max time',
      dataIndex: 'maxTime',
    },
    {
      title: 'entry count',
      dataIndex: 'count',
      align: 'right',
    },
    {
      title: 'sensor',
      dataIndex: 'sensor',
    },
  ]

  return (
    <PageContent
      title={
        isVirtualDevice ? (
          <>
            {'Virtual Device'}
            <Tooltip title="This page writes temperature measurements for the last 7 days from an emulated device, the temperature is reported every minute.">
              <InfoCircleFilled style={{fontSize: '1em', marginLeft: 5}} />
            </Tooltip>
          </>
        ) : (
          `Device ${deviceId}`
        )
      }
      message={message}
      spin={loading}
      titleExtra={pageControls}
    >
      {deviceId === VIRTUAL_DEVICE ? (
        <>
          <div style={{visibility: progress >= 0 ? 'visible' : 'hidden'}}>
            <Progress
              percent={progress >= 0 ? Math.trunc(progress) : 0}
              strokeColor={COLOR_LINK}
            />
          </div>
        </>
      ) : undefined}
      <GridDescription
        title="Device Configuration"
        column={
          helpCollapsed ? {xxl: 3, xl: 2, md: 1, sm: 1} : {xxl: 2, md: 1, sm: 1}
        }
        descriptions={[
          {
            label: 'Device ID',
            value: deviceData?.config.id,
          },
          {
            label: 'Registration Time',
            value: deviceData?.config.createdAt,
          },
          {
            label: 'InfluxDB URL',
            value: deviceData?.config.influx_url,
          },
          {
            label: 'InfluxDB Organization',
            value: deviceData?.config.influx_org,
          },
          {
            label: 'InfluxDB Bucket',
            value: deviceData?.config.influx_bucket,
          },
          {
            label: 'InfluxDB Token',
            value: deviceData?.config.influx_token ? '***' : 'N/A',
          },
          ...(mqttEnabled
            ? [
                {
                  label: 'Mqtt URL',
                  value: deviceData?.config?.mqtt_url,
                },
                {
                  label: 'Mqtt topic',
                  value: deviceData?.config?.mqtt_topic,
                },
              ]
            : []),
          {
            label: 'Device type',
            value: (
              <InputConfirm
                value={deviceData?.config?.device}
                tooltip={'Device type is used for dynamic dashboard filtering'}
                onValueChange={async (newValue) => {
                  try {
                    await fetchSetDeviceType(deviceId, newValue)
                    setDataStamp(dataStamp + 1)
                  } catch (e) {
                    console.error(e)
                    setMessage({
                      title: 'Cannot load device data',
                      description: String(e),
                      type: 'error',
                    })
                  }
                }}
              />
            ),
          },
        ]}
      />
      <Title>Measurements</Title>
      <Table
        dataSource={deviceData?.measurements}
        columns={columnDefinitions}
        pagination={false}
        rowKey={measurementTableRowKey}
      />
      <div style={{height: 20}} />
      {isVirtualDevice && mqttEnabled ? (
        <RealTimeSettings onBeforeStart={writeData} />
      ) : undefined}
    </PageContent>
  )
}
Example #6
Source File: RealTimePage.tsx    From iot-center-v2 with MIT License 4 votes vote down vote up
RealTimePage: FunctionComponent<
  RouteComponentProps<PropsRoute> & Props
> = ({match, history, helpCollapsed, mqttEnabled}) => {
  const deviceId = match.params.deviceId ?? VIRTUAL_DEVICE
  // loading is defaultly false because we don't load data when page load.
  const [loading, setLoading] = useState(false)
  const [message, setMessage] = useState<Message | undefined>()
  const [deviceData, setDeviceData] = useState<DeviceData | undefined>()
  const [dataStamp, setDataStamp] = useState(0)
  const [devices, setDevices] = useState<DeviceInfo[] | undefined>(undefined)
  const [timeStart, setTimeStart] = useState(timeOptionsRealtime[0].value)

  const manager = useRef(new DataManager()).current

  // resetXDomain removed, doesn't make sense to zoom plot in realtime

  const isVirtualDevice = deviceId === VIRTUAL_DEVICE
  const measurementsTable = deviceData?.measurementsTable

  // unlike before, data don't have to be in react state.

  // #region realtime

  const isRealtime = getIsRealtime(timeStart)

  // Default time selected to Past when mqtt not configured
  useEffect(() => {
    if (mqttEnabled === false) {
      setTimeStart(timeOptions[0].value)
    }
  }, [mqttEnabled])

  const [subscriptions, setSubscriptions] = useState<RealtimeSubscription[]>([])

  /** plot is showed with fixed time range if set */
  const retentionTimeMs = isRealtime
    ? timeOptionsRealtime[
        timeOptionsRealtime.findIndex((x) => x.value === timeStart)
      ].realtimeRetention
    : Infinity

  useEffect(() => {
    manager.retentionTimeMs = retentionTimeMs
  }, [retentionTimeMs, manager])

  useEffect(() => {
    setSubscriptions(
      isRealtime
        ? [{measurement: 'environment', tags: [`clientId=${deviceId}`]}]
        : []
    )
  }, [deviceId, isRealtime])

  /** Push data to manager */
  const updateData = useRef((points: DiagramEntryPoint[] | undefined) => {
    if (points?.length) manager.updateData(points)
  }).current

  /** Clear data in manager */
  const clearData = useRef(() => {
    manager.updateData(undefined)
  }).current

  useRealtimeData(
    subscriptions,
    useRef((points: RealtimePoint[]) => {
      updateData(realtimePointToDiagrameEntryPoint(points))
    }).current
  )

  useEffect(() => {
    if (isRealtime) clearData()
  }, [isRealtime, clearData])
  useEffect(clearData, [deviceId, clearData])

  // On measurementsTable is changed, we render it in plots
  useEffect(() => {
    updateData(giraffeTableToDiagramEntryPoints(measurementsTable, fieldsAll))
  }, [measurementsTable, updateData, clearData])

  // #endregion realtime

  // fetch device configuration and data
  useEffect(() => {
    // we don't use fetchDeviceLastValues
    //   Gauge plots will handle last walue selection for us

    const fetchData = async () => {
      setLoading(true)
      clearData()
      try {
        const config = await fetchDeviceConfig(deviceId)
        const deviceData: DeviceData = {config}
        const [table] = await Promise.all([
          fetchDeviceMeasurements(config, timeStart),
        ])
        deviceData.measurementsTable = table
        setDeviceData(deviceData)
      } catch (e) {
        console.error(e)
        setMessage({
          title: 'Cannot load device data',
          description: String(e),
          type: 'error',
        })
      }
      setLoading(false)
    }

    // fetch data only if not in realtime mode
    if (!isRealtime) fetchData()
  }, [dataStamp, deviceId, timeStart, isRealtime, clearData])

  useEffect(() => {
    const fetchDevices = async () => {
      try {
        const response = await fetch('/api/devices')
        if (response.status >= 300) {
          const text = await response.text()
          throw new Error(`${response.status} ${text}`)
        }
        const data = await response.json()
        setDevices(data)
      } catch (e) {
        setMessage({
          title: 'Cannot fetch data',
          description: String(e),
          type: 'error',
        })
      }
    }

    fetchDevices()
  }, [])

  /*
    Rendering plots with minilibrary written in util/realtime/
    This time, data isn't pass by state but by calling callback (got by onUpdaterChange) 
    which allows us to update plot more frequently with better performance.
    All plots has to be rendered whole time because we need to have updater function from it. (so we use display 'none' instead of conditional rendering)
  */
  const renderGauge = (column: string) => (
    <ManagedComponentReact
      component={ManagedG2Plot}
      keys={column}
      props={{ctor: Gauge, options: gaugesPlotOptions[column]}}
    />
  )

  // gaugeLastTimeMessage not implemented

  const gauges = (
    <Row gutter={[22, 22]}>
      {fields.map((column, i) => {
        return (
          <Col
            sm={helpCollapsed ? 24 : 24}
            md={helpCollapsed ? 12 : 24}
            xl={helpCollapsed ? 6 : 12}
            key={i}
          >
            <Card title={column}>{renderGauge(column)}</Card>
          </Col>
        )
      })}
    </Row>
  )

  const plotDivider = (
    <Divider style={{color: 'rgba(0, 0, 0, .2)'}} orientation="right"></Divider>
  )

  const geo = (
    <div
      style={{
        height: '500px',
        minWidth: '200px',
      }}
    >
      <ManagedComponentReact
        component={ManagedMap}
        keys={['Lat', 'Lon']}
        props={{}}
      />
    </div>
  )

  const renderPlot = (column: string) => (
    <ManagedComponentReact
      component={ManagedG2Plot}
      keys={column}
      props={{ctor: Line, options: linePlotOptions[column]}}
    />
  )

  const plots = (() => {
    return (
      <>
        <Row gutter={[0, 24]}>
          {fields.map((field, i) => (
            <Col xs={24} key={i}>
              <Collapse defaultActiveKey={[i]}>
                <CollapsePanel key={i} header={field}>
                  {renderPlot(field)}
                </CollapsePanel>
              </Collapse>
            </Col>
          ))}
        </Row>
      </>
    )
  })()

  const pageControls = (
    <>
      <Tooltip title="Choose device" placement="left">
        <Select
          showSearch
          value={deviceId}
          placeholder={'select device to show'}
          showArrow={true}
          filterOption={true}
          // goes to realtime page (instead of dashboard)
          onChange={(key) => history.push(`/realtime/${key}`)}
          style={{minWidth: 200, width: 350, marginRight: 10}}
          loading={!devices}
          disabled={!devices}
        >
          {devices &&
            devices.map(({deviceId}) => (
              <Select.Option key={deviceId} value={deviceId}>
                {deviceId}
              </Select.Option>
            ))}
        </Select>
      </Tooltip>

      <Tooltip
        title={
          (mqttEnabled === false ? 'MQTT not configured on server! ' : '') +
          'Choose time'
        }
        placement="left"
      >
        <Select
          value={timeStart}
          onChange={setTimeStart}
          style={{minWidth: 100}}
          loading={loading || mqttEnabled === undefined}
          disabled={loading}
        >
          {timeOptionsRealtime.map(({label, value}) => (
            <Select.Option
              disabled={mqttEnabled === false}
              key={value}
              value={value}
            >
              {label}
            </Select.Option>
          ))}
          {timeOptions.map(({label, value}) => (
            <Select.Option key={value} value={value}>
              {label}
            </Select.Option>
          ))}
        </Select>
      </Tooltip>

      <Tooltip title="Reload Device Data">
        <Button
          // disable refresh when in realtime mode
          disabled={loading || isRealtime}
          loading={loading}
          onClick={() => setDataStamp(dataStamp + 1)}
          style={{marginLeft: 10}}
          icon={<IconRefresh />}
        />
      </Tooltip>

      <Tooltip title="Go to device settings" placement="topRight">
        <Button
          type="primary"
          icon={<IconSettings />}
          style={{marginLeft: 10}}
          href={`/devices/${deviceId}`}
        ></Button>
      </Tooltip>
    </>
  )

  return (
    <PageContent
      title={
        <>
          Realtime Dashboard
          {isVirtualDevice ? (
            <Tooltip title="This page is based on Dashboard page, it has two modes: past and live. Past data are received from influxdb and live data are sent directly from device by mqtt">
              <InfoCircleFilled style={{fontSize: '1em', marginLeft: 5}} />
            </Tooltip>
          ) : undefined}
        </>
      }
      titleExtra={pageControls}
      message={message}
      spin={loading}
      forceShowScroll={true}
    >
      <DataManagerContextProvider value={manager}>
        {true ? (
          <>
            {gauges}
            {plotDivider}
            {geo}
            {plots}
          </>
        ) : (
          <Card>
            <Empty />
          </Card>
        )}
      </DataManagerContextProvider>
    </PageContent>
  )
}
Example #7
Source File: BrickAlert.tsx    From next-basics with GNU General Public License v3.0 4 votes vote down vote up
export function BrickAlert(props: BrickAlertProps): React.ReactElement {
  const [show, setShow] = React.useState<boolean>(false);
  const theme = useCurrentTheme();
  const onClose = () => {
    props.onClose?.();
  };
  // istanbul ignore next
  const message = props.enableMessageSlot ? (
    <>
      {props.foldDesc ? (
        <>
          <span style={{ ...props.messageStyle }}>
            <slot name="message"></slot>
          </span>
          <span
            onClick={() => {
              setShow(!show);
            }}
            style={{
              marginLeft: "5px",
              color: "var(--bg-color-button-link)",
              cursor: "pointer",
            }}
          >
            <span style={{ ...props.messageStyle }}>
              {props.foldDescLabel ?? "故障排查"}
            </span>
            <UpOutlined
              rotate={show ? 0 : 180}
              style={{ marginLeft: "4px", lineHeight: "0px", fontSize: "12px" }}
            />
          </span>
        </>
      ) : (
        <div>
          <slot name="message"></slot>
        </div>
      )}
    </>
  ) : (
    <span style={{ ...props.messageStyle }}>{props.message}</span>
  );
  const action = props.enableActionSlot ? (
    <div>
      <slot name="action"></slot>
    </div>
  ) : null;

  let desc = props.enableDescSlot ? (
    <div>
      <slot name="description"></slot>
    </div>
  ) : (
    props.description
  );
  if (props.foldDesc) {
    desc = <div style={{ display: show ? "block" : "none" }}>{desc}</div>;
  }

  const text =
    props.closeOnce && props.closable ? (
      <span style={{ color: "var(--text-color-link)" }}>
        不再提示 <CloseOutlined style={{ color: "var(--text-color-link)" }} />
      </span>
    ) : (
      ""
    );
  // istanbul ignore next

  const getThemeIcon = useCallback(
    (
      lightIcon: React.ReactElement,
      darkIcon: React.ReactElement
    ): React.ReactElement => {
      return theme == "dark-v2" ? darkIcon : lightIcon;
    },
    [theme]
  );
  const customIcon = () => {
    let icon: React.ReactNode;
    let iconRender: any;
    if (props.iconSize === "big") {
      switch (props.type) {
        case "info":
          iconRender = getThemeIcon(
            <BigInfoCircleOutlined />,
            <BigInfoCircleOutlinedDark />
          );
          break;
        case "success":
          iconRender = getThemeIcon(
            <BigSuccessCircleOutlined />,
            <BigSuccessCircleOutlinedDark />
          );
          break;
        case "warning":
          iconRender = getThemeIcon(
            <BigWarningCircleOutlined />,
            <BigWarningCircleOutlinedDark />
          );
          break;
        case "error":
          iconRender = getThemeIcon(
            <BigErrorCircleOutlined />,
            <BigErrorCircleOutlinedDark />
          );
          break;
      }
      icon = <Icon component={() => iconRender} />;
    }
    if (props.iconSize === "small") {
      const iconStyle: CSSProperties = { position: "relative", top: "5px" };
      const componentStyrle: CSSProperties = { fontSize: "14px" };
      switch (props.type) {
        case "info":
          iconRender = <InfoCircleFilled style={componentStyrle} />;
          break;
        case "success":
          iconRender = <CheckCircleFilled style={componentStyrle} />;
          break;
        case "warning":
          iconRender = <ExclamationCircleFilled style={componentStyrle} />;
          break;
        case "error":
          iconRender = <CloseCircleFilled style={componentStyrle} />;
          break;
      }
      icon = <Icon style={iconStyle} component={() => iconRender} />;
    }
    return icon;
  };
  return (
    <Alert
      className={classnames(
        {
          [cssStyle.closeOnce]: props.closeOnce && props.closable,
        },
        props.noBorderRadio ? cssStyle.noBorderRadio : null
      )}
      type={props.type}
      message={message}
      showIcon={props.showIcon}
      closable={props.closable}
      onClose={onClose}
      description={desc}
      closeText={text}
      action={action}
      {...(customIcon() ? { icon: customIcon() } : {})}
    />
  );
}