Comments: Moved to tab UI, Converted tabs component to ts
Some checks failed
analyse-php / build (push) Waiting to run
lint-php / build (push) Waiting to run
test-js / build (push) Waiting to run
test-migrations / build (8.3) (push) Waiting to run
test-migrations / build (8.4) (push) Waiting to run
test-migrations / build (8.2) (push) Waiting to run
test-php / build (8.2) (push) Waiting to run
test-php / build (8.3) (push) Waiting to run
test-php / build (8.4) (push) Waiting to run
lint-js / build (push) Has been cancelled

This commit is contained in:
Dan Brown
2025-04-30 17:42:09 +01:00
parent 099f6104d0
commit e7dcc2dcdf
8 changed files with 117 additions and 55 deletions

View File

@ -140,8 +140,8 @@ export class PageComment extends Component {
const action = isArchived ? 'unarchive' : 'archive';
const response = await window.$http.put(`/comment/${this.commentId}/${action}`);
this.$emit(action, {new_thread_dom: htmlToDom(response.data as string)});
window.$events.success(this.archiveText);
this.$emit(action, {new_thread_dom: htmlToDom(response.data as string)});
this.container.closest('.comment-branch')?.remove();
}

View File

@ -1,6 +1,7 @@
import {Component} from './component';
import {getLoading, htmlToDom} from '../services/dom.ts';
import {buildForInput} from '../wysiwyg-tinymce/config';
import {Tabs} from "./tabs";
export interface CommentReplyEvent extends Event {
detail: {
@ -21,7 +22,8 @@ export class PageComments extends Component {
private pageId: number;
private container: HTMLElement;
private commentCountBar: HTMLElement;
private commentsTitle: HTMLElement;
private activeTab: HTMLElement;
private archivedTab: HTMLElement;
private addButtonContainer: HTMLElement;
private archiveContainer: HTMLElement;
private replyToRow: HTMLElement;
@ -37,6 +39,7 @@ export class PageComments extends Component {
private wysiwygEditor: any = null;
private createdText: string;
private countText: string;
private archivedCountText: string;
private parentId: number | null = null;
private contentReference: string = '';
private formReplyText: string = '';
@ -48,7 +51,8 @@ export class PageComments extends Component {
// Element references
this.container = this.$refs.commentContainer;
this.commentCountBar = this.$refs.commentCountBar;
this.commentsTitle = this.$refs.commentsTitle;
this.activeTab = this.$refs.activeTab;
this.archivedTab = this.$refs.archivedTab;
this.addButtonContainer = this.$refs.addButtonContainer;
this.archiveContainer = this.$refs.archiveContainer;
this.replyToRow = this.$refs.replyToRow;
@ -67,6 +71,7 @@ export class PageComments extends Component {
// Translations
this.createdText = this.$opts.createdText;
this.countText = this.$opts.countText;
this.archivedCountText = this.$opts.archivedCountText;
this.formReplyText = this.formReplyLink?.textContent || '';
@ -85,10 +90,12 @@ export class PageComments extends Component {
this.elem.addEventListener('page-comment-archive', (event: ArchiveEvent) => {
this.archiveContainer.append(event.detail.new_thread_dom);
setTimeout(() => this.updateCount(), 1);
});
this.elem.addEventListener('page-comment-unarchive', (event: ArchiveEvent) => {
this.container.append(event.detail.new_thread_dom)
this.container.append(event.detail.new_thread_dom);
setTimeout(() => this.updateCount(), 1);
});
if (this.form) {
@ -136,8 +143,10 @@ export class PageComments extends Component {
}
protected updateCount(): void {
const count = this.getCommentCount();
this.commentsTitle.textContent = window.$trans.choice(this.countText, count);
const activeCount = this.getActiveThreadCount();
this.activeTab.textContent = window.$trans.choice(this.countText, activeCount);
const archivedCount = this.getArchivedThreadCount();
this.archivedTab.textContent = window.$trans.choice(this.archivedCountText, archivedCount);
}
protected resetForm(): void {
@ -155,12 +164,18 @@ export class PageComments extends Component {
this.addButtonContainer.toggleAttribute('hidden', true);
this.formContainer.scrollIntoView({behavior: 'smooth', block: 'nearest'});
this.loadEditor();
// Ensure the active comments tab is displaying
const tabs = window.$components.firstOnElement(this.elem, 'tabs');
if (tabs instanceof Tabs) {
tabs.show('comment-tab-panel-active');
}
}
protected hideForm(): void {
this.resetForm();
this.formContainer.toggleAttribute('hidden', true);
if (this.getCommentCount() > 0) {
if (this.getActiveThreadCount() > 0) {
this.elem.append(this.addButtonContainer);
} else {
this.commentCountBar.append(this.addButtonContainer);
@ -198,8 +213,12 @@ export class PageComments extends Component {
}
}
protected getCommentCount(): number {
return this.container.querySelectorAll('[component="page-comment"]').length;
protected getActiveThreadCount(): number {
return this.container.querySelectorAll(':scope > .comment-branch:not([hidden])').length;
}
protected getArchivedThreadCount(): number {
return this.archiveContainer.querySelectorAll(':scope > .comment-branch').length;
}
protected setReply(commentLocalId, commentElement): void {

View File

@ -19,18 +19,25 @@ import {Component} from './component';
*/
export class Tabs extends Component {
protected container: HTMLElement;
protected tabList: HTMLElement;
protected tabs: HTMLElement[];
protected panels: HTMLElement[];
protected activeUnder: number;
protected active: null|boolean = null;
setup() {
this.container = this.$el;
this.tabList = this.container.querySelector('[role="tablist"]');
this.tabList = this.container.querySelector('[role="tablist"]') as HTMLElement;
this.tabs = Array.from(this.tabList.querySelectorAll('[role="tab"]'));
this.panels = Array.from(this.container.querySelectorAll(':scope > [role="tabpanel"], :scope > * > [role="tabpanel"]'));
this.activeUnder = this.$opts.activeUnder ? Number(this.$opts.activeUnder) : 10000;
this.active = null;
this.container.addEventListener('click', event => {
const tab = event.target.closest('[role="tab"]');
if (tab && this.tabs.includes(tab)) {
this.show(tab.getAttribute('aria-controls'));
const tab = (event.target as HTMLElement).closest('[role="tab"]');
if (tab instanceof HTMLElement && this.tabs.includes(tab)) {
this.show(tab.getAttribute('aria-controls') || '');
}
});
@ -40,7 +47,7 @@ export class Tabs extends Component {
this.updateActiveState();
}
show(sectionId) {
public show(sectionId: string): void {
for (const panel of this.panels) {
panel.toggleAttribute('hidden', panel.id !== sectionId);
}
@ -54,7 +61,7 @@ export class Tabs extends Component {
this.$emit('change', {showing: sectionId});
}
updateActiveState() {
protected updateActiveState(): void {
const active = window.innerWidth < this.activeUnder;
if (active === this.active) {
return;
@ -69,13 +76,13 @@ export class Tabs extends Component {
this.active = active;
}
activate() {
protected activate(): void {
const panelToShow = this.panels.find(p => !p.hasAttribute('hidden')) || this.panels[0];
this.show(panelToShow.id);
this.tabList.toggleAttribute('hidden', false);
}
deactivate() {
protected deactivate(): void {
for (const panel of this.panels) {
panel.removeAttribute('hidden');
}