Skip to content

Commit

Permalink
Merge branch 'main' into bs-table
Browse files Browse the repository at this point in the history
  • Loading branch information
mguetta1 authored Jun 19, 2024
2 parents 730f1e0 + 0cce0d8 commit a034768
Show file tree
Hide file tree
Showing 43 changed files with 933 additions and 490 deletions.
10 changes: 8 additions & 2 deletions CODEOWNERS
Original file line number Diff line number Diff line change
@@ -1,2 +1,8 @@
* @konveyor/migration-engineering-ui-committers
/pkg/qe-tests/ @konveyor/migration-engineering-qe-committers
#
# Until an organization group (for example `@konveyor/tackle/ui-reviewers`) is created
# and maintained to hold the set of people to auto-assign PRs for review, individually
# name each person.
#
# The list (or group membership) should match up with the `OWNERS.md` file.
#
* @ibolton336 @sjd78 @rszwajko
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ COPY --chown=1001 . .
RUN npm clean-install --ignore-scripts && npm run build && npm run dist

# Runner image
FROM registry.access.redhat.com/ubi9/nodejs-18-minimal:1-113.1716472876
FROM registry.access.redhat.com/ubi9/nodejs-18-minimal:1-117

# Add ps package to allow liveness probe for k8s cluster
# Add tar package to allow copying files with kubectl scp
Expand Down
2 changes: 1 addition & 1 deletion client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"build": "NODE_ENV=production webpack --config ./config/webpack.prod.ts",
"build:dev": "NODE_ENV=development webpack --config ./config/webpack.dev.ts",
"start:dev": "NODE_ENV=development webpack serve --config ./config/webpack.dev.ts",
"test": "NODE_ENV=test jest --rootDir=. --config=./config/jest.config.ts",
"test": "NODE_ENV=test TZ=UTC jest --rootDir=. --config=./config/jest.config.ts",
"lint": "eslint .",
"tsc": "tsc -p ./tsconfig.json"
},
Expand Down
4 changes: 2 additions & 2 deletions client/public/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@
"delete": "Delete",
"discardAssessment": "Discard assessment(s)",
"discardReview": "Discard review",

