Skip to content

Commit 9fed494

Browse files
app/vmui: vmalert ui for logs
1 parent aa5b74c commit 9fed494

File tree

43 files changed

+1938
-38
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+1938
-38
lines changed

app/vmui/packages/vmui/src/App.tsx

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@ import AppContextProvider from "./contexts/AppContextProvider";
44
import ThemeProvider from "./components/Main/ThemeProvider/ThemeProvider";
55
import ExploreLogs from "./pages/ExploreLogs/ExploreLogs";
66
import LogsLayout from "./layouts/LogsLayout/LogsLayout";
7+
import ExploreRules from "./pages/ExploreAlerts/ExploreRules";
8+
import ExploreNotifiers from "./pages/ExploreAlerts/ExploreNotifiers";
79
import "./constants/markedPlugins";
10+
import router from "./router";
811

912
const App: FC = () => {
1013
const [loadedTheme, setLoadedTheme] = useState(false);
@@ -24,6 +27,22 @@ const App: FC = () => {
2427
path={"/"}
2528
element={<ExploreLogs/>}
2629
/>
30+
<Route
31+
path={router.rules}
32+
element={<ExploreRules
33+
ruleTypeFilter=""
34+
/>}
35+
/>
36+
<Route
37+
path={router.alerts}
38+
element={<ExploreRules
39+
ruleTypeFilter="alert"
40+
/>}
41+
/>
42+
<Route
43+
path={router.notifiers}
44+
element={<ExploreNotifiers/>}
45+
/>
2746
</Route>
2847
</Routes>
2948
)}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
export const getGroupsUrl = (server: string, ruleType: string): string => {
2+
let groupUrl = `${server}/api/v1/rules`;
3+
if (ruleType) {
4+
groupUrl = `${groupUrl}?type=${ruleType}`;
5+
}
6+
return groupUrl;
7+
};
8+
9+
export const getNotifiersUrl = (server: string): string => {
10+
return `${server}/api/v1/notifiers`;
11+
};
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import { FC } from "preact/compat";
2+
import "./style.scss";
3+
import useDeviceDetect from "../../../hooks/useDeviceDetect";
4+
import { Group as APIGroup } from "../../../types";
5+
import useCopyToClipboard from "../../../hooks/useCopyToClipboard";
6+
import { CopyIcon } from "../../../components/Main/Icons";
7+
import Button from "../../../components/Main/Button/Button";
8+
9+
interface GroupHeaderControlsProps {
10+
group: APIGroup,
11+
}
12+
13+
const GroupHeaderHeader: FC<GroupHeaderControlsProps> = ({
14+
group,
15+
}) => {
16+
const { isMobile } = useDeviceDetect();
17+
const copyToClipboard = useCopyToClipboard();
18+
19+
const handlerCopy = async () => {
20+
const link = `${window.location.origin}${window.location.pathname}#/groups#group-${group.id}`;
21+
await copyToClipboard(link, "Link to group has been copied");
22+
};
23+
24+
if (isMobile) {
25+
return (
26+
<div className="vm-explore-alerts-group-header vm-explore-alerts-group-header_mobile">
27+
<div className="vm-explore-alerts-group-header__name">{group.name}</div>
28+
<div className="circle-container">
29+
{Object.entries(group.states || {}).map(([name, value]) => (
30+
<div
31+
key={name}
32+
className={`circle ${name.toLowerCase().replace(" ", "-")}`}
33+
>{value}</div>
34+
))}
35+
<Button
36+
variant="outlined"
37+
startIcon={<CopyIcon/>}
38+
onClick={handlerCopy}
39+
/>
40+
</div>
41+
</div>
42+
);
43+
}
44+
45+
return (
46+
<div className="vm-explore-alerts-group-header">
47+
<div className="vm-explore-alerts-group-header__desc">
48+
<div className="vm-explore-alerts-group-header__name">{group.name}</div>
49+
<div className="vm-explore-alerts-group-header__file">{group.file}</div>
50+
</div>
51+
<div className="circle-container">
52+
{Object.entries(group.states || {}).map(([name, value]) => (
53+
<div
54+
key={name}
55+
className={`circle ${name.toLowerCase().replace(" ", "-")}`}
56+
>{value}</div>
57+
))}
58+
<Button
59+
variant="outlined"
60+
startIcon={<CopyIcon/>}
61+
onClick={handlerCopy}
62+
/>
63+
</div>
64+
</div>
65+
);
66+
};
67+
68+
export default GroupHeaderHeader;
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
@use "src/styles/variables" as *;
2+
3+
.vm-explore-alerts-group-header {
4+
display: flex;
5+
align-items: center;
6+
padding: $padding-global;
7+
justify-content: space-between;
8+
padding-right: 50px;
9+
10+
&_mobile {
11+
padding: $padding-small $padding-global;
12+
padding-right: 35px;
13+
}
14+
15+
&__desc {
16+
display: flex;
17+
flex-direction: column;
18+
gap: $padding-global;
19+
}
20+
21+
&__index {
22+
color: $color-text-secondary;
23+
font-size: $font-size-small;
24+
}
25+
26+
&__name {
27+
flex-grow: 1;
28+
font-weight: bold;
29+
max-width: 100%;
30+
text-overflow: ellipsis;
31+
overflow: hidden;
32+
line-height: 130%;
33+
word-break: break-word;
34+
}
35+
36+
&__file {
37+
color: $color-text-disabled;
38+
}
39+
40+
code {
41+
padding: 0.2em 0.4em;
42+
font-size: 85%;
43+
background-color: $color-hover-black;
44+
border-radius: 6px;
45+
}
46+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import { FC } from "preact/compat";
2+
import "./style.scss";
3+
import { Target as APITarget } from "../../../types";
4+
5+
interface NotifierProps {
6+
targets: APITarget[]
7+
}
8+
9+
const Notifier: FC<NotifierProps> = ({
10+
targets,
11+
}) => {
12+
13+
return (
14+
<div className="vm-explore-alerts-notifier">
15+
<table>
16+
<thead>
17+
<tr>
18+
<th className="vm-col-small">Address</th>
19+
<th>Labels</th>
20+
</tr>
21+
</thead>
22+
<tbody>
23+
{targets.map(target => (
24+
<tr key={target.address}>
25+
<td className="vm-col-small">{target.address}</td>
26+
<td className="vm-badge-container">
27+
{Object.entries(target.labels || {}).map(([name, value]) => (
28+
<span
29+
className="vm-badge"
30+
key={name}
31+
>{`${name}: ${value}`}</span>
32+
))}
33+
</td>
34+
</tr>
35+
))}
36+
</tbody>
37+
</table>
38+
</div>
39+
);
40+
};
41+
42+
export default Notifier;
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
@use "src/styles/variables" as *;
2+
3+
.vm-explore-alerts-notifier {
4+
row-gap: $padding-global;
5+
margin-right: $padding-global;
6+
display: flex;
7+
flex-direction: column;
8+
9+
.vm-col-small {
10+
width: 40%;
11+
text-align: left;
12+
overflow: hidden;
13+
text-overflow: ellipsis;
14+
}
15+
16+
table {
17+
width: 100%;
18+
table-layout: fixed;
19+
td {
20+
padding: $padding-global $padding-small;
21+
}
22+
th {
23+
font-weight: bold;
24+
text-align: center;
25+
padding: 0 $padding-small;
26+
}
27+
}
28+
29+
.vm-badge-container {
30+
display: flex;
31+
flex-wrap: wrap;
32+
gap: $padding-small;
33+
}
34+
35+
.vm-badge {
36+
padding: $padding-small;
37+
border-radius: $border-radius-small;
38+
background-color: $color-hover-black;
39+
max-width: 300px;
40+
overflow: hidden;
41+
white-space: nowrap;
42+
text-overflow: ellipsis;
43+
width: fit-content;
44+
45+
&:is(.firing) {
46+
background: $color-error;
47+
color: $color-white;
48+
}
49+
50+
&:is(.pending) {
51+
background: $color-warning;
52+
color: $color-white;
53+
}
54+
}
55+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { FC } from "preact/compat";
2+
import "./style.scss";
3+
import useDeviceDetect from "../../../hooks/useDeviceDetect";
4+
import { Notifier } from "../../../types";
5+
import classNames from "classnames";
6+
7+
interface NotifierHeaderControlsProps {
8+
notifier: Notifier
9+
}
10+
11+
const NotifierHeaderHeader: FC<NotifierHeaderControlsProps> = ({
12+
notifier,
13+
}) => {
14+
const { isMobile } = useDeviceDetect();
15+
16+
return (
17+
<div
18+
className={classNames({
19+
"vm-explore-alerts-notifier-header": true,
20+
"vm-explore-alerts-notifier-header_mobile": isMobile
21+
})}
22+
>
23+
<div className="vm-explore-alerts-notifier-header__name">{notifier.kind}</div>
24+
</div>
25+
);
26+
};
27+
28+
export default NotifierHeaderHeader;
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
@use "src/styles/variables" as *;
2+
3+
.vm-explore-alerts-notifier-header {
4+
display: flex;
5+
grid-template-columns: auto 1fr auto auto;
6+
align-items: center;
7+
padding: $padding-global;
8+
justify-content: space-between;
9+
gap: $padding-global;
10+
padding-right: 50px;
11+
12+
&_mobile {
13+
grid-template-columns: 1fr auto;
14+
padding: $padding-small $padding-global;
15+
}
16+
17+
&__index {
18+
color: $color-text-secondary;
19+
font-size: $font-size-small;
20+
}
21+
22+
&__name {
23+
flex-grow: 1;
24+
font-weight: bold;
25+
max-width: 100%;
26+
text-overflow: ellipsis;
27+
overflow: hidden;
28+
line-height: 130%;
29+
}
30+
31+
&__file {
32+
color: $color-text-disabled;
33+
}
34+
35+
code {
36+
padding: 0.2em 0.4em;
37+
font-size: 85%;
38+
background-color: $color-hover-black;
39+
border-radius: 6px;
40+
}
41+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import { FC } from "preact/compat";
2+
import Select from "../../Main/Select/Select";
3+
import { SearchIcon } from "../../Main/Icons";
4+
import TextField from "../../Main/TextField/TextField";
5+
import "./style.scss";
6+
import classNames from "classnames";
7+
import useDeviceDetect from "../../../hooks/useDeviceDetect";
8+
9+
interface NotifiersHeaderProps {
10+
kinds: string[]
11+
allKinds: string[]
12+
onChangeKinds: (input: string) => void
13+
onChangeSearch: (input: string) => void
14+
}
15+
16+
const NotifiersHeader: FC<NotifiersHeaderProps> = ({
17+
kinds,
18+
allKinds,
19+
onChangeKinds,
20+
onChangeSearch,
21+
}) => {
22+
const { isMobile } = useDeviceDetect();
23+
24+
return (
25+
<>
26+
<div
27+
className={classNames({
28+
"vm-explore-alerts-header": true,
29+
"vm-explore-alerts-header_mobile": isMobile,
30+
"vm-block": true,
31+
"vm-block_mobile": isMobile,
32+
})}
33+
>
34+
<div className="vm-explore-alerts-header__rule_type">
35+
<Select
36+
value={kinds}
37+
list={allKinds}
38+
label="Notifier type"
39+
placeholder="Please select notifier type"
40+
onChange={onChangeKinds}
41+
autofocus={!!kinds.length && !isMobile}
42+
includeAll
43+
searchable
44+
/>
45+
</div>
46+
<div className="vm-explore-alerts-header-search">
47+
<TextField
48+
label="Search"
49+
placeholder="Fitler by kind, address or labels"
50+
startIcon={<SearchIcon/>}
51+
onChange={onChangeSearch}
52+
/>
53+
</div>
54+
</div>
55+
</>
56+
);
57+
};
58+
59+
export default NotifiersHeader;

0 commit comments

Comments
 (0)