resources page
parent
74689dbc93
commit
e3fad73d40
|
@ -14,6 +14,7 @@ const useHttpRequest = () => {
|
|||
|
||||
const defaultOptions = useMemo(
|
||||
() => ({
|
||||
onStart: () => {},
|
||||
onCompleted: () => {},
|
||||
onError: handleError
|
||||
}),
|
||||
|
@ -23,9 +24,10 @@ const useHttpRequest = () => {
|
|||
const exec = useCallback(
|
||||
async (request, options) => {
|
||||
const internalOptions = { ...defaultOptions, ...options };
|
||||
const { onCompleted, onError } = internalOptions;
|
||||
const { onStart, onCompleted, onError } = internalOptions;
|
||||
|
||||
try {
|
||||
onStart();
|
||||
const result = await request();
|
||||
onCompleted(result);
|
||||
return result;
|
||||
|
|
|
@ -1,21 +1,10 @@
|
|||
import { useCallback } from "react";
|
||||
import useHttpRequest from "./useHttpRequest";
|
||||
import { get } from "../utils/axios";
|
||||
import { defaultResourcesFilters } from "../constants/resourcesConstants";
|
||||
|
||||
const cdn = process.env.REACT_APP_CDN_URL;
|
||||
|
||||
const defaultResourcesInput = {
|
||||
page: 1,
|
||||
pageSize: 10,
|
||||
sortBy: null,
|
||||
sortDirection: 0,
|
||||
fullTextSearch: null,
|
||||
resourceCode: null,
|
||||
resourceName: null,
|
||||
categoryId: null,
|
||||
secured: null
|
||||
};
|
||||
|
||||
const getResourcesEndpoint = (filters) => {
|
||||
const {
|
||||
page,
|
||||
|
@ -28,11 +17,12 @@ const getResourcesEndpoint = (filters) => {
|
|||
categoryId,
|
||||
secured
|
||||
} = filters;
|
||||
let endpoint = `${cdn}/admin/resources?Page=${page}&PageSize=${pageSize}&SortDirection=${sortDirection}`;
|
||||
let endpoint = `${cdn}/admin/resources?Page=${page}&PageSize=${pageSize}`;
|
||||
if (sortBy) endpoint += `&SortBy=${sortBy}`;
|
||||
if (sortDirection) endpoint += `&SortDirection=${sortDirection}`;
|
||||
if (fullTextSearch) endpoint += `&FullTextSearch=${fullTextSearch}`;
|
||||
if (resourceCode) endpoint += `&ResourceCode=${resourceCode}`;
|
||||
if (resourceCode) endpoint += `&ResourceName=${resourceName}`;
|
||||
if (resourceName) endpoint += `&ResourceName=${resourceName}`;
|
||||
if (categoryId) endpoint += `&CategoryId=${categoryId}`;
|
||||
if (secured) endpoint += `&Secured=${secured}`;
|
||||
return endpoint;
|
||||
|
@ -43,7 +33,7 @@ const useResourcesApi = () => {
|
|||
|
||||
const getResources = useCallback(
|
||||
(filters, options) => {
|
||||
const input = { ...defaultResourcesInput, ...filters };
|
||||
const input = { ...defaultResourcesFilters, ...filters };
|
||||
const endpoint = getResourcesEndpoint(input);
|
||||
const promise = exec(() => get(endpoint), options);
|
||||
return promise;
|
||||
|
|
|
@ -33,7 +33,7 @@ const Content = () => {
|
|||
[classes.contentShift]: layoutState.isSidebarOpened
|
||||
})}
|
||||
>
|
||||
<div className={classes.fakeToolbar} />
|
||||
<div id="fakeToolbar" className={classes.fakeToolbar} />
|
||||
<Switch>
|
||||
<Route path="/dashboard" component={Dashboard} />
|
||||
<Route path="/resources" component={ResourcesContainer} />
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
import { makeStyles } from "@material-ui/styles";
|
||||
|
||||
export default makeStyles(theme => ({
|
||||
export default makeStyles((theme) => ({
|
||||
pageTitleContainer: {
|
||||
display: "flex",
|
||||
justifyContent: "space-between",
|
||||
marginBottom: theme.spacing(4),
|
||||
marginTop: theme.spacing(5),
|
||||
marginBottom: theme.spacing(2),
|
||||
marginTop: theme.spacing(0)
|
||||
},
|
||||
typo: {
|
||||
color: theme.palette.text.hint,
|
||||
color: theme.palette.text.hint
|
||||
},
|
||||
button: {
|
||||
boxShadow: theme.customShadows.widget,
|
||||
textTransform: "none",
|
||||
"&:active": {
|
||||
boxShadow: theme.customShadows.widgetWide,
|
||||
},
|
||||
},
|
||||
boxShadow: theme.customShadows.widgetWide
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
const defaultResourcesFilters = Object.freeze({
|
||||
page: 1,
|
||||
pageSize: 10,
|
||||
sortBy: null,
|
||||
sortDirection: null,
|
||||
fullTextSearch: null,
|
||||
resourceCode: null,
|
||||
resourceName: null,
|
||||
categoryId: null,
|
||||
secured: null
|
||||
});
|
||||
|
||||
export { defaultResourcesFilters };
|
|
@ -1,24 +1,34 @@
|
|||
import React, { useState, useEffect, useMemo } from "react";
|
||||
import { Grid, CircularProgress, Checkbox } from "@material-ui/core";
|
||||
import MUIDataTable from "mui-datatables";
|
||||
import React, { useState, useEffect, useMemo, useCallback } from "react";
|
||||
import { Grid, Checkbox, CircularProgress, FormLabel } from "@material-ui/core";
|
||||
import MUIDataTable, { debounceSearchRender } from "mui-datatables";
|
||||
import PageTitle from "../../../components/PageTitle";
|
||||
import { useResourcesApi } from "../../../api";
|
||||
import { defaultResourcesFilters } from "../../../constants/resourcesConstants";
|
||||
|
||||
const __ROWS_PER_PAGE_OPTIONS = [10, 20, 50, 100];
|
||||
|
||||
const ResourcesContainer = () => {
|
||||
const [list, setList] = useState({ loaded: false });
|
||||
const [state, setState] = useState({ loaded: false, loadedPages: null });
|
||||
const [filters, setFilters] = useState({ ...defaultResourcesFilters });
|
||||
const { getResources } = useResourcesApi();
|
||||
|
||||
useEffect(() => {
|
||||
getResources(
|
||||
{},
|
||||
{
|
||||
onCompleted: (resources) => {
|
||||
const data = Object.assign(resources, { loaded: true });
|
||||
setList(data);
|
||||
}
|
||||
if (state.loadedPages && state.loadedPages.includes(filters.page)) return;
|
||||
|
||||
getResources(filters, {
|
||||
onCompleted: (resources) => {
|
||||
const data = { ...resources, loaded: true };
|
||||
setState((prev) => ({
|
||||
...prev,
|
||||
...data,
|
||||
values: prev?.values ? [...prev.values, ...data.values] : data.values,
|
||||
loadedPages: prev?.loadedPages
|
||||
? [...prev.loadedPages, data.page]
|
||||
: [data.page]
|
||||
}));
|
||||
}
|
||||
);
|
||||
}, [getResources]);
|
||||
});
|
||||
}, [getResources, filters, state.loadedPages]);
|
||||
|
||||
const columns = useMemo(
|
||||
() => [
|
||||
|
@ -32,8 +42,14 @@ const ResourcesContainer = () => {
|
|||
print: false,
|
||||
searchable: true,
|
||||
sort: true,
|
||||
customFilterListOptions: {
|
||||
render: (v) => (v ? `Code contains: ${v}` : [])
|
||||
},
|
||||
filter: true,
|
||||
filterType: "textField",
|
||||
filterOptions: {
|
||||
logic: (_prop, _filterValue, _row) => false
|
||||
},
|
||||
filterList: undefined,
|
||||
hint: undefined
|
||||
}
|
||||
|
@ -48,8 +64,14 @@ const ResourcesContainer = () => {
|
|||
print: false,
|
||||
searchable: true,
|
||||
sort: true,
|
||||
customFilterListOptions: {
|
||||
render: (v) => (v ? `Name contains: ${v}` : [])
|
||||
},
|
||||
filter: true,
|
||||
filterType: "textField",
|
||||
filterOptions: {
|
||||
logic: (_prop, _filterValue, _row) => false
|
||||
},
|
||||
filterList: undefined,
|
||||
hint: undefined
|
||||
}
|
||||
|
@ -66,6 +88,9 @@ const ResourcesContainer = () => {
|
|||
sort: true,
|
||||
filter: true,
|
||||
filterType: "dropdown",
|
||||
filterOptions: {
|
||||
logic: (_prop, _filterValue, _row) => false
|
||||
},
|
||||
filterList: [],
|
||||
hint: undefined
|
||||
}
|
||||
|
@ -80,11 +105,7 @@ const ResourcesContainer = () => {
|
|||
print: false,
|
||||
searchable: true,
|
||||
sort: true,
|
||||
filter: true,
|
||||
filterType: "checkbox",
|
||||
filterList: undefined,
|
||||
hint: undefined,
|
||||
customBodyRender: (value, tableMeta, updateValue) => {
|
||||
customBodyRender: (value, _tableMeta, _updateValue) => {
|
||||
return (
|
||||
<Checkbox
|
||||
disabled
|
||||
|
@ -93,17 +114,64 @@ const ResourcesContainer = () => {
|
|||
style={{ padding: "0" }}
|
||||
/>
|
||||
);
|
||||
}
|
||||
},
|
||||
customFilterListOptions: {
|
||||
render: (v) => {
|
||||
const checked = v[0];
|
||||
return checked ? <span>Secured</span> : [];
|
||||
}
|
||||
},
|
||||
filter: true,
|
||||
filterType: "custom",
|
||||
filterOptions: {
|
||||
logic: (_prop, _filterValue, _row) => false,
|
||||
display: (filterList, onChange, index, column) => {
|
||||
return (
|
||||
<div>
|
||||
<FormLabel>Secured</FormLabel>
|
||||
<Checkbox
|
||||
color="primary"
|
||||
checked={filterList[index][0] || false}
|
||||
onChange={(event) => {
|
||||
filterList[index][0] = event.target.checked;
|
||||
onChange(filterList[index], index, column);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
},
|
||||
filterList: undefined,
|
||||
hint: undefined
|
||||
}
|
||||
}
|
||||
],
|
||||
[]
|
||||
);
|
||||
|
||||
const handleResetFilters = useCallback(() => {
|
||||
setFilters((prev) => ({ ...prev, ...defaultResourcesFilters }));
|
||||
}, [setFilters]);
|
||||
|
||||
const handleFilterChange = useCallback(
|
||||
(changedColumn, filterList, type, changedColumnIndex, displayData) => {
|
||||
if (type === "reset") {
|
||||
handleResetFilters();
|
||||
return;
|
||||
}
|
||||
const filterValue = filterList[changedColumnIndex][0];
|
||||
setFilters((prev) => ({
|
||||
...prev,
|
||||
[changedColumn]: filterValue
|
||||
}));
|
||||
},
|
||||
[handleResetFilters]
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<PageTitle title="ResourcesX" />
|
||||
{list.loaded === false ? (
|
||||
{state.loaded === false ? (
|
||||
<CircularProgress size={26} />
|
||||
) : (
|
||||
<Grid container spacing={4}>
|
||||
|
@ -111,14 +179,39 @@ const ResourcesContainer = () => {
|
|||
<MUIDataTable
|
||||
title="Resources"
|
||||
columns={columns}
|
||||
data={list.values ?? []}
|
||||
data={state.values ?? []}
|
||||
options={{
|
||||
filterType: "textField",
|
||||
expandableRows: false,
|
||||
print: false,
|
||||
selectableRows: false,
|
||||
rowsPerPage: 10,
|
||||
rowsPerPageOptions: [10, 20, 50, 100]
|
||||
selectableRows: "none",
|
||||
rowsPerPage: state.pageSize,
|
||||
rowsPerPageOptions: __ROWS_PER_PAGE_OPTIONS,
|
||||
count: state.totalCount,
|
||||
customSearchRender: debounceSearchRender(500),
|
||||
onChangePage: (currentPage) => {
|
||||
setFilters((prev) => ({ ...prev, page: currentPage + 1 }));
|
||||
},
|
||||
onChangeRowsPerPage: (numberOfRows) => {
|
||||
setFilters((prev) => ({ ...prev, pageSize: numberOfRows }));
|
||||
},
|
||||
onColumnSortChange: (changedColumn, direction) =>
|
||||
setFilters((prev) => ({
|
||||
...prev,
|
||||
sortBy: changedColumn,
|
||||
sortDirection: direction
|
||||
})),
|
||||
onFilterChange: handleFilterChange,
|
||||
onSearchChange: (text) =>
|
||||
setFilters((prev) => ({ ...prev, fullTextSearch: text })),
|
||||
customSort: (data) => data,
|
||||
customSearch: () => true,
|
||||
setFilterChipProps: (_colIndex, _colName, _data) => {
|
||||
return {
|
||||
color: "primary",
|
||||
variant: "outlined"
|
||||
};
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
|
|
Loading…
Reference in New Issue