@omnsight/osint-entity-components 0.1.4 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "0.1.4",
6
+ "version": "0.2.0",
7
7
  "engines": {
8
8
  "node": ">=24.0.0"
9
9
  },
@@ -54,6 +54,7 @@
54
54
  "@mantine/hooks": "^8.3.18",
55
55
  "@svgr/plugin-jsx": "^8.1.0",
56
56
  "@svgr/plugin-svgo": "^8.1.0",
57
+ "omni-monitoring-client": "latest",
57
58
  "omni-osint-crud-client": "latest",
58
59
  "react": "^19.2.4",
59
60
  "react-dom": "^19.2.4",
package/src/App.tsx CHANGED
@@ -42,12 +42,14 @@ import type {
42
42
  Website,
43
43
  Relation,
44
44
  } from "omni-osint-crud-client";
45
+ import type { MonitoringSource } from "omni-monitoring-client";
45
46
  import {
46
47
  EventCard,
47
48
  OrganizationCard,
48
49
  PersonCard,
49
50
  SourceCard,
50
51
  WebsiteCard,
52
+ MonitoringSourceCard,
51
53
  } from "./cards";
52
54
  import { ArrowRightIcon } from "@heroicons/react/24/solid";
53
55
 
@@ -87,6 +89,13 @@ function App() {
87
89
  description: "An example website.",
88
90
  tags: ["website", "example"],
89
91
  });
