Skip to content

Commit

Permalink
Merge branch 'main' into mta-1130
Browse files Browse the repository at this point in the history
  • Loading branch information
ibolton336 authored Oct 3, 2023
2 parents 335a87e + 5c99540 commit 070f522
Show file tree
Hide file tree
Showing 14 changed files with 211 additions and 122 deletions.
1 change: 1 addition & 0 deletions client/public/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,7 @@
"label": "Label",
"loading": "Loading",
"lowRisk": "Low risk",
"manualTags": "Manual Tags",
"maintainers": "Maintainers",
"mavenConfig": "Maven configuration",
"mediumRisk": "Medium risk",
Expand Down
2 changes: 1 addition & 1 deletion client/src/app/api/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export interface BusinessService {
id: number;
name: string;
description?: string;
owner?: Stakeholder;
owner?: Ref;
}

export interface Stakeholder {
Expand Down
32 changes: 16 additions & 16 deletions client/src/app/api/rest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -610,27 +610,27 @@ export const updateStakeholderGroup = (
): Promise<StakeholderGroup> =>
axios.put(`${STAKEHOLDER_GROUPS}/${obj.id}`, obj);

// ---------------------------------------
// Business services
//
export const getBusinessServices = () =>
axios
.get<BusinessService[]>(BUSINESS_SERVICES)
.then((response) => response.data);

export const getBusinessServices = (): Promise<BusinessService[]> =>
axios.get(BUSINESS_SERVICES).then((response) => response.data);

export const deleteBusinessService = (
id: number | string
): Promise<BusinessService> => axios.delete(`${BUSINESS_SERVICES}/${id}`);
export const getBusinessServiceById = (id: number | string) =>
axios
.get<BusinessService>(`${BUSINESS_SERVICES}/${id}`)
.then((response) => response.data);

export const createBusinessService = (
obj: New<BusinessService>
): Promise<BusinessService> => axios.post(BUSINESS_SERVICES, obj);
export const createBusinessService = (obj: New<BusinessService>) =>
axios.post<BusinessService>(BUSINESS_SERVICES, obj);

export const updateBusinessService = (
obj: BusinessService
): Promise<BusinessService> => axios.put(`${BUSINESS_SERVICES}/${obj.id}`, obj);
export const updateBusinessService = (obj: BusinessService) =>
axios.put<void>(`${BUSINESS_SERVICES}/${obj.id}`, obj);

export const getBusinessServiceById = (
id: number | string
): Promise<BusinessService> =>
axios.get(`${BUSINESS_SERVICES}/${id}`).then((response) => response.data);
export const deleteBusinessService = (id: number | string) =>
axios.delete<void>(`${BUSINESS_SERVICES}/${id}`);

// Job functions

Expand Down
2 changes: 1 addition & 1 deletion client/src/app/components/KeycloakProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { deleteCookie, getCookie, setCookie } from "@app/queries/cookies";
import { AppPlaceholder } from "./AppPlaceholder";
import { Flex, FlexItem, Spinner } from "@patternfly/react-core";
import { ReactKeycloakProvider } from "@react-keycloak/web";
import React, { Suspense, useEffect } from "react";
import React, { Suspense } from "react";

interface IKeycloakProviderProps {
children: React.ReactNode;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { useState, useEffect } from "react";
import axios from "axios";
import DefaultImage from "@app/images/Icon-Red_Hat-Virtual_server_stack-A-Black-RGB.svg";
import { Target } from "@app/api/models";
import { FILES } from "@app/api/rest";

const useFetchImageDataUrl = (target: Target) => {
const [imageDataUrl, setImageDataUrl] = useState<string | null>(null);

useEffect(() => {
const imagePath = target?.image?.id
? `${FILES}/${target?.image.id}`
: DefaultImage;

(async () => {
try {
const response = await axios.get(imagePath, {
headers: {
Accept: "application/octet-stream",
},
responseType: "arraybuffer",
});
const contentType = response.headers["content-type"];

let imageData;

if (contentType === "image/svg+xml") {
const text = new TextDecoder().decode(response.data);
imageData = `data:${contentType},${encodeURIComponent(text)}`;
} else {
const base64 = btoa(
new Uint8Array(response.data).reduce(
(data, byte) => data + String.fromCharCode(byte),
""
)
);
imageData = `data:${contentType};base64,${base64}`;
}

setImageDataUrl(imageData);
} catch (error) {
console.error("There was an issue fetching the image:", error);
}
})();
}, [target]);

return imageDataUrl;
};

export default useFetchImageDataUrl;
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import "./target-card.css";
import * as React from "react";
import {
EmptyState,
Expand All @@ -24,14 +25,14 @@ import {
SelectVariant,
SelectOptionObject,
} from "@patternfly/react-core/deprecated";
import { CubesIcon, GripVerticalIcon } from "@patternfly/react-icons";
import { GripVerticalIcon } from "@patternfly/react-icons";
import spacing from "@patternfly/react-styles/css/utilities/Spacing/spacing";
import { useTranslation } from "react-i18next";

import { KebabDropdown } from "./KebabDropdown";
import DefaultRulesetIcon from "@app/images/Icon-Red_Hat-Virtual_server_stack-A-Black-RGB.svg";
import { KebabDropdown } from "../KebabDropdown";
import DefaultImage from "@app/images/Icon-Red_Hat-Virtual_server_stack-A-Black-RGB.svg";
import { Target, TargetLabel } from "@app/api/models";
import "./TargetCard.css";
import useFetchImageDataUrl from "./hooks/useFetchImageDataUrl";

export interface TargetCardProps {
item: Target;
Expand Down Expand Up @@ -67,6 +68,7 @@ export const TargetCard: React.FC<TargetCardProps> = ({
}) => {
const { t } = useTranslation();
const [isCardSelected, setCardSelected] = React.useState(cardSelected);
const imageDataUrl = useFetchImageDataUrl(target);

const prevSelectedLabel =
formLabels?.find((formLabel) => {
Expand Down Expand Up @@ -105,24 +107,6 @@ export const TargetCard: React.FC<TargetCardProps> = ({
}
};

const getImage = (): React.ComponentType => {
let result: React.ComponentType<any> = CubesIcon;
const imagePath = target?.image?.id
? `/hub/files/${target?.image.id}`
: DefaultRulesetIcon;
if (target.image) {
result = () => (
<img
src={imagePath}
alt="Card logo"
style={{ height: 80, pointerEvents: "none" }}
/>
);
}

return result;
};

return (
<Card
onClick={handleCardClick}
Expand Down Expand Up @@ -176,7 +160,18 @@ export const TargetCard: React.FC<TargetCardProps> = ({
variant={EmptyStateVariant.sm}
className="select-card__component__empty-state"
>
<EmptyStateIcon icon={getImage()} />
<EmptyStateIcon
icon={() => (
<img
src={imageDataUrl || DefaultImage}
alt="Card logo"
style={{ height: 80, pointerEvents: "none" }}
onError={(e) => {
e.currentTarget.src = DefaultImage;
}}
/>
)}
/>
<Title headingLevel="h4" size="md">
{target.name}
</Title>
Expand Down
3 changes: 2 additions & 1 deletion client/src/app/layout/HeaderApp/SSOMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,11 @@ export const SSOMenu: React.FC = () => {
}} /** this user dropdown is hidden on mobile sizes */
>
<Dropdown
isPlain
onSelect={onDropdownSelect}
isOpen={isDropdownOpen}
toggle={(toggleRef) => (
<MenuToggle
isFullHeight
ref={toggleRef}
id="sso-actions-toggle"
onClick={() => onDropdownToggle(!isDropdownOpen)}
Expand Down Expand Up @@ -75,6 +75,7 @@ export const SSOMenu: React.FC = () => {
history.push("/");
})
.catch((err) => {
console.error("Logout failed:", err);
history.push("/");
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ export const AnalysisWizard: React.FC<IAnalysisWizard> = ({
hasExcludedPackages: false,
associatedCredentials: "",
rulesKind: "manual",
repositoryType: "",
repositoryType: undefined,
sourceRepository: "",
branch: "",
rootPath: "",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
import { useTranslation } from "react-i18next";
import { useFormContext } from "react-hook-form";

import { TargetCard } from "@app/components/TargetCard";
import { TargetCard } from "@app/components/target-card/target-card";
import { AnalysisWizardFormValues } from "./schema";
import { useSetting } from "@app/queries/settings";
import { useFetchTargets } from "@app/queries/targets";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ export const ApplicationForm: React.FC<ApplicationFormProps> = ({

const nonManualTags = application?.tags?.filter((t) => t.source !== "") ?? [];

// TODO: Filter this if we want to exclude non-manual tags from manual tag selection
// Allow all tags to be selected manually, even if they are included from another source
const allowedManualTags = tags;

const getBinaryInitialValue = (
Expand Down Expand Up @@ -364,7 +364,7 @@ export const ApplicationForm: React.FC<ApplicationFormProps> = ({
items={allowedManualTags}
control={control}
name="tags"
label={t("terms.tags")}
label={t("terms.manualTags")}
fieldId="tags"
noResultsMessage={t("message.noResultsFoundTitle")}
placeholderText={t("composed.selectMany", {
Expand Down
Loading

0 comments on commit 070f522

Please sign in to comment.