import {buildForInput} from '../wysiwyg-tinymce/config';
import {el} from "../wysiwyg/utils/dom";
+import commentIcon from "@icons/comment.svg"
+
export class PageComment extends Component {
protected commentId: string;
protected commentContentRef: string;
protected deletedText: string;
protected updatedText: string;
+ protected viewCommentText: string;
protected wysiwygEditor: any = null;
protected wysiwygLanguage: string;
this.commentContentRef = this.$opts.commentContentRef;
this.deletedText = this.$opts.deletedText;
this.updatedText = this.$opts.updatedText;
+ this.viewCommentText = this.$opts.viewCommentText;
// Editor reference and text options
this.wysiwygLanguage = this.$opts.wysiwygLanguage;
const relLeft = bounds.left - refElBounds.left;
const relTop = bounds.top - refElBounds.top;
- // TODO - Extract to class, Use theme color
- const marker = el('div', {
+
+ const marker = el('button', {
+ type: 'button',
+ class: 'content-comment-marker',
+ title: this.viewCommentText,
+ });
+ marker.innerHTML = <string>commentIcon;
+ marker.addEventListener('click', event => {
+ this.showCommentAtMarker(marker);
+ });
+
+ const markerWrap = el('div', {
class: 'content-comment-highlight',
style: `left: ${relLeft}px; top: ${relTop}px; width: ${bounds.width}px; height: ${bounds.height}px;`
- }, ['']);
+ }, [marker]);
refEl.style.position = 'relative';
- refEl.append(marker);
+ refEl.append(markerWrap);
+ }
+
+ protected showCommentAtMarker(marker: HTMLElement): void {
+
+ marker.hidden = true;
+ const readClone = this.container.closest('.comment-branch').cloneNode(true) as HTMLElement;
+ const toRemove = readClone.querySelectorAll('.actions, form');
+ for (const el of toRemove) {
+ el.remove();
+ }
+
+ const close = el('button', {type: 'button'}, ['x']);
+ const jump = el('button', {type: 'button'}, ['Jump to thread']);
+
+ const commentWindow = el('div', {
+ class: 'content-comment-window'
+ }, [
+ el('div', {
+ class: 'content-comment-window-actions',
+ }, [jump, close]),
+ el('div', {
+ class: 'content-comment-window-content',
+ }, [readClone]),
+ ]);
+
+ marker.parentElement.append(commentWindow);
+
+ const closeAction = () => {
+ commentWindow.remove();
+ marker.hidden = false;
+ };
+
+ close.addEventListener('click', closeAction.bind(this));
+
+ jump.addEventListener('click', () => {
+ closeAction();
+ this.container.scrollIntoView({behavior: 'smooth'});
+ const highlightTarget = this.container.querySelector('.header') as HTMLElement;
+ highlightTarget.classList.add('anim-highlight');
+ highlightTarget.addEventListener('animationend', () => highlightTarget.classList.remove('anim-highlight'))
+ });
+
+ // TODO - Position wrapper sensibly
+ // TODO - Movement control?
}
}
opacity: 0.25;
}
}
+.content-comment-window {
+ font-size: vars.$fs-m;
+ line-height: 1.4;
+ position: relative;
+ z-index: 90;
+ pointer-events: all;
+ min-width: min(340px, 80vw);
+ background-color: #FFF;
+ //border: 1px solid var(--color-primary);
+ box-shadow: vars.$bs-hover;
+ border-radius: 4px;
+ overflow: hidden;
+}
+.content-comment-window-actions {
+ background-color: var(--color-primary);
+ color: #FFF;
+ display: flex;
+ align-items: center;
+ justify-content: end;
+}
+.content-comment-window-content {
+ padding: vars.$xs;
+ max-height: 200px;
+ overflow-y: scroll;
+}
+.content-comment-marker {
+ position: absolute;
+ right: -16px;
+ top: -16px;
+ pointer-events: all;
+ width: min(1.5em, 32px);
+ height: min(1.5em, 32px);
+ border-radius: min(calc(1.5em / 2), 32px);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ background-color: var(--color-primary);
+ box-shadow: vars.$bs-hover;
+ color: #FFF;
+ cursor: pointer;
+ z-index: 90;
+ svg {
+ fill: #FFF;
+ width: 80%;
+ }
+}
// Page editor sidebar toolbox
.floating-toolbox {