Skip to content

Commit 2a34443

Browse files
committed
Add support for counters for message tab menus
1 parent a982d6f commit 2a34443

File tree

7 files changed

+182
-21
lines changed

7 files changed

+182
-21
lines changed
Lines changed: 39 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,56 @@
11
{* the settings template does not generate direct ouput anymore, but captures it content *}
22
{include file='messageFormSettings'}
33

4-
<div class="messageTabMenu" data-preselect="{if $preselectTabMenu|isset}{$preselectTabMenu}{else}true{/if}" data-wysiwyg-container-id="{if $wysiwygContainerID|isset}{$wysiwygContainerID}{else}text{/if}">
4+
<div class="messageTabMenu" data-preselect="{if $preselectTabMenu|isset}{$preselectTabMenu}{else}true{/if}"
5+
data-wysiwyg-container-id="{if $wysiwygContainerID|isset}{$wysiwygContainerID}{else}text{/if}">
56
<nav class="messageTabMenuNavigation jsOnly">
67
<ul>
7-
{if MODULE_SMILEY && !$smileyCategories|empty}<li data-name="smilies"><button type="button">{icon name='face-smile'} <span>{lang}wcf.message.smilies{/lang}</span></button></li>{/if}
8+
{if MODULE_SMILEY && !$smileyCategories|empty}
9+
<li data-name="smilies">
10+
<button type="button">
11+
{icon name='face-smile'}
12+
<span>{lang}wcf.message.smilies{/lang}</span>
13+
</button>
14+
</li>
15+
{/if}
816
{if !$attachmentHandler|empty && $attachmentHandler->canUpload()}
9-
<li data-name="attachments"><button type="button">{icon name='paperclip'} <span>{lang}wcf.attachment.attachments{/lang}</span></button></li>
17+
<li data-name="attachments">
18+
<button type="button">
19+
{icon name='paperclip'}
20+
<span>{lang}wcf.attachment.attachments{/lang}</span>
21+
{if $attachmentHandler->count() > 0}
22+
<span class="badge badgeUpdate">{#$attachmentHandler->count()}</span>
23+
{/if}
24+
</button>
25+
</li>
26+
{/if}
27+
{if $__messageFormSettings}
28+
<li data-name="settings">
29+
<button type="button">
30+
{icon name='gear'}
31+
<span>{lang}wcf.message.settings{/lang}</span>
32+
</button>
33+
</li>
34+
{/if}
35+
{if $__showPoll|isset && $__showPoll}
36+
<li data-name="poll">
37+
<button type="button">
38+
{icon name='chart-bar'}
39+
<span>{lang}wcf.poll.management{/lang}</span>
40+
</button>
41+
</li>
1042
{/if}
11-
{if $__messageFormSettings}<li data-name="settings"><button type="button">{icon name='gear'} <span>{lang}wcf.message.settings{/lang}</span></button></li>{/if}
12-
{if $__showPoll|isset && $__showPoll}<li data-name="poll"><button type="button">{icon name='chart-bar'} <span>{lang}wcf.poll.management{/lang}</span></button></li>{/if}
1343
{event name='tabMenuTabs'}
1444
</ul>
1545
</nav>
16-
46+
1747
{if MODULE_SMILEY && !$smileyCategories|empty}{include file='shared_messageFormSmileyTab'}{/if}
1848
{if !$attachmentHandler|empty && $attachmentHandler->canUpload()}
1949
{include file='shared_messageFormAttachments'}
2050
{/if}
21-
51+
2252
{if $__messageFormSettings}{unsafe:$__messageFormSettings}{/if}
2353
{include file='__messageFormPoll'}
24-
54+
2555
{event name='tabMenuContents'}
26-
</div>
56+
</div>

com.woltlab.wcf/templates/messageFormTabsInline.tpl

Lines changed: 39 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,27 +5,56 @@
55
{capture assign='__messageFormSettingsInlineContent'}{include file='messageFormSettingsInline'}{/capture}
66
{assign var='__messageFormSettingsInlineContent' value=$__messageFormSettingsInlineContent|trim}
77

8-
<div class="messageTabMenu"{if $preselectTabMenu|isset} data-preselect="{$preselectTabMenu}"{/if} data-wysiwyg-container-id="{$wysiwygSelector}">
8+
<div class="messageTabMenu" {if $preselectTabMenu|isset} data-preselect="{$preselectTabMenu}" {/if}
9+
data-wysiwyg-container-id="{$wysiwygSelector}">
910
<nav class="messageTabMenuNavigation jsOnly">
1011
<ul>
11-
{if MODULE_SMILEY && !$smileyCategories|empty}<li data-name="smilies"><button type="button">{icon name='face-smile'} <span>{lang}wcf.message.smilies{/lang}</span></button></li>{/if}
12+
{if MODULE_SMILEY && !$smileyCategories|empty}
13+
<li data-name="smilies">
14+
<button type="button">
15+
{icon name='face-smile'}
16+
<span>{lang}wcf.message.smilies{/lang}</span>
17+
</button>
18+
</li>
19+
{/if}
1220
{if !$attachmentHandler|empty && $attachmentHandler->canUpload()}
13-
<li data-name="attachments"><button type="button">{icon name='paperclip'} <span>{lang}wcf.attachment.attachments{/lang}</span></button></li>
21+
<li data-name="attachments">
22+
<button type="button">
23+
{icon name='paperclip'}
24+
<span>{lang}wcf.attachment.attachments{/lang}</span>
25+
{if $attachmentHandler->count() > 0}
26+
<span class="badge badgeUpdate">{#$attachmentHandler->count()}</span>
27+
{/if}
28+
</button>
29+
</li>
30+
{/if}
31+
{if $__messageFormSettingsInlineContent}
32+
<li data-name="settings"><button type="button">
33+
{icon name='gear'}
34+
<span>{lang}wcf.message.settings{/lang}</span>
35+
</button>
36+
</li>
37+
{/if}
38+
{if $__showPoll|isset && $__showPoll}
39+
<li data-name="poll">
40+
<button type="button">
41+
{icon name='chart-bar'}
42+
<span>{lang}wcf.poll.management{/lang}</span>
43+
</button>
44+
</li>
1445
{/if}
15-
{if $__messageFormSettingsInlineContent}<li data-name="settings"><button type="button">{icon name='gear'} <span>{lang}wcf.message.settings{/lang}</span></button></li>{/if}
16-
{if $__showPoll|isset && $__showPoll}<li data-name="poll"><button type="button">{icon name='chart-bar'} <span>{lang}wcf.poll.management{/lang}</span></button></li>{/if}
1746
{event name='tabMenuTabs'}
1847
</ul>
1948
</nav>
20-
49+
2150
{if MODULE_SMILEY && !$smileyCategories|empty}{include file='shared_messageFormSmileyTab'}{/if}
2251
{if !$attachmentHandler|empty && $attachmentHandler->canUpload()}
2352
{include file='shared_messageFormAttachments'}
2453
{/if}
25-
54+
2655
{if $__messageFormSettingsInlineContent}{@$__messageFormSettingsInlineContent}{/if}
27-
56+
2857
{include file='__messageFormPollInline'}
29-
58+
3059
{event name='tabMenuContents'}
31-
</div>
60+
</div>

ts/WoltLabSuite/Core/Component/Attachment/List.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@ export function setup(editorId: string): void {
1818
throw new Error(`The attachments container for '${editorId}' does not exist.`);
1919
}
2020

21+
const tabMenu = getTabMenu(editorId);
22+
if (tabMenu === undefined) {
23+
throw new Error("Unable to find the corresponding tab menu.");
24+
}
25+
2126
const editor = document.getElementById(editorId);
2227
if (editor === null) {
2328
throw new Error(`The editor element for '${editorId}' does not exist.`);
@@ -85,4 +90,20 @@ export function setup(editorId: string): void {
8590

8691
existingFiles.remove();
8792
}
93+
94+
const files = fileList.getElementsByTagName("woltlab-core-file");
95+
const observer = new MutationObserver(() => {
96+
let counter = 0;
97+
for (const file of files) {
98+
if (!file.isFailedUpload()) {
99+
counter++;
100+
}
101+
}
102+
103+
tabMenu.setTabCounter("attachments", counter);
104+
});
105+
observer.observe(fileList, {
106+
childList: true,
107+
subtree: true,
108+
});
88109
}

ts/WoltLabSuite/Core/Component/Message/MessageTabMenu.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,28 @@ class TabMenu {
6565
this.#activeTabName = tabName;
6666
}
6767

68+
setTabCounter(tabName: string, value: number): void {
69+
const tab = this.#tabs.find((element) => element.dataset.name === tabName);
70+
if (tab === undefined) {
71+
throw new Error(`Unknown tab '${tabName}'.`);
72+
}
73+
74+
let badgeUpdate = tab.querySelector(".badgeUpdate");
75+
if (value === 0) {
76+
badgeUpdate?.remove();
77+
78+
return;
79+
}
80+
81+
if (badgeUpdate === null) {
82+
badgeUpdate = document.createElement("span");
83+
badgeUpdate.classList.add("badge", "badgeUpdate");
84+
tab.querySelector("a, button")!.append(badgeUpdate);
85+
}
86+
87+
badgeUpdate.textContent = value.toString();
88+
}
89+
6890
#init(): void {
6991
for (let i = 0; i < this.#tabs.length; i++) {
7092
const tab = this.#tabs[i];
@@ -142,9 +164,19 @@ function initTabMenu(tabMenu: HTMLElement): void {
142164
}
143165

144166
export function getTabMenu(identifier: string): TabMenu | undefined {
167+
setup();
168+
145169
return tabMenus.get(identifier);
146170
}
147171

172+
let initialized = false;
173+
148174
export function setup(): void {
175+
if (initialized) {
176+
return;
177+
}
178+
179+
initialized = true;
180+
149181
wheneverFirstSeen(".messageTabMenu", (tabMenu) => initTabMenu(tabMenu));
150182
}

wcfsetup/install/files/js/WoltLabSuite/Core/Component/Attachment/List.js

Lines changed: 18 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

wcfsetup/install/files/js/WoltLabSuite/Core/Component/Message/MessageTabMenu.js

Lines changed: 23 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

wcfsetup/install/files/style/ui/tabMenuMessage.scss

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,13 +108,21 @@
108108

109109
> a,
110110
> button {
111+
align-items: center;
111112
color: inherit;
112-
display: block;
113+
/* 0.2em matches the width of a space */
114+
column-gap: 0.2em;
115+
display: flex;
113116
padding: 10px 20px;
114117

115118
@include userSelectNone;
116119
@include wcfFontDefault;
117120

121+
.badgeUpdate {
122+
font-variant: tabular-nums;
123+
margin-left: 0.3em;
124+
}
125+
118126
@include screen-md-up {
119127
> .icon {
120128
display: none;
@@ -126,7 +134,7 @@
126134
display: block;
127135
}
128136

129-
> span:not(.icon) {
137+
> span:not(.badgeUpdate) {
130138
display: none;
131139
}
132140
}

0 commit comments

Comments
 (0)