Skip to content

Commit

Permalink
Merge branch 'release/FY24Q4.6.0' into dev-support/APPEALS-59528
Browse files Browse the repository at this point in the history
  • Loading branch information
craigrva authored Sep 30, 2024
2 parents 5fa7358 + ed1f8fc commit a98f8ba
Show file tree
Hide file tree
Showing 29 changed files with 1,402 additions and 153 deletions.
1 change: 1 addition & 0 deletions client/app/components/icons/FilterNoOutlineIcon.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export const FilterNoOutlineIcon = (props) => {
const { color, size, className } = props;

return <svg height={size} viewBox="0 0 12 14" className={className}>
<title >filtered indicator</title>
<g stroke="none" strokeWidth="1" fill="none" fillRule="evenodd">
<g fillRule="nonzero" fill={color}>
<g id="filter-filled-tool-symbol" transform="translate(6.000000, 7.000000)
Expand Down
9 changes: 8 additions & 1 deletion client/app/reader/DecisionReviewer.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ export class DecisionReviewer extends React.PureComponent {
super(props);

this.state = {
isCommentLabelSelected: false
isCommentLabelSelected: false,
zoomLevel: 100
};

this.routedPdfListView.displayName = 'RoutedPdfListView';
Expand Down Expand Up @@ -83,6 +84,10 @@ export class DecisionReviewer extends React.PureComponent {
}
};

updateZoomLevel = (newZoomLevel) => {
this.setState({ zoomLevel: newZoomLevel });
};

routedPdfListView = (props) => {
const { vacolsId } = props.match.params;

Expand Down Expand Up @@ -142,6 +147,8 @@ export class DecisionReviewer extends React.PureComponent {
allDocuments={_.values(this.props.storeDocuments)}
showPdf={this.showPdf(props.history, vacolsId)}
documentPathBase={`/${vacolsId}/documents`}
zoomLevel={this.state.zoomLevel}
onZoomChange={this.updateZoomLevel}
{...props}
/>
</ReaderLoadingScreen>
Expand Down
5 changes: 2 additions & 3 deletions client/app/reader/SideBarCategories.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,7 @@ class SideBarCategories extends PureComponent {

const categoryToggleStates = _.mapValues(
Constants.documentCategories,
(val, key) =>
documents[doc.id][categoryFieldNameOfCategoryName(key)]
(val, key) => documents[doc.id][categoryFieldNameOfCategoryName(key)]
);

return <div className="cf-category-sidebar">
Expand All @@ -58,7 +57,7 @@ class SideBarCategories extends PureComponent {

SideBarCategories.propTypes = {
doc: PropTypes.object,
documents: PropTypes.object,
documents: PropTypes.array,
id: PropTypes.number,
category_medical: PropTypes.bool,
category_procedural: PropTypes.bool,
Expand Down
2 changes: 1 addition & 1 deletion client/app/reader/reducers.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import pdfViewerReducer from './PdfViewer/PdfViewerReducer';
import documentsReducer from './Documents/DocumentsReducer';
import annotationLayerReducer from './AnnotationLayer/AnnotationLayerReducer';

const rootReducer = combineReducers({
export const rootReducer = combineReducers({
caseSelect: caseSelectReducer,
pdf: pdfReducer,
searchActionReducer,
Expand Down
2 changes: 1 addition & 1 deletion client/app/reader/selectors.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { createSelector } from 'reselect';
import { keyBy, memoize, reject, sum, uniqBy, map, mapValues, filter, size, values, some } from 'lodash';

const getFilteredDocIds = (state) => state.documentList.filteredDocIds;
export const getFilteredDocIds = (state) => state.documentList.filteredDocIds;
const getAllDocs = (state) => state.documents;

export const getFilteredDocuments = createSelector(
Expand Down
3 changes: 2 additions & 1 deletion client/app/reader/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export const rotateCoordinates = ({ x, y }, container, rotation) => {
case 180:
rotatedCoords = { x: container.width - x, y: container.height - y };
break;
case 27:
case 270:
rotatedCoords = { x: container.height - y, y: x };
break;
default:
Expand Down Expand Up @@ -80,6 +80,7 @@ export const getPageCoordinatesOfMouseEventPrototype = (event, container, scale,
rotation
);
};

/**
* immutability-helper takes two arguments: an object and a spec for how to change it:
*
Expand Down
79 changes: 52 additions & 27 deletions client/app/readerprototype/DocumentViewer.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,24 +12,23 @@ import { CATEGORIES } from '../reader/analytics';
import { stopPlacingAnnotation } from '../reader/AnnotationLayer/AnnotationActions';
import DeleteModal from './components/Comments/DeleteModal';
import ShareModal from './components/Comments/ShareModal';
import { getNextDocId, getPrevDocId, getRotationDeg, selectedDoc, selectedDocIndex } from './util/documentUtil';
import { ROTATION_DEGREES } from './util/readerConstants';

const ZOOM_LEVEL_MIN = 20;
const ZOOM_LEVEL_MAX = 300;
const ZOOM_INCREMENT = 20;
import { getRotationDeg } from './util/documentUtil';
import { ROTATION_DEGREES, ZOOM_INCREMENT, ZOOM_LEVEL_MAX, ZOOM_LEVEL_MIN } from './util/readerConstants';

const DocumentViewer = (props) => {
const [currentPage, setCurrentPage] = useState(1);
const [numPages, setNumPages] = useState(null);
const [rotateDeg, setRotateDeg] = useState('0deg');
const [showSearchBar, setShowSearchBar] = useState(false);
const [showSideBar, setShowSideBar] = useState(true);
const [zoomLevel, setZoomLevel] = useState(100);
const [disabled, setDisabled] = useState(true);
const [isDocumentLoadError, setIsDocumentLoadError] = useState(false);

const dispatch = useDispatch();

const currentDocumentId = Number(props.match.params.docId);
const doc = props.allDocuments.find((x) => x.id === currentDocumentId);

document.title = `${(doc && doc.type) || ''} | Document Viewer | Caseflow Reader`;

useEffect(() => {
setShowSearchBar(false);
Expand Down Expand Up @@ -59,7 +58,17 @@ const DocumentViewer = (props) => {
return () => window.removeEventListener('keydown', keyHandler);
}, []);

const doc = selectedDoc(props);
useEffect(() => {
const keyHandler = (event) => {
if (event.altKey && event.code === 'KeyM' && !event.shiftKey) {
setShowSideBar(!showSideBar);
}
};

window.addEventListener('keydown', keyHandler);

return () => window.removeEventListener('keydown', keyHandler);
}, [showSideBar]);

const getPageNumFromScrollTop = (event) => {
const { clientHeight, scrollTop, scrollHeight } = event.target;
Expand All @@ -76,54 +85,68 @@ const DocumentViewer = (props) => {
}
};

document.body.style.overflow = 'hidden';
const handleZoomIn = () => {
const newZoomLevel = props.zoomLevel + ZOOM_INCREMENT;

props.onZoomChange(newZoomLevel);
};

const handleZoomOut = () => {
const newZoomLevel = props.zoomLevel - ZOOM_INCREMENT;

props.onZoomChange(newZoomLevel);
};

useEffect(() => {
document.body.style.overflow = 'hidden';

return () => document.body.style.overflow = 'auto';
}, [window.location.pathname]);

return (
<div id="prototype-reader" className="cf-pdf-page-container">
<div id="prototype-reader-main">
<ReaderToolbar
disableZoomIn={zoomLevel === ZOOM_LEVEL_MAX}
disableZoomOut={zoomLevel === ZOOM_LEVEL_MIN}
disableZoomIn={props.zoomLevel === ZOOM_LEVEL_MAX}
disableZoomOut={props.zoomLevel === ZOOM_LEVEL_MIN}
doc={doc}
documentPathBase={props.documentPathBase}
resetZoomLevel={() => setZoomLevel(100)}
resetZoomLevel={() => props.onZoomChange(100)}
rotateDocument={() => setRotateDeg(getRotationDeg(rotateDeg))}
setZoomInLevel={() => setZoomLevel(zoomLevel + ZOOM_INCREMENT)}
setZoomOutLevel={() => setZoomLevel(zoomLevel - ZOOM_INCREMENT)}
setZoomInLevel={handleZoomIn}
setZoomOutLevel={handleZoomOut}
showClaimsFolderNavigation={props.allDocuments.length > 1}
showSearchBar={showSearchBar}
toggleSearchBar={setShowSearchBar}
showSideBar={showSideBar}
toggleSideBar={() => setShowSideBar(true)}
zoomLevel={zoomLevel}
zoomLevel={props.zoomLevel}
/>
{showSearchBar && <ReaderSearchBar />}
<div className="cf-pdf-scroll-view" onScroll={getPageNumFromScrollTop}>
<PdfDocument
currentPage={currentPage}
doc={doc}
isDocumentLoadError={isDocumentLoadError}
rotateDeg={rotateDeg}
setIsDocumentLoadError={setIsDocumentLoadError}
setNumPages={setNumPages}
zoomLevel={zoomLevel}
onLoad={setDisabled}
zoomLevel={props.zoomLevel}
/>
</div>
<ReaderFooter
currentPage={currentPage}
docCount={props.allDocuments.length}
nextDocId={getNextDocId(props)}
docId={doc.id}
isDocumentLoadError={isDocumentLoadError}
numPages={numPages}
prevDocId={getPrevDocId(props)}
setCurrentPage={() => setCurrentPage()}
selectedDocIndex={selectedDocIndex(props)}
showNextDocument={props.showPdf(getNextDocId(props))}
showPreviousDocument={props.showPdf(getPrevDocId(props))}
disablePreviousNext={disabled}
showPdf={props.showPdf}
/>
</div>
{showSideBar && (
<ReaderSidebar
doc={doc}
documents={props.allDocuments}
showSideBar={showSideBar}
toggleSideBar={() => setShowSideBar(false)}
vacolsId={props.match.params.vacolsId}
/>
Expand All @@ -141,7 +164,9 @@ DocumentViewer.propTypes = {
fetchAppealDetails: PropTypes.func,
history: PropTypes.any,
showPdf: PropTypes.func,
match: PropTypes.object
match: PropTypes.object,
zoomLevel: PropTypes.number,
onZoomChange: PropTypes.func
};

export default DocumentViewer;
45 changes: 38 additions & 7 deletions client/app/readerprototype/components/Comments/Layer.jsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import _ from 'lodash';
import noop from 'lodash/noop';
import PropTypes from 'prop-types';
import React, { useEffect, useRef } from 'react';
import { useDispatch, useSelector } from 'react-redux';
Expand All @@ -13,6 +13,7 @@ import {
import { handleSelectCommentIcon } from '../../../reader/PdfViewer/PdfViewerActions';
import { getPageCoordinatesOfMouseEventPrototype } from '../../../reader/utils';
import { annotationPlacement, annotationsForDocumentId, annotationsForDocumentIdAndPageId } from '../../selectors';
import { centerOfPage, iconKeypressOffset } from '../../util/coordinates';
import Icon from './Icon';

// This comment provides the framework for positioning, moving and selecting comment icons.
Expand All @@ -27,7 +28,7 @@ import Icon from './Icon';
// The second is after they've clicked but haven't saved it yet (ie, they still need to type in their comment)
// The third is the display of the comments already saved that were fetched from the db.
const Layer = (props) => {
const { zoomLevel, pageNumber, documentId, rotation, children, dimensions } = props;
const { zoomLevel, pageNumber, documentId, rotation, children, dimensions, isCurrentPage } = props;
const scale = zoomLevel / 100;
const rotationDegrees = Number(rotation.replace('deg', ''));

Expand Down Expand Up @@ -55,8 +56,37 @@ const Layer = (props) => {
}
}

if (event.altKey && event.code === 'KeyC') {
if (isPlacingAnnotation && placingAnnotationIconPageCoords?.pageIndex === pageNumber && [
'ArrowUp',
'ArrowDown',
'ArrowLeft',
'ArrowRight'
].includes(event.key)
) {
event.preventDefault();

dispatch(
showPlaceAnnotationIcon(
pageNumber,
iconKeypressOffset(
placingAnnotationIconPageCoords,
event.key,
rotation
)
)
);
}

if (event.altKey && event.code === 'KeyC' && isCurrentPage) {
dispatch(startPlacingAnnotation(INTERACTION_TYPES.KEYBOARD_SHORTCUT));

const boundingRect = layerRef.current?.getBoundingClientRect();

if (boundingRect) {
const coords = centerOfPage(boundingRect, rotationDegrees);

dispatch(showPlaceAnnotationIcon(pageNumber, coords));
}
}

if (event.altKey && event.code === 'Enter') {
Expand All @@ -78,7 +108,7 @@ const Layer = (props) => {
window.addEventListener('keydown', keyHandler);

return () => window.removeEventListener('keydown', keyHandler);
}, [isPlacingAnnotation, placingAnnotationIconPageCoords]);
}, [isPlacingAnnotation, placingAnnotationIconPageCoords, rotation, isCurrentPage]);

const onPageDragOver = (event) => {
event.preventDefault();
Expand Down Expand Up @@ -199,7 +229,7 @@ const Layer = (props) => {
pageIndex: placingAnnotationIconPageCoords.pageIndex,
}}
comment={{}}
onClick={_.noop}
onClick={noop}
/>
)}
{!isPlacingAnnotation && placedButUnsavedAnnotation && placedButUnsavedAnnotation.page === pageNumber && (
Expand All @@ -208,7 +238,7 @@ const Layer = (props) => {
comment={placedButUnsavedAnnotation}
rotation={-rotationDegrees}
position={{ x: placedButUnsavedAnnotation.x * scale, y: placedButUnsavedAnnotation.y * scale }}
onClick={_.noop}
onClick={noop}
/>
)}
{annotations.map((annotation) => (
Expand All @@ -218,7 +248,7 @@ const Layer = (props) => {
comment={annotation}
rotation={-rotationDegrees}
position={{ x: annotation.x * scale, y: annotation.y * scale }}
onClick={annotation.isPlacingAnnotation ? _.noop : () => onIconClick(annotation)}
onClick={annotation.isPlacingAnnotation ? noop : () => onIconClick(annotation)}
/>
))}
</div>
Expand All @@ -235,6 +265,7 @@ Layer.propTypes = {
rotation: PropTypes.string,
children: PropTypes.element,
dimensions: PropTypes.object,
isCurrentPage: PropTypes.bool
};

export default Layer;
Loading

0 comments on commit a98f8ba

Please sign in to comment.