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

Soorya,Arjun,Tanya,Phani | Improvements in new Form2 display controls #945

Merged
merged 8 commits into from
Jun 13, 2024
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { useEffect, useState } from 'react';
import PropTypes from "prop-types";
import { getLocale } from "../i18n/utils";
import { getFormByFormName ,getFormDetail, getFormTranslations } from "./EditObservationFormUtils";
import { getFormByFormName, getFormDetail, getFormTranslations } from "./EditObservationFormUtils";
import { findByEncounterUuid } from '../../utils/FormDisplayControl/FormView';
import { getLatestPublishedForms } from '../../utils/FormDisplayControl/FormUtils';
import { Modal, Loading } from 'carbon-components-react';
Expand Down Expand Up @@ -47,6 +47,7 @@ const EditObservationForm = (props) => {
return;
}
encounter.observations = editedObservations.observations;
encounter.orders = [];
handleEditSave(encounter);
};

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
import React, { useState } from "react";
import propTypes from "prop-types";
import { Link } from "carbon-components-react";
import { DocumentPdf, Download, PlayFilledAlt } from "@carbon/icons-react/next";
import { formatDate } from "../../../../utils/utils";
import { FileViewerModal } from "../FileViewerModal/FileViewerModal";
import { getThumbnail } from "../../../../utils/FormDisplayControl/FormView";
import { document_images_path } from "../../../../constants";
import "../FileViewer.scss";

export const BuildFileViewer = (props) => {
const { item, index } = props;

const [isFileViewerModalOpen, setFileViewerModal] = useState(false);

const itemInfoMap = {
providerName: item?.providers[0]?.name || "",
encounterDateTime: formatDate(item?.encounterDateTime),
comment: item?.comment || "",
fileName: item?.complexData?.title,
fileType: item?.complexData?.mimeType,
fileRelativePath: item?.value,
fileSource: document_images_path + item?.value,
};

const closeModel = () => {
setFileViewerModal(false);
};

if (itemInfoMap?.fileType == "video/mp4") {
return (
<>
<div className={`video-viewer video-${index}`}>
<div
className="video-play-button"
onClick={() => setFileViewerModal(!isFileViewerModalOpen)}
>
<img
className="form-obs-video-image"
src={
document_images_path +
getThumbnail(itemInfoMap.fileRelativePath, "jpg")
}
alt="image"
/>
<div className="video-play-button-icon">
<PlayFilledAlt size={22} />
</div>
</div>
<span className="file-notes-section">
{itemInfoMap?.comment}
<br />
<span className="provider-info">
{itemInfoMap?.providerName}
&nbsp;
{itemInfoMap?.encounterDateTime}
</span>
<span className="download-link">
<Link
href={itemInfoMap?.fileSource}
download={itemInfoMap.fileName}
>
<Download size={20} />
</Link>
</span>
</span>
</div>
{isFileViewerModalOpen && (
<FileViewerModal closeModel={closeModel} infoMap={itemInfoMap} />
)}
</>
);
} else {
return (
<>
<div className={`image-viewer img-${index}`}>
{itemInfoMap?.fileType === "application/pdf" ? (
<Link
className="pdf-link"
href={itemInfoMap.fileSource}
target="_blank"
>
<DocumentPdf size={93} />
</Link>
) : (
<div onClick={() => setFileViewerModal(!isFileViewerModalOpen)}>
<img
className="form-obs-image"
src={
document_images_path +
getThumbnail(itemInfoMap.fileRelativePath)
}
alt="image"
/>
</div>
)}
{
<span className="file-notes-section">
{itemInfoMap?.comment}
<br />
<span className="provider-info">
{itemInfoMap.providerName}
&nbsp;
{itemInfoMap.encounterDateTime}
</span>
</span>
}
</div>
{isFileViewerModalOpen && (
<FileViewerModal closeModel={closeModel} infoMap={itemInfoMap} />
)}
</>
);
}
};

BuildFileViewer.propTypes = {
item: propTypes.object,
index: propTypes.number,
};

export default BuildFileViewer;
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import React from "react";
import { render, screen, within } from "@testing-library/react";
import { BuildFileViewer } from "./BuildFileViewer.jsx";
import { mockIndex, mockItem, mockPdfItem, mockVideoItem } from "../FileViewerMockData";
import { formatDate } from "../../../../utils/utils";