92
+ const [monitoringSource] = useState<MonitoringSource>({
93
+ name: "Test Monitoring Source",
94
+ description:
95
+ "This is a test description for the monitoring source card. It should truncate after a certain point to avoid overflowing the card.",
96
+ reliability: 75,
97
+ owner: "test-owner",
98
+ });
90
99
  const [relation] = useState<Relation>({
91
100
  _id: "relation-1",
92
101
  _from: "person-1",
@@ -112,7 +121,13 @@ function App() {
112
121
  >
113
122
  Toggle Language
114
123
  </Button>
115
- <Button onClick={() => setColorScheme(colorScheme === "dark" ? "light" : "dark")}>Toggle Theme</Button>
124
+ <Button
125
+ onClick={() =>
126
+ setColorScheme(colorScheme === "dark" ? "light" : "dark")
127
+ }
128
+ >
129
+ Toggle Theme
130
+ </Button>
116
131
  </Group>
117
132
  <ScrollArea style={{ height: "100vh" }}>
118
133
  <SimpleGrid
@@ -233,9 +248,14 @@ function App() {
233
248
  <OrganizationCard organization={{}} />
234
249
  <SourceCard source={{}} />
235
250
  <WebsiteCard website={{}} />
251
+ <MonitoringSourceCard monitoringSource={{ owner: "" }} />
236
252
  </Stack>
237
253
  </ScrollArea>
238
254
  </Card>
255
+
256
+ <Card withBorder style={cardStyle}>
257
+ <MonitoringSourceCard monitoringSource={monitoringSource} />
258
+ </Card>
239
259
  </SimpleGrid>
240
260
  </ScrollArea>
241
261
  </>
@@ -1,4 +1,4 @@
1
- import { Badge, Group, Paper, Stack, Text, Title } from "@mantine/core";
1
+ import { Badge, Group, Paper, ScrollArea, Stack, Text, Title } from "@mantine/core";
2
2
  import { type Event } from "omni-osint-crud-client";
3
3
  import { useTranslation } from "react-i18next";
4
4
  import React from "react";
@@ -22,15 +22,17 @@ export const EventCard: React.FC<Props> = ({
22
22
  <Paper p="xs" bg={background} withBorder={withBorder}>
23
23
  <Group justify="space-between" wrap="nowrap" align="flex-start">
24
24
  <Stack gap={0}>
25
- <Title>{event.title || t("event.title")}</Title>
25
+ <Title order={2}>{event.title || t("event.title")}</Title>
26
26
  {event.happened_at && (
27
27
  <Text c="dimmed">
28
28
  {new Date(event.happened_at * 1000).toLocaleString()}
29
29
  </Text>
30
30
  )}
31
- <Text truncate="end">
32
- {event.description || t("event.description")}
33
- </Text>
31
+ <ScrollArea h={50} type="auto" offsetScrollbars>
32
+ <Text>
33
+ {event.description || t("event.description")}
34
+ </Text>
35
+ </ScrollArea>
34
36
  {event.tags && (
35
37
  <Group gap="xs" mt="xs">
36
38
  {event.tags.map((tag) => (
@@ -0,0 +1,61 @@
1
+ import { Group, Paper, RingProgress, Stack, Text, Title, Textarea, ScrollArea } from "@mantine/core";
2
+ import { type MonitoringSource } from "omni-monitoring-client";
3
+ import { useTranslation } from "react-i18next";
4
+ import React from "react";
5
+
6
+ interface Props {
7
+ monitoringSource: MonitoringSource;
8
+ background?: string;
9
+ withBorder?: boolean;
10
+ action?: React.ReactNode;
11
+ }
12
+
13
+ export const MonitoringSourceCard: React.FC<Props> = ({
14
+ monitoringSource,
15
+ background,
16
+ withBorder = true,
17
+ action,
18
+ }) => {
19
+ const { t } = useTranslation();
20
+
21
+ const reliability = monitoringSource.reliability || 0;
22
+ const color = reliability < 50 ? "red" : reliability < 80 ? "yellow" : "green";
23
+
24
+ return (
25
+ <Paper p="xs" bg={background} withBorder={withBorder}>
26
+ <Group justify="space-between" wrap="nowrap" align="flex-start">
27
+ <Stack gap={0}>
28
+ <Group>
29
+ <Title order={2}>
30
+ {monitoringSource.name || t("monitoringSource.name")}
31
+ </Title>
32
+ {monitoringSource.reliability && (
33
+ <RingProgress
34
+ size={36}
35
+ thickness={3}
36
+ roundCaps
37
+ sections={[{ value: reliability, color }]}
38
+ label={
39
+ <Text c={color} fw={700} ta="center" size="xs" style={{ fontSize: 9 }}>
40
+ {`${reliability}%`}
41
+ </Text>
42
+ }
43
+ />
44
+ )}
45
+ </Group>
46
+ {monitoringSource.type && (
47
+ <Text c="dimmed">
48
+ {monitoringSource.type || t("monitoringSource.type")}
49
+ </Text>
50
+ )}
51
+ <ScrollArea h={50} type="auto" offsetScrollbars>
52
+ <Text>
53
+ {monitoringSource.description || t("monitoringSource.description")}
54
+ </Text>
55
+ </ScrollArea>
56
+ </Stack>
57
+ {action}
58
+ </Group>
59
+ </Paper>
60
+ );
61
+ };
@@ -22,7 +22,7 @@ export const OrganizationCard: React.FC<Props> = ({
22
22
  <Paper withBorder={withBorder} p="xs" bg={background}>
23
23
  <Group justify="space-between" wrap="nowrap" align="flex-start">
24
24
  <Stack gap={0}>
25
- <Title>{organization.name || t("organization.name")}</Title>
25
+ <Title order={2}>{organization.name || t("organization.name")}</Title>
26
26
  {organization.tags && (
27
27
  <Group gap="xs" mt="xs">
28
28
  {organization.tags.map((tag) => (
@@ -22,7 +22,7 @@ export const PersonCard: React.FC<Props> = ({
22
22
  <Paper withBorder={withBorder} p="xs" bg={background}>
23
23
  <Group justify="space-between" wrap="nowrap" align="flex-start">
24
24
  <Stack gap={0}>
25
- <Title>{person.name || t("person.name")}</Title>
25
+ <Title order={2}>{person.name || t("person.name")}</Title>
26
26
  {person.role && (
27
27
  <Text c="dimmed">{person.role || t("person.role")}</Text>
28
28
  )}
@@ -3,6 +3,7 @@ import {
3
3
  Badge,
4
4
  Group,
5
5
  Paper,
6
+ ScrollArea,
6
7
  Stack,
7
8
  Text,
8
9
  Title,
@@ -32,7 +33,7 @@ export const SourceCard: React.FC<Props> = ({
32
33
  <Group justify="space-between" wrap="nowrap" align="flex-start">
33
34
  <Stack gap={0}>
34
35
  <Group>
35
- <Title>{source.name || t("source.name")}</Title>
36
+ <Title order={2}>{source.name || t("source.name")}</Title>
36
37
  {source.url && (
37
38
  <ActionIcon
38
39
  variant="subtle"
@@ -45,9 +46,11 @@ export const SourceCard: React.FC<Props> = ({
45
46
  </ActionIcon>
46
47
  )}
47
48
  </Group>
48
- <Text truncate="end">
49
- {source.description || t("source.description")}
50
- </Text>
49
+ <ScrollArea h={50} type="auto" offsetScrollbars>
50
+ <Text>
51
+ {source.description || t("source.description")}
52
+ </Text>
53
+ </ScrollArea>
51
54
  {source.tags && (
52
55
  <Group gap="xs" mt="xs">
53
56
  {source.tags.map((tag) => (
@@ -3,6 +3,7 @@ import {
3
3
  Badge,
4
4
  Group,
5
5
  Paper,
6
+ ScrollArea,
6
7
  Stack,
7
8
  Text,
8
9
  Title,
@@ -32,7 +33,7 @@ export const WebsiteCard: React.FC<Props> = ({
32
33
  <Group justify="space-between" wrap="nowrap" align="flex-start">
33
34
  <Stack gap={0}>
34
35
  <Group>
35
- <Title>{website.title || t("website.title")}</Title>
36
+ <Title order={2}>{website.title || t("website.title")}</Title>
36
37
  {website.url && (
37
38
  <ActionIcon
38
39
  variant="subtle"
@@ -45,9 +46,11 @@ export const WebsiteCard: React.FC<Props> = ({
45
46
  </ActionIcon>
46
47
  )}
47
48
  </Group>
48
- <Text truncate="end">
49
- {website.description || t("website.description")}
50
- </Text>
49
+ <ScrollArea h={50} type="auto" offsetScrollbars>
50
+ <Text>
51
+ {website.description || t("website.description")}
52
+ </Text>
53
+ </ScrollArea>
51
54
  {website.tags && (
52
55
  <Group gap="xs" mt="xs">
53
56
  {website.tags.map((tag) => (
@@ -3,3 +3,4 @@ export * from './PersonCard';
3
3
  export * from './OrganizationCard';
4
4
  export * from './WebsiteCard';
5
5
  export * from './SourceCard';
6
+ export * from './MonittoringSourceCard';
@@ -66,6 +66,11 @@
66
66
  "title": "Title",
67
67
  "description": "Description"
68
68
  },
69
+ "monitoringSource": {
70
+ "name": "Name",
71
+ "type": "Type",
72
+ "description": "Description"
73
+ },
69
74
  "tooltip": {
70
75
  "relation": "Related",
71
76
  "confidence": "Confidence",
@@ -65,7 +65,11 @@
65
65
  },
66
66
  "title": "标题",
67
67
  "description": "描述"
68
-
68
+ },
69
+ "monitoringSource": {
70
+ "name": "名称",
71
+ "type": "类型",
72
+ "description": "描述"
69
73
  },
70
74
  "tooltip": {
71
75
  "relation": "相关",