Skip to content

Commit

Permalink
Refactor SuperAdmin dashboard table filtering
Browse files Browse the repository at this point in the history
  • Loading branch information
jake-low committed Feb 19, 2025
1 parent a04aa85 commit bf8718e
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 84 deletions.
32 changes: 18 additions & 14 deletions src/components/SuperAdmin/SuperAdmin.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,19 @@ import messages from "./Messages";
import MetricsHeader from "./MetricsHeader";
import MetricsTable from "./MetricsTable";
import internalFilterToggle from "./internalFilterToggle";

const formatDateFromTab = (date) => {
const offset = date.getTimezoneOffset();
date = new Date(date.getTime() + offset * 60 * 1000);
return date;
};

const formatDate = (date) => {
const offset = date.getTimezoneOffset();
date = new Date(date.getTime() - offset * 60 * 1000);
return date.toISOString().split("T")[0];
};

/**
* SuperAdminPane is the top-level component for super administration functions. It has a
* User/Project/Challenge metrics tab for management of users, projects and challenges, and display of various summary metrics.
Expand All @@ -25,12 +38,6 @@ export const SuperAdminPane = (props) => {
const params = queryString.parse(props.location.search);
const currentTab = params["tab"] ? params["tab"] : "challenges";

const formatDateFromTab = (date) => {
const offset = date.getTimezoneOffset();
date = new Date(date.getTime() + offset * 60 * 1000);
return date;
};

const fromDateTab = params["from"] ? formatDateFromTab(new Date(params["from"])) : null;
const endDateTab = params["to"] ? formatDateFromTab(new Date(params["to"])) : null;

Expand All @@ -54,6 +61,7 @@ export const SuperAdminPane = (props) => {
const ArchivedFilterToggle = internalFilterToggle("archived");
const VirtualProjectFilterToggle = internalFilterToggle("virtual");
const manager = AsManager(props.user);

if (!manager.isLoggedIn()) {
return props.checkingLoginStatus ? (
<div className="admin mr-flex mr-justify-center mr-py-8 mr-w-full mr-bg-blue">
Expand All @@ -64,11 +72,9 @@ export const SuperAdminPane = (props) => {
);
}

const formatDate = (date) => {
const offset = date.getTimezoneOffset();
date = new Date(date.getTime() - offset * 60 * 1000);
return date.toISOString().split("T")[0];
};
if (!manager.isSuperUser()) {
return <div>You are not a super admin</div>;
}

const handleStartDate = (date) => {
setStartDate(date);
Expand All @@ -88,7 +94,7 @@ export const SuperAdminPane = (props) => {
setEndDate(null);
};

return manager.isSuperUser() ? (
return (
<div className="mr-bg-gradient-r-green-dark-blue mr-text-white mr-px-6 mr-py-8 mr-cards-inverse">
<MetricsHeader {...props} currentTab={currentTab} clearDate={clearDate} />
{
Expand Down Expand Up @@ -168,8 +174,6 @@ export const SuperAdminPane = (props) => {
}
<MetricsTable {...props} currentTab={currentTab} />
</div>
) : (
<div>You are not a super admin</div>
);
};

Expand Down
91 changes: 21 additions & 70 deletions src/components/SuperAdmin/WithMetricsSearchResults.jsx
Original file line number Diff line number Diff line change
@@ -1,82 +1,33 @@
import _filter from "lodash/filter";
import _isEmpty from "lodash/isEmpty";
import _omit from "lodash/omit";
import queryString from "query-string";
import { Component } from "react";
import WithSearch from "../HOCs/WithSearch/WithSearch";

const SEARCH_FIELD_GETTER = {
challenges: (item) => item.name,
projects: (item) => item.displayName,
users: (item) => item.osmProfile?.displayName,
};

/**
* WithMetricsSearchResults acts as a filter that applies the named search query to an
* array of candidate items, presenting to the wrapped component only those
* items that match the query.
*
* @param {string} searchName - the name of the search/query to work with
* @param {string} itemsProp - the name of the prop containing the array
* of items to search (e.g. 'challenges' or 'projects' or 'users').
* @param {string} outputProp - optional name of the prop to use when passing
* down the filtered results. By default it will be the same as
* itemsProp.
**/
export function WithMetricsSearchResults(WrappedComponent) {
return function (props) {
const params = queryString.parse(props.location.search);
const searchType = params["searchType"] || "challenges";
const getSearchField = SEARCH_FIELD_GETTER[searchType];
let items = props[searchType];

export const WithMetricsSearchResults = function (
WrappedComponent,
searchName,
itemsProp,
outputProp,
) {
return class extends Component {
/**
* @private
*/
render() {
const query = this.props.searchCriteria?.query ?? "";
let items, searchType;

const params = queryString.parse(this.props.location.search);
searchType = params["searchType"] || "challenges";
items = this.props[searchType];

let searchResults = this.props[searchType];
let searchActive = false;

if (searchType === "challenges" && query) {
searchResults = _filter(
items,
(item) => (item?.name ?? "").toLowerCase().indexOf(query) !== -1,
);
} else if (searchType === "projects" && query) {
searchResults = _filter(
items,
(item) => (item?.displayName ?? "").toLowerCase().indexOf(query) !== -1,
);
} else if (searchType === "users" && query) {
searchResults = _filter(
items,
(item) => (item?.osmProfile?.displayName ?? "").toLowerCase().indexOf(query) !== -1,
);
}

if (_isEmpty(outputProp)) {
outputProp = itemsProp;
}
outputProp = searchType;
searchName = searchType;
return (
<WrappedComponent
{...{
[outputProp]: searchResults,
[`${searchName}SearchActive`]: searchActive,
}}
{..._omit(this.props, outputProp)}
/>
);
const query = props.searchCriteria?.query ?? "";
if (query && getSearchField) {
items = items.filter((item) => getSearchField(item)?.toLowerCase().includes(query));
}

const forwardedProps = { ...props, [searchType]: items };
return <WrappedComponent {...forwardedProps} />;
};
};
}

export default (WrappedComponent, searchName, itemsProp, outputProp, searchFunction = null) =>
WithSearch(
WithMetricsSearchResults(WrappedComponent, searchName, itemsProp, outputProp),
searchName,
searchFunction,
);
export default (WrappedComponent, searchName, itemsProp, searchFunction = null) =>
WithSearch(WithMetricsSearchResults(WrappedComponent), searchName, searchFunction);

0 comments on commit bf8718e

Please sign in to comment.