github.com/thanos-io/thanos@v0.32.5/pkg/ui/react-app/src/thanos/pages/blocks/BlockDetails.tsx (about)

     1  import React, { FC, useState } from 'react';
     2  import { Block } from './block';
     3  import styles from './blocks.module.css';
     4  import moment from 'moment';
     5  import { Button, Modal, ModalBody, Form, Input, ModalHeader, ModalFooter } from 'reactstrap';
     6  import { download } from './helpers';
     7  
     8  export interface BlockDetailsProps {
     9    block: Block | undefined;
    10    selectBlock: React.Dispatch<React.SetStateAction<Block | undefined>>;
    11  }
    12  
    13  export const BlockDetails: FC<BlockDetailsProps> = ({ block, selectBlock }) => {
    14    const [modalAction, setModalAction] = useState<string>('');
    15    const [detailValue, setDetailValue] = useState<string | null>(null);
    16  
    17    const submitMarkBlock = async (action: string, ulid: string, detail: string | null) => {
    18      try {
    19        const body = detail
    20          ? new URLSearchParams({
    21              id: ulid,
    22              action,
    23              detail,
    24            })
    25          : new URLSearchParams({
    26              id: ulid,
    27              action,
    28            });
    29  
    30        const response = await fetch('/api/v1/blocks/mark', {
    31          method: 'POST',
    32          body,
    33        });
    34  
    35        if (!response.ok) {
    36          throw new Error(response.statusText);
    37        }
    38      } finally {
    39        setModalAction('');
    40      }
    41    };
    42  
    43    return (
    44      <div className={`${styles.blockDetails} ${block && styles.open}`}>
    45        {block && (
    46          <>
    47            <div className={styles.detailsTop}>
    48              <span className={styles.header} data-testid="ulid">
    49                {block.ulid}
    50              </span>
    51              <button className={styles.closeBtn} onClick={(): void => selectBlock(undefined)}>
    52                &times;
    53              </button>
    54            </div>
    55            <hr />
    56            <div data-testid="start-time">
    57              <b>Start Time:</b> <span>{moment.unix(block.minTime / 1000).format('LLL')}</span>
    58            </div>
    59            <div data-testid="end-time">
    60              <b>End Time:</b> <span>{moment.unix(block.maxTime / 1000).format('LLL')}</span>
    61            </div>
    62            <div data-testid="duration">
    63              <b>Duration:</b> <span>{moment.duration(block.maxTime - block.minTime, 'ms').humanize()}</span>
    64            </div>
    65            <hr />
    66            <div data-testid="series">
    67              <b>Series:</b> <span>{block.stats.numSeries}</span>
    68            </div>
    69            <div data-testid="samples">
    70              <b>Samples:</b> <span>{block.stats.numSamples}</span>
    71            </div>
    72            <div data-testid="chunks">
    73              <b>Chunks:</b> <span>{block.stats.numChunks}</span>
    74            </div>
    75            <hr />
    76            <div data-testid="resolution">
    77              <b>Resolution:</b> <span>{block.thanos.downsample.resolution}</span>
    78            </div>
    79            <div data-testid="level">
    80              <b>Level:</b> <span>{block.compaction.level}</span>
    81            </div>
    82            <div data-testid="source">
    83              <b>Source:</b> <span>{block.thanos.source}</span>
    84            </div>
    85            <hr />
    86            <div data-testid="labels">
    87              <b>Labels:</b>
    88              <ul>
    89                {Object.entries(block.thanos.labels).map(([key, value]) => (
    90                  <li key={key}>
    91                    <b>{key}: </b>
    92                    {value}
    93                  </li>
    94                ))}
    95              </ul>
    96            </div>
    97            <hr />
    98            <div data-testid="download">
    99              <a href={download(block)} download="meta.json">
   100                <Button>Download meta.json</Button>
   101              </a>
   102            </div>
   103            <div style={{ marginTop: '12px' }}>
   104              <Button
   105                onClick={() => {
   106                  setModalAction('DELETION');
   107                  setDetailValue('');
   108                }}
   109              >
   110                Mark Deletion
   111              </Button>
   112            </div>
   113            <div style={{ marginTop: '12px' }}>
   114              <Button
   115                onClick={() => {
   116                  setModalAction('NO_COMPACTION');
   117                  setDetailValue('');
   118                }}
   119              >
   120                Mark No Compaction
   121              </Button>
   122            </div>
   123            <Modal isOpen={!!modalAction}>
   124              <ModalBody>
   125                <ModalHeader toggle={() => setModalAction('')}>
   126                  Mark {modalAction === 'DELETION' ? 'Deletion' : 'No Compaction'} Detail (Optional)
   127                </ModalHeader>
   128                <Form
   129                  onSubmit={(e) => {
   130                    e.preventDefault();
   131                    submitMarkBlock(modalAction, block.ulid, detailValue);
   132                  }}
   133                >
   134                  <Input
   135                    placeholder="Reason for marking block..."
   136                    style={{ marginBottom: '16px', marginTop: '16px' }}
   137                    onChange={(e) => setDetailValue(e.target.value)}
   138                  />
   139                  <ModalFooter>
   140                    <Button color="primary" type="submit">
   141                      Submit
   142                    </Button>
   143                  </ModalFooter>
   144                </Form>
   145              </ModalBody>
   146            </Modal>
   147          </>
   148        )}
   149      </div>
   150    );
   151  };