diff --git a/client/common/configuration/register.ts b/client/common/configuration/register.ts index 76098858..f408a07c 100644 --- a/client/common/configuration/register.ts +++ b/client/common/configuration/register.ts @@ -5,6 +5,7 @@ import type { RegisterClientOptions } from '@peertube/peertube-types/client' import { renderConfigurationHome } from './templates/home' import { renderConfigurationChannel } from './templates/channel' +import { render } from 'lit' /** * Registers stuff related to the user's configuration pages. @@ -19,7 +20,7 @@ async function registerConfiguration (clientOptions: RegisterClientOptions): Pro registerClientRoute({ route: 'livechat/configuration', onMount: async ({ rootEl }) => { - rootEl.innerHTML = await renderConfigurationHome(clientOptions) + render(await renderConfigurationHome(clientOptions), rootEl) } }) @@ -28,7 +29,7 @@ async function registerConfiguration (clientOptions: RegisterClientOptions): Pro onMount: async ({ rootEl }) => { const urlParams = new URLSearchParams(window.location.search) const channelId = urlParams.get('channelId') ?? '' - await renderConfigurationChannel(clientOptions, channelId, rootEl) + render(await renderConfigurationChannel(clientOptions, channelId, rootEl), rootEl) } }) diff --git a/client/common/configuration/templates/channel.mustache b/client/common/configuration/templates/channel.mustache index 0c053d00..6813b672 100644 --- a/client/common/configuration/templates/channel.mustache +++ b/client/common/configuration/templates/channel.mustache @@ -87,42 +87,34 @@ - {{! warning: don't add extra line break in textarea! }} -

{{forbiddenWordsDesc2}}

- -

{{forbiddenWordsRegexpDesc}}

- -

{{forbiddenWordsApplyToModeratorsDesc}}

+ - + + + + -

{{forbiddenWordsLabelDesc}}

+ - -

{{forbiddenWordsReasonDesc}}

- + {{! warning: don't add extra line break in textarea! }} -

{{forbiddenWordsCommentsDesc}}

+ diff --git a/client/common/configuration/templates/channel.ts b/client/common/configuration/templates/channel.ts index df0b2b76..95afb2e7 100644 --- a/client/common/configuration/templates/channel.ts +++ b/client/common/configuration/templates/channel.ts @@ -6,6 +6,8 @@ import type { RegisterClientOptions } from '@peertube/peertube-types/client' import { localizedHelpUrl } from '../../../utils/help' import { helpButtonSVG } from '../../../videowatch/buttons' import { vivifyConfigurationChannel, getConfigurationChannelViewData } from './logic/channel' +import { TemplateResult, html } from 'lit' +import { unsafeHTML } from 'lit/directives/unsafe-html.js' // Must use require for mustache, import seems buggy. const Mustache = require('mustache') @@ -21,20 +23,18 @@ async function renderConfigurationChannel ( registerClientOptions: RegisterClientOptions, channelId: string, rootEl: HTMLElement -): Promise { +): Promise { try { const view = await getConfigurationChannelViewData(registerClientOptions, channelId) await fillViewHelpButtons(registerClientOptions, view) await fillLabels(registerClientOptions, view) - const content = Mustache.render(MUSTACHE_CONFIGURATION_CHANNEL, view) as string - - rootEl.innerHTML = content + return html`${unsafeHTML(Mustache.render(MUSTACHE_CONFIGURATION_CHANNEL, view))}` await vivifyConfigurationChannel(registerClientOptions, rootEl, channelId) } catch (err: any) { registerClientOptions.peertubeHelpers.notifier.error(err.toString()) - rootEl.innerHTML = '' + return html`` } } diff --git a/client/common/configuration/templates/home.ts b/client/common/configuration/templates/home.ts index d3313a8f..f343e7cd 100644 --- a/client/common/configuration/templates/home.ts +++ b/client/common/configuration/templates/home.ts @@ -5,15 +5,22 @@ import type { RegisterClientOptions } from '@peertube/peertube-types/client' import { localizedHelpUrl } from '../../../utils/help' import { helpButtonSVG } from '../../../videowatch/buttons' -// Must use require for mustache, import seems buggy. -const Mustache = require('mustache') +import { TemplateResult, html } from 'lit'; + +interface HomeViewData { + title: string + description: string + please_select: string + channels: any[] + helpButton: TemplateResult +} /** * Renders the livechat configuration setup home page. * @param registerClientOptions Peertube client options * @returns The page content */ -async function renderConfigurationHome (registerClientOptions: RegisterClientOptions): Promise { +async function renderConfigurationHome (registerClientOptions: RegisterClientOptions): Promise { const { peertubeHelpers } = registerClientOptions try { @@ -50,34 +57,33 @@ async function renderConfigurationHome (registerClientOptions: RegisterClientOpt } } - const view = { + const view : HomeViewData = { title: await peertubeHelpers.translate(LOC_LIVECHAT_CONFIGURATION_TITLE), description: await peertubeHelpers.translate(LOC_LIVECHAT_CONFIGURATION_DESC), please_select: await peertubeHelpers.translate(LOC_LIVECHAT_CONFIGURATION_PLEASE_SELECT), - channels: channels.data + channels: channels.data, + helpButton: await _fillViewHelpButtons(registerClientOptions) } - await _fillViewHelpButtons(registerClientOptions, view) - return Mustache.render(MUSTACHE_CONFIGURATION_HOME, view) as string + return renderConfigurationHomeFromTemplate(view) } catch (err: any) { peertubeHelpers.notifier.error(err.toString()) - return '' + return html`` } } async function _fillViewHelpButtons ( // TODO: refactor with the similar function in channel.ts - registerClientOptions: RegisterClientOptions, - view: any -): Promise { + registerClientOptions: RegisterClientOptions +): Promise { const title = await registerClientOptions.peertubeHelpers.translate(LOC_ONLINE_HELP) - const button = async (page: string): Promise => { + const button = async (page: string): Promise => { const helpUrl = await localizedHelpUrl(registerClientOptions, { page }) const helpIcon = helpButtonSVG() - return `${helpIcon}` } - view.helpButton = await button('documentation/user/streamers/channel') + return button('documentation/user/streamers/channel') +} + +function renderConfigurationHomeFromTemplate(view: HomeViewData) { + return html` +
+

+ ${view.title} + ${view.helpButton} +

+

${view.description}

+

${view.please_select}

+ +
+ ` } export { diff --git a/package-lock.json b/package-lock.json index b99d9a0f..3fa9bac7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,6 +15,7 @@ "escape-html": "^1.0.3", "got": "^11.8.2", "http-proxy": "^1.18.1", + "lit": "^3.1.3", "log-rotate": "^0.2.8", "openid-client": "^5.6.5", "validate-color": "^2.2.1", @@ -2664,6 +2665,19 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@lit-labs/ssr-dom-shim": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@lit-labs/ssr-dom-shim/-/ssr-dom-shim-1.2.0.tgz", + "integrity": "sha512-yWJKmpGE6lUURKAaIltoPIE/wrbY3TEkqQt+X0m+7fQNnAv0keydnYvbiJFP1PnMhizmIWRWOG5KLhYyc/xl+g==" + }, + "node_modules/@lit/reactive-element": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-2.0.4.tgz", + "integrity": "sha512-GFn91inaUa2oHLak8awSIigYz0cU0Payr1rcFsrkf5OJ5eSPxElyZfKh0f2p9FsTiZWXQdWGJeXZICEfXXYSXQ==", + "dependencies": { + "@lit-labs/ssr-dom-shim": "^1.2.0" + } + }, "node_modules/@msgpackr-extract/msgpackr-extract-darwin-arm64": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-3.0.2.tgz", @@ -4095,6 +4109,11 @@ "integrity": "sha512-Y0K95ThC3esLEYD6ZuqNek29lNX2EM1qxV8y2FTLUB0ff5wWrk7az+mLrnNFUnaXcgKye22+sFBRXOgpPILZNg==", "dev": true }, + "node_modules/@types/trusted-types": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", + "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==" + }, "node_modules/@types/validator": { "version": "13.7.1", "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.7.1.tgz", @@ -8644,6 +8663,34 @@ "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=", "dev": true }, + "node_modules/lit": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/lit/-/lit-3.1.3.tgz", + "integrity": "sha512-l4slfspEsnCcHVRTvaP7YnkTZEZggNFywLEIhQaGhYDczG+tu/vlgm/KaWIEjIp+ZyV20r2JnZctMb8LeLCG7Q==", + "dependencies": { + "@lit/reactive-element": "^2.0.4", + "lit-element": "^4.0.4", + "lit-html": "^3.1.2" + } + }, + "node_modules/lit-element": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/lit-element/-/lit-element-4.0.5.tgz", + "integrity": "sha512-iTWskWZEtn9SyEf4aBG6rKT8GABZMrTWop1+jopsEOgEcugcXJGKuX5bEbkq9qfzY+XB4MAgCaSPwnNpdsNQ3Q==", + "dependencies": { + "@lit-labs/ssr-dom-shim": "^1.2.0", + "@lit/reactive-element": "^2.0.4", + "lit-html": "^3.1.2" + } + }, + "node_modules/lit-html": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/lit-html/-/lit-html-3.1.3.tgz", + "integrity": "sha512-FwIbqDD8O/8lM4vUZ4KvQZjPPNx7V1VhT7vmRB8RBAO0AU6wuTVdoXiu2CivVjEGdugvcbPNBLtPE1y0ifplHA==", + "dependencies": { + "@types/trusted-types": "^2.0.2" + } + }, "node_modules/locate-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", @@ -14237,6 +14284,19 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "@lit-labs/ssr-dom-shim": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@lit-labs/ssr-dom-shim/-/ssr-dom-shim-1.2.0.tgz", + "integrity": "sha512-yWJKmpGE6lUURKAaIltoPIE/wrbY3TEkqQt+X0m+7fQNnAv0keydnYvbiJFP1PnMhizmIWRWOG5KLhYyc/xl+g==" + }, + "@lit/reactive-element": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-2.0.4.tgz", + "integrity": "sha512-GFn91inaUa2oHLak8awSIigYz0cU0Payr1rcFsrkf5OJ5eSPxElyZfKh0f2p9FsTiZWXQdWGJeXZICEfXXYSXQ==", + "requires": { + "@lit-labs/ssr-dom-shim": "^1.2.0" + } + }, "@msgpackr-extract/msgpackr-extract-darwin-arm64": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-3.0.2.tgz", @@ -15546,6 +15606,11 @@ "integrity": "sha512-Y0K95ThC3esLEYD6ZuqNek29lNX2EM1qxV8y2FTLUB0ff5wWrk7az+mLrnNFUnaXcgKye22+sFBRXOgpPILZNg==", "dev": true }, + "@types/trusted-types": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", + "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==" + }, "@types/validator": { "version": "13.7.1", "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.7.1.tgz", @@ -18891,6 +18956,34 @@ "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=", "dev": true }, + "lit": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/lit/-/lit-3.1.3.tgz", + "integrity": "sha512-l4slfspEsnCcHVRTvaP7YnkTZEZggNFywLEIhQaGhYDczG+tu/vlgm/KaWIEjIp+ZyV20r2JnZctMb8LeLCG7Q==", + "requires": { + "@lit/reactive-element": "^2.0.4", + "lit-element": "^4.0.4", + "lit-html": "^3.1.2" + } + }, + "lit-element": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/lit-element/-/lit-element-4.0.5.tgz", + "integrity": "sha512-iTWskWZEtn9SyEf4aBG6rKT8GABZMrTWop1+jopsEOgEcugcXJGKuX5bEbkq9qfzY+XB4MAgCaSPwnNpdsNQ3Q==", + "requires": { + "@lit-labs/ssr-dom-shim": "^1.2.0", + "@lit/reactive-element": "^2.0.4", + "lit-html": "^3.1.2" + } + }, + "lit-html": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/lit-html/-/lit-html-3.1.3.tgz", + "integrity": "sha512-FwIbqDD8O/8lM4vUZ4KvQZjPPNx7V1VhT7vmRB8RBAO0AU6wuTVdoXiu2CivVjEGdugvcbPNBLtPE1y0ifplHA==", + "requires": { + "@types/trusted-types": "^2.0.2" + } + }, "locate-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", diff --git a/package.json b/package.json index 17a27216..1a9f1ede 100644 --- a/package.json +++ b/package.json @@ -39,6 +39,7 @@ "escape-html": "^1.0.3", "got": "^11.8.2", "http-proxy": "^1.18.1", + "lit": "^3.1.3", "log-rotate": "^0.2.8", "openid-client": "^5.6.5", "validate-color": "^2.2.1",