Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updated Document Upload and details #3643

Merged
merged 13 commits into from
Dec 14, 2023
11 changes: 10 additions & 1 deletion source/frontend/src/components/common/GenericModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export interface ModalContent {
handleCancel?: Function;
/** Optional function to control behaviour of ok button. Default is to reload the app. */
handleOk?: Function;
handleOkDisabled?: boolean;
/** Optional text to display on the cancel button. Default is Cancel. */
cancelButtonText?: string;
/** Optional variant that will override the default variant of warning. */
Expand Down Expand Up @@ -98,6 +99,7 @@ export const GenericModal = (props: Omit<BsModalProps, 'onHide'> & ModalProps) =
display,
setDisplay,
handleOk,
handleOkDisabled,
handleCancel,
title,
message,
Expand Down Expand Up @@ -215,12 +217,19 @@ export const GenericModal = (props: Omit<BsModalProps, 'onHide'> & ModalProps) =
title="cancel-modal"
variant={cancelButtonVariant ?? 'secondary'}
onClick={close}
data-testid="cancel-modal-button"
>
{cancelButtonText}
</Button>
)}

<Button title="ok-modal" variant={okButtonVariant ?? 'primary'} onClick={ok}>
<Button
title="ok-modal"
variant={okButtonVariant ?? 'primary'}
onClick={ok}
disabled={handleOkDisabled}
data-testid="ok-modal-button"
>
{okButtonText ?? 'Ok'}
</Button>
</div>
Expand Down
19 changes: 15 additions & 4 deletions source/frontend/src/components/common/Section/Section.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,29 @@ interface SectionProps {
header?: React.ReactNode;
isCollapsable?: boolean;
initiallyExpanded?: boolean;
noPadding?: boolean;
}

