@burdenoff/microfe-theculturepost 2026.1031.1 → 2026.1031.2
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/dist/theculturepost/analytics/index.d.ts +7 -0
- package/dist/theculturepost/analytics/index.d.ts.map +1 -0
- package/dist/theculturepost/analytics/index.js +2 -0
- package/dist/theculturepost/analytics/theculturepostAnalytics.d.ts +127 -0
- package/dist/theculturepost/analytics/theculturepostAnalytics.d.ts.map +1 -0
- package/dist/theculturepost/analytics/theculturepostAnalytics.js +135 -0
- package/dist/theculturepost/analytics/theculturepostAnalytics.js.map +1 -0
- package/dist/theculturepost/analytics/useTheculturepostAnalytics.d.ts +5 -0
- package/dist/theculturepost/analytics/useTheculturepostAnalytics.d.ts.map +1 -0
- package/dist/theculturepost/analytics/useTheculturepostAnalytics.js +15 -0
- package/dist/theculturepost/analytics/useTheculturepostAnalytics.js.map +1 -0
- package/dist/theculturepost/hooks/usePageAnalytics.d.ts +13 -4
- package/dist/theculturepost/hooks/usePageAnalytics.d.ts.map +1 -1
- package/dist/theculturepost/hooks/usePageAnalytics.js +19 -26
- package/dist/theculturepost/hooks/usePageAnalytics.js.map +1 -1
- package/dist/theculturepost/hooks/useTcpApi.d.ts +6 -6
- package/dist/theculturepost/hooks/useTcpApi.d.ts.map +1 -1
- package/dist/theculturepost/hooks/useTcpApi.js +242 -239
- package/dist/theculturepost/hooks/useTcpApi.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TheCulturePost product analytics (BOFF-3167).
|
|
3
|
+
* @module theculturepost/analytics
|
|
4
|
+
*/
|
|
5
|
+
export { THECULTUREPOST_ANALYTICS_EVENTS, normalizePageName, theculturepostAnalytics, type TheculturepostAnalyticsEmission, type TheculturepostAnalyticsEventName, } from './theculturepostAnalytics';
|
|
6
|
+
export { useTheculturepostAnalytics, type TheculturepostAnalyticsSend, } from './useTheculturepostAnalytics';
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/theculturepost/analytics/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACL,+BAA+B,EAC/B,iBAAiB,EACjB,uBAAuB,EACvB,KAAK,+BAA+B,EACpC,KAAK,gCAAgC,GACtC,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACL,0BAA0B,EAC1B,KAAK,2BAA2B,GACjC,MAAM,8BAA8B,CAAC"}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { TcpArchiveItem, TcpCitation, TcpCollection, TcpDiscussion, TcpOralHistory, TcpReply, TcpStory } from '../types';
|
|
2
|
+
|
|
3
|
+
/** Every TheCulturePost analytics event this MFE emits. */
|
|
4
|
+
export declare const THECULTUREPOST_ANALYTICS_EVENTS: {
|
|
5
|
+
readonly pageViewed: "theculturepost.page.viewed";
|
|
6
|
+
readonly storyDraftCreated: "theculturepost.story.draft_created";
|
|
7
|
+
readonly storyPublished: "theculturepost.story.published";
|
|
8
|
+
readonly storySaved: "theculturepost.story.saved";
|
|
9
|
+
readonly citationAttached: "theculturepost.citation.attached";
|
|
10
|
+
readonly collectionCreated: "theculturepost.collection.created";
|
|
11
|
+
readonly archiveItemUploaded: "theculturepost.archive_item.uploaded";
|
|
12
|
+
readonly oralHistoryRecorded: "theculturepost.oral_history.recorded";
|
|
13
|
+
readonly discussionOpened: "theculturepost.discussion.opened";
|
|
14
|
+
readonly discussionReplied: "theculturepost.discussion.replied";
|
|
15
|
+
};
|
|
16
|
+
export type TheculturepostAnalyticsEventName = (typeof THECULTUREPOST_ANALYTICS_EVENTS)[keyof typeof THECULTUREPOST_ANALYTICS_EVENTS];
|
|
17
|
+
/** A single bus emission: the event name and its payload. */
|
|
18
|
+
export interface TheculturepostAnalyticsEmission {
|
|
19
|
+
name: TheculturepostAnalyticsEventName;
|
|
20
|
+
payload: Record<string, string | boolean | undefined>;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Turns a pathname (already stripped of the MFE base path) into a stable,
|
|
24
|
+
* low-cardinality page key, mirroring the MFE routes:
|
|
25
|
+
* `/` -> `home`, `/stories` -> `stories`, `/stories/:id` -> `stories.detail`,
|
|
26
|
+
* `/stories/:id/citations` -> `stories.citations`,
|
|
27
|
+
* `/archive/collections/:id` -> `archive.collections`. Ids and slugs never
|
|
28
|
+
* reach the key, so the dimension is safe for Rybbit.
|
|
29
|
+
*/
|
|
30
|
+
export declare function normalizePageName(pathname: string): string;
|
|
31
|
+
/**
|
|
32
|
+
* Pure payload builders. Kept separate from the hook so the exact shape that
|
|
33
|
+
* reaches the bus is reviewable (and testable) without a React tree.
|
|
34
|
+
*/
|
|
35
|
+
export declare const theculturepostAnalytics: {
|
|
36
|
+
pageViewed(workspaceId: string | undefined, pathname: string): {
|
|
37
|
+
name: "theculturepost.page.viewed";
|
|
38
|
+
payload: {
|
|
39
|
+
workspaceId: string | undefined;
|
|
40
|
+
page: string;
|
|
41
|
+
};
|
|
42
|
+
};
|
|
43
|
+
storyDraftCreated(story: Pick<TcpStory, "id" | "workspaceId" | "topicId" | "format">): {
|
|
44
|
+
name: "theculturepost.story.draft_created";
|
|
45
|
+
payload: {
|
|
46
|
+
workspaceId: string;
|
|
47
|
+
storyId: string;
|
|
48
|
+
topicId: string | undefined;
|
|
49
|
+
format: import('../types').TcpStoryFormat;
|
|
50
|
+
};
|
|
51
|
+
};
|
|
52
|
+
storyPublished(story: Pick<TcpStory, "id" | "workspaceId" | "topicId" | "format"> & {
|
|
53
|
+
citations?: readonly unknown[] | null;
|
|
54
|
+
}): {
|
|
55
|
+
name: "theculturepost.story.published";
|
|
56
|
+
payload: {
|
|
57
|
+
workspaceId: string;
|
|
58
|
+
storyId: string;
|
|
59
|
+
topicId: string | undefined;
|
|
60
|
+
format: import('../types').TcpStoryFormat;
|
|
61
|
+
cited: boolean;
|
|
62
|
+
};
|
|
63
|
+
};
|
|
64
|
+
storySaved(workspaceId: string | undefined, storyId: string): {
|
|
65
|
+
name: "theculturepost.story.saved";
|
|
66
|
+
payload: {
|
|
67
|
+
workspaceId: string | undefined;
|
|
68
|
+
storyId: string;
|
|
69
|
+
};
|
|
70
|
+
};
|
|
71
|
+
citationAttached(citation: Pick<TcpCitation, "id" | "workspaceId" | "storyId" | "sourceType" | "claimId">): {
|
|
72
|
+
name: "theculturepost.citation.attached";
|
|
73
|
+
payload: {
|
|
74
|
+
workspaceId: string;
|
|
75
|
+
storyId: string;
|
|
76
|
+
citationId: string;
|
|
77
|
+
sourceType: import('../types').TcpSourceType;
|
|
78
|
+
linkedToClaim: boolean;
|
|
79
|
+
};
|
|
80
|
+
};
|
|
81
|
+
collectionCreated(collection: Pick<TcpCollection, "id" | "workspaceId">): {
|
|
82
|
+
name: "theculturepost.collection.created";
|
|
83
|
+
payload: {
|
|
84
|
+
workspaceId: string;
|
|
85
|
+
collectionId: string;
|
|
86
|
+
};
|
|
87
|
+
};
|
|
88
|
+
archiveItemUploaded(item: Pick<TcpArchiveItem, "id" | "workspaceId" | "kind" | "accessLevel" | "collectionId" | "file">): {
|
|
89
|
+
name: "theculturepost.archive_item.uploaded";
|
|
90
|
+
payload: {
|
|
91
|
+
workspaceId: string;
|
|
92
|
+
archiveItemId: string;
|
|
93
|
+
collectionId: string | undefined;
|
|
94
|
+
kind: import('../types').TcpArchiveItemKind;
|
|
95
|
+
accessLevel: import('../types').TcpAccessLevel;
|
|
96
|
+
hasFile: boolean;
|
|
97
|
+
};
|
|
98
|
+
};
|
|
99
|
+
oralHistoryRecorded(oralHistory: Pick<TcpOralHistory, "id" | "workspaceId" | "accessLevel" | "collectionId" | "recording">): {
|
|
100
|
+
name: "theculturepost.oral_history.recorded";
|
|
101
|
+
payload: {
|
|
102
|
+
workspaceId: string;
|
|
103
|
+
oralHistoryId: string;
|
|
104
|
+
collectionId: string | undefined;
|
|
105
|
+
accessLevel: import('../types').TcpAccessLevel;
|
|
106
|
+
hasRecording: boolean;
|
|
107
|
+
};
|
|
108
|
+
};
|
|
109
|
+
discussionOpened(discussion: Pick<TcpDiscussion, "id" | "workspaceId" | "storyId" | "isInterfaith">): {
|
|
110
|
+
name: "theculturepost.discussion.opened";
|
|
111
|
+
payload: {
|
|
112
|
+
workspaceId: string;
|
|
113
|
+
discussionId: string;
|
|
114
|
+
storyId: string | undefined;
|
|
115
|
+
isInterfaith: boolean;
|
|
116
|
+
};
|
|
117
|
+
};
|
|
118
|
+
discussionReplied(reply: Pick<TcpReply, "id" | "workspaceId" | "discussionId">): {
|
|
119
|
+
name: "theculturepost.discussion.replied";
|
|
120
|
+
payload: {
|
|
121
|
+
workspaceId: string;
|
|
122
|
+
discussionId: string;
|
|
123
|
+
replyId: string;
|
|
124
|
+
};
|
|
125
|
+
};
|
|
126
|
+
};
|
|
127
|
+
//# sourceMappingURL=theculturepostAnalytics.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"theculturepostAnalytics.d.ts","sourceRoot":"","sources":["../../../src/theculturepost/analytics/theculturepostAnalytics.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,KAAK,EACV,cAAc,EACd,WAAW,EACX,aAAa,EACb,aAAa,EACb,cAAc,EACd,QAAQ,EACR,QAAQ,EACT,MAAM,UAAU,CAAC;AAElB,2DAA2D;AAC3D,eAAO,MAAM,+BAA+B;;;;;;;;;;;CAWlC,CAAC;AAEX,MAAM,MAAM,gCAAgC,GAC1C,CAAC,OAAO,+BAA+B,CAAC,CAAC,MAAM,OAAO,+BAA+B,CAAC,CAAC;AAEzF,6DAA6D;AAC7D,MAAM,WAAW,+BAA+B;IAC9C,IAAI,EAAE,gCAAgC,CAAC;IACvC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC,CAAC;CACvD;AAQD;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAS1D;AAED;;;GAGG;AACH,eAAO,MAAM,uBAAuB;4BACV,MAAM,GAAG,SAAS,YAAY,MAAM;;;;;;;6BAMnC,IAAI,CAAC,QAAQ,EAAE,IAAI,GAAG,aAAa,GAAG,SAAS,GAAG,QAAQ,CAAC;;;;;;;;;0BAY3E,IAAI,CAAC,QAAQ,EAAE,IAAI,GAAG,aAAa,GAAG,SAAS,GAAG,QAAQ,CAAC,GAAG;QACnE,SAAS,CAAC,EAAE,SAAS,OAAO,EAAE,GAAG,IAAI,CAAC;KACvC;;;;;;;;;;4BAaqB,MAAM,GAAG,SAAS,WAAW,MAAM;;;;;;;+BAO/C,IAAI,CAAC,WAAW,EAAE,IAAI,GAAG,aAAa,GAAG,SAAS,GAAG,YAAY,GAAG,SAAS,CAAC;;;;;;;;;;kCAa5D,IAAI,CAAC,aAAa,EAAE,IAAI,GAAG,aAAa,CAAC;;;;;;;8BAO/D,IAAI,CACR,cAAc,EACd,IAAI,GAAG,aAAa,GAAG,MAAM,GAAG,aAAa,GAAG,cAAc,GAAG,MAAM,CACxE;;;;;;;;;;;qCAeY,IAAI,CACf,cAAc,EACd,IAAI,GAAG,aAAa,GAAG,aAAa,GAAG,cAAc,GAAG,WAAW,CACpE;;;;;;;;;;iCAcW,IAAI,CAAC,aAAa,EAAE,IAAI,GAAG,aAAa,GAAG,SAAS,GAAG,cAAc,CAAC;;;;;;;;;6BAY3D,IAAI,CAAC,QAAQ,EAAE,IAAI,GAAG,aAAa,GAAG,cAAc,CAAC;;;;;;;;CAU/E,CAAC"}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
//#region src/theculturepost/analytics/theculturepostAnalytics.ts
|
|
2
|
+
var e = {
|
|
3
|
+
pageViewed: "theculturepost.page.viewed",
|
|
4
|
+
storyDraftCreated: "theculturepost.story.draft_created",
|
|
5
|
+
storyPublished: "theculturepost.story.published",
|
|
6
|
+
storySaved: "theculturepost.story.saved",
|
|
7
|
+
citationAttached: "theculturepost.citation.attached",
|
|
8
|
+
collectionCreated: "theculturepost.collection.created",
|
|
9
|
+
archiveItemUploaded: "theculturepost.archive_item.uploaded",
|
|
10
|
+
oralHistoryRecorded: "theculturepost.oral_history.recorded",
|
|
11
|
+
discussionOpened: "theculturepost.discussion.opened",
|
|
12
|
+
discussionReplied: "theculturepost.discussion.replied"
|
|
13
|
+
}, t = new Set([
|
|
14
|
+
"stories",
|
|
15
|
+
"topics",
|
|
16
|
+
"discussions"
|
|
17
|
+
]), n = /^[a-z][a-z-]*$/;
|
|
18
|
+
function r(e) {
|
|
19
|
+
let [r, i, a] = e.split("/").filter(Boolean);
|
|
20
|
+
return r ? n.test(r) ? i ? t.has(r) ? a && n.test(a) ? `${r}.${a}` : `${r}.detail` : n.test(i) ? `${r}.${i}` : `${r}.detail` : r : "other" : "home";
|
|
21
|
+
}
|
|
22
|
+
var i = {
|
|
23
|
+
pageViewed(t, n) {
|
|
24
|
+
return {
|
|
25
|
+
name: e.pageViewed,
|
|
26
|
+
payload: {
|
|
27
|
+
workspaceId: t,
|
|
28
|
+
page: r(n)
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
},
|
|
32
|
+
storyDraftCreated(t) {
|
|
33
|
+
return {
|
|
34
|
+
name: e.storyDraftCreated,
|
|
35
|
+
payload: {
|
|
36
|
+
workspaceId: t.workspaceId,
|
|
37
|
+
storyId: t.id,
|
|
38
|
+
topicId: t.topicId ?? void 0,
|
|
39
|
+
format: t.format
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
},
|
|
43
|
+
storyPublished(t) {
|
|
44
|
+
return {
|
|
45
|
+
name: e.storyPublished,
|
|
46
|
+
payload: {
|
|
47
|
+
workspaceId: t.workspaceId,
|
|
48
|
+
storyId: t.id,
|
|
49
|
+
topicId: t.topicId ?? void 0,
|
|
50
|
+
format: t.format,
|
|
51
|
+
cited: (t.citations?.length ?? 0) > 0
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
},
|
|
55
|
+
storySaved(t, n) {
|
|
56
|
+
return {
|
|
57
|
+
name: e.storySaved,
|
|
58
|
+
payload: {
|
|
59
|
+
workspaceId: t,
|
|
60
|
+
storyId: n
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
},
|
|
64
|
+
citationAttached(t) {
|
|
65
|
+
return {
|
|
66
|
+
name: e.citationAttached,
|
|
67
|
+
payload: {
|
|
68
|
+
workspaceId: t.workspaceId,
|
|
69
|
+
storyId: t.storyId,
|
|
70
|
+
citationId: t.id,
|
|
71
|
+
sourceType: t.sourceType,
|
|
72
|
+
linkedToClaim: !!t.claimId
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
},
|
|
76
|
+
collectionCreated(t) {
|
|
77
|
+
return {
|
|
78
|
+
name: e.collectionCreated,
|
|
79
|
+
payload: {
|
|
80
|
+
workspaceId: t.workspaceId,
|
|
81
|
+
collectionId: t.id
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
},
|
|
85
|
+
archiveItemUploaded(t) {
|
|
86
|
+
return {
|
|
87
|
+
name: e.archiveItemUploaded,
|
|
88
|
+
payload: {
|
|
89
|
+
workspaceId: t.workspaceId,
|
|
90
|
+
archiveItemId: t.id,
|
|
91
|
+
collectionId: t.collectionId ?? void 0,
|
|
92
|
+
kind: t.kind,
|
|
93
|
+
accessLevel: t.accessLevel,
|
|
94
|
+
hasFile: !!t.file
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
},
|
|
98
|
+
oralHistoryRecorded(t) {
|
|
99
|
+
return {
|
|
100
|
+
name: e.oralHistoryRecorded,
|
|
101
|
+
payload: {
|
|
102
|
+
workspaceId: t.workspaceId,
|
|
103
|
+
oralHistoryId: t.id,
|
|
104
|
+
collectionId: t.collectionId ?? void 0,
|
|
105
|
+
accessLevel: t.accessLevel,
|
|
106
|
+
hasRecording: !!t.recording
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
},
|
|
110
|
+
discussionOpened(t) {
|
|
111
|
+
return {
|
|
112
|
+
name: e.discussionOpened,
|
|
113
|
+
payload: {
|
|
114
|
+
workspaceId: t.workspaceId,
|
|
115
|
+
discussionId: t.id,
|
|
116
|
+
storyId: t.storyId ?? void 0,
|
|
117
|
+
isInterfaith: t.isInterfaith
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
},
|
|
121
|
+
discussionReplied(t) {
|
|
122
|
+
return {
|
|
123
|
+
name: e.discussionReplied,
|
|
124
|
+
payload: {
|
|
125
|
+
workspaceId: t.workspaceId,
|
|
126
|
+
discussionId: t.discussionId,
|
|
127
|
+
replyId: t.id
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
//#endregion
|
|
133
|
+
export { e as THECULTUREPOST_ANALYTICS_EVENTS, r as normalizePageName, i as theculturepostAnalytics };
|
|
134
|
+
|
|
135
|
+
//# sourceMappingURL=theculturepostAnalytics.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"theculturepostAnalytics.js","names":[],"sources":["../../../src/theculturepost/analytics/theculturepostAnalytics.ts"],"sourcesContent":["/**\n * TheCulturePost product analytics (BOFF-3167).\n *\n * The activation and engagement events this MFE emits on the shared fe-libs\n * event bus. The MFE never talks to Rybbit: the app shell's RybbitSink forwards\n * the names in `THECULTUREPOST_RYBBIT_EVENTS` (fe-libs\n * `shared/events/theculturepost.ts`), and the other sinks (BroadcastChannel,\n * OTel, devtools) see every event.\n *\n * The event dictionary (firing rules, dimensions, funnels, backend twins) is\n * `theculturepost-specs/business/status/ANALYTICS_PLAN.md`. Keep the names\n * here, the fe-libs taxonomy and that plan identical.\n *\n * Payload rule: ids are carried for the bus sinks, but RybbitSink strips every\n * identifier key before Rybbit. Never put titles, story bodies, citation text,\n * narrator names, transcripts, reply text or a contributor's tradition or\n * perspective in a payload: the builders below only read ids, enums and flags.\n */\nimport type {\n TcpArchiveItem,\n TcpCitation,\n TcpCollection,\n TcpDiscussion,\n TcpOralHistory,\n TcpReply,\n TcpStory,\n} from '../types';\n\n/** Every TheCulturePost analytics event this MFE emits. */\nexport const THECULTUREPOST_ANALYTICS_EVENTS = {\n pageViewed: 'theculturepost.page.viewed',\n storyDraftCreated: 'theculturepost.story.draft_created',\n storyPublished: 'theculturepost.story.published',\n storySaved: 'theculturepost.story.saved',\n citationAttached: 'theculturepost.citation.attached',\n collectionCreated: 'theculturepost.collection.created',\n archiveItemUploaded: 'theculturepost.archive_item.uploaded',\n oralHistoryRecorded: 'theculturepost.oral_history.recorded',\n discussionOpened: 'theculturepost.discussion.opened',\n discussionReplied: 'theculturepost.discussion.replied',\n} as const;\n\nexport type TheculturepostAnalyticsEventName =\n (typeof THECULTUREPOST_ANALYTICS_EVENTS)[keyof typeof THECULTUREPOST_ANALYTICS_EVENTS];\n\n/** A single bus emission: the event name and its payload. */\nexport interface TheculturepostAnalyticsEmission {\n name: TheculturepostAnalyticsEventName;\n payload: Record<string, string | boolean | undefined>;\n}\n\n/** Top-level sections whose second path part is an entity id (`/stories/:id`). */\nconst ENTITY_SECTIONS = new Set(['stories', 'topics', 'discussions']);\n\n/** Allowed shape of a route word; ids, slugs and anything else never match. */\nconst PAGE_WORD = /^[a-z][a-z-]*$/;\n\n/**\n * Turns a pathname (already stripped of the MFE base path) into a stable,\n * low-cardinality page key, mirroring the MFE routes:\n * `/` -> `home`, `/stories` -> `stories`, `/stories/:id` -> `stories.detail`,\n * `/stories/:id/citations` -> `stories.citations`,\n * `/archive/collections/:id` -> `archive.collections`. Ids and slugs never\n * reach the key, so the dimension is safe for Rybbit.\n */\nexport function normalizePageName(pathname: string): string {\n const [first, second, third] = pathname.split('/').filter(Boolean);\n if (!first) return 'home';\n if (!PAGE_WORD.test(first)) return 'other';\n if (!second) return first;\n if (ENTITY_SECTIONS.has(first)) {\n return third && PAGE_WORD.test(third) ? `${first}.${third}` : `${first}.detail`;\n }\n return PAGE_WORD.test(second) ? `${first}.${second}` : `${first}.detail`;\n}\n\n/**\n * Pure payload builders. Kept separate from the hook so the exact shape that\n * reaches the bus is reviewable (and testable) without a React tree.\n */\nexport const theculturepostAnalytics = {\n pageViewed(workspaceId: string | undefined, pathname: string) {\n return {\n name: THECULTUREPOST_ANALYTICS_EVENTS.pageViewed,\n payload: { workspaceId, page: normalizePageName(pathname) },\n } satisfies TheculturepostAnalyticsEmission;\n },\n storyDraftCreated(story: Pick<TcpStory, 'id' | 'workspaceId' | 'topicId' | 'format'>) {\n return {\n name: THECULTUREPOST_ANALYTICS_EVENTS.storyDraftCreated,\n payload: {\n workspaceId: story.workspaceId,\n storyId: story.id,\n topicId: story.topicId ?? undefined,\n format: story.format,\n },\n } satisfies TheculturepostAnalyticsEmission;\n },\n storyPublished(\n story: Pick<TcpStory, 'id' | 'workspaceId' | 'topicId' | 'format'> & {\n citations?: readonly unknown[] | null;\n }\n ) {\n return {\n name: THECULTUREPOST_ANALYTICS_EVENTS.storyPublished,\n payload: {\n workspaceId: story.workspaceId,\n storyId: story.id,\n topicId: story.topicId ?? undefined,\n format: story.format,\n cited: (story.citations?.length ?? 0) > 0,\n },\n } satisfies TheculturepostAnalyticsEmission;\n },\n storySaved(workspaceId: string | undefined, storyId: string) {\n return {\n name: THECULTUREPOST_ANALYTICS_EVENTS.storySaved,\n payload: { workspaceId, storyId },\n } satisfies TheculturepostAnalyticsEmission;\n },\n citationAttached(\n citation: Pick<TcpCitation, 'id' | 'workspaceId' | 'storyId' | 'sourceType' | 'claimId'>\n ) {\n return {\n name: THECULTUREPOST_ANALYTICS_EVENTS.citationAttached,\n payload: {\n workspaceId: citation.workspaceId,\n storyId: citation.storyId,\n citationId: citation.id,\n sourceType: citation.sourceType,\n linkedToClaim: Boolean(citation.claimId),\n },\n } satisfies TheculturepostAnalyticsEmission;\n },\n collectionCreated(collection: Pick<TcpCollection, 'id' | 'workspaceId'>) {\n return {\n name: THECULTUREPOST_ANALYTICS_EVENTS.collectionCreated,\n payload: { workspaceId: collection.workspaceId, collectionId: collection.id },\n } satisfies TheculturepostAnalyticsEmission;\n },\n archiveItemUploaded(\n item: Pick<\n TcpArchiveItem,\n 'id' | 'workspaceId' | 'kind' | 'accessLevel' | 'collectionId' | 'file'\n >\n ) {\n return {\n name: THECULTUREPOST_ANALYTICS_EVENTS.archiveItemUploaded,\n payload: {\n workspaceId: item.workspaceId,\n archiveItemId: item.id,\n collectionId: item.collectionId ?? undefined,\n kind: item.kind,\n accessLevel: item.accessLevel,\n hasFile: Boolean(item.file),\n },\n } satisfies TheculturepostAnalyticsEmission;\n },\n oralHistoryRecorded(\n oralHistory: Pick<\n TcpOralHistory,\n 'id' | 'workspaceId' | 'accessLevel' | 'collectionId' | 'recording'\n >\n ) {\n return {\n name: THECULTUREPOST_ANALYTICS_EVENTS.oralHistoryRecorded,\n payload: {\n workspaceId: oralHistory.workspaceId,\n oralHistoryId: oralHistory.id,\n collectionId: oralHistory.collectionId ?? undefined,\n accessLevel: oralHistory.accessLevel,\n hasRecording: Boolean(oralHistory.recording),\n },\n } satisfies TheculturepostAnalyticsEmission;\n },\n discussionOpened(\n discussion: Pick<TcpDiscussion, 'id' | 'workspaceId' | 'storyId' | 'isInterfaith'>\n ) {\n return {\n name: THECULTUREPOST_ANALYTICS_EVENTS.discussionOpened,\n payload: {\n workspaceId: discussion.workspaceId,\n discussionId: discussion.id,\n storyId: discussion.storyId ?? undefined,\n isInterfaith: discussion.isInterfaith,\n },\n } satisfies TheculturepostAnalyticsEmission;\n },\n discussionReplied(reply: Pick<TcpReply, 'id' | 'workspaceId' | 'discussionId'>) {\n return {\n name: THECULTUREPOST_ANALYTICS_EVENTS.discussionReplied,\n payload: {\n workspaceId: reply.workspaceId,\n discussionId: reply.discussionId,\n replyId: reply.id,\n },\n } satisfies TheculturepostAnalyticsEmission;\n },\n};\n"],"mappings":";AA6BA,IAAa,IAAkC;CAC7C,YAAY;CACZ,mBAAmB;CACnB,gBAAgB;CAChB,YAAY;CACZ,kBAAkB;CAClB,mBAAmB;CACnB,qBAAqB;CACrB,qBAAqB;CACrB,kBAAkB;CAClB,mBAAmB;CACpB,EAYK,IAAkB,IAAI,IAAI;CAAC;CAAW;CAAU;CAAc,CAAC,EAG/D,IAAY;AAUlB,SAAgB,EAAkB,GAA0B;CAC1D,IAAM,CAAC,GAAO,GAAQ,KAAS,EAAS,MAAM,IAAI,CAAC,OAAO,QAAQ;AAOlE,QANK,IACA,EAAU,KAAK,EAAM,GACrB,IACD,EAAgB,IAAI,EAAM,GACrB,KAAS,EAAU,KAAK,EAAM,GAAG,GAAG,EAAM,GAAG,MAAU,GAAG,EAAM,WAElE,EAAU,KAAK,EAAO,GAAG,GAAG,EAAM,GAAG,MAAW,GAAG,EAAM,WAJ5C,IADe,UADhB;;AAarB,IAAa,IAA0B;CACrC,WAAW,GAAiC,GAAkB;AAC5D,SAAO;GACL,MAAM,EAAgC;GACtC,SAAS;IAAE;IAAa,MAAM,EAAkB,EAAS;IAAE;GAC5D;;CAEH,kBAAkB,GAAoE;AACpF,SAAO;GACL,MAAM,EAAgC;GACtC,SAAS;IACP,aAAa,EAAM;IACnB,SAAS,EAAM;IACf,SAAS,EAAM,WAAW,KAAA;IAC1B,QAAQ,EAAM;IACf;GACF;;CAEH,eACE,GAGA;AACA,SAAO;GACL,MAAM,EAAgC;GACtC,SAAS;IACP,aAAa,EAAM;IACnB,SAAS,EAAM;IACf,SAAS,EAAM,WAAW,KAAA;IAC1B,QAAQ,EAAM;IACd,QAAQ,EAAM,WAAW,UAAU,KAAK;IACzC;GACF;;CAEH,WAAW,GAAiC,GAAiB;AAC3D,SAAO;GACL,MAAM,EAAgC;GACtC,SAAS;IAAE;IAAa;IAAS;GAClC;;CAEH,iBACE,GACA;AACA,SAAO;GACL,MAAM,EAAgC;GACtC,SAAS;IACP,aAAa,EAAS;IACtB,SAAS,EAAS;IAClB,YAAY,EAAS;IACrB,YAAY,EAAS;IACrB,eAAe,EAAQ,EAAS;IACjC;GACF;;CAEH,kBAAkB,GAAuD;AACvE,SAAO;GACL,MAAM,EAAgC;GACtC,SAAS;IAAE,aAAa,EAAW;IAAa,cAAc,EAAW;IAAI;GAC9E;;CAEH,oBACE,GAIA;AACA,SAAO;GACL,MAAM,EAAgC;GACtC,SAAS;IACP,aAAa,EAAK;IAClB,eAAe,EAAK;IACpB,cAAc,EAAK,gBAAgB,KAAA;IACnC,MAAM,EAAK;IACX,aAAa,EAAK;IAClB,SAAS,EAAQ,EAAK;IACvB;GACF;;CAEH,oBACE,GAIA;AACA,SAAO;GACL,MAAM,EAAgC;GACtC,SAAS;IACP,aAAa,EAAY;IACzB,eAAe,EAAY;IAC3B,cAAc,EAAY,gBAAgB,KAAA;IAC1C,aAAa,EAAY;IACzB,cAAc,EAAQ,EAAY;IACnC;GACF;;CAEH,iBACE,GACA;AACA,SAAO;GACL,MAAM,EAAgC;GACtC,SAAS;IACP,aAAa,EAAW;IACxB,cAAc,EAAW;IACzB,SAAS,EAAW,WAAW,KAAA;IAC/B,cAAc,EAAW;IAC1B;GACF;;CAEH,kBAAkB,GAA8D;AAC9E,SAAO;GACL,MAAM,EAAgC;GACtC,SAAS;IACP,aAAa,EAAM;IACnB,cAAc,EAAM;IACpB,SAAS,EAAM;IAChB;GACF;;CAEJ"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { TheculturepostAnalyticsEmission } from './theculturepostAnalytics';
|
|
2
|
+
|
|
3
|
+
export type TheculturepostAnalyticsSend = (emission: TheculturepostAnalyticsEmission) => void;
|
|
4
|
+
export declare function useTheculturepostAnalytics(): TheculturepostAnalyticsSend;
|
|
5
|
+
//# sourceMappingURL=useTheculturepostAnalytics.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useTheculturepostAnalytics.d.ts","sourceRoot":"","sources":["../../../src/theculturepost/analytics/useTheculturepostAnalytics.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,+BAA+B,EAAE,MAAM,2BAA2B,CAAC;AAEjF,MAAM,MAAM,2BAA2B,GAAG,CAAC,QAAQ,EAAE,+BAA+B,KAAK,IAAI,CAAC;AAE9F,wBAAgB,0BAA0B,IAAI,2BAA2B,CAexE"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { useCallback as e } from "react";
|
|
2
|
+
import { useEventBus as t } from "@burdenoff/fe-libs/shared/events";
|
|
3
|
+
//#region src/theculturepost/analytics/useTheculturepostAnalytics.ts
|
|
4
|
+
function n() {
|
|
5
|
+
let n = t();
|
|
6
|
+
return e((e) => {
|
|
7
|
+
try {
|
|
8
|
+
n.emitCustom(e.name, e.payload);
|
|
9
|
+
} catch {}
|
|
10
|
+
}, [n]);
|
|
11
|
+
}
|
|
12
|
+
//#endregion
|
|
13
|
+
export { n as useTheculturepostAnalytics };
|
|
14
|
+
|
|
15
|
+
//# sourceMappingURL=useTheculturepostAnalytics.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useTheculturepostAnalytics.js","names":[],"sources":["../../../src/theculturepost/analytics/useTheculturepostAnalytics.ts"],"sourcesContent":["/**\n * React hook that emits TheCulturePost analytics events on the shared event bus.\n *\n * `send` is fire-and-forget and never throws: analytics must not be able to\n * break a contributor's draft, citation, upload or reply. Outside an app shell\n * (Storybook, standalone) the bus context is a no-op, so calls are inert.\n */\nimport { useCallback } from 'react';\nimport { useEventBus } from '@burdenoff/fe-libs/shared/events';\n\nimport type { TheculturepostAnalyticsEmission } from './theculturepostAnalytics';\n\nexport type TheculturepostAnalyticsSend = (emission: TheculturepostAnalyticsEmission) => void;\n\nexport function useTheculturepostAnalytics(): TheculturepostAnalyticsSend {\n const bus = useEventBus();\n return useCallback(\n (emission: TheculturepostAnalyticsEmission) => {\n try {\n // emitCustom: the names are registered in fe-libs' BurdenoffEventName\n // union from the fe-libs release that ships the TheCulturePost taxonomy;\n // the runtime path (bus.onAny -> sinks) is identical to emit().\n bus.emitCustom(emission.name, emission.payload);\n } catch {\n /* analytics is best-effort and must never break the contributor flow */\n }\n },\n [bus]\n );\n}\n"],"mappings":";;;AAcA,SAAgB,IAA0D;CACxE,IAAM,IAAM,GAAa;AACzB,QAAO,GACJ,MAA8C;AAC7C,MAAI;AAIF,KAAI,WAAW,EAAS,MAAM,EAAS,QAAQ;UACzC;IAIV,CAAC,EAAI,CACN"}
|
|
@@ -1,9 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Page-view analytics hook for TheCulturePost.
|
|
2
|
+
* Page-view analytics hook for TheCulturePost (BOFF-3167).
|
|
3
3
|
*
|
|
4
|
-
* Emits
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* Emits `theculturepost.page.viewed` on the shared event bus every time the
|
|
5
|
+
* MFE route changes. The shell's RybbitSink forwards it (it is in fe-libs'
|
|
6
|
+
* `THECULTUREPOST_RYBBIT_EVENTS`) once the visitor has granted analytics
|
|
7
|
+
* consent. The payload is the normalised page key only (`stories.detail`,
|
|
8
|
+
* never the raw path with an id in it), plus the workspace id, which the sink
|
|
9
|
+
* strips before Rybbit.
|
|
10
|
+
*
|
|
11
|
+
* Driven by the router location rather than `popstate`: in-app navigation is
|
|
12
|
+
* `history.pushState`, which never fires `popstate`, so the earlier listener
|
|
13
|
+
* only ever reported the first screen and back/forward moves.
|
|
7
14
|
*/
|
|
15
|
+
/** Strips the MFE mount path so `/culture/stories` and `/stories` map to the same key. */
|
|
16
|
+
export declare function stripBasePath(pathname: string, basePath: string | undefined): string;
|
|
8
17
|
export declare function usePageAnalytics(): void;
|
|
9
18
|
//# sourceMappingURL=usePageAnalytics.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usePageAnalytics.d.ts","sourceRoot":"","sources":["../../../src/theculturepost/hooks/usePageAnalytics.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"usePageAnalytics.d.ts","sourceRoot":"","sources":["../../../src/theculturepost/hooks/usePageAnalytics.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAQH,0FAA0F;AAC1F,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAKpF;AAED,wBAAgB,gBAAgB,IAAI,IAAI,CAQvC"}
|
|
@@ -1,34 +1,27 @@
|
|
|
1
1
|
import { useTheCulturePost as e } from "../context/TheCulturePostContext.js";
|
|
2
|
+
import { theculturepostAnalytics as t } from "../analytics/theculturepostAnalytics.js";
|
|
3
|
+
import { useTheculturepostAnalytics as n } from "../analytics/useTheculturepostAnalytics.js";
|
|
4
|
+
import "../analytics/index.js";
|
|
2
5
|
import "../context/index.js";
|
|
3
|
-
import { useEffect as
|
|
4
|
-
import {
|
|
6
|
+
import { useEffect as r } from "react";
|
|
7
|
+
import { useLocation as i } from "react-router";
|
|
5
8
|
//#region src/theculturepost/hooks/usePageAnalytics.ts
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
return t.length <= 1 ? n : [
|
|
10
|
-
"stories",
|
|
11
|
-
"topics",
|
|
12
|
-
"discussions",
|
|
13
|
-
"archive"
|
|
14
|
-
].includes(t[1] ?? "") ? t.length >= 3 ? `${t[1]}.detail` : t[1] ?? n : t.slice(1).join(".");
|
|
9
|
+
function a(e, t) {
|
|
10
|
+
let n = t && t !== "/" ? t.replace(/\/$/, "") : "";
|
|
11
|
+
return n ? e === n ? "/" : e.startsWith(`${n}/`) ? e.slice(n.length) : e : e;
|
|
15
12
|
}
|
|
16
|
-
function
|
|
17
|
-
let
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
});
|
|
27
|
-
};
|
|
28
|
-
return e(), window.addEventListener("popstate", e), () => window.removeEventListener("popstate", e);
|
|
29
|
-
}, [o, a]);
|
|
13
|
+
function o() {
|
|
14
|
+
let o = n(), { basePath: s, workspaceId: c } = e(), { pathname: l } = i();
|
|
15
|
+
r(() => {
|
|
16
|
+
o(t.pageViewed(c, a(l, s)));
|
|
17
|
+
}, [
|
|
18
|
+
s,
|
|
19
|
+
l,
|
|
20
|
+
o,
|
|
21
|
+
c
|
|
22
|
+
]);
|
|
30
23
|
}
|
|
31
24
|
//#endregion
|
|
32
|
-
export { a as usePageAnalytics };
|
|
25
|
+
export { a as stripBasePath, o as usePageAnalytics };
|
|
33
26
|
|
|
34
27
|
//# sourceMappingURL=usePageAnalytics.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usePageAnalytics.js","names":[],"sources":["../../../src/theculturepost/hooks/usePageAnalytics.ts"],"sourcesContent":["/**\n * Page-view analytics hook for TheCulturePost.\n *\n * Emits
|
|
1
|
+
{"version":3,"file":"usePageAnalytics.js","names":[],"sources":["../../../src/theculturepost/hooks/usePageAnalytics.ts"],"sourcesContent":["/**\n * Page-view analytics hook for TheCulturePost (BOFF-3167).\n *\n * Emits `theculturepost.page.viewed` on the shared event bus every time the\n * MFE route changes. The shell's RybbitSink forwards it (it is in fe-libs'\n * `THECULTUREPOST_RYBBIT_EVENTS`) once the visitor has granted analytics\n * consent. The payload is the normalised page key only (`stories.detail`,\n * never the raw path with an id in it), plus the workspace id, which the sink\n * strips before Rybbit.\n *\n * Driven by the router location rather than `popstate`: in-app navigation is\n * `history.pushState`, which never fires `popstate`, so the earlier listener\n * only ever reported the first screen and back/forward moves.\n */\n\nimport { useEffect } from 'react';\nimport { useLocation } from 'react-router';\n\nimport { theculturepostAnalytics, useTheculturepostAnalytics } from '../analytics';\nimport { useTheCulturePost } from '../context';\n\n/** Strips the MFE mount path so `/culture/stories` and `/stories` map to the same key. */\nexport function stripBasePath(pathname: string, basePath: string | undefined): string {\n const base = basePath && basePath !== '/' ? basePath.replace(/\\/$/, '') : '';\n if (!base) return pathname;\n if (pathname === base) return '/';\n return pathname.startsWith(`${base}/`) ? pathname.slice(base.length) : pathname;\n}\n\nexport function usePageAnalytics(): void {\n const send = useTheculturepostAnalytics();\n const { basePath, workspaceId } = useTheCulturePost();\n const { pathname } = useLocation();\n\n useEffect(() => {\n send(theculturepostAnalytics.pageViewed(workspaceId, stripBasePath(pathname, basePath)));\n }, [basePath, pathname, send, workspaceId]);\n}\n"],"mappings":";;;;;;;;AAsBA,SAAgB,EAAc,GAAkB,GAAsC;CACpF,IAAM,IAAO,KAAY,MAAa,MAAM,EAAS,QAAQ,OAAO,GAAG,GAAG;AAG1E,QAFK,IACD,MAAa,IAAa,MACvB,EAAS,WAAW,GAAG,EAAK,GAAG,GAAG,EAAS,MAAM,EAAK,OAAO,GAAG,IAFrD;;AAKpB,SAAgB,IAAyB;CACvC,IAAM,IAAO,GAA4B,EACnC,EAAE,aAAU,mBAAgB,GAAmB,EAC/C,EAAE,gBAAa,GAAa;AAElC,SAAgB;AACd,IAAK,EAAwB,WAAW,GAAa,EAAc,GAAU,EAAS,CAAC,CAAC;IACvF;EAAC;EAAU;EAAU;EAAM;EAAY,CAAC"}
|
|
@@ -50,14 +50,14 @@ export declare const useTcpTopic: (id: string | undefined) => import('@tanstack/
|
|
|
50
50
|
stories: TcpStory[];
|
|
51
51
|
workspaceId: string;
|
|
52
52
|
id: string;
|
|
53
|
-
name: string;
|
|
54
|
-
description?: string | null | undefined;
|
|
55
53
|
slug: string;
|
|
56
54
|
isFeatured: boolean;
|
|
57
55
|
createdAt: string;
|
|
58
56
|
updatedAt: string;
|
|
59
|
-
|
|
57
|
+
name: string;
|
|
58
|
+
description?: string | null | undefined;
|
|
60
59
|
tradition?: string | null | undefined;
|
|
60
|
+
category: TcpTopicCategory;
|
|
61
61
|
storyCount: number;
|
|
62
62
|
} | null, Error>;
|
|
63
63
|
export declare const useTcpCreateTopic: () => import('@tanstack/react-query').UseMutationResult<TcpTopic, Error, TcpCreateTopicInput, unknown>;
|
|
@@ -82,9 +82,9 @@ export declare const useTcpDiscussion: (id: string | undefined) => import('@tans
|
|
|
82
82
|
createdAt: string;
|
|
83
83
|
updatedAt: string;
|
|
84
84
|
storyId?: string | null | undefined;
|
|
85
|
+
isInterfaith: boolean;
|
|
85
86
|
prompt?: string | null | undefined;
|
|
86
87
|
openedById?: string | null | undefined;
|
|
87
|
-
isInterfaith: boolean;
|
|
88
88
|
isLocked: boolean;
|
|
89
89
|
replyCount: number;
|
|
90
90
|
} | null, Error>;
|
|
@@ -102,12 +102,12 @@ export declare const useTcpCollection: (id: string | undefined) => import('@tans
|
|
|
102
102
|
oralHistories: TcpOralHistory[];
|
|
103
103
|
workspaceId: string;
|
|
104
104
|
id: string;
|
|
105
|
-
name: string;
|
|
106
|
-
description?: string | null | undefined;
|
|
107
105
|
slug: string;
|
|
108
106
|
cover?: (import('../types').TcpFileRef | null) | undefined;
|
|
109
107
|
createdAt: string;
|
|
110
108
|
updatedAt: string;
|
|
109
|
+
name: string;
|
|
110
|
+
description?: string | null | undefined;
|
|
111
111
|
tradition?: string | null | undefined;
|
|
112
112
|
itemCount: number;
|
|
113
113
|
} | null, Error>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useTcpApi.d.ts","sourceRoot":"","sources":["../../../src/theculturepost/hooks/useTcpApi.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;
|
|
1
|
+
{"version":3,"file":"useTcpApi.d.ts","sourceRoot":"","sources":["../../../src/theculturepost/hooks/useTcpApi.ts"],"names":[],"mappings":"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"}
|