@financial-times/qanda-ui 0.0.1-beta.33 → 0.0.1-beta.34
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/cjs/services/comments-api.js +28 -17
- package/dist/cjs/services/listeners-middleware.js +76 -27
- package/dist/cjs/store/updateComments.js +1 -1
- package/dist/esm/services/comments-api.js +28 -17
- package/dist/esm/services/listeners-middleware.js +76 -27
- package/dist/esm/store/updateComments.js +1 -1
- package/dist/types/services/comments-api.d.ts +6 -37
- package/dist/types/store/index.d.ts +40 -200
- package/package.json +1 -1
|
@@ -48,18 +48,16 @@ exports.nextCommentsApi = (0, react_1.createApi)({
|
|
|
48
48
|
console.log(`Connected to SSE: ${sseEndpoint}`);
|
|
49
49
|
const state = getState();
|
|
50
50
|
const lastEventId = state.stream.mostRecentUpdateTime;
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
reliability_1.qandaReliability.failure('qa-updates', error);
|
|
62
|
-
}
|
|
51
|
+
try {
|
|
52
|
+
await dispatch(exports.nextCommentsApi.endpoints.getCatchupUpdates.initiate({
|
|
53
|
+
storyId: arg.storyId,
|
|
54
|
+
useStaging: arg.useStaging,
|
|
55
|
+
commentsAPIUrl: arg.commentsAPIUrl,
|
|
56
|
+
...(lastEventId && { lastEventId: `${lastEventId}` }),
|
|
57
|
+
}, { forceRefetch: true }));
|
|
58
|
+
}
|
|
59
|
+
catch (error) {
|
|
60
|
+
reliability_1.qandaReliability.failure('qa-updates', error);
|
|
63
61
|
}
|
|
64
62
|
};
|
|
65
63
|
exports.eventSource.onmessage = (event) => {
|
|
@@ -117,14 +115,27 @@ exports.nextCommentsApi = (0, react_1.createApi)({
|
|
|
117
115
|
}),
|
|
118
116
|
// CATCHUP UPDATES
|
|
119
117
|
getCatchupUpdates: builder.query({
|
|
120
|
-
query: ({ storyId, useStaging, commentsAPIUrl, lastEventId, }) =>
|
|
118
|
+
query: ({ storyId, useStaging, commentsAPIUrl, lastEventId, }) => {
|
|
119
|
+
const params = new URLSearchParams();
|
|
120
|
+
if (useStaging) {
|
|
121
|
+
params.append('staging', '1');
|
|
122
|
+
}
|
|
123
|
+
if (lastEventId) {
|
|
124
|
+
params.append('lastEventId', lastEventId);
|
|
125
|
+
}
|
|
126
|
+
const queryString = params.toString();
|
|
127
|
+
return `${commentsAPIUrl}/story/${storyId}/catchup-updates${queryString ? `?${queryString}` : ''}`;
|
|
128
|
+
},
|
|
121
129
|
transformResponse: (response) => {
|
|
122
|
-
const updatedComments = response?.comments
|
|
123
|
-
|
|
124
|
-
|
|
130
|
+
const updatedComments = Array.isArray(response?.comments)
|
|
131
|
+
? response.comments.map((comment) => {
|
|
132
|
+
return comment.data;
|
|
133
|
+
})
|
|
134
|
+
: [];
|
|
125
135
|
return {
|
|
126
136
|
updatedComments,
|
|
127
|
-
|
|
137
|
+
status: response?.status ?? null,
|
|
138
|
+
lastEventId: response?.lastEventId ?? null,
|
|
128
139
|
};
|
|
129
140
|
},
|
|
130
141
|
}),
|
|
@@ -18,7 +18,7 @@ exports.listenerMiddleware = (0, toolkit_1.createListenerMiddleware)();
|
|
|
18
18
|
* Calculates the most recent update timestamp and answer id from a Q&A question
|
|
19
19
|
*
|
|
20
20
|
* @param qandas - A Comment object representing a question with nested answers
|
|
21
|
-
* @returns Object containing mostRecentUpdateTime (timestamp) and mostRecentUpdateId (answer id)
|
|
21
|
+
* @returns Object containing mostRecentUpdateTime (answer timestamp) and mostRecentUpdateId (answer id)
|
|
22
22
|
*
|
|
23
23
|
* @example
|
|
24
24
|
* const { mostRecentUpdateTime, mostRecentUpdateId } = getMostRecentUpdate(qandas);
|
|
@@ -38,6 +38,28 @@ function getMostRecentUpdate(qandaComment) {
|
|
|
38
38
|
}
|
|
39
39
|
return { mostRecentUpdateTime, mostRecentUpdateId };
|
|
40
40
|
}
|
|
41
|
+
/**
|
|
42
|
+
* Shallow compares two StreamStatus objects to determine if they are identical
|
|
43
|
+
*
|
|
44
|
+
* Performs a shallow comparison of all properties between the previous and new status
|
|
45
|
+
* entries. Used to prevent unnecessary updates when the status hasn't actually changed.
|
|
46
|
+
*
|
|
47
|
+
* @param previousEntry - The previous StreamStatus object to compare
|
|
48
|
+
* @param newEntry - The new StreamStatus object to compare against
|
|
49
|
+
* @returns True if all properties are identical, false otherwise
|
|
50
|
+
*/
|
|
51
|
+
function isSameStatus(previousEntry, newEntry) {
|
|
52
|
+
if (Object.keys(previousEntry).length !== Object.keys(newEntry).length) {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
for (const key in previousEntry) {
|
|
56
|
+
const typedKey = key;
|
|
57
|
+
if (previousEntry[typedKey] !== newEntry[typedKey]) {
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return true;
|
|
62
|
+
}
|
|
41
63
|
/**
|
|
42
64
|
* Listener: Updates most recent timestamp and initiates catchup when live Q&A stream data is fetched
|
|
43
65
|
*
|
|
@@ -51,12 +73,17 @@ function getMostRecentUpdate(qandaComment) {
|
|
|
51
73
|
* @dispatches setStreamStartMostRecentAnswerId - Updates stream.streamStartMostRecentAnswerId in Redux store
|
|
52
74
|
* @dispatches nextCommentsApi.endpoints.getCatchupUpdates.initiate - Triggers catchup request for missed updates
|
|
53
75
|
*/
|
|
76
|
+
// TODO: consider when this should run now that we have state changes too.
|
|
77
|
+
// consider that it will run on every live stream query, not just the first one.
|
|
78
|
+
// therefore it will happen on state change, and on first load maybe twice.
|
|
54
79
|
exports.listenerMiddleware.startListening({
|
|
55
80
|
matcher: (0, toolkit_1.isAnyOf)(comments_api_1.nextCommentsApi.endpoints.getQandAStream.matchFulfilled),
|
|
56
81
|
effect: (action, listenerApi) => {
|
|
82
|
+
const state = listenerApi.getState();
|
|
57
83
|
const { payload, meta } = action;
|
|
58
84
|
const { storyId, useStaging, commentsAPIUrl, status } = meta.arg.originalArgs;
|
|
59
|
-
// Check if this is a live stream QUERY, not response. If it is a live
|
|
85
|
+
// Check if this is a live stream QUERY, not response. If it is a live QUERY we will get questions and answers. This will fire when stream starts in live mode or switches to live mode for first time.
|
|
86
|
+
const isPreLiveStream = status === 'pre-live';
|
|
60
87
|
const isLiveStream = status === 'live';
|
|
61
88
|
if (isLiveStream &&
|
|
62
89
|
Array.isArray(payload.qandas) &&
|
|
@@ -68,54 +95,76 @@ exports.listenerMiddleware.startListening({
|
|
|
68
95
|
listenerApi.dispatch((0, stream_1.setMostRecentUpdateTime)(`${mostRecentUpdateTime}`));
|
|
69
96
|
listenerApi.dispatch((0, stream_1.setStreamLoadMostRecentAnswerId)(mostRecentUpdateId));
|
|
70
97
|
}
|
|
98
|
+
}
|
|
99
|
+
const { mostRecentUpdateTime } = state.stream;
|
|
100
|
+
if (isPreLiveStream || isLiveStream) {
|
|
71
101
|
listenerApi.dispatch(comments_api_1.nextCommentsApi.endpoints.getCatchupUpdates.initiate({
|
|
72
|
-
storyId
|
|
73
|
-
useStaging
|
|
74
|
-
commentsAPIUrl
|
|
75
|
-
|
|
102
|
+
storyId,
|
|
103
|
+
useStaging,
|
|
104
|
+
commentsAPIUrl,
|
|
105
|
+
...(mostRecentUpdateTime && {
|
|
106
|
+
lastEventId: `${mostRecentUpdateTime}`,
|
|
107
|
+
}),
|
|
76
108
|
}));
|
|
77
109
|
}
|
|
78
110
|
},
|
|
79
111
|
});
|
|
80
112
|
/**
|
|
81
|
-
* Listener:
|
|
113
|
+
* Listener: Processes successful catchup updates and manages comment/status updates
|
|
82
114
|
*
|
|
83
|
-
* Responds to successful getCatchupUpdates queries and
|
|
84
|
-
*
|
|
85
|
-
*
|
|
115
|
+
* Responds to successful getCatchupUpdates queries and processes the response:
|
|
116
|
+
* - Adds new comments to the updates cache, filtering out duplicates
|
|
117
|
+
* - Updates status when changes are detected compared to the last status
|
|
118
|
+
* - Updates the most recent timestamp for future catchup requests
|
|
86
119
|
*
|
|
87
120
|
* @listens nextCommentsApi.endpoints.getCatchupUpdates.matchFulfilled
|
|
88
121
|
* @dispatches nextCommentsApi.util.updateQueryData - Updates the cache of updated comments in the store
|
|
89
122
|
* @dispatches setMostRecentUpdateTime - Updates stream.mostRecentUpdateTime with new lastEventId
|
|
123
|
+
* @dispatches nextCommentsApi.util.updateQueryData - Updates the status if it has changed
|
|
90
124
|
*/
|
|
91
125
|
exports.listenerMiddleware.startListening({
|
|
92
126
|
matcher: comments_api_1.nextCommentsApi.endpoints.getCatchupUpdates.matchFulfilled,
|
|
93
127
|
effect: (action, listenerApi) => {
|
|
94
128
|
const { payload, meta } = action;
|
|
95
129
|
const { storyId, useStaging, commentsAPIUrl } = meta.arg.originalArgs;
|
|
96
|
-
const { updatedComments, lastEventId } = payload;
|
|
97
|
-
if (!updatedComments)
|
|
130
|
+
const { updatedComments, status, lastEventId = null } = payload;
|
|
131
|
+
if (!updatedComments && !status)
|
|
98
132
|
return;
|
|
99
|
-
console.log('Received catchup updates, new event id:', lastEventId);
|
|
100
|
-
const updateType = comments_api_1.updateTypes['QA_NEW_REPLY'];
|
|
101
133
|
const state = listenerApi.getState();
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
134
|
+
// check for new updated comments
|
|
135
|
+
if (Array.isArray(updatedComments) && updatedComments.length > 0) {
|
|
136
|
+
const updateType = comments_api_1.updateTypes['QA_NEW_REPLY'];
|
|
137
|
+
const { streamLoadMostRecentAnswerId, mostRecentUpdateTime: mostRecentInStreamTime, } = state.stream;
|
|
138
|
+
// filter out catchup comments that are the same as the most recent update in the stream list, which can happen on first load when the valkey and coral response timestamps don't match
|
|
139
|
+
// there is latency between the comment being saved in coral and then added to our valkey stream. Updates after this will all come from valkey.
|
|
140
|
+
const filteredComments = updatedComments.filter((comment) => {
|
|
141
|
+
const { mostRecentUpdateId, mostRecentUpdateTime } = getMostRecentUpdate(comment);
|
|
142
|
+
if (streamLoadMostRecentAnswerId === mostRecentUpdateId &&
|
|
143
|
+
mostRecentInStreamTime === `${mostRecentUpdateTime}`) {
|
|
144
|
+
return false;
|
|
145
|
+
}
|
|
146
|
+
return true;
|
|
147
|
+
});
|
|
148
|
+
if (Array.isArray(filteredComments) && filteredComments.length) {
|
|
149
|
+
listenerApi.dispatch(comments_api_1.nextCommentsApi.util.updateQueryData('getQandAUpdates', { storyId, useStaging, commentsAPIUrl }, (draft) => {
|
|
150
|
+
draft[updateType] = draft[updateType] || [];
|
|
151
|
+
draft[updateType].push(...filteredComments);
|
|
152
|
+
}));
|
|
110
153
|
}
|
|
111
|
-
|
|
112
|
-
}
|
|
113
|
-
|
|
154
|
+
listenerApi.dispatch((0, stream_1.setMostRecentUpdateTime)(lastEventId));
|
|
155
|
+
}
|
|
156
|
+
// check for status updates
|
|
157
|
+
if (status) {
|
|
158
|
+
const updateType = comments_api_1.updateTypes['QA_UPDATE'];
|
|
114
159
|
listenerApi.dispatch(comments_api_1.nextCommentsApi.util.updateQueryData('getQandAUpdates', { storyId, useStaging, commentsAPIUrl }, (draft) => {
|
|
115
160
|
draft[updateType] = draft[updateType] || [];
|
|
116
|
-
|
|
161
|
+
// in order to avoid unnecessary updates, we check if the last update is identical to the new status. we only push changed status updates.
|
|
162
|
+
if (draft[updateType].length > 0 &&
|
|
163
|
+
isSameStatus(draft[updateType].at(-1), status)) {
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
draft[updateType] = [status];
|
|
117
167
|
}));
|
|
118
168
|
}
|
|
119
|
-
listenerApi.dispatch((0, stream_1.setMostRecentUpdateTime)(lastEventId));
|
|
120
169
|
},
|
|
121
170
|
});
|
|
@@ -34,7 +34,7 @@ const updateComments = (dispatch, updatedComments, storyId, useStaging, comments
|
|
|
34
34
|
dispatch((0, stream_1.setLatestAnsweredQuestionId)(latestAnsweredQuestionId));
|
|
35
35
|
}
|
|
36
36
|
catch (error) {
|
|
37
|
-
console.
|
|
37
|
+
console.error('error', error);
|
|
38
38
|
}
|
|
39
39
|
};
|
|
40
40
|
exports.updateComments = updateComments;
|
|
@@ -45,18 +45,16 @@ export const nextCommentsApi = createApi({
|
|
|
45
45
|
console.log(`Connected to SSE: ${sseEndpoint}`);
|
|
46
46
|
const state = getState();
|
|
47
47
|
const lastEventId = state.stream.mostRecentUpdateTime;
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
qandaReliability.failure('qa-updates', error);
|
|
59
|
-
}
|
|
48
|
+
try {
|
|
49
|
+
await dispatch(nextCommentsApi.endpoints.getCatchupUpdates.initiate({
|
|
50
|
+
storyId: arg.storyId,
|
|
51
|
+
useStaging: arg.useStaging,
|
|
52
|
+
commentsAPIUrl: arg.commentsAPIUrl,
|
|
53
|
+
...(lastEventId && { lastEventId: `${lastEventId}` }),
|
|
54
|
+
}, { forceRefetch: true }));
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
qandaReliability.failure('qa-updates', error);
|
|
60
58
|
}
|
|
61
59
|
};
|
|
62
60
|
eventSource.onmessage = (event) => {
|
|
@@ -114,14 +112,27 @@ export const nextCommentsApi = createApi({
|
|
|
114
112
|
}),
|
|
115
113
|
// CATCHUP UPDATES
|
|
116
114
|
getCatchupUpdates: builder.query({
|
|
117
|
-
query: ({ storyId, useStaging, commentsAPIUrl, lastEventId, }) =>
|
|
115
|
+
query: ({ storyId, useStaging, commentsAPIUrl, lastEventId, }) => {
|
|
116
|
+
const params = new URLSearchParams();
|
|
117
|
+
if (useStaging) {
|
|
118
|
+
params.append('staging', '1');
|
|
119
|
+
}
|
|
120
|
+
if (lastEventId) {
|
|
121
|
+
params.append('lastEventId', lastEventId);
|
|
122
|
+
}
|
|
123
|
+
const queryString = params.toString();
|
|
124
|
+
return `${commentsAPIUrl}/story/${storyId}/catchup-updates${queryString ? `?${queryString}` : ''}`;
|
|
125
|
+
},
|
|
118
126
|
transformResponse: (response) => {
|
|
119
|
-
const updatedComments = response?.comments
|
|
120
|
-
|
|
121
|
-
|
|
127
|
+
const updatedComments = Array.isArray(response?.comments)
|
|
128
|
+
? response.comments.map((comment) => {
|
|
129
|
+
return comment.data;
|
|
130
|
+
})
|
|
131
|
+
: [];
|
|
122
132
|
return {
|
|
123
133
|
updatedComments,
|
|
124
|
-
|
|
134
|
+
status: response?.status ?? null,
|
|
135
|
+
lastEventId: response?.lastEventId ?? null,
|
|
125
136
|
};
|
|
126
137
|
},
|
|
127
138
|
}),
|
|
@@ -15,7 +15,7 @@ export const listenerMiddleware = createListenerMiddleware();
|
|
|
15
15
|
* Calculates the most recent update timestamp and answer id from a Q&A question
|
|
16
16
|
*
|
|
17
17
|
* @param qandas - A Comment object representing a question with nested answers
|
|
18
|
-
* @returns Object containing mostRecentUpdateTime (timestamp) and mostRecentUpdateId (answer id)
|
|
18
|
+
* @returns Object containing mostRecentUpdateTime (answer timestamp) and mostRecentUpdateId (answer id)
|
|
19
19
|
*
|
|
20
20
|
* @example
|
|
21
21
|
* const { mostRecentUpdateTime, mostRecentUpdateId } = getMostRecentUpdate(qandas);
|
|
@@ -35,6 +35,28 @@ function getMostRecentUpdate(qandaComment) {
|
|
|
35
35
|
}
|
|
36
36
|
return { mostRecentUpdateTime, mostRecentUpdateId };
|
|
37
37
|
}
|
|
38
|
+
/**
|
|
39
|
+
* Shallow compares two StreamStatus objects to determine if they are identical
|
|
40
|
+
*
|
|
41
|
+
* Performs a shallow comparison of all properties between the previous and new status
|
|
42
|
+
* entries. Used to prevent unnecessary updates when the status hasn't actually changed.
|
|
43
|
+
*
|
|
44
|
+
* @param previousEntry - The previous StreamStatus object to compare
|
|
45
|
+
* @param newEntry - The new StreamStatus object to compare against
|
|
46
|
+
* @returns True if all properties are identical, false otherwise
|
|
47
|
+
*/
|
|
48
|
+
function isSameStatus(previousEntry, newEntry) {
|
|
49
|
+
if (Object.keys(previousEntry).length !== Object.keys(newEntry).length) {
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
for (const key in previousEntry) {
|
|
53
|
+
const typedKey = key;
|
|
54
|
+
if (previousEntry[typedKey] !== newEntry[typedKey]) {
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return true;
|
|
59
|
+
}
|
|
38
60
|
/**
|
|
39
61
|
* Listener: Updates most recent timestamp and initiates catchup when live Q&A stream data is fetched
|
|
40
62
|
*
|
|
@@ -48,12 +70,17 @@ function getMostRecentUpdate(qandaComment) {
|
|
|
48
70
|
* @dispatches setStreamStartMostRecentAnswerId - Updates stream.streamStartMostRecentAnswerId in Redux store
|
|
49
71
|
* @dispatches nextCommentsApi.endpoints.getCatchupUpdates.initiate - Triggers catchup request for missed updates
|
|
50
72
|
*/
|
|
73
|
+
// TODO: consider when this should run now that we have state changes too.
|
|
74
|
+
// consider that it will run on every live stream query, not just the first one.
|
|
75
|
+
// therefore it will happen on state change, and on first load maybe twice.
|
|
51
76
|
listenerMiddleware.startListening({
|
|
52
77
|
matcher: isAnyOf(nextCommentsApi.endpoints.getQandAStream.matchFulfilled),
|
|
53
78
|
effect: (action, listenerApi) => {
|
|
79
|
+
const state = listenerApi.getState();
|
|
54
80
|
const { payload, meta } = action;
|
|
55
81
|
const { storyId, useStaging, commentsAPIUrl, status } = meta.arg.originalArgs;
|
|
56
|
-
// Check if this is a live stream QUERY, not response. If it is a live
|
|
82
|
+
// Check if this is a live stream QUERY, not response. If it is a live QUERY we will get questions and answers. This will fire when stream starts in live mode or switches to live mode for first time.
|
|
83
|
+
const isPreLiveStream = status === 'pre-live';
|
|
57
84
|
const isLiveStream = status === 'live';
|
|
58
85
|
if (isLiveStream &&
|
|
59
86
|
Array.isArray(payload.qandas) &&
|
|
@@ -65,54 +92,76 @@ listenerMiddleware.startListening({
|
|
|
65
92
|
listenerApi.dispatch(setMostRecentUpdateTime(`${mostRecentUpdateTime}`));
|
|
66
93
|
listenerApi.dispatch(setStreamLoadMostRecentAnswerId(mostRecentUpdateId));
|
|
67
94
|
}
|
|
95
|
+
}
|
|
96
|
+
const { mostRecentUpdateTime } = state.stream;
|
|
97
|
+
if (isPreLiveStream || isLiveStream) {
|
|
68
98
|
listenerApi.dispatch(nextCommentsApi.endpoints.getCatchupUpdates.initiate({
|
|
69
|
-
storyId
|
|
70
|
-
useStaging
|
|
71
|
-
commentsAPIUrl
|
|
72
|
-
|
|
99
|
+
storyId,
|
|
100
|
+
useStaging,
|
|
101
|
+
commentsAPIUrl,
|
|
102
|
+
...(mostRecentUpdateTime && {
|
|
103
|
+
lastEventId: `${mostRecentUpdateTime}`,
|
|
104
|
+
}),
|
|
73
105
|
}));
|
|
74
106
|
}
|
|
75
107
|
},
|
|
76
108
|
});
|
|
77
109
|
/**
|
|
78
|
-
* Listener:
|
|
110
|
+
* Listener: Processes successful catchup updates and manages comment/status updates
|
|
79
111
|
*
|
|
80
|
-
* Responds to successful getCatchupUpdates queries and
|
|
81
|
-
*
|
|
82
|
-
*
|
|
112
|
+
* Responds to successful getCatchupUpdates queries and processes the response:
|
|
113
|
+
* - Adds new comments to the updates cache, filtering out duplicates
|
|
114
|
+
* - Updates status when changes are detected compared to the last status
|
|
115
|
+
* - Updates the most recent timestamp for future catchup requests
|
|
83
116
|
*
|
|
84
117
|
* @listens nextCommentsApi.endpoints.getCatchupUpdates.matchFulfilled
|
|
85
118
|
* @dispatches nextCommentsApi.util.updateQueryData - Updates the cache of updated comments in the store
|
|
86
119
|
* @dispatches setMostRecentUpdateTime - Updates stream.mostRecentUpdateTime with new lastEventId
|
|
120
|
+
* @dispatches nextCommentsApi.util.updateQueryData - Updates the status if it has changed
|
|
87
121
|
*/
|
|
88
122
|
listenerMiddleware.startListening({
|
|
89
123
|
matcher: nextCommentsApi.endpoints.getCatchupUpdates.matchFulfilled,
|
|
90
124
|
effect: (action, listenerApi) => {
|
|
91
125
|
const { payload, meta } = action;
|
|
92
126
|
const { storyId, useStaging, commentsAPIUrl } = meta.arg.originalArgs;
|
|
93
|
-
const { updatedComments, lastEventId } = payload;
|
|
94
|
-
if (!updatedComments)
|
|
127
|
+
const { updatedComments, status, lastEventId = null } = payload;
|
|
128
|
+
if (!updatedComments && !status)
|
|
95
129
|
return;
|
|
96
|
-
console.log('Received catchup updates, new event id:', lastEventId);
|
|
97
|
-
const updateType = updateTypes['QA_NEW_REPLY'];
|
|
98
130
|
const state = listenerApi.getState();
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
131
|
+
// check for new updated comments
|
|
132
|
+
if (Array.isArray(updatedComments) && updatedComments.length > 0) {
|
|
133
|
+
const updateType = updateTypes['QA_NEW_REPLY'];
|
|
134
|
+
const { streamLoadMostRecentAnswerId, mostRecentUpdateTime: mostRecentInStreamTime, } = state.stream;
|
|
135
|
+
// filter out catchup comments that are the same as the most recent update in the stream list, which can happen on first load when the valkey and coral response timestamps don't match
|
|
136
|
+
// there is latency between the comment being saved in coral and then added to our valkey stream. Updates after this will all come from valkey.
|
|
137
|
+
const filteredComments = updatedComments.filter((comment) => {
|
|
138
|
+
const { mostRecentUpdateId, mostRecentUpdateTime } = getMostRecentUpdate(comment);
|
|
139
|
+
if (streamLoadMostRecentAnswerId === mostRecentUpdateId &&
|
|
140
|
+
mostRecentInStreamTime === `${mostRecentUpdateTime}`) {
|
|
141
|
+
return false;
|
|
142
|
+
}
|
|
143
|
+
return true;
|
|
144
|
+
});
|
|
145
|
+
if (Array.isArray(filteredComments) && filteredComments.length) {
|
|
146
|
+
listenerApi.dispatch(nextCommentsApi.util.updateQueryData('getQandAUpdates', { storyId, useStaging, commentsAPIUrl }, (draft) => {
|
|
147
|
+
draft[updateType] = draft[updateType] || [];
|
|
148
|
+
draft[updateType].push(...filteredComments);
|
|
149
|
+
}));
|
|
107
150
|
}
|
|
108
|
-
|
|
109
|
-
}
|
|
110
|
-
|
|
151
|
+
listenerApi.dispatch(setMostRecentUpdateTime(lastEventId));
|
|
152
|
+
}
|
|
153
|
+
// check for status updates
|
|
154
|
+
if (status) {
|
|
155
|
+
const updateType = updateTypes['QA_UPDATE'];
|
|
111
156
|
listenerApi.dispatch(nextCommentsApi.util.updateQueryData('getQandAUpdates', { storyId, useStaging, commentsAPIUrl }, (draft) => {
|
|
112
157
|
draft[updateType] = draft[updateType] || [];
|
|
113
|
-
|
|
158
|
+
// in order to avoid unnecessary updates, we check if the last update is identical to the new status. we only push changed status updates.
|
|
159
|
+
if (draft[updateType].length > 0 &&
|
|
160
|
+
isSameStatus(draft[updateType].at(-1), status)) {
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
draft[updateType] = [status];
|
|
114
164
|
}));
|
|
115
165
|
}
|
|
116
|
-
listenerApi.dispatch(setMostRecentUpdateTime(lastEventId));
|
|
117
166
|
},
|
|
118
167
|
});
|
|
@@ -1,51 +1,21 @@
|
|
|
1
|
-
import type { Comment } from '../types/comment';
|
|
2
|
-
import type { QA } from '../types/qa';
|
|
3
1
|
import type { Status } from '../types/qa';
|
|
2
|
+
import type { CommentsAPIUrlParams, CommentsStreamTransformed, CachedData, UserRolesTransformed, CommentsAPIUrlTokenParams, CommentsAPIUrlQuestionParams } from '../types/comments-api';
|
|
4
3
|
export declare const updateTypes: {
|
|
5
4
|
QA_NEW_REPLY: string;
|
|
6
5
|
QA_UPDATE: string;
|
|
7
6
|
};
|
|
8
7
|
export declare let eventSource: EventSource | null;
|
|
9
|
-
type CommentsStreamResponse = {
|
|
10
|
-
type: string;
|
|
11
|
-
children?: Comment[];
|
|
12
|
-
status?: Status;
|
|
13
|
-
startDateTime?: string;
|
|
14
|
-
endDateTime?: string;
|
|
15
|
-
};
|
|
16
|
-
type CommentsStreamTransformed = Omit<CommentsStreamResponse, 'children'> & {
|
|
17
|
-
qandas: Comment[];
|
|
18
|
-
};
|
|
19
|
-
type CommentsAPIUrlParams = {
|
|
20
|
-
storyId: string;
|
|
21
|
-
useStaging: boolean;
|
|
22
|
-
commentsAPIUrl: string;
|
|
23
|
-
};
|
|
24
|
-
type CommentsAPIUrlTokenParams = CommentsAPIUrlParams & {
|
|
25
|
-
token: string;
|
|
26
|
-
};
|
|
27
|
-
type CommentsAPIUrlQuestionParams = CommentsAPIUrlTokenParams & {
|
|
28
|
-
question: string;
|
|
29
|
-
postAnonymously: boolean;
|
|
30
|
-
};
|
|
31
|
-
type CachedData = {
|
|
32
|
-
updatedComments?: Comment[];
|
|
33
|
-
updateQA?: QA;
|
|
34
|
-
[key: string]: any;
|
|
35
|
-
};
|
|
36
|
-
type UserRolesTransformed = {
|
|
37
|
-
expertView: boolean;
|
|
38
|
-
};
|
|
39
8
|
export declare const nextCommentsApi: import("@reduxjs/toolkit/query/react").Api<import("@reduxjs/toolkit/query/react").BaseQueryFn<string | import("@reduxjs/toolkit/query/react").FetchArgs, unknown, import("@reduxjs/toolkit/query/react").FetchBaseQueryError, {}, import("@reduxjs/toolkit/query/react").FetchBaseQueryMeta>, {
|
|
40
9
|
getQandAStream: import("@reduxjs/toolkit/query/react").QueryDefinition<CommentsAPIUrlParams & {
|
|
41
10
|
status: Status;
|
|
42
11
|
}, import("@reduxjs/toolkit/query/react").BaseQueryFn<string | import("@reduxjs/toolkit/query/react").FetchArgs, unknown, import("@reduxjs/toolkit/query/react").FetchBaseQueryError, {}, import("@reduxjs/toolkit/query/react").FetchBaseQueryMeta>, never, CommentsStreamTransformed, "nextCommentsApi">;
|
|
43
12
|
getQandAUpdates: import("@reduxjs/toolkit/query/react").QueryDefinition<CommentsAPIUrlParams, import("@reduxjs/toolkit/query/react").BaseQueryFn<string | import("@reduxjs/toolkit/query/react").FetchArgs, unknown, import("@reduxjs/toolkit/query/react").FetchBaseQueryError, {}, import("@reduxjs/toolkit/query/react").FetchBaseQueryMeta>, never, CachedData, "nextCommentsApi">;
|
|
44
13
|
getCatchupUpdates: import("@reduxjs/toolkit/query/react").QueryDefinition<CommentsAPIUrlParams & {
|
|
45
|
-
lastEventId
|
|
14
|
+
lastEventId?: string;
|
|
46
15
|
}, import("@reduxjs/toolkit/query/react").BaseQueryFn<string | import("@reduxjs/toolkit/query/react").FetchArgs, unknown, import("@reduxjs/toolkit/query/react").FetchBaseQueryError, {}, import("@reduxjs/toolkit/query/react").FetchBaseQueryMeta>, never, {
|
|
47
|
-
updatedComments: Comment[]
|
|
48
|
-
|
|
16
|
+
updatedComments: import("../types/comment").Comment[];
|
|
17
|
+
status: import("../types/comments-api").StreamStatus | null;
|
|
18
|
+
lastEventId: string | null;
|
|
49
19
|
}, "nextCommentsApi">;
|
|
50
20
|
getUserRoles: import("@reduxjs/toolkit/query/react").QueryDefinition<CommentsAPIUrlTokenParams, import("@reduxjs/toolkit/query/react").BaseQueryFn<string | import("@reduxjs/toolkit/query/react").FetchArgs, unknown, import("@reduxjs/toolkit/query/react").FetchBaseQueryError, {}, import("@reduxjs/toolkit/query/react").FetchBaseQueryMeta>, never, UserRolesTransformed, "nextCommentsApi">;
|
|
51
21
|
postQuestion: import("@reduxjs/toolkit/query/react").MutationDefinition<CommentsAPIUrlQuestionParams, import("@reduxjs/toolkit/query/react").BaseQueryFn<string | import("@reduxjs/toolkit/query/react").FetchArgs, unknown, import("@reduxjs/toolkit/query/react").FetchBaseQueryError, {}, import("@reduxjs/toolkit/query/react").FetchBaseQueryMeta>, never, {
|
|
@@ -59,6 +29,5 @@ export declare const useGetQandAStreamQuery: import("@reduxjs/toolkit/dist/query
|
|
|
59
29
|
}, "nextCommentsApi">>;
|
|
60
30
|
export declare const useUpdatedComments: ({ storyId, useStaging, commentsAPIUrl }: CommentsAPIUrlParams, options?: {
|
|
61
31
|
skip: boolean;
|
|
62
|
-
}) => Comment[];
|
|
32
|
+
}) => import("../types/comment").Comment[];
|
|
63
33
|
export declare const useUpdatedQA: ({ storyId, useStaging, commentsAPIUrl, }: CommentsAPIUrlParams) => any;
|
|
64
|
-
export {};
|
|
@@ -9,59 +9,19 @@ export declare const rootReducer: import("@reduxjs/toolkit").Reducer<import("@re
|
|
|
9
9
|
user: any;
|
|
10
10
|
expert: ExpertState;
|
|
11
11
|
nextCommentsApi: import("@reduxjs/toolkit/query").CombinedState<{
|
|
12
|
-
getQandAStream: import("@reduxjs/toolkit/query").QueryDefinition<{
|
|
13
|
-
storyId: string;
|
|
14
|
-
useStaging: boolean;
|
|
15
|
-
commentsAPIUrl: string;
|
|
16
|
-
} & {
|
|
12
|
+
getQandAStream: import("@reduxjs/toolkit/query").QueryDefinition<import("../types/comments-api").CommentsAPIUrlParams & {
|
|
17
13
|
status: import("../types/qa").Status;
|
|
18
|
-
}, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("@reduxjs/toolkit/query").FetchArgs, unknown, import("@reduxjs/toolkit/query").FetchBaseQueryError, {}, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, never,
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
startDateTime?: string;
|
|
23
|
-
endDateTime?: string;
|
|
24
|
-
}, "children"> & {
|
|
25
|
-
qandas: import("../types/comment").Comment[];
|
|
26
|
-
}, "nextCommentsApi">;
|
|
27
|
-
getQandAUpdates: import("@reduxjs/toolkit/query").QueryDefinition<{
|
|
28
|
-
storyId: string;
|
|
29
|
-
useStaging: boolean;
|
|
30
|
-
commentsAPIUrl: string;
|
|
31
|
-
}, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("@reduxjs/toolkit/query").FetchArgs, unknown, import("@reduxjs/toolkit/query").FetchBaseQueryError, {}, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, never, {
|
|
32
|
-
[key: string]: any;
|
|
33
|
-
updatedComments?: import("../types/comment").Comment[];
|
|
34
|
-
updateQA?: import("../types/qa").QA;
|
|
35
|
-
}, "nextCommentsApi">;
|
|
36
|
-
getCatchupUpdates: import("@reduxjs/toolkit/query").QueryDefinition<{
|
|
37
|
-
storyId: string;
|
|
38
|
-
useStaging: boolean;
|
|
39
|
-
commentsAPIUrl: string;
|
|
40
|
-
} & {
|
|
41
|
-
lastEventId: string;
|
|
14
|
+
}, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("@reduxjs/toolkit/query").FetchArgs, unknown, import("@reduxjs/toolkit/query").FetchBaseQueryError, {}, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, never, import("../types/comments-api").CommentsStreamTransformed, "nextCommentsApi">;
|
|
15
|
+
getQandAUpdates: import("@reduxjs/toolkit/query").QueryDefinition<import("../types/comments-api").CommentsAPIUrlParams, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("@reduxjs/toolkit/query").FetchArgs, unknown, import("@reduxjs/toolkit/query").FetchBaseQueryError, {}, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, never, import("../types/comments-api").CachedData, "nextCommentsApi">;
|
|
16
|
+
getCatchupUpdates: import("@reduxjs/toolkit/query").QueryDefinition<import("../types/comments-api").CommentsAPIUrlParams & {
|
|
17
|
+
lastEventId?: string;
|
|
42
18
|
}, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("@reduxjs/toolkit/query").FetchArgs, unknown, import("@reduxjs/toolkit/query").FetchBaseQueryError, {}, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, never, {
|
|
43
|
-
updatedComments: import("../types/comment").Comment[]
|
|
44
|
-
|
|
19
|
+
updatedComments: import("../types/comment").Comment[];
|
|
20
|
+
status: import("../types/comments-api").StreamStatus | null;
|
|
21
|
+
lastEventId: string | null;
|
|
45
22
|
}, "nextCommentsApi">;
|
|
46
|
-
getUserRoles: import("@reduxjs/toolkit/query").QueryDefinition<{
|
|
47
|
-
|
|
48
|
-
useStaging: boolean;
|
|
49
|
-
commentsAPIUrl: string;
|
|
50
|
-
} & {
|
|
51
|
-
token: string;
|
|
52
|
-
}, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("@reduxjs/toolkit/query").FetchArgs, unknown, import("@reduxjs/toolkit/query").FetchBaseQueryError, {}, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, never, {
|
|
53
|
-
expertView: boolean;
|
|
54
|
-
}, "nextCommentsApi">;
|
|
55
|
-
postQuestion: import("@reduxjs/toolkit/query").MutationDefinition<{
|
|
56
|
-
storyId: string;
|
|
57
|
-
useStaging: boolean;
|
|
58
|
-
commentsAPIUrl: string;
|
|
59
|
-
} & {
|
|
60
|
-
token: string;
|
|
61
|
-
} & {
|
|
62
|
-
question: string;
|
|
63
|
-
postAnonymously: boolean;
|
|
64
|
-
}, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("@reduxjs/toolkit/query").FetchArgs, unknown, import("@reduxjs/toolkit/query").FetchBaseQueryError, {}, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, never, {
|
|
23
|
+
getUserRoles: import("@reduxjs/toolkit/query").QueryDefinition<import("../types/comments-api").CommentsAPIUrlTokenParams, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("@reduxjs/toolkit/query").FetchArgs, unknown, import("@reduxjs/toolkit/query").FetchBaseQueryError, {}, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, never, import("../types/comments-api").UserRolesTransformed, "nextCommentsApi">;
|
|
24
|
+
postQuestion: import("@reduxjs/toolkit/query").MutationDefinition<import("../types/comments-api").CommentsAPIUrlQuestionParams, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("@reduxjs/toolkit/query").FetchArgs, unknown, import("@reduxjs/toolkit/query").FetchBaseQueryError, {}, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, never, {
|
|
65
25
|
message: string;
|
|
66
26
|
}, "nextCommentsApi">;
|
|
67
27
|
}, never, "nextCommentsApi">;
|
|
@@ -78,59 +38,19 @@ export declare const store: import("@reduxjs/toolkit/dist/configureStore").Toolk
|
|
|
78
38
|
user: any;
|
|
79
39
|
expert: ExpertState;
|
|
80
40
|
nextCommentsApi: import("@reduxjs/toolkit/query").CombinedState<{
|
|
81
|
-
getQandAStream: import("@reduxjs/toolkit/query").QueryDefinition<{
|
|
82
|
-
storyId: string;
|
|
83
|
-
useStaging: boolean;
|
|
84
|
-
commentsAPIUrl: string;
|
|
85
|
-
} & {
|
|
41
|
+
getQandAStream: import("@reduxjs/toolkit/query").QueryDefinition<import("../types/comments-api").CommentsAPIUrlParams & {
|
|
86
42
|
status: import("../types/qa").Status;
|
|
87
|
-
}, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("@reduxjs/toolkit/query").FetchArgs, unknown, import("@reduxjs/toolkit/query").FetchBaseQueryError, {}, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, never,
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
startDateTime?: string;
|
|
92
|
-
endDateTime?: string;
|
|
93
|
-
}, "children"> & {
|
|
94
|
-
qandas: import("../types/comment").Comment[];
|
|
95
|
-
}, "nextCommentsApi">;
|
|
96
|
-
getQandAUpdates: import("@reduxjs/toolkit/query").QueryDefinition<{
|
|
97
|
-
storyId: string;
|
|
98
|
-
useStaging: boolean;
|
|
99
|
-
commentsAPIUrl: string;
|
|
100
|
-
}, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("@reduxjs/toolkit/query").FetchArgs, unknown, import("@reduxjs/toolkit/query").FetchBaseQueryError, {}, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, never, {
|
|
101
|
-
[key: string]: any;
|
|
102
|
-
updatedComments?: import("../types/comment").Comment[];
|
|
103
|
-
updateQA?: import("../types/qa").QA;
|
|
104
|
-
}, "nextCommentsApi">;
|
|
105
|
-
getCatchupUpdates: import("@reduxjs/toolkit/query").QueryDefinition<{
|
|
106
|
-
storyId: string;
|
|
107
|
-
useStaging: boolean;
|
|
108
|
-
commentsAPIUrl: string;
|
|
109
|
-
} & {
|
|
110
|
-
lastEventId: string;
|
|
43
|
+
}, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("@reduxjs/toolkit/query").FetchArgs, unknown, import("@reduxjs/toolkit/query").FetchBaseQueryError, {}, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, never, import("../types/comments-api").CommentsStreamTransformed, "nextCommentsApi">;
|
|
44
|
+
getQandAUpdates: import("@reduxjs/toolkit/query").QueryDefinition<import("../types/comments-api").CommentsAPIUrlParams, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("@reduxjs/toolkit/query").FetchArgs, unknown, import("@reduxjs/toolkit/query").FetchBaseQueryError, {}, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, never, import("../types/comments-api").CachedData, "nextCommentsApi">;
|
|
45
|
+
getCatchupUpdates: import("@reduxjs/toolkit/query").QueryDefinition<import("../types/comments-api").CommentsAPIUrlParams & {
|
|
46
|
+
lastEventId?: string;
|
|
111
47
|
}, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("@reduxjs/toolkit/query").FetchArgs, unknown, import("@reduxjs/toolkit/query").FetchBaseQueryError, {}, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, never, {
|
|
112
|
-
updatedComments: import("../types/comment").Comment[]
|
|
113
|
-
|
|
48
|
+
updatedComments: import("../types/comment").Comment[];
|
|
49
|
+
status: import("../types/comments-api").StreamStatus | null;
|
|
50
|
+
lastEventId: string | null;
|
|
114
51
|
}, "nextCommentsApi">;
|
|
115
|
-
getUserRoles: import("@reduxjs/toolkit/query").QueryDefinition<{
|
|
116
|
-
|
|
117
|
-
useStaging: boolean;
|
|
118
|
-
commentsAPIUrl: string;
|
|
119
|
-
} & {
|
|
120
|
-
token: string;
|
|
121
|
-
}, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("@reduxjs/toolkit/query").FetchArgs, unknown, import("@reduxjs/toolkit/query").FetchBaseQueryError, {}, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, never, {
|
|
122
|
-
expertView: boolean;
|
|
123
|
-
}, "nextCommentsApi">;
|
|
124
|
-
postQuestion: import("@reduxjs/toolkit/query").MutationDefinition<{
|
|
125
|
-
storyId: string;
|
|
126
|
-
useStaging: boolean;
|
|
127
|
-
commentsAPIUrl: string;
|
|
128
|
-
} & {
|
|
129
|
-
token: string;
|
|
130
|
-
} & {
|
|
131
|
-
question: string;
|
|
132
|
-
postAnonymously: boolean;
|
|
133
|
-
}, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("@reduxjs/toolkit/query").FetchArgs, unknown, import("@reduxjs/toolkit/query").FetchBaseQueryError, {}, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, never, {
|
|
52
|
+
getUserRoles: import("@reduxjs/toolkit/query").QueryDefinition<import("../types/comments-api").CommentsAPIUrlTokenParams, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("@reduxjs/toolkit/query").FetchArgs, unknown, import("@reduxjs/toolkit/query").FetchBaseQueryError, {}, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, never, import("../types/comments-api").UserRolesTransformed, "nextCommentsApi">;
|
|
53
|
+
postQuestion: import("@reduxjs/toolkit/query").MutationDefinition<import("../types/comments-api").CommentsAPIUrlQuestionParams, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("@reduxjs/toolkit/query").FetchArgs, unknown, import("@reduxjs/toolkit/query").FetchBaseQueryError, {}, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, never, {
|
|
134
54
|
message: string;
|
|
135
55
|
}, "nextCommentsApi">;
|
|
136
56
|
}, never, "nextCommentsApi">;
|
|
@@ -140,116 +60,36 @@ export declare const store: import("@reduxjs/toolkit/dist/configureStore").Toolk
|
|
|
140
60
|
user: any;
|
|
141
61
|
expert: ExpertState;
|
|
142
62
|
nextCommentsApi: import("@reduxjs/toolkit/query").CombinedState<{
|
|
143
|
-
getQandAStream: import("@reduxjs/toolkit/query").QueryDefinition<{
|
|
144
|
-
storyId: string;
|
|
145
|
-
useStaging: boolean;
|
|
146
|
-
commentsAPIUrl: string;
|
|
147
|
-
} & {
|
|
63
|
+
getQandAStream: import("@reduxjs/toolkit/query").QueryDefinition<import("../types/comments-api").CommentsAPIUrlParams & {
|
|
148
64
|
status: import("../types/qa").Status;
|
|
149
|
-
}, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("@reduxjs/toolkit/query").FetchArgs, unknown, import("@reduxjs/toolkit/query").FetchBaseQueryError, {}, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, never,
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
startDateTime?: string;
|
|
154
|
-
endDateTime?: string;
|
|
155
|
-
}, "children"> & {
|
|
156
|
-
qandas: import("../types/comment").Comment[];
|
|
157
|
-
}, "nextCommentsApi">;
|
|
158
|
-
getQandAUpdates: import("@reduxjs/toolkit/query").QueryDefinition<{
|
|
159
|
-
storyId: string;
|
|
160
|
-
useStaging: boolean;
|
|
161
|
-
commentsAPIUrl: string;
|
|
162
|
-
}, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("@reduxjs/toolkit/query").FetchArgs, unknown, import("@reduxjs/toolkit/query").FetchBaseQueryError, {}, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, never, {
|
|
163
|
-
[key: string]: any;
|
|
164
|
-
updatedComments?: import("../types/comment").Comment[];
|
|
165
|
-
updateQA?: import("../types/qa").QA;
|
|
166
|
-
}, "nextCommentsApi">;
|
|
167
|
-
getCatchupUpdates: import("@reduxjs/toolkit/query").QueryDefinition<{
|
|
168
|
-
storyId: string;
|
|
169
|
-
useStaging: boolean;
|
|
170
|
-
commentsAPIUrl: string;
|
|
171
|
-
} & {
|
|
172
|
-
lastEventId: string;
|
|
65
|
+
}, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("@reduxjs/toolkit/query").FetchArgs, unknown, import("@reduxjs/toolkit/query").FetchBaseQueryError, {}, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, never, import("../types/comments-api").CommentsStreamTransformed, "nextCommentsApi">;
|
|
66
|
+
getQandAUpdates: import("@reduxjs/toolkit/query").QueryDefinition<import("../types/comments-api").CommentsAPIUrlParams, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("@reduxjs/toolkit/query").FetchArgs, unknown, import("@reduxjs/toolkit/query").FetchBaseQueryError, {}, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, never, import("../types/comments-api").CachedData, "nextCommentsApi">;
|
|
67
|
+
getCatchupUpdates: import("@reduxjs/toolkit/query").QueryDefinition<import("../types/comments-api").CommentsAPIUrlParams & {
|
|
68
|
+
lastEventId?: string;
|
|
173
69
|
}, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("@reduxjs/toolkit/query").FetchArgs, unknown, import("@reduxjs/toolkit/query").FetchBaseQueryError, {}, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, never, {
|
|
174
|
-
updatedComments: import("../types/comment").Comment[]
|
|
175
|
-
|
|
70
|
+
updatedComments: import("../types/comment").Comment[];
|
|
71
|
+
status: import("../types/comments-api").StreamStatus | null;
|
|
72
|
+
lastEventId: string | null;
|
|
176
73
|
}, "nextCommentsApi">;
|
|
177
|
-
getUserRoles: import("@reduxjs/toolkit/query").QueryDefinition<{
|
|
178
|
-
|
|
179
|
-
useStaging: boolean;
|
|
180
|
-
commentsAPIUrl: string;
|
|
181
|
-
} & {
|
|
182
|
-
token: string;
|
|
183
|
-
}, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("@reduxjs/toolkit/query").FetchArgs, unknown, import("@reduxjs/toolkit/query").FetchBaseQueryError, {}, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, never, {
|
|
184
|
-
expertView: boolean;
|
|
185
|
-
}, "nextCommentsApi">;
|
|
186
|
-
postQuestion: import("@reduxjs/toolkit/query").MutationDefinition<{
|
|
187
|
-
storyId: string;
|
|
188
|
-
useStaging: boolean;
|
|
189
|
-
commentsAPIUrl: string;
|
|
190
|
-
} & {
|
|
191
|
-
token: string;
|
|
192
|
-
} & {
|
|
193
|
-
question: string;
|
|
194
|
-
postAnonymously: boolean;
|
|
195
|
-
}, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("@reduxjs/toolkit/query").FetchArgs, unknown, import("@reduxjs/toolkit/query").FetchBaseQueryError, {}, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, never, {
|
|
74
|
+
getUserRoles: import("@reduxjs/toolkit/query").QueryDefinition<import("../types/comments-api").CommentsAPIUrlTokenParams, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("@reduxjs/toolkit/query").FetchArgs, unknown, import("@reduxjs/toolkit/query").FetchBaseQueryError, {}, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, never, import("../types/comments-api").UserRolesTransformed, "nextCommentsApi">;
|
|
75
|
+
postQuestion: import("@reduxjs/toolkit/query").MutationDefinition<import("../types/comments-api").CommentsAPIUrlQuestionParams, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("@reduxjs/toolkit/query").FetchArgs, unknown, import("@reduxjs/toolkit/query").FetchBaseQueryError, {}, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, never, {
|
|
196
76
|
message: string;
|
|
197
77
|
}, "nextCommentsApi">;
|
|
198
78
|
}, never, "nextCommentsApi">;
|
|
199
79
|
}>, import("@reduxjs/toolkit").AnyAction>, import("@reduxjs/toolkit").Middleware<{}, import("@reduxjs/toolkit/query").RootState<{
|
|
200
|
-
getQandAStream: import("@reduxjs/toolkit/query").QueryDefinition<{
|
|
201
|
-
storyId: string;
|
|
202
|
-
useStaging: boolean;
|
|
203
|
-
commentsAPIUrl: string;
|
|
204
|
-
} & {
|
|
80
|
+
getQandAStream: import("@reduxjs/toolkit/query").QueryDefinition<import("../types/comments-api").CommentsAPIUrlParams & {
|
|
205
81
|
status: import("../types/qa").Status;
|
|
206
|
-
}, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("@reduxjs/toolkit/query").FetchArgs, unknown, import("@reduxjs/toolkit/query").FetchBaseQueryError, {}, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, never,
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
startDateTime?: string;
|
|
211
|
-
endDateTime?: string;
|
|
212
|
-
}, "children"> & {
|
|
213
|
-
qandas: import("../types/comment").Comment[];
|
|
214
|
-
}, "nextCommentsApi">;
|
|
215
|
-
getQandAUpdates: import("@reduxjs/toolkit/query").QueryDefinition<{
|
|
216
|
-
storyId: string;
|
|
217
|
-
useStaging: boolean;
|
|
218
|
-
commentsAPIUrl: string;
|
|
219
|
-
}, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("@reduxjs/toolkit/query").FetchArgs, unknown, import("@reduxjs/toolkit/query").FetchBaseQueryError, {}, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, never, {
|
|
220
|
-
[key: string]: any;
|
|
221
|
-
updatedComments?: import("../types/comment").Comment[];
|
|
222
|
-
updateQA?: import("../types/qa").QA;
|
|
223
|
-
}, "nextCommentsApi">;
|
|
224
|
-
getCatchupUpdates: import("@reduxjs/toolkit/query").QueryDefinition<{
|
|
225
|
-
storyId: string;
|
|
226
|
-
useStaging: boolean;
|
|
227
|
-
commentsAPIUrl: string;
|
|
228
|
-
} & {
|
|
229
|
-
lastEventId: string;
|
|
82
|
+
}, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("@reduxjs/toolkit/query").FetchArgs, unknown, import("@reduxjs/toolkit/query").FetchBaseQueryError, {}, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, never, import("../types/comments-api").CommentsStreamTransformed, "nextCommentsApi">;
|
|
83
|
+
getQandAUpdates: import("@reduxjs/toolkit/query").QueryDefinition<import("../types/comments-api").CommentsAPIUrlParams, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("@reduxjs/toolkit/query").FetchArgs, unknown, import("@reduxjs/toolkit/query").FetchBaseQueryError, {}, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, never, import("../types/comments-api").CachedData, "nextCommentsApi">;
|
|
84
|
+
getCatchupUpdates: import("@reduxjs/toolkit/query").QueryDefinition<import("../types/comments-api").CommentsAPIUrlParams & {
|
|
85
|
+
lastEventId?: string;
|
|
230
86
|
}, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("@reduxjs/toolkit/query").FetchArgs, unknown, import("@reduxjs/toolkit/query").FetchBaseQueryError, {}, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, never, {
|
|
231
|
-
updatedComments: import("../types/comment").Comment[]
|
|
232
|
-
|
|
87
|
+
updatedComments: import("../types/comment").Comment[];
|
|
88
|
+
status: import("../types/comments-api").StreamStatus | null;
|
|
89
|
+
lastEventId: string | null;
|
|
233
90
|
}, "nextCommentsApi">;
|
|
234
|
-
getUserRoles: import("@reduxjs/toolkit/query").QueryDefinition<{
|
|
235
|
-
|
|
236
|
-
useStaging: boolean;
|
|
237
|
-
commentsAPIUrl: string;
|
|
238
|
-
} & {
|
|
239
|
-
token: string;
|
|
240
|
-
}, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("@reduxjs/toolkit/query").FetchArgs, unknown, import("@reduxjs/toolkit/query").FetchBaseQueryError, {}, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, never, {
|
|
241
|
-
expertView: boolean;
|
|
242
|
-
}, "nextCommentsApi">;
|
|
243
|
-
postQuestion: import("@reduxjs/toolkit/query").MutationDefinition<{
|
|
244
|
-
storyId: string;
|
|
245
|
-
useStaging: boolean;
|
|
246
|
-
commentsAPIUrl: string;
|
|
247
|
-
} & {
|
|
248
|
-
token: string;
|
|
249
|
-
} & {
|
|
250
|
-
question: string;
|
|
251
|
-
postAnonymously: boolean;
|
|
252
|
-
}, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("@reduxjs/toolkit/query").FetchArgs, unknown, import("@reduxjs/toolkit/query").FetchBaseQueryError, {}, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, never, {
|
|
91
|
+
getUserRoles: import("@reduxjs/toolkit/query").QueryDefinition<import("../types/comments-api").CommentsAPIUrlTokenParams, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("@reduxjs/toolkit/query").FetchArgs, unknown, import("@reduxjs/toolkit/query").FetchBaseQueryError, {}, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, never, import("../types/comments-api").UserRolesTransformed, "nextCommentsApi">;
|
|
92
|
+
postQuestion: import("@reduxjs/toolkit/query").MutationDefinition<import("../types/comments-api").CommentsAPIUrlQuestionParams, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("@reduxjs/toolkit/query").FetchArgs, unknown, import("@reduxjs/toolkit/query").FetchBaseQueryError, {}, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, never, {
|
|
253
93
|
message: string;
|
|
254
94
|
}, "nextCommentsApi">;
|
|
255
95
|
}, string, "nextCommentsApi">, ThunkDispatch<any, any, import("@reduxjs/toolkit").AnyAction>>, import("@reduxjs/toolkit").Middleware<{}, any, import("@reduxjs/toolkit").Dispatch<Action<any>>>]>>;
|