From: Alexander Ebert Date: Mon, 6 Jan 2025 15:10:29 +0000 (+0100) Subject: Present stored quotes using the existing UI design X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=aa6a8a742b630848a06fe9ac92970cf98bc9dfe5;p=GitHub%2FWoltLab%2FWCF.git Present stored quotes using the existing UI design --- diff --git a/com.woltlab.wcf/templates/__messageFormQuote.tpl b/com.woltlab.wcf/templates/__messageFormQuote.tpl index d4b635e106..16c489f614 100644 --- a/com.woltlab.wcf/templates/__messageFormQuote.tpl +++ b/com.woltlab.wcf/templates/__messageFormQuote.tpl @@ -1,11 +1,8 @@ -{* TODO *} - -
- -
+
+}); + \ No newline at end of file diff --git a/com.woltlab.wcf/templates/__messageFormQuoteInline.tpl b/com.woltlab.wcf/templates/__messageFormQuoteInline.tpl index d4b635e106..16c489f614 100644 --- a/com.woltlab.wcf/templates/__messageFormQuoteInline.tpl +++ b/com.woltlab.wcf/templates/__messageFormQuoteInline.tpl @@ -1,11 +1,8 @@ -{* TODO *} - -
- -
+
+}); + \ No newline at end of file diff --git a/ts/WoltLabSuite/Core/Component/Quote/List.ts b/ts/WoltLabSuite/Core/Component/Quote/List.ts index 680f905f7f..fa2c558a0b 100644 --- a/ts/WoltLabSuite/Core/Component/Quote/List.ts +++ b/ts/WoltLabSuite/Core/Component/Quote/List.ts @@ -12,8 +12,9 @@ import { listenToCkeditor, dispatchToCkeditor } from "WoltLabSuite/Core/Componen import { getTabMenu } from "WoltLabSuite/Core/Component/Message/MessageTabMenu"; import { getPhrase } from "WoltLabSuite/Core/Language"; import { setActiveEditor } from "WoltLabSuite/Core/Component/Quote/Message"; -import { getQuotes, getMessage } from "WoltLabSuite/Core/Component/Quote/Storage"; +import { getQuotes, getMessage, removeQuote } from "WoltLabSuite/Core/Component/Quote/Storage"; import DomUtil from "WoltLabSuite/Core/Dom/Util"; +import { escapeHTML } from "WoltLabSuite/Core/StringUtil"; const quoteLists = new Map(); @@ -43,67 +44,46 @@ class QuoteList { let quotesCount = 0; for (const [key, quotes] of getQuotes()) { const message = getMessage(key)!; - quotesCount += quotes.size; - - // TODO escape values - // TODO create web components??? - const fragment = DomUtil.createFragmentFromHtml(`
-
-
-
- - -
-

- ${message.title} -

- -
-
-
-
-
-
    - ${Array.from(quotes) - .map( - (quote) => `
  • - - - + - - -
    - ${quote.message}
    -
  • `, - ) - .join("")} -
