Handle choosing a color and clicking on the note icon differently

Resolves MS-869 and MS870 #Complete
This commit is contained in:
Ramon Wenger 2024-02-01 16:31:52 +01:00
parent f69af1e4cf
commit 837fcc81be
5 changed files with 86 additions and 39 deletions

View File

@ -94,5 +94,7 @@ module.exports = {
],
},
],
'no-unused-vars': 'off',
'@typescript-eslint/no-unused-vars': 'error',
},
};

View File

@ -126,9 +126,12 @@ import type { Modal } from '@/plugins/modal.types';
import { PAGE_LOAD_TIMEOUT } from '@/consts/navigation.consts';
import { getSelectionHandler } from '@/directives/highlight';
import { getSelectionHandler, SelectionHandlerOptions } from '@/helpers/highlight';
import { graphql } from '@/__generated__';
import log from 'loglevel';
import highlightSidebar from '@/helpers/highlight-sidebar';
import { doUpdateHighlight } from '@/graphql/mutations';
import { AddHighlightArgument } from '@/__generated__/graphql';
export interface Props {
contentBlock: ExtendedContentBlockNode;
@ -255,11 +258,11 @@ graphql(`
selectionLength
contentUuid
startPosition
color
note {
text
}
text
color
contentBlock {
id
}
@ -312,6 +315,16 @@ const { mutate: doCreateHighlight } = useMutation(
})
);
let selectionHandler: (event: Event) => void;
const createHighlight = (highlight: AddHighlightArgument) => {
return doCreateHighlight({
input: {
highlight: highlight,
},
});
};
onMounted(() => {
log.debug('onMounted ContentBlock called');
@ -329,17 +342,38 @@ onMounted(() => {
}, PAGE_LOAD_TIMEOUT);
}
const options: SelectionHandlerOptions = {
el: element,
contentBlock: props.contentBlock,
onChangeColor: (newHighlight: AddHighlightArgument) => {
createHighlight(newHighlight);
},
onCreateNote: (newHighlight: AddHighlightArgument) => {
// we also open the sidebar when clicking on the note icon
createHighlight(newHighlight).then(
({
data: {
addHighlight: { highlight },
},
}) => {
highlightSidebar.open({
highlight,
onUpdateText: (text: string) => {
doUpdateHighlight({
input: {
note: text,
id: highlight.id,
},
});
},
});
}
);
},
};
selectionHandler = getSelectionHandler(options);
// add the listener from highlights
element.addEventListener(
'mouseup',
getSelectionHandler(element, props.contentBlock, (newHighlight) => {
doCreateHighlight({
input: {
highlight: newHighlight,
},
});
})
);
element.addEventListener('mouseup', selectionHandler);
}
});
@ -347,8 +381,7 @@ onUnmounted(() => {
const element = contentBlockDiv.value;
if (element !== null) {
console.log('unmounting');
element.removeEventListener('mouseup', getSelectionHandler(element, props.contentBlock));
element.removeEventListener('mouseup', selectionHandler);
}
});

View File

@ -17,7 +17,7 @@
<section class="highlight-popover__section">
<note-icon
class="highlight-popover__icon"
@click="$emit('confirm')"
@click="$emit('note')"
/>
</section>
<section class="highlight-popover__section">

View File

@ -1,10 +1,7 @@
import { DirectiveBinding } from 'vue';
import * as rangy from 'rangy';
import 'rangy/lib/rangy-textrange';
import log from 'loglevel';
import Mark from 'mark.js';
import { ContentBlockNode } from '@/__generated__/graphql';
import ContentBlock from '@/components/ContentBlock.vue';
import popover from '@/helpers/popover';
// todo: we need to get the following information for a highlight:
@ -119,8 +116,16 @@ const getSiblings = (element: HTMLElement): Element[] => {
return children;
};
export interface SelectionHandlerOptions {
el: HTMLElement;
contentBlock: ContentBlockNode;
onChangeColor?: (highlight: any) => void;
onCreateNote?: (highlight: any) => void;
}
export const getSelectionHandler =
(el: HTMLElement, contentBlock: ContentBlockNode, onUpdateHighlight: (highlight: any) => void = () => {}) =>
({ el, contentBlock, onChangeColor, onCreateNote }: SelectionHandlerOptions) =>
// (el: HTMLElement, contentBlock: ContentBlockNode, onUpdateHighlight: (highlight: any) => void = () => {}) =>
(_e: Event) => {
const rect = el.getBoundingClientRect();
if (isInsideViewport(rect.top) || isInsideViewport(rect.bottom)) {
@ -167,24 +172,25 @@ export const getSelectionHandler =
const positionOfContentBlock = el.getBoundingClientRect();
const positionOfSelection = startAncestor?.getBoundingClientRect();
const offsetTop = positionOfSelection.top - positionOfContentBlock.top;
popover
.show({
wrapper: el,
offsetTop,
onChooseColor: (color: string) => {
console.log('chosenColor', color);
highlightedText.color = color;
onUpdateHighlight(highlightedText);
},
})
.then(() => {
console.log('confirmed here');
})
.catch(() => {
console.log('canceled');
});
// todo: how do we save this? maybe we need to move away from the directive and do this inside the mounted
// and unmounted hooks of the ContentBlock
const onChooseColor = (color: string) => {
console.log('chosenColor', color);
highlightedText.color = color;
if (onChangeColor) {
onChangeColor(highlightedText);
}
};
const onNote = () => {
highlightedText.color = 'alpha';
if (onCreateNote) {
onCreateNote(highlightedText);
}
};
popover.show({
wrapper: el,
offsetTop,
onChooseColor,
onNote,
});
}
}
}

View File

@ -9,10 +9,11 @@ interface Options {
onChooseColor: (color: string) => void;
// we don't use the id as a param here, because the calling component knows already which entity it is
onDelete?: () => void;
onNote?: () => void;
}
export default {
show({ wrapper, offsetTop, onChooseColor, onDelete }: Options) {
show({ wrapper, offsetTop, onChooseColor, onDelete, onNote }: Options) {
const mountEl = document.createElement('div');
wrapper.appendChild(mountEl);
@ -46,6 +47,11 @@ export default {
cleanUp();
_resolve();
},
onNote() {
if (onNote) {
onNote();
}
},
onClose() {
cleanUp();
_reject();
@ -63,7 +69,7 @@ export default {
setTimeout(() => {
document.addEventListener('click', clickOutsideElementListener);
}, 1); // do not triger ont the same event that created the popover
}, 1); // do not trigger on the same event that created the popover
return promise;
},
};