diff --git a/src/components/HeatMap/HeatMap.js b/src/components/HeatMap/HeatMap.js
index a2c1976a..e30a2a0c 100644
--- a/src/components/HeatMap/HeatMap.js
+++ b/src/components/HeatMap/HeatMap.js
@@ -7,29 +7,42 @@ import $ from 'jquery';
import { DocumentFiltersContext, DocumentAnnotationsContext } from '../../contexts/DocumentContext';
-function HeatMap({ pdf }) {
+const HeatMap = ({ pdf }) => {
const lineHeight = 18;
const documentHeight = $('#document-container').height() || 0;
- let scaleFactor = $('#document-container').get(0) === undefined ? 1 : $('#document-container').height() / $('#document-container').get(0).scrollHeight;
+ const scaleFactor = $('#document-container').get(0) === undefined
+ ? 1
+ : $('#document-container').height() / $('#document-container').get(0).scrollHeight;
const minStrokeHeight = 1;
- const offsetTop = $('#document-container').offset() === undefined ? 0 : $('#document-container').offset().top;
- const grandularity = lineHeight * scaleFactor >= minStrokeHeight ? lineHeight : Math.ceil(minStrokeHeight / scaleFactor);
+ const offsetTop = $('#document-container').offset() === undefined
+ ? 0
+ : $('#document-container').offset().top;
+ const grandularity = lineHeight * scaleFactor >= minStrokeHeight
+ ? lineHeight
+ : Math.ceil(minStrokeHeight / scaleFactor);
const [channelAnnotations] = useContext(DocumentAnnotationsContext);
const [documentFilters] = useContext(DocumentFiltersContext);
const n = (Math.ceil($('#document-card-container').height() / grandularity));
- const map = new Array(isNaN(n) ? 0 : n);
+ const map = new Array(Number.isNaN(n) ? 0 : n);
for (const side in channelAnnotations) {
if (channelAnnotations[side] !== null) {
for (const anno of channelAnnotations[side]) {
- if (documentFilters.annotationIds[side] !== null && documentFilters.annotationIds[side].includes(anno._id)) {
+ if (documentFilters.annotationIds[side] !== null
+ && documentFilters.annotationIds[side].includes(anno._id)) {
if (anno.position.height !== undefined) {
let h = anno.position.height;
- // if for some reason the height of this annotation is a negative number we are going to recalculate the value in the loop
+ // if for some reason the height of this annotation is a negative number,
+ // recalculate the value in the loop
if (h < 0) {
- const annotationBeginning = $(`#document-content-container span[annotation-id='${anno._id}'] .annotation-beginning-marker`);
- const annotationEnding = $(`#document-content-container span[annotation-id='${anno._id}'] .annotation-ending-marker`);
- if (annotationBeginning.get(0) !== undefined && annotationEnding.get(0) !== undefined) {
+ const annotationBeginning = $(
+ `#document-content-container span[annotation-id='${anno._id}'] .annotation-beginning-marker`,
+ );
+ const annotationEnding = $(
+ `#document-content-container span[annotation-id='${anno._id}'] .annotation-ending-marker`,
+ );
+ if (annotationBeginning.get(0) !== undefined
+ && annotationEnding.get(0) !== undefined) {
const annotationBeginningPosition = annotationBeginning.offset();
const annotationEndingPosition = annotationEnding.offset();
h = (annotationEndingPosition.top - annotationBeginningPosition.top) + lineHeight;
@@ -37,8 +50,11 @@ function HeatMap({ pdf }) {
h = 0;
}
}
- // now we have to convert the annotations position and height into starting and ending indexs for the map
- let startIndex = Math.floor((anno.position.top - offsetTop) / grandularity);
+ // convert the annotation position and height
+ // into starting and ending indexs for the map
+ let startIndex = Math.floor(
+ (anno.position.top - offsetTop) / grandularity,
+ );
startIndex = startIndex < 0 ? 0 : startIndex;
const endIndex = Math.floor((anno.position.top + h - offsetTop) / grandularity);
for (let i = startIndex; i <= endIndex; i += 1) {
@@ -57,8 +73,21 @@ function HeatMap({ pdf }) {
return (
<>
-
- {map.map((v, i) =>
)}
+
+ {map.map((v, i) => (
+
+ ))}
>
);
-}
+};
export default HeatMap;
diff --git a/src/components/HeatMap/HeatMap.test.js b/src/components/HeatMap/HeatMap.test.js
new file mode 100644
index 00000000..a4b8059a
--- /dev/null
+++ b/src/components/HeatMap/HeatMap.test.js
@@ -0,0 +1,24 @@
+/**
+ * @jest-environment jsdom
+ */
+
+import { render } from '@testing-library/react';
+import HeatMap from './HeatMap';
+import { DocumentFiltersContext, DocumentAnnotationsContext } from '../../contexts/DocumentContext';
+
+test('renders heatmap', async () => {
+ const { getByTestId } = render(
+
+
+
+
+ ,
+ );
+ const heatMap = getByTestId('heat-map');
+ expect(heatMap).toBeInTheDocument();
+});
+
diff --git a/src/components/SemanticField/SemanticField.test.js b/src/components/SemanticField/SemanticField.test.js
new file mode 100644
index 00000000..e1cfefbc
--- /dev/null
+++ b/src/components/SemanticField/SemanticField.test.js
@@ -0,0 +1,20 @@
+/**
+ * @jest-environment jsdom
+ */
+
+import { render } from '@testing-library/react';
+import { Formik } from 'formik';
+import SemanticField from './SemanticField';
+
+test('renders semantic field', async () => {
+ const { getByRole } = render(
+
+
+ ,
+ );
+ const field = getByRole('textbox');
+ expect(field).toBeInTheDocument();
+});
diff --git a/src/components/SlateMediaEmbedElement/SlateMediaEmbedElement.js b/src/components/SlateMediaEmbedElement/SlateMediaEmbedElement.js
index 032eb576..c3c962a7 100644
--- a/src/components/SlateMediaEmbedElement/SlateMediaEmbedElement.js
+++ b/src/components/SlateMediaEmbedElement/SlateMediaEmbedElement.js
@@ -15,6 +15,7 @@ const SlateMediaEmbedElement = ({
title="embed"
src={`${url}`}
frameBorder="0"
+ data-testid="slate-iframe"
/>
diff --git a/src/components/SlateMediaEmbedElement/SlateMediaEmbedElement.test.js b/src/components/SlateMediaEmbedElement/SlateMediaEmbedElement.test.js
new file mode 100644
index 00000000..f68b7e54
--- /dev/null
+++ b/src/components/SlateMediaEmbedElement/SlateMediaEmbedElement.test.js
@@ -0,0 +1,19 @@
+/**
+ * @jest-environment jsdom
+ */
+
+import { render } from '@testing-library/react';
+import { Formik } from 'formik';
+import SlateMediaEmbedElement from './SlateMediaEmbedElement';
+
+test('renders slate media embed element', async () => {
+ const { getByTestId } = render(
+
+
+ ,
+ );
+ const elem = getByTestId('slate-iframe');
+ expect(elem).toBeInTheDocument();
+});
diff --git a/src/pages/documents/[slug]/index.jsx b/src/pages/documents/[slug]/index.jsx
index ae6a282f..20adae30 100644
--- a/src/pages/documents/[slug]/index.jsx
+++ b/src/pages/documents/[slug]/index.jsx
@@ -3,7 +3,7 @@
/* eslint-disable no-underscore-dangle */
/* eslint-disable no-restricted-syntax */
import { useState, useEffect } from 'react';
-import { isMobile } from "react-device-detect"
+import { isMobile } from 'react-device-detect';
import { useSession } from 'next-auth/client';
import $ from 'jquery';
import {
@@ -109,7 +109,8 @@ const DocumentPage = (props) => {
const [annotationChannel1Loaded, setAnnotationChannel1Loaded] = useState(false);
const [annotationChannel2Loaded, setAnnotationChannel2Loaded] = useState(false);
const minDisplayWidth = 1150;
- // if true annotations will displayed in channels otherwise they will be displayed as popovers that show on hover or on click
+ // popovers for mobile
+ // eslint-disable-next-line no-unused-vars
const [displayAnnotationsInChannels, setDisplayAnnotationsInChannels] = useState(!isMobile);
const [scrollToAnnotation, setScrollToAnnotation] = useState(validQuery);
@@ -117,9 +118,9 @@ const DocumentPage = (props) => {
const [showMoreInfoShareModal, setShowMoreInfoShareModal] = useState();
const [session, loading] = useSession();
- // the interesection between the groups that this user is in and the groups the document is shared too
+ // interesection between user's groups and groups the document is shared to
const [groupIntersection, setGroupIntersection] = useState();
- // the people the user can share their annotations with which is generated from the groupIntersection
+ // other users this user can share annotations with, generated from groupIntersection
const [membersIntersection, setMembersIntersection] = useState([]);
@@ -381,25 +382,32 @@ const DocumentPage = (props) => {
});
useEffect(() => {
+ // eslint-disable-next-line no-undef
window.addEventListener('resize', () => {
+ // eslint-disable-next-line no-undef
setDisplayAnnotationsInChannels(window.innerWidth > minDisplayWidth && !isMobile);
});
});
async function getIntersectionOfGroupsAndUsers() {
- // when the session gets loaded in we are going to get the intersection of groups and the users that applies to
- if (session !== undefined && groupIntersection === undefined) { // this means we haven't set it yet
+ // when session loaded, get intersection of groups and the users that applies to
+ if (session && !groupIntersection) {
const userGroupIds = session.user.groups.map((g) => g.id);
const intersection = userGroupIds.filter((id) => document.groups.includes(id));
const intersectionGroups = await Promise.all(intersection.map((id) => getGroupById(id)));
let intersectionMembers = [];
for (let i = 0; i < intersectionGroups.length; i += 1) {
- // filtering out members for this specific group that we have already included in the intersectionMembers array
- const members = intersectionGroups[i].members.filter((m) => !intersectionMembers.some((im) => im.id === m.id));
+ // filtering out members for this specific group
+ // that we have already included in the intersectionMembers array
+ const members = intersectionGroups[i].members
+ // eslint-disable-next-line no-loop-func
+ .filter((m) => !intersectionMembers.some((im) => im.id === m.id));
intersectionMembers = intersectionMembers.concat(members);
}
- // before we set the intersection of members we need to remove the id of the current user session
- setMembersIntersection(intersectionMembers.filter((m) => m.id !== session.user.id).map((m) => ({ ...m, name: FirstNameLastInitial(m.name) })));
+ // remove id of current user session before setting intersection of members
+ setMembersIntersection(intersectionMembers
+ .filter((m) => m.id !== session.user.id)
+ .map((m) => ({ ...m, name: FirstNameLastInitial(m.name) })));
setGroupIntersection(intersectionGroups);
}
}
@@ -418,7 +426,9 @@ const DocumentPage = (props) => {
return (
-
+
{!session && loading && (
@@ -525,11 +535,16 @@ const DocumentPage = (props) => {
Only you can see the annotation
- Share with group(s)
+
+ Share with group(s)
+
- Share this annotation with all members of your group(s) who have access to this document.
+ Share this annotation with all members of
+ your group(s) who have access to this document.
+
+
+ Share with user(s)
- Share with user(s)
Share this annotation with a specific user or users only.