nodebb-plugin-admin-chats 3.1.2 → 3.3.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/client.js +67 -37
- package/library.js +61 -25
- package/package.json +1 -1
package/client.js
CHANGED
|
@@ -336,68 +336,69 @@ $(document).ready(function() {
|
|
|
336
336
|
return null;
|
|
337
337
|
}
|
|
338
338
|
|
|
339
|
+
// First, check if we have the room data in ajaxify.data (from the current page)
|
|
339
340
|
const currentRoom = ajaxify && ajaxify.data && (ajaxify.data.room || ajaxify.data);
|
|
340
|
-
if (currentRoom && parseInt(currentRoom.roomId, 10) === roomId
|
|
341
|
-
|
|
342
|
-
|
|
341
|
+
if (currentRoom && parseInt(currentRoom.roomId, 10) === roomId) {
|
|
342
|
+
if (currentRoom.adminChatLock) {
|
|
343
|
+
setCachedRoomData(roomId, currentRoom);
|
|
344
|
+
return currentRoom;
|
|
345
|
+
}
|
|
343
346
|
}
|
|
344
347
|
|
|
348
|
+
// Check cache
|
|
345
349
|
const cached = getCachedRoomData(roomId);
|
|
346
350
|
if (cached) {
|
|
347
351
|
return cached;
|
|
348
352
|
}
|
|
349
353
|
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
`${config.relative_path || ''}/api/chats/${roomId}`;
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
'x-csrf-token': config.csrf_token,
|
|
356
|
-
},
|
|
357
|
-
credentials: 'same-origin',
|
|
358
|
-
});
|
|
359
|
-
if (!response.ok) {
|
|
360
|
-
if (hasAdminChatsAccess() && !isAdminAllChatsPage()) {
|
|
361
|
-
const adminResponse = await fetch(`${config.relative_path || ''}/api/admin-chats/page/${roomId}`, {
|
|
354
|
+
// Try admin endpoint first if user has access
|
|
355
|
+
if (hasAdminChatsAccess()) {
|
|
356
|
+
const adminEndpoint = `${config.relative_path || ''}/api/admin-chats/page/${roomId}`;
|
|
357
|
+
try {
|
|
358
|
+
const adminResponse = await fetch(adminEndpoint, {
|
|
362
359
|
headers: {
|
|
363
360
|
'x-csrf-token': config.csrf_token,
|
|
364
361
|
},
|
|
365
362
|
credentials: 'same-origin',
|
|
366
363
|
});
|
|
367
|
-
if (
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
364
|
+
if (adminResponse.ok) {
|
|
365
|
+
const adminPayload = await adminResponse.json();
|
|
366
|
+
const adminRoom = adminPayload && adminPayload.roomId ? adminPayload : (adminPayload && adminPayload.room ? adminPayload.room : null);
|
|
367
|
+
if (adminRoom) {
|
|
368
|
+
setCachedRoomData(roomId, adminRoom);
|
|
369
|
+
return adminRoom;
|
|
370
|
+
}
|
|
374
371
|
}
|
|
375
|
-
|
|
372
|
+
} catch (err) {
|
|
373
|
+
// Continue to fallback
|
|
376
374
|
}
|
|
377
|
-
return null;
|
|
378
375
|
}
|
|
379
376
|
|
|
380
|
-
|
|
381
|
-
const
|
|
382
|
-
|
|
383
|
-
const
|
|
377
|
+
// For all users, try to get lock data from the new endpoint
|
|
378
|
+
const lockEndpoint = `${config.relative_path || ''}/api/admin-chats/${roomId}/lock`;
|
|
379
|
+
try {
|
|
380
|
+
const lockResponse = await fetch(lockEndpoint, {
|
|
384
381
|
headers: {
|
|
385
382
|
'x-csrf-token': config.csrf_token,
|
|
386
383
|
},
|
|
387
384
|
credentials: 'same-origin',
|
|
388
385
|
});
|
|
389
|
-
if (
|
|
390
|
-
const
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
386
|
+
if (lockResponse.ok) {
|
|
387
|
+
const lockPayload = await lockResponse.json();
|
|
388
|
+
if (lockPayload && lockPayload.lockData) {
|
|
389
|
+
const roomData = {
|
|
390
|
+
roomId: roomId,
|
|
391
|
+
adminChatLock: lockPayload.lockData,
|
|
392
|
+
};
|
|
393
|
+
setCachedRoomData(roomId, roomData);
|
|
394
|
+
return roomData;
|
|
394
395
|
}
|
|
395
396
|
}
|
|
397
|
+
} catch (err) {
|
|
398
|
+
// Ignore error
|
|
396
399
|
}
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
}
|
|
400
|
-
return roomData;
|
|
400
|
+
|
|
401
|
+
return null;
|
|
401
402
|
}
|
|
402
403
|
function isLockedForUser(roomData) {
|
|
403
404
|
return !!(roomData && roomData.adminChatLock && roomData.adminChatLock.isLocked && !canManageChats());
|
|
@@ -739,6 +740,35 @@ $(document).ready(function() {
|
|
|
739
740
|
socket.on('event:chats.restore', function() { setTimeout(refreshChatUi, 0); });
|
|
740
741
|
}
|
|
741
742
|
|
|
743
|
+
// Monitor for new chat modals/windows being added to the DOM
|
|
744
|
+
// This ensures styling is applied to floating chat windows opened from non-chat pages
|
|
745
|
+
const observer = new MutationObserver(function(mutations) {
|
|
746
|
+
let hasNewChatWindow = false;
|
|
747
|
+
mutations.forEach(function(mutation) {
|
|
748
|
+
if (mutation.type === 'childList') {
|
|
749
|
+
mutation.addedNodes.forEach(function(node) {
|
|
750
|
+
if (node.nodeType === 1) { // Element node
|
|
751
|
+
const $node = $(node);
|
|
752
|
+
if ($node.is('.chat-modal') || $node.find('.chat-modal').length) {
|
|
753
|
+
hasNewChatWindow = true;
|
|
754
|
+
}
|
|
755
|
+
if ($node.is('[component="chat/message/window"]') || $node.find('[component="chat/message/window"]').length) {
|
|
756
|
+
hasNewChatWindow = true;
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
});
|
|
760
|
+
}
|
|
761
|
+
});
|
|
762
|
+
if (hasNewChatWindow) {
|
|
763
|
+
setTimeout(refreshChatUi, 50);
|
|
764
|
+
}
|
|
765
|
+
});
|
|
766
|
+
|
|
767
|
+
observer.observe(document.body, {
|
|
768
|
+
childList: true,
|
|
769
|
+
subtree: true
|
|
770
|
+
});
|
|
771
|
+
|
|
742
772
|
// Handle browser back/forward navigation
|
|
743
773
|
$(window).on('popstate', function() {
|
|
744
774
|
if (isAdminAllChatsPage()) {
|
package/library.js
CHANGED
|
@@ -113,7 +113,6 @@ async function getLockedActionMessage(uid) {
|
|
|
113
113
|
}
|
|
114
114
|
}
|
|
115
115
|
const ADMIN_CHAT_PAGE_SIZE = 30;
|
|
116
|
-
const ADMIN_CHAT_SCAN_SIZE = 100;
|
|
117
116
|
|
|
118
117
|
async function canAccessAdminChats(uid) {
|
|
119
118
|
if (!uid) {
|
|
@@ -830,6 +829,29 @@ function registerRoutes(app, router, middleware) {
|
|
|
830
829
|
return res.status(500).json({ status: { code: 'error', message: err.message } });
|
|
831
830
|
}
|
|
832
831
|
});
|
|
832
|
+
|
|
833
|
+
router.get('/api/admin-chats/:roomId/lock', ...routeMiddleware, async (req, res) => {
|
|
834
|
+
try {
|
|
835
|
+
const roomId = parseInt(req.params.roomId, 10);
|
|
836
|
+
|
|
837
|
+
if (Number.isNaN(roomId)) {
|
|
838
|
+
return res.status(400).json({ status: { code: 'bad-request', message: 'Invalid room id' } });
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
if (!await roomExists(roomId)) {
|
|
842
|
+
return res.status(404).json({ status: { code: 'not-found', message: 'Room not found' } });
|
|
843
|
+
}
|
|
844
|
+
|
|
845
|
+
const lockData = await getRoomLockData(roomId);
|
|
846
|
+
return res.json({
|
|
847
|
+
status: { code: 'ok', message: 'Lock data retrieved' },
|
|
848
|
+
roomId,
|
|
849
|
+
lockData,
|
|
850
|
+
});
|
|
851
|
+
} catch (err) {
|
|
852
|
+
return res.status(500).json({ status: { code: 'error', message: err.message } });
|
|
853
|
+
}
|
|
854
|
+
});
|
|
833
855
|
}
|
|
834
856
|
|
|
835
857
|
async function renderAdminChatsPage(req, res, next) {
|
|
@@ -947,42 +969,57 @@ async function getPrivateRoomCount() {
|
|
|
947
969
|
}
|
|
948
970
|
|
|
949
971
|
async function getAdminRecentChats(uid, start, limit) {
|
|
950
|
-
|
|
951
|
-
const
|
|
972
|
+
const offset = Math.max(0, parseInt(start, 10) || 0);
|
|
973
|
+
const pageSize = Math.max(0, parseInt(limit, 10) || 0);
|
|
974
|
+
const allRoomIds = await db.getSortedSetRevRange('chat:rooms', 0, -1);
|
|
952
975
|
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
976
|
+
if (!allRoomIds.length || !pageSize) {
|
|
977
|
+
return {
|
|
978
|
+
rooms: [],
|
|
979
|
+
nextStart: offset,
|
|
980
|
+
};
|
|
981
|
+
}
|
|
982
|
+
|
|
983
|
+
const allRooms = await Messaging.getRoomsData(allRoomIds);
|
|
984
|
+
const roomPairs = (await Promise.all(allRooms.map(async (room, index) => {
|
|
985
|
+
const roomId = parseInt(allRoomIds[index], 10) || 0;
|
|
986
|
+
if (!room || room.public || !roomId) {
|
|
987
|
+
return null;
|
|
957
988
|
}
|
|
958
989
|
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
});
|
|
966
|
-
}
|
|
967
|
-
});
|
|
990
|
+
return {
|
|
991
|
+
roomId,
|
|
992
|
+
room,
|
|
993
|
+
lastActivity: await getAdminRoomLastActivity(roomId, room),
|
|
994
|
+
};
|
|
995
|
+
}))).filter(Boolean);
|
|
968
996
|
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
}
|
|
997
|
+
roomPairs.sort((a, b) => (
|
|
998
|
+
b.lastActivity - a.lastActivity ||
|
|
999
|
+
b.roomId - a.roomId
|
|
1000
|
+
));
|
|
974
1001
|
|
|
975
|
-
const
|
|
976
|
-
const
|
|
1002
|
+
const pagedRooms = roomPairs.slice(offset, offset + pageSize);
|
|
1003
|
+
const rooms = pagedRooms.map(item => item.room);
|
|
1004
|
+
const roomIds = pagedRooms.map(item => item.roomId);
|
|
977
1005
|
|
|
978
1006
|
await enrichAdminRecentRooms(uid, roomIds, rooms);
|
|
979
1007
|
|
|
980
1008
|
return {
|
|
981
1009
|
rooms,
|
|
982
|
-
nextStart:
|
|
1010
|
+
nextStart: offset + rooms.length,
|
|
983
1011
|
};
|
|
984
1012
|
}
|
|
985
1013
|
|
|
1014
|
+
async function getAdminRoomLastActivity(roomId, room) {
|
|
1015
|
+
const lastMessage = await db.getSortedSetRevRangeWithScores(`chat:room:${roomId}:mids`, 0, 0);
|
|
1016
|
+
if (lastMessage.length) {
|
|
1017
|
+
return parseInt(lastMessage[0].score, 10) || 0;
|
|
1018
|
+
}
|
|
1019
|
+
|
|
1020
|
+
return parseInt(room && room.timestamp, 10) || 0;
|
|
1021
|
+
}
|
|
1022
|
+
|
|
986
1023
|
async function enrichAdminRecentRooms(uid, roomIds, rooms) {
|
|
987
1024
|
if (!roomIds.length) {
|
|
988
1025
|
return;
|
|
@@ -1225,4 +1262,3 @@ module.exports = plugin;
|
|
|
1225
1262
|
|
|
1226
1263
|
|
|
1227
1264
|
|
|
1228
|
-
|