Skip to content

Commit

Permalink
✨ View files task attachments (#1954)
Browse files Browse the repository at this point in the history
Resolves: #1929

Functional changes:
1. document to be viewed is selected from the list (first action above
   the editor) or via URL
2. display language toggle based on languages supported by the document.
   For attachments the list consists of plain text and optionally a
   second language discovered based on file extension (YAML or JSON).
3. replace "merged" checkbox with an option in the select

Related refactorings:
1. split getTaskById() query into specialized queries:
   a) getTaskById() returning Promise<Task> for working with the object
   b) getTaskByIdAndFormat() returning Promise<string> for displaying
      the task as a formatted text
2. configure AnalysisDetails component to respond to 2 routes: existing
details route and newly added
/applications/:applicationId/analysis-details/:taskId/attachments/:attachmentId
3. persist merge mode in the URL as search param "merged"

Signed-off-by: Radoslaw Szwajkowski <[email protected]>
  • Loading branch information
rszwajko authored Jun 20, 2024
1 parent a3ef502 commit eeea000
Show file tree
Hide file tree
Showing 11 changed files with 396 additions and 112 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 @@ -285,6 +285,7 @@
"assessmentQuestionnaires": "Assessment questionnaires",
"assessmentNotes": "Assessment notes",
"assessmentSummary": "Assessment summary",
"attachments": "Attachments",
"autoTagging": "Automated Tagging",
"binary": "Binary",
"branch": "Branch",
Expand Down
8 changes: 8 additions & 0 deletions client/src/app/Paths.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ export const DevPaths = {
applications: "/applications",
applicationsAnalysisDetails:
"/applications/:applicationId/analysis-details/:taskId",
applicationsAnalysisDetailsAttachment:
"/applications/:applicationId/analysis-details/:taskId/attachments/:attachmentId",
applicationsAnalysisTab: "/applications/analysis-tab",
applicationsAssessmentTab: "/applications/assessment-tab",
applicationsImports: "/applications/application-imports",
Expand Down Expand Up @@ -93,3 +95,9 @@ export interface AnalysisDetailsRoute {
applicationId: string;
taskId: string;
}

export interface AnalysisDetailsAttachmentRoute {
applicationId: string;
taskId: string;
attachmentId: string;
}
5 changes: 5 additions & 0 deletions client/src/app/Routes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,11 @@ export const devRoutes: IRoute<DevPathValues>[] = [
{
path: Paths.applicationsAnalysisDetails,
comp: AnalysisDetails,
exact: true,
},
{
path: Paths.applicationsAnalysisDetailsAttachment,
comp: AnalysisDetails,
exact: false,
},
{
Expand Down
29 changes: 24 additions & 5 deletions client/src/app/api/rest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -319,13 +319,25 @@ export const getApplicationImports = (
.get(`${APP_IMPORT}?importSummary.id=${importSummaryID}&isValid=${isValid}`)
.then((response) => response.data);

export function getTaskById(
export function getTaskById(id: number): Promise<Task> {
return axios
.get(`${TASKS}/${id}`, {
headers: { ...jsonHeaders },
responseType: "json",
})
.then((response) => {
return response.data;
});
}

export function getTaskByIdAndFormat(
id: number,
format: string,
merged: boolean = false
): Promise<Task | string> {
const headers = format === "yaml" ? { ...yamlHeaders } : { ...jsonHeaders };
const responseType = format === "yaml" ? "text" : "json";
): Promise<string> {
const isYaml = format === "yaml";
const headers = isYaml ? { ...yamlHeaders } : { ...jsonHeaders };
const responseType = isYaml ? "text" : "json";

let url = `${TASKS}/${id}`;
if (merged) {
Expand All @@ -338,7 +350,9 @@ export function getTaskById(
responseType: responseType,
})
.then((response) => {
return response.data;
return isYaml
? String(response.data ?? "")
: JSON.stringify(response.data, undefined, 2);
});
}

Expand Down Expand Up @@ -439,6 +453,11 @@ export const createFile = ({
return response.data;
});

export const getTextFile = (id: number): Promise<string> =>
axios
.get(`${FILES}/${id}`, { headers: { Accept: "text/plain" } })
.then((response) => response.data);

export const getSettingById = <K extends keyof SettingTypes>(
id: K
): Promise<SettingTypes[K]> =>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import React, { FC, useState } from "react";

import {
Select,
SelectOption,
SelectList,
MenuToggleElement,
MenuToggle,
} from "@patternfly/react-core";
import { Document } from "./SimpleDocumentViewer";
import "./SimpleDocumentViewer.css";

export const AttachmentToggle: FC<{
onSelect: (docId: string | number) => void;
documents: (Document & { isSelected: boolean })[];
}> = ({ onSelect, documents }) => {
const [isOpen, setIsOpen] = useState(false);
const onToggle = () => {
setIsOpen(!isOpen);
};

return (
<div className="simple-task-viewer-attachment-toggle">
<Select
isOpen={isOpen}
onSelect={(_event, selectedId: string | number | undefined) => {
if (selectedId) {
onSelect(selectedId);
}
onToggle();
}}
onOpenChange={(isOpen) => setIsOpen(isOpen)}
toggle={(toggleRef: React.Ref<MenuToggleElement>) => (
<MenuToggle ref={toggleRef} onClick={onToggle} isExpanded={isOpen}>
{documents.find(({ isSelected }) => isSelected)?.name}
</MenuToggle>
)}
shouldFocusToggleOnSelect
>
<SelectList>
{documents.map(({ id, name, isSelected, description }) => (
<SelectOption
isSelected={isSelected}
key={id}
value={id}
description={description}
>
{name}
</SelectOption>
))}
</SelectList>
</Select>
</div>
);
};
86 changes: 42 additions & 44 deletions client/src/app/components/simple-document-viewer/LanguageToggle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,49 +7,47 @@ import CodeIcon from "@patternfly/react-icons/dist/esm/icons/code-icon";
import "./SimpleDocumentViewer.css";

export const LanguageToggle: React.FC<{
currentLanguage: Language.yaml | Language.json;
currentLanguage: Language;
code?: string;
setCurrentLanguage: (lang: Language.yaml | Language.json) => void;
}> = ({ currentLanguage, code, setCurrentLanguage }) => (
<div
className={css(
editorStyles.codeEditorTab,
"language-toggle-group-container"
)}
key="code-language-toggle"
>
<ToggleGroup
aria-label="code content type selection"
className="language-toggle-group"
supportedLanguages: Language[];
setCurrentLanguage: (lang: Language) => void;
}> = ({ currentLanguage, code, setCurrentLanguage, supportedLanguages }) => {
if (supportedLanguages.length <= 1) {
return <></>;
}

return (
<div
className={css(
editorStyles.codeEditorTab,
"language-toggle-group-container"
)}
key="code-language-toggle"
>
<ToggleGroupItem
text={
<>
<span className={editorStyles.codeEditorTabIcon}>
<CodeIcon />
</span>
<span className={editorStyles.codeEditorTabText}>JSON</span>
</>
}
buttonId="code-language-select-json"
isSelected={currentLanguage === "json"}
isDisabled={!code && currentLanguage !== "json"}
onChange={() => setCurrentLanguage(Language.json)}
/>
<ToggleGroupItem
text={
<>
<span className={editorStyles.codeEditorTabIcon}>
<CodeIcon />
</span>
<span className={editorStyles.codeEditorTabText}>YAML</span>
</>
}
buttonId="code-language-select-yaml"
isSelected={currentLanguage === "yaml"}
isDisabled={!code && currentLanguage !== "yaml"}
onChange={() => setCurrentLanguage(Language.yaml)}
/>
</ToggleGroup>
</div>
);
<ToggleGroup
aria-label="code content type selection"
className="language-toggle-group"
>
{supportedLanguages.map((lang) => (
<ToggleGroupItem
key={lang}
text={
<>
<span className={editorStyles.codeEditorTabIcon}>
<CodeIcon />
</span>
<span className={editorStyles.codeEditorTabText}>
{lang === Language.plaintext ? "Text" : lang.toUpperCase()}
</span>
</>
}
buttonId={`code-language-select-${lang}`}
isSelected={currentLanguage === lang}
isDisabled={!code && currentLanguage !== lang}
onChange={() => setCurrentLanguage(lang)}
/>
))}
</ToggleGroup>
</div>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
.simple-task-viewer-container {
display: flex;
flex-direction: column;
height: 100%;
}

.simple-task-viewer-code {
Expand Down Expand Up @@ -53,6 +54,10 @@
flex-grow: 1;
}

.simple-task-viewer-code .pf-v5-c-code-editor__controls > * {
display: flex;
}

.simple-task-viewer-code .pf-v5-c-code-editor__header-main {
display: none;
}
Expand All @@ -67,6 +72,6 @@
--pf-v5-c-toggle-group__button--FontSize: var(--pf-v5-global--FontSize--md);
}

.merged-checkbox {
margin: auto 0.5rem;
.simple-task-viewer-attachment-toggle {
order: -1;
}
Loading

0 comments on commit eeea000

Please sign in to comment.