"downloadCsvTemplate": "Download CSV template",
"download": "Download {{what}}",
"duplicate": "Duplicate",
Expand Down Expand Up @@ -105,7 +104,6 @@
"dialog": {
"message": {
"applicationsBulkDelete": "The selected application(s) will be deleted.",

"delete": "This action cannot be undone.",
"discardAssessment": "The assessment(s) for <1>{{applicationName}}</1> will be discarded. Do you wish to continue?",
"discardReview": "The review for <1>{{applicationName}}</1> will be discarded. Do you wish to continue?",
Expand Down Expand Up @@ -332,6 +330,7 @@
"effort": "Effort",
"effortEstimate": "Effort estimate",
"email": "Email",
"endDate": "End date",
"error": "Error",
"errorReport": "Error report",
"explanation": "Explanation",
Expand Down Expand Up @@ -434,6 +433,7 @@
"stakeholderGroupDeleted": "Stakeholder group deleted",
"stakeholderGroups": "Stakeholder groups",
"stakeholders": "Stakeholders",
"startDate": "Start date",
"status": "Status",
"suggestedAdoptionPlan": "Suggested adoption plan",
"svnConfig": "Subversion configuration",
Expand Down
7 changes: 7 additions & 0 deletions client/src/app/Paths.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
export const DevPaths = {
// Developer perspective
applications: "/applications",
applicationsAnalysisDetails:
"/applications/:applicationId/analysis-details/:taskId",
applicationsAnalysisTab: "/applications/analysis-tab",
applicationsAssessmentTab: "/applications/assessment-tab",
applicationsImports: "/applications/application-imports",
Expand Down Expand Up @@ -86,3 +88,8 @@ export interface ReviewRoute {
export interface ImportSummaryRoute {
importId: string;
}

export interface AnalysisDetailsRoute {
applicationId: string;
taskId: string;
}
9 changes: 8 additions & 1 deletion client/src/app/Routes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ const ManageImports = lazy(() => import("./pages/applications/manage-imports"));
const ImportDetails = lazy(
() => import("./pages/applications/manage-imports-details")
);

const AnalysisDetails = lazy(
() => import("./pages/applications/analysis-details")
);
const Reports = lazy(() => import("./pages/reports"));
const Controls = lazy(() => import("./pages/controls"));
const Identities = lazy(() => import("./pages/identities"));
Expand Down Expand Up @@ -74,6 +76,11 @@ export const devRoutes: IRoute<DevPathValues>[] = [
comp: ImportDetails,
exact: false,
},
{
path: Paths.applicationsAnalysisDetails,
comp: AnalysisDetails,
exact: false,
},
{
path: Paths.applicationsImports,
comp: ManageImports,
Expand Down
69 changes: 50 additions & 19 deletions client/src/app/api/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -307,18 +307,62 @@ export type TaskState =

export interface Task {
id?: number;
createUser?: string;
updateUser?: string;
createTime?: string;
application: { id: number };

name: string;
kind: string;
addon: string;
extensions: string[];
state?: TaskState;
locator?: string;
priority?: number;
policy: TaskPolicy;
ttl: TTL;
data: TaskData;
error?: string;
image?: string;
application: Ref;
bucket?: Ref;
pod?: string;
retries?: number;
started?: string;
terminated?: string;
state?: TaskState;
job?: string;
report?: TaskReport;
events?: TaskEvent[];
errors?: TaskError[];
activity?: string[];
attached?: TaskAttachment[];
}

export interface TaskPolicy {
isolated?: boolean;
preemptEnabled?: boolean;
preemptExempt?: boolean;
}

export interface TTL {
created?: number;
pending?: number;
running?: number;
succeeded?: number;
failed?: number;
}

export interface TaskEvent {
kind: string;
count: number;
reason?: string;
last: string; // time
}

export interface TaskError {
severity: string;
description: string;
}

export interface TaskAttachment {
id: number;
name?: string;
activity?: number;
}

export interface TaskData {
Expand Down Expand Up @@ -355,19 +399,6 @@ export interface TaskData {
};
}

interface TaskReport {
activity: string[];
completed: number;
createTime: string;
createUser: string;
error: string;
id: number;
status: string;
task: number;
total: number;
updateUser: string;
}

export interface TaskgroupTask {
name: string;
data: any;
Expand Down
3 changes: 3 additions & 0 deletions client/src/app/api/rest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,9 @@ export function getTaskById(
export const getTasks = () =>
axios.get<Task[]>(TASKS).then((response) => response.data);

export const getServerTasks = (params: HubRequestParams = {}) =>
getHubPaginatedResult<Task>(TASKS, params);

export const deleteTask = (id: number) => axios.delete<Task>(`${TASKS}/${id}`);

export const cancelTask = (id: number) =>
Expand Down
7 changes: 6 additions & 1 deletion client/src/app/components/BreadCrumbPath.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Link } from "react-router-dom";
import { Breadcrumb, BreadcrumbItem, Button } from "@patternfly/react-core";

export interface BreadCrumbPathProps {
breadcrumbs: { title: string; path: string | (() => void) }[];
breadcrumbs: { title: string; path?: string | (() => void) }[];
}

export const BreadCrumbPath: React.FC<BreadCrumbPathProps> = ({
Expand All @@ -12,6 +12,11 @@ export const BreadCrumbPath: React.FC<BreadCrumbPathProps> = ({
return (
<Breadcrumb>
{breadcrumbs.map((crumb, i, { length }) => {
if (!crumb.path) {
// the item is not a link
return <BreadcrumbItem key={i}>{crumb.title}</BreadcrumbItem>;
}

const isLast = i === length - 1;

const link =
Expand Down
135 changes: 135 additions & 0 deletions client/src/app/components/FilterToolbar/DateRangeFilter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
import React, { FormEvent, useState } from "react";

import {
DatePicker,
InputGroup,
isValidDate as isValidJSDate,
ToolbarChip,
ToolbarChipGroup,
ToolbarFilter,
Tooltip,
} from "@patternfly/react-core";

import { IFilterControlProps } from "./FilterControl";
import {
localizeInterval,
americanDateFormat,
isValidAmericanShortDate,
isValidInterval,
parseAmericanDate,
parseInterval,
toISODateInterval,
} from "./dateUtils";

/**
* This Filter type enables selecting an closed date range.
* Precisely given range [A,B] a date X in the range if A <= X <= B.
*
* **Props are interpreted as follows**:<br>
* 1) filterValue - date range encoded as ISO 8601 time interval string ("dateFrom/dateTo"). Only date part is used (no time).<br>
* 2) setFilterValue - accepts the list of ranges.<br>
*
*/

export const DateRangeFilter = <TItem,>({
category,
filterValue,
setFilterValue,
showToolbarItem,
isDisabled = false,
}: React.PropsWithChildren<
IFilterControlProps<TItem, string>
>): JSX.Element | null => {
const selectedFilters = filterValue ?? [];

const validFilters =
selectedFilters?.filter((interval) =>
isValidInterval(parseInterval(interval))
) ?? [];
const [from, setFrom] = useState<Date>();
const [to, setTo] = useState<Date>();

const rangeToOption = (range: string) => {
const [abbrRange, fullRange] = localizeInterval(range);
return {
key: range,
node: (
<Tooltip content={fullRange ?? range}>
<span>{abbrRange ?? ""}</span>
</Tooltip>
),
};
};

const clearSingleRange = (
category: string | ToolbarChipGroup,
option: string | ToolbarChip
) => {
const target = (option as ToolbarChip)?.key;
setFilterValue([...validFilters.filter((range) => range !== target)]);
};

const onFromDateChange = (
event: FormEvent<HTMLInputElement>,
value: string
) => {
if (isValidAmericanShortDate(value)) {
setFrom(parseAmericanDate(value));
setTo(undefined);
}
};

const onToDateChange = (even: FormEvent<HTMLInputElement>, value: string) => {
if (isValidAmericanShortDate(value)) {
const newTo = parseAmericanDate(value);
setTo(newTo);
const target = toISODateInterval(from, newTo);
if (target) {
setFilterValue([
...validFilters.filter((range) => range !== target),
target,
]);
}
}
};

return (
<ToolbarFilter
key={category.categoryKey}
chips={validFilters.map(rangeToOption)}
deleteChip={clearSingleRange}
deleteChipGroup={() => setFilterValue([])}
categoryName={category.title}
showToolbarItem={showToolbarItem}
>
<InputGroup>
<DatePicker
value={from ? americanDateFormat(from) : ""}
dateFormat={americanDateFormat}
dateParse={parseAmericanDate}
onChange={onFromDateChange}
aria-label="Interval start"
placeholder="MM/DD/YYYY"
// disable error text (no space in toolbar scenario)
invalidFormatText={""}
// default value ("parent") creates collision with sticky table header
appendTo={document.body}
isDisabled={isDisabled}
/>
<DatePicker
value={to ? americanDateFormat(to) : ""}
onChange={onToDateChange}
isDisabled={isDisabled || !isValidJSDate(from)}
dateFormat={americanDateFormat}
dateParse={parseAmericanDate}
// disable error text (no space in toolbar scenario)
invalidFormatText={""}
rangeStart={from}
aria-label="Interval end"
placeholder="MM/DD/YYYY"
appendTo={document.body}
/>
</InputGroup>
</ToolbarFilter>
);
};
4 changes: 4 additions & 0 deletions client/src/app/components/FilterToolbar/FilterControl.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
import { SelectFilterControl } from "./SelectFilterControl";
import { SearchFilterControl } from "./SearchFilterControl";
import { MultiselectFilterControl } from "./MultiselectFilterControl";
import { DateRangeFilter } from "./DateRangeFilter";

export interface IFilterControlProps<TItem, TFilterCategoryKey extends string> {
category: FilterCategory<TItem, TFilterCategoryKey>;
Expand Down Expand Up @@ -58,5 +59,8 @@ export const FilterControl = <TItem, TFilterCategoryKey extends string>({
/>
);
}
if (category.type === FilterType.dateRange) {
return <DateRangeFilter category={category} {...props} />;
}
return null;
};
4 changes: 3 additions & 1 deletion client/src/app/components/FilterToolbar/FilterToolbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export enum FilterType {
multiselect = "multiselect",
search = "search",
numsearch = "numsearch",
dateRange = "dateRange",
}

export type FilterValue = string[] | undefined | null;
Expand Down Expand Up @@ -81,7 +82,8 @@ export interface ISearchFilterCategory<TItem, TFilterCategoryKey extends string>
export type FilterCategory<TItem, TFilterCategoryKey extends string> =
| IMultiselectFilterCategory<TItem, TFilterCategoryKey>
| ISelectFilterCategory<TItem, TFilterCategoryKey>
| ISearchFilterCategory<TItem, TFilterCategoryKey>;
| ISearchFilterCategory<TItem, TFilterCategoryKey>
| IBasicFilterCategory<TItem, TFilterCategoryKey>;

export type IFilterValues<TFilterCategoryKey extends string> = Partial<
Record<TFilterCategoryKey, FilterValue>
Expand Down
Loading

0 comments on commit a034768

Please sign in to comment.