Skip to content

Commit

Permalink
Add sharetype bulk
Browse files Browse the repository at this point in the history
  • Loading branch information
arcuo committed May 9, 2023
1 parent 1227f29 commit c8a0465
Show file tree
Hide file tree
Showing 8 changed files with 211 additions and 81 deletions.
1 change: 1 addition & 0 deletions i18n/translation-en.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
"showMoreResults": "Show more results",
"sign": "Sign",
"style": "Style",
"shareType": "Set share type",
"submit": "Submit",
"zoom": "Zoom",
"zoomIn": "Zoom in",
Expand Down
60 changes: 2 additions & 58 deletions src/components/NoteShareType/NoteShareType.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import useOnClickOutside from 'hooks/useOnClickOutside';
import DataElementWrapper from 'components/DataElementWrapper';
import ShareTypes from 'constants/shareTypes';
import ShareTypeIcon from '../NoteShareType/ShareTypeIcon';
import NoteShareTypeDialog from './NoteShareTypeDialog';

const propTypes = {
annotation: PropTypes.object.isRequired,
Expand Down Expand Up @@ -58,8 +59,6 @@ function NoteShareType(props) {
onClose();
});

const preventAutoClose = (e) => e.stopPropagation();

const handleStateChange = useCallback((newValue) => {
// CUSTOM WISEFLOW: Set custom data value called sharetype and trigger annotationChanged event

Expand All @@ -84,62 +83,7 @@ function NoteShareType(props) {
>
<button className="share-type-icon-button" onClick={togglePopup}><ShareTypeIcon shareType={shareType} label={annotationTooltip} /></button>

<dialog
ref={dialogRef}
style={style}
className={classNames('note-share-type-dialog')}
onKeyDown={(e) => {
if (e.key === 'Escape') {
onClose();
}
}}
>
<div className="note-share-type-popup" onClick={preventAutoClose}>
<DataElementWrapper
tabbable
dataElement="notePopupStateAssessor"
type="button"
className={classNames('note-sharetype-option', { selected: shareType === ShareTypes.ASSESSORS })}
onClick={() => handleStateChange(ShareTypes.ASSESSORS)}
>
<ShareTypeIcon shareType={ShareTypes.ASSESSORS} />
{t('option.state.assessors')}
</DataElementWrapper>

<DataElementWrapper
tabbable
dataElement="notePopupStateParticipants"
type="button"
className={classNames('note-sharetype-option', { selected: shareType === ShareTypes.PARTICIPANTS })}
onClick={() => handleStateChange(ShareTypes.PARTICIPANTS)}
>
<ShareTypeIcon shareType={ShareTypes.PARTICIPANTS} />
{t('option.state.participants')}
</DataElementWrapper>

<DataElementWrapper
tabbable
dataElement="notePopupStateAll"
type="button"
className={classNames('note-sharetype-option', { selected: shareType === ShareTypes.ALL })}
onClick={() => handleStateChange(ShareTypes.ALL)}
>
<ShareTypeIcon shareType={ShareTypes.ALL} />
{t('option.state.all')}
</DataElementWrapper>

<DataElementWrapper
tabbable
dataElement="notePopupStateAssessors"
type="button"
className={classNames('note-sharetype-option', { selected: shareType === ShareTypes.NONE })}
onClick={() => handleStateChange(ShareTypes.NONE)}
>
<ShareTypeIcon shareType={ShareTypes.NONE} />
{t('option.state.none')}
</DataElementWrapper>
</div>
</dialog>
<NoteShareTypeDialog onClose={onClose} ref={dialogRef} positionStyle={style} onSelect={handleStateChange} />
</DataElementWrapper>
);
}
Expand Down
87 changes: 87 additions & 0 deletions src/components/NoteShareType/NoteShareTypeDialog.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import { useTranslation } from 'react-i18next';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import React, { forwardRef } from 'react';

import ShareTypes from 'constants/shareTypes';
import DataElementWrapper from 'components/DataElementWrapper';
import ShareTypeIcon from '../NoteShareType/ShareTypeIcon';

import './NoteShareType.scss';

const propTypes = {
onClose: PropTypes.func,
onSelect: PropTypes.func,
positionStyle: PropTypes.object,
selectedShareType: PropTypes.string,
};

const NoteShareTypeDialog = forwardRef(({ onClose, onSelect, positionStyle, selectedShareType }, dialogRef) => {
const [t] = useTranslation();

const preventAutoClose = (e) => e.stopPropagation();

return (
<dialog
ref={dialogRef}
style={positionStyle}
className={classNames('note-share-type-dialog')}
onKeyDown={(e) => {
if (e.key === 'Escape') {
onClose();
}
}}
>
<div className="note-share-type-popup" onClick={preventAutoClose}>
<DataElementWrapper
tabbable
dataElement="notePopupStateAssessor"
type="button"
className={classNames('note-sharetype-option', { selected: selectedShareType === ShareTypes.ASSESSORS })}
onClick={() => onSelect(ShareTypes.ASSESSORS)}
>
<ShareTypeIcon shareType={ShareTypes.ASSESSORS} />
{t('option.state.assessors')}
</DataElementWrapper>

<DataElementWrapper
tabbable
dataElement="notePopupStateParticipants"
type="button"
className={classNames('note-sharetype-option', { selected: selectedShareType === ShareTypes.PARTICIPANTS })}
onClick={() => onSelect(ShareTypes.PARTICIPANTS)}
>
<ShareTypeIcon shareType={ShareTypes.PARTICIPANTS} />
{t('option.state.participants')}
</DataElementWrapper>

<DataElementWrapper
tabbable
dataElement="notePopupStateAll"
type="button"
className={classNames('note-sharetype-option', { selected: selectedShareType === ShareTypes.ALL })}
onClick={() => onSelect(ShareTypes.ALL)}
>
<ShareTypeIcon shareType={ShareTypes.ALL} />
{t('option.state.all')}
</DataElementWrapper>

<DataElementWrapper
tabbable
dataElement="notePopupStateAssessors"
type="button"
className={classNames('note-sharetype-option', { selected: selectedShareType === ShareTypes.NONE })}
onClick={() => onSelect(ShareTypes.NONE)}
>
<ShareTypeIcon shareType={ShareTypes.NONE} />
{t('option.state.none')}
</DataElementWrapper>
</div>
</dialog>
);
});

NoteShareTypeDialog.displayName = 'NoteShareTypeDialog';
NoteShareTypeDialog.propTypes = propTypes;

export default NoteShareTypeDialog;
91 changes: 91 additions & 0 deletions src/components/NoteShareType/NoteShareTypeMultiControl.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import React, { useEffect, useState } from 'react';
import classNames from 'classnames';
import { useTranslation } from 'react-i18next';

import useOverflowContainer from 'hooks/useOverflowContainer';
import useOnClickOutside from 'hooks/useOnClickOutside';

import DataElements from 'constants/dataElement';
import NoteShareTypeDialog from './NoteShareTypeDialog';
import ShareTypeIcon from '../NoteShareType/ShareTypeIcon';

import { getAnnotationShareType, setAnnotationShareType } from 'src/helpers/annotationShareType';
import getAnnotationManager from 'src/core/getAnnotationManager';

import './NoteShareType.scss';

/**
* Multi control button and popup menu
* @param {{
* multiSelectedAnnotations: Array<Annotation>,
* }} props
*/
const NoteShareTypeMultiControl = ({ multiSelectedAnnotations }) => {
const [t] = useTranslation();
const [dialogIsOpen, setDialogIsOpen] = useState(false);
const { popupMenuRef: dialogRef, style } = useOverflowContainer(dialogIsOpen, { defaultLocation: 'top' });
const [collectiveShareType, setCollectiveShareType] = useState();

useEffect(() => {
const shareTypes = new Set(multiSelectedAnnotations.map((annotation) => getAnnotationShareType(annotation)));
if (shareTypes.size === 1) {
setCollectiveShareType(shareTypes.values().next().value);
} else {
setCollectiveShareType(undefined);
}
}, [multiSelectedAnnotations]);

const onClose = () => {
dialogRef.current?.close();
setDialogIsOpen(false);
};

const onOpen = () => {
dialogRef.current?.show();
setDialogIsOpen(true);
};

const togglePopup = (e) => {
e.stopPropagation();
if (dialogIsOpen) {
onClose();
} else {
onOpen();
}
};

useOnClickOutside(dialogRef, () => {
onClose();
});

const handleSelect = (shareType) => {

multiSelectedAnnotations.forEach((annotation) => {
setAnnotationShareType(annotation, shareType);
});

getAnnotationManager().trigger('annotationChanged', [multiSelectedAnnotations, 'modify', {}]);
setCollectiveShareType(shareType);
onClose();
};

return (
<div style={{ position: 'relative', display: 'flex' }}>
<button
style={{ padding: '0 3px' }}
dataElement={DataElements.NOTE_MULTI_SHARE_TYPE_BUTTON}
onClick={togglePopup}
className={classNames('share-type-icon-button', {
active: dialogIsOpen,
})}
disabled={!multiSelectedAnnotations.length}
>
<ShareTypeIcon shareType={collectiveShareType} label={t('action.shareType')} />
</button>

<NoteShareTypeDialog onClose={onClose} selectedShareType={collectiveShareType} ref={dialogRef} positionStyle={style} onSelect={handleSelect} />
</div >
);
};

export default NoteShareTypeMultiControl;
14 changes: 8 additions & 6 deletions src/components/NoteShareType/ShareTypeIcon.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,24 @@
import React, { useRef } from 'react';
import PropTypes from 'prop-types';

import { ShareTypeColors } from 'constants/shareTypes';
import ShareTypes, { ShareTypeColors } from 'constants/shareTypes';
import './ShareTypeIcon.scss';
import Tooltip from '../Tooltip';

const propTypes = {
shareType: PropTypes.string, // in ["ASSESSORS", "PARTICIPANTS", "ALL", "NONE"]
label: PropTypes.string,
label: PropTypes.string.isRequired,
};

function ShareTypeIcon(props) {
const shareTypeColor = ShareTypeColors[props.shareType];
const { shareType, label } = props;
const shareTypeColor = shareType ? ShareTypeColors[shareType] : undefined;
const empty = !shareTypeColor;
const iconRef = useRef();
return (
<Tooltip ref={iconRef} translatedContent={props.label} showOnKeyboardFocus hideOnClick>
<div ref={iconRef} className="share-type-icon" aria-label={props.label}>
<div className="share-type-icon-inner" style={{ backgroundColor: shareTypeColor }} />
<Tooltip ref={iconRef} translatedContent={label} showOnKeyboardFocus hideOnClick>
<div ref={iconRef} className="share-type-icon" aria-label={label}>
<div className="share-type-icon-inner" style={{ background: empty ? 'transparent' : shareTypeColor, border: empty ? `2px solid ${ShareTypeColors[ShareTypes.NONE]}` : undefined }} />
</div>
</Tooltip>
);
Expand Down
37 changes: 20 additions & 17 deletions src/components/NotesPanel/MultiSelectControls.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import classNames from 'classnames';
import core from 'core';

import './MultiSelectControls.scss';
import NoteShareTypeMultiControl from '../NoteShareType/NoteShareTypeMultiControl';

const propTypes = {
showMultiReply: PropTypes.bool.isRequired,
Expand Down Expand Up @@ -137,33 +138,33 @@ const MultiSelectControls = ({
setShowMultiState(false);
};

if (showMultiReply) {
return (
<NoteContext.Provider value={{
resize: () => {},
}}>
<ReplyAreaMultiSelect
annotations={getParentAnnotations(multiSelectedAnnotations)}
onSubmit={() => setShowMultiReply(false)}
onClose={() => setShowMultiReply(false)}
/>
</NoteContext.Provider>
);
}
// if (showMultiReply) {
// return (
// <NoteContext.Provider value={{
// resize: () => {},
// }}>
// <ReplyAreaMultiSelect
// annotations={getParentAnnotations(multiSelectedAnnotations)}
// onSubmit={() => setShowMultiReply(false)}
// onClose={() => setShowMultiReply(false)}
// />
// </NoteContext.Provider>
// );
// }

return (
<div className="multi-select-footer">
<div className="buttons-container">
<Button
{/* <Button
dataElement={DataElements.NOTE_MULTI_REPLY_BUTTON}
disabled={multiSelectedAnnotations.length === 0}
img="icon-header-chat-line"
onClick={() => {
setShowMultiReply(true);
}}
title="action.comment"
/>
<Button
/> */}
{/* <Button
dataElement={DataElements.NOTE_MULTI_STATE_BUTTON}
className={classNames({
active: showMultiState,
Expand All @@ -186,7 +187,9 @@ const MultiSelectControls = ({
onClose={() => {
setShowMultiState(false);
}}
/>}
/>} */}

<NoteShareTypeMultiControl multiSelectedAnnotations={modifiableMultiSelectAnnotations} />
<Button
dataElement={DataElements.NOTE_MULTI_STYLE_BUTTON}
img="icon-menu-style-line"
Expand Down
1 change: 1 addition & 0 deletions src/constants/dataElement.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ const DataElements = {
NOTE_MULTI_SELECT_MODE_BUTTON: 'multiSelectModeButton',
NOTE_MULTI_REPLY_BUTTON: 'multiReplyButton',
NOTE_MULTI_STATE_BUTTON: 'multiStateButton',
NOTE_MULTI_SHARE_TYPE_BUTTON: 'multiShareTypeButton',
NOTE_MULTI_STYLE_BUTTON: 'multiStyleButton',
NOTE_MULTI_GROUP_BUTTON: 'multiGroupButton',
NOTE_MULTI_UNGROUP_BUTTON: 'multiUngroupButton',
Expand Down
1 change: 1 addition & 0 deletions src/helpers/annotationShareType.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const getAnnotationShareType = (annot) => {
* @returns {Annotation} annot with share type set
*/
const setAnnotationShareType = (annot, shareType) => {
console.log('annot:', annot);
annot.setCustomData('shareType', shareType);
return annot;
};
Expand Down

0 comments on commit c8a0465

Please sign in to comment.