Save task-rows-per-page as user settings

This commit is contained in:
Ken Hibino 2021-04-09 16:28:01 -07:00
parent f00f19d838
commit 33ac2d7316
9 changed files with 66 additions and 28 deletions

1
.gitignore vendored
View File

@ -29,3 +29,4 @@ dist/
# Editor configs # Editor configs
.vscode/ .vscode/
.editorconfig

View File

@ -3,6 +3,7 @@ import { ThemePreference } from "../reducers/settingsReducer";
export const POLL_INTERVAL_CHANGE = "POLL_INTERVAL_CHANGE"; export const POLL_INTERVAL_CHANGE = "POLL_INTERVAL_CHANGE";
export const THEME_PREFERENCE_CHANGE = "THEME_PREFERENCE_CHANGE"; export const THEME_PREFERENCE_CHANGE = "THEME_PREFERENCE_CHANGE";
export const TOGGLE_DRAWER = "TOGGLE_DRAWER"; export const TOGGLE_DRAWER = "TOGGLE_DRAWER";
export const TASK_ROWS_PER_PAGE_CHANGE = "TASK_ROWS_PER_PAGE_CHANGE";
interface PollIntervalChangeAction { interface PollIntervalChangeAction {
type: typeof POLL_INTERVAL_CHANGE; type: typeof POLL_INTERVAL_CHANGE;
@ -18,11 +19,17 @@ interface ToggleDrawerAction {
type: typeof TOGGLE_DRAWER; type: typeof TOGGLE_DRAWER;
} }
interface TaskRowsPerPageChange {
type: typeof TASK_ROWS_PER_PAGE_CHANGE;
value: number;
}
// Union of all settings related action types. // Union of all settings related action types.
export type SettingsActionTypes = export type SettingsActionTypes =
| PollIntervalChangeAction | PollIntervalChangeAction
| ThemePreferenceChangeAction | ThemePreferenceChangeAction
| ToggleDrawerAction; | ToggleDrawerAction
| TaskRowsPerPageChange;
export function pollIntervalChange(value: number) { export function pollIntervalChange(value: number) {
return { return {
@ -41,3 +48,10 @@ export function selectTheme(value: ThemePreference) {
export function toggleDrawer() { export function toggleDrawer() {
return { type: TOGGLE_DRAWER }; return { type: TOGGLE_DRAWER };
} }
export function taskRowsPerPageChange(value: number) {
return {
type: TASK_ROWS_PER_PAGE_CHANGE,
value,
};
}

View File

@ -24,10 +24,10 @@ import {
batchCancelActiveTasksAsync, batchCancelActiveTasksAsync,
cancelAllActiveTasksAsync, cancelAllActiveTasksAsync,
} from "../actions/tasksActions"; } from "../actions/tasksActions";
import { taskRowsPerPageChange } from "../actions/settingsActions";
import { AppState } from "../store"; import { AppState } from "../store";
import TablePaginationActions, { import TablePaginationActions, {
rowsPerPageOptions, rowsPerPageOptions,
defaultPageSize,
} from "./TablePaginationActions"; } from "./TablePaginationActions";
import TableActions from "./TableActions"; import TableActions from "./TableActions";
import { usePolling } from "../hooks"; import { usePolling } from "../hooks";
@ -59,6 +59,7 @@ function mapStateToProps(state: AppState) {
batchActionPending: state.tasks.activeTasks.batchActionPending, batchActionPending: state.tasks.activeTasks.batchActionPending,
allActionPending: state.tasks.activeTasks.allActionPending, allActionPending: state.tasks.activeTasks.allActionPending,
pollInterval: state.settings.pollInterval, pollInterval: state.settings.pollInterval,
pageSize: state.settings.taskRowsPerPage,
}; };
} }
@ -67,6 +68,7 @@ const mapDispatchToProps = {
cancelActiveTaskAsync, cancelActiveTaskAsync,
batchCancelActiveTasksAsync, batchCancelActiveTasksAsync,
cancelAllActiveTasksAsync, cancelAllActiveTasksAsync,
taskRowsPerPageChange,
}; };
const columns: TableColumn[] = [ const columns: TableColumn[] = [
@ -88,10 +90,9 @@ interface Props {
} }
function ActiveTasksTable(props: Props & ReduxProps) { function ActiveTasksTable(props: Props & ReduxProps) {
const { pollInterval, listActiveTasksAsync, queue } = props; const { pollInterval, listActiveTasksAsync, queue, pageSize } = props;
const classes = useStyles(); const classes = useStyles();
const [page, setPage] = useState(0); const [page, setPage] = useState(0);
const [pageSize, setPageSize] = useState(defaultPageSize);
const [selectedIds, setSelectedIds] = useState<string[]>([]); const [selectedIds, setSelectedIds] = useState<string[]>([]);
const [activeTaskId, setActiveTaskId] = useState<string>(""); const [activeTaskId, setActiveTaskId] = useState<string>("");
@ -105,7 +106,7 @@ function ActiveTasksTable(props: Props & ReduxProps) {
const handleChangeRowsPerPage = ( const handleChangeRowsPerPage = (
event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement> event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>
) => { ) => {
setPageSize(parseInt(event.target.value, 10)); props.taskRowsPerPageChange(parseInt(event.target.value, 10));
setPage(0); setPage(0);
}; };

View File

@ -30,9 +30,9 @@ import {
runAllArchivedTasksAsync, runAllArchivedTasksAsync,
} from "../actions/tasksActions"; } from "../actions/tasksActions";
import TablePaginationActions, { import TablePaginationActions, {
defaultPageSize,
rowsPerPageOptions, rowsPerPageOptions,
} from "./TablePaginationActions"; } from "./TablePaginationActions";
import { taskRowsPerPageChange } from "../actions/settingsActions";
import TableActions from "./TableActions"; import TableActions from "./TableActions";
import { timeAgo, uuidPrefix } from "../utils"; import { timeAgo, uuidPrefix } from "../utils";
import { usePolling } from "../hooks"; import { usePolling } from "../hooks";
@ -63,6 +63,7 @@ function mapStateToProps(state: AppState) {
batchActionPending: state.tasks.archivedTasks.batchActionPending, batchActionPending: state.tasks.archivedTasks.batchActionPending,
allActionPending: state.tasks.archivedTasks.allActionPending, allActionPending: state.tasks.archivedTasks.allActionPending,
pollInterval: state.settings.pollInterval, pollInterval: state.settings.pollInterval,
pageSize: state.settings.taskRowsPerPage,
}; };
} }
@ -74,6 +75,7 @@ const mapDispatchToProps = {
deleteAllArchivedTasksAsync, deleteAllArchivedTasksAsync,
batchRunArchivedTasksAsync, batchRunArchivedTasksAsync,
batchDeleteArchivedTasksAsync, batchDeleteArchivedTasksAsync,
taskRowsPerPageChange,
}; };
const connector = connect(mapStateToProps, mapDispatchToProps); const connector = connect(mapStateToProps, mapDispatchToProps);
@ -86,10 +88,9 @@ interface Props {
} }
function ArchivedTasksTable(props: Props & ReduxProps) { function ArchivedTasksTable(props: Props & ReduxProps) {
const { pollInterval, listArchivedTasksAsync, queue } = props; const { pollInterval, listArchivedTasksAsync, queue, pageSize } = props;
const classes = useStyles(); const classes = useStyles();
const [page, setPage] = useState(0); const [page, setPage] = useState(0);
const [pageSize, setPageSize] = useState(defaultPageSize);
const [selectedKeys, setSelectedKeys] = useState<string[]>([]); const [selectedKeys, setSelectedKeys] = useState<string[]>([]);
const [activeTaskId, setActiveTaskId] = useState<string>(""); const [activeTaskId, setActiveTaskId] = useState<string>("");
@ -103,7 +104,7 @@ function ArchivedTasksTable(props: Props & ReduxProps) {
const handleChangeRowsPerPage = ( const handleChangeRowsPerPage = (
event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement> event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>
) => { ) => {
setPageSize(parseInt(event.target.value, 10)); props.taskRowsPerPageChange(parseInt(event.target.value, 10));
setPage(0); setPage(0);
}; };
@ -288,14 +289,14 @@ function ArchivedTasksTable(props: Props & ReduxProps) {
); );
} }
const useRowStyles = makeStyles(theme => ({ const useRowStyles = makeStyles((theme) => ({
actionCell: { actionCell: {
width: "96px", width: "96px",
}, },
actionButton: { actionButton: {
marginLeft: 3, marginLeft: 3,
marginRight: 3, marginRight: 3,
} },
})); }));
interface RowProps { interface RowProps {

View File

@ -20,7 +20,6 @@ import ArchiveIcon from "@material-ui/icons/Archive";
import MoreHorizIcon from "@material-ui/icons/MoreHoriz"; import MoreHorizIcon from "@material-ui/icons/MoreHoriz";
import SyntaxHighlighter from "./SyntaxHighlighter"; import SyntaxHighlighter from "./SyntaxHighlighter";
import TablePaginationActions, { import TablePaginationActions, {
defaultPageSize,
rowsPerPageOptions, rowsPerPageOptions,
} from "./TablePaginationActions"; } from "./TablePaginationActions";
import TableActions from "./TableActions"; import TableActions from "./TableActions";
@ -33,6 +32,7 @@ import {
batchArchivePendingTasksAsync, batchArchivePendingTasksAsync,
archiveAllPendingTasksAsync, archiveAllPendingTasksAsync,
} from "../actions/tasksActions"; } from "../actions/tasksActions";
import { taskRowsPerPageChange } from "../actions/settingsActions";
import { AppState } from "../store"; import { AppState } from "../store";
import { usePolling } from "../hooks"; import { usePolling } from "../hooks";
import { uuidPrefix } from "../utils"; import { uuidPrefix } from "../utils";
@ -63,6 +63,7 @@ function mapStateToProps(state: AppState) {
batchActionPending: state.tasks.pendingTasks.batchActionPending, batchActionPending: state.tasks.pendingTasks.batchActionPending,
allActionPending: state.tasks.pendingTasks.allActionPending, allActionPending: state.tasks.pendingTasks.allActionPending,
pollInterval: state.settings.pollInterval, pollInterval: state.settings.pollInterval,
pageSize: state.settings.taskRowsPerPage,
}; };
} }
@ -74,6 +75,7 @@ const mapDispatchToProps = {
archivePendingTaskAsync, archivePendingTaskAsync,
batchArchivePendingTasksAsync, batchArchivePendingTasksAsync,
archiveAllPendingTasksAsync, archiveAllPendingTasksAsync,
taskRowsPerPageChange,
}; };
const connector = connect(mapStateToProps, mapDispatchToProps); const connector = connect(mapStateToProps, mapDispatchToProps);
@ -86,10 +88,9 @@ interface Props {
} }
function PendingTasksTable(props: Props & ReduxProps) { function PendingTasksTable(props: Props & ReduxProps) {
const { pollInterval, listPendingTasksAsync, queue } = props; const { pollInterval, listPendingTasksAsync, queue, pageSize } = props;
const classes = useStyles(); const classes = useStyles();
const [page, setPage] = useState(0); const [page, setPage] = useState(0);
const [pageSize, setPageSize] = useState(defaultPageSize);
const [selectedKeys, setSelectedKeys] = useState<string[]>([]); const [selectedKeys, setSelectedKeys] = useState<string[]>([]);
const [activeTaskId, setActiveTaskId] = useState<string>(""); const [activeTaskId, setActiveTaskId] = useState<string>("");
@ -103,7 +104,7 @@ function PendingTasksTable(props: Props & ReduxProps) {
const handleChangeRowsPerPage = ( const handleChangeRowsPerPage = (
event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement> event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>
) => { ) => {
setPageSize(parseInt(event.target.value, 10)); props.taskRowsPerPageChange(parseInt(event.target.value, 10));
setPage(0); setPage(0);
}; };

View File

@ -34,9 +34,9 @@ import {
} from "../actions/tasksActions"; } from "../actions/tasksActions";
import { AppState } from "../store"; import { AppState } from "../store";
import TablePaginationActions, { import TablePaginationActions, {
defaultPageSize,
rowsPerPageOptions, rowsPerPageOptions,
} from "./TablePaginationActions"; } from "./TablePaginationActions";
import { taskRowsPerPageChange } from "../actions/settingsActions";
import TableActions from "./TableActions"; import TableActions from "./TableActions";
import { durationBefore, uuidPrefix } from "../utils"; import { durationBefore, uuidPrefix } from "../utils";
import { usePolling } from "../hooks"; import { usePolling } from "../hooks";
@ -67,6 +67,7 @@ function mapStateToProps(state: AppState) {
batchActionPending: state.tasks.retryTasks.batchActionPending, batchActionPending: state.tasks.retryTasks.batchActionPending,
allActionPending: state.tasks.retryTasks.allActionPending, allActionPending: state.tasks.retryTasks.allActionPending,
pollInterval: state.settings.pollInterval, pollInterval: state.settings.pollInterval,
pageSize: state.settings.taskRowsPerPage,
}; };
} }
@ -81,6 +82,7 @@ const mapDispatchToProps = {
deleteRetryTaskAsync, deleteRetryTaskAsync,
runRetryTaskAsync, runRetryTaskAsync,
archiveRetryTaskAsync, archiveRetryTaskAsync,
taskRowsPerPageChange,
}; };
const connector = connect(mapStateToProps, mapDispatchToProps); const connector = connect(mapStateToProps, mapDispatchToProps);
@ -93,10 +95,9 @@ interface Props {
} }
function RetryTasksTable(props: Props & ReduxProps) { function RetryTasksTable(props: Props & ReduxProps) {
const { pollInterval, listRetryTasksAsync, queue } = props; const { pollInterval, listRetryTasksAsync, queue, pageSize } = props;
const classes = useStyles(); const classes = useStyles();
const [page, setPage] = useState(0); const [page, setPage] = useState(0);
const [pageSize, setPageSize] = useState(defaultPageSize);
const [selectedKeys, setSelectedKeys] = useState<string[]>([]); const [selectedKeys, setSelectedKeys] = useState<string[]>([]);
const [activeTaskId, setActiveTaskId] = useState<string>(""); const [activeTaskId, setActiveTaskId] = useState<string>("");
@ -110,7 +111,7 @@ function RetryTasksTable(props: Props & ReduxProps) {
const handleChangeRowsPerPage = ( const handleChangeRowsPerPage = (
event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement> event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>
) => { ) => {
setPageSize(parseInt(event.target.value, 10)); props.taskRowsPerPageChange(parseInt(event.target.value, 10));
setPage(0); setPage(0);
}; };

View File

@ -32,9 +32,9 @@ import {
runScheduledTaskAsync, runScheduledTaskAsync,
archiveScheduledTaskAsync, archiveScheduledTaskAsync,
} from "../actions/tasksActions"; } from "../actions/tasksActions";
import { taskRowsPerPageChange } from "../actions/settingsActions";
import { AppState } from "../store"; import { AppState } from "../store";
import TablePaginationActions, { import TablePaginationActions, {
defaultPageSize,
rowsPerPageOptions, rowsPerPageOptions,
} from "./TablePaginationActions"; } from "./TablePaginationActions";
import TableActions from "./TableActions"; import TableActions from "./TableActions";
@ -67,6 +67,7 @@ function mapStateToProps(state: AppState) {
batchActionPending: state.tasks.scheduledTasks.batchActionPending, batchActionPending: state.tasks.scheduledTasks.batchActionPending,
allActionPending: state.tasks.scheduledTasks.allActionPending, allActionPending: state.tasks.scheduledTasks.allActionPending,
pollInterval: state.settings.pollInterval, pollInterval: state.settings.pollInterval,
pageSize: state.settings.taskRowsPerPage,
}; };
} }
@ -81,6 +82,7 @@ const mapDispatchToProps = {
deleteScheduledTaskAsync, deleteScheduledTaskAsync,
runScheduledTaskAsync, runScheduledTaskAsync,
archiveScheduledTaskAsync, archiveScheduledTaskAsync,
taskRowsPerPageChange,
}; };
const connector = connect(mapStateToProps, mapDispatchToProps); const connector = connect(mapStateToProps, mapDispatchToProps);
@ -93,10 +95,9 @@ interface Props {
} }
function ScheduledTasksTable(props: Props & ReduxProps) { function ScheduledTasksTable(props: Props & ReduxProps) {
const { pollInterval, listScheduledTasksAsync, queue } = props; const { pollInterval, listScheduledTasksAsync, queue, pageSize } = props;
const classes = useStyles(); const classes = useStyles();
const [page, setPage] = useState(0); const [page, setPage] = useState(0);
const [pageSize, setPageSize] = useState(defaultPageSize);
const [selectedKeys, setSelectedKeys] = useState<string[]>([]); const [selectedKeys, setSelectedKeys] = useState<string[]>([]);
const [activeTaskId, setActiveTaskId] = useState<string>(""); const [activeTaskId, setActiveTaskId] = useState<string>("");
@ -110,7 +111,7 @@ function ScheduledTasksTable(props: Props & ReduxProps) {
const handleChangeRowsPerPage = ( const handleChangeRowsPerPage = (
event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement> event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>
) => { ) => {
setPageSize(parseInt(event.target.value, 10)); props.taskRowsPerPageChange(parseInt(event.target.value, 10));
setPage(0); setPage(0);
}; };

View File

@ -1,16 +1,24 @@
import { initialState as settingsInitialState } from "./reducers/settingsReducer"
import { AppState } from "./store"; import { AppState } from "./store";
const LOCAL_STORAGE_KEY = "asynqmon:state"; const LOCAL_STORAGE_KEY = "asynqmon:state";
export function loadState(): AppState | undefined { export function loadState(): Partial<AppState> {
try { try {
const serializedState = localStorage.getItem(LOCAL_STORAGE_KEY); const serializedState = localStorage.getItem(LOCAL_STORAGE_KEY);
if (serializedState === null) { if (serializedState === null) {
return undefined; return {};
}
const savedState = JSON.parse(serializedState);
return {
settings: {
...settingsInitialState,
...(savedState.settings || {}),
}
} }
return JSON.parse(serializedState);
} catch (err) { } catch (err) {
return undefined; console.log("loadState: could not load state ", err)
return {};
} }
} }

View File

@ -1,9 +1,11 @@
import { import {
POLL_INTERVAL_CHANGE, POLL_INTERVAL_CHANGE,
SettingsActionTypes, SettingsActionTypes,
TASK_ROWS_PER_PAGE_CHANGE,
THEME_PREFERENCE_CHANGE, THEME_PREFERENCE_CHANGE,
TOGGLE_DRAWER, TOGGLE_DRAWER,
} from "../actions/settingsActions"; } from "../actions/settingsActions";
import { defaultPageSize } from "../components/TablePaginationActions"
export enum ThemePreference { export enum ThemePreference {
SystemDefault, SystemDefault,
@ -15,12 +17,14 @@ export interface SettingsState {
pollInterval: number; pollInterval: number;
themePreference: ThemePreference; themePreference: ThemePreference;
isDrawerOpen: boolean; isDrawerOpen: boolean;
taskRowsPerPage: number,
} }
const initialState: SettingsState = { export const initialState: SettingsState = {
pollInterval: 8, pollInterval: 8,
themePreference: ThemePreference.SystemDefault, themePreference: ThemePreference.SystemDefault,
isDrawerOpen: true, isDrawerOpen: true,
taskRowsPerPage: defaultPageSize,
}; };
function settingsReducer( function settingsReducer(
@ -46,6 +50,12 @@ function settingsReducer(
isDrawerOpen: !state.isDrawerOpen, isDrawerOpen: !state.isDrawerOpen,
}; };
case TASK_ROWS_PER_PAGE_CHANGE:
return {
...state,
taskRowsPerPage: action.value,
}
default: default:
return state; return state;
} }