diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/assets/app.scss | 1 | ||||
-rw-r--r-- | src/assets/defaults.yml | 2 | ||||
-rw-r--r-- | src/components/services/Prometheus.vue | 143 |
3 files changed, 146 insertions, 0 deletions
diff --git a/src/assets/app.scss b/src/assets/app.scss index f2dfb37..c709282 100644 --- a/src/assets/app.scss +++ b/src/assets/app.scss | |||
@@ -31,6 +31,7 @@ body { | |||
31 | transition: background-color cubic-bezier(0.165, 0.84, 0.44, 1) 300ms; | 31 | transition: background-color cubic-bezier(0.165, 0.84, 0.44, 1) 300ms; |
32 | 32 | ||
33 | a { | 33 | a { |
34 | color: var(--link); | ||
34 | &:hover { | 35 | &:hover { |
35 | color: var(--link-hover); | 36 | color: var(--link-hover); |
36 | } | 37 | } |
diff --git a/src/assets/defaults.yml b/src/assets/defaults.yml index ae4f523..ed1fbc9 100644 --- a/src/assets/defaults.yml +++ b/src/assets/defaults.yml | |||
@@ -23,6 +23,7 @@ colors: | |||
23 | text-title: "#303030" | 23 | text-title: "#303030" |
24 | text-subtitle: "#424242" | 24 | text-subtitle: "#424242" |
25 | card-shadow: rgba(0, 0, 0, 0.1) | 25 | card-shadow: rgba(0, 0, 0, 0.1) |
26 | link: "#3273dc" | ||
26 | link-hover: "#363636" | 27 | link-hover: "#363636" |
27 | background-image: "" | 28 | background-image: "" |
28 | dark: | 29 | dark: |
@@ -36,6 +37,7 @@ colors: | |||
36 | text-title: "#fafafa" | 37 | text-title: "#fafafa" |
37 | text-subtitle: "#f5f5f5" | 38 | text-subtitle: "#f5f5f5" |
38 | card-shadow: rgba(0, 0, 0, 0.4) | 39 | card-shadow: rgba(0, 0, 0, 0.4) |
40 | link: "#3273dc" | ||
39 | link-hover: "#ffdd57" | 41 | link-hover: "#ffdd57" |
40 | background-image: "" | 42 | background-image: "" |
41 | 43 | ||
diff --git a/src/components/services/Prometheus.vue b/src/components/services/Prometheus.vue new file mode 100644 index 0000000..6efcb34 --- /dev/null +++ b/src/components/services/Prometheus.vue | |||
@@ -0,0 +1,143 @@ | |||
1 | <template> | ||
2 | <Generic :item="item"> | ||
3 | <template #content> | ||
4 | <p class="title is-4">{{ item.name }}</p> | ||
5 | <p class="subtitle is-6"> | ||
6 | <template v-if="item.subtitle"> | ||
7 | {{ item.subtitle }} | ||
8 | </template> | ||
9 | <template v-else-if="api"> {{ count }} {{ level }} alerts </template> | ||
10 | </p> | ||
11 | </template> | ||
12 | <template #indicator> | ||
13 | <div v-if="api" class="status" :class="level"> | ||
14 | {{ count }} | ||
15 | </div> | ||
16 | </template> | ||
17 | </Generic> | ||
18 | </template> | ||
19 | |||
20 | <script> | ||
21 | import service from "@/mixins/service.js"; | ||
22 | import Generic from "./Generic.vue"; | ||
23 | |||
24 | const AlertsStatus = Object.freeze({ | ||
25 | firing: "firing", | ||
26 | pending: "pending", | ||
27 | inactive: "inactive", | ||
28 | }); | ||
29 | |||
30 | export default { | ||
31 | name: "Prometheus", | ||
32 | mixins: [service], | ||
33 | props: { | ||
34 | item: Object, | ||
35 | }, | ||
36 | components: { | ||
37 | Generic, | ||
38 | }, | ||
39 | data: () => ({ | ||
40 | api: { | ||
41 | status: "", | ||
42 | count: 0, | ||
43 | alerts: { | ||
44 | firing: 0, | ||
45 | inactive: 0, | ||
46 | pending: 0, | ||
47 | }, | ||
48 | }, | ||
49 | }), | ||
50 | computed: { | ||
51 | count: function () { | ||
52 | return ( | ||
53 | this.countFiring() || this.countPending() || this.countInactive() || 0 | ||
54 | ); | ||
55 | }, | ||
56 | level: function () { | ||
57 | if (this.countFiring()) { | ||
58 | return AlertsStatus.firing; | ||
59 | } else if (this.countPending()) { | ||
60 | return AlertsStatus.pending; | ||
61 | } | ||
62 | return AlertsStatus.inactive; | ||
63 | }, | ||
64 | }, | ||
65 | created() { | ||
66 | this.fetchStatus(); | ||
67 | }, | ||
68 | methods: { | ||
69 | fetchStatus: async function () { | ||
70 | this.api = await this.fetch("api/v1/alerts").catch((e) => console.log(e)); | ||
71 | }, | ||
72 | countFiring: function () { | ||
73 | if (this.api) { | ||
74 | return this.api.data?.alerts?.filter( | ||
75 | (alert) => alert.state === AlertsStatus.firing | ||
76 | ).length; | ||
77 | } | ||
78 | return 0; | ||
79 | }, | ||
80 | countPending: function () { | ||
81 | if (this.api) { | ||
82 | return this.api.data?.alerts?.filter( | ||
83 | (alert) => alert.state === AlertsStatus.pending | ||
84 | ).length; | ||
85 | } | ||
86 | return 0; | ||
87 | }, | ||
88 | countInactive: function () { | ||
89 | if (this.api) { | ||
90 | return this.api.data?.alerts?.filter( | ||
91 | (alert) => alert.state === AlertsStatus.pending | ||
92 | ).length; | ||
93 | } | ||
94 | return 0; | ||
95 | }, | ||
96 | }, | ||
97 | }; | ||
98 | </script> | ||
99 | |||
100 | <style scoped lang="scss"> | ||
101 | .media-left { | ||
102 | .image { | ||
103 | display: flex; | ||
104 | align-items: center; | ||
105 | } | ||
106 | |||
107 | img { | ||
108 | max-height: 100%; | ||
109 | } | ||
110 | } | ||
111 | .status { | ||
112 | font-size: 0.8rem; | ||
113 | color: var(--text-title); | ||
114 | |||
115 | &.firing:before { | ||
116 | background-color: #d65c68; | ||
117 | border-color: #e87d88; | ||
118 | box-shadow: 0 0 5px 1px #d65c68; | ||
119 | } | ||
120 | |||
121 | &.pending:before { | ||
122 | background-color: #e8bb7d; | ||
123 | border-color: #d6a35c; | ||
124 | box-shadow: 0 0 5px 1px #e8bb7d; | ||
125 | } | ||
126 | |||
127 | &.inactive:before { | ||
128 | background-color: #8fe87d; | ||
129 | border-color: #70d65c; | ||
130 | box-shadow: 0 0 5px 1px #8fe87d; | ||
131 | } | ||
132 | |||
133 | &:before { | ||
134 | content: " "; | ||
135 | display: inline-block; | ||
136 | width: 7px; | ||
137 | height: 7px; | ||
138 | margin-right: 10px; | ||
139 | border: 1px solid #000; | ||
140 | border-radius: 7px; | ||
141 | } | ||
142 | } | ||
143 | </style> | ||