describe("BuildFileViewer", function () {

it("should render BuildFileViewer with all the data with image", function () {
const { container } = render(
<BuildFileViewer item={mockItem} index={mockIndex} />
);
expect(container.querySelector(".form-obs-image")).not.toBeNull();
expect(screen.getByAltText(/image/i)).toBeTruthy();
expect(screen.getByText(mockItem.comment)).toBeTruthy();
const provider_info = container.querySelector(".provider-info");
expect(within(provider_info).getByText(/test provider/i)).toBeTruthy();
expect(within(provider_info).getByText(new RegExp(formatDate(mockItem.encounterDateTime)))).toBeTruthy();
});

it("should render BuildFileViewer with all the data with video and download option", function () {
const { container } = render(
<BuildFileViewer item={mockVideoItem} index={mockIndex} />
);
expect(container.querySelector(".form-obs-video-image")).not.toBeNull();
expect(container.querySelector(".video-play-button-icon")).not.toBeNull();
expect(container.querySelector(".download-link")).not.toBeNull();
expect(screen.getByAltText(/image/i)).toBeTruthy();
expect(screen.getByText(mockVideoItem.comment)).toBeTruthy();
const provider_info = container.querySelector(".provider-info");
expect(within(provider_info).getByText(/test provider/i)).toBeTruthy();
expect(within(provider_info).getByText(new RegExp(formatDate(mockItem.encounterDateTime)))).toBeTruthy();
});


it("should render BuildFileViewer with all the data with pdf link", function () {
const { container } = render(
<BuildFileViewer item={mockPdfItem} index={mockIndex} />
);
expect(container.querySelector(".pdf-link")).not.toBeNull();
expect(screen.getByText(mockPdfItem.comment)).toBeTruthy();
const provider_info = container.querySelector(".provider-info");
expect(within(provider_info).getByText(/test provider/i)).toBeTruthy();
expect(within(provider_info).getByText(new RegExp(formatDate(mockItem.encounterDateTime)))).toBeTruthy();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import React from "react";
import propTypes from "prop-types";
import { Tile } from "carbon-components-react";
import { BuildFileViewer } from "./BuildFileViewer/BuildFileViewer";
import "./FileViewer.scss";

export const FileViewer = (props) => {
const { members, isHeader = false } = props;
const groupByConceptUuid = members.reduce((acc, member) => {
acc[member.concept.uuid] = acc[member.concept.uuid] || [];
acc[member.concept.uuid].push(member);
return acc;
}, {});

return (
<>
{Object.values(groupByConceptUuid).map((elementList, index) => {
return isHeader ? (
<Tile key={index}>
<div key={index} className="file-section">
<span
className="section-header row-label"
data-testid={`section-label-${index}`}
>
{elementList[0].concept.shortName}
</span>
<span
className="row-value viewer-value-block"
key={`row-value-${index}`}
>
{elementList.map((subItem, index) => (
<BuildFileViewer item={subItem} index={index} />
))}
</span>
</div>
</Tile>
) : (
<>
<div
key={index}
className="row-element"
data-testid={`subItem-${index}`}
>
<div className="row-content">
<div className="row-label">
{elementList[0].concept.shortName}
</div>
<div className="row-value viewer-value-block">
{elementList.map((subItem, index) => (
<BuildFileViewer item={subItem} index={index} />
))}
</div>
</div>
</div>
</>
);
})}
</>
);
};

FileViewer.propTypes = {
members: propTypes.array,
isHeader: propTypes.bool,
};
export default FileViewer;
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
.form-obs-image {
height: 93px;
width: 93px;
border: 1px solid #ccc;

&:hover {
cursor: pointer;
box-shadow: 0 14px 28px rgba(0, 0, 0, 0.25), 0 10px 10px rgba(0, 0, 0, 0.22);
border-color: #eee;
}
}

.form-obs-video-image {
height: 100%;
width: 100%;
}

.viewer-value-block {
display: flex;
width: 100%;
flex-wrap: wrap;
}

.image-viewer {
display: flex;
width: 50%;
padding-bottom: 10px;
}

.video-viewer {
display: flex;
width: 100%;
padding-bottom: 10px;
}

.file-notes-section {
padding: 10px;
width: 85%;
}

.provider-info {
font-size: 12px;
font-weight: bold;
}

.file-section {
display: flex;
}

.download-link{
display: flex;
}

.video-play-button {
position: relative;
height: 93px;
width: 93px;
display: inline-block;

&:hover {
cursor: pointer;
filter: brightness(1.5);
box-shadow: 0 14px 28px rgba(0, 0, 0, 0.25), 0 10px 10px rgba(0, 0, 0, 0.22);
border-color: #eee;
}
}

.video-play-button-icon {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
Loading
Loading