src/routes/Main/ApisList/index.tsx (149 lines of code) (raw):
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See LICENSE.md in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { useEffect, useState } from "react";
import { useSearchParams } from "react-router-dom";
import { Spinner } from "@fluentui/react-components";
import NoApis from "../../../components/logos/NoApis";
import RestrictedAccessModal from "../../../components/RestrictedAccessModal/index";
import { Api } from "../../../contracts/api";
import { useApiService } from "../../../util/useApiService";
import { useAuthService } from "../../../util/useAuthService";
import { useConfigService } from "../../../util/useConfigService";
import {
LocalStorageKey,
useLocalStorage,
} from "../../../util/useLocalStorage";
import { useLogger } from "../../../util/useLogger";
import { useSession } from "../../../util/useSession";
import useFilters, { TFilterTag } from "./Filters/useFilters";
import ApisCards from "./ApisCards";
import ApisTable from "./ApisTable";
import Filters from "./Filters";
import FiltersActive from "./FiltersActive";
import FirstRow from "./FirstRow";
import { TLayout } from "./LayoutSwitch";
import css from "./index.module.scss";
const groupByKey = <T extends Record<string, any>>(list: T[], key: keyof T) =>
list.reduce(
(hash, obj) => ({
...hash,
[obj[key]]: (hash[obj[key]] || []).concat(obj),
}),
{} as Record<string, T[]>
);
const sortApis = (apis: Api[], sortBy?: string) => {
if (sortBy) {
const sortingOption = sortBy.split(".");
const key = sortingOption[0];
const order = sortingOption[1];
if (order === "asc") {
return apis && [...apis].sort((a, b) => (a[key] > b[key] ? 1 : -1));
} else {
return apis && [...apis].sort((a, b) => (a[key] < b[key] ? 1 : -1));
}
}
return apis;
};
const ApisList = () => {
const configService = useConfigService();
const layout = useLocalStorage(LocalStorageKey.apiListLayout).get();
const sortBy = useLocalStorage(LocalStorageKey.apiListSortBy).get();
const isRestricted = useLocalStorage(LocalStorageKey.isRestricted).get();
const session = useSession();
const isAuthenticated = session.isAuthenticated();
const apiService = useApiService();
const authService = useAuthService();
const logger = useLogger();
const [filters] = useFilters();
const [apis, setApis] = useState<Api[] | null>(null);
const [isLoading, setIsLoading] = useState(false);
const [showRestrictedModal, setShowRestrictedModal] = useState<boolean>(
false
);
const [searchParams] = useSearchParams();
const search = searchParams.get("search");
useEffect(() => {
setShowRestrictedModal(isRestricted === "true");
}, [isRestricted]);
useEffect(() => {
logger.trackView("API list");
initialize();
}, [isAuthenticated, filters, search, sortBy]);
const initialize = async () => {
const config = await configService.getSettings();
setIsLoading(true);
let searchQuery = "";
let filterQuery = "";
if (search) {
searchQuery = "$search=" + search;
}
if (filters?.length > 0 || config.scopingFilter?.length > 0) {
const groupedParams = groupByKey(filters, "filterTypeKey");
const groupedParamsArray = Object.values(groupedParams);
groupedParamsArray.forEach((paramGroup, index) => {
filterQuery += "(";
paramGroup.forEach((param: TFilterTag, paramIndex: number) => {
filterQuery += param.filterQuery;
if (paramIndex !== paramGroup.length - 1) {
filterQuery += " or ";
}
});
filterQuery += ")";
if (index !== groupedParamsArray.length - 1) {
filterQuery += " and ";
}
});
if (filterQuery.length > 0) {
filterQuery = "$filter=" + filterQuery;
if (config.scopingFilter?.length > 0) {
filterQuery += " and (" + config.scopingFilter + ")";
}
} else if (config.scopingFilter?.length > 0) {
filterQuery = "$filter=(" + config.scopingFilter + ")";
}
}
const result = await authService.isAuthenticated();
session.setAuthenticated(result);
setIsLoading(false);
if (filterQuery !== "" || searchQuery !== "") {
const queryString: string[] = [];
if (filterQuery) queryString.push(filterQuery);
if (searchQuery) queryString.push(searchQuery);
if (isAuthenticated) {
const apis = await apiService.getApis(queryString.join("&"));
setApis(sortApis(apis?.value, sortBy));
setIsLoading(false);
}
} else {
if (isAuthenticated) {
const apis = await apiService.getApis();
setApis(sortApis(apis?.value, sortBy));
setIsLoading(false);
}
}
};
return (
<section className={css.apisList}>
{showRestrictedModal && <RestrictedAccessModal />}
<Filters />
<div className={css.main}>
<FirstRow apis={apis} />
<FiltersActive />
{isLoading ? (
<Spinner size={"small"} />
) : !isAuthenticated ? (
<div className={css.emptyState}>
Sign in or create an account to view APIs.
</div>
) : apis?.length === 0 ? (
<div className={css.emptyState}>
<NoApis />
<div>
Could not find APIs. Try a different search term.
</div>
</div>
) : layout === TLayout.table ? (
<ApisTable apis={apis} />
) : (
<ApisCards apis={apis} />
)}
</div>
</section>
);
};
export default ApisList;