1
0
mirror of https://github.com/BookStackApp/BookStack.git synced 2025-06-08 15:21:56 +03:00

Comments: Addressed a range of edge cases and ux issues for references

Handles only display and handling references when they're in the active
tab, while handling proper removal when made not visible.
This commit is contained in:
Dan Brown 2025-05-01 16:33:42 +01:00
parent e7dcc2dcdf
commit 15c79c38db
No known key found for this signature in database
GPG Key ID: 46D9F943C24A2EF9
3 changed files with 37 additions and 8 deletions

View File

@ -3,7 +3,7 @@ import {findTargetNodeAndOffset, hashElement} from "../services/dom";
import {el} from "../wysiwyg/utils/dom";
import commentIcon from "@icons/comment.svg";
import closeIcon from "@icons/close.svg";
import {scrollAndHighlightElement} from "../services/util";
import {debounce, scrollAndHighlightElement} from "../services/util";
/**
* Track the close function for the current open marker so it can be closed
@ -29,7 +29,7 @@ export class PageCommentReference extends Component {
// Show within page display area if seen
const pageContentArea = document.querySelector('.page-content');
if (pageContentArea instanceof HTMLElement) {
if (pageContentArea instanceof HTMLElement && this.link.checkVisibility()) {
this.updateMarker(pageContentArea);
}
@ -43,6 +43,21 @@ export class PageCommentReference extends Component {
this.hideMarker();
}
});
// Handle comments tab changes to hide/show markers & indicators
window.addEventListener('tabs-change', event => {
const sectionId = (event as {detail: {showing: string}}).detail.showing;
if (!sectionId.startsWith('comment-tab-panel') || !(pageContentArea instanceof HTMLElement)) {
return;
}
const panel = document.getElementById(sectionId);
if (panel?.contains(this.link)) {
this.updateMarker(pageContentArea);
} else {
this.hideMarker();
}
});
}
protected showForEditor() {
@ -111,9 +126,10 @@ export class PageCommentReference extends Component {
scrollAndHighlightElement(refEl);
});
window.addEventListener('resize', () => {
const debouncedReposition = debounce(() => {
this.positionMarker(refEl, refRange);
});
}, 50, false).bind(this);
window.addEventListener('resize', debouncedReposition);
}
protected positionMarker(targetEl: HTMLElement, range: string) {
@ -145,12 +161,13 @@ export class PageCommentReference extends Component {
this.markerWrap.style.height = `${targetBounds.height}px`;
}
protected hideMarker() {
public hideMarker() {
// Hide marker and close existing marker windows
if (openMarkerClose) {
openMarkerClose();
}
this.markerWrap?.remove();
this.markerWrap = null;
}
protected showCommentAtMarker(marker: HTMLElement): void {

View File

@ -1,6 +1,7 @@
import {Component} from './component';
import {getLoading, htmlToDom} from '../services/dom.ts';
import {buildForInput} from '../wysiwyg-tinymce/config';
import {PageCommentReference} from "./page-comment-reference";
export class PageComment extends Component {
@ -142,7 +143,13 @@ export class PageComment extends Component {
const response = await window.$http.put(`/comment/${this.commentId}/${action}`);
window.$events.success(this.archiveText);
this.$emit(action, {new_thread_dom: htmlToDom(response.data as string)});
this.container.closest('.comment-branch')?.remove();
const branch = this.container.closest('.comment-branch') as HTMLElement;
const references = window.$components.allWithinElement<PageCommentReference>(branch, 'page-comment-reference');
for (const reference of references) {
reference.hideMarker();
}
branch.remove();
}
protected showLoading(): HTMLElement {

View File

@ -139,8 +139,8 @@ export class ComponentStore {
/**
* Get all the components of the given name.
*/
public get(name: string): Component[] {
return this.components[name] || [];
public get<T extends Component>(name: string): T[] {
return (this.components[name] || []) as T[];
}
/**
@ -150,4 +150,9 @@ export class ComponentStore {
const elComponents = this.elementComponentMap.get(element) || {};
return elComponents[name] || null;
}
public allWithinElement<T extends Component>(element: HTMLElement, name: string): T[] {
const components = this.get<T>(name);
return components.filter(c => element.contains(c.$el));
}
}