diff --git a/.changeset/silent-zoos-notice.md b/.changeset/silent-zoos-notice.md
new file mode 100644
index 0000000000000..4490e8d3c610e
--- /dev/null
+++ b/.changeset/silent-zoos-notice.md
@@ -0,0 +1,6 @@
+---
+"@rocket.chat/meteor": minor
+"@rocket.chat/i18n": minor
+---
+
+Adds 2 new buttons to the App Logs Filters, "Expand all" and "Refresh"
diff --git a/apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppLogs/AppLogs.tsx b/apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppLogs/AppLogs.tsx
index 81b620dc237b6..d47e7e68bd9ea 100644
--- a/apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppLogs/AppLogs.tsx
+++ b/apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppLogs/AppLogs.tsx
@@ -1,5 +1,6 @@
+import type { ILogItem } from '@rocket.chat/core-typings';
import { Box, Pagination } from '@rocket.chat/fuselage';
-import { useMemo, type ReactElement } from 'react';
+import { useEffect, useMemo, useReducer, type ReactElement } from 'react';
import { useTranslation } from 'react-i18next';
import AppLogsItem from './AppLogsItem';
@@ -13,6 +14,25 @@ import { usePagination } from '../../../../../components/GenericTable/hooks/useP
import AccordionLoading from '../../../components/AccordionLoading';
import { useLogs } from '../../../hooks/useLogs';
+function expandedReducer(
+ expandedStates: { id: string; expanded: boolean }[],
+ action: { type: 'update'; id: string; expanded: boolean } | { type: 'expand-all' } | { type: 'reset'; logs: ILogItem[] },
+) {
+ switch (action.type) {
+ case 'update':
+ return expandedStates.map((state) => (state.id === action.id ? { ...state, expanded: action.expanded } : state));
+
+ case 'expand-all':
+ return expandedStates.map((state) => ({ ...state, expanded: true }));
+
+ case 'reset':
+ return action.logs.map((log) => ({ id: log._id, expanded: false }));
+
+ default:
+ return expandedStates;
+ }
+}
+
const AppLogs = ({ id }: { id: string }): ReactElement => {
const { t } = useTranslation();
@@ -22,7 +42,13 @@ const AppLogs = ({ id }: { id: string }): ReactElement => {
const { current, itemsPerPage, setItemsPerPage: onSetItemsPerPage, setCurrent: onSetCurrent, ...paginationProps } = usePagination();
- const { data, isSuccess, isError, error, isFetching } = useLogs({
+ const [expandedStates, dispatch] = useReducer(expandedReducer, []);
+
+ const handleExpand = ({ id, expanded }: { id: string; expanded: boolean }) => dispatch({ id, expanded, type: 'update' });
+
+ const handleExpandAll = () => dispatch({ type: 'expand-all' });
+
+ const { data, isSuccess, isError, error, refetch, isFetching } = useLogs({
appId: id,
current,
itemsPerPage,
@@ -33,6 +59,12 @@ const AppLogs = ({ id }: { id: string }): ReactElement => {
...(endTime && endDate && { endDate: new Date(`${endDate}T${endTime}`).toISOString() }),
});
+ useEffect(() => {
+ if (isSuccess) {
+ dispatch({ type: 'reset', logs: data.logs });
+ }
+ }, [data, isSuccess]);
+
const parsedError = useMemo(() => {
if (error) {
// TODO: Check why tanstack expects a default Error but we return {error: string}
@@ -47,15 +79,29 @@ const AppLogs = ({ id }: { id: string }): ReactElement => {
return (
<>
-
+ handleExpandAll()}
+ refetchLogs={() => refetch()}
+ />
{isFetching && }
{isError && }
{!isFetching && isSuccess && data?.logs?.length === 0 && }
{!isFetching && isSuccess && data?.logs?.length > 0 && (
-
- {data?.logs?.map((log, index) => )}
+
+ {data?.logs?.map((log, index) => (
+ state.id === log._id)?.expanded || false}
+ onExpand={handleExpand}
+ key={`${index}-${log._createdAt}`}
+ {...log}
+ />
+ ))}
)}
diff --git a/apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppLogs/AppLogsItem.tsx b/apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppLogs/AppLogsItem.tsx
index 7bb6f9b65a04c..5d2fa63ca27e5 100644
--- a/apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppLogs/AppLogsItem.tsx
+++ b/apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppLogs/AppLogsItem.tsx
@@ -1,6 +1,6 @@
import type { ILogItem } from '@rocket.chat/core-typings';
import { Box, Divider } from '@rocket.chat/fuselage';
-import { useRef, useState } from 'react';
+import { useRef } from 'react';
import { useTranslation } from 'react-i18next';
import AppLogsItemEntry from './AppLogsItemEntry';
@@ -11,11 +11,12 @@ import { useFormatDateAndTime } from '../../../../../hooks/useFormatDateAndTime'
export type AppLogsItemProps = {
regionId: string;
+ expanded: boolean;
+ onExpand: ({ id }: { id: string; expanded: boolean }) => void;
} & ILogItem;
-const AppLogsItem = ({ regionId, ...props }: AppLogsItemProps) => {
+const AppLogsItem = ({ regionId, expanded, onExpand, ...props }: AppLogsItemProps) => {
const { t } = useTranslation();
- const [expanded, setExpanded] = useState(false);
const title = (
<>
{props.entries.map(({ severity, timestamp, caller, args }, index) => {
@@ -33,7 +34,7 @@ const AppLogsItem = ({ regionId, ...props }: AppLogsItemProps) => {
);
const handleClick = () => {
- setExpanded(!expanded);
+ onExpand({ id: regionId, expanded: !expanded });
};
const anchorRef = useRef(null);
diff --git a/apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppLogs/Filters/AppLogsFilter.stories.tsx b/apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppLogs/Filters/AppLogsFilter.stories.tsx
index 09ae4a97e3a42..0c02a79c3b384 100644
--- a/apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppLogs/Filters/AppLogsFilter.stories.tsx
+++ b/apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppLogs/Filters/AppLogsFilter.stories.tsx
@@ -1,5 +1,6 @@
import { Box } from '@rocket.chat/fuselage';
import { mockAppRoot } from '@rocket.chat/mock-providers';
+import { action } from '@storybook/addon-actions';
import type { Meta } from '@storybook/react';
import { FormProvider } from 'react-hook-form';
@@ -33,4 +34,6 @@ export default {
},
} satisfies Meta;
-export const Default = () => ;
+export const Default = () => (
+
+);
diff --git a/apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppLogs/Filters/AppLogsFilter.tsx b/apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppLogs/Filters/AppLogsFilter.tsx
index 703e959c5e2d1..211c37e711308 100644
--- a/apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppLogs/Filters/AppLogsFilter.tsx
+++ b/apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppLogs/Filters/AppLogsFilter.tsx
@@ -3,7 +3,7 @@ import { useRouter, useSetModal } from '@rocket.chat/ui-contexts';
import { Controller } from 'react-hook-form';
import { useTranslation } from 'react-i18next';
-import CompactFilterOptions from './AppsLogsFilterOptionsCompact';
+import CompactFilterOptions from './CompactFilterOptions';
import { EventFilterSelect } from './EventFilterSelect';
import { InstanceFilterSelect } from './InstanceFilterSelect';
import { SeverityFilterSelect } from './SeverityFilterSelect';
@@ -14,11 +14,13 @@ import { ExportLogsModal } from './ExportLogsModal';
type AppsLogsFilterProps = {
appId: string;
- isLoading?: boolean;
+ expandAll: () => void;
+ refetchLogs: () => void;
+ isLoading: boolean;
noResults?: boolean;
};
-export const AppLogsFilter = ({ appId, isLoading = false, noResults = false }: AppsLogsFilterProps) => {
+export const AppLogsFilter = ({ appId, expandAll, refetchLogs, isLoading, noResults = false }: AppsLogsFilterProps) => {
const { t } = useTranslation();
const { control, getValues } = useAppLogsFilterFormContext();
@@ -37,6 +39,11 @@ export const AppLogsFilter = ({ appId, isLoading = false, noResults = false }: A
);
};
+ const openAllLogs = () => expandAll();
+
+ const refreshLogs = () => {
+ refetchLogs();
+ };
const openExportModal = () => {
setModal( setModal(null)} filterValues={getValues()} />);
};
@@ -83,6 +90,22 @@ export const AppLogsFilter = ({ appId, isLoading = false, noResults = false }: A
} />
)}
+ {!compactMode && (
+
+ )}
+ {!compactMode && (
+ refreshLogs()}
+ />
+ )}
{!compactMode && (
)}
- {compactMode && }
+ {compactMode && (
+
+ )}
);
};
diff --git a/apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppLogs/Filters/AppsLogsFilterOptionsCompact.tsx b/apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppLogs/Filters/AppsLogsFilterOptionsCompact.tsx
deleted file mode 100644
index 8b163b92092b5..0000000000000
--- a/apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppLogs/Filters/AppsLogsFilterOptionsCompact.tsx
+++ /dev/null
@@ -1,26 +0,0 @@
-import { Box, Icon, Menu } from '@rocket.chat/fuselage';
-import { useTranslation } from 'react-i18next';
-
-type CompactFilterOptionsProps = {
- handleExportLogs: () => void;
- isLoading: boolean;
-};
-
-const CompactFilterOptions = ({ handleExportLogs, ...props }: CompactFilterOptionsProps) => {
- const { t } = useTranslation();
-
- const menuOptions = {
- exportLogs: {
- label: (
-
-
- {t('Export')}
-
- ),
- action: handleExportLogs,
- },
- };
- return ;
-};
-
-export default CompactFilterOptions;
diff --git a/apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppLogs/Filters/CompactFilterOptions.tsx b/apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppLogs/Filters/CompactFilterOptions.tsx
new file mode 100644
index 0000000000000..b0479681974c9
--- /dev/null
+++ b/apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppLogs/Filters/CompactFilterOptions.tsx
@@ -0,0 +1,47 @@
+import { Box, Icon, Menu } from '@rocket.chat/fuselage';
+import { useTranslation } from 'react-i18next';
+
+type CompactFilterOptionsProps = {
+ onExpandAll: () => void;
+ onRefreshLogs: () => void;
+ onExportLogs: () => void;
+ isLoading: boolean;
+};
+
+const CompactFilterOptions = ({ onExportLogs, onExpandAll, onRefreshLogs, isLoading, ...props }: CompactFilterOptionsProps) => {
+ const { t } = useTranslation();
+
+ const menuOptions = {
+ exportLogs: {
+ label: (
+
+
+ {t('Export')}
+
+ ),
+ action: onExportLogs,
+ },
+ expandAll: {
+ label: (
+
+
+ {t('Expand_all')}
+
+ ),
+ action: onExpandAll,
+ },
+ refreshLogs: {
+ label: (
+
+
+ {t('Refresh_logs')}
+
+ ),
+ action: onRefreshLogs,
+ disabled: isLoading,
+ },
+ };
+ return ;
+};
+
+export default CompactFilterOptions;
diff --git a/apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppLogs/Filters/__snapshots__/AppLogsFilterExpanded.spec.tsx.snap b/apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppLogs/Filters/__snapshots__/AppLogsFilterExpanded.spec.tsx.snap
index c2d86bd0912c5..9ef55418e6ff4 100644
--- a/apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppLogs/Filters/__snapshots__/AppLogsFilterExpanded.spec.tsx.snap
+++ b/apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppLogs/Filters/__snapshots__/AppLogsFilterExpanded.spec.tsx.snap
@@ -204,6 +204,34 @@ exports[`renders AppLogsItem without crashing 1`] = `
+
+