-
-
+
+ ${quote.rawMessage === undefined ? quote.message : quote.rawMessage}
-
`); + + `); - // TODO dont query the DOM - fragment.querySelectorAll(".jsInsertQuote").forEach((button) => { - button.addEventListener("click", () => { - // TODO use rawMessage to insert if available otherwise use message + fragment.querySelector('button[data-action="insert"]')!.addEventListener("click", () => { dispatchToCkeditor(this.#editor).insertQuote({ author: message.author, - content: button.closest("li")!.querySelector(".jsQuote")!.innerHTML, - isText: false, + content: quote.rawMessage === undefined ? quote.message : quote.rawMessage, + isText: quote.rawMessage === undefined, link: message.link, }); }); - }); - this.#container.append(fragment); + fragment.querySelector('button[data-action="delete"]')!.addEventListener("click", () => { + removeQuote(key, index); + }); + + this.#container.append(fragment); + }); } if (quotesCount > 0) { diff --git a/ts/WoltLabSuite/Core/Component/Quote/Storage.ts b/ts/WoltLabSuite/Core/Component/Quote/Storage.ts index 5a9413a114..0cc2e255bf 100644 --- a/ts/WoltLabSuite/Core/Component/Quote/Storage.ts +++ b/ts/WoltLabSuite/Core/Component/Quote/Storage.ts @@ -29,7 +29,7 @@ interface Quote { } interface StorageData { - quotes: Map>; + quotes: Map; messages: Map; } @@ -76,7 +76,7 @@ export async function saveFullQuote(objectType: string, objectClassName: string, refreshQuoteLists(); } -export function getQuotes(): Map> { +export function getQuotes(): Map { return getStorage().quotes; } @@ -86,17 +86,15 @@ export function getMessage(objectType: string, objectId?: number): Message | und return getStorage().messages.get(key); } -export function removeQuote(objectType: string, objectId: number, quote: Quote): void { +export function removeQuote(key: string, index: number): void { const storage = getStorage(); - - const key = getKey(objectType, objectId); if (!storage.quotes.has(key)) { return; } - storage.quotes.get(key)!.delete(quote); + storage.quotes.get(key)!.splice(index, 1); - if (storage.quotes.get(key)!.size === 0) { + if (storage.quotes.get(key)!.length === 0) { storage.quotes.delete(key); storage.messages.delete(key); } @@ -111,18 +109,11 @@ function storeQuote(objectType: string, message: Message, quote: Quote): void { const key = getKey(objectType, message.objectID); if (!storage.quotes.has(key)) { - storage.quotes.set(key, new Set()); + storage.quotes.set(key, []); } storage.messages.set(key, message); - - if ( - !Array.from(storage.quotes.get(key)!) - .map((q) => q.message) - .includes(quote.message) - ) { - storage.quotes.get(key)!.add(quote); - } + storage.quotes.get(key)!.push(quote); saveStorage(storage); } @@ -137,11 +128,7 @@ function getStorage(): StorageData { } else { return JSON.parse(data, (key, value) => { if (key === "quotes") { - const result = new Map>(value); - for (const [key, setValue] of result) { - result.set(key, new Set(setValue)); - } - return result; + return new Map(value); } else if (key === "messages") { return new Map(value); } @@ -158,7 +145,7 @@ function getKey(objectType: string, objectId: number): string { function saveStorage(data: StorageData) { window.localStorage.setItem( STORAGE_KEY, - JSON.stringify(data, (key, value) => { + JSON.stringify(data, (_key, value) => { if (value instanceof Map) { return Array.from(value.entries()); } else if (value instanceof Set) { diff --git a/wcfsetup/install/files/js/WoltLabSuite/Core/Component/Quote/List.js b/wcfsetup/install/files/js/WoltLabSuite/Core/Component/Quote/List.js index d2dd115fc7..6d12ac1fb2 100644 --- a/wcfsetup/install/files/js/WoltLabSuite/Core/Component/Quote/List.js +++ b/wcfsetup/install/files/js/WoltLabSuite/Core/Component/Quote/List.js @@ -7,7 +7,7 @@ * @since 6.2 * @woltlabExcludeBundle tiny */ -define(["require", "exports", "tslib", "WoltLabSuite/Core/Component/Ckeditor/Event", "WoltLabSuite/Core/Component/Message/MessageTabMenu", "WoltLabSuite/Core/Language", "WoltLabSuite/Core/Component/Quote/Message", "WoltLabSuite/Core/Component/Quote/Storage", "WoltLabSuite/Core/Dom/Util"], function (require, exports, tslib_1, Event_1, MessageTabMenu_1, Language_1, Message_1, Storage_1, Util_1) { +define(["require", "exports", "tslib", "WoltLabSuite/Core/Component/Ckeditor/Event", "WoltLabSuite/Core/Component/Message/MessageTabMenu", "WoltLabSuite/Core/Language", "WoltLabSuite/Core/Component/Quote/Message", "WoltLabSuite/Core/Component/Quote/Storage", "WoltLabSuite/Core/Dom/Util", "WoltLabSuite/Core/StringUtil"], function (require, exports, tslib_1, Event_1, MessageTabMenu_1, Language_1, Message_1, Storage_1, Util_1, StringUtil_1) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getQuoteList = getQuoteList; @@ -36,62 +36,42 @@ define(["require", "exports", "tslib", "WoltLabSuite/Core/Component/Ckeditor/Eve let quotesCount = 0; for (const [key, quotes] of (0, Storage_1.getQuotes)()) { const message = (0, Storage_1.getMessage)(key); - quotesCount += quotes.size; - // TODO escape values - // TODO create web components??? - const fragment = Util_1.default.createFragmentFromHtml(`
-
-
-
- - -
-

- ${message.title} -

- -
-
-
-
-
-
    - ${Array.from(quotes) - .map((quote) => `
  • - - - + - - -
    - ${quote.message}
    -
  • `) - .join("")} -
