Skip to content

Commit 569b239

Browse files
authored
Merge pull request #6114 from WoltLab/message-preview-typescript
Migrate `WCF.Message.Preview` to Typescript
2 parents 3b054f6 + bbecddf commit 569b239

File tree

13 files changed

+399
-56
lines changed

13 files changed

+399
-56
lines changed

com.woltlab.wcf/templates/articleAdd.tpl

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -615,29 +615,34 @@
615615
</div>
616616
</form>
617617

618+
<script data-relocate="true">
619+
require(["WoltLabSuite/Core/Component/Message/I18nPreview"], ({ setup }) => {
620+
{jsphrase name='wcf.global.preview'}
621+
setup(
622+
[
623+
{if !$isMultilingual}
624+
'content0',
625+
{else}
626+
{implode from=$availableLanguages item=availableLanguage}'content{$availableLanguage->languageID}'{/implode}
627+
{/if}
628+
],
629+
'buttonMessagePreview',
630+
'com.woltlab.wcf.article.content',
631+
{if $action === 'edit'}{$article->articleID}{else}0{/if}
632+
);
633+
});
634+
</script>
635+
618636
{js application='wcf' file='WCF.Label' bundle='WCF.Combined'}
619637
<script data-relocate="true">
620638
$(function() {
621639
WCF.Language.addObject({
622640
'wcf.label.none': '{jslang}wcf.label.none{/jslang}',
623-
'wcf.global.preview': '{jslang}wcf.global.preview{/jslang}',
624641
});
625642
626643
{if !$labelGroups|empty}
627644
new WCF.Label.ArticleLabelChooser({ {implode from=$labelGroupsToCategories key=__labelCategoryID item=labelGroupIDs}{@$__labelCategoryID}: [ {implode from=$labelGroupIDs item=labelGroupID}{@$labelGroupID}{/implode} ] {/implode} }, { {implode from=$labelIDs key=groupID item=labelID}{@$groupID}: {@$labelID}{/implode} }, '.articleAddForm');
628645
{/if}
629-
630-
new WCF.Message.I18nPreview({
631-
messageFields: [
632-
{if !$isMultilingual}
633-
'content0',
634-
{else}
635-
{implode from=$availableLanguages item=availableLanguage}'content{$availableLanguage->languageID}'{/implode}
636-
{/if}
637-
],
638-
messageObjectType: 'com.woltlab.wcf.article.content',
639-
messageObjectID: {if $action === 'edit'}{$article->articleID}{else}0{/if}
640-
});
641646
});
642647
</script>
643648

com.woltlab.wcf/templates/messageFormPreviewButton.tpl

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,13 @@
66
<button type="button" id="{$previewButtonID}" class="button jsOnly">{lang}wcf.global.button.preview{/lang}</button>
77

