Skip to content

Commit

Permalink
feat: Added ability to filter by Request Number via url param and the…
Browse files Browse the repository at this point in the history
… filters menu
  • Loading branch information
rebeccaeve committed Jan 9, 2025
1 parent d352cb1 commit 866f0af
Show file tree
Hide file tree
Showing 5 changed files with 144 additions and 21 deletions.
31 changes: 28 additions & 3 deletions src/projects-browser/Filters.jsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import { useRef, useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import Select from "react-select";
import { selectFilters, selectTypeLists } from "./helpers/browserSlice";
import { selectFilters, selectIsFiltered, selectTypeLists } from "./helpers/browserSlice";
import {
getProjects,
setShowPagination,
resetFilters,
toggleAllFos,
toggleFos,
toggleListFiltered,
updateFilter,
updatePageData,
} from "./helpers/browserSlice";
Expand All @@ -17,6 +18,8 @@ const Filters = () => {
const dispatch = useDispatch();
const filters = useSelector(selectFilters);
const typeLists = useSelector(selectTypeLists);
const filtered = useSelector(selectIsFiltered);

const orgList = typeLists.orgs.map((org) => {
return {
label: org,
Expand All @@ -25,7 +28,6 @@ const Filters = () => {
});
const selectRef = useRef();
const [orgValue, setOrgValue] = useState(null);
const [filtered, setFiltered] = useState(false);
const fosSelectListStyle = {
height: "200px",
overflowX: "auto",
Expand Down Expand Up @@ -56,14 +58,22 @@ const Filters = () => {
}
};

const setFiltered = (b) => {
dispatch( toggleListFiltered(b) );
}

const updateOrgs = (opt) => {
setOrgValue(opt);
dispatch(updateFilter({ name: "org", value: opt.value }));
};

const buttonDisabled = () => {
return (
filters.org == "" && filters.allocationType == "" && filters.allFosToggled && filters.resource == ""
filters.org == ""
&& filters.allocationType == ""
&& filters.allFosToggled
&& filters.resource == ""
&& filters.requestNumber == ""
);
};

Expand Down Expand Up @@ -170,6 +180,21 @@ const Filters = () => {
</select>
</div>

<h5 id="request_number_label" className="mb-1">
Request Number
</h5>
<div className="mb-3">
<input
type="text"
className="form-control"
value={filters.requestNumber}
name="requestNumber"
id="requestNumber"
aria-labelledby="request_number_label"
onChange={(e) => handleFilterChange(e)}
/>
</div>

<div className="mt-2">
<button className="btn btn-primary me-2" onClick={handleSubmit}>
Submit
Expand Down
68 changes: 64 additions & 4 deletions src/projects-browser/Project.jsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
import { useRef, useState } from "react";
import { useSelector } from "react-redux";
import style from "./Project.module.scss";
import Accordion from "react-bootstrap/Accordion";
import OverlayTrigger from "react-bootstrap/OverlayTrigger";
import Tooltip from 'react-bootstrap/Tooltip';
import { selectIsSingleEntry } from "./helpers/browserSlice";

const Project = ({ project }) => {
const resources = project.resources;
const [showAlert, setShowAlert] = useState(false);
const singleEntry = useSelector( selectIsSingleEntry );
const defaultActiveKeys = singleEntry ? ['0','1'] : [];

const formatNumber = (resource) => {
let units = resource.units ? resource.units : resource.resourceUnits;
Expand Down Expand Up @@ -32,16 +40,68 @@ const Project = ({ project }) => {
}
}

const copyRequestNumber = () => {
const { origin, pathname } = window.location;
const link = `${origin}${pathname}?_requestNumber=${project.requestNumber}`;
navigator.clipboard.writeText(link);
setTimeout(() => setShowAlert(false), 2000);
}

const requestNumber = () => {
if(project.requestNumber && project.requestNumber != '') return `(${project.requestNumber})`
return '';
return <></>
}

const renderTooltip = (
<Tooltip id="link-tooltip">
Link Copied!
</Tooltip>
)

const requestNumberLink = () => {
if(requestNumber()){
const btnStyle = {
background: "none",
border: "none",
color: "#fff",
fontSize: "24px",
};

return (
<OverlayTrigger
placement="left"
trigger="click"
defaultShow={showAlert}
show={showAlert}
onToggle={() => setShowAlert(!showAlert)}
overlay={renderTooltip}
>
<button
onClick={copyRequestNumber}
style={btnStyle}
>
<i className="bi bi-link-45deg"><div className="d-none">Direct link to project</div></i>
</button>
</OverlayTrigger>

)
}

return <></>
}

return (
<div className="card mb-4">
<div className="card-header bg-primary text-white">
<span className="fw-bold">{requestNumber()} {project.requestTitle}</span> <br />
<span className="fst-italic">{project.pi} <small> ({project.piInstitution}) </small></span>
<div className="d-flex justify-content-between">
<div>
<span className="fw-bold">{requestNumber()} {project.requestTitle}</span> <br />
<span className="fst-italic">{project.pi} <small> ({project.piInstitution}) </small></span>
</div>
<div>
{ requestNumberLink() }
</div>
</div>
</div>
<div className="card-body">
<div className="row fw-bold border-bottom">
Expand All @@ -68,7 +128,7 @@ const Project = ({ project }) => {
</div>
</div>

<Accordion flush className="mt-3 mb-1">
<Accordion defaultActiveKey={defaultActiveKeys} activeKey={defaultActiveKeys} flush className="mt-3 mb-1" alwaysOpen>
<Accordion.Item eventKey="0">
<Accordion.Header>
Resources
Expand Down
11 changes: 11 additions & 0 deletions src/projects-browser/Project.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,14 @@
white-space: pre-wrap;
padding: 5px;
}

.plainButton {
background: none;
border: none;
color: #fff;
}

.plainButton:hover {
background: none;
text-decoration: underline;
}
50 changes: 37 additions & 13 deletions src/projects-browser/helpers/browserSlice.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ import { initialState } from "./initialState";
export const initApp = createAsyncThunk(
'projectsBrowser/initApp',
async(args, { getState, dispatch }) => {
const queryString = window.location.search;
const urlParams = new URLSearchParams(queryString);
if(urlParams.has('_requestNumber')){
dispatch( updateFilter({ name: 'requestNumber', value: urlParams.get('_requestNumber')}) )
dispatch( toggleListFiltered(true) );
}
await dispatch( getFilters() );
await dispatch( getProjects() );
dispatch( filterCleanup() );
Expand Down Expand Up @@ -44,28 +50,35 @@ export const getFilters = createAsyncThunk(

export const getProjects = createAsyncThunk(
'projectsBrowser/getProjects',
async (args, { getState }) => {
async (args, { getState, dispatch }) => {
const state = getState().projectsBrowser;

const filters = state.filters;

const typeLists = state.typeLists;
const fosList = typeLists.fosTypes.filter((fos) => fos.checked)
let url = `${state.apiUrl}?page=${state.pageData.current_page}`;

if(fosList.length != typeLists.fosTypes.length){
url += `&fos=${fosList.map((fos) => fos.fosTypeId).join(',')}`;
}
if(filters.requestNumber != ''){
url += `&request_number=${filters.requestNumber}`;
dispatch( toggleSingleEntry(true) );
} else {
dispatch( toggleSingleEntry(false) );
if(fosList.length != typeLists.fosTypes.length){
url += `&fos=${fosList.map((fos) => fos.fosTypeId).join(',')}`;
}

if(filters.org != '' && filters.org != '-- ALL --'){
url += `&org=${encodeURIComponent(filters.org)}`;
}
if(filters.org != '' && filters.org != '-- ALL --'){
url += `&org=${encodeURIComponent(filters.org)}`;
}

if(filters.allocationType != ''){
url += `&allocation_type=${filters.allocationType}`;
}
if(filters.allocationType != ''){
url += `&allocation_type=${filters.allocationType}`;
}

if(filters.resource != ''){
url += `&resources=${filters.resource}`;
if(filters.resource != ''){
url += `&resources=${filters.resource}`;
}
}

const response = await fetch(url);
Expand All @@ -85,7 +98,8 @@ export const browserSlice = createSlice({
org: '',
allocationType: '',
allFosToggled: false,
resource: ''
resource: '',
requestNumber: ''
}

browserSlice.caseReducers.toggleAllFos(state);
Expand Down Expand Up @@ -118,6 +132,12 @@ export const browserSlice = createSlice({
state.filters.allFosToggled = true;
}
},
toggleListFiltered: (state, { payload }) => {
state.listIsFiltered = payload;
},
toggleSingleEntry: (state, { payload }) => {
state.singleEntry = payload;
},
updateFilter: (state, { payload }) => {
state.filters[payload.name] = payload.value;
},
Expand Down Expand Up @@ -166,13 +186,17 @@ export const {
setTypeLists,
toggleAllFos,
toggleFos,
toggleListFiltered,
toggleSingleEntry,
updateFilter,
updatePageData,
} = browserSlice.actions;

export const selectFilters = (state) => state.projectsBrowser.filters;
export const selectFiltersLoaded = (state) => state.projectsBrowser.filtersLoaded;
export const selectFosTypes = (state) => state.projectsBrowser.fosTypes;
export const selectIsFiltered = (state) => state.projectsBrowser.listIsFiltered;
export const selectIsSingleEntry = (state) => state.projectsBrowser.singleEntry;
export const selectProjectsLoaded = (state) => state.projectsBrowser.projectsLoaded;
export const selectPageData = (state) => state.projectsBrowser.pageData;
export const selectPages = (state) => state.projectsBrowser.selectPages;
Expand Down
5 changes: 4 additions & 1 deletion src/projects-browser/helpers/initialState.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
export const initialState = {
apiUrl: null,
listIsFiltered: false,
pages: 1,
projects: [],
projectsLoaded: false,
filtersLoaded: true,
showPagination: false,
singleEntry: false,
filters: {
org: '',
allocationType: '',
allFosToggled: true,
resource: ''
resource: '',
requestNumber: '',
},
pageData: {
current_page: 1,
Expand Down

0 comments on commit 866f0af

Please sign in to comment.