@echothink-ui/activity 0.1.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/README.md +5 -0
- package/dist/components/ActivityFeed.d.ts +7 -0
- package/dist/components/ActivityTimeline.d.ts +6 -0
- package/dist/components/AlertBanner.d.ts +10 -0
- package/dist/components/ChangelogPanel.d.ts +6 -0
- package/dist/components/IncidentPanel.d.ts +6 -0
- package/dist/components/MentionList.d.ts +7 -0
- package/dist/components/NotificationCenter.d.ts +10 -0
- package/dist/components/NotificationItem.d.ts +8 -0
- package/dist/components/SubscriptionPreferences.d.ts +7 -0
- package/dist/components/SystemStatusBanner.d.ts +9 -0
- package/dist/components/WatcherList.d.ts +8 -0
- package/dist/components/helpers.d.ts +4 -0
- package/dist/components/types.d.ts +65 -0
- package/dist/index.cjs +944 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.css +711 -0
- package/dist/index.css.map +1 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.js +904 -0
- package/dist/index.js.map +1 -0
- package/package.json +43 -0
- package/src/components/ActivityFeed.tsx +83 -0
- package/src/components/ActivityTimeline.tsx +178 -0
- package/src/components/AlertBanner.tsx +69 -0
- package/src/components/ChangelogPanel.tsx +100 -0
- package/src/components/IncidentPanel.tsx +82 -0
- package/src/components/MentionList.tsx +85 -0
- package/src/components/NotificationCenter.tsx +117 -0
- package/src/components/NotificationItem.tsx +99 -0
- package/src/components/SubscriptionPreferences.test.tsx +64 -0
- package/src/components/SubscriptionPreferences.tsx +140 -0
- package/src/components/SystemStatusBanner.tsx +46 -0
- package/src/components/WatcherList.test.tsx +50 -0
- package/src/components/WatcherList.tsx +122 -0
- package/src/components/helpers.ts +15 -0
- package/src/components/types.ts +71 -0
- package/src/index.tsx +31 -0
- package/src/styles.css +854 -0
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Badge,
|
|
3
|
+
Button,
|
|
4
|
+
IconButton,
|
|
5
|
+
Surface,
|
|
6
|
+
type SurfaceComponentProps
|
|
7
|
+
} from "@echothink-ui/core";
|
|
8
|
+
import { CloseIcon, PlusIcon } from "@echothink-ui/icons";
|
|
9
|
+
import type { IdentityRef } from "./types";
|
|
10
|
+
|
|
11
|
+
export interface WatcherListProps extends Omit<SurfaceComponentProps, "children"> {
|
|
12
|
+
watchers: IdentityRef[];
|
|
13
|
+
onAdd?: () => void;
|
|
14
|
+
onRemove?: (id: string) => void;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function WatcherList({
|
|
18
|
+
watchers,
|
|
19
|
+
onAdd,
|
|
20
|
+
onRemove,
|
|
21
|
+
title,
|
|
22
|
+
subtitle,
|
|
23
|
+
className,
|
|
24
|
+
role,
|
|
25
|
+
footer,
|
|
26
|
+
"aria-label": ariaLabel,
|
|
27
|
+
...props
|
|
28
|
+
}: WatcherListProps) {
|
|
29
|
+
const heading = title ?? "Watchers";
|
|
30
|
+
const regionLabel = ariaLabel ?? (typeof heading === "string" ? heading : "Watchers");
|
|
31
|
+
const addAction = onAdd ? (
|
|
32
|
+
<Button
|
|
33
|
+
type="button"
|
|
34
|
+
density="compact"
|
|
35
|
+
intent="tertiary"
|
|
36
|
+
icon={<PlusIcon size={16} />}
|
|
37
|
+
onClick={onAdd}
|
|
38
|
+
>
|
|
39
|
+
Add watcher
|
|
40
|
+
</Button>
|
|
41
|
+
) : null;
|
|
42
|
+
const surfaceFooter =
|
|
43
|
+
addAction || footer ? (
|
|
44
|
+
<div className="eth-activity-watcher-list__footer">
|
|
45
|
+
{addAction}
|
|
46
|
+
{footer}
|
|
47
|
+
</div>
|
|
48
|
+
) : undefined;
|
|
49
|
+
|
|
50
|
+
return (
|
|
51
|
+
<Surface
|
|
52
|
+
{...props}
|
|
53
|
+
title={heading}
|
|
54
|
+
subtitle={subtitle ?? watcherSummary(watchers.length)}
|
|
55
|
+
className={["eth-activity-watcher-list", className].filter(Boolean).join(" ")}
|
|
56
|
+
data-eth-component="WatcherList"
|
|
57
|
+
role={role ?? "region"}
|
|
58
|
+
aria-label={regionLabel}
|
|
59
|
+
footer={surfaceFooter}
|
|
60
|
+
>
|
|
61
|
+
{watchers.length ? (
|
|
62
|
+
<ul className="eth-activity-watcher-list__items" aria-label="Watchers">
|
|
63
|
+
{watchers.map((watcher) => (
|
|
64
|
+
<li key={watcher.id} className="eth-activity-watcher-list__item">
|
|
65
|
+
<span className="eth-activity-watcher-list__avatar" aria-hidden="true">
|
|
66
|
+
{watcher.avatar ? (
|
|
67
|
+
<img src={watcher.avatar} alt="" />
|
|
68
|
+
) : (
|
|
69
|
+
initialsForName(watcher.label)
|
|
70
|
+
)}
|
|
71
|
+
</span>
|
|
72
|
+
<span className="eth-activity-watcher-list__identity">
|
|
73
|
+
<strong>{watcher.label}</strong>
|
|
74
|
+
<span>{watcherDetail(watcher)}</span>
|
|
75
|
+
</span>
|
|
76
|
+
<span className="eth-activity-watcher-list__actions">
|
|
77
|
+
<Badge severity="neutral">{watcherKindLabel(watcher.kind)}</Badge>
|
|
78
|
+
{onRemove ? (
|
|
79
|
+
<IconButton
|
|
80
|
+
type="button"
|
|
81
|
+
density="compact"
|
|
82
|
+
intent="ghost"
|
|
83
|
+
label={`Remove ${watcher.label} from watchers`}
|
|
84
|
+
icon={<CloseIcon size={16} />}
|
|
85
|
+
onClick={() => onRemove(watcher.id)}
|
|
86
|
+
/>
|
|
87
|
+
) : null}
|
|
88
|
+
</span>
|
|
89
|
+
</li>
|
|
90
|
+
))}
|
|
91
|
+
</ul>
|
|
92
|
+
) : (
|
|
93
|
+
<p className="eth-activity-watcher-list__empty" role="status">
|
|
94
|
+
No watchers have been added.
|
|
95
|
+
</p>
|
|
96
|
+
)}
|
|
97
|
+
</Surface>
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function watcherSummary(count: number) {
|
|
102
|
+
if (count === 0) return "No watchers configured";
|
|
103
|
+
return `${count} ${count === 1 ? "watcher" : "watchers"} notified on updates`;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function watcherDetail(watcher: IdentityRef) {
|
|
107
|
+
const details = [watcher.role, watcher.email].filter(Boolean);
|
|
108
|
+
return details.length ? details.join(" / ") : "Receives activity updates";
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function watcherKindLabel(kind: IdentityRef["kind"]) {
|
|
112
|
+
if (kind === "group") return "Group";
|
|
113
|
+
if (kind === "service-account") return "Service account";
|
|
114
|
+
return "User";
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function initialsForName(value: string) {
|
|
118
|
+
const parts = value.trim().split(/\s+/).filter(Boolean);
|
|
119
|
+
if (!parts.length) return "?";
|
|
120
|
+
if (parts.length === 1) return parts[0].slice(0, 2).toUpperCase();
|
|
121
|
+
return `${parts[0][0]}${parts[parts.length - 1][0]}`.toUpperCase();
|
|
122
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { EthSeverity } from "@echothink-ui/core";
|
|
2
|
+
import type { ActivitySeverity } from "./types";
|
|
3
|
+
|
|
4
|
+
export function severityToCore(severity: ActivitySeverity): EthSeverity {
|
|
5
|
+
if (severity === "error" || severity === "danger") return "danger";
|
|
6
|
+
if (severity === "success") return "success";
|
|
7
|
+
if (severity === "warning") return "warning";
|
|
8
|
+
return "info";
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function dateGroupKey(value: string) {
|
|
12
|
+
const date = new Date(value);
|
|
13
|
+
if (!Number.isFinite(date.valueOf())) return value;
|
|
14
|
+
return date.toISOString().slice(0, 10);
|
|
15
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import type { EthAction } from "@echothink-ui/core";
|
|
2
|
+
|
|
3
|
+
export type ActivitySeverity = "info" | "success" | "warning" | "error" | "danger";
|
|
4
|
+
|
|
5
|
+
export interface NotificationItemData {
|
|
6
|
+
id: string;
|
|
7
|
+
title: string;
|
|
8
|
+
body?: string;
|
|
9
|
+
severity: ActivitySeverity;
|
|
10
|
+
createdAt: string;
|
|
11
|
+
read?: boolean;
|
|
12
|
+
actions?: EthAction[];
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface ActivityEvent {
|
|
16
|
+
id: string;
|
|
17
|
+
actor: string;
|
|
18
|
+
verb: string;
|
|
19
|
+
objectLabel: string;
|
|
20
|
+
targetLabel?: string;
|
|
21
|
+
createdAt: string;
|
|
22
|
+
details?: string;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface ChangelogEntry {
|
|
26
|
+
id: string;
|
|
27
|
+
version: string;
|
|
28
|
+
date: string;
|
|
29
|
+
changes: Array<{ type: "added" | "changed" | "fixed" | "removed"; summary: string }>;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface SubscriptionChannel {
|
|
33
|
+
id: string;
|
|
34
|
+
label: string;
|
|
35
|
+
enabled: boolean;
|
|
36
|
+
description?: string;
|
|
37
|
+
disabled?: boolean;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface SubscriptionCategory {
|
|
41
|
+
id: string;
|
|
42
|
+
label: string;
|
|
43
|
+
description?: string;
|
|
44
|
+
channels: SubscriptionChannel[];
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export interface Mention {
|
|
48
|
+
id: string;
|
|
49
|
+
from: string;
|
|
50
|
+
messageRef: string;
|
|
51
|
+
excerpt: string;
|
|
52
|
+
createdAt: string;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export interface IdentityRef {
|
|
56
|
+
id: string;
|
|
57
|
+
label: string;
|
|
58
|
+
email?: string;
|
|
59
|
+
avatar?: string;
|
|
60
|
+
role?: string;
|
|
61
|
+
kind?: "user" | "service-account" | "group";
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export interface ActivityIncident {
|
|
65
|
+
id: string;
|
|
66
|
+
title: string;
|
|
67
|
+
status?: "investigating" | "identified" | "monitoring" | "resolved";
|
|
68
|
+
severity?: ActivitySeverity;
|
|
69
|
+
startedAt?: string;
|
|
70
|
+
description?: string;
|
|
71
|
+
}
|
package/src/index.tsx
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import "./styles.css";
|
|
2
|
+
|
|
3
|
+
export * from "./components/types";
|
|
4
|
+
export * from "./components/NotificationCenter";
|
|
5
|
+
export * from "./components/NotificationItem";
|
|
6
|
+
export * from "./components/ActivityFeed";
|
|
7
|
+
export * from "./components/ActivityTimeline";
|
|
8
|
+
export * from "./components/AlertBanner";
|
|
9
|
+
export * from "./components/SystemStatusBanner";
|
|
10
|
+
export * from "./components/IncidentPanel";
|
|
11
|
+
export * from "./components/ChangelogPanel";
|
|
12
|
+
export * from "./components/SubscriptionPreferences";
|
|
13
|
+
export * from "./components/MentionList";
|
|
14
|
+
export * from "./components/WatcherList";
|
|
15
|
+
export { AuditLogTable, type AuditExportFormat, type AuditLogTableProps } from "@echothink-ui/data";
|
|
16
|
+
|
|
17
|
+
export const ActivityComponentNames = [
|
|
18
|
+
"NotificationCenter",
|
|
19
|
+
"NotificationItem",
|
|
20
|
+
"ActivityFeed",
|
|
21
|
+
"ActivityTimeline",
|
|
22
|
+
"AlertBanner",
|
|
23
|
+
"SystemStatusBanner",
|
|
24
|
+
"IncidentPanel",
|
|
25
|
+
"ChangelogPanel",
|
|
26
|
+
"SubscriptionPreferences",
|
|
27
|
+
"MentionList",
|
|
28
|
+
"WatcherList",
|
|
29
|
+
"AuditLogTable"
|
|
30
|
+
] as const;
|
|
31
|
+
export type ActivityComponentName = (typeof ActivityComponentNames)[number];
|