From d9dc3fba58b84de2c17cd67c28821ea23d5834c8 Mon Sep 17 00:00:00 2001 From: ibolton336 Date: Fri, 19 May 2023 17:27:08 -0400 Subject: [PATCH] 6.2 release branch setup with windup working Signed-off-by: ibolton336 --- client/public/locales/en/translation.json | 2 + client/public/locales/es/translation.json | 2 + client/src/app/api/models.ts | 8 +- .../app/common/CustomRules/rules-utils.tsx | 90 +++++++------------ .../app/common/CustomRules/useRuleFiles.tsx | 31 +++---- .../analysis-wizard/analysis-wizard.tsx | 19 ++-- .../analysis-wizard/custom-rules.tsx | 4 +- .../applications-table-analyze.tsx | 2 +- .../applications-table-assessment.tsx | 2 +- .../application-detail-drawer-analysis.tsx | 61 ++++++++++++- client/src/app/pages/general/general.tsx | 51 +++++++++++ .../migration-targets/custom-target-form.tsx | 8 +- client/src/app/queries/rulesets.ts | 3 - 13 files changed, 180 insertions(+), 103 deletions(-) diff --git a/client/public/locales/en/translation.json b/client/public/locales/en/translation.json index 1e10f4d601..3d9953a44a 100644 --- a/client/public/locales/en/translation.json +++ b/client/public/locales/en/translation.json @@ -305,6 +305,8 @@ "select": "Select", "settingsAllowApps": "Allow reviewing applications without running an assessment first", "source": "Source", + "settingsCSVReports": "Enable downloads for CSV reports", + "settingsHTMLReports": "Enable downloads for HTML reports", "sourceBranch": "Branch", "sourceCode": "Source code", "sourceRepo": "Source Repository", diff --git a/client/public/locales/es/translation.json b/client/public/locales/es/translation.json index 3252f24eee..e469e4fc1e 100644 --- a/client/public/locales/es/translation.json +++ b/client/public/locales/es/translation.json @@ -274,6 +274,8 @@ "scheduled": "Programado", "select": "Seleccione", "settingsAllowApps": "Permitir la revisión de aplicaciones sin ejecutar una evaluación primero", + "settingsCSVReports": "Habilitar descargas para informes CSV", + "settingsHTMLReports": "Habilitar descargas para informes HTML", "sourceBranch": "Rama", "sourceCode": "Código fuente.", "sourceRepo": "Repositorio", diff --git a/client/src/app/api/models.ts b/client/src/app/api/models.ts index 5d4d4ed940..8a2abac117 100644 --- a/client/src/app/api/models.ts +++ b/client/src/app/api/models.ts @@ -338,6 +338,8 @@ export interface ApplicationImportPage { } export type SettingTypes = { + "download.csv.enabled": boolean; + "download.html.enabled": boolean; "git.insecure.enabled": boolean; "mvn.dependencies.update.forced": boolean; "mvn.insecure.enabled": boolean; @@ -385,6 +387,7 @@ export interface TaskData { tagger: { enabled: boolean; }; + output: string; mode: { binary: boolean; withDeps: boolean; @@ -409,10 +412,7 @@ export interface TaskData { rulesets: Ref[]; repository?: Repository; identity?: Ref; - labels: { - included: string[]; - excluded: string[]; - }; + labels: string[]; }; } diff --git a/client/src/app/common/CustomRules/rules-utils.tsx b/client/src/app/common/CustomRules/rules-utils.tsx index e98cfef23f..cc457ea78f 100644 --- a/client/src/app/common/CustomRules/rules-utils.tsx +++ b/client/src/app/common/CustomRules/rules-utils.tsx @@ -1,5 +1,4 @@ -import { IReadFile, ParsedRule, Rule, Ruleset } from "@app/api/models"; -import yaml from "js-yaml"; +import { IReadFile, ParsedRule, Ruleset } from "@app/api/models"; type RuleFileType = "YAML" | "XML" | null; @@ -14,69 +13,43 @@ export const checkRuleFileType = (filename: string): RuleFileType => { export const parseRules = (file: IReadFile): ParsedRule => { if (file.data) { - if (checkRuleFileType(file.fileName) === "YAML") { - const yamlDoc = yaml.load(file.data) as any[]; - const yamlLabels = yamlDoc?.reduce((acc, parsedLine) => { - const newLabels = parsedLine?.labels ? parsedLine?.labels : []; - return [...acc, ...newLabels]; - }, []); - const allLabels = getLabels(yamlLabels); - return { - source: allLabels?.sourceLabel, - target: allLabels?.targetLabel, - otherLabels: allLabels?.otherLabels, - allLabels: allLabels?.allLabels, - total: 0, - ...(file.responseID && { - fileID: file.responseID, - }), - }; - } else if (checkRuleFileType(file.fileName) === "XML") { - let source: string | null = null; - let target: string | null = null; - let rulesCount = 0; + let source: string | null = null; + let target: string | null = null; + let rulesCount = 0; - const parser = new DOMParser(); - const xml = parser.parseFromString(file.data, "text/xml"); + const parser = new DOMParser(); + const xml = parser.parseFromString(file.data, "text/xml"); - const ruleSets = xml.getElementsByTagName("ruleset"); + const ruleSets = xml.getElementsByTagName("ruleset"); - if (ruleSets && ruleSets.length > 0) { - const metadata = ruleSets[0].getElementsByTagName("metadata"); + if (ruleSets && ruleSets.length > 0) { + const metadata = ruleSets[0].getElementsByTagName("metadata"); - if (metadata && metadata.length > 0) { - const sources = metadata[0].getElementsByTagName("sourceTechnology"); - if (sources && sources.length > 0) source = sources[0].id; + if (metadata && metadata.length > 0) { + const sources = metadata[0].getElementsByTagName("sourceTechnology"); + if (sources && sources.length > 0) source = sources[0].id; - const targets = metadata[0].getElementsByTagName("targetTechnology"); - if (targets && targets.length > 0) target = targets[0].id; - } - - const rulesGroup = ruleSets[0].getElementsByTagName("rules"); - if (rulesGroup && rulesGroup.length > 0) - rulesCount = rulesGroup[0].getElementsByTagName("rule").length; + const targets = metadata[0].getElementsByTagName("targetTechnology"); + if (targets && targets.length > 0) target = targets[0].id; } - const allLabels = [ - ...(source ? [`konveyor.io/source=${source}`] : []), - ...(target ? [`konveyor.io/target=${target}`] : []), - ]; - return { - source: source, - target: target, - otherLabels: allLabels, - allLabels: allLabels, - total: rulesCount, - ...(file.responseID && { - fileID: file.responseID, - }), - }; - } else { - return { - source: null, - target: null, - total: 0, - }; + + const rulesGroup = ruleSets[0].getElementsByTagName("rules"); + if (rulesGroup && rulesGroup.length > 0) + rulesCount = rulesGroup[0].getElementsByTagName("rule").length; } + const allLabels = [ + ...(source ? [`konveyor.io/source=${source}`] : []), + ...(target ? [`konveyor.io/target=${target}`] : []), + ]; + return { + source, + target, + total: rulesCount, + allLabels, + ...(file.responseID && { + fileID: file.responseID, + }), + }; } else { return { source: null, @@ -85,7 +58,6 @@ export const parseRules = (file: IReadFile): ParsedRule => { }; } }; - interface ILabelMap { sourceLabel: string; targetLabel: string; diff --git a/client/src/app/common/CustomRules/useRuleFiles.tsx b/client/src/app/common/CustomRules/useRuleFiles.tsx index 2d0c176118..d472aac89b 100644 --- a/client/src/app/common/CustomRules/useRuleFiles.tsx +++ b/client/src/app/common/CustomRules/useRuleFiles.tsx @@ -1,4 +1,6 @@ import { useContext, useState } from "react"; +import XSDSchema from "./windup-jboss-ruleset.xsd"; +import { XMLValidator } from "fast-xml-parser"; import { FileLoadError, IReadFile } from "@app/api/models"; import { NotificationsContext } from "@app/shared/notifications-context"; import { AxiosError } from "axios"; @@ -7,9 +9,6 @@ import { getAxiosErrorMessage } from "@app/utils/utils"; import { useCreateFileMutation } from "@app/queries/rulesets"; import { CustomTargetFormValues } from "@app/pages/migration-targets/custom-target-form"; import { UseFormReturn } from "react-hook-form"; -import { XMLValidator } from "fast-xml-parser"; -import XSDSchema from "./windup-jboss-ruleset.xsd"; -import { checkRuleFileType } from "./rules-utils"; const xmllint = require("xmllint"); export default function useRuleFiles( @@ -199,22 +198,15 @@ export default function useRuleFiles( handleReadFail(error, 100, file); } else { if (data) { - if (checkRuleFileType(file.name) === "XML") { - const validatedXMLResult = validateXMLFile(data); - if (validatedXMLResult.state === "valid") { - handleReadSuccess(data, file); - } else { - const error = new Error( - `File "${file.name}" is not a valid XML: ${validatedXMLResult.message}` - ); - handleReadFail(error, 100, file); - } - } else { + const validatedXMLResult = validateXMLFile(data); + if (validatedXMLResult.state === "valid") handleReadSuccess(data, file); + else { + const error = new Error( + `File "${file.name}" is not a valid XML: ${validatedXMLResult.message}` + ); + handleReadFail(error, 100, file); } - } else { - const error = new Error("error"); - handleReadFail(error, 100, file); } } } @@ -314,6 +306,11 @@ export default function useRuleFiles( }; }; + interface IParsedXMLFileStatus { + state: "valid" | "error"; + message?: string; + } + return { handleFileDrop, removeFiles, diff --git a/client/src/app/pages/applications/analysis-wizard/analysis-wizard.tsx b/client/src/app/pages/applications/analysis-wizard/analysis-wizard.tsx index 7586d3e390..4f59478f28 100644 --- a/client/src/app/pages/applications/analysis-wizard/analysis-wizard.tsx +++ b/client/src/app/pages/applications/analysis-wizard/analysis-wizard.tsx @@ -47,6 +47,7 @@ interface IAnalysisWizard { } const defaultTaskData: TaskData = { + output: "/windup/report", tagger: { enabled: true, }, @@ -56,8 +57,6 @@ const defaultTaskData: TaskData = { artifact: "", diva: false, }, - targets: [], - sources: [], scope: { withKnown: false, packages: { @@ -68,8 +67,8 @@ const defaultTaskData: TaskData = { }; const defaultTaskgroup: Taskgroup = { - name: `taskgroup.analyzer`, - addon: "analyzer", + name: `taskgroup.windup`, + addon: "windup", data: { ...defaultTaskData, }, @@ -194,7 +193,6 @@ export const AnalysisWizard: React.FC = ({ const { handleSubmit, watch, reset } = methods; const values = watch(); - console.log("values", values); enum StepId { AnalysisMode = 1, @@ -256,13 +254,10 @@ export const AnalysisWizard: React.FC = ({ }, }, rules: { - labels: { - included: [ - ...fieldValues.formTargets, - ...fieldValues.selectedFormSources, - ], - excluded: [], - }, + labels: [ + ...fieldValues.formTargets, + ...fieldValues.selectedFormSources, + ], path: fieldValues.customRulesFiles.length > 0 ? "/rules" : "", tags: { excluded: fieldValues.excludedRulesTags, diff --git a/client/src/app/pages/applications/analysis-wizard/custom-rules.tsx b/client/src/app/pages/applications/analysis-wizard/custom-rules.tsx index 001a4c48ad..9307338bcd 100644 --- a/client/src/app/pages/applications/analysis-wizard/custom-rules.tsx +++ b/client/src/app/pages/applications/analysis-wizard/custom-rules.tsx @@ -484,14 +484,14 @@ export const CustomRules: React.FC = (props) => { } titleText="Drag and drop files here" titleTextSeparator="or" - infoText="Accepted file types: .yml, .yaml, .xml " + infoText="Accepted file types: .xml " /> {showStatus && ( { activeAppInDetailDrawer, } = useApplicationsFilterValues(ApplicationTableType.Analysis, applications); - const { tasks } = useFetchTasks({ addon: "analyzer" }); + const { tasks } = useFetchTasks({ addon: "windup" }); const queryClient = useQueryClient(); const allTasksComplete = tasks.every((task) => task.state !== "Running"); diff --git a/client/src/app/pages/applications/applications-table-assessment/applications-table-assessment.tsx b/client/src/app/pages/applications/applications-table-assessment/applications-table-assessment.tsx index f4a121e3cf..86df52d6e7 100644 --- a/client/src/app/pages/applications/applications-table-assessment/applications-table-assessment.tsx +++ b/client/src/app/pages/applications/applications-table-assessment/applications-table-assessment.tsx @@ -137,7 +137,7 @@ export const ApplicationsTable: React.FC = () => { refetch: fetchApplications, } = useFetchApplications(); - const { tasks } = useFetchTasks({ addon: "analyzer" }); + const { tasks } = useFetchTasks({ addon: "windup" }); const getTask = (application: Application) => tasks.find((task: Task) => task.application?.id === application.id); diff --git a/client/src/app/pages/applications/components/application-detail-drawer/application-detail-drawer-analysis.tsx b/client/src/app/pages/applications/components/application-detail-drawer/application-detail-drawer-analysis.tsx index 54a37a2fe9..8c0bb33592 100644 --- a/client/src/app/pages/applications/components/application-detail-drawer/application-detail-drawer-analysis.tsx +++ b/client/src/app/pages/applications/components/application-detail-drawer/application-detail-drawer-analysis.tsx @@ -13,6 +13,7 @@ import { ExclamationCircleIcon, } from "@patternfly/react-icons"; import spacing from "@patternfly/react-styles/css/utilities/Spacing/spacing"; +import textStyles from "@patternfly/react-styles/css/utilities/Text/text"; import { Identity, Task } from "@app/api/models"; import { getKindIDByRef } from "@app/utils/model-utils"; import { useFetchIdentities } from "@app/queries/identities"; @@ -21,6 +22,8 @@ import { IApplicationDetailDrawerProps, } from "./application-detail-drawer"; import { EmptyTextMessage } from "@app/shared/components"; +import { useSetting } from "@app/queries/settings"; +import { APPLICATIONS } from "@app/api/rest"; export interface IApplicationDetailDrawerAnalysisProps extends Pick< @@ -37,6 +40,9 @@ export const ApplicationDetailDrawerAnalysis: React.FC< const { identities } = useFetchIdentities(); + const { data: isCSVDownloadEnabled } = useSetting("download.csv.enabled"); + const { data: isHTMLDownloadEnabled } = useSetting("download.html.enabled"); + let matchingSourceCredsRef: Identity | undefined; let matchingMavenCredsRef: Identity | undefined; if (application && identities) { @@ -100,13 +106,64 @@ export const ApplicationDetailDrawerAnalysis: React.FC< + {(isHTMLDownloadEnabled || isCSVDownloadEnabled) && ( + + Download report: + {isHTMLDownloadEnabled && ( + + + + )} + {isHTMLDownloadEnabled && + isCSVDownloadEnabled && + task?.data?.mode?.csv && ( + | + )} + {isCSVDownloadEnabled && task?.data?.mode?.csv && ( + <> + + + + + )} + + )} ) : task?.state === "Failed" ? ( <> diff --git a/client/src/app/pages/general/general.tsx b/client/src/app/pages/general/general.tsx index 56f4eb9d58..aa51a1a0f1 100644 --- a/client/src/app/pages/general/general.tsx +++ b/client/src/app/pages/general/general.tsx @@ -24,15 +24,30 @@ export const General: React.FC = () => { const { t } = useTranslation(); const reviewAssessmentSetting = useSetting("review.assessment.required"); + const downloadHTMLSetting = useSetting("download.html.enabled"); + const downloadCSVSetting = useSetting("download.csv.enabled"); const reviewAssessmentSettingMutation = useSettingMutation( "review.assessment.required" ); + const downloadHTMLSettingMutation = useSettingMutation( + "download.html.enabled" + ); + const downloadCSVSettingMutation = useSettingMutation("download.csv.enabled"); const onChangeReviewAssessmentSetting = () => { if (reviewAssessmentSetting.isSuccess) reviewAssessmentSettingMutation.mutate(!reviewAssessmentSetting.data); }; + const onChangeDownloadHTMLSetting = () => { + if (downloadHTMLSetting.isSuccess) + downloadHTMLSettingMutation.mutate(!downloadHTMLSetting.data); + }; + + const onChangeDownloadCSVSetting = () => { + if (downloadCSVSetting.isSuccess) + downloadCSVSettingMutation.mutate(!downloadCSVSetting.data); + }; return ( <> @@ -50,6 +65,20 @@ export const General: React.FC = () => { title={reviewAssessmentSetting.error} /> )} + {downloadCSVSetting.isError && ( + + )} + {downloadHTMLSetting.isError && ( + + )}
{ } onChange={onChangeReviewAssessmentSetting} /> + + diff --git a/client/src/app/pages/migration-targets/custom-target-form.tsx b/client/src/app/pages/migration-targets/custom-target-form.tsx index 0527460123..08fd3be63d 100644 --- a/client/src/app/pages/migration-targets/custom-target-form.tsx +++ b/client/src/app/pages/migration-targets/custom-target-form.tsx @@ -268,6 +268,10 @@ export const CustomTargetForm: React.FC = ({ const { source, target, fileID, allLabels } = parseRules(file); const newRule: Rule = { name: file.fileName, + // metadata: { + // target: target ? target : "", + // source: source ? source : "", + // }, labels: allLabels, file: { id: fileID ? fileID : 0, @@ -475,7 +479,7 @@ export const CustomTargetForm: React.FC = ({ @@ -483,7 +487,7 @@ export const CustomTargetForm: React.FC = ({ titleIcon={} titleText="Drag and drop files here" titleTextSeparator="or" - infoText="Accepted file types: .yml, .yaml, .xml" + infoText="Accepted file types: XML with '.windup.xml' suffix." /> {showStatus && ( { select: (data) => { return data.map((ruleset) => { const mappedRules = ruleset.rules.map((rule) => { - if (ruleset?.name === "rule-example.yaml") { - debugger; - } const labels = getLabels(rule.labels || []); const transformedMetadata: Metadata = {