Skip to content

Commit

Permalink
Merge branch 'main' into mta-1895
Browse files Browse the repository at this point in the history
  • Loading branch information
ibolton336 authored Dec 15, 2023
2 parents f36b2ef + 8637733 commit a391625
Show file tree
Hide file tree
Showing 13 changed files with 128 additions and 84 deletions.
13 changes: 6 additions & 7 deletions .github/workflows/ci-actions.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,25 @@ on:
push:
branches:
- main
- "v[0-9]+.[0-9]+.[0-9]+"
- "release-*"
pull_request:
branches:
- main
- "v[0-9]+.[0-9]+.[0-9]+"
- "release-*"

jobs:
unit-test:
runs-on: ubuntu-latest
strategy:
matrix:
# Note: This should match the node version(s) used in the base Dockerfile
node-version: [18.x]

steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4

- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}

Expand All @@ -43,21 +42,21 @@ jobs:
run: npm run test -- --coverage --watchAll=false

- name: Upload to codecov (client)
uses: codecov/codecov-action@v1
uses: codecov/codecov-action@v3
with:
flags: client
directory: ./*/coverage

- name: Upload to codecov (server)
uses: codecov/codecov-action@v1
uses: codecov/codecov-action@v3
with:
flags: server
directory: ./*/coverage

build-and-upload-for-global-ci:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4

- name: save tackle2-ui image
run: |
Expand Down
6 changes: 6 additions & 0 deletions client/src/app/Constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ export const isRWXSupported = ENV.RWX_SUPPORTED === "true";

export const DEFAULT_SELECT_MAX_HEIGHT = 200;

/**
* The name of the client generated id field inserted in a object marked with mixin type
* `WithUiId`.
*/
export const UI_UNIQUE_ID = "_ui_unique_id";

// Colors

// t('colors.red')
Expand Down
8 changes: 7 additions & 1 deletion client/src/app/api/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -578,8 +578,14 @@ export interface BaseAnalysisIssueReport extends AnalysisIssuesCommonFields {
files: number;
}

// After fetching from the hub, we inject a unique id composed of ruleset+rule for convenience
/**
* Mark an object as having a unique client generated id field. Use this type if
* an objects from hub does not have a single field with a unique key AND the object
* is to be used in a table. Our table handlers assume a single field with a unique
* value across all objects in a set to properly handle row selections.
*/
export type WithUiId<T> = T & { _ui_unique_id: string };

export type AnalysisRuleReport = WithUiId<BaseAnalysisRuleReport>;
export type AnalysisIssueReport = WithUiId<BaseAnalysisIssueReport>;

Expand Down
4 changes: 3 additions & 1 deletion client/src/app/hooks/table-controls/DOCS.md
Original file line number Diff line number Diff line change
Expand Up @@ -514,7 +514,9 @@ Table columns are identified by unique keys which are statically inferred from t

#### Item IDs

Item objects must contain some unique identifier which is either a string or number. The property key of this identifier is a required config argument called `idProperty`, which will usually be `"id"`. If no unique identifier is present in the API data, an artificial one can be injected before passing the data into these hooks, which can be done in the useQuery `select` callback (see instances where we have used `"_ui_unique_id"`). Any state which keeps track of something by item (i.e. by row) makes use of `item[idProperty]` as an identifier. Examples of this include selected rows, expanded rows and active rows. Valid `idProperty` values are also enforced by TypeScript generics; if an `idProperty` is provided that is not a property on the `TItem` type, you should get a type error.
Item objects must contain some unique identifier which is either a string or number. The property key of this identifier is a required config argument called `idProperty`, which will usually be `"id"`. If no unique identifier is present in the API data, an artificial one can be injected before passing the data into these hooks. This can be done in the useQuery `select` callback (see instances where we have used `"_ui_unique_id"`). Another option is to use the query hook `useWithUiId()` on the react-query fetched data. Since `select` modified data is not part of the query cache, it does not matter if transforms are done in react-query, `useWithUiId` hook, or other means.

Any state which keeps track of something by item (i.e. by row) makes use of `item[idProperty]` as an identifier. Examples of this include selected rows, expanded rows and active rows. Valid `idProperty` values are also enforced by TypeScript generics. If an `idProperty` is provided that is not a property on the `TItem` type, you should get a type error.

