Skip to content
This repository was archived by the owner on Mar 13, 2025. It is now read-only.
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 85974c1

Browse files
committedJun 18, 2021
Update URL/restore state from URL work-in-progress
1 parent 9726e18 commit 85974c1

File tree

13 files changed

+319
-99
lines changed

13 files changed

+319
-99
lines changed
 

‎src/constants/index.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ export { PLATFORM_WEBSITE_URL, TOPCODER_WEBSITE_URL };
44

55
export const APP_BASE_PATH = "/taas-admin";
66

7+
export const WORK_PERIODS_PATH = `${APP_BASE_PATH}/work-periods`;
8+
9+
export const FREELANCERS_PATH = `${APP_BASE_PATH}/freelancers`;
10+
711
export const TAAS_BASE_PATH = "/taas";
812

913
export const ADMIN_ROLES = ["bookingmanager", "administrator"];

‎src/constants/workPeriods.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ export const DATE_FORMAT_API = "YYYY-MM-DD";
1919
export const DATE_FORMAT_UI = "MMM DD, YYYY";
2020

2121
// Field names that are required to be retrieved for display, filtering and sorting.
22-
export const REQUIRED_FIELDS = [
22+
export const API_REQUIRED_FIELDS = [
2323
"id",
2424
"jobId",
2525
"projectId",
@@ -40,15 +40,15 @@ export const REQUIRED_FIELDS = [
4040
];
4141

4242
// Valid parameter names for requests.
43-
export const QUERY_PARAM_NAMES = [
43+
export const API_QUERY_PARAM_NAMES = [
4444
"fields",
4545
"page",
4646
"perPage",
4747
"sortBy",
4848
"sortOrder",
49-
].concat(REQUIRED_FIELDS);
49+
].concat(API_REQUIRED_FIELDS);
5050

51-
export const FIELDS_QUERY = REQUIRED_FIELDS.join(",");
51+
export const API_FIELDS_QUERY = API_REQUIRED_FIELDS.join(",");
5252

5353
export const SORT_BY_DEFAULT = SORT_BY.USER_HANDLE;
5454

‎src/root.component.jsx

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,11 @@ import store from "store";
55
import { disableSidebarForRoute } from "@topcoder/micro-frontends-navbar-app";
66
import WorkPeriods from "routes/WorkPeriods";
77
import Freelancers from "routes/Freelancers";
8-
import { APP_BASE_PATH } from "./constants";
8+
import {
9+
APP_BASE_PATH,
10+
FREELANCERS_PATH,
11+
WORK_PERIODS_PATH,
12+
} from "./constants";
913
import "styles/global.scss";
1014

1115
export default function Root() {
@@ -15,15 +19,10 @@ export default function Root() {
1519

1620
return (
1721
<Provider store={store}>
18-
<Router>
19-
<Redirect
20-
from={APP_BASE_PATH}
21-
to={`${APP_BASE_PATH}/work-periods`}
22-
exact
23-
noThrow
24-
/>
25-
<WorkPeriods path={`${APP_BASE_PATH}/work-periods`} />
26-
<Freelancers path={`${APP_BASE_PATH}/freelancers`} />
22+
<Router primary={false}>
23+
<Redirect from={APP_BASE_PATH} to={WORK_PERIODS_PATH} exact noThrow />
24+
<WorkPeriods path={WORK_PERIODS_PATH} />
25+
<Freelancers path={FREELANCERS_PATH} />
2726
</Router>
2827
</Provider>
2928
);

‎src/routes/WorkPeriods/components/PeriodFilters/index.jsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useCallback } from "react";
1+
import React, { memo, useCallback } from "react";
22
import { useDispatch, useSelector } from "react-redux";
33
import debounce from "lodash/debounce";
44
import PT from "prop-types";
@@ -103,4 +103,4 @@ const PAYMENT_STATUS_OPTIONS = [
103103
{ value: PAYMENT_STATUS.NO_DAYS, label: "No Days" },
104104
];
105105

106-
export default PeriodFilters;
106+
export default memo(PeriodFilters);

‎src/routes/WorkPeriods/components/Periods/index.jsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,13 @@ const Periods = () => {
2323
const isLoading = useSelector(getWorkPeriodsIsLoading);
2424
const dispatch = useDispatch();
2525

26-
// Load working periods' first page once when page loads and then
27-
// only if page size or sorting changes.
26+
// Load working periods' page once the page is loaded.
2827
useEffect(() => {
28+
dispatch(loadWorkPeriodsPage());
29+
}, [dispatch]);
30+
31+
// Load working periods' first page only if page size or sorting changes.
32+
useUpdateEffect(() => {
2933
dispatch(loadWorkPeriodsPage(1));
3034
}, [dispatch, pagination.pageSize, sorting]);
3135

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { memo, useCallback, useEffect } from "react";
2+
import { useDispatch, useSelector } from "react-redux";
3+
import { useLocation, useNavigate } from "@reach/router";
4+
import debounce from "lodash/debounce";
5+
import { WORK_PERIODS_PATH } from "constants/index.js";
6+
import { useUpdateEffect } from "utils/hooks";
7+
import { getWorkPeriodsUrlQuery } from "store/selectors/workPeriods";
8+
import { updateStateFromQuery } from "store/actions/workPeriods";
9+
10+
const PeriodsUrl = () => {
11+
const query = useSelector(getWorkPeriodsUrlQuery);
12+
const dispatch = useDispatch();
13+
const location = useLocation();
14+
const navigate = useNavigate();
15+
16+
const updateUrl = useCallback(
17+
debounce(
18+
(query) => {
19+
navigate(`${WORK_PERIODS_PATH}?${query}`);
20+
},
21+
300,
22+
{ leading: false }
23+
),
24+
[navigate]
25+
);
26+
27+
useEffect(() => {
28+
updateUrl(query);
29+
}, [updateUrl, query]);
30+
31+
useUpdateEffect(() => {
32+
dispatch(updateStateFromQuery(location.search));
33+
}, [dispatch, location.search]);
34+
35+
return null;
36+
};
37+
38+
export default memo(PeriodsUrl);

‎src/routes/WorkPeriods/index.jsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import PeriodsContentHeader from "./components/PeriodsContentHeader";
88
import PeriodFilters from "./components/PeriodFilters";
99
import Periods from "./components/Periods";
1010
import PeriodCount from "./components/PeriodCount";
11+
import PeriodsUrl from "./components/PeriodsUrl";
1112
import PeriodsPagination from "./components/PeriodsPagination";
1213
import PeriodsSelectionMessage from "./components/PeriodsSelectionMessage";
1314
import PeriodWeekPicker from "./components/PeriodWeekPicker";
@@ -45,6 +46,7 @@ const WorkPeriods = () => (
4546
</div>
4647
</ContentBlock>
4748
</Content>
49+
<PeriodsUrl />
4850
</Page>
4951
);
5052

‎src/services/workPeriods.js

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import {
44
JOBS_API_URL,
55
PAYMENTS_API_URL,
66
PROJECTS_API_URL,
7-
QUERY_PARAM_NAMES,
7+
API_QUERY_PARAM_NAMES,
88
WORK_PERIODS_API_URL,
99
} from "constants/workPeriods";
1010
import { buildRequestQuery, extractResponseData } from "utils/misc";
@@ -98,9 +98,12 @@ export const fetchWorkPeriods = (rbId, source) => {
9898
export const fetchResourceBookings = (params) => {
9999
const source = CancelToken.source();
100100
return [
101-
axios.get(`${RB_API_URL}?${buildRequestQuery(params, QUERY_PARAM_NAMES)}`, {
102-
cancelToken: source.token,
103-
}),
101+
axios.get(
102+
`${RB_API_URL}?${buildRequestQuery(params, API_QUERY_PARAM_NAMES)}`,
103+
{
104+
cancelToken: source.token,
105+
}
106+
),
104107
source,
105108
];
106109
};

‎src/store/actionTypes/workPeriods.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,4 @@ export const WP_TOGGLE_PERIOD = "WP_TOGGLE_PERIOD";
3333
export const WP_TOGGLE_PERIODS_ALL = "WP_TOGGLE_PERIODS_ALL";
3434
export const WP_TOGGLE_PERIODS_VISIBLE = "WP_TOGGLE_PERIODS_VISIBLE";
3535
export const WP_TOGGLE_PROCESSING_PAYMENTS = "WP_TOGGLE_PROCESSING_PAYMENTS";
36+
export const WP_UPDATE_STATE_FROM_QUERY = "WP_UPDATE_STATE_FROM_QUERY";

‎src/store/actions/workPeriods.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -383,3 +383,15 @@ export const toggleWorkPeriodsProcessingPeyments = (on = null) => ({
383383
type: ACTION_TYPE.WP_TOGGLE_PROCESSING_PAYMENTS,
384384
payload: on,
385385
});
386+
387+
/**
388+
* Creates an action denoting an update of working periods state slice using
389+
* the provided query.
390+
*
391+
* @param {string} query URL search query
392+
* @returns {Object}
393+
*/
394+
export const updateStateFromQuery = (query) => ({
395+
type: ACTION_TYPE.WP_UPDATE_STATE_FROM_QUERY,
396+
payload: query,
397+
});

‎src/store/reducers/workPeriods.js

Lines changed: 224 additions & 75 deletions
Large diffs are not rendered by default.

‎src/store/selectors/workPeriods.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ export const getWorkPeriodsSelected = (state) =>
5050
*/
5151
export const getWorkPeriodsFilters = (state) => state.workPeriods.filters;
5252

53+
export const getWorkPeriodsPaymentStatuses = (state) =>
54+
state.workPeriods.filters.paymentStatuses;
55+
5356
export const getWorkPeriodsDateRange = (state) =>
5457
state.workPeriods.filters.dateRange;
5558

@@ -59,9 +62,14 @@ export const getWorkPeriodsSorting = (state) => state.workPeriods.sorting;
5962

6063
export const getWorkPeriodsPagination = (state) => state.workPeriods.pagination;
6164

65+
export const getWorkPeriodsPageNumber = (state) =>
66+
state.workPeriods.pagination.pageNumber;
67+
6268
export const getWorkPeriodsPageSize = (state) =>
6369
state.workPeriods.pagination.pageSize;
6470

71+
export const getWorkPeriodsUrlQuery = (state) => state.workPeriods.query;
72+
6573
export const getWorkPeriodsCount = (state) => state.workPeriods.periods.length;
6674

6775
export const getWorkPeriodsData = (state) => state.workPeriods.periodsData;

‎src/store/thunks/workPeriods.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {
77
API_SORT_BY,
88
DATE_FORMAT_API,
99
PAYMENT_STATUS_MAP,
10-
FIELDS_QUERY,
10+
API_FIELDS_QUERY,
1111
JOB_NAME_NONE,
1212
} from "constants/workPeriods";
1313
import {
@@ -66,7 +66,7 @@ export const loadWorkPeriodsPage =
6666
// For parameter description see:
6767
// https://topcoder-platform.github.io/taas-apis/#/ResourceBookings/get_resourceBookings
6868
const [promise, cancelSource] = services.fetchResourceBookings({
69-
fields: FIELDS_QUERY,
69+
fields: API_FIELDS_QUERY,
7070
page: pageNumber,
7171
perPage: pagination.pageSize,
7272
sortBy,

0 commit comments

Comments
 (0)
This repository has been archived.