Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🐛 Convert dependency code to use rq & fix cyclic dep alert #1419

Merged
merged 1 commit into from
Oct 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions client/src/app/api/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,8 +144,8 @@ export interface Review {

export interface ApplicationDependency {
id?: number;
from: Application;
to: Application;
from: Ref;
to: Ref;
}

export interface ApplicationAdoptionPlan {
Expand Down
54 changes: 23 additions & 31 deletions client/src/app/api/rest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,28 +117,6 @@ const yamlHeaders = { headers: { Accept: "application/x-yaml" } };

type Direction = "asc" | "desc";

const buildQuery = (params: any) => {
const query: string[] = [];

Object.keys(params).forEach((key) => {
const value = (params as any)[key];

if (value !== undefined && value !== null) {
let queryParamValues: string[] = [];
if (Array.isArray(value)) {
queryParamValues = value;
} else {
queryParamValues = [value];
}
queryParamValues.forEach((v) => query.push(`${key}=${v}`));
}
});

return query;
};

// App inventory

export const updateAllApplications = (
updatePromises: Promise<Application>[]
) => {
Expand All @@ -147,22 +125,36 @@ export const updateAllApplications = (
.catch((error) => error);
};

// Applications Dependencies
interface DependencyParams {
from?: string[];
to?: string[];
}

export const getApplicationDependencies = (): AxiosPromise<
ApplicationDependency[]
> => {
return APIClient.get(`${APPLICATION_DEPENDENCY}`, jsonHeaders);
export const getApplicationDependencies = (
params?: DependencyParams
): Promise<ApplicationDependency[]> => {
return axios
.get(`${APPLICATION_DEPENDENCY}`, {
params,
headers: jsonHeaders,
})
.then((response) => response.data);
};

export const createApplicationDependency = (
obj: ApplicationDependency
): AxiosPromise<ApplicationDependency> => {
return APIClient.post(`${APPLICATION_DEPENDENCY}`, obj);
): Promise<ApplicationDependency> => {
return axios
.post(`${APPLICATION_DEPENDENCY}`, obj)
.then((response) => response.data);
};

export const deleteApplicationDependency = (id: number): AxiosPromise => {
return APIClient.delete(`${APPLICATION_DEPENDENCY}/${id}`);
export const deleteApplicationDependency = (
id: number
): Promise<ApplicationDependency> => {
return axios
.delete(`${APPLICATION_DEPENDENCY}/${id}`)
.then((response) => response.data);
};

// Reviews
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useContext, useEffect, useState } from "react";
import React, { useEffect, useState } from "react";
import { useTranslation } from "react-i18next";

import {
Expand All @@ -19,11 +19,12 @@ import { OptionWithValue } from "@app/components/SimpleSelect";

import { Application, ApplicationDependency } from "@app/api/models";

import { FormContext } from "./FormContext";
import { SelectDependency } from "./SelectDependency";
import { getAxiosErrorMessage } from "@app/utils/utils";
import { useFetchApplications } from "@app/queries/applications";
import useFetchApplicationDependencies from "@app/hooks/useFetchApplicationDependencies/useFetchApplicationDependencies";
import {
useFetchApplicationDependencies,
useFetchApplications,
} from "@app/queries/applications";
import { toRef } from "@app/utils/model-utils";

const northToStringFn = (value: ApplicationDependency) => value.from.name;
const southToStringFn = (value: ApplicationDependency) => value.to.name;
Expand All @@ -44,90 +45,54 @@ export interface ApplicationDependenciesFormProps {
export const ApplicationDependenciesForm: React.FC<
ApplicationDependenciesFormProps
> = ({ application, onCancel }) => {
const {
isNorthBeingSaved,
isSouthBeingSaved,
northSaveError,
southSaveError,
setIsNorthBeingSaved,
setIsSouthBeingSaved,
setNorthSaveError,
setSouthSaveError,
} = useContext(FormContext);

const { t } = useTranslation();

const [northboundDependencies, setNorthboundDependencies] = useState<
OptionWithValue<ApplicationDependency>[]
>([]);
const [southboundDependencies, setSouthboundDependencies] = useState<
OptionWithValue<ApplicationDependency>[]
>([]);

// Dependencies

const {
applicationDependencies: northDependencies,
isFetching: isFetchingNorthDependencies,
fetchError: fetchErrorNorthDependencies,
fetchAllApplicationDependencies: fetchAllNorthDependencies,
} = useFetchApplicationDependencies();

const {
applicationDependencies: southDependencies,
isFetching: isFetchingSouthDependencies,
fetchError: fetchErrorSouthDependencies,
fetchAllApplicationDependencies: fetchAllSouthDependencies,
} = useFetchApplicationDependencies();

useEffect(() => {
fetchAllNorthDependencies({
to: [`${application.id}`],
});
}, [application, fetchAllNorthDependencies]);

useEffect(() => {
fetchAllSouthDependencies({
from: [`${application.id}`],
});
}, [application, fetchAllSouthDependencies]);

// Applications
northboundDependencies,
southboundDependencies,
isFetching,
fetchError,
refetch,
} = useFetchApplicationDependencies(application?.id);
const [southSaveError, setSouthSaveError] = useState<null | string>(null);
const [northSaveError, setNorthSaveError] = useState<null | string>(null);

const [northboundDependenciesOptions, setNorthboundDependenciesOptions] =
useState<OptionWithValue<ApplicationDependency>[]>([]);
const [southboundDependenciesOptions, setSouthboundDependenciesOptions] =
useState<OptionWithValue<ApplicationDependency>[]>([]);

const {
data: applications,
isFetching: isFetchingApplications,
error: fetchErrorApplications,
} = useFetchApplications();

// Initial value

useEffect(() => {
if (northDependencies) {
const north = northDependencies
if (northboundDependencies) {
const north = northboundDependencies
.filter((f) => f.to.id === application.id)
.map((f) => dependencyToOption(f, northToStringFn));
setNorthboundDependencies(north);
setNorthboundDependenciesOptions(north);
}
}, [application, northDependencies]);
}, [application, northboundDependencies]);

useEffect(() => {
if (southDependencies) {
const south = southDependencies
if (southboundDependencies) {
const south = southboundDependencies
.filter((f) => f.from.id === application.id)
.map((f) => dependencyToOption(f, southToStringFn));
setSouthboundDependencies(south);
setSouthboundDependenciesOptions(south);
}
}, [application, southDependencies]);
}, [application, southboundDependencies]);

const savingMsg = (
<div className="pf-v5-u-font-size-sm">
<Spinner size="sm" /> {`${t("message.savingSelection")}...`}
</div>
);
const existingDependencyMappings = southboundDependencies
const existingDependencyMappings = southboundDependenciesOptions
.map((sbd) => sbd.value.to.id)
.concat(northboundDependencies.map((nbd) => nbd.value.from.id));
.concat(northboundDependenciesOptions.map((nbd) => nbd.value.from.id));

return (
<Form>
Expand All @@ -148,8 +113,8 @@ export const ApplicationDependenciesForm: React.FC<
toggleId="northbound-dependencies-toggle"
fieldId="northbound-dependencies"
toStringFn={northToStringFn}
value={northboundDependencies}
setValue={setNorthboundDependencies}
value={northboundDependenciesOptions}
setValue={setNorthboundDependenciesOptions}
options={(applications || [])
.filter((f) => f.id !== application.id)
.filter((app) => {
Expand All @@ -158,24 +123,19 @@ export const ApplicationDependenciesForm: React.FC<
.map((f) =>
dependencyToOption({ from: f, to: application }, northToStringFn)
)}
isFetching={isFetchingApplications || isFetchingNorthDependencies}
fetchError={fetchErrorApplications || fetchErrorNorthDependencies}
isSaving={isNorthBeingSaved}
setIsSaving={setIsNorthBeingSaved}
saveError={northSaveError}
setSaveError={setNorthSaveError}
isFetching={isFetchingApplications || isFetching}
isSaving={isFetching}
setErrorMsg={setNorthSaveError}
/>
{northSaveError &&
isNorthBeingSaved === getAxiosErrorMessage(northSaveError) && (
<FormHelperText>
<HelperText>
<HelperTextItem>{savingMsg}</HelperTextItem>
</HelperText>
</FormHelperText>
)}
{northSaveError && (
<FormHelperText>
<HelperText>
<HelperTextItem>{northSaveError}</HelperTextItem>
</HelperText>
</FormHelperText>
)}
</FormGroup>
<FormGroup
// t("terms.southboundDependencies")
label={t("composed.add", {
what: t("terms.southboundDependencies").toLowerCase(),
})}
Expand All @@ -187,31 +147,39 @@ export const ApplicationDependenciesForm: React.FC<
fieldId="southbound-dependencies"
toggleId="southbound-dependencies-toggle"
toStringFn={southToStringFn}
value={southboundDependencies}
setValue={setSouthboundDependencies}
value={southboundDependenciesOptions}
setValue={setSouthboundDependenciesOptions}
options={(applications || [])
.filter((f) => f.id !== application.id)
.filter((app) => {
return !existingDependencyMappings?.includes(app.id);
.filter(
(app) =>
app.id !== application.id &&
!existingDependencyMappings?.includes(app.id)
)
.map((app) => {
const fromApplicationRef = toRef(application);
const toApplicationRef = toRef(app);

if (fromApplicationRef && toApplicationRef) {
return dependencyToOption(
{ from: fromApplicationRef, to: toApplicationRef },
southToStringFn
);
} else {
return null;
}
})
.map((f) =>
dependencyToOption({ from: application, to: f }, southToStringFn)
)}
isFetching={isFetchingApplications || isFetchingSouthDependencies}
fetchError={fetchErrorApplications || fetchErrorSouthDependencies}
isSaving={isSouthBeingSaved}
setIsSaving={setIsSouthBeingSaved}
saveError={southSaveError}
setSaveError={setSouthSaveError}
.filter(Boolean)}
isFetching={isFetchingApplications || isFetching}
isSaving={isFetching}
setErrorMsg={setSouthSaveError}
/>
{southSaveError &&
isSouthBeingSaved === getAxiosErrorMessage(southSaveError) && (
<FormHelperText>
<HelperText>
<HelperTextItem>{savingMsg}</HelperTextItem>
</HelperText>
</FormHelperText>
)}
{southSaveError && (
<FormHelperText>
<HelperText>
<HelperTextItem>{southSaveError}</HelperTextItem>
</HelperText>
</FormHelperText>
)}
</FormGroup>

<ActionGroup>
Expand All @@ -221,7 +189,7 @@ export const ApplicationDependenciesForm: React.FC<
aria-label="close"
variant={ButtonVariant.primary}
onClick={onCancel}
isDisabled={isNorthBeingSaved || isSouthBeingSaved}
isDisabled={isFetching}
>
{t("actions.close")}
</Button>
Expand Down
Loading