diff --git a/src/pages/application-inventory/application-assessment/components/stakeholders-form/stakeholders-form.tsx b/src/pages/application-inventory/application-assessment/components/stakeholders-form/stakeholders-form.tsx index f1a3bc6e..4be75445 100644 --- a/src/pages/application-inventory/application-assessment/components/stakeholders-form/stakeholders-form.tsx +++ b/src/pages/application-inventory/application-assessment/components/stakeholders-form/stakeholders-form.tsx @@ -1,4 +1,4 @@ -import React, { useEffect } from "react"; +import React, { useEffect, useMemo } from "react"; import { useTranslation } from "react-i18next"; import { useFormikContext } from "formik"; @@ -11,11 +11,19 @@ import { TextContent, } from "@patternfly/react-core"; -import { useFetchStakeholderGroups, useFetchStakeholders } from "shared/hooks"; +import { useFetch } from "shared/hooks"; import { DEFAULT_SELECT_MAX_HEIGHT } from "Constants"; import { getValidatedFromError } from "utils/utils"; +import { StakeholderGroupPage, StakeholderPage } from "api/models"; +import { + getAllStakeholderGroups, + getAllStakeholders, + stakeholderGroupPageMapper, + stakeholderPageMapper, +} from "api/apiUtils"; + import { IFormValues } from "../../form-utils"; import { StakeholderSelect } from "./stakeholder-select"; @@ -27,23 +35,45 @@ export const StakeholdersForm: React.FC = () => { const { t } = useTranslation(); const formik = useFormikContext(); + // Fetch stakeholders + const { - stakeholders, + data: stakeholdersPage, isFetching: isFetchingStakeholders, fetchError: fetchErrorStakeholders, - fetchAllStakeholders, - } = useFetchStakeholders(); + requestFetch: fetchAllStakeholders, + } = useFetch({ + defaultIsFetching: true, + onFetch: getAllStakeholders, + }); + + const stakeholders = useMemo(() => { + return stakeholdersPage + ? stakeholderPageMapper(stakeholdersPage) + : undefined; + }, [stakeholdersPage]); useEffect(() => { fetchAllStakeholders(); }, [fetchAllStakeholders]); + // Fetch stakeholder groups + const { - stakeholderGroups, + data: stakeholderGroupPage, isFetching: isFetchingStakeholderGroups, fetchError: fetchErrorStakeholderGroups, - fetchAllStakeholderGroups, - } = useFetchStakeholderGroups(); + requestFetch: fetchAllStakeholderGroups, + } = useFetch({ + defaultIsFetching: true, + onFetch: getAllStakeholderGroups, + }); + + const stakeholderGroups = useMemo(() => { + return stakeholderGroupPage + ? stakeholderGroupPageMapper(stakeholderGroupPage) + : undefined; + }, [stakeholderGroupPage]); useEffect(() => { fetchAllStakeholderGroups(); diff --git a/src/pages/application-inventory/application-list/components/application-dependencies-form/application-dependencies-form.tsx b/src/pages/application-inventory/application-list/components/application-dependencies-form/application-dependencies-form.tsx index 8a69763c..32cb0ecd 100644 --- a/src/pages/application-inventory/application-list/components/application-dependencies-form/application-dependencies-form.tsx +++ b/src/pages/application-inventory/application-list/components/application-dependencies-form/application-dependencies-form.tsx @@ -1,4 +1,10 @@ -import React, { useContext, useEffect, useState } from "react"; +import React, { + useCallback, + useContext, + useEffect, + useMemo, + useState, +} from "react"; import { useTranslation } from "react-i18next"; import { @@ -13,16 +19,25 @@ import { } from "@patternfly/react-core"; import { OptionWithValue } from "shared/components"; +import { useFetch } from "shared/hooks"; + import { - useFetchApplicationDependencies, - useFetchApplications, -} from "shared/hooks"; + Application, + ApplicationDependency, + ApplicationDependencyPage, + ApplicationPage, +} from "api/models"; -import { Application, ApplicationDependency } from "api/models"; +import { + applicationDependencyPageMapper, + applicationPageMapper, + getAllApplicationDependencies, + getAllApplications, +} from "api/apiUtils"; +import { getAxiosErrorMessage } from "utils/utils"; import { FormContext } from "./form-context"; import { SelectDependency } from "./select-dependency"; -import { getAxiosErrorMessage } from "utils/utils"; const northToStringFn = (value: ApplicationDependency) => value.from.name; const southToStringFn = (value: ApplicationDependency) => value.to.name; @@ -66,40 +81,75 @@ export const ApplicationDependenciesForm: React.FC { + return getAllApplicationDependencies({ + to: [`${application.id}`], + }); + }, [application]); + + const getAllSouthApplicationDependencies = useCallback(() => { + return getAllApplicationDependencies({ + from: [`${application.id}`], + }); + }, [application]); + const { - applicationDependencies: northDependencies, + data: northDependenciesPage, isFetching: isFetchingNorthDependencies, fetchError: fetchErrorNorthDependencies, - fetchAllApplicationDependencies: fetchAllNorthDependencies, - } = useFetchApplicationDependencies(); + requestFetch: fetchAllNorthDependencies, + } = useFetch({ + defaultIsFetching: true, + onFetch: getAllNorthApplicationDependencies, + }); + + const northDependencies = useMemo(() => { + return northDependenciesPage + ? applicationDependencyPageMapper(northDependenciesPage) + : undefined; + }, [northDependenciesPage]); const { - applicationDependencies: southDependencies, + data: southDependenciesPage, isFetching: isFetchingSouthDependencies, fetchError: fetchErrorSouthDependencies, - fetchAllApplicationDependencies: fetchAllSouthDependencies, - } = useFetchApplicationDependencies(); + requestFetch: fetchAllSouthDependencies, + } = useFetch({ + defaultIsFetching: true, + onFetch: getAllSouthApplicationDependencies, + }); + + const southDependencies = useMemo(() => { + return southDependenciesPage + ? applicationDependencyPageMapper(southDependenciesPage) + : undefined; + }, [southDependenciesPage]); useEffect(() => { - fetchAllNorthDependencies({ - to: [`${application.id}`], - }); - }, [application, fetchAllNorthDependencies]); + fetchAllNorthDependencies(); + }, [fetchAllNorthDependencies]); useEffect(() => { - fetchAllSouthDependencies({ - from: [`${application.id}`], - }); - }, [application, fetchAllSouthDependencies]); + fetchAllSouthDependencies(); + }, [fetchAllSouthDependencies]); // Applications const { - applications, + data: applicationsPage, isFetching: isFetchingApplications, fetchError: fetchErrorApplications, - fetchAllApplications, - } = useFetchApplications(); + requestFetch: fetchAllApplications, + } = useFetch({ + defaultIsFetching: true, + onFetch: getAllApplications, + }); + + const applications = useMemo(() => { + return applicationsPage + ? applicationPageMapper(applicationsPage) + : undefined; + }, [applicationsPage]); useEffect(() => { fetchAllApplications(); diff --git a/src/pages/application-inventory/application-list/components/application-form/application-form.tsx b/src/pages/application-inventory/application-list/components/application-form/application-form.tsx index daaeb01e..e37d879c 100644 --- a/src/pages/application-inventory/application-list/components/application-form/application-form.tsx +++ b/src/pages/application-inventory/application-list/components/application-form/application-form.tsx @@ -20,16 +20,32 @@ import { MultiSelectFetchFormikField, OptionWithValue, } from "shared/components"; -import { useFetchBusinessServices, useFetchTagTypes } from "shared/hooks"; +import { useFetch } from "shared/hooks"; import { DEFAULT_SELECT_MAX_HEIGHT } from "Constants"; import { createApplication, TagTypeSortBy, updateApplication } from "api/rest"; -import { Application, BusinessService, Tag } from "api/models"; +import { + Application, + BusinessService, + BusinessServicePage, + Tag, + TagTypePage, +} from "api/models"; import { getAxiosErrorMessage, getValidatedFromError, getValidatedFromErrorTouched, } from "utils/utils"; +import { + bussinessServicePageMapper, + getAllBusinessServices, + getAllTagTypes, + tagTypePageMapper, +} from "api/apiUtils"; + +export const getAllTagTypesSortedByRank = () => { + return getAllTagTypes({ field: TagTypeSortBy.RANK }); +}; const businesServiceToOption = ( value: BusinessService @@ -72,11 +88,20 @@ export const ApplicationForm: React.FC = ({ // Business services const { - businessServices, + data: businessServicesPage, isFetching: isFetchingBusinessServices, fetchError: fetchErrorBusinessServices, - fetchAllBusinessServices, - } = useFetchBusinessServices(); + requestFetch: fetchAllBusinessServices, + } = useFetch({ + defaultIsFetching: true, + onFetch: getAllBusinessServices, + }); + + const businessServices = useMemo(() => { + return businessServicesPage + ? bussinessServicePageMapper(businessServicesPage) + : undefined; + }, [businessServicesPage]); useEffect(() => { fetchAllBusinessServices(); @@ -85,14 +110,21 @@ export const ApplicationForm: React.FC = ({ // TagTypes const { - tagTypes, + data: tagTypesPage, isFetching: isFetchingTagTypes, fetchError: fetchErrorTagTypes, - fetchAllTagTypes, - } = useFetchTagTypes(); + requestFetch: fetchAllTagTypes, + } = useFetch({ + defaultIsFetching: true, + onFetch: getAllTagTypesSortedByRank, + }); + + const tagTypes = useMemo(() => { + return tagTypesPage ? tagTypePageMapper(tagTypesPage) : undefined; + }, [tagTypesPage]); useEffect(() => { - fetchAllTagTypes({ field: TagTypeSortBy.RANK }); + fetchAllTagTypes(); }, [fetchAllTagTypes]); // Tags diff --git a/src/pages/controls/business-services/business-services.tsx b/src/pages/controls/business-services/business-services.tsx index 514ef561..c676fca3 100644 --- a/src/pages/controls/business-services/business-services.tsx +++ b/src/pages/controls/business-services/business-services.tsx @@ -1,4 +1,4 @@ -import React, { useCallback, useEffect, useState } from "react"; +import React, { useCallback, useEffect, useMemo, useState } from "react"; import { AxiosResponse } from "axios"; import { useTranslation } from "react-i18next"; @@ -32,12 +32,17 @@ import { } from "shared/components"; import { useTableControls, - useFetchBusinessServices, + useFetch, useDeleteBusinessService, } from "shared/hooks"; -import { BusinessService, SortByQuery } from "api/models"; -import { BusinessServiceSortBy, BusinessServiceSortByQuery } from "api/rest"; +import { BusinessService, BusinessServicePage, SortByQuery } from "api/models"; +import { + BusinessServiceSortBy, + BusinessServiceSortByQuery, + getBusinessServices, +} from "api/rest"; +import { bussinessServicePageMapper } from "api/apiUtils"; import { getAxiosErrorMessage } from "utils/utils"; import { NewBusinessServiceModal } from "./components/new-business-service-modal"; @@ -107,13 +112,6 @@ export const BusinessServices: React.FC = () => { const { deleteBusinessService } = useDeleteBusinessService(); - const { - businessServices, - isFetching, - fetchError, - fetchBusinessServices, - } = useFetchBusinessServices(true); - const { paginationQuery, sortByQuery, @@ -123,8 +121,8 @@ export const BusinessServices: React.FC = () => { sortByQuery: { direction: "asc", index: 0 }, }); - const refreshTable = useCallback(() => { - fetchBusinessServices( + const fetchBusinessServices = useCallback(() => { + return getBusinessServices( { name: filtersValue.get(FilterKey.NAME), description: filtersValue.get(FilterKey.DESCRIPTION), @@ -133,19 +131,27 @@ export const BusinessServices: React.FC = () => { paginationQuery, toSortByQuery(sortByQuery) ); - }, [filtersValue, paginationQuery, sortByQuery, fetchBusinessServices]); + }, [filtersValue, paginationQuery, sortByQuery]); + + const { + data: businessServicesPage, + isFetching, + fetchError, + requestFetch: refreshTable, + } = useFetch({ + defaultIsFetching: true, + onFetch: fetchBusinessServices, + }); + + const businessServices = useMemo(() => { + return businessServicesPage + ? bussinessServicePageMapper(businessServicesPage) + : undefined; + }, [businessServicesPage]); useEffect(() => { - fetchBusinessServices( - { - name: filtersValue.get(FilterKey.NAME), - description: filtersValue.get(FilterKey.DESCRIPTION), - owner: filtersValue.get(FilterKey.OWNER), - }, - paginationQuery, - toSortByQuery(sortByQuery) - ); - }, [filtersValue, paginationQuery, sortByQuery, fetchBusinessServices]); + refreshTable(); + }, [filtersValue, paginationQuery, sortByQuery, refreshTable]); const columns: ICell[] = [ { title: t("terms.name"), transforms: [sortable, cellWidth(25)] }, diff --git a/src/pages/controls/business-services/components/business-service-form/business-service-form.tsx b/src/pages/controls/business-services/components/business-service-form/business-service-form.tsx index 343809a1..f4cbce41 100644 --- a/src/pages/controls/business-services/components/business-service-form/business-service-form.tsx +++ b/src/pages/controls/business-services/components/business-service-form/business-service-form.tsx @@ -19,16 +19,17 @@ import { SingleSelectFetchFormikField, OptionWithValue, } from "shared/components"; -import { useFetchStakeholders } from "shared/hooks"; +import { useFetch } from "shared/hooks"; import { DEFAULT_SELECT_MAX_HEIGHT } from "Constants"; import { createBusinessService, updateBusinessService } from "api/rest"; -import { BusinessService, Stakeholder } from "api/models"; +import { BusinessService, Stakeholder, StakeholderPage } from "api/models"; import { getAxiosErrorMessage, getValidatedFromError, getValidatedFromErrorTouched, } from "utils/utils"; +import { getAllStakeholders, stakeholderPageMapper } from "api/apiUtils"; const stakeholderToOption = ( value: Stakeholder @@ -59,11 +60,20 @@ export const BusinessServiceForm: React.FC = ({ const [error, setError] = useState(); const { - stakeholders, + data: stakeholdersPage, isFetching: isFetchingStakeholders, fetchError: fetchErrorStakeholders, - fetchAllStakeholders, - } = useFetchStakeholders(); + requestFetch: fetchAllStakeholders, + } = useFetch({ + defaultIsFetching: true, + onFetch: getAllStakeholders, + }); + + const stakeholders = useMemo(() => { + return stakeholdersPage + ? stakeholderPageMapper(stakeholdersPage) + : undefined; + }, [stakeholdersPage]); useEffect(() => { fetchAllStakeholders(); diff --git a/src/pages/controls/job-functions/job-functions.tsx b/src/pages/controls/job-functions/job-functions.tsx index 0b876e86..ee89f79b 100644 --- a/src/pages/controls/job-functions/job-functions.tsx +++ b/src/pages/controls/job-functions/job-functions.tsx @@ -1,4 +1,4 @@ -import React, { useCallback, useEffect, useState } from "react"; +import React, { useCallback, useEffect, useMemo, useState } from "react"; import { AxiosResponse } from "axios"; import { useTranslation } from "react-i18next"; @@ -30,15 +30,16 @@ import { NoDataEmptyState, SearchFilter, } from "shared/components"; -import { - useTableControls, - useDeleteJobFunction, - useFetchJobFunctions, -} from "shared/hooks"; +import { useTableControls, useDeleteJobFunction, useFetch } from "shared/hooks"; import { getAxiosErrorMessage } from "utils/utils"; -import { JobFunctionSortBy, JobFunctionSortByQuery } from "api/rest"; -import { SortByQuery, JobFunction } from "api/models"; +import { + getJobFunctions, + JobFunctionSortBy, + JobFunctionSortByQuery, +} from "api/rest"; +import { SortByQuery, JobFunction, JobFunctionPage } from "api/models"; +import { jobFunctionPageMapper } from "api/apiUtils"; import { NewJobFunctionModal } from "./components/new-job-function-modal"; import { UpdateJobFunctionModal } from "./components/update-job-function-modal"; @@ -90,13 +91,6 @@ export const JobFunctions: React.FC = () => { const { deleteJobFunction } = useDeleteJobFunction(); - const { - jobFunctions, - isFetching, - fetchError, - fetchJobFunctions, - } = useFetchJobFunctions(true); - const { paginationQuery, sortByQuery, @@ -106,25 +100,35 @@ export const JobFunctions: React.FC = () => { sortByQuery: { direction: "asc", index: 0 }, }); - const refreshTable = useCallback(() => { - fetchJobFunctions( + const fetchJobFunctions = useCallback(() => { + return getJobFunctions( { role: filtersValue.get(FilterKey.NAME), }, paginationQuery, toSortByQuery(sortByQuery) ); - }, [filtersValue, paginationQuery, sortByQuery, fetchJobFunctions]); + }, [filtersValue, paginationQuery, sortByQuery]); + + const { + data: jobFunctionsPage, + isFetching, + fetchError, + requestFetch: refreshTable, + } = useFetch({ + defaultIsFetching: true, + onFetch: fetchJobFunctions, + }); + + const jobFunctions = useMemo(() => { + return jobFunctionsPage + ? jobFunctionPageMapper(jobFunctionsPage) + : undefined; + }, [jobFunctionsPage]); useEffect(() => { - fetchJobFunctions( - { - role: filtersValue.get(FilterKey.NAME), - }, - paginationQuery, - toSortByQuery(sortByQuery) - ); - }, [filtersValue, paginationQuery, sortByQuery, fetchJobFunctions]); + refreshTable(); + }, [filtersValue, paginationQuery, sortByQuery, refreshTable]); // diff --git a/src/pages/controls/stakeholder-groups/components/stakeholder-group-form/stakeholder-group-form.tsx b/src/pages/controls/stakeholder-groups/components/stakeholder-group-form/stakeholder-group-form.tsx index 27073bb6..f9ae8c96 100644 --- a/src/pages/controls/stakeholder-groups/components/stakeholder-group-form/stakeholder-group-form.tsx +++ b/src/pages/controls/stakeholder-groups/components/stakeholder-group-form/stakeholder-group-form.tsx @@ -19,16 +19,17 @@ import { OptionWithValue, MultiSelectFetchFormikField, } from "shared/components"; -import { useFetchStakeholders } from "shared/hooks"; +import { useFetch } from "shared/hooks"; import { DEFAULT_SELECT_MAX_HEIGHT } from "Constants"; import { createStakeholderGroup, updateStakeholderGroup } from "api/rest"; -import { Stakeholder, StakeholderGroup } from "api/models"; +import { Stakeholder, StakeholderGroup, StakeholderPage } from "api/models"; import { getAxiosErrorMessage, getValidatedFromError, getValidatedFromErrorTouched, } from "utils/utils"; +import { getAllStakeholders, stakeholderPageMapper } from "api/apiUtils"; const stakeholderToOption = ( value: Stakeholder @@ -59,11 +60,20 @@ export const StakeholderGroupForm: React.FC = ({ const [error, setError] = useState(); const { - stakeholders, + data: stakeholdersPage, isFetching: isFetchingStakeholders, fetchError: fetchErrorStakeholders, - fetchAllStakeholders, - } = useFetchStakeholders(); + requestFetch: fetchAllStakeholders, + } = useFetch({ + defaultIsFetching: true, + onFetch: getAllStakeholders, + }); + + const stakeholders = useMemo(() => { + return stakeholdersPage + ? stakeholderPageMapper(stakeholdersPage) + : undefined; + }, [stakeholdersPage]); useEffect(() => { fetchAllStakeholders(); diff --git a/src/pages/controls/stakeholder-groups/stakeholder-groups.tsx b/src/pages/controls/stakeholder-groups/stakeholder-groups.tsx index 7f14ea9d..de751d22 100644 --- a/src/pages/controls/stakeholder-groups/stakeholder-groups.tsx +++ b/src/pages/controls/stakeholder-groups/stakeholder-groups.tsx @@ -1,4 +1,4 @@ -import React, { useCallback, useEffect, useState } from "react"; +import React, { useCallback, useEffect, useMemo, useState } from "react"; import { AxiosResponse } from "axios"; import { useTranslation } from "react-i18next"; import { useSelectionState } from "@konveyor/lib-ui"; @@ -40,13 +40,23 @@ import { } from "shared/components"; import { useTableControls, - useFetchStakeholderGroups, + useFetch, useDeleteStakeholderGroup, } from "shared/hooks"; import { getAxiosErrorMessage } from "utils/utils"; -import { StakeholderGroupSortBy, StakeholderGroupSortByQuery } from "api/rest"; -import { StakeholderGroup, SortByQuery } from "api/models"; + +import { + getStakeholderGroups, + StakeholderGroupSortBy, + StakeholderGroupSortByQuery, +} from "api/rest"; +import { + StakeholderGroup, + SortByQuery, + StakeholderGroupPage, +} from "api/models"; +import { stakeholderGroupPageMapper } from "api/apiUtils"; import { NewStakeholderGroupModal } from "./components/new-stakeholder-group-modal"; import { UpdateStakeholderGroupModal } from "./components/update-stakeholder-group-modal"; @@ -115,13 +125,6 @@ export const StakeholderGroups: React.FC = () => { const { deleteStakeholderGroup } = useDeleteStakeholderGroup(); - const { - stakeholderGroups, - isFetching, - fetchError, - fetchStakeholderGroups, - } = useFetchStakeholderGroups(true); - const { paginationQuery, sortByQuery, @@ -131,16 +134,8 @@ export const StakeholderGroups: React.FC = () => { sortByQuery: { direction: "asc", index: 1 }, }); - const { - isItemSelected: isItemExpanded, - toggleItemSelected: toggleItemExpanded, - } = useSelectionState({ - items: stakeholderGroups?.data || [], - isEqual: (a, b) => a.id === b.id, - }); - - const refreshTable = useCallback(() => { - fetchStakeholderGroups( + const fetchStakeholderGroups = useCallback(() => { + return getStakeholderGroups( { name: filtersValue.get(FilterKey.NAME), description: filtersValue.get(FilterKey.DESCRIPTION), @@ -149,19 +144,35 @@ export const StakeholderGroups: React.FC = () => { paginationQuery, toSortByQuery(sortByQuery) ); - }, [filtersValue, paginationQuery, sortByQuery, fetchStakeholderGroups]); + }, [filtersValue, paginationQuery, sortByQuery]); + + const { + data: stakeholderGroupsPage, + isFetching, + fetchError, + requestFetch: refreshTable, + } = useFetch({ + defaultIsFetching: true, + onFetch: fetchStakeholderGroups, + }); + + const stakeholderGroups = useMemo(() => { + return stakeholderGroupsPage + ? stakeholderGroupPageMapper(stakeholderGroupsPage) + : undefined; + }, [stakeholderGroupsPage]); useEffect(() => { - fetchStakeholderGroups( - { - name: filtersValue.get(FilterKey.NAME), - description: filtersValue.get(FilterKey.DESCRIPTION), - stakeholder: filtersValue.get(FilterKey.STAKEHOLDER), - }, - paginationQuery, - toSortByQuery(sortByQuery) - ); - }, [filtersValue, paginationQuery, sortByQuery, fetchStakeholderGroups]); + refreshTable(); + }, [filtersValue, paginationQuery, sortByQuery, refreshTable]); + + const { + isItemSelected: isItemExpanded, + toggleItemSelected: toggleItemExpanded, + } = useSelectionState({ + items: stakeholderGroups?.data || [], + isEqual: (a, b) => a.id === b.id, + }); const columns: ICell[] = [ { diff --git a/src/pages/controls/stakeholders/components/stakeholder-form/stakeholder-form.tsx b/src/pages/controls/stakeholders/components/stakeholder-form/stakeholder-form.tsx index 393cf35d..523cac3f 100644 --- a/src/pages/controls/stakeholders/components/stakeholder-form/stakeholder-form.tsx +++ b/src/pages/controls/stakeholders/components/stakeholder-form/stakeholder-form.tsx @@ -19,16 +19,28 @@ import { OptionWithValue, MultiSelectFetchFormikField, } from "shared/components"; -import { useFetchStakeholderGroups, useFetchJobFunctions } from "shared/hooks"; +import { useFetch } from "shared/hooks"; import { DEFAULT_SELECT_MAX_HEIGHT } from "Constants"; import { createStakeholder, updateStakeholder } from "api/rest"; -import { JobFunction, Stakeholder, StakeholderGroup } from "api/models"; +import { + JobFunction, + JobFunctionPage, + Stakeholder, + StakeholderGroup, + StakeholderGroupPage, +} from "api/models"; import { getAxiosErrorMessage, getValidatedFromError, getValidatedFromErrorTouched, } from "utils/utils"; +import { + getAllJobFunctions, + getAllStakeholderGroups, + jobFunctionPageMapper, + stakeholderGroupPageMapper, +} from "api/apiUtils"; const jobFunctionToOption = ( value: JobFunction @@ -67,22 +79,40 @@ export const StakeholderForm: React.FC = ({ const [error, setError] = useState(); const { - jobFunctions, + data: jobFunctionsPage, isFetching: isFetchingJobFunctions, fetchError: fetchErrorJobFunctions, - fetchAllJobFunctions, - } = useFetchJobFunctions(); + requestFetch: fetchAllJobFunctions, + } = useFetch({ + defaultIsFetching: true, + onFetch: getAllJobFunctions, + }); + + const jobFunctions = useMemo(() => { + return jobFunctionsPage + ? jobFunctionPageMapper(jobFunctionsPage) + : undefined; + }, [jobFunctionsPage]); useEffect(() => { fetchAllJobFunctions(); }, [fetchAllJobFunctions]); const { - stakeholderGroups, + data: stakeholderGroupsPage, isFetching: isFetchingGroups, fetchError: fetchErrorGroups, - fetchAllStakeholderGroups, - } = useFetchStakeholderGroups(); + requestFetch: fetchAllStakeholderGroups, + } = useFetch({ + defaultIsFetching: true, + onFetch: getAllStakeholderGroups, + }); + + const stakeholderGroups = useMemo(() => { + return stakeholderGroupsPage + ? stakeholderGroupPageMapper(stakeholderGroupsPage) + : undefined; + }, [stakeholderGroupsPage]); useEffect(() => { fetchAllStakeholderGroups(); diff --git a/src/pages/controls/stakeholders/stakeholders.tsx b/src/pages/controls/stakeholders/stakeholders.tsx index 042f3fad..1ea3c5b1 100644 --- a/src/pages/controls/stakeholders/stakeholders.tsx +++ b/src/pages/controls/stakeholders/stakeholders.tsx @@ -1,4 +1,4 @@ -import React, { useCallback, useEffect, useState } from "react"; +import React, { useCallback, useEffect, useMemo, useState } from "react"; import { AxiosResponse } from "axios"; import { useTranslation } from "react-i18next"; import { useSelectionState } from "@konveyor/lib-ui"; @@ -38,15 +38,16 @@ import { AppTableToolbarToggleGroup, NoDataEmptyState, } from "shared/components"; -import { - useTableControls, - useFetchStakeholders, - useDeleteStakeholder, -} from "shared/hooks"; +import { useTableControls, useDeleteStakeholder, useFetch } from "shared/hooks"; import { getAxiosErrorMessage } from "utils/utils"; -import { StakeholderSortBy, StakeholderSortByQuery } from "api/rest"; -import { Stakeholder, SortByQuery } from "api/models"; +import { + getStakeholders, + StakeholderSortBy, + StakeholderSortByQuery, +} from "api/rest"; +import { Stakeholder, SortByQuery, StakeholderPage } from "api/models"; +import { stakeholderPageMapper } from "api/apiUtils"; import { NewStakeholderModal } from "./components/new-stakeholder-modal"; import { UpdateStakeholderModal } from "./components/update-stakeholder-modal"; @@ -126,13 +127,6 @@ export const Stakeholders: React.FC = () => { const { deleteStakeholder } = useDeleteStakeholder(); - const { - stakeholders, - isFetching, - fetchError, - fetchStakeholders, - } = useFetchStakeholders(true); - const { paginationQuery, sortByQuery, @@ -142,16 +136,8 @@ export const Stakeholders: React.FC = () => { sortByQuery: { direction: "asc", index: 1 }, }); - const { - isItemSelected: isItemExpanded, - toggleItemSelected: toggleItemExpanded, - } = useSelectionState({ - items: stakeholders?.data || [], - isEqual: (a, b) => a.id === b.id, - }); - - const refreshTable = useCallback(() => { - fetchStakeholders( + const fetchStakeholders = useCallback(() => { + return getStakeholders( { email: filtersValue.get(FilterKey.EMAIL), displayName: filtersValue.get(FilterKey.DISPLAY_NAME), @@ -161,20 +147,35 @@ export const Stakeholders: React.FC = () => { paginationQuery, toSortByQuery(sortByQuery) ); - }, [filtersValue, paginationQuery, sortByQuery, fetchStakeholders]); + }, [filtersValue, paginationQuery, sortByQuery]); + + const { + data: stakeholdersPage, + isFetching, + fetchError, + requestFetch: refreshTable, + } = useFetch({ + defaultIsFetching: true, + onFetch: fetchStakeholders, + }); + + const stakeholders = useMemo(() => { + return stakeholdersPage + ? stakeholderPageMapper(stakeholdersPage) + : undefined; + }, [stakeholdersPage]); useEffect(() => { - fetchStakeholders( - { - email: filtersValue.get(FilterKey.EMAIL), - displayName: filtersValue.get(FilterKey.DISPLAY_NAME), - jobFunction: filtersValue.get(FilterKey.JOB_FUNCTION), - stakeholderGroup: filtersValue.get(FilterKey.STAKEHOLDER_GROUP), - }, - paginationQuery, - toSortByQuery(sortByQuery) - ); - }, [filtersValue, paginationQuery, sortByQuery, fetchStakeholders]); + refreshTable(); + }, [filtersValue, paginationQuery, sortByQuery, refreshTable]); + + const { + isItemSelected: isItemExpanded, + toggleItemSelected: toggleItemExpanded, + } = useSelectionState({ + items: stakeholders?.data || [], + isEqual: (a, b) => a.id === b.id, + }); const columns: ICell[] = [ { diff --git a/src/pages/controls/tags/components/tag-form/tag-form.tsx b/src/pages/controls/tags/components/tag-form/tag-form.tsx index de17b4dc..12b52998 100644 --- a/src/pages/controls/tags/components/tag-form/tag-form.tsx +++ b/src/pages/controls/tags/components/tag-form/tag-form.tsx @@ -18,16 +18,17 @@ import { SingleSelectFetchFormikField, OptionWithValue, } from "shared/components"; -import { useFetchTagTypes } from "shared/hooks"; +import { useFetch } from "shared/hooks"; import { DEFAULT_SELECT_MAX_HEIGHT } from "Constants"; import { createTag, updateTag } from "api/rest"; -import { Tag, TagType } from "api/models"; +import { Tag, TagType, TagTypePage } from "api/models"; import { getAxiosErrorMessage, getValidatedFromError, getValidatedFromErrorTouched, } from "utils/utils"; +import { getAllTagTypes, tagTypePageMapper } from "api/apiUtils"; const tagTypeToOption = (value: TagType): OptionWithValue => ({ value, @@ -50,11 +51,18 @@ export const TagForm: React.FC = ({ tag, onSaved, onCancel }) => { const [error, setError] = useState(); const { - tagTypes, + data: tagTypesPage, isFetching: isFetchingTagTypes, fetchError: fetchErrorTagTypes, - fetchAllTagTypes, - } = useFetchTagTypes(); + requestFetch: fetchAllTagTypes, + } = useFetch({ + defaultIsFetching: true, + onFetch: getAllTagTypes, + }); + + const tagTypes = useMemo(() => { + return tagTypesPage ? tagTypePageMapper(tagTypesPage) : undefined; + }, [tagTypesPage]); useEffect(() => { fetchAllTagTypes(); diff --git a/src/pages/controls/tags/tags.tsx b/src/pages/controls/tags/tags.tsx index 447558ca..3e2f2d80 100644 --- a/src/pages/controls/tags/tags.tsx +++ b/src/pages/controls/tags/tags.tsx @@ -1,4 +1,4 @@ -import React, { useCallback, useEffect, useState } from "react"; +import React, { useCallback, useEffect, useMemo, useState } from "react"; import { AxiosResponse } from "axios"; import { useTranslation } from "react-i18next"; import { useSelectionState } from "@konveyor/lib-ui"; @@ -36,13 +36,14 @@ import { import { useTableControls, useDeleteTagType, - useFetchTagTypes, + useFetch, useDeleteTag, } from "shared/hooks"; import { getAxiosErrorMessage } from "utils/utils"; -import { TagTypeSortBy, TagTypeSortByQuery } from "api/rest"; -import { SortByQuery, Tag, TagType } from "api/models"; +import { getTagTypes, TagTypeSortBy, TagTypeSortByQuery } from "api/rest"; +import { SortByQuery, Tag, TagType, TagTypePage } from "api/models"; +import { tagTypePageMapper } from "api/apiUtils"; import { NewTagTypeModal } from "./components/new-tag-type-modal"; import { UpdateTagTypeModal } from "./components/update-tag-type-modal"; @@ -119,10 +120,6 @@ export const Tags: React.FC = () => { const { deleteTagType } = useDeleteTagType(); const { deleteTag } = useDeleteTag(); - const { tagTypes, isFetching, fetchError, fetchTagTypes } = useFetchTagTypes( - true - ); - const { paginationQuery, sortByQuery, @@ -132,16 +129,8 @@ export const Tags: React.FC = () => { sortByQuery: { direction: "asc", index: 1 }, }); - const { - isItemSelected: isItemExpanded, - toggleItemSelected: toggleItemExpanded, - } = useSelectionState({ - items: tagTypes?.data || [], - isEqual: (a, b) => a.id === b.id, - }); - - const refreshTable = useCallback(() => { - fetchTagTypes( + const fetchTagTypes = useCallback(() => { + return getTagTypes( { tagTypes: filtersValue.get(FilterKey.TAG_TYPE), tags: filtersValue.get(FilterKey.TAG), @@ -149,18 +138,33 @@ export const Tags: React.FC = () => { paginationQuery, toSortByQuery(sortByQuery) ); - }, [filtersValue, paginationQuery, sortByQuery, fetchTagTypes]); + }, [filtersValue, paginationQuery, sortByQuery]); + + const { + data: tagTypesPage, + isFetching: isFetchingTagTypes, + fetchError: fetchErrorTagTypes, + requestFetch: refreshTable, + } = useFetch({ + defaultIsFetching: true, + onFetch: fetchTagTypes, + }); + + const tagTypes = useMemo(() => { + return tagTypesPage ? tagTypePageMapper(tagTypesPage) : undefined; + }, [tagTypesPage]); useEffect(() => { - fetchTagTypes( - { - tagTypes: filtersValue.get(FilterKey.TAG_TYPE), - tags: filtersValue.get(FilterKey.TAG), - }, - paginationQuery, - toSortByQuery(sortByQuery) - ); - }, [filtersValue, paginationQuery, sortByQuery, fetchTagTypes]); + refreshTable(); + }, [filtersValue, paginationQuery, sortByQuery, refreshTable]); + + const { + isItemSelected: isItemExpanded, + toggleItemSelected: toggleItemExpanded, + } = useSelectionState({ + items: tagTypes?.data || [], + isEqual: (a, b) => a.id === b.id, + }); // @@ -411,7 +415,7 @@ export const Tags: React.FC = () => { return ( <> } > { cells={columns} rows={rows} // actions={actions} - isLoading={isFetching} + isLoading={isFetchingTagTypes} loadingVariant="skeleton" - fetchError={fetchError} + fetchError={fetchErrorTagTypes} toolbarClearAllFilters={handleOnClearAllFilters} filtersApplied={ Array.from(filtersValue.values()).reduce( diff --git a/src/shared/containers/select-business-service-filter/select-business-service-filter.tsx b/src/shared/containers/select-business-service-filter/select-business-service-filter.tsx index 3a1d8526..949cbf4c 100644 --- a/src/shared/containers/select-business-service-filter/select-business-service-filter.tsx +++ b/src/shared/containers/select-business-service-filter/select-business-service-filter.tsx @@ -1,12 +1,16 @@ -import React, { useEffect } from "react"; +import React, { useEffect, useMemo } from "react"; import { useTranslation } from "react-i18next"; import { SelectVariant, ToolbarChip } from "@patternfly/react-core"; import { SimpleSelectFetch, OptionWithValue } from "shared/components"; -import { useFetchBusinessServices } from "shared/hooks"; +import { useFetch } from "shared/hooks"; -import { BusinessService } from "api/models"; +import { BusinessService, BusinessServicePage } from "api/models"; +import { + bussinessServicePageMapper, + getAllBusinessServices, +} from "api/apiUtils"; import { DEFAULT_SELECT_MAX_HEIGHT } from "Constants"; const businessServiceToToolbarChip = (value: BusinessService): ToolbarChip => ({ @@ -46,11 +50,20 @@ export const SelectBusinessServiceFilter: React.FC = const { t } = useTranslation(); const { - businessServices, + data: businessServicesPage, isFetching: isFetchingBusinessServices, fetchError: fetchErrorBusinessServices, - fetchAllBusinessServices, - } = useFetchBusinessServices(); + requestFetch: fetchAllBusinessServices, + } = useFetch({ + defaultIsFetching: true, + onFetch: getAllBusinessServices, + }); + + const businessServices = useMemo(() => { + return businessServicesPage + ? bussinessServicePageMapper(businessServicesPage) + : undefined; + }, [businessServicesPage]); useEffect(() => { fetchAllBusinessServices(); diff --git a/src/shared/containers/select-tag-filter/select-tag-filter.tsx b/src/shared/containers/select-tag-filter/select-tag-filter.tsx index 6a483de5..fa129bb4 100644 --- a/src/shared/containers/select-tag-filter/select-tag-filter.tsx +++ b/src/shared/containers/select-tag-filter/select-tag-filter.tsx @@ -1,15 +1,20 @@ -import React, { useEffect, useState } from "react"; +import React, { useEffect, useMemo, useState } from "react"; import { useTranslation } from "react-i18next"; import { SelectVariant, ToolbarChip } from "@patternfly/react-core"; import { SimpleSelectFetch, OptionWithValue } from "shared/components"; -import { useFetchTagTypes } from "shared/hooks"; +import { useFetch } from "shared/hooks"; -import { Tag } from "api/models"; import { DEFAULT_SELECT_MAX_HEIGHT } from "Constants"; +import { Tag, TagTypePage } from "api/models"; +import { getAllTagTypes, tagTypePageMapper } from "api/apiUtils"; import { TagTypeSortBy } from "api/rest"; +export const getAllTagTypesSortedByRank = () => { + return getAllTagTypes({ field: TagTypeSortBy.RANK }); +}; + const tagToToolbarChip = (value: Tag): ToolbarChip => ({ key: `${value.id}`, node: value.name, @@ -50,14 +55,21 @@ export const SelectTagFilter: React.FC = ({ // Tag types const { - tagTypes, + data: tagTypesPage, isFetching: isFetchingTagTypes, fetchError: fetchErrorTagTypes, - fetchAllTagTypes, - } = useFetchTagTypes(); + requestFetch: fetchAllTagTypes, + } = useFetch({ + defaultIsFetching: true, + onFetch: getAllTagTypesSortedByRank, + }); + + const tagTypes = useMemo(() => { + return tagTypesPage ? tagTypePageMapper(tagTypesPage) : undefined; + }, [tagTypesPage]); useEffect(() => { - fetchAllTagTypes({ field: TagTypeSortBy.RANK }); + fetchAllTagTypes(); }, [fetchAllTagTypes]); // Tags diff --git a/src/shared/hooks/index.ts b/src/shared/hooks/index.ts index 0b8f16ab..00aea39c 100644 --- a/src/shared/hooks/index.ts +++ b/src/shared/hooks/index.ts @@ -6,17 +6,10 @@ export { useDeleteBusinessService } from "./useDeleteBusinessService"; export { useDeleteJobFunction } from "./useDeleteJobFunction"; export { useDeleteStakeholder } from "./useDeleteStakeholder"; export { useDeleteStakeholderGroup } from "./useDeleteStakeholderGroup"; -export { useFetchApplicationDependencies } from "./useFetchApplicationDependencies"; export { useDeleteTag } from "./useDeleteTag"; export { useDeleteTagType } from "./useDeleteTagType"; export { useEntityModal } from "./useEntityModal"; export { useFetch } from "./useFetch"; -export { useFetchApplications } from "./useFetchApplications"; -export { useFetchBusinessServices } from "./useFetchBusinessServices"; -export { useFetchJobFunctions } from "./useFetchJobFunctions"; -export { useFetchStakeholderGroups } from "./useFetchStakeholderGroups"; -export { useFetchStakeholders } from "./useFetchStakeholders"; -export { useFetchTagTypes } from "./useFetchTagTypes"; export { useMultipleFetch } from "./useMultipleFetch"; export { useQueryString } from "./useRouteAsState"; export { useToolbarFilter } from "./useToolbarFilter"; diff --git a/src/shared/hooks/useFetchApplicationDependencies/index.ts b/src/shared/hooks/useFetchApplicationDependencies/index.ts deleted file mode 100644 index a47b2956..00000000 --- a/src/shared/hooks/useFetchApplicationDependencies/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { useFetchApplicationDependencies } from "./useFetchApplicationDependencies"; diff --git a/src/shared/hooks/useFetchApplicationDependencies/useFetchApplicationDependencies.test.tsx b/src/shared/hooks/useFetchApplicationDependencies/useFetchApplicationDependencies.test.tsx deleted file mode 100644 index b0f81682..00000000 --- a/src/shared/hooks/useFetchApplicationDependencies/useFetchApplicationDependencies.test.tsx +++ /dev/null @@ -1,51 +0,0 @@ -import axios from "axios"; -import MockAdapter from "axios-mock-adapter"; -import { renderHook, act } from "@testing-library/react-hooks"; -import { useFetchApplicationDependencies } from "./useFetchApplicationDependencies"; -import { ApplicationDependencyPage } from "api/models"; -import { APPLICATION_DEPENDENCY } from "api/rest"; - -describe("useFetchApplicationDependencies", () => { - it("Fetch all", async () => { - // Mock REST API - const data: ApplicationDependencyPage = { - _embedded: { - "applications-dependency": [], - }, - total_count: 0, - }; - - new MockAdapter(axios) - .onGet(`${APPLICATION_DEPENDENCY}?page=0&size=1000&from.id=1`) - .reply(200, data); - - // Use hook - const { result, waitForNextUpdate } = renderHook(() => - useFetchApplicationDependencies() - ); - - const { - applicationDependencies: items, - isFetching, - fetchError, - fetchAllApplicationDependencies: fetchAll, - } = result.current; - - expect(isFetching).toBe(false); - expect(items).toBeUndefined(); - expect(fetchError).toBeUndefined(); - - // Init fetch - act(() => fetchAll({ from: ["1"] })); - expect(result.current.isFetching).toBe(true); - - // Fetch finished - await waitForNextUpdate(); - expect(result.current.isFetching).toBe(false); - expect(result.current.applicationDependencies).toMatchObject({ - data: [], - meta: { count: 0 }, - }); - expect(result.current.fetchError).toBeUndefined(); - }); -}); diff --git a/src/shared/hooks/useFetchApplicationDependencies/useFetchApplicationDependencies.ts b/src/shared/hooks/useFetchApplicationDependencies/useFetchApplicationDependencies.ts deleted file mode 100644 index 8149d5a5..00000000 --- a/src/shared/hooks/useFetchApplicationDependencies/useFetchApplicationDependencies.ts +++ /dev/null @@ -1,120 +0,0 @@ -import { useCallback, useReducer } from "react"; -import { AxiosError } from "axios"; -import { ActionType, createAsyncAction, getType } from "typesafe-actions"; - -import { getApplicationDependencies } from "api/rest"; -import { PageRepresentation, ApplicationDependency } from "api/models"; - -export const { - request: fetchRequest, - success: fetchSuccess, - failure: fetchFailure, -} = createAsyncAction( - "useFetchApplicationDependencies/fetch/request", - "useFetchApplicationDependencies/fetch/success", - "useFetchApplicationDependencies/fetch/failure" -), AxiosError>(); - -type State = Readonly<{ - isFetching: boolean; - applicationDependencies?: PageRepresentation; - fetchError?: AxiosError; - fetchCount: number; -}>; - -const defaultState: State = { - isFetching: false, - applicationDependencies: undefined, - fetchError: undefined, - fetchCount: 0, -}; - -type Action = ActionType< - typeof fetchRequest | typeof fetchSuccess | typeof fetchFailure ->; - -const initReducer = (isFetching: boolean): State => { - return { - ...defaultState, - isFetching, - }; -}; - -const reducer = (state: State, action: Action): State => { - switch (action.type) { - case getType(fetchRequest): - return { - ...state, - isFetching: true, - }; - case getType(fetchSuccess): - return { - ...state, - isFetching: false, - fetchError: undefined, - applicationDependencies: action.payload, - fetchCount: state.fetchCount + 1, - }; - case getType(fetchFailure): - return { - ...state, - isFetching: false, - fetchError: action.payload, - fetchCount: state.fetchCount + 1, - }; - default: - return state; - } -}; - -export interface IState { - applicationDependencies?: PageRepresentation; - isFetching: boolean; - fetchError?: AxiosError; - fetchCount: number; - fetchAllApplicationDependencies: (filters: { - from?: string[]; - to?: string[]; - }) => void; -} - -export const useFetchApplicationDependencies = ( - defaultIsFetching: boolean = false -): IState => { - const [state, dispatch] = useReducer(reducer, defaultIsFetching, initReducer); - - const fetchAllApplicationDependencies = useCallback( - (filters: { from?: string[]; to?: string[] }) => { - dispatch(fetchRequest()); - - getApplicationDependencies(filters, { page: 1, perPage: 1000 }) - .then(({ data }) => { - const list = data._embedded["applications-dependency"]; - const total = data.total_count; - - dispatch( - fetchSuccess({ - data: list, - meta: { - count: total, - }, - }) - ); - }) - .catch((error: AxiosError) => { - dispatch(fetchFailure(error)); - }); - }, - [] - ); - - return { - applicationDependencies: state.applicationDependencies, - isFetching: state.isFetching, - fetchError: state.fetchError, - fetchCount: state.fetchCount, - fetchAllApplicationDependencies, - }; -}; - -export default useFetchApplicationDependencies; diff --git a/src/shared/hooks/useFetchApplications/index.ts b/src/shared/hooks/useFetchApplications/index.ts deleted file mode 100644 index 8ecdca30..00000000 --- a/src/shared/hooks/useFetchApplications/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { useFetchApplications } from "./useFetchApplications"; diff --git a/src/shared/hooks/useFetchApplications/useFetchApplications.test.tsx b/src/shared/hooks/useFetchApplications/useFetchApplications.test.tsx deleted file mode 100644 index 5bb5da04..00000000 --- a/src/shared/hooks/useFetchApplications/useFetchApplications.test.tsx +++ /dev/null @@ -1,125 +0,0 @@ -import axios from "axios"; -import MockAdapter from "axios-mock-adapter"; -import { renderHook, act } from "@testing-library/react-hooks"; -import { useFetchApplications } from "./useFetchApplications"; -import { ApplicationPage } from "api/models"; -import { APPLICATIONS } from "api/rest"; - -describe("useFetchApplications", () => { - it("Fetch error due to no REST API found", async () => { - // Mock REST API - new MockAdapter(axios).onGet(APPLICATIONS).networkError(); - - // Use hook - const { result, waitForNextUpdate } = renderHook(() => - useFetchApplications() - ); - - const { - applications: items, - isFetching, - fetchError, - fetchApplications: fetchPage, - } = result.current; - - expect(isFetching).toBe(false); - expect(items).toBeUndefined(); - expect(fetchError).toBeUndefined(); - - // Init fetch - act(() => fetchPage({}, { page: 2, perPage: 50 })); - expect(result.current.isFetching).toBe(true); - - // Fetch finished - await waitForNextUpdate(); - expect(result.current.isFetching).toBe(false); - expect(result.current.applications).toBeUndefined(); - expect(result.current.fetchError).not.toBeUndefined(); - }); - - it("Fetch success", async () => { - // Mock REST API - const data: ApplicationPage = { - _embedded: { - application: [], - }, - total_count: 0, - }; - - new MockAdapter(axios) - .onGet(`${APPLICATIONS}?page=0&size=10`) - .reply(200, data); - - // Use hook - const { result, waitForNextUpdate } = renderHook(() => - useFetchApplications() - ); - - const { - applications: items, - isFetching, - fetchError, - fetchApplications: fetchPage, - } = result.current; - - expect(isFetching).toBe(false); - expect(items).toBeUndefined(); - expect(fetchError).toBeUndefined(); - - // Init fetch - act(() => fetchPage({}, { page: 1, perPage: 10 })); - expect(result.current.isFetching).toBe(true); - - // Fetch finished - await waitForNextUpdate(); - expect(result.current.isFetching).toBe(false); - expect(result.current.applications).toMatchObject({ - data: [], - meta: { count: 0 }, - }); - expect(result.current.fetchError).toBeUndefined(); - }); - - it("Fetch all", async () => { - // Mock REST API - const data: ApplicationPage = { - _embedded: { - application: [], - }, - total_count: 0, - }; - - new MockAdapter(axios) - .onGet(`${APPLICATIONS}?page=0&size=1000&sort=name`) - .reply(200, data); - - // Use hook - const { result, waitForNextUpdate } = renderHook(() => - useFetchApplications() - ); - - const { - applications: items, - isFetching, - fetchError, - fetchAllApplications: fetchAll, - } = result.current; - - expect(isFetching).toBe(false); - expect(items).toBeUndefined(); - expect(fetchError).toBeUndefined(); - - // Init fetch - act(() => fetchAll()); - expect(result.current.isFetching).toBe(true); - - // Fetch finished - await waitForNextUpdate(); - expect(result.current.isFetching).toBe(false); - expect(result.current.applications).toMatchObject({ - data: [], - meta: { count: 0 }, - }); - expect(result.current.fetchError).toBeUndefined(); - }); -}); diff --git a/src/shared/hooks/useFetchApplications/useFetchApplications.ts b/src/shared/hooks/useFetchApplications/useFetchApplications.ts deleted file mode 100644 index 2f02a53d..00000000 --- a/src/shared/hooks/useFetchApplications/useFetchApplications.ts +++ /dev/null @@ -1,167 +0,0 @@ -import { useCallback, useReducer } from "react"; -import { AxiosError } from "axios"; -import { ActionType, createAsyncAction, getType } from "typesafe-actions"; - -import { - getApplications, - ApplicationSortByQuery, - ApplicationSortBy, -} from "api/rest"; -import { PageRepresentation, Application, PageQuery } from "api/models"; - -export const { - request: fetchRequest, - success: fetchSuccess, - failure: fetchFailure, -} = createAsyncAction( - "useFetchApplications/fetch/request", - "useFetchApplications/fetch/success", - "useFetchApplications/fetch/failure" -), AxiosError>(); - -type State = Readonly<{ - isFetching: boolean; - applications?: PageRepresentation; - fetchError?: AxiosError; - fetchCount: number; -}>; - -const defaultState: State = { - isFetching: false, - applications: undefined, - fetchError: undefined, - fetchCount: 0, -}; - -type Action = ActionType< - typeof fetchRequest | typeof fetchSuccess | typeof fetchFailure ->; - -const initReducer = (isFetching: boolean): State => { - return { - ...defaultState, - isFetching, - }; -}; - -const reducer = (state: State, action: Action): State => { - switch (action.type) { - case getType(fetchRequest): - return { - ...state, - isFetching: true, - }; - case getType(fetchSuccess): - return { - ...state, - isFetching: false, - fetchError: undefined, - applications: action.payload, - fetchCount: state.fetchCount + 1, - }; - case getType(fetchFailure): - return { - ...state, - isFetching: false, - fetchError: action.payload, - fetchCount: state.fetchCount + 1, - }; - default: - return state; - } -}; - -export interface IState { - applications?: PageRepresentation; - isFetching: boolean; - fetchError?: AxiosError; - fetchCount: number; - fetchApplications: ( - filters: { - name?: string[]; - description?: string[]; - businessService?: string[]; - tag?: string[]; - }, - page: PageQuery, - sortBy?: ApplicationSortByQuery - ) => void; - fetchAllApplications: () => void; -} - -export const useFetchApplications = ( - defaultIsFetching: boolean = false -): IState => { - const [state, dispatch] = useReducer(reducer, defaultIsFetching, initReducer); - - const fetchApplications = useCallback( - ( - filters: { - name?: string[]; - description?: string[]; - businessService?: string[]; - tag?: string[]; - }, - page: PageQuery, - sortBy?: ApplicationSortByQuery - ) => { - dispatch(fetchRequest()); - - getApplications(filters, page, sortBy) - .then(({ data }) => { - const list = data._embedded.application; - const total = data.total_count; - - dispatch( - fetchSuccess({ - data: list, - meta: { - count: total, - }, - }) - ); - }) - .catch((error: AxiosError) => { - dispatch(fetchFailure(error)); - }); - }, - [] - ); - - const fetchAllApplications = useCallback(() => { - dispatch(fetchRequest()); - - getApplications( - {}, - { page: 1, perPage: 1000 }, - { field: ApplicationSortBy.NAME } - ) - .then(({ data }) => { - const list = data._embedded.application; - const total = data.total_count; - - dispatch( - fetchSuccess({ - data: list, - meta: { - count: total, - }, - }) - ); - }) - .catch((error: AxiosError) => { - dispatch(fetchFailure(error)); - }); - }, []); - - return { - applications: state.applications, - isFetching: state.isFetching, - fetchError: state.fetchError, - fetchCount: state.fetchCount, - fetchApplications, - fetchAllApplications, - }; -}; - -export default useFetchApplications; diff --git a/src/shared/hooks/useFetchBusinessServices/index.ts b/src/shared/hooks/useFetchBusinessServices/index.ts deleted file mode 100644 index e066df53..00000000 --- a/src/shared/hooks/useFetchBusinessServices/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { useFetchBusinessServices } from "./useFetchBusinessServices"; diff --git a/src/shared/hooks/useFetchBusinessServices/useFetchBusinessServices.test.tsx b/src/shared/hooks/useFetchBusinessServices/useFetchBusinessServices.test.tsx deleted file mode 100644 index d6d6265d..00000000 --- a/src/shared/hooks/useFetchBusinessServices/useFetchBusinessServices.test.tsx +++ /dev/null @@ -1,127 +0,0 @@ -import axios from "axios"; -import MockAdapter from "axios-mock-adapter"; -import { renderHook, act } from "@testing-library/react-hooks"; -import { useFetchBusinessServices } from "./useFetchBusinessServices"; -import { BusinessServicePage } from "api/models"; -import { BUSINESS_SERVICES } from "api/rest"; - -describe("useFetchBusinessServices", () => { - it("Fetch error due to no REST API found", async () => { - // Mock REST API - new MockAdapter(axios).onGet(BUSINESS_SERVICES).networkError(); - - // Use hook - const { result, waitForNextUpdate } = renderHook(() => - useFetchBusinessServices() - ); - - const { - businessServices, - isFetching, - fetchError, - fetchBusinessServices, - } = result.current; - - expect(isFetching).toBe(false); - expect(businessServices).toBeUndefined(); - expect(fetchError).toBeUndefined(); - - // Init fetch - act(() => fetchBusinessServices({}, { page: 2, perPage: 50 })); - expect(result.current.isFetching).toBe(true); - - // Fetch finished - await waitForNextUpdate(); - expect(result.current.isFetching).toBe(false); - expect(result.current.businessServices).toBeUndefined(); - expect(result.current.fetchError).not.toBeUndefined(); - }); - - it("Fetch success", async () => { - // Mock REST API - const data: BusinessServicePage = { - _embedded: { - "business-service": [], - }, - total_count: 0, - }; - - new MockAdapter(axios) - .onGet(`${BUSINESS_SERVICES}?page=0&size=10&name=something`) - .reply(200, data); - - // Use hook - const { result, waitForNextUpdate } = renderHook(() => - useFetchBusinessServices() - ); - - const { - businessServices, - isFetching, - fetchError, - fetchBusinessServices, - } = result.current; - - expect(isFetching).toBe(false); - expect(businessServices).toBeUndefined(); - expect(fetchError).toBeUndefined(); - - // Init fetch - act(() => - fetchBusinessServices({ name: ["something"] }, { page: 1, perPage: 10 }) - ); - expect(result.current.isFetching).toBe(true); - - // Fetch finished - await waitForNextUpdate(); - expect(result.current.isFetching).toBe(false); - expect(result.current.businessServices).toMatchObject({ - data: [], - meta: { count: 0 }, - }); - expect(result.current.fetchError).toBeUndefined(); - }); - - it("Fetch all", async () => { - // Mock REST API - const data: BusinessServicePage = { - _embedded: { - "business-service": [], - }, - total_count: 0, - }; - - new MockAdapter(axios) - .onGet(`${BUSINESS_SERVICES}?page=0&size=1000&sort=name`) - .reply(200, data); - - // Use hook - const { result, waitForNextUpdate } = renderHook(() => - useFetchBusinessServices() - ); - - const { - businessServices: items, - isFetching, - fetchError, - fetchAllBusinessServices: fetchAll, - } = result.current; - - expect(isFetching).toBe(false); - expect(items).toBeUndefined(); - expect(fetchError).toBeUndefined(); - - // Init fetch - act(() => fetchAll()); - expect(result.current.isFetching).toBe(true); - - // Fetch finished - await waitForNextUpdate(); - expect(result.current.isFetching).toBe(false); - expect(result.current.businessServices).toMatchObject({ - data: [], - meta: { count: 0 }, - }); - expect(result.current.fetchError).toBeUndefined(); - }); -}); diff --git a/src/shared/hooks/useFetchBusinessServices/useFetchBusinessServices.ts b/src/shared/hooks/useFetchBusinessServices/useFetchBusinessServices.ts deleted file mode 100644 index 1c401f4b..00000000 --- a/src/shared/hooks/useFetchBusinessServices/useFetchBusinessServices.ts +++ /dev/null @@ -1,161 +0,0 @@ -import { useCallback, useReducer } from "react"; -import { AxiosError } from "axios"; -import { ActionType, createAsyncAction, getType } from "typesafe-actions"; - -import { - getBusinessServices, - BusinessServiceSortByQuery, - BusinessServiceSortBy, -} from "api/rest"; -import { PageRepresentation, BusinessService, PageQuery } from "api/models"; - -export const { - request: fetchRequest, - success: fetchSuccess, - failure: fetchFailure, -} = createAsyncAction( - "useFetchBusinessServices/fetch/request", - "useFetchBusinessServices/fetch/success", - "useFetchBusinessServices/fetch/failure" -), AxiosError>(); - -type State = Readonly<{ - isFetching: boolean; - businessServices?: PageRepresentation; - fetchError?: AxiosError; - fetchCount: number; -}>; - -const defaultState: State = { - isFetching: false, - businessServices: undefined, - fetchError: undefined, - fetchCount: 0, -}; - -type Action = ActionType< - typeof fetchRequest | typeof fetchSuccess | typeof fetchFailure ->; - -const initReducer = (isFetching: boolean): State => { - return { - ...defaultState, - isFetching, - }; -}; - -const reducer = (state: State, action: Action): State => { - switch (action.type) { - case getType(fetchRequest): - return { - ...state, - isFetching: true, - }; - case getType(fetchSuccess): - return { - ...state, - isFetching: false, - fetchError: undefined, - businessServices: action.payload, - fetchCount: state.fetchCount + 1, - }; - case getType(fetchFailure): - return { - ...state, - isFetching: false, - fetchError: action.payload, - fetchCount: state.fetchCount + 1, - }; - default: - return state; - } -}; - -export interface IState { - businessServices?: PageRepresentation; - isFetching: boolean; - fetchError?: AxiosError; - fetchCount: number; - fetchBusinessServices: ( - filters: { - name?: string[]; - description?: string[]; - owner?: string[]; - }, - page: PageQuery, - sortBy?: BusinessServiceSortByQuery - ) => void; - fetchAllBusinessServices: () => void; -} - -export const useFetchBusinessServices = ( - defaultIsFetching: boolean = false -): IState => { - const [state, dispatch] = useReducer(reducer, defaultIsFetching, initReducer); - - const fetchBusinessServices = useCallback( - ( - filters: { name?: string[]; description?: string[]; owner?: string[] }, - page: PageQuery, - sortBy?: BusinessServiceSortByQuery - ) => { - dispatch(fetchRequest()); - - getBusinessServices(filters, page, sortBy) - .then(({ data }) => { - const list = data._embedded["business-service"]; - const total = data.total_count; - - dispatch( - fetchSuccess({ - data: list, - meta: { - count: total, - }, - }) - ); - }) - .catch((error: AxiosError) => { - dispatch(fetchFailure(error)); - }); - }, - [] - ); - - const fetchAllBusinessServices = useCallback(() => { - dispatch(fetchRequest()); - - getBusinessServices( - {}, - { page: 1, perPage: 1000 }, - { field: BusinessServiceSortBy.NAME } - ) - .then(({ data }) => { - const list = data._embedded["business-service"]; - const total = data.total_count; - - dispatch( - fetchSuccess({ - data: list, - meta: { - count: total, - }, - }) - ); - }) - .catch((error: AxiosError) => { - dispatch(fetchFailure(error)); - }); - }, []); - - return { - businessServices: state.businessServices, - isFetching: state.isFetching, - fetchError: state.fetchError, - fetchCount: state.fetchCount, - fetchBusinessServices, - fetchAllBusinessServices, - }; -}; - -export default useFetchBusinessServices; diff --git a/src/shared/hooks/useFetchJobFunctions/index.ts b/src/shared/hooks/useFetchJobFunctions/index.ts deleted file mode 100644 index afb12de4..00000000 --- a/src/shared/hooks/useFetchJobFunctions/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { useFetchJobFunctions } from "./useFetchJobFunctions"; diff --git a/src/shared/hooks/useFetchJobFunctions/useFetchJobFunctions.test.tsx b/src/shared/hooks/useFetchJobFunctions/useFetchJobFunctions.test.tsx deleted file mode 100644 index 1ae2ab80..00000000 --- a/src/shared/hooks/useFetchJobFunctions/useFetchJobFunctions.test.tsx +++ /dev/null @@ -1,51 +0,0 @@ -import axios from "axios"; -import MockAdapter from "axios-mock-adapter"; -import { renderHook, act } from "@testing-library/react-hooks"; -import { useFetchJobFunctions } from "./useFetchJobFunctions"; -import { JobFunctionPage } from "api/models"; -import { JOB_FUNCTIONS } from "api/rest"; - -describe("useFetchJobFunctions", () => { - it("Fetch all", async () => { - // Mock REST API - const data: JobFunctionPage = { - _embedded: { - "job-function": [], - }, - total_count: 0, - }; - - new MockAdapter(axios) - .onGet(`${JOB_FUNCTIONS}?page=0&size=1000&sort=role`) - .reply(200, data); - - // Use hook - const { result, waitForNextUpdate } = renderHook(() => - useFetchJobFunctions() - ); - - const { - jobFunctions: items, - isFetching, - fetchError, - fetchAllJobFunctions: fetchAll, - } = result.current; - - expect(isFetching).toBe(false); - expect(items).toBeUndefined(); - expect(fetchError).toBeUndefined(); - - // Init fetch - act(() => fetchAll()); - expect(result.current.isFetching).toBe(true); - - // Fetch finished - await waitForNextUpdate(); - expect(result.current.isFetching).toBe(false); - expect(result.current.jobFunctions).toMatchObject({ - data: [], - meta: { count: 0 }, - }); - expect(result.current.fetchError).toBeUndefined(); - }); -}); diff --git a/src/shared/hooks/useFetchJobFunctions/useFetchJobFunctions.ts b/src/shared/hooks/useFetchJobFunctions/useFetchJobFunctions.ts deleted file mode 100644 index 9e5436ff..00000000 --- a/src/shared/hooks/useFetchJobFunctions/useFetchJobFunctions.ts +++ /dev/null @@ -1,159 +0,0 @@ -import { useCallback, useReducer } from "react"; -import { AxiosError } from "axios"; -import { ActionType, createAsyncAction, getType } from "typesafe-actions"; - -import { - getJobFunctions, - JobFunctionSortBy, - JobFunctionSortByQuery, -} from "api/rest"; -import { PageRepresentation, JobFunction, PageQuery } from "api/models"; - -export const { - request: fetchRequest, - success: fetchSuccess, - failure: fetchFailure, -} = createAsyncAction( - "useFetchJobFunctions/fetch/request", - "useFetchJobFunctions/fetch/success", - "useFetchJobFunctions/fetch/failure" -), AxiosError>(); - -type State = Readonly<{ - isFetching: boolean; - jobFunctions?: PageRepresentation; - fetchError?: AxiosError; - fetchCount: number; -}>; - -const defaultState: State = { - isFetching: false, - jobFunctions: undefined, - fetchError: undefined, - fetchCount: 0, -}; - -type Action = ActionType< - typeof fetchRequest | typeof fetchSuccess | typeof fetchFailure ->; - -const initReducer = (isFetching: boolean): State => { - return { - ...defaultState, - isFetching, - }; -}; - -const reducer = (state: State, action: Action): State => { - switch (action.type) { - case getType(fetchRequest): - return { - ...state, - isFetching: true, - }; - case getType(fetchSuccess): - return { - ...state, - isFetching: false, - fetchError: undefined, - jobFunctions: action.payload, - fetchCount: state.fetchCount + 1, - }; - case getType(fetchFailure): - return { - ...state, - isFetching: false, - fetchError: action.payload, - fetchCount: state.fetchCount + 1, - }; - default: - return state; - } -}; - -export interface IState { - jobFunctions?: PageRepresentation; - isFetching: boolean; - fetchError?: AxiosError; - fetchCount: number; - fetchJobFunctions: ( - filters: { - role?: string[]; - }, - page: PageQuery, - sortBy?: JobFunctionSortByQuery - ) => void; - fetchAllJobFunctions: () => void; -} - -export const useFetchJobFunctions = ( - defaultIsFetching: boolean = false -): IState => { - const [state, dispatch] = useReducer(reducer, defaultIsFetching, initReducer); - - const fetchJobFunctions = useCallback( - ( - filters: { role?: string[] }, - page: PageQuery, - sortBy?: JobFunctionSortByQuery - ) => { - dispatch(fetchRequest()); - - getJobFunctions(filters, page, sortBy) - .then(({ data }) => { - const list = data._embedded["job-function"]; - const total = data.total_count; - - dispatch( - fetchSuccess({ - data: list, - meta: { - count: total, - }, - }) - ); - }) - .catch((error: AxiosError) => { - dispatch(fetchFailure(error)); - }); - }, - [] - ); - - const fetchAllJobFunctions = useCallback(() => { - dispatch(fetchRequest()); - - getJobFunctions( - {}, - { page: 1, perPage: 1000 }, - { field: JobFunctionSortBy.ROLE } - ) - .then(({ data }) => { - const list = data._embedded["job-function"]; - const total = data.total_count; - - dispatch( - fetchSuccess({ - data: list, - meta: { - count: total, - }, - }) - ); - }) - .catch((error: AxiosError) => { - dispatch(fetchFailure(error)); - }); - }, []); - - return { - jobFunctions: state.jobFunctions, - isFetching: state.isFetching, - fetchError: state.fetchError, - fetchCount: state.fetchCount, - fetchJobFunctions, - fetchAllJobFunctions, - }; -}; - -export default useFetchJobFunctions; diff --git a/src/shared/hooks/useFetchStakeholderGroups/index.ts b/src/shared/hooks/useFetchStakeholderGroups/index.ts deleted file mode 100644 index 91061bf6..00000000 --- a/src/shared/hooks/useFetchStakeholderGroups/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { useFetchStakeholderGroups } from "./useFetchStakeholderGroups"; diff --git a/src/shared/hooks/useFetchStakeholderGroups/useFetchStakeholderGroups.test.tsx b/src/shared/hooks/useFetchStakeholderGroups/useFetchStakeholderGroups.test.tsx deleted file mode 100644 index ab3a4c1d..00000000 --- a/src/shared/hooks/useFetchStakeholderGroups/useFetchStakeholderGroups.test.tsx +++ /dev/null @@ -1,125 +0,0 @@ -import axios from "axios"; -import MockAdapter from "axios-mock-adapter"; -import { renderHook, act } from "@testing-library/react-hooks"; -import { useFetchStakeholderGroups } from "./useFetchStakeholderGroups"; -import { StakeholderGroupPage } from "api/models"; -import { STAKEHOLDER_GROUPS } from "api/rest"; - -describe("useFetchStakeholderGroups", () => { - it("Fetch error due to no REST API found", async () => { - // Mock REST API - new MockAdapter(axios).onGet(STAKEHOLDER_GROUPS).networkError(); - - // Use hook - const { result, waitForNextUpdate } = renderHook(() => - useFetchStakeholderGroups() - ); - - const { - stakeholderGroups: stakeholders, - isFetching, - fetchError, - fetchStakeholderGroups, - } = result.current; - - expect(isFetching).toBe(false); - expect(stakeholders).toBeUndefined(); - expect(fetchError).toBeUndefined(); - - // Init fetch - act(() => fetchStakeholderGroups({}, { page: 2, perPage: 50 })); - expect(result.current.isFetching).toBe(true); - - // Fetch finished - await waitForNextUpdate(); - expect(result.current.isFetching).toBe(false); - expect(result.current.stakeholderGroups).toBeUndefined(); - expect(result.current.fetchError).not.toBeUndefined(); - }); - - it("Fetch success", async () => { - // Mock REST API - const data: StakeholderGroupPage = { - _embedded: { - "stakeholder-group": [], - }, - total_count: 0, - }; - - new MockAdapter(axios) - .onGet(`${STAKEHOLDER_GROUPS}?page=0&size=10`) - .reply(200, data); - - // Use hook - const { result, waitForNextUpdate } = renderHook(() => - useFetchStakeholderGroups() - ); - - const { - stakeholderGroups: stakeholders, - isFetching, - fetchError, - fetchStakeholderGroups: fetchStakeholders, - } = result.current; - - expect(isFetching).toBe(false); - expect(stakeholders).toBeUndefined(); - expect(fetchError).toBeUndefined(); - - // Init fetch - act(() => fetchStakeholders({}, { page: 1, perPage: 10 })); - expect(result.current.isFetching).toBe(true); - - // Fetch finished - await waitForNextUpdate(); - expect(result.current.isFetching).toBe(false); - expect(result.current.stakeholderGroups).toMatchObject({ - data: [], - meta: { count: 0 }, - }); - expect(result.current.fetchError).toBeUndefined(); - }); - - it("Fetch all", async () => { - // Mock REST API - const data: StakeholderGroupPage = { - _embedded: { - "stakeholder-group": [], - }, - total_count: 0, - }; - - new MockAdapter(axios) - .onGet(`${STAKEHOLDER_GROUPS}?page=0&size=1000&sort=name`) - .reply(200, data); - - // Use hook - const { result, waitForNextUpdate } = renderHook(() => - useFetchStakeholderGroups() - ); - - const { - stakeholderGroups, - isFetching, - fetchError, - fetchAllStakeholderGroups, - } = result.current; - - expect(isFetching).toBe(false); - expect(stakeholderGroups).toBeUndefined(); - expect(fetchError).toBeUndefined(); - - // Init fetch - act(() => fetchAllStakeholderGroups()); - expect(result.current.isFetching).toBe(true); - - // Fetch finished - await waitForNextUpdate(); - expect(result.current.isFetching).toBe(false); - expect(result.current.stakeholderGroups).toMatchObject({ - data: [], - meta: { count: 0 }, - }); - expect(result.current.fetchError).toBeUndefined(); - }); -}); diff --git a/src/shared/hooks/useFetchStakeholderGroups/useFetchStakeholderGroups.ts b/src/shared/hooks/useFetchStakeholderGroups/useFetchStakeholderGroups.ts deleted file mode 100644 index 312c4925..00000000 --- a/src/shared/hooks/useFetchStakeholderGroups/useFetchStakeholderGroups.ts +++ /dev/null @@ -1,165 +0,0 @@ -import { useCallback, useReducer } from "react"; -import { AxiosError } from "axios"; -import { ActionType, createAsyncAction, getType } from "typesafe-actions"; - -import { - getStakeholderGroups, - StakeholderGroupSortBy, - StakeholderGroupSortByQuery, -} from "api/rest"; -import { PageRepresentation, StakeholderGroup, PageQuery } from "api/models"; - -export const { - request: fetchRequest, - success: fetchSuccess, - failure: fetchFailure, -} = createAsyncAction( - "useFetchStakeholderGroups/fetch/request", - "useFetchStakeholderGroups/fetch/success", - "useFetchStakeholderGroups/fetch/failure" -), AxiosError>(); - -type State = Readonly<{ - isFetching: boolean; - stakeholderGroups?: PageRepresentation; - fetchError?: AxiosError; - fetchCount: number; -}>; - -const defaultState: State = { - isFetching: false, - stakeholderGroups: undefined, - fetchError: undefined, - fetchCount: 0, -}; - -type Action = ActionType< - typeof fetchRequest | typeof fetchSuccess | typeof fetchFailure ->; - -const initReducer = (isFetching: boolean): State => { - return { - ...defaultState, - isFetching, - }; -}; - -const reducer = (state: State, action: Action): State => { - switch (action.type) { - case getType(fetchRequest): - return { - ...state, - isFetching: true, - }; - case getType(fetchSuccess): - return { - ...state, - isFetching: false, - fetchError: undefined, - stakeholderGroups: action.payload, - fetchCount: state.fetchCount + 1, - }; - case getType(fetchFailure): - return { - ...state, - isFetching: false, - fetchError: action.payload, - fetchCount: state.fetchCount + 1, - }; - default: - return state; - } -}; - -export interface IState { - stakeholderGroups?: PageRepresentation; - isFetching: boolean; - fetchError?: AxiosError; - fetchCount: number; - fetchStakeholderGroups: ( - filters: { - name?: string[]; - description?: string[]; - stakeholder?: string[]; - }, - page: PageQuery, - sortBy?: StakeholderGroupSortByQuery - ) => void; - fetchAllStakeholderGroups: () => void; -} - -export const useFetchStakeholderGroups = ( - defaultIsFetching: boolean = false -): IState => { - const [state, dispatch] = useReducer(reducer, defaultIsFetching, initReducer); - - const fetchStakeholderGroups = useCallback( - ( - filters: { - name?: string[]; - description?: string[]; - stakeholder?: string[]; - }, - page: PageQuery, - sortBy?: StakeholderGroupSortByQuery - ) => { - dispatch(fetchRequest()); - - getStakeholderGroups(filters, page, sortBy) - .then(({ data }) => { - const list = data._embedded["stakeholder-group"]; - const total = data.total_count; - - dispatch( - fetchSuccess({ - data: list, - meta: { - count: total, - }, - }) - ); - }) - .catch((error: AxiosError) => { - dispatch(fetchFailure(error)); - }); - }, - [] - ); - - const fetchAllStakeholderGroups = useCallback(() => { - dispatch(fetchRequest()); - - getStakeholderGroups( - {}, - { page: 1, perPage: 1000 }, - { field: StakeholderGroupSortBy.NAME } - ) - .then(({ data }) => { - const list = data._embedded["stakeholder-group"]; - const total = data.total_count; - - dispatch( - fetchSuccess({ - data: list, - meta: { - count: total, - }, - }) - ); - }) - .catch((error: AxiosError) => { - dispatch(fetchFailure(error)); - }); - }, []); - - return { - stakeholderGroups: state.stakeholderGroups, - isFetching: state.isFetching, - fetchError: state.fetchError, - fetchCount: state.fetchCount, - fetchStakeholderGroups, - fetchAllStakeholderGroups, - }; -}; - -export default useFetchStakeholderGroups; diff --git a/src/shared/hooks/useFetchStakeholders/index.ts b/src/shared/hooks/useFetchStakeholders/index.ts deleted file mode 100644 index 6908b875..00000000 --- a/src/shared/hooks/useFetchStakeholders/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { useFetchStakeholders } from "./useFetchStakeholders"; diff --git a/src/shared/hooks/useFetchStakeholders/useFetchStakeholders.test.tsx b/src/shared/hooks/useFetchStakeholders/useFetchStakeholders.test.tsx deleted file mode 100644 index bac3bb88..00000000 --- a/src/shared/hooks/useFetchStakeholders/useFetchStakeholders.test.tsx +++ /dev/null @@ -1,125 +0,0 @@ -import axios from "axios"; -import MockAdapter from "axios-mock-adapter"; -import { renderHook, act } from "@testing-library/react-hooks"; -import { useFetchStakeholders } from "./useFetchStakeholders"; -import { StakeholderPage } from "api/models"; -import { STAKEHOLDERS } from "api/rest"; - -describe("useFetchStakeholders", () => { - it("Fetch error due to no REST API found", async () => { - // Mock REST API - new MockAdapter(axios).onGet(STAKEHOLDERS).networkError(); - - // Use hook - const { result, waitForNextUpdate } = renderHook(() => - useFetchStakeholders() - ); - - const { - stakeholders, - isFetching, - fetchError, - fetchStakeholders, - } = result.current; - - expect(isFetching).toBe(false); - expect(stakeholders).toBeUndefined(); - expect(fetchError).toBeUndefined(); - - // Init fetch - act(() => fetchStakeholders({}, { page: 2, perPage: 50 })); - expect(result.current.isFetching).toBe(true); - - // Fetch finished - await waitForNextUpdate(); - expect(result.current.isFetching).toBe(false); - expect(result.current.stakeholders).toBeUndefined(); - expect(result.current.fetchError).not.toBeUndefined(); - }); - - it("Fetch success", async () => { - // Mock REST API - const data: StakeholderPage = { - _embedded: { - stakeholder: [], - }, - total_count: 0, - }; - - new MockAdapter(axios) - .onGet(`${STAKEHOLDERS}?page=0&size=10`) - .reply(200, data); - - // Use hook - const { result, waitForNextUpdate } = renderHook(() => - useFetchStakeholders() - ); - - const { - stakeholders, - isFetching, - fetchError, - fetchStakeholders, - } = result.current; - - expect(isFetching).toBe(false); - expect(stakeholders).toBeUndefined(); - expect(fetchError).toBeUndefined(); - - // Init fetch - act(() => fetchStakeholders({}, { page: 1, perPage: 10 })); - expect(result.current.isFetching).toBe(true); - - // Fetch finished - await waitForNextUpdate(); - expect(result.current.isFetching).toBe(false); - expect(result.current.stakeholders).toMatchObject({ - data: [], - meta: { count: 0 }, - }); - expect(result.current.fetchError).toBeUndefined(); - }); - - it("Fetch all", async () => { - // Mock REST API - const data: StakeholderPage = { - _embedded: { - stakeholder: [], - }, - total_count: 0, - }; - - new MockAdapter(axios) - .onGet(`${STAKEHOLDERS}?page=0&size=1000&sort=displayName`) - .reply(200, data); - - // Use hook - const { result, waitForNextUpdate } = renderHook(() => - useFetchStakeholders() - ); - - const { - stakeholders, - isFetching, - fetchError, - fetchAllStakeholders, - } = result.current; - - expect(isFetching).toBe(false); - expect(stakeholders).toBeUndefined(); - expect(fetchError).toBeUndefined(); - - // Init fetch - act(() => fetchAllStakeholders()); - expect(result.current.isFetching).toBe(true); - - // Fetch finished - await waitForNextUpdate(); - expect(result.current.isFetching).toBe(false); - expect(result.current.stakeholders).toMatchObject({ - data: [], - meta: { count: 0 }, - }); - expect(result.current.fetchError).toBeUndefined(); - }); -}); diff --git a/src/shared/hooks/useFetchStakeholders/useFetchStakeholders.ts b/src/shared/hooks/useFetchStakeholders/useFetchStakeholders.ts deleted file mode 100644 index d4057a75..00000000 --- a/src/shared/hooks/useFetchStakeholders/useFetchStakeholders.ts +++ /dev/null @@ -1,167 +0,0 @@ -import { useCallback, useReducer } from "react"; -import { AxiosError } from "axios"; -import { ActionType, createAsyncAction, getType } from "typesafe-actions"; - -import { - getStakeholders, - StakeholderSortBy, - StakeholderSortByQuery, -} from "api/rest"; -import { PageRepresentation, Stakeholder, PageQuery } from "api/models"; - -export const { - request: fetchRequest, - success: fetchSuccess, - failure: fetchFailure, -} = createAsyncAction( - "useFetchStakeholders/fetch/request", - "useFetchStakeholders/fetch/success", - "useFetchStakeholders/fetch/failure" -), AxiosError>(); - -type State = Readonly<{ - isFetching: boolean; - stakeholders?: PageRepresentation; - fetchError?: AxiosError; - fetchCount: number; -}>; - -const defaultState: State = { - isFetching: false, - stakeholders: undefined, - fetchError: undefined, - fetchCount: 0, -}; - -type Action = ActionType< - typeof fetchRequest | typeof fetchSuccess | typeof fetchFailure ->; - -const initReducer = (isFetching: boolean): State => { - return { - ...defaultState, - isFetching, - }; -}; - -const reducer = (state: State, action: Action): State => { - switch (action.type) { - case getType(fetchRequest): - return { - ...state, - isFetching: true, - }; - case getType(fetchSuccess): - return { - ...state, - isFetching: false, - fetchError: undefined, - stakeholders: action.payload, - fetchCount: state.fetchCount + 1, - }; - case getType(fetchFailure): - return { - ...state, - isFetching: false, - fetchError: action.payload, - fetchCount: state.fetchCount + 1, - }; - default: - return state; - } -}; - -export interface IState { - stakeholders?: PageRepresentation; - isFetching: boolean; - fetchError?: AxiosError; - fetchCount: number; - fetchStakeholders: ( - filters: { - email?: string[]; - displayName?: string[]; - jobFunction?: string[]; - stakeholderGroup?: string[]; - }, - page: PageQuery, - sortBy?: StakeholderSortByQuery - ) => void; - fetchAllStakeholders: () => void; -} - -export const useFetchStakeholders = ( - defaultIsFetching: boolean = false -): IState => { - const [state, dispatch] = useReducer(reducer, defaultIsFetching, initReducer); - - const fetchStakeholders = useCallback( - ( - filters: { - email?: string[]; - displayName?: string[]; - jobFunction?: string[]; - stakeholderGroups?: string[]; - }, - page: PageQuery, - sortBy?: StakeholderSortByQuery - ) => { - dispatch(fetchRequest()); - - getStakeholders(filters, page, sortBy) - .then(({ data }) => { - const list = data._embedded.stakeholder; - const total = data.total_count; - - dispatch( - fetchSuccess({ - data: list, - meta: { - count: total, - }, - }) - ); - }) - .catch((error: AxiosError) => { - dispatch(fetchFailure(error)); - }); - }, - [] - ); - - const fetchAllStakeholders = useCallback(() => { - dispatch(fetchRequest()); - - getStakeholders( - {}, - { page: 1, perPage: 1000 }, - { field: StakeholderSortBy.DISPLAY_NAME } - ) - .then(({ data }) => { - const list = data._embedded.stakeholder; - const total = data.total_count; - - dispatch( - fetchSuccess({ - data: list, - meta: { - count: total, - }, - }) - ); - }) - .catch((error: AxiosError) => { - dispatch(fetchFailure(error)); - }); - }, []); - - return { - stakeholders: state.stakeholders, - isFetching: state.isFetching, - fetchError: state.fetchError, - fetchCount: state.fetchCount, - fetchStakeholders, - fetchAllStakeholders, - }; -}; - -export default useFetchStakeholders; diff --git a/src/shared/hooks/useFetchTagTypes/index.ts b/src/shared/hooks/useFetchTagTypes/index.ts deleted file mode 100644 index 489ee3f9..00000000 --- a/src/shared/hooks/useFetchTagTypes/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { useFetchTagTypes } from "./useFetchTagTypes"; diff --git a/src/shared/hooks/useFetchTagTypes/useFetchTagTypes.test.tsx b/src/shared/hooks/useFetchTagTypes/useFetchTagTypes.test.tsx deleted file mode 100644 index 5de10bae..00000000 --- a/src/shared/hooks/useFetchTagTypes/useFetchTagTypes.test.tsx +++ /dev/null @@ -1,119 +0,0 @@ -import axios from "axios"; -import MockAdapter from "axios-mock-adapter"; -import { renderHook, act } from "@testing-library/react-hooks"; -import { useFetchTagTypes } from "./useFetchTagTypes"; -import { TagTypePage } from "api/models"; -import { TAG_TYPES } from "api/rest"; - -describe("useFetchTagTypes", () => { - it("Fetch error due to no REST API found", async () => { - // Mock REST API - new MockAdapter(axios).onGet(TAG_TYPES).networkError(); - - // Use hook - const { result, waitForNextUpdate } = renderHook(() => useFetchTagTypes()); - - const { - tagTypes: items, - isFetching, - fetchError, - fetchTagTypes: fetchEntities, - } = result.current; - - expect(isFetching).toBe(false); - expect(items).toBeUndefined(); - expect(fetchError).toBeUndefined(); - - // Init fetch - act(() => fetchEntities({}, { page: 2, perPage: 50 })); - expect(result.current.isFetching).toBe(true); - - // Fetch finished - await waitForNextUpdate(); - expect(result.current.isFetching).toBe(false); - expect(result.current.tagTypes).toBeUndefined(); - expect(result.current.fetchError).not.toBeUndefined(); - }); - - it("Fetch success", async () => { - // Mock REST API - const data: TagTypePage = { - _embedded: { - "tag-type": [], - }, - total_count: 0, - }; - - new MockAdapter(axios) - .onGet(`${TAG_TYPES}?page=0&size=10`) - .reply(200, data); - - // Use hook - const { result, waitForNextUpdate } = renderHook(() => useFetchTagTypes()); - - const { - tagTypes: stakeholders, - isFetching, - fetchError, - fetchTagTypes: fetchStakeholders, - } = result.current; - - expect(isFetching).toBe(false); - expect(stakeholders).toBeUndefined(); - expect(fetchError).toBeUndefined(); - - // Init fetch - act(() => fetchStakeholders({}, { page: 1, perPage: 10 })); - expect(result.current.isFetching).toBe(true); - - // Fetch finished - await waitForNextUpdate(); - expect(result.current.isFetching).toBe(false); - expect(result.current.tagTypes).toMatchObject({ - data: [], - meta: { count: 0 }, - }); - expect(result.current.fetchError).toBeUndefined(); - }); - - it("Fetch all", async () => { - // Mock REST API - const data: TagTypePage = { - _embedded: { - "tag-type": [], - }, - total_count: 0, - }; - - new MockAdapter(axios) - .onGet(`${TAG_TYPES}?page=0&size=1000&sort=name`) - .reply(200, data); - - // Use hook - const { result, waitForNextUpdate } = renderHook(() => useFetchTagTypes()); - - const { - tagTypes: items, - isFetching, - fetchError, - fetchAllTagTypes: fetchAll, - } = result.current; - - expect(isFetching).toBe(false); - expect(items).toBeUndefined(); - expect(fetchError).toBeUndefined(); - - // Init fetch - act(() => fetchAll()); - expect(result.current.isFetching).toBe(true); - - // Fetch finished - await waitForNextUpdate(); - expect(result.current.isFetching).toBe(false); - expect(result.current.tagTypes).toMatchObject({ - data: [], - meta: { count: 0 }, - }); - expect(result.current.fetchError).toBeUndefined(); - }); -}); diff --git a/src/shared/hooks/useFetchTagTypes/useFetchTagTypes.ts b/src/shared/hooks/useFetchTagTypes/useFetchTagTypes.ts deleted file mode 100644 index 714a4d4e..00000000 --- a/src/shared/hooks/useFetchTagTypes/useFetchTagTypes.ts +++ /dev/null @@ -1,159 +0,0 @@ -import { useCallback, useReducer } from "react"; -import { AxiosError } from "axios"; -import { ActionType, createAsyncAction, getType } from "typesafe-actions"; - -import { getTagTypes, TagTypeSortBy, TagTypeSortByQuery } from "api/rest"; -import { PageRepresentation, PageQuery, TagType } from "api/models"; - -export const { - request: fetchRequest, - success: fetchSuccess, - failure: fetchFailure, -} = createAsyncAction( - "useFetchTagTypes/fetch/request", - "useFetchTagTypes/fetch/success", - "useFetchTagTypes/fetch/failure" -), AxiosError>(); - -type State = Readonly<{ - isFetching: boolean; - tagTypes?: PageRepresentation; - fetchError?: AxiosError; - fetchCount: number; -}>; - -const defaultState: State = { - isFetching: false, - tagTypes: undefined, - fetchError: undefined, - fetchCount: 0, -}; - -type Action = ActionType< - typeof fetchRequest | typeof fetchSuccess | typeof fetchFailure ->; - -const initReducer = (isFetching: boolean): State => { - return { - ...defaultState, - isFetching, - }; -}; - -const reducer = (state: State, action: Action): State => { - switch (action.type) { - case getType(fetchRequest): - return { - ...state, - isFetching: true, - }; - case getType(fetchSuccess): - return { - ...state, - isFetching: false, - fetchError: undefined, - tagTypes: action.payload, - fetchCount: state.fetchCount + 1, - }; - case getType(fetchFailure): - return { - ...state, - isFetching: false, - fetchError: action.payload, - fetchCount: state.fetchCount + 1, - }; - default: - return state; - } -}; - -export interface IState { - tagTypes?: PageRepresentation; - isFetching: boolean; - fetchError?: AxiosError; - fetchCount: number; - fetchTagTypes: ( - filters: { - tagTypes?: string[]; - tags?: string[]; - }, - page: PageQuery, - sortBy?: TagTypeSortByQuery - ) => void; - fetchAllTagTypes: (sortBy?: TagTypeSortByQuery) => void; -} - -export const useFetchTagTypes = ( - defaultIsFetching: boolean = false -): IState => { - const [state, dispatch] = useReducer(reducer, defaultIsFetching, initReducer); - - const fetchTagTypes = useCallback( - ( - filters: { - name?: string[]; - tagTypes?: string[]; - }, - page: PageQuery, - sortBy?: TagTypeSortByQuery - ) => { - dispatch(fetchRequest()); - - getTagTypes(filters, page, sortBy) - .then(({ data }) => { - const list = data._embedded["tag-type"]; - const total = data.total_count; - - dispatch( - fetchSuccess({ - data: list, - meta: { - count: total, - }, - }) - ); - }) - .catch((error: AxiosError) => { - dispatch(fetchFailure(error)); - }); - }, - [] - ); - - const fetchAllTagTypes = useCallback((sortBy?: TagTypeSortByQuery) => { - dispatch(fetchRequest()); - - getTagTypes( - {}, - { page: 1, perPage: 1000 }, - sortBy || { field: TagTypeSortBy.NAME } - ) - .then(({ data }) => { - const list = data._embedded["tag-type"]; - const total = data.total_count; - - dispatch( - fetchSuccess({ - data: list, - meta: { - count: total, - }, - }) - ); - }) - .catch((error: AxiosError) => { - dispatch(fetchFailure(error)); - }); - }, []); - - return { - tagTypes: state.tagTypes, - isFetching: state.isFetching, - fetchError: state.fetchError, - fetchCount: state.fetchCount, - fetchTagTypes, - fetchAllTagTypes, - }; -}; - -export default useFetchTagTypes;