-
-
+
+ ${quote.rawMessage === undefined ? quote.message : quote.rawMessage}
-
`); - fragment.querySelectorAll(".jsInsertQuote").forEach((button) => { - button.addEventListener("click", () => { - // TODO dont query the DOM - // TODO use rawMessage to insert if available otherwise use message + + `); + fragment.querySelector('button[data-action="insert"]').addEventListener("click", () => { (0, Event_1.dispatchToCkeditor)(this.#editor).insertQuote({ author: message.author, - content: button.closest("li").querySelector(".jsQuote").innerHTML, - isText: false, + content: quote.rawMessage === undefined ? quote.message : quote.rawMessage, + isText: quote.rawMessage === undefined, link: message.link, }); }); + fragment.querySelector('button[data-action="delete"]').addEventListener("click", () => { + (0, Storage_1.removeQuote)(key, index); + }); + this.#container.append(fragment); }); - this.#container.append(fragment); } if (quotesCount > 0) { (0, MessageTabMenu_1.getTabMenu)(this.#editorId)?.showTab("quotes", (0, Language_1.getPhrase)("wcf.message.quote.showQuotes", { diff --git a/wcfsetup/install/files/js/WoltLabSuite/Core/Component/Quote/Storage.js b/wcfsetup/install/files/js/WoltLabSuite/Core/Component/Quote/Storage.js index b71b4f69be..c5cece8d3b 100644 --- a/wcfsetup/install/files/js/WoltLabSuite/Core/Component/Quote/Storage.js +++ b/wcfsetup/install/files/js/WoltLabSuite/Core/Component/Quote/Storage.js @@ -55,14 +55,13 @@ define(["require", "exports", "tslib", "WoltLabSuite/Core/Core", "WoltLabSuite/C const key = objectId ? getKey(objectType, objectId) : objectType; return getStorage().messages.get(key); } - function removeQuote(objectType, objectId, quote) { + function removeQuote(key, index) { const storage = getStorage(); - const key = getKey(objectType, objectId); if (!storage.quotes.has(key)) { return; } - storage.quotes.get(key).delete(quote); - if (storage.quotes.get(key).size === 0) { + storage.quotes.get(key).splice(index, 1); + if (storage.quotes.get(key).length === 0) { storage.quotes.delete(key); storage.messages.delete(key); } @@ -73,14 +72,10 @@ define(["require", "exports", "tslib", "WoltLabSuite/Core/Core", "WoltLabSuite/C const storage = getStorage(); const key = getKey(objectType, message.objectID); if (!storage.quotes.has(key)) { - storage.quotes.set(key, new Set()); + storage.quotes.set(key, []); } storage.messages.set(key, message); - if (!Array.from(storage.quotes.get(key)) - .map((q) => q.message) - .includes(quote.message)) { - storage.quotes.get(key).add(quote); - } + storage.quotes.get(key).push(quote); saveStorage(storage); } function getStorage() { @@ -94,11 +89,7 @@ define(["require", "exports", "tslib", "WoltLabSuite/Core/Core", "WoltLabSuite/C else { return JSON.parse(data, (key, value) => { if (key === "quotes") { - const result = new Map(value); - for (const [key, setValue] of result) { - result.set(key, new Set(setValue)); - } - return result; + return new Map(value); } else if (key === "messages") { return new Map(value); @@ -111,7 +102,7 @@ define(["require", "exports", "tslib", "WoltLabSuite/Core/Core", "WoltLabSuite/C return `${objectType}:${objectId}`; } function saveStorage(data) { - window.localStorage.setItem(STORAGE_KEY, JSON.stringify(data, (key, value) => { + window.localStorage.setItem(STORAGE_KEY, JSON.stringify(data, (_key, value) => { if (value instanceof Map) { return Array.from(value.entries()); } diff --git a/wcfsetup/install/files/style/bbcode/quote.scss b/wcfsetup/install/files/style/bbcode/quote.scss index c2e2490cd7..944b6ee8ff 100644 --- a/wcfsetup/install/files/style/bbcode/quote.scss +++ b/wcfsetup/install/files/style/bbcode/quote.scss @@ -8,7 +8,7 @@ display: grid; font-style: normal; grid-template-areas: - "icon title" + "icon title" "content content"; grid-template-columns: 24px auto; margin: 2em 0 1em 0; @@ -79,3 +79,38 @@ margin-bottom: 0 !important; } } + +.quoteBox.quoteBox--tabMenu { + grid-template-areas: + "icon title buttons" + "content content content"; + grid-template-columns: 24px auto min-content; + margin: 0; +} + +.quoteBox.quoteBox--tabMenu + .quoteBox.quoteBox--tabMenu { + margin-top: 10px; +} + +.quoteBoxButtons { + align-self: center; + column-gap: 5px; + display: flex; + grid-area: buttons; + white-space: nowrap; +} + +.quoteBox.quoteBox--tabMenu :is(.quoteBoxIcon, .quoteBoxTitle) { + align-self: center; +} + +.quoteBox.quoteBox--tabMenu .quoteBoxContent { + pointer-events: none !important; +} + +@include screen-xs { + .messageTabMenu:not(.messageTabMenuContent) > .messageTabMenuContent.messageTabMenuContent--quotes.active { + padding-left: 10px; + padding-right: 10px; + } +}