Handle choosing a color and clicking on the note icon differently
Resolves MS-869 and MS870 #Complete
This commit is contained in:
parent
f69af1e4cf
commit
837fcc81be
|
|
@ -94,5 +94,7 @@ module.exports = {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
'no-unused-vars': 'off',
|
||||||
|
'@typescript-eslint/no-unused-vars': 'error',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -126,9 +126,12 @@ import type { Modal } from '@/plugins/modal.types';
|
||||||
|
|
||||||
import { PAGE_LOAD_TIMEOUT } from '@/consts/navigation.consts';
|
import { PAGE_LOAD_TIMEOUT } from '@/consts/navigation.consts';
|
||||||
|
|
||||||
import { getSelectionHandler } from '@/directives/highlight';
|
import { getSelectionHandler, SelectionHandlerOptions } from '@/helpers/highlight';
|
||||||
import { graphql } from '@/__generated__';
|
import { graphql } from '@/__generated__';
|
||||||
import log from 'loglevel';
|
import log from 'loglevel';
|
||||||
|
import highlightSidebar from '@/helpers/highlight-sidebar';
|
||||||
|
import { doUpdateHighlight } from '@/graphql/mutations';
|
||||||
|
import { AddHighlightArgument } from '@/__generated__/graphql';
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
contentBlock: ExtendedContentBlockNode;
|
contentBlock: ExtendedContentBlockNode;
|
||||||
|
|
@ -255,11 +258,11 @@ graphql(`
|
||||||
selectionLength
|
selectionLength
|
||||||
contentUuid
|
contentUuid
|
||||||
startPosition
|
startPosition
|
||||||
|
color
|
||||||
note {
|
note {
|
||||||
text
|
text
|
||||||
}
|
}
|
||||||
text
|
text
|
||||||
color
|
|
||||||
contentBlock {
|
contentBlock {
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
|
|
@ -312,6 +315,16 @@ const { mutate: doCreateHighlight } = useMutation(
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let selectionHandler: (event: Event) => void;
|
||||||
|
|
||||||
|
const createHighlight = (highlight: AddHighlightArgument) => {
|
||||||
|
return doCreateHighlight({
|
||||||
|
input: {
|
||||||
|
highlight: highlight,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
log.debug('onMounted ContentBlock called');
|
log.debug('onMounted ContentBlock called');
|
||||||
|
|
||||||
|
|
@ -329,17 +342,38 @@ onMounted(() => {
|
||||||
}, PAGE_LOAD_TIMEOUT);
|
}, PAGE_LOAD_TIMEOUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
// add the listener from highlights
|
const options: SelectionHandlerOptions = {
|
||||||
element.addEventListener(
|
el: element,
|
||||||
'mouseup',
|
contentBlock: props.contentBlock,
|
||||||
getSelectionHandler(element, props.contentBlock, (newHighlight) => {
|
onChangeColor: (newHighlight: AddHighlightArgument) => {
|
||||||
doCreateHighlight({
|
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: {
|
input: {
|
||||||
highlight: newHighlight,
|
note: text,
|
||||||
|
id: highlight.id,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
})
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
);
|
);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
selectionHandler = getSelectionHandler(options);
|
||||||
|
// add the listener from highlights
|
||||||
|
element.addEventListener('mouseup', selectionHandler);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -347,8 +381,7 @@ onUnmounted(() => {
|
||||||
const element = contentBlockDiv.value;
|
const element = contentBlockDiv.value;
|
||||||
|
|
||||||
if (element !== null) {
|
if (element !== null) {
|
||||||
console.log('unmounting');
|
element.removeEventListener('mouseup', selectionHandler);
|
||||||
element.removeEventListener('mouseup', getSelectionHandler(element, props.contentBlock));
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@
|
||||||
<section class="highlight-popover__section">
|
<section class="highlight-popover__section">
|
||||||
<note-icon
|
<note-icon
|
||||||
class="highlight-popover__icon"
|
class="highlight-popover__icon"
|
||||||
@click="$emit('confirm')"
|
@click="$emit('note')"
|
||||||
/>
|
/>
|
||||||
</section>
|
</section>
|
||||||
<section class="highlight-popover__section">
|
<section class="highlight-popover__section">
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,7 @@
|
||||||
import { DirectiveBinding } from 'vue';
|
|
||||||
import * as rangy from 'rangy';
|
import * as rangy from 'rangy';
|
||||||
import 'rangy/lib/rangy-textrange';
|
import 'rangy/lib/rangy-textrange';
|
||||||
import log from 'loglevel';
|
import log from 'loglevel';
|
||||||
import Mark from 'mark.js';
|
|
||||||
import { ContentBlockNode } from '@/__generated__/graphql';
|
import { ContentBlockNode } from '@/__generated__/graphql';
|
||||||
import ContentBlock from '@/components/ContentBlock.vue';
|
|
||||||
import popover from '@/helpers/popover';
|
import popover from '@/helpers/popover';
|
||||||
|
|
||||||
// todo: we need to get the following information for a highlight:
|
// todo: we need to get the following information for a highlight:
|
||||||
|
|
@ -119,8 +116,16 @@ const getSiblings = (element: HTMLElement): Element[] => {
|
||||||
return children;
|
return children;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export interface SelectionHandlerOptions {
|
||||||
|
el: HTMLElement;
|
||||||
|
contentBlock: ContentBlockNode;
|
||||||
|
onChangeColor?: (highlight: any) => void;
|
||||||
|
onCreateNote?: (highlight: any) => void;
|
||||||
|
}
|
||||||
|
|
||||||
export const getSelectionHandler =
|
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) => {
|
(_e: Event) => {
|
||||||
const rect = el.getBoundingClientRect();
|
const rect = el.getBoundingClientRect();
|
||||||
if (isInsideViewport(rect.top) || isInsideViewport(rect.bottom)) {
|
if (isInsideViewport(rect.top) || isInsideViewport(rect.bottom)) {
|
||||||
|
|
@ -167,24 +172,25 @@ export const getSelectionHandler =
|
||||||
const positionOfContentBlock = el.getBoundingClientRect();
|
const positionOfContentBlock = el.getBoundingClientRect();
|
||||||
const positionOfSelection = startAncestor?.getBoundingClientRect();
|
const positionOfSelection = startAncestor?.getBoundingClientRect();
|
||||||
const offsetTop = positionOfSelection.top - positionOfContentBlock.top;
|
const offsetTop = positionOfSelection.top - positionOfContentBlock.top;
|
||||||
popover
|
const onChooseColor = (color: string) => {
|
||||||
.show({
|
|
||||||
wrapper: el,
|
|
||||||
offsetTop,
|
|
||||||
onChooseColor: (color: string) => {
|
|
||||||
console.log('chosenColor', color);
|
console.log('chosenColor', color);
|
||||||
highlightedText.color = color;
|
highlightedText.color = color;
|
||||||
onUpdateHighlight(highlightedText);
|
if (onChangeColor) {
|
||||||
},
|
onChangeColor(highlightedText);
|
||||||
})
|
}
|
||||||
.then(() => {
|
};
|
||||||
console.log('confirmed here');
|
const onNote = () => {
|
||||||
})
|
highlightedText.color = 'alpha';
|
||||||
.catch(() => {
|
if (onCreateNote) {
|
||||||
console.log('canceled');
|
onCreateNote(highlightedText);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
popover.show({
|
||||||
|
wrapper: el,
|
||||||
|
offsetTop,
|
||||||
|
onChooseColor,
|
||||||
|
onNote,
|
||||||
});
|
});
|
||||||
// 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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -9,10 +9,11 @@ interface Options {
|
||||||
onChooseColor: (color: string) => void;
|
onChooseColor: (color: string) => void;
|
||||||
// we don't use the id as a param here, because the calling component knows already which entity it is
|
// we don't use the id as a param here, because the calling component knows already which entity it is
|
||||||
onDelete?: () => void;
|
onDelete?: () => void;
|
||||||
|
onNote?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
show({ wrapper, offsetTop, onChooseColor, onDelete }: Options) {
|
show({ wrapper, offsetTop, onChooseColor, onDelete, onNote }: Options) {
|
||||||
const mountEl = document.createElement('div');
|
const mountEl = document.createElement('div');
|
||||||
wrapper.appendChild(mountEl);
|
wrapper.appendChild(mountEl);
|
||||||
|
|
||||||
|
|
@ -46,6 +47,11 @@ export default {
|
||||||
cleanUp();
|
cleanUp();
|
||||||
_resolve();
|
_resolve();
|
||||||
},
|
},
|
||||||
|
onNote() {
|
||||||
|
if (onNote) {
|
||||||
|
onNote();
|
||||||
|
}
|
||||||
|
},
|
||||||
onClose() {
|
onClose() {
|
||||||
cleanUp();
|
cleanUp();
|
||||||
_reject();
|
_reject();
|
||||||
|
|
@ -63,7 +69,7 @@ export default {
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
document.addEventListener('click', clickOutsideElementListener);
|
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;
|
return promise;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue