prometheus

Форк
0
131 строка · 4.2 Кб
1
import React, { ChangeEvent, FC, useState } from 'react';
2
import { Input, InputGroup, Table } from 'reactstrap';
3
import { withStatusIndicator } from '../../components/withStatusIndicator';
4
import { useFetch } from '../../hooks/useFetch';
5
import { usePathPrefix } from '../../contexts/PathPrefixContext';
6
import { API_PATH } from '../../constants/constants';
7
import { faSort, faSortDown, faSortUp } from '@fortawesome/free-solid-svg-icons';
8
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
9
import { IconDefinition } from '@fortawesome/fontawesome-common-types';
10
import sanitizeHTML from 'sanitize-html';
11
import { Fuzzy, FuzzyResult } from '@nexucis/fuzzy';
12

13
const fuz = new Fuzzy({ pre: '<strong>', post: '</strong>', shouldSort: true });
14
const flagSeparator = '||';
15

16
interface FlagMap {
17
  [key: string]: string;
18
}
19

20
interface FlagsProps {
21
  data?: FlagMap;
22
}
23

24
const compareAlphaFn =
25
  (keys: boolean, reverse: boolean) =>
26
  ([k1, v1]: [string, string], [k2, v2]: [string, string]): number => {
27
    const a = keys ? k1 : v1;
28
    const b = keys ? k2 : v2;
29
    const reverser = reverse ? -1 : 1;
30
    return reverser * a.localeCompare(b);
31
  };
32

33
const getSortIcon = (b: boolean | undefined): IconDefinition => {
34
  if (b === undefined) {
35
    return faSort;
36
  }
37
  if (b) {
38
    return faSortDown;
39
  }
40
  return faSortUp;
41
};
42

43
interface SortState {
44
  name: string;
45
  alpha: boolean;
46
  focused: boolean;
47
}
48

49
export const FlagsContent: FC<FlagsProps> = ({ data = {} }) => {
50
  const initialSearch = '';
51
  const [searchState, setSearchState] = useState(initialSearch);
52
  const initialSort: SortState = {
53
    name: 'Flag',
54
    alpha: true,
55
    focused: true,
56
  };
57
  const [sortState, setSortState] = useState(initialSort);
58
  const searchable = Object.entries(data)
59
    .sort(compareAlphaFn(sortState.name === 'Flag', !sortState.alpha))
60
    .map(([flag, value]) => `--${flag}${flagSeparator}${value}`);
61
  let filtered = searchable;
62
  if (searchState.length > 0) {
63
    filtered = fuz.filter(searchState, searchable).map((value: FuzzyResult) => value.rendered);
64
  }
65
  return (
66
    <>
67
      <h2>Command-Line Flags</h2>
68
      <InputGroup>
69
        <Input
70
          autoFocus
71
          placeholder="Filter by flag name or value..."
72
          className="my-3"
73
          value={searchState}
74
          onChange={({ target }: ChangeEvent<HTMLInputElement>): void => {
75
            setSearchState(target.value);
76
          }}
77
        />
78
      </InputGroup>
79
      <Table bordered size="sm" striped hover>
80
        <thead>
81
          <tr>
82
            {['Flag', 'Value'].map((col: string) => (
83
              <td
84
                key={col}
85
                className={`px-4 ${col}`}
86
                style={{ width: '50%' }}
87
                onClick={(): void =>
88
                  setSortState({
89
                    name: col,
90
                    focused: true,
91
                    alpha: sortState.name === col ? !sortState.alpha : true,
92
                  })
93
                }
94
              >
95
                <span className="mr-2">{col}</span>
96
                <FontAwesomeIcon icon={getSortIcon(sortState.name !== col ? undefined : sortState.alpha)} />
97
              </td>
98
            ))}
99
          </tr>
100
        </thead>
101
        <tbody>
102
          {filtered.map((result: string) => {
103
            const [flagMatchStr, valueMatchStr] = result.split(flagSeparator);
104
            const sanitizeOpts = { allowedTags: ['strong'] };
105
            return (
106
              <tr key={flagMatchStr}>
107
                <td className="flag-item">
108
                  <span dangerouslySetInnerHTML={{ __html: sanitizeHTML(flagMatchStr, sanitizeOpts) }} />
109
                </td>
110
                <td className="flag-value">
111
                  <span dangerouslySetInnerHTML={{ __html: sanitizeHTML(valueMatchStr, sanitizeOpts) }} />
112
                </td>
113
              </tr>
114
            );
115
          })}
116
        </tbody>
117
      </Table>
118
    </>
119
  );
120
};
121
const FlagsWithStatusIndicator = withStatusIndicator(FlagsContent);
122

123
FlagsContent.displayName = 'Flags';
124

125
const Flags: FC = () => {
126
  const pathPrefix = usePathPrefix();
127
  const { response, error, isLoading } = useFetch<FlagMap>(`${pathPrefix}/${API_PATH}/status/flags`);
128
  return <FlagsWithStatusIndicator data={response.data} error={error} isLoading={isLoading} />;
129
};
130

131
export default Flags;
132

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.