|
13 | 13 | import { fade } from "svelte/transition"; |
14 | 14 | import { handleKeydown, copyCustomText } from "../../utils/functions.js"; |
15 | 15 | import { findSearchTextInLogs } from "../../Views/Logs/functions.js"; |
| 16 | + import { applySharedLogUrl, buildSharedLogUrl } from "./shareLink.js"; |
| 17 | + import { |
| 18 | + shouldAutoScrollLogs, |
| 19 | + shouldFlushBufferedLogs, |
| 20 | + } from "./shareLinkViewState.js"; |
16 | 21 |
|
17 | 22 | import { |
18 | 23 | store, |
|
84 | 89 | let topFetchIsStarted = false; |
85 | 90 | let pinedBadgeTimer = null; |
86 | 91 | let pinedBadgeIsVisible = false; |
| 92 | + let skipNextSearchReload = false; |
| 93 | + let skipNextStatusReload = false; |
| 94 | + let searchResetVersion = 0; |
| 95 | + let isSharedLinkFocusMode = false; |
87 | 96 |
|
88 | 97 | function refreshStatus() { |
89 | 98 | chosenStatus.set(""); |
|
209 | 218 |
|
210 | 219 | async function fetchIfHashIsInUrl(startWith) { |
211 | 220 | const initialService = $lastChosenService; |
212 | | - const viewLogs = [ |
213 | | - ...(await api.getLogsWithPrev({ |
214 | | - containerName: $lastChosenService, |
215 | | - hostName: $lastChosenHost, |
216 | | - limit: limit * 2, |
217 | | - startWith, |
218 | | - })).logs, |
219 | | - ].reverse(); |
| 221 | + const getLogsArray = (response) => |
| 222 | + Array.isArray(response?.logs) ? response.logs : []; |
| 223 | +
|
| 224 | + const logsWithPrevResponse = await api.getLogsWithPrev({ |
| 225 | + containerName: $lastChosenService, |
| 226 | + hostName: $lastChosenHost, |
| 227 | + limit: limit * 2, |
| 228 | + startWith, |
| 229 | + }); |
| 230 | + const viewLogs = [...getLogsArray(logsWithPrevResponse)].reverse(); |
220 | 231 | let downLogs = []; |
221 | 232 | let upperLogs = []; |
222 | 233 |
|
223 | 234 | if (viewLogs.length !== limit * 2) { |
224 | | - let limitDifference = limit * 2 - viewLogs.length; |
225 | | -
|
226 | | - downLogs = [ |
227 | | - ...(await api.getPrevLogs({ |
228 | | - containerName: $lastChosenService, |
229 | | - hostName: $lastChosenHost, |
230 | | - status: $chosenStatus, |
231 | | - })).logs, |
232 | | - ]; |
| 235 | + const limitDifference = limit * 2 - viewLogs.length; |
| 236 | + const prevLogsResponse = await api.getPrevLogs({ |
| 237 | + containerName: $lastChosenService, |
| 238 | + limit: limitDifference, |
| 239 | + startWith, |
| 240 | + hostName: $lastChosenHost, |
| 241 | + status: $chosenStatus, |
| 242 | + }); |
| 243 | + downLogs = [...getLogsArray(prevLogsResponse)]; |
233 | 244 | } else { |
234 | | - downLogs = [ |
235 | | - ...(await api.getPrevLogs({ |
236 | | - containerName: $lastChosenService, |
237 | | - limit, |
238 | | - startWith: startWith, |
239 | | - hostName: $lastChosenHost, |
240 | | - status: $chosenStatus, |
241 | | - })).logs, |
242 | | - ]; |
| 245 | + const prevLogsResponse = await api.getPrevLogs({ |
| 246 | + containerName: $lastChosenService, |
| 247 | + limit, |
| 248 | + startWith: startWith, |
| 249 | + hostName: $lastChosenHost, |
| 250 | + status: $chosenStatus, |
| 251 | + }); |
| 252 | + downLogs = [...getLogsArray(prevLogsResponse)]; |
243 | 253 |
|
244 | 254 | if (limit - downLogs.length) { |
245 | | - upperLogs = await api.getLogs({ |
| 255 | + const upperLogsResponse = await api.getLogs({ |
246 | 256 | containerName: $lastChosenService, |
247 | 257 | limit: limit - downLogs.length, |
248 | 258 | startWith: viewLogs?.at(0)[0], |
249 | 259 | hostName: $lastChosenHost, |
250 | 260 | status: $chosenStatus, |
251 | | - }).logs; |
| 261 | + }); |
| 262 | + upperLogs = getLogsArray(upperLogsResponse); |
252 | 263 | } |
253 | 264 | } |
254 | 265 | if (initialService === $lastChosenService) { |
|
283 | 294 | } |
284 | 295 |
|
285 | 296 | function addLogFromWS(logfromWS) { |
| 297 | + if (isSharedLinkFocusMode) { |
| 298 | + logsFromWS = [...logsFromWS, logfromWS]; |
| 299 | + autoscroll = false; |
| 300 | + return; |
| 301 | + } |
| 302 | +
|
286 | 303 | if ( |
287 | 304 | (!mouseDownBlockFetch && endOffLogsIntersect) || |
288 | 305 | (allLogs.length < 3 * limit && endOffLogsIntersect) |
|
359 | 376 | }, |
360 | 377 | }); |
361 | 378 | toastIsVisible.set(true); |
362 | | - |
| 379 | +
|
363 | 380 | } |
364 | 381 | } |
365 | 382 |
|
|
403 | 420 | function resetSearchParams() { |
404 | 421 | searchText = ""; |
405 | 422 | } |
| 423 | +
|
| 424 | + async function exitSharedLinkFocusMode(flushBufferedLogs = false) { |
| 425 | + isSharedLinkFocusMode = false; |
| 426 | +
|
| 427 | + if (flushBufferedLogs && logsFromWS.length) { |
| 428 | + await getFullLogsSet(); |
| 429 | + logsFromWS = []; |
| 430 | + } |
| 431 | + } |
| 432 | +
|
| 433 | + function showCopiedUrlToast() { |
| 434 | + toast.set({ |
| 435 | + tittle: "Success", |
| 436 | + message: "URL has been copied", |
| 437 | + position: "", |
| 438 | + status: "Success", |
| 439 | + }); |
| 440 | +
|
| 441 | + if (!$toastIsVisible) { |
| 442 | + toastIsVisible.set(true); |
| 443 | + toastTimeoutId.set( |
| 444 | + setTimeout(() => { |
| 445 | + toastIsVisible.set(false); |
| 446 | + }, 1500) |
| 447 | + ); |
| 448 | + } else { |
| 449 | + clearTimeout($toastTimeoutId); |
| 450 | + toastIsVisible.set(false); |
| 451 | + setTimeout(() => { |
| 452 | + toastIsVisible.set(true); |
| 453 | + }, 400); |
| 454 | + } |
| 455 | + } |
| 456 | +
|
| 457 | + async function applySharedLinkToCurrentView(timeStamp) { |
| 458 | + const hadSearchText = Boolean(searchText); |
| 459 | + const hadChosenStatus = Boolean($chosenStatus); |
| 460 | + const { hash } = applySharedLogUrl(location.href, timeStamp); |
| 461 | +
|
| 462 | + isSharedLinkFocusMode = true; |
| 463 | + chosenLogsString.set(timeStamp); |
| 464 | + urlHash.set(hash); |
| 465 | +
|
| 466 | + if (hadSearchText) { |
| 467 | + skipNextSearchReload = true; |
| 468 | + } |
| 469 | + if (hadChosenStatus) { |
| 470 | + skipNextStatusReload = true; |
| 471 | + } |
| 472 | +
|
| 473 | + resetSearchParams(); |
| 474 | + searchResetVersion = searchResetVersion + 1; |
| 475 | + refreshStatus(); |
| 476 | + resetAllLogs(); |
| 477 | + resetParams(); |
| 478 | + setInitialScroll(0); |
| 479 | + isPending.set(true); |
| 480 | + closeWS(); |
| 481 | + getLogsFromWS(); |
| 482 | + topFetchIsStarted = true; |
| 483 | +
|
| 484 | + await fetchIfHashIsInUrl(timeStamp); |
| 485 | + } |
406 | 486 | function closeWS() { |
407 | 487 | if (webSocket) { |
408 | 488 | webSocket.close(); |
|
494 | 574 | } |
495 | 575 | }, 50); |
496 | 576 | } |
497 | | - |
| 577 | +
|
498 | 578 | } |
499 | 579 | isSearching.set(false); |
500 | | - } |
| 580 | + } |
501 | 581 | lastFetchActionIsFetch = true; |
502 | 582 | return total_logs; |
503 | 583 | } catch (e) { |
|
527 | 607 | let total_received_logs_count = 0; |
528 | 608 | let is_all_logs_processed = false; |
529 | 609 | let last_key = customStartWith ? customStartWith : customStartWith === 0 ? "" : allLogs.at(0)?.at(0); |
530 | | - |
| 610 | +
|
531 | 611 | while (limit > total_received_logs_count && !is_all_logs_processed) { |
532 | 612 | isSearching.set(true); |
533 | 613 | const data = await getLogs({ |
|
569 | 649 | if (scrollDirection === "down" && !scrollFromButton && !stopLogsUnfetch) { |
570 | 650 | const initialService = $lastChosenService; |
571 | 651 | isFeatching.set(true); |
572 | | - |
| 652 | +
|
573 | 653 | let last_key = allLogs.at(-1) ? allLogs.at(-1)[0] : ""; |
574 | 654 | let total_logs = []; |
575 | 655 | let total_received_logs_count = 0; |
|
621 | 701 | $: { |
622 | 702 | (async () => { |
623 | 703 | if ($lastChosenHost && $lastChosenService) { |
| 704 | + await exitSharedLinkFocusMode(); |
624 | 705 | setInitialScroll(0); |
625 | 706 | resetAllLogs(); |
626 | 707 | resetParams(); |
|
670 | 751 |
|
671 | 752 | $: { |
672 | 753 | (async () => { |
| 754 | + if (skipNextSearchReload) { |
| 755 | + skipNextSearchReload = false; |
| 756 | + return; |
| 757 | + } |
| 758 | + await exitSharedLinkFocusMode(); |
673 | 759 | if (searchText) { |
674 | 760 | resetParams(); |
675 | 761 | resetAllLogs(); |
|
685 | 771 |
|
686 | 772 | $: { |
687 | 773 | (async () => { |
| 774 | + if (skipNextStatusReload) { |
| 775 | + skipNextStatusReload = false; |
| 776 | + return; |
| 777 | + } |
| 778 | + await exitSharedLinkFocusMode(); |
688 | 779 | if ($chosenStatus) { |
689 | 780 | resetParams(); |
690 | 781 | resetAllLogs(); |
|
719 | 810 |
|
720 | 811 | $: { |
721 | 812 | (async () => { |
722 | | - if (endOffLogsIntersect && logsFromWS.length) { |
| 813 | + if ( |
| 814 | + shouldFlushBufferedLogs( |
| 815 | + logsFromWS.length, |
| 816 | + isSharedLinkFocusMode, |
| 817 | + false |
| 818 | + ) && |
| 819 | + endOffLogsIntersect |
| 820 | + ) { |
723 | 821 | logsFromWS.length && (await getFullLogsSet()); |
724 | 822 | logsFromWS = []; |
725 | 823 | } |
|
761 | 859 | }); |
762 | 860 |
|
763 | 861 | afterUpdate(() => { |
764 | | - if (autoscroll) { |
| 862 | + if (shouldAutoScrollLogs(autoscroll, isSharedLinkFocusMode)) { |
765 | 863 | div && div.scrollTo(0, div.scrollHeight ? div.scrollHeight : 0); |
766 | 864 | } |
767 | 865 | autoscroll = false; |
768 | 866 | }); |
769 | 867 | </script> |
770 | 868 |
|
771 | | -<LogsViewHeder bind:searchText /> |
| 869 | +<LogsViewHeder bind:searchText {searchResetVersion} /> |
772 | 870 | {#if pinedDate}<div> |
773 | 871 | {#if pinedBadgeIsVisible || endOffLogsIntersect}<div |
774 | 872 | transition:fade={{ duration: 250 }} |
|
864 | 962 | isHiglighted={new Date($lastLogTimestamp).getTime() < |
865 | 963 | new Date(logItem?.at(0)).getTime()} |
866 | 964 | sharedLinkCallBack={() => { |
867 | | - let option = ""; |
868 | | - // if ($chosenLogsString !== logItem?.at(0)) { |
869 | | - option = logItem?.at(0); |
870 | | - // } |
871 | | - chosenLogsString.set(option); |
872 | | - const copiedUrl = `${location.href}#${$chosenLogsString}`; |
873 | | - copyCustomText(copiedUrl, () => { |
874 | | - toast.set({ |
875 | | - tittle: "Success", |
876 | | - message: "URL has been copied", |
877 | | - position: "", |
878 | | - status: "Success", |
879 | | - }); |
880 | | - if (!$toastIsVisible) { |
881 | | - toastIsVisible.set(true); |
882 | | - toastTimeoutId.set( |
883 | | - setTimeout(() => { |
884 | | - toastIsVisible.set(false); |
885 | | - }, 3000) |
886 | | - ); |
887 | | - } else { |
888 | | - clearTimeout($toastTimeoutId); |
889 | | - toastIsVisible.set(false); |
890 | | - setTimeout(() => { |
891 | | - toastIsVisible.set(true); |
892 | | - }, 400); |
893 | | - } |
| 965 | + const timeStamp = logItem?.at(0); |
| 966 | + const nextUrl = buildSharedLogUrl(location.href, timeStamp); |
| 967 | +
|
| 968 | + copyCustomText(nextUrl, async () => { |
| 969 | + showCopiedUrlToast(); |
| 970 | + await applySharedLinkToCurrentView(timeStamp); |
894 | 971 | }); |
895 | 972 | }} |
896 | 973 | getLogsByTagOptions={(limit, searchText)} |
|
921 | 998 | number={logsFromWS.length} |
922 | 999 | ico={"Down"} |
923 | 1000 | callBack={async () => { |
| 1001 | + await exitSharedLinkFocusMode(true); |
924 | 1002 | scrollFromButton = true; |
925 | 1003 | autoscroll = true; |
926 | 1004 | scrollDirection === "up"; |
|
947 | 1025 | }} |
948 | 1026 | on:keydown={(e) => { |
949 | 1027 | handleKeydown(e, "Escape", () => { |
| 1028 | + exitSharedLinkFocusMode(); |
950 | 1029 | chosenLogsString.set(""); |
951 | 1030 | chosenStatus.set(""); |
952 | 1031 | }); |
|
0 commit comments