From 33ac2d73168edcc02f4755f3b01acf8bbf40a439 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Fri, 9 Apr 2021 16:28:01 -0700 Subject: [PATCH] Save task-rows-per-page as user settings --- .gitignore | 1 + ui/src/actions/settingsActions.ts | 16 +++++++++++++++- ui/src/components/ActiveTasksTable.tsx | 9 +++++---- ui/src/components/ArchivedTasksTable.tsx | 13 +++++++------ ui/src/components/PendingTasksTable.tsx | 9 +++++---- ui/src/components/RetryTasksTable.tsx | 9 +++++---- ui/src/components/ScheduledTasksTable.tsx | 9 +++++---- ui/src/localStorage.ts | 16 ++++++++++++---- ui/src/reducers/settingsReducer.ts | 12 +++++++++++- 9 files changed, 66 insertions(+), 28 deletions(-) diff --git a/.gitignore b/.gitignore index b9d1bb6..09e13e3 100644 --- a/.gitignore +++ b/.gitignore @@ -29,3 +29,4 @@ dist/ # Editor configs .vscode/ +.editorconfig diff --git a/ui/src/actions/settingsActions.ts b/ui/src/actions/settingsActions.ts index 53c7564..9e970d4 100644 --- a/ui/src/actions/settingsActions.ts +++ b/ui/src/actions/settingsActions.ts @@ -3,6 +3,7 @@ import { ThemePreference } from "../reducers/settingsReducer"; export const POLL_INTERVAL_CHANGE = "POLL_INTERVAL_CHANGE"; export const THEME_PREFERENCE_CHANGE = "THEME_PREFERENCE_CHANGE"; export const TOGGLE_DRAWER = "TOGGLE_DRAWER"; +export const TASK_ROWS_PER_PAGE_CHANGE = "TASK_ROWS_PER_PAGE_CHANGE"; interface PollIntervalChangeAction { type: typeof POLL_INTERVAL_CHANGE; @@ -18,11 +19,17 @@ interface ToggleDrawerAction { type: typeof TOGGLE_DRAWER; } +interface TaskRowsPerPageChange { + type: typeof TASK_ROWS_PER_PAGE_CHANGE; + value: number; +} + // Union of all settings related action types. export type SettingsActionTypes = | PollIntervalChangeAction | ThemePreferenceChangeAction - | ToggleDrawerAction; + | ToggleDrawerAction + | TaskRowsPerPageChange; export function pollIntervalChange(value: number) { return { @@ -41,3 +48,10 @@ export function selectTheme(value: ThemePreference) { export function toggleDrawer() { return { type: TOGGLE_DRAWER }; } + +export function taskRowsPerPageChange(value: number) { + return { + type: TASK_ROWS_PER_PAGE_CHANGE, + value, + }; +} diff --git a/ui/src/components/ActiveTasksTable.tsx b/ui/src/components/ActiveTasksTable.tsx index 3b7d69a..d73d649 100644 --- a/ui/src/components/ActiveTasksTable.tsx +++ b/ui/src/components/ActiveTasksTable.tsx @@ -24,10 +24,10 @@ import { batchCancelActiveTasksAsync, cancelAllActiveTasksAsync, } from "../actions/tasksActions"; +import { taskRowsPerPageChange } from "../actions/settingsActions"; import { AppState } from "../store"; import TablePaginationActions, { rowsPerPageOptions, - defaultPageSize, } from "./TablePaginationActions"; import TableActions from "./TableActions"; import { usePolling } from "../hooks"; @@ -59,6 +59,7 @@ function mapStateToProps(state: AppState) { batchActionPending: state.tasks.activeTasks.batchActionPending, allActionPending: state.tasks.activeTasks.allActionPending, pollInterval: state.settings.pollInterval, + pageSize: state.settings.taskRowsPerPage, }; } @@ -67,6 +68,7 @@ const mapDispatchToProps = { cancelActiveTaskAsync, batchCancelActiveTasksAsync, cancelAllActiveTasksAsync, + taskRowsPerPageChange, }; const columns: TableColumn[] = [ @@ -88,10 +90,9 @@ interface Props { } function ActiveTasksTable(props: Props & ReduxProps) { - const { pollInterval, listActiveTasksAsync, queue } = props; + const { pollInterval, listActiveTasksAsync, queue, pageSize } = props; const classes = useStyles(); const [page, setPage] = useState(0); - const [pageSize, setPageSize] = useState(defaultPageSize); const [selectedIds, setSelectedIds] = useState([]); const [activeTaskId, setActiveTaskId] = useState(""); @@ -105,7 +106,7 @@ function ActiveTasksTable(props: Props & ReduxProps) { const handleChangeRowsPerPage = ( event: React.ChangeEvent ) => { - setPageSize(parseInt(event.target.value, 10)); + props.taskRowsPerPageChange(parseInt(event.target.value, 10)); setPage(0); }; diff --git a/ui/src/components/ArchivedTasksTable.tsx b/ui/src/components/ArchivedTasksTable.tsx index 12587be..e72ac5e 100644 --- a/ui/src/components/ArchivedTasksTable.tsx +++ b/ui/src/components/ArchivedTasksTable.tsx @@ -30,9 +30,9 @@ import { runAllArchivedTasksAsync, } from "../actions/tasksActions"; import TablePaginationActions, { - defaultPageSize, rowsPerPageOptions, } from "./TablePaginationActions"; +import { taskRowsPerPageChange } from "../actions/settingsActions"; import TableActions from "./TableActions"; import { timeAgo, uuidPrefix } from "../utils"; import { usePolling } from "../hooks"; @@ -63,6 +63,7 @@ function mapStateToProps(state: AppState) { batchActionPending: state.tasks.archivedTasks.batchActionPending, allActionPending: state.tasks.archivedTasks.allActionPending, pollInterval: state.settings.pollInterval, + pageSize: state.settings.taskRowsPerPage, }; } @@ -74,6 +75,7 @@ const mapDispatchToProps = { deleteAllArchivedTasksAsync, batchRunArchivedTasksAsync, batchDeleteArchivedTasksAsync, + taskRowsPerPageChange, }; const connector = connect(mapStateToProps, mapDispatchToProps); @@ -86,10 +88,9 @@ interface Props { } function ArchivedTasksTable(props: Props & ReduxProps) { - const { pollInterval, listArchivedTasksAsync, queue } = props; + const { pollInterval, listArchivedTasksAsync, queue, pageSize } = props; const classes = useStyles(); const [page, setPage] = useState(0); - const [pageSize, setPageSize] = useState(defaultPageSize); const [selectedKeys, setSelectedKeys] = useState([]); const [activeTaskId, setActiveTaskId] = useState(""); @@ -103,7 +104,7 @@ function ArchivedTasksTable(props: Props & ReduxProps) { const handleChangeRowsPerPage = ( event: React.ChangeEvent ) => { - setPageSize(parseInt(event.target.value, 10)); + props.taskRowsPerPageChange(parseInt(event.target.value, 10)); setPage(0); }; @@ -288,14 +289,14 @@ function ArchivedTasksTable(props: Props & ReduxProps) { ); } -const useRowStyles = makeStyles(theme => ({ +const useRowStyles = makeStyles((theme) => ({ actionCell: { width: "96px", }, actionButton: { marginLeft: 3, marginRight: 3, - } + }, })); interface RowProps { diff --git a/ui/src/components/PendingTasksTable.tsx b/ui/src/components/PendingTasksTable.tsx index d3cd98e..d8cc850 100644 --- a/ui/src/components/PendingTasksTable.tsx +++ b/ui/src/components/PendingTasksTable.tsx @@ -20,7 +20,6 @@ import ArchiveIcon from "@material-ui/icons/Archive"; import MoreHorizIcon from "@material-ui/icons/MoreHoriz"; import SyntaxHighlighter from "./SyntaxHighlighter"; import TablePaginationActions, { - defaultPageSize, rowsPerPageOptions, } from "./TablePaginationActions"; import TableActions from "./TableActions"; @@ -33,6 +32,7 @@ import { batchArchivePendingTasksAsync, archiveAllPendingTasksAsync, } from "../actions/tasksActions"; +import { taskRowsPerPageChange } from "../actions/settingsActions"; import { AppState } from "../store"; import { usePolling } from "../hooks"; import { uuidPrefix } from "../utils"; @@ -63,6 +63,7 @@ function mapStateToProps(state: AppState) { batchActionPending: state.tasks.pendingTasks.batchActionPending, allActionPending: state.tasks.pendingTasks.allActionPending, pollInterval: state.settings.pollInterval, + pageSize: state.settings.taskRowsPerPage, }; } @@ -74,6 +75,7 @@ const mapDispatchToProps = { archivePendingTaskAsync, batchArchivePendingTasksAsync, archiveAllPendingTasksAsync, + taskRowsPerPageChange, }; const connector = connect(mapStateToProps, mapDispatchToProps); @@ -86,10 +88,9 @@ interface Props { } function PendingTasksTable(props: Props & ReduxProps) { - const { pollInterval, listPendingTasksAsync, queue } = props; + const { pollInterval, listPendingTasksAsync, queue, pageSize } = props; const classes = useStyles(); const [page, setPage] = useState(0); - const [pageSize, setPageSize] = useState(defaultPageSize); const [selectedKeys, setSelectedKeys] = useState([]); const [activeTaskId, setActiveTaskId] = useState(""); @@ -103,7 +104,7 @@ function PendingTasksTable(props: Props & ReduxProps) { const handleChangeRowsPerPage = ( event: React.ChangeEvent ) => { - setPageSize(parseInt(event.target.value, 10)); + props.taskRowsPerPageChange(parseInt(event.target.value, 10)); setPage(0); }; diff --git a/ui/src/components/RetryTasksTable.tsx b/ui/src/components/RetryTasksTable.tsx index 079343e..a7dc177 100644 --- a/ui/src/components/RetryTasksTable.tsx +++ b/ui/src/components/RetryTasksTable.tsx @@ -34,9 +34,9 @@ import { } from "../actions/tasksActions"; import { AppState } from "../store"; import TablePaginationActions, { - defaultPageSize, rowsPerPageOptions, } from "./TablePaginationActions"; +import { taskRowsPerPageChange } from "../actions/settingsActions"; import TableActions from "./TableActions"; import { durationBefore, uuidPrefix } from "../utils"; import { usePolling } from "../hooks"; @@ -67,6 +67,7 @@ function mapStateToProps(state: AppState) { batchActionPending: state.tasks.retryTasks.batchActionPending, allActionPending: state.tasks.retryTasks.allActionPending, pollInterval: state.settings.pollInterval, + pageSize: state.settings.taskRowsPerPage, }; } @@ -81,6 +82,7 @@ const mapDispatchToProps = { deleteRetryTaskAsync, runRetryTaskAsync, archiveRetryTaskAsync, + taskRowsPerPageChange, }; const connector = connect(mapStateToProps, mapDispatchToProps); @@ -93,10 +95,9 @@ interface Props { } function RetryTasksTable(props: Props & ReduxProps) { - const { pollInterval, listRetryTasksAsync, queue } = props; + const { pollInterval, listRetryTasksAsync, queue, pageSize } = props; const classes = useStyles(); const [page, setPage] = useState(0); - const [pageSize, setPageSize] = useState(defaultPageSize); const [selectedKeys, setSelectedKeys] = useState([]); const [activeTaskId, setActiveTaskId] = useState(""); @@ -110,7 +111,7 @@ function RetryTasksTable(props: Props & ReduxProps) { const handleChangeRowsPerPage = ( event: React.ChangeEvent ) => { - setPageSize(parseInt(event.target.value, 10)); + props.taskRowsPerPageChange(parseInt(event.target.value, 10)); setPage(0); }; diff --git a/ui/src/components/ScheduledTasksTable.tsx b/ui/src/components/ScheduledTasksTable.tsx index d017b15..5c0bf6e 100644 --- a/ui/src/components/ScheduledTasksTable.tsx +++ b/ui/src/components/ScheduledTasksTable.tsx @@ -32,9 +32,9 @@ import { runScheduledTaskAsync, archiveScheduledTaskAsync, } from "../actions/tasksActions"; +import { taskRowsPerPageChange } from "../actions/settingsActions"; import { AppState } from "../store"; import TablePaginationActions, { - defaultPageSize, rowsPerPageOptions, } from "./TablePaginationActions"; import TableActions from "./TableActions"; @@ -67,6 +67,7 @@ function mapStateToProps(state: AppState) { batchActionPending: state.tasks.scheduledTasks.batchActionPending, allActionPending: state.tasks.scheduledTasks.allActionPending, pollInterval: state.settings.pollInterval, + pageSize: state.settings.taskRowsPerPage, }; } @@ -81,6 +82,7 @@ const mapDispatchToProps = { deleteScheduledTaskAsync, runScheduledTaskAsync, archiveScheduledTaskAsync, + taskRowsPerPageChange, }; const connector = connect(mapStateToProps, mapDispatchToProps); @@ -93,10 +95,9 @@ interface Props { } function ScheduledTasksTable(props: Props & ReduxProps) { - const { pollInterval, listScheduledTasksAsync, queue } = props; + const { pollInterval, listScheduledTasksAsync, queue, pageSize } = props; const classes = useStyles(); const [page, setPage] = useState(0); - const [pageSize, setPageSize] = useState(defaultPageSize); const [selectedKeys, setSelectedKeys] = useState([]); const [activeTaskId, setActiveTaskId] = useState(""); @@ -110,7 +111,7 @@ function ScheduledTasksTable(props: Props & ReduxProps) { const handleChangeRowsPerPage = ( event: React.ChangeEvent ) => { - setPageSize(parseInt(event.target.value, 10)); + props.taskRowsPerPageChange(parseInt(event.target.value, 10)); setPage(0); }; diff --git a/ui/src/localStorage.ts b/ui/src/localStorage.ts index 013d71d..0d05fdb 100644 --- a/ui/src/localStorage.ts +++ b/ui/src/localStorage.ts @@ -1,16 +1,24 @@ +import { initialState as settingsInitialState } from "./reducers/settingsReducer" import { AppState } from "./store"; const LOCAL_STORAGE_KEY = "asynqmon:state"; -export function loadState(): AppState | undefined { +export function loadState(): Partial { try { const serializedState = localStorage.getItem(LOCAL_STORAGE_KEY); if (serializedState === null) { - return undefined; + return {}; + } + const savedState = JSON.parse(serializedState); + return { + settings: { + ...settingsInitialState, + ...(savedState.settings || {}), + } } - return JSON.parse(serializedState); } catch (err) { - return undefined; + console.log("loadState: could not load state ", err) + return {}; } } diff --git a/ui/src/reducers/settingsReducer.ts b/ui/src/reducers/settingsReducer.ts index ea744c8..9237c56 100644 --- a/ui/src/reducers/settingsReducer.ts +++ b/ui/src/reducers/settingsReducer.ts @@ -1,9 +1,11 @@ import { POLL_INTERVAL_CHANGE, SettingsActionTypes, + TASK_ROWS_PER_PAGE_CHANGE, THEME_PREFERENCE_CHANGE, TOGGLE_DRAWER, } from "../actions/settingsActions"; +import { defaultPageSize } from "../components/TablePaginationActions" export enum ThemePreference { SystemDefault, @@ -15,12 +17,14 @@ export interface SettingsState { pollInterval: number; themePreference: ThemePreference; isDrawerOpen: boolean; + taskRowsPerPage: number, } -const initialState: SettingsState = { +export const initialState: SettingsState = { pollInterval: 8, themePreference: ThemePreference.SystemDefault, isDrawerOpen: true, + taskRowsPerPage: defaultPageSize, }; function settingsReducer( @@ -46,6 +50,12 @@ function settingsReducer( isDrawerOpen: !state.isDrawerOpen, }; + case TASK_ROWS_PER_PAGE_CHANGE: + return { + ...state, + taskRowsPerPage: action.value, + } + default: return state; }