export const Section: React.FC<
React.PropsWithChildren<SectionProps & React.HTMLAttributes<HTMLDivElement>> & {
'data-testid'?: string;
}
> = ({ header, children, title, isCollapsable, initiallyExpanded, className, ...rest }) => {
> = ({
header,
children,
title,
isCollapsable,
initiallyExpanded,
noPadding,
className,
...rest
}) => {
const [isCollapsed, setIsCollapsed] = useState<boolean>(!initiallyExpanded && true);
return (
<StyledFormSection
className={clsx('form-section', className)}
data-testid={rest['data-testid']}
noPadding={noPadding}
>
{header && (
<StyledSectionHeader>
Expand Down Expand Up @@ -66,9 +77,9 @@ const StyledSectionHeader = styled.h2`
margin-bottom: 2rem;
`;

const StyledFormSection = styled.div`
margin: 1.5rem;
padding: 1.5rem;
const StyledFormSection = styled.div<{ noPadding?: boolean }>`
margin: ${props => (props.noPadding === true ? '' : '1.5rem')};
padding: ${props => (props.noPadding === true ? '' : '1.5rem')};
background-color: white;
text-align: left;
border-radius: 0.5rem;
Expand Down
152 changes: 152 additions & 0 deletions source/frontend/src/components/common/form/FileDragAndDrop.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
import { ChangeEvent, FunctionComponent, useState } from 'react';
import styled from 'styled-components';

import { SectionField } from '../Section/SectionField';

interface IFileDragAndDropProps {
onSelectFile: (file: File | null) => void;
selectedFile: File | null;
validExtensions: string[];
}

const FileDragAndDrop: FunctionComponent<React.PropsWithChildren<IFileDragAndDropProps>> = ({
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test coverage on this isn't great. Unit testing this completely may not be realistic but is there anything we can do here?

onSelectFile,
selectedFile,
validExtensions,
}) => {
const validDocumentExtensions: string = validExtensions.map(x => `.${x}`).join(',');

const [isDragging, setIsDragging] = useState(false);

const handleFileInput = (changeEvent: ChangeEvent<HTMLInputElement>) => {
// handle validations
if (changeEvent.target !== null) {
var target = changeEvent.target;
if (target.files !== null && target.files.length > 0) {
onSelectFile(target.files[0]);

Check warning on line 26 in source/frontend/src/components/common/form/FileDragAndDrop.tsx

View check run for this annotation

Codecov / codecov/patch

source/frontend/src/components/common/form/FileDragAndDrop.tsx#L23-L26

Added lines #L23 - L26 were not covered by tests
}
}
};

const handleDragEnter = (event: React.DragEvent) => {
event.preventDefault();
event.stopPropagation();

Check warning on line 33 in source/frontend/src/components/common/form/FileDragAndDrop.tsx

View check run for this annotation

Codecov / codecov/patch

source/frontend/src/components/common/form/FileDragAndDrop.tsx#L32-L33

Added lines #L32 - L33 were not covered by tests

setIsDragging(true);

Check warning on line 35 in source/frontend/src/components/common/form/FileDragAndDrop.tsx

View check run for this annotation

Codecov / codecov/patch

source/frontend/src/components/common/form/FileDragAndDrop.tsx#L35

Added line #L35 was not covered by tests
};

const handleDragLeave = (event: React.DragEvent) => {
event.preventDefault();
event.stopPropagation();

Check warning on line 40 in source/frontend/src/components/common/form/FileDragAndDrop.tsx

View check run for this annotation

Codecov / codecov/patch

source/frontend/src/components/common/form/FileDragAndDrop.tsx#L39-L40

Added lines #L39 - L40 were not covered by tests

setIsDragging(false);

Check warning on line 42 in source/frontend/src/components/common/form/FileDragAndDrop.tsx

View check run for this annotation

Codecov / codecov/patch

source/frontend/src/components/common/form/FileDragAndDrop.tsx#L42

Added line #L42 was not covered by tests
};

const handleDragOver = (event: React.DragEvent) => {
event.preventDefault();
event.stopPropagation();

Check warning on line 47 in source/frontend/src/components/common/form/FileDragAndDrop.tsx

View check run for this annotation

Codecov / codecov/patch

source/frontend/src/components/common/form/FileDragAndDrop.tsx#L46-L47

Added lines #L46 - L47 were not covered by tests

setIsDragging(true);

Check warning on line 49 in source/frontend/src/components/common/form/FileDragAndDrop.tsx

View check run for this annotation

Codecov / codecov/patch

source/frontend/src/components/common/form/FileDragAndDrop.tsx#L49

Added line #L49 was not covered by tests
};

const handleDrop = (event: React.DragEvent) => {
event.preventDefault();
event.stopPropagation();

Check warning on line 54 in source/frontend/src/components/common/form/FileDragAndDrop.tsx

View check run for this annotation

Codecov / codecov/patch

source/frontend/src/components/common/form/FileDragAndDrop.tsx#L53-L54

Added lines #L53 - L54 were not covered by tests

let files = [...event.dataTransfer.files];

Check warning on line 56 in source/frontend/src/components/common/form/FileDragAndDrop.tsx

View check run for this annotation

Codecov / codecov/patch

source/frontend/src/components/common/form/FileDragAndDrop.tsx#L56

Added line #L56 was not covered by tests

if (files && files.length > 0) {
onSelectFile(files[0]);
event.dataTransfer.clearData();

Check warning on line 60 in source/frontend/src/components/common/form/FileDragAndDrop.tsx

View check run for this annotation

Codecov / codecov/patch

source/frontend/src/components/common/form/FileDragAndDrop.tsx#L58-L60

Added lines #L58 - L60 were not covered by tests
}

setIsDragging(false);

Check warning on line 63 in source/frontend/src/components/common/form/FileDragAndDrop.tsx

View check run for this annotation

Codecov / codecov/patch

source/frontend/src/components/common/form/FileDragAndDrop.tsx#L63

Added line #L63 was not covered by tests
};

const shortenString = (text: string, maxLength: number, terminator: string = '...'): string => {
if (text.length > maxLength) {
return text.substring(0, maxLength - terminator.length) + terminator;

Check warning on line 68 in source/frontend/src/components/common/form/FileDragAndDrop.tsx

View check run for this annotation

Codecov / codecov/patch

source/frontend/src/components/common/form/FileDragAndDrop.tsx#L67-L68

Added lines #L67 - L68 were not covered by tests
}

return text;

Check warning on line 71 in source/frontend/src/components/common/form/FileDragAndDrop.tsx

View check run for this annotation

Codecov / codecov/patch

source/frontend/src/components/common/form/FileDragAndDrop.tsx#L71

Added line #L71 was not covered by tests
};

return (
<div>
<DragDropZone
onDrop={handleDrop}
onDragOver={handleDragOver}
onDragEnter={handleDragEnter}
onDragLeave={handleDragLeave}
isDragging={isDragging}
>
<StyledContent>
Drag files here to attach or{' '}
<StyledUploadLabel>
Browse
<StyledFileInput
data-testid="upload-input"
id="uploadInput"
type="file"
name="documentFile"
accept={validDocumentExtensions}
onChange={handleFileInput}
className=""
/>
</StyledUploadLabel>
</StyledContent>
</DragDropZone>
{selectedFile !== null && (
<StyledSelectedFile>

Check warning on line 100 in source/frontend/src/components/common/form/FileDragAndDrop.tsx

View check run for this annotation

Codecov / codecov/patch

source/frontend/src/components/common/form/FileDragAndDrop.tsx#L100

Added line #L100 was not covered by tests
<SectionField label="File to add" labelWidth="3">
{shortenString(selectedFile.name || '', 20)}

Check warning on line 102 in source/frontend/src/components/common/form/FileDragAndDrop.tsx

View check run for this annotation

Codecov / codecov/patch

source/frontend/src/components/common/form/FileDragAndDrop.tsx#L102

Added line #L102 was not covered by tests
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe could use the OverflowTip component instead?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I checked with ana and this way worked better

</SectionField>
</StyledSelectedFile>
)}
</div>
);
};

export default FileDragAndDrop;

const DragDropZone = styled.div<{ isDragging: boolean }>`
border: 1px solid ${({ theme }) => theme.css.lightVariantColor};

border-style: ${({ isDragging }) => (isDragging ? 'solid' : 'dashed')};

border: ${props => (props.isDragging ? `1px solid ${props.theme.css.draftColor}` : '')};

background-color: ${props => (props.isDragging ? props.theme.css.filterBoxColor : '')};

height: 10rem;
line-height: 10rem;
text-align: center;
`;

const StyledContent = styled.div`
width: 100%;
display: inline-block;
vertical-align: middle;
line-height: normal;
`;

const StyledUploadLabel = styled.label`
display: inline-block;
color: ${({ theme }) => theme.css.linkColor};
cursor: pointer;

&:hover {
color: ${({ theme }) => theme.css.linkHoverColor};
text-decoration: underline;
}
`;

const StyledFileInput = styled.input`
display: none;
`;

const StyledSelectedFile = styled.div`
padding-top: 2rem;
overflow: hide;
word-wrap: break-word;
`;
6 changes: 6 additions & 0 deletions source/frontend/src/features/documents/ComposedDocument.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ export class DocumentUploadFormData {
public documentTypeId: string;
public documentStatusCode: string;
public documentMetadata: Record<string, string>;
public isDocumentTypeChanged: boolean = false;
public isSelectedFile: boolean = false;

public constructor(
initialStatus: string,
Expand Down Expand Up @@ -125,6 +127,7 @@ export class DocumentUpdateFormData {
public mayanDocumentId: number;
public documentStatusCode: string;
public documentMetadata: Record<string, string>;
public documentTypeId: string = '';

public static fromApi(
composedDocument: ComposedDocument,
Expand All @@ -144,6 +147,9 @@ export class DocumentUpdateFormData {
model.documentMetadata[metaType.metadata_type?.id?.toString() || '-'] =
foundMetadata?.value ?? '';
});
const documentTypeLabel = composedDocument.pimsDocumentRelationship?.document?.documentType?.id;

model.documentTypeId = documentTypeLabel?.toString() || '';
return model;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,8 @@ export const getDocumentMetadataYupSchema = (
}
}

return Yup.object().shape({ documentMetadata: Yup.object().shape(metadataSchema) });
return Yup.object().shape({
documentMetadata: Yup.object().shape(metadataSchema),
documentTypeId: Yup.string().required('Document type is required'),
});
};
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { Col, Row } from 'react-bootstrap';
import { Button } from '@/components/common/buttons/Button';
import { Select } from '@/components/common/form';
import LoadingBackdrop from '@/components/common/LoadingBackdrop';
import { Section } from '@/components/common/Section/Section';
import { SectionField } from '@/components/common/Section/SectionField';
import TooltipIcon from '@/components/common/TooltipIcon';
import * as API from '@/constants/API';
Expand All @@ -13,13 +14,7 @@ import useLookupCodeHelpers from '@/hooks/useLookupCodeHelpers';
import { Api_DocumentUpdateRequest } from '@/models/api/Document';
import { Api_Storage_DocumentTypeMetadataType } from '@/models/api/DocumentStorage';

import {
StyledGreySection,
StyledH2,
StyledH3,
StyledHeader,
StyledScrollable,
} from '../commonStyles';
import { StyledH3, StyledScrollable } from '../commonStyles';
import { ComposedDocument, DocumentUpdateFormData } from '../ComposedDocument';
import { DocumentMetadataView } from '../DocumentMetadataView';
import { getDocumentMetadataYupSchema } from '../DocumentMetadataYupSchema';
Expand Down Expand Up @@ -53,20 +48,20 @@ export const DocumentDetailForm: React.FunctionComponent<
{hasClaim(Claims.DOCUMENT_VIEW) && (
<>
<DocumentDetailHeader document={props.document} />
<StyledGreySection>
<Row className="pb-3">
<Col className="text-left">
<StyledHeader>
<StyledH2>Document information</StyledH2>
<TooltipIcon
toolTipId={'documentInfoToolTip'}
innerClassName={'documentInfoToolTip'}
toolTip="Information you provided here will be searchable"
></TooltipIcon>
</StyledHeader>
</Col>
</Row>

<Section
noPadding
header={
<>
Document information
<TooltipIcon
toolTipId="documentInfoToolTip"
innerClassName="documentInfoToolTip"
toolTip="Information you provided here will be searchable"
/>{' '}
</>
}
>
<StyledScrollable>
<Formik<DocumentUpdateFormData>
innerRef={props.formikRef}
Expand Down Expand Up @@ -95,23 +90,30 @@ export const DocumentDetailForm: React.FunctionComponent<
mayanMetadata={props.mayanMetadataTypes}
formikProps={formikProps}
/>
<div className="pt-5">Do you want to proceed?</div>
<hr />
<Row className="justify-content-end pt-4">
<Col xs="auto">
<Button variant="secondary" type="button" onClick={props.onCancel}>
Cancel
<Button
variant="secondary"
type="button"
onClick={props.onCancel}
className="px-5"
>
No
</Button>
</Col>
<Col xs="auto">
<Button type="submit" onClick={formikProps.submitForm}>
Save
<Button type="submit" onClick={formikProps.submitForm} className="px-5">
Yes
</Button>
</Col>
</Row>
</>
)}
</Formik>
</StyledScrollable>
</StyledGreySection>
</Section>
</>
)}
</StyledContainer>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const DocumentDetailHeader: React.FunctionComponent<
const mayanDocumentId = props.document.pimsDocumentRelationship?.document?.mayanDocumentId || -1;

return (
<>
<div className="pb-4">
<SectionField
data-testid="document-type"
label="Document type"
Expand All @@ -39,7 +39,7 @@ const DocumentDetailHeader: React.FunctionComponent<
</Col>
</Row>
</SectionField>
</>
</div>
);
};

Expand Down
Loading
Loading