> ⚠️ TECH DEBT NOTE: Things specific to `useQuery` and `_ui_unique_id` here are Konveyor-specific notes that should be removed after moving this to table-batteries.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import {
} from "@tanstack/react-query";
import { TrashIcon } from "@patternfly/react-icons";
import useIsArchetype from "@app/hooks/useIsArchetype";
import spacing from "@patternfly/react-styles/css/utilities/Spacing/spacing";

enum AssessmentAction {
Take = "Take",
Expand Down Expand Up @@ -189,6 +190,7 @@ const DynamicAssessmentActionsRow: FunctionComponent<
assessmentId: assessment.id,
applicationName: application?.name,
applicationId: application?.id,
archetypeName: archetype?.name,
archetypeId: archetype?.id,
}).then(() => {
createAssessment();
Expand Down Expand Up @@ -222,7 +224,7 @@ const DynamicAssessmentActionsRow: FunctionComponent<
{action}
</Button>
) : (
<Spinner role="status" size="md">
<Spinner role="status" size="md" className={spacing.mxLg}>
<span className="sr-only">Loading...</span>
</Spinner>
)}
Expand Down Expand Up @@ -262,6 +264,7 @@ const DynamicAssessmentActionsRow: FunctionComponent<
assessmentId: assessment.id,
applicationName: application?.name,
applicationId: application?.id,
archetypeName: archetype?.name,
archetypeId: archetype?.id,
});
}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,7 @@ export const AssessmentWizard: React.FC<AssessmentWizardProps> = ({
assessmentId: assessment.id,
applicationName: assessment.application?.name,
applicationId: assessment.application?.id,
archetypeName: assessment.archetype?.name,
archetypeId: assessment.archetype?.id,
});
} else {
Expand All @@ -455,6 +456,7 @@ export const AssessmentWizard: React.FC<AssessmentWizardProps> = ({
assessmentId: assessment.id,
applicationName: assessment.application?.name,
applicationId: assessment.application?.id,
archetypeName: assessment.archetype?.name,
archetypeId: assessment.archetype?.id,
});
}
Expand Down
4 changes: 2 additions & 2 deletions client/src/app/pages/dependencies/dependencies.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import {
useTableControlProps,
getHubRequestParams,
} from "@app/hooks/table-controls";
import { TablePersistenceKeyPrefix } from "@app/Constants";
import { TablePersistenceKeyPrefix, UI_UNIQUE_ID } from "@app/Constants";
import { SimplePagination } from "@app/components/SimplePagination";
import {
ConditionalTableBody,
Expand Down Expand Up @@ -97,7 +97,7 @@ export const Dependencies: React.FC = () => {

const tableControls = useTableControlProps({
...tableControlState, // Includes filterState, sortState and paginationState
idProperty: "_ui_unique_id",
idProperty: UI_UNIQUE_ID,
currentPageItems,
totalItemCount,
isLoading: isFetching,
Expand Down
4 changes: 2 additions & 2 deletions client/src/app/pages/issues/issues-table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import { useSelectionState } from "@migtools/lib-ui";

import { AppPlaceholder } from "@app/components/AppPlaceholder";
import { OptionWithValue, SimpleSelect } from "@app/components/SimpleSelect";
import { TablePersistenceKeyPrefix } from "@app/Constants";
import { TablePersistenceKeyPrefix, UI_UNIQUE_ID } from "@app/Constants";
import { useFetchIssueReports, useFetchRuleReports } from "@app/queries/issues";
import {
FilterType,
Expand Down Expand Up @@ -226,7 +226,7 @@ export const IssuesTable: React.FC<IIssuesTableProps> = ({ mode }) => {

const tableControls = useTableControlProps({
...tableControlState, // Includes filterState, sortState and paginationState
idProperty: "_ui_unique_id",
idProperty: UI_UNIQUE_ID,
currentPageItems: currentPageReports,
totalItemCount: totalReportCount,
isLoading,
Expand Down
8 changes: 8 additions & 0 deletions client/src/app/pages/reports/components/donut/donut.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
StackItem,
Text,
TextContent,
TextVariants,
} from "@patternfly/react-core";

export interface IDonutProps {
Expand All @@ -31,6 +32,7 @@ export const Donut: React.FC<IDonutProps> = ({
riskLabel,
isAssessment,
riskTitle,
riskDescription,
}) => {
const { t } = useTranslation();

Expand Down Expand Up @@ -63,6 +65,12 @@ export const Donut: React.FC<IDonutProps> = ({
<StackItem style={{ width: "100%" }}>
<TextContent className="pf-v5-u-text-align-center">
<Text component="h3">{riskLabel}</Text>
<Text
component={TextVariants.small}
className="pf-v5-u-color-200 pf-v5-u-font-weight-light"
>
{riskDescription}
</Text>
</TextContent>
</StackItem>
</Stack>
Expand Down
6 changes: 4 additions & 2 deletions client/src/app/queries/assessments.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ export const useUpdateAssessmentMutation = (
};

export const useDeleteAssessmentMutation = (
onSuccess?: (applicationName: string) => void,
onSuccess?: (name: string) => void,
onError?: (err: AxiosError) => void
) => {
const queryClient = useQueryClient();
Expand All @@ -117,6 +117,7 @@ export const useDeleteAssessmentMutation = (
assessmentId: number;
applicationName?: string;
applicationId?: number;
archetypeName?: string;
archetypeId?: number;
}) => {
const deletedAssessment = deleteAssessment(args.assessmentId);
Expand All @@ -138,7 +139,8 @@ export const useDeleteAssessmentMutation = (
return deletedAssessment;
},
onSuccess: (_, args) => {
onSuccess && onSuccess(args?.applicationName || "Unknown");
onSuccess &&
onSuccess(args?.applicationName || args?.archetypeName || "Unknown");
},
onError: onError,
});
Expand Down
60 changes: 18 additions & 42 deletions client/src/app/queries/dependencies.ts
Original file line number Diff line number Diff line change
@@ -1,70 +1,46 @@
import { useMemo } from "react";
import { useQuery } from "@tanstack/react-query";
import {
AnalysisAppDependency,
AnalysisDependency,
HubPaginatedResult,
HubRequestParams,
WithUiId,
} from "@app/api/models";
import { getAppDependencies, getDependencies } from "@app/api/rest";

export interface IDependenciesFetchState {
result: HubPaginatedResult<WithUiId<AnalysisDependency>>;
isFetching: boolean;
fetchError: unknown;
refetch: () => void;
}
export interface IAppDependenciesFetchState {
result: HubPaginatedResult<AnalysisAppDependency>;
isFetching: boolean;
fetchError: unknown;
refetch: () => void;
}
import { useWithUiId } from "@app/utils/query-utils";

export const DependenciesQueryKey = "dependencies";
export const AppDependenciesQueryKey = "appDependencies";

export const useFetchDependencies = (
params: HubRequestParams = {}
): IDependenciesFetchState => {
const { data, isLoading, error, refetch } = useQuery({
export const useFetchDependencies = (params: HubRequestParams = {}) => {
const {
data: dependencies,
isLoading,
error,
refetch,
} = useQuery({
queryKey: [DependenciesQueryKey, params],
queryFn: async () => await getDependencies(params),
onError: (error) => console.log("error, ", error),
keepPreviousData: true,
});

const result = useMemo(() => {
if (!data) {
return { data: [], total: 0, params };
}

const syntheticData: WithUiId<AnalysisDependency>[] = data.data.map(
(dep) => ({
...dep,
_ui_unique_id: `${dep.name}/${dep.provider}`,
})
);

return {
data: syntheticData,
total: data.total,
params: data.params,
};
}, [data, params]);

const withUiId = useWithUiId(
dependencies?.data,
(d) => `${d.name}/${d.provider}`
);
return {
result,
result: {
data: withUiId,
total: dependencies?.total ?? 0,
params: dependencies?.params ?? params,
} as HubPaginatedResult<WithUiId<AnalysisDependency>>,
isFetching: isLoading,
fetchError: error,
refetch,
};
};

export const useFetchAppDependencies = (
params: HubRequestParams = {}
): IAppDependenciesFetchState => {
export const useFetchAppDependencies = (params: HubRequestParams = {}) => {
const { data, isLoading, error, refetch } = useQuery({
queryKey: [AppDependenciesQueryKey, params],
queryFn: async () => await getAppDependencies(params),
Expand Down
Loading

0 comments on commit a391625

Please sign in to comment.