88
<script data-relocate="true">
9-
$(function() {
10-
WCF.Language.addObject({
11-
'wcf.global.preview': '{jslang}wcf.global.preview{/jslang}'
12-
});
13-
14-
new WCF.Message.DefaultPreview({
15-
messageFieldID: '{$previewMessageFieldID}',
16-
previewButtonID: '{$previewButtonID}',
17-
messageObjectType: '{$previewMessageObjectType}',
18-
messageObjectID: '{$previewMessageObjectID}'
19-
});
9+
require(["WoltLabSuite/Core/Component/Message/Preview"], ({ setup }) => {
10+
{jsphrase name='wcf.global.preview'}
11+
setup(
12+
'{unsafe:$previewMessageFieldID|encodeJS}',
13+
'{unsafe:$previewButtonID|encodeJS}',
14+
'{unsafe:$previewMessageObjectType|encodeJS}',
15+
'{unsafe:$previewMessageObjectID|encodeJS}'
16+
);
2017
});
2118
</script>

com.woltlab.wcf/templates/shared_wysiwygPreviewFormButton.tpl

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,13 @@
55
*}>{$button->getLabel()}</button>
66

77
<script data-relocate="true">
8-
require(['Language'], function(Language) {
9-
Language.addObject({
10-
'wcf.global.preview': '{jslang}wcf.global.preview{/jslang}'
11-
});
12-
13-
new WCF.Message.DefaultPreview({
14-
messageFieldID: '{@$button->getPrefixedWysiwygId()|encodeJS}',
15-
previewButtonID: '{@$button->getPrefixedId()|encodeJS}',
16-
messageObjectType: '{@$button->getObjectType()->objectType|encodeJS}',
17-
messageObjectID: '{@$button->getObjectId()}'
18-
});
8+
require(["WoltLabSuite/Core/Component/Message/Preview"], ({ setup }) => {
9+
{jsphrase name='wcf.global.preview'}
10+
setup(
11+
'{unsafe:$button->getPrefixedWysiwygId()|encodeJS}',
12+
'{unsafe:$button->getPrefixedId()|encodeJS}',
13+
'{unsafe:$button->getObjectType()->objectType|encodeJS}',
14+
'{unsafe:$button->getObjectId()|encodeJS}'
15+
);
1916
});
2017
</script>

com.woltlab.wcf/templates/signatureEdit.tpl

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,17 @@
1717
<section class="section">
1818
<h2 class="sectionTitle">{lang}wcf.user.signature.current{/lang}</h2>
1919

20-
<div class="htmlContent messageSignatureConstraints">{@$signatureCache}</div>
20+
<div class="htmlContent messageSignatureConstraints">{unsafe:$signatureCache}</div>
2121
</section>
2222
{/if}
23+
24+
<template id="previewTemplate">
25+
<section class="section">
26+
<h2 class="sectionTitle">{lang}wcf.global.preview{/lang}</h2>
27+
28+
<div class="htmlContent messageSignatureConstraints" id="previewContainer"></div>
29+
</section>
30+
</template>
2331

2432
{if !$__wcf->user->disableSignature}
2533
<section class="section" id="signatureContainer">
@@ -42,7 +50,7 @@
4250
{elseif $errorType == 'disallowedBBCodes'}
4351
{lang}wcf.message.error.disallowedBBCodes{/lang}
4452
{else}
45-
{lang}wcf.user.signature.error.{@$errorType}{/lang}
53+
{lang}wcf.user.signature.error.{$errorType}{/lang}
4654
{/if}
4755
</small>
4856
{/if}
@@ -67,12 +75,8 @@
6775
</form>
6876

6977
<script data-relocate="true">
70-
$(function() {
71-
WCF.Language.addObject({
72-
'wcf.global.preview': '{jslang}wcf.global.preview{/jslang}'
73-
});
74-
75-
new WCF.User.SignaturePreview('wcf\\data\\user\\UserProfileAction', 'text', 'previewButton');
78+
require(["WoltLabSuite/Core/Component/User/Signature/Preview"], ({ setup }) => {
79+
setup();
7680
});
7781
</script>
7882

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
/**
2+
* Provides previews for mulitple CKEditor 5 message fields.
3+
*
4+
* @author Marcel Werk
5+
* @copyright 2001-2024 WoltLab GmbH
6+
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
7+
* @since 6.2
8+
*/
9+
10+
import { promiseMutex } from "WoltLabSuite/Core/Helper/PromiseMutex";
11+
import { dboAction } from "WoltLabSuite/Core/Ajax";
12+
import { listenToCkeditor } from "WoltLabSuite/Core/Component/Ckeditor/Event";
13+
import { dialogFactory } from "WoltLabSuite/Core/Component/Dialog";
14+
import { getPhrase } from "WoltLabSuite/Core/Language";
15+
import DomUtil from "WoltLabSuite/Core/Dom/Util";
16+
import { CKEditor } from "WoltLabSuite/Core/Component/Ckeditor";
17+
18+
type ResponseGetMessagePreview = {
19+
message: string;
20+
raw: string;
21+
};
22+
23+
async function loadPreview(message: string, objectType: string, objectId: number): Promise<void> {
24+
const response = (await dboAction("getMessagePreview", "wcf\\data\\bbcode\\MessagePreviewAction")
25+
.payload({
26+
data: {
27+
message,
28+
},
29+
messageObjectType: objectType,
30+
messageObjectID: objectId,
31+
})
32+
.dispatch()) as ResponseGetMessagePreview;
33+
34+
const dialog = dialogFactory()
35+
.fromHtml('<div class="htmlContent">' + response.message + "</div>")
36+
.withoutControls();
37+
dialog.show(getPhrase("wcf.global.preview"));
38+
}
39+
40+
function getEditorMap(messageFieldIds: string[]): Map<string, CKEditor> {
41+
const map = new Map<string, CKEditor>();
42+
messageFieldIds.forEach((messageFieldId) => {
43+
listenToCkeditor(document.getElementById(messageFieldId)!).ready(({ ckeditor }) => {
44+
map.set(messageFieldId, ckeditor);
45+
});
46+
});
47+
48+
return map;
49+
}
50+
51+
function getActiveEditor(map: Map<string, CKEditor>): CKEditor | undefined {
52+
let activeEditor: CKEditor | undefined = undefined;
53+
map.forEach((editor) => {
54+
if (editor.isVisible()) {
55+
activeEditor = editor;
56+
}
57+
});
58+
59+
return activeEditor;
60+
}
61+
62+
export function setup(messageFieldIds: string[], previewButtonId: string, objectType: string, objectId: number): void {
63+
const map = getEditorMap(messageFieldIds);
64+
65+
document.getElementById(previewButtonId)?.addEventListener(
66+
"click",
67+
promiseMutex(() => {
68+
const activeEditor = getActiveEditor(map);
69+
if (activeEditor === undefined) {
70+
return Promise.resolve();
71+
}
72+
73+
if (activeEditor.getHtml() === "") {
74+
DomUtil.innerError(activeEditor.element, getPhrase("wcf.global.form.error.empty"));
75+
return Promise.resolve();
76+
} else {
77+
DomUtil.innerError(activeEditor.element, false);
78+
}
79+
80+
return loadPreview(activeEditor.getHtml(), objectType, objectId);
81+
}),
82+
);
83+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/**
2+
* Provides previews for CKEditor 5 message fields.
3+
*
4+
* @author Marcel Werk
5+
* @copyright 2001-2024 WoltLab GmbH
6+
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
7+
* @since 6.2
8+
*/
9+
10+
import { promiseMutex } from "WoltLabSuite/Core/Helper/PromiseMutex";
11+
import { dboAction } from "WoltLabSuite/Core/Ajax";
12+
import { listenToCkeditor } from "WoltLabSuite/Core/Component/Ckeditor/Event";
13+
import { dialogFactory } from "WoltLabSuite/Core/Component/Dialog";
14+
import { getPhrase } from "WoltLabSuite/Core/Language";
15+
import DomUtil from "WoltLabSuite/Core/Dom/Util";
16+
17+
type ResponseGetMessagePreview = {
18+
message: string;
19+
raw: string;
20+
};
21+
22+
async function loadPreview(message: string, objectType: string, objectId: number): Promise<void> {
23+
const response = (await dboAction("getMessagePreview", "wcf\\data\\bbcode\\MessagePreviewAction")
24+
.payload({
25+
data: {
26+
message,
27+
},
28+
messageObjectType: objectType,
29+
messageObjectID: objectId,
30+
})
31+
.dispatch()) as ResponseGetMessagePreview;
32+
33+
const dialog = dialogFactory()
34+
.fromHtml('<div class="htmlContent">' + response.message + "</div>")
35+
.withoutControls();
36+
dialog.show(getPhrase("wcf.global.preview"));
37+
}
38+
39+
export function setup(messageFieldId: string, previewButtonId: string, objectType: string, objectId: number): void {
40+
listenToCkeditor(document.getElementById(messageFieldId)!).ready(({ ckeditor }) => {
41+
document.getElementById(previewButtonId)?.addEventListener(
42+
"click",
43+
promiseMutex(() => {
44+
if (ckeditor.getHtml() === "") {
45+
DomUtil.innerError(ckeditor.element, getPhrase("wcf.global.form.error.empty"));
46+
return Promise.resolve();
47+
} else {
48+
DomUtil.innerError(ckeditor.element, false);
49+
}
50+
51+
return loadPreview(ckeditor.getHtml(), objectType, objectId);
52+
}),
53+
);
54+
});
55+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/**
2+
* Handles the preview of signatures.
3+
*
4+
* @author Marcel Werk
5+
* @copyright 2001-2024 WoltLab GmbH
6+
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
7+
* @since 6.2
8+
*/
9+
10+
import { promiseMutex } from "WoltLabSuite/Core/Helper/PromiseMutex";
11+
import { dboAction } from "WoltLabSuite/Core/Ajax";
12+
import { listenToCkeditor } from "WoltLabSuite/Core/Component/Ckeditor/Event";
13+
14+
type ResponseGetMessagePreview = {
15+
message: string;
16+
raw: string;
17+
};
18+
19+
let previewContainer: HTMLElement;
20+
21+
async function loadPreview(message: string): Promise<void> {
22+
const response = (await dboAction("getMessagePreview", "wcf\\data\\user\\UserProfileAction")
23+
.payload({
24+
data: {
25+
message,
26+
},
27+
})
28+
.dispatch()) as ResponseGetMessagePreview;
29+
30+
if (previewContainer === undefined) {
31+
const template = document.getElementById("previewTemplate") as HTMLTemplateElement;
32+
const fragment = template.content.cloneNode(true);
33+
template.replaceWith(fragment);
34+
35+
previewContainer = document.getElementById("previewContainer")!;
36+
}
37+
38+
previewContainer.innerHTML = response.message;
39+
}
40+
41+
export function setup(): void {
42+
listenToCkeditor(document.getElementById("text")!).ready(({ ckeditor }) => {
43+
document.getElementById("previewButton")?.addEventListener(
44+
"click",
45+
promiseMutex(() => loadPreview(ckeditor.getHtml())),
46+
);
47+
});
48+
}

wcfsetup/install/files/acp/templates/articleAdd.tpl

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -616,30 +616,36 @@
616616
</div>
617617
</form>
618618

619+
<script data-relocate="true">
620+
require(["WoltLabSuite/Core/Component/Message/I18nPreview"], ({ setup }) => {
621+
{jsphrase name='wcf.global.preview'}
622+
setup(
623+
[
624+
{if !$isMultilingual}
625+
'content0',
626+
{else}
627+
{implode from=$availableLanguages item=availableLanguage}'content{$availableLanguage->languageID}'{/implode}
628+
{/if}
629+
],
630+
'buttonMessagePreview',
631+
'com.woltlab.wcf.article.content',
632+
{if $action === 'edit'}{$article->articleID}{else}0{/if}
633+
);
634+
});
635+
</script>
636+
619637
{js application='wcf' file='WCF.Label' bundle='WCF.Combined'}
620638
<script data-relocate="true">
621639
$(function() {
622640
WCF.Language.addObject({
623641
'wcf.label.none': '{jslang}wcf.label.none{/jslang}',
624-
'wcf.global.preview': '{jslang}wcf.global.preview{/jslang}',
625642
});
626643
627644
{if !$labelGroups|empty}
628645
new WCF.Label.ArticleLabelChooser({ {implode from=$labelGroupsToCategories key=__labelCategoryID item=labelGroupIDs}{@$__labelCategoryID}: [ {implode from=$labelGroupIDs item=labelGroupID}{@$labelGroupID}{/implode} ] {/implode} }, { {implode from=$labelIDs key=groupID item=labelID}{@$groupID}: {@$labelID}{/implode} }, '.articleAddForm');
629646
{/if}
630-
631-
new WCF.Message.I18nPreview({
632-
messageFields: [
633-
{if !$isMultilingual}
634-
'content0',
635-
{else}
636-
{implode from=$availableLanguages item=availableLanguage}'content{$availableLanguage->languageID}'{/implode}
637-
{/if}
638-
],
639-
messageObjectType: 'com.woltlab.wcf.article.content',
640-
messageObjectID: {if $action === 'edit'}{$article->articleID}{else}0{/if}
641-
});
642647
});
643648
</script>
644649

650+
645651
{include file='footer'}

0 commit comments

Comments
 (0)