Using ChannelConfigurationElement + Adding TranslationDirective
and a lots of fixes
This commit is contained in:
parent
0fe9fb4dca
commit
9ea26dfd26
2
client/@types/global.d.ts
vendored
2
client/@types/global.d.ts
vendored
@ -61,6 +61,8 @@ declare const LOC_LIVECHAT_CONFIGURATION_CHANNEL_FORBIDDEN_WORDS_REGEXP_LABEL: s
|
|||||||
declare const LOC_LIVECHAT_CONFIGURATION_CHANNEL_FORBIDDEN_WORDS_REGEXP_DESC: string
|
declare const LOC_LIVECHAT_CONFIGURATION_CHANNEL_FORBIDDEN_WORDS_REGEXP_DESC: string
|
||||||
declare const LOC_LIVECHAT_CONFIGURATION_CHANNEL_FORBIDDEN_WORDS_APPLYTOMODERATORS_LABEL: string
|
declare const LOC_LIVECHAT_CONFIGURATION_CHANNEL_FORBIDDEN_WORDS_APPLYTOMODERATORS_LABEL: string
|
||||||
declare const LOC_LIVECHAT_CONFIGURATION_CHANNEL_FORBIDDEN_WORDS_APPLYTOMODERATORS_DESC: string
|
declare const LOC_LIVECHAT_CONFIGURATION_CHANNEL_FORBIDDEN_WORDS_APPLYTOMODERATORS_DESC: string
|
||||||
|
declare const LOC_LIVECHAT_CONFIGURATION_CHANNEL_FORBIDDEN_WORDS_LABEL_LABEL: string
|
||||||
|
declare const LOC_LIVECHAT_CONFIGURATION_CHANNEL_FORBIDDEN_WORDS_LABEL_DESC: string
|
||||||
declare const LOC_LIVECHAT_CONFIGURATION_CHANNEL_FORBIDDEN_WORDS_COMMENTS_LABEL: string
|
declare const LOC_LIVECHAT_CONFIGURATION_CHANNEL_FORBIDDEN_WORDS_COMMENTS_LABEL: string
|
||||||
declare const LOC_LIVECHAT_CONFIGURATION_CHANNEL_FORBIDDEN_WORDS_COMMENTS_DESC: string
|
declare const LOC_LIVECHAT_CONFIGURATION_CHANNEL_FORBIDDEN_WORDS_COMMENTS_DESC: string
|
||||||
declare const LOC_LIVECHAT_CONFIGURATION_CHANNEL_COMMAND_LABEL: string
|
declare const LOC_LIVECHAT_CONFIGURATION_CHANNEL_COMMAND_LABEL: string
|
||||||
|
@ -4,8 +4,8 @@
|
|||||||
|
|
||||||
import type { RegisterClientOptions } from '@peertube/peertube-types/client'
|
import type { RegisterClientOptions } from '@peertube/peertube-types/client'
|
||||||
import { renderConfigurationHome } from './templates/home'
|
import { renderConfigurationHome } from './templates/home'
|
||||||
import { renderConfigurationChannel } from './templates/channel'
|
import './templates/ChannelConfigurationElement'
|
||||||
import { render } from 'lit'
|
import { html, render } from 'lit'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers stuff related to the user's configuration pages.
|
* Registers stuff related to the user's configuration pages.
|
||||||
@ -29,7 +29,7 @@ async function registerConfiguration (clientOptions: RegisterClientOptions): Pro
|
|||||||
onMount: async ({ rootEl }) => {
|
onMount: async ({ rootEl }) => {
|
||||||
const urlParams = new URLSearchParams(window.location.search)
|
const urlParams = new URLSearchParams(window.location.search)
|
||||||
const channelId = urlParams.get('channelId') ?? ''
|
const channelId = urlParams.get('channelId') ?? ''
|
||||||
render(await renderConfigurationChannel(clientOptions, channelId, rootEl), rootEl)
|
render(html`<channel-configuration .registerClientOptions=${clientOptions}></channel-configuration>`, rootEl)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -1,42 +1,146 @@
|
|||||||
|
import { RegisterClientOptions } from '@peertube/peertube-types/client'
|
||||||
import { html, LitElement } from 'lit'
|
import { html, LitElement } from 'lit'
|
||||||
import { repeat } from 'lit-html/directives/repeat.js'
|
import { repeat } from 'lit-html/directives/repeat.js'
|
||||||
import { customElement, property } from 'lit/decorators.js'
|
import { customElement, property } from 'lit/decorators.js'
|
||||||
|
import { ptTr } from './TranslationDirective'
|
||||||
|
import { localizedHelpUrl } from '../../../utils/help'
|
||||||
|
import './DynamicTableFormElement'
|
||||||
|
import './PluginConfigurationRow'
|
||||||
|
import { until } from 'async'
|
||||||
|
import { Task } from '@lit/task';
|
||||||
|
|
||||||
|
|
||||||
@customElement('channel-configuration')
|
@customElement('channel-configuration')
|
||||||
export class ChannelConfigurationElement extends LitElement {
|
export class ChannelConfigurationElement extends LitElement {
|
||||||
|
|
||||||
@property()
|
@property({ attribute: false })
|
||||||
public list: string[] = ["foo", "bar", "baz"]
|
public registerClientOptions: RegisterClientOptions | undefined
|
||||||
|
|
||||||
@property()
|
|
||||||
public newEl: string = 'change_me'
|
|
||||||
|
|
||||||
createRenderRoot = () => {
|
createRenderRoot = () => {
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
private _asyncTaskRender = new Task(this, {
|
||||||
return html`
|
|
||||||
<ul>
|
|
||||||
${repeat(this.list, (el: string, index) => html`<li>${el}<button @click=${this._removeFromList(index)}>remove</button></li>`
|
|
||||||
)}
|
|
||||||
<li><input .value=${this.newEl}/><button @click=${this._addToList(this.newEl)}>add</button></li>
|
|
||||||
</ul>
|
|
||||||
`
|
|
||||||
}
|
|
||||||
|
|
||||||
private _addToList(newEl: string) {
|
task: async ([registerClientOptions], {signal}) => {
|
||||||
return () => {
|
let link = registerClientOptions ? await localizedHelpUrl(registerClientOptions, { page: 'documentation/user/streamers/bot/forbidden_words' }) : '';
|
||||||
this.list.push(newEl)
|
|
||||||
this.requestUpdate('list')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private _removeFromList(index: number) {
|
return {
|
||||||
return () => {
|
url : new URL(link),
|
||||||
this.list.splice(index, 1)
|
title: ptTr(LOC_LIVECHAT_CONFIGURATION_CHANNEL_FORBIDDEN_WORDS_DESC)
|
||||||
this.requestUpdate('list')
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
args: () => [this.registerClientOptions]
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
render = () => {
|
||||||
|
let tableHeader = {
|
||||||
|
words: {
|
||||||
|
colName: ptTr(LOC_LIVECHAT_CONFIGURATION_CHANNEL_FORBIDDEN_WORDS_LABEL),
|
||||||
|
description: ptTr(LOC_LIVECHAT_CONFIGURATION_CHANNEL_FORBIDDEN_WORDS_DESC2)
|
||||||
|
},
|
||||||
|
regex: {
|
||||||
|
colName: ptTr(LOC_LIVECHAT_CONFIGURATION_CHANNEL_FORBIDDEN_WORDS_REGEXP_LABEL),
|
||||||
|
description: ptTr(LOC_LIVECHAT_CONFIGURATION_CHANNEL_FORBIDDEN_WORDS_REGEXP_DESC)
|
||||||
|
},
|
||||||
|
applyToModerators: {
|
||||||
|
colName: ptTr(LOC_LIVECHAT_CONFIGURATION_CHANNEL_FORBIDDEN_WORDS_APPLYTOMODERATORS_LABEL),
|
||||||
|
description: ptTr(LOC_LIVECHAT_CONFIGURATION_CHANNEL_FORBIDDEN_WORDS_APPLYTOMODERATORS_DESC)
|
||||||
|
},
|
||||||
|
label: {
|
||||||
|
colName: ptTr(LOC_LIVECHAT_CONFIGURATION_CHANNEL_FORBIDDEN_WORDS_LABEL_LABEL),
|
||||||
|
description: ptTr(LOC_LIVECHAT_CONFIGURATION_CHANNEL_FORBIDDEN_WORDS_LABEL_DESC)
|
||||||
|
},
|
||||||
|
reason: {
|
||||||
|
colName: ptTr(LOC_LIVECHAT_CONFIGURATION_CHANNEL_FORBIDDEN_WORDS_REASON_LABEL),
|
||||||
|
description: ptTr(LOC_LIVECHAT_CONFIGURATION_CHANNEL_FORBIDDEN_WORDS_REASON_DESC)
|
||||||
|
},
|
||||||
|
comments: {
|
||||||
|
colName: ptTr(LOC_LIVECHAT_CONFIGURATION_CHANNEL_FORBIDDEN_WORDS_COMMENTS_LABEL),
|
||||||
|
description: ptTr(LOC_LIVECHAT_CONFIGURATION_CHANNEL_FORBIDDEN_WORDS_COMMENTS_DESC)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
let tableSchema = {
|
||||||
|
words: {
|
||||||
|
inputType: 'text',
|
||||||
|
default: 'helloqwesad'
|
||||||
|
},
|
||||||
|
regex: {
|
||||||
|
inputType: 'text',
|
||||||
|
default: 'helloaxzca'
|
||||||
|
},
|
||||||
|
applyToModerators: {
|
||||||
|
inputType: 'checkbox',
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
label: {
|
||||||
|
inputType: 'text',
|
||||||
|
default: 'helloasx'
|
||||||
|
},
|
||||||
|
reason: {
|
||||||
|
inputType: 'select',
|
||||||
|
default: 'transphobia',
|
||||||
|
label: 'choose your poison',
|
||||||
|
options: {'racism': 'Racism', 'sexism': 'Sexism', 'transphobia': 'Transphobia', 'bigotry': 'Bigotry'}
|
||||||
|
},
|
||||||
|
comments: {
|
||||||
|
inputType: 'textarea',
|
||||||
|
default: `Lorem ipsum dolor sit amet, consectetur adipiscing elit,
|
||||||
|
sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
||||||
|
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris
|
||||||
|
nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in
|
||||||
|
reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
|
||||||
|
pariatur. Excepteur sint occaecat cupidatat non proident, sunt in
|
||||||
|
culpa qui officia deserunt mollit anim id est laborum.`
|
||||||
|
},
|
||||||
|
}
|
||||||
|
let tableRows = [
|
||||||
|
{
|
||||||
|
words: 'teweqwst',
|
||||||
|
regex: 'tesdgst',
|
||||||
|
applyToModerators: false,
|
||||||
|
label: 'teswet',
|
||||||
|
reason: 'sexism',
|
||||||
|
comments: 'tsdaswest',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
words: 'tedsadst',
|
||||||
|
regex: 'tezxccst',
|
||||||
|
applyToModerators: true,
|
||||||
|
label: 'tewest',
|
||||||
|
reason: 'racism',
|
||||||
|
comments: 'tesxzct',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
words: 'tesadsdxst',
|
||||||
|
regex: 'dsfsdf',
|
||||||
|
applyToModerators: false,
|
||||||
|
label: 'tesdadst',
|
||||||
|
reason: 'bigotry',
|
||||||
|
comments: 'tsadest',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
return this._asyncTaskRender.render({
|
||||||
|
complete: (helpLink) => html`
|
||||||
|
<div class="container">
|
||||||
|
<channel-configuration></channel-configuration>
|
||||||
|
<plugin-configuration-row
|
||||||
|
.title=${ptTr(LOC_LIVECHAT_CONFIGURATION_CHANNEL_FORBIDDEN_WORDS_LABEL)}
|
||||||
|
.description=${ptTr(LOC_LIVECHAT_CONFIGURATION_CHANNEL_FORBIDDEN_WORDS_DESC)}
|
||||||
|
.helpLink=${helpLink}
|
||||||
|
>
|
||||||
|
<dynamic-table-form
|
||||||
|
.header=${tableHeader}
|
||||||
|
.schema=${tableSchema}
|
||||||
|
.rows=${tableRows}
|
||||||
|
.formName=${'forbidden-words'}
|
||||||
|
>
|
||||||
|
</dynamic-table-form>
|
||||||
|
</plugin-configuration-row>
|
||||||
|
</div>`
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
import { html, LitElement, TemplateResult } from 'lit'
|
import { html, LitElement, TemplateResult } from 'lit'
|
||||||
import { repeat } from 'lit/directives/repeat.js'
|
import { repeat } from 'lit/directives/repeat.js'
|
||||||
import { customElement, property, state } from 'lit/decorators.js'
|
import { customElement, property, state } from 'lit/decorators.js'
|
||||||
|
import { unsafeHTML } from 'lit/directives/unsafe-html.js'
|
||||||
|
import { ifDefined } from 'lit/directives/if-defined.js'
|
||||||
|
import { StaticValue, unsafeStatic } from 'lit/static-html.js'
|
||||||
|
|
||||||
type DynamicTableAcceptedTypes = number | string | boolean | Date
|
type DynamicTableAcceptedTypes = number | string | boolean | Date
|
||||||
|
|
||||||
@ -41,7 +44,7 @@ interface CellDataSchema {
|
|||||||
export class DynamicTableFormElement extends LitElement {
|
export class DynamicTableFormElement extends LitElement {
|
||||||
|
|
||||||
@property({ attribute: false })
|
@property({ attribute: false })
|
||||||
public header: { [key : string]: TemplateResult<1> } = {}
|
public header: { [key : string]: { colName: TemplateResult, description: TemplateResult } } = {}
|
||||||
|
|
||||||
|
|
||||||
@property({ attribute: false })
|
@property({ attribute: false })
|
||||||
@ -87,55 +90,51 @@ export class DynamicTableFormElement extends LitElement {
|
|||||||
render = () => {
|
render = () => {
|
||||||
const inputId = `peertube-livechat-${this.formName.replaceAll('_','-')}-table`
|
const inputId = `peertube-livechat-${this.formName.replaceAll('_','-')}-table`
|
||||||
|
|
||||||
|
for(let row of this.rows) {
|
||||||
|
if (!row._id) {
|
||||||
|
row._id = this._lastRowId++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
<div class="row mt-5">
|
<table class="table table-striped table-hover table-sm" id=${inputId}>
|
||||||
<div class="col-12 col-lg-4 col-xl-3">
|
${this._renderHeader()}
|
||||||
<h2>Bot command #1</h2>
|
<tbody>
|
||||||
<p>You can configure the bot to respond to commands. A command is a message starting with a "!", like for example "!help" that calls the "help" command. For more information about how to configure this feature, please refer to the documentation by clicking on the help button.</p>
|
${repeat(this.rows,(row) => row._id, this._renderDataRow)}
|
||||||
<a href="https://livingston.frama.io/peertube-plugin-livechat/documentation/user/streamers/bot/commands/" target="_blank" title="Online help" class="orange-button peertube-button-link">
|
</tbody>
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 4.233 4.233">
|
<tfoot>
|
||||||
<path style="display:inline;opacity:.998;fill:none;fill-opacity:1;stroke:currentColor;stroke-width:.529167;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" d="M1.48 1.583V.86c0-.171.085-.31.19-.31h.893c.106 0 .19.139.19.31v.838c0 .171-.107.219-.19.284l-.404.314c-.136.106-.219.234-.221.489l-.003.247"></path>
|
<tr><td><button @click=${this._addRow}>Add Row</button></td></tr>
|
||||||
<path style="display:inline;fill:currentColor;stroke-width:.235169" d="M1.67 3.429h.529v.597H1.67z"></path>
|
</tfoot>
|
||||||
</svg>
|
</table>
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<div class="col-12 col-lg-8 col-xl-9">
|
|
||||||
<table class="table table-striped table-hover table-sm" id=${inputId}>
|
|
||||||
${this._renderHeader()}
|
|
||||||
<tbody>
|
|
||||||
${repeat(this.rows, this._renderDataRow)}
|
|
||||||
</tbody>
|
|
||||||
<tfoot>
|
|
||||||
<tr><td><button @click=${this._addRow}>Add Row</button></td></tr>
|
|
||||||
</tfoot>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
${JSON.stringify(this.rows)}
|
|
||||||
`
|
`
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private _renderHeader = () => {
|
private _renderHeader = () => {
|
||||||
return html`<thead><tr><th scope="col">#</th>${Object.values(this.header).map(this._renderHeaderCell)}<th scope="col">Remove Row</th></tr></thead>`
|
return html`<thead>
|
||||||
|
<tr>
|
||||||
|
<!-- <th scope="col">#</th> -->
|
||||||
|
${Object.values(this.header).map(this._renderHeaderCell)}
|
||||||
|
<th scope="col">Remove Row</th>
|
||||||
|
</tr>
|
||||||
|
</thead>`
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private _renderHeaderCell = (headerCellData: TemplateResult<1> | any) => {
|
private _renderHeaderCell = (headerCellData: { colName: TemplateResult, description: TemplateResult }) => {
|
||||||
return html`<th scope="col">${headerCellData}</th>`
|
return html`<th scope="col">
|
||||||
|
<div data-toggle="tooltip" data-placement="bottom" data-html="true" title="${headerCellData.description}">${headerCellData.colName}</div>
|
||||||
|
</th>`
|
||||||
}
|
}
|
||||||
|
|
||||||
private _renderDataRow = (rowData: { _id: number; [key : string]: DynamicTableAcceptedTypes }) => {
|
private _renderDataRow = (rowData: { _id: number; [key : string]: DynamicTableAcceptedTypes }) => {
|
||||||
if (!rowData._id) {
|
|
||||||
rowData._id = this._lastRowId++
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
const inputId = `peertube-livechat-${this.formName.replaceAll('_','-')}-row-${rowData._id}`
|
const inputId = `peertube-livechat-${this.formName.replaceAll('_','-')}-row-${rowData._id}`
|
||||||
|
|
||||||
return html`<tr id=${inputId}><td class="form-group">${rowData._id}</td>${repeat(Object.entries(rowData).filter(([k,v]) => k != '_id'), (data) => this.renderDataCell(data, rowData._id))}<td class="form-group"><button @click=${() => this._removeRow(rowData._id)}>Remove</button></td></tr>`
|
return html`<tr id=${inputId}>
|
||||||
|
<!-- <td class="form-group">${rowData._id}</td> -->
|
||||||
|
${Object.entries(rowData).filter(([k,v]) => k != '_id').map((data) => this.renderDataCell(data, rowData._id))}
|
||||||
|
<td class="form-group"><button @click=${() => this._removeRow(rowData._id)}>Remove</button></td>
|
||||||
|
</tr>`
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -175,12 +174,12 @@ export class DynamicTableFormElement extends LitElement {
|
|||||||
name=${inputName}
|
name=${inputName}
|
||||||
class="form-control"
|
class="form-control"
|
||||||
id=${inputId}
|
id=${inputId}
|
||||||
min=${propertySchema?.min}
|
min=${ifDefined(propertySchema?.min)}
|
||||||
max=${propertySchema?.max}
|
max=${ifDefined(propertySchema?.max)}
|
||||||
minlength=${propertySchema?.minlength}
|
minlength=${ifDefined(propertySchema?.minlength)}
|
||||||
maxlength=${propertySchema?.maxlength}
|
maxlength=${ifDefined(propertySchema?.maxlength)}
|
||||||
@oninput=${(event: InputEvent) => this._updatePropertyFromValue(event, propertyName, rowId)}
|
@input=${(event: InputEvent) => this._updatePropertyFromValue(event, propertyName, rowId)}
|
||||||
.value=${propertyValue}
|
.value=${propertyValue as string}
|
||||||
/>`
|
/>`
|
||||||
break
|
break
|
||||||
|
|
||||||
@ -189,19 +188,26 @@ export class DynamicTableFormElement extends LitElement {
|
|||||||
name=${inputName}
|
name=${inputName}
|
||||||
class="form-control"
|
class="form-control"
|
||||||
id=${inputId}
|
id=${inputId}
|
||||||
min=${propertySchema?.min}
|
min=${ifDefined(propertySchema?.min)}
|
||||||
max=${propertySchema?.max}
|
max=${ifDefined(propertySchema?.max)}
|
||||||
minlength=${propertySchema?.minlength}
|
minlength=${ifDefined(propertySchema?.minlength)}
|
||||||
maxlength=${propertySchema?.maxlength}
|
maxlength=${ifDefined(propertySchema?.maxlength)}
|
||||||
@oninput=${(event: InputEvent) => this._updatePropertyFromValue(event, propertyName, rowId)}
|
@input=${(event: InputEvent) => this._updatePropertyFromValue(event, propertyName, rowId)}
|
||||||
.value=${propertyValue}
|
.value=${propertyValue as string}
|
||||||
></textarea>`
|
></textarea>`
|
||||||
break
|
break
|
||||||
|
|
||||||
case 'select':
|
case 'select':
|
||||||
formElement = html`<select class="form-select" aria-label="Default select example">
|
formElement = html`<select
|
||||||
|
class="form-select"
|
||||||
|
aria-label="Default select example"
|
||||||
|
@change=${(event: InputEvent) => this._updatePropertyFromValue(event, propertyName, rowId)}
|
||||||
|
>
|
||||||
<option ?selected=${!propertyValue}>${propertySchema?.label ?? 'Choose your option'}</option>
|
<option ?selected=${!propertyValue}>${propertySchema?.label ?? 'Choose your option'}</option>
|
||||||
${Object.entries(propertySchema?.options ?? {})?.map(([value,name]) => html`<option ?selected=${propertyValue === value} value=${value}>${name}</option>`)}
|
${Object.entries(propertySchema?.options ?? {})
|
||||||
|
?.map(([value,name]) =>
|
||||||
|
html`<option ?selected=${propertyValue === value} value=${value}>${name}</option>`
|
||||||
|
)}
|
||||||
</select>`
|
</select>`
|
||||||
break
|
break
|
||||||
|
|
||||||
@ -222,12 +228,12 @@ export class DynamicTableFormElement extends LitElement {
|
|||||||
name=${inputName}
|
name=${inputName}
|
||||||
class="form-control"
|
class="form-control"
|
||||||
id=${inputId}
|
id=${inputId}
|
||||||
min=${propertySchema?.min}
|
min=${ifDefined(propertySchema?.min)}
|
||||||
max=${propertySchema?.max}
|
max=${ifDefined(propertySchema?.max)}
|
||||||
minlength=${propertySchema?.minlength}
|
minlength=${ifDefined(propertySchema?.minlength)}
|
||||||
maxlength=${propertySchema?.maxlength}
|
maxlength=${ifDefined(propertySchema?.maxlength)}
|
||||||
@oninput=${(event: InputEvent) => this._updatePropertyFromValue(event, propertyName, rowId)}
|
@input=${(event: InputEvent) => this._updatePropertyFromValue(event, propertyName, rowId)}
|
||||||
.value=${propertyValue}
|
.value=${(propertyValue as Date).toISOString()}
|
||||||
/>`
|
/>`
|
||||||
break
|
break
|
||||||
|
|
||||||
@ -246,12 +252,12 @@ export class DynamicTableFormElement extends LitElement {
|
|||||||
name=${inputName}
|
name=${inputName}
|
||||||
class="form-control"
|
class="form-control"
|
||||||
id=${inputId}
|
id=${inputId}
|
||||||
min=${propertySchema?.min}
|
min=${ifDefined(propertySchema?.min)}
|
||||||
max=${propertySchema?.max}
|
max=${ifDefined(propertySchema?.max)}
|
||||||
minlength=${propertySchema?.minlength}
|
minlength=${ifDefined(propertySchema?.minlength)}
|
||||||
maxlength=${propertySchema?.maxlength}
|
maxlength=${ifDefined(propertySchema?.maxlength)}
|
||||||
@oninput=${(event: InputEvent) => this._updatePropertyFromValue(event, propertyName, rowId)}
|
@input=${(event: InputEvent) => this._updatePropertyFromValue(event, propertyName, rowId)}
|
||||||
.value=${propertyValue}
|
.value=${propertyValue as String}
|
||||||
/>`
|
/>`
|
||||||
break
|
break
|
||||||
|
|
||||||
@ -269,9 +275,9 @@ export class DynamicTableFormElement extends LitElement {
|
|||||||
name=${inputName}
|
name=${inputName}
|
||||||
class="form-check-input"
|
class="form-check-input"
|
||||||
id=${inputId}
|
id=${inputId}
|
||||||
@oninput=${(event: InputEvent) => this._updatePropertyFromValue(event, propertyName, rowId)}
|
@input=${(event: InputEvent) => this._updatePropertyFromValue(event, propertyName, rowId)}
|
||||||
value=""
|
.value=${propertyValue as String}
|
||||||
?checked=${propertyValue}
|
?checked=${propertyValue as Boolean}
|
||||||
/>`
|
/>`
|
||||||
break
|
break
|
||||||
|
|
||||||
@ -281,24 +287,26 @@ export class DynamicTableFormElement extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!formElement) {
|
if (!formElement) {
|
||||||
console.warn(`value type '${propertyValue.constructor}' is incompatible with field type '${propertySchema.inputType}' for form entry '${propertyName.toString()}'.`)
|
console.warn(`value type '${propertyValue.constructor}' is incompatible`
|
||||||
|
+ `with field type '${propertySchema.inputType}' for form entry '${propertyName.toString()}'.`)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log
|
|
||||||
|
|
||||||
return html`<td class="form-group">${formElement}</td>`
|
return html`<td class="form-group">${formElement}</td>`
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
_updatePropertyFromValue(event: InputEvent, propertyName: string, rowId : number) {
|
_updatePropertyFromValue(event: Event, propertyName: string, rowId : number) {
|
||||||
let target = event?.target as (HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement)
|
let target = event?.target as (HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement)
|
||||||
|
let value = (target && target instanceof HTMLInputElement && target.type == "checkbox") ? !!(target?.checked) : target?.value
|
||||||
|
|
||||||
if(target?.value) {
|
if(value !== undefined) {
|
||||||
for(let row of this.rows) {
|
for(let row of this.rows) {
|
||||||
if(row._id === rowId) {
|
if(row._id === rowId) {
|
||||||
row[propertyName] = target?.value
|
row[propertyName] = value
|
||||||
|
|
||||||
|
this.requestUpdate('rows')
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,41 @@
|
|||||||
|
import { html, LitElement } from 'lit'
|
||||||
|
import { customElement, property } from 'lit/decorators.js'
|
||||||
|
import { unsafeSVG } from 'lit/directives/unsafe-svg.js'
|
||||||
|
import { StaticValue } from 'lit/static-html.js'
|
||||||
|
import { helpButtonSVG } from '../../../videowatch/buttons'
|
||||||
|
|
||||||
|
@customElement('plugin-configuration-row')
|
||||||
|
export class PLuginConfigurationRow extends LitElement {
|
||||||
|
|
||||||
|
@property({ attribute: false })
|
||||||
|
public title: string = `title`
|
||||||
|
|
||||||
|
@property({ attribute: false })
|
||||||
|
public description: string = `Here's a description`
|
||||||
|
|
||||||
|
@property({ attribute: false })
|
||||||
|
public helpLink: { url: URL, title: string } = { url : new URL('https://lmddgtfy.net/'), title: 'Online Help'}
|
||||||
|
|
||||||
|
createRenderRoot = () => {
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return html`
|
||||||
|
<div class="row mt-5">
|
||||||
|
<div class="col-12 col-lg-4 col-xl-3">
|
||||||
|
<h2>${this.title}</h2>
|
||||||
|
<p>${this.description}</p>
|
||||||
|
<a
|
||||||
|
href="${this.helpLink.url.href}"
|
||||||
|
target=_blank
|
||||||
|
title="${this.helpLink.title}"
|
||||||
|
class="orange-button peertube-button-link"
|
||||||
|
>${unsafeSVG(helpButtonSVG())}</a>
|
||||||
|
</div>
|
||||||
|
<div class="col-12 col-lg-8 col-xl-9">
|
||||||
|
<slot><p>Nothing in this row.</p></slot>
|
||||||
|
</div>
|
||||||
|
</div>`
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,41 @@
|
|||||||
|
import { PartInfo, directive } from 'lit/directive.js'
|
||||||
|
import { AsyncDirective } from 'lit/async-directive.js'
|
||||||
|
import { RegisterClientHelpers } from '@peertube/peertube-types/client';
|
||||||
|
|
||||||
|
export class TranslationDirective extends AsyncDirective {
|
||||||
|
|
||||||
|
private _peertubeHelpers?: RegisterClientHelpers
|
||||||
|
|
||||||
|
private _translatedValue : string = ''
|
||||||
|
private _localizationId : string = ''
|
||||||
|
|
||||||
|
constructor(partInfo: PartInfo) {
|
||||||
|
super(partInfo);
|
||||||
|
|
||||||
|
//_peertubeOptionsPromise.then((options) => this._peertubeHelpers = options.peertubeHelpers)
|
||||||
|
}
|
||||||
|
|
||||||
|
override render = (locId: string) => {
|
||||||
|
this._localizationId = locId // TODO Check current component for context (to infer the prefix)
|
||||||
|
|
||||||
|
if (this._translatedValue === '') {
|
||||||
|
this._translatedValue = locId
|
||||||
|
}
|
||||||
|
|
||||||
|
this._asyncUpdateTranslation()
|
||||||
|
|
||||||
|
return this._translatedValue
|
||||||
|
}
|
||||||
|
|
||||||
|
_asyncUpdateTranslation = async () => {
|
||||||
|
let newValue = await this._peertubeHelpers?.translate(this._localizationId) ?? ''
|
||||||
|
|
||||||
|
if (newValue !== '' && newValue !== this._translatedValue) {
|
||||||
|
this._translatedValue = newValue
|
||||||
|
this.setValue(newValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ptTr = directive(TranslationDirective)
|
||||||
|
|
@ -2,16 +2,20 @@
|
|||||||
//
|
//
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
import type { RegisterClientOptions } from '@peertube/peertube-types/client'
|
import type { RegisterClientHelpers, RegisterClientOptions } from '@peertube/peertube-types/client'
|
||||||
import { localizedHelpUrl } from '../../../utils/help'
|
import { localizedHelpUrl } from '../../../utils/help'
|
||||||
import { helpButtonSVG } from '../../../videowatch/buttons'
|
import { helpButtonSVG } from '../../../videowatch/buttons'
|
||||||
import { getConfigurationChannelViewData } from './logic/channel'
|
import { getConfigurationChannelViewData } from './logic/channel'
|
||||||
import { TemplateResult, html } from 'lit'
|
import { TemplateResult, html } from 'lit'
|
||||||
import { unsafeHTML } from 'lit/directives/unsafe-html.js'
|
import { unsafeHTML } from 'lit/directives/unsafe-html.js'
|
||||||
|
import { unsafeSVG } from 'lit/directives/unsafe-svg.js';
|
||||||
// Must use require for mustache, import seems buggy.
|
// Must use require for mustache, import seems buggy.
|
||||||
const Mustache = require('mustache')
|
const Mustache = require('mustache')
|
||||||
|
|
||||||
import './DynamicTableFormElement'
|
import './DynamicTableFormElement'
|
||||||
import './ChannelConfigurationElement'
|
import './ChannelConfigurationElement'
|
||||||
|
import './PluginConfigurationRow'
|
||||||
|
import { ptTr } from './TranslationDirective'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Renders the configuration settings page for a given channel,
|
* Renders the configuration settings page for a given channel,
|
||||||
@ -26,6 +30,8 @@ async function renderConfigurationChannel (
|
|||||||
channelId: string,
|
channelId: string,
|
||||||
rootEl: HTMLElement
|
rootEl: HTMLElement
|
||||||
): Promise<TemplateResult> {
|
): Promise<TemplateResult> {
|
||||||
|
const peertubeHelpers = registerClientOptions.peertubeHelpers
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const view : {[key: string] : any} = await getConfigurationChannelViewData(registerClientOptions, channelId)
|
const view : {[key: string] : any} = await getConfigurationChannelViewData(registerClientOptions, channelId)
|
||||||
await fillViewHelpButtons(registerClientOptions, view)
|
await fillViewHelpButtons(registerClientOptions, view)
|
||||||
@ -34,12 +40,30 @@ async function renderConfigurationChannel (
|
|||||||
//await vivifyConfigurationChannel(registerClientOptions, rootEl, channelId)
|
//await vivifyConfigurationChannel(registerClientOptions, rootEl, channelId)
|
||||||
|
|
||||||
let tableHeader = {
|
let tableHeader = {
|
||||||
words: html`${view.forbiddenWords}<div data-toggle="tooltip" data-placement="bottom" data-html="true" title=${view.forbiddenWordsDesc}></div>`,
|
words: {
|
||||||
regex: html`${view.forbiddenWordsRegexp}<div data-toggle="tooltip" data-placement="bottom" data-html="true" title=${view.forbiddenWordsRegexpDesc}></div>`,
|
colName: ptTr(LOC_LIVECHAT_CONFIGURATION_CHANNEL_FORBIDDEN_WORDS_LABEL),
|
||||||
applyToModerators: html`${view.forbiddenWordsApplyToModerators}<div data-toggle="tooltip" data-placement="bottom" data-html="true" title=${view.forbiddenWordsApplyToModeratorsDesc}></div>`,
|
description: ptTr(LOC_LIVECHAT_CONFIGURATION_CHANNEL_FORBIDDEN_WORDS_DESC2)
|
||||||
label: html`${view.forbiddenWordsLabel}<div data-toggle="tooltip" data-placement="bottom" data-html="true" title=${view.forbiddenWordsLabelDesc}></div>`,
|
},
|
||||||
reason: html`${view.forbiddenWordsReason}<div data-toggle="tooltip" data-placement="bottom" data-html="true" title=${view.forbiddenWordsReasonDesc}></div>`,
|
regex: {
|
||||||
comments: html`${view.forbiddenWordsComments}<div data-toggle="tooltip" data-placement="bottom" data-html="true" title=${view.forbiddenWordsCommentsDesc}></div>`,
|
colName: ptTr(LOC_LIVECHAT_CONFIGURATION_CHANNEL_FORBIDDEN_WORDS_REGEXP_LABEL),
|
||||||
|
description: ptTr(LOC_LIVECHAT_CONFIGURATION_CHANNEL_FORBIDDEN_WORDS_REGEXP_DESC)
|
||||||
|
},
|
||||||
|
applyToModerators: {
|
||||||
|
colName: ptTr(LOC_LIVECHAT_CONFIGURATION_CHANNEL_FORBIDDEN_WORDS_APPLYTOMODERATORS_LABEL),
|
||||||
|
description: ptTr(LOC_LIVECHAT_CONFIGURATION_CHANNEL_FORBIDDEN_WORDS_APPLYTOMODERATORS_DESC)
|
||||||
|
},
|
||||||
|
label: {
|
||||||
|
colName: ptTr(LOC_LIVECHAT_CONFIGURATION_CHANNEL_FORBIDDEN_WORDS_LABEL_LABEL),
|
||||||
|
description: ptTr(LOC_LIVECHAT_CONFIGURATION_CHANNEL_FORBIDDEN_WORDS_LABEL_DESC)
|
||||||
|
},
|
||||||
|
reason: {
|
||||||
|
colName: ptTr(LOC_LIVECHAT_CONFIGURATION_CHANNEL_FORBIDDEN_WORDS_REASON_LABEL),
|
||||||
|
description: ptTr(LOC_LIVECHAT_CONFIGURATION_CHANNEL_FORBIDDEN_WORDS_REASON_DESC)
|
||||||
|
},
|
||||||
|
comments: {
|
||||||
|
colName: ptTr(LOC_LIVECHAT_CONFIGURATION_CHANNEL_FORBIDDEN_WORDS_COMMENTS_LABEL),
|
||||||
|
description: ptTr(LOC_LIVECHAT_CONFIGURATION_CHANNEL_FORBIDDEN_WORDS_COMMENTS_DESC)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
let tableSchema = {
|
let tableSchema = {
|
||||||
words: {
|
words: {
|
||||||
@ -102,19 +126,30 @@ async function renderConfigurationChannel (
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
return html`${unsafeHTML(Mustache.render(MUSTACHE_CONFIGURATION_CHANNEL, view))}
|
let helpLink = {
|
||||||
|
url : new URL(await localizedHelpUrl(registerClientOptions, { page: 'documentation/user/streamers/bot/forbidden_words' })),
|
||||||
|
title: ptTr(LOC_LIVECHAT_CONFIGURATION_CHANNEL_FORBIDDEN_WORDS_DESC)
|
||||||
|
}
|
||||||
|
|
||||||
|
return html`
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<channel-configuration></channel-configuration>
|
<channel-configuration></channel-configuration>
|
||||||
<dynamic-table-form
|
<plugin-configuration-row
|
||||||
.header=${tableHeader}
|
.title=${ptTr(LOC_LIVECHAT_CONFIGURATION_CHANNEL_FORBIDDEN_WORDS_LABEL)}
|
||||||
.schema=${tableSchema}
|
.description=${ptTr(LOC_LIVECHAT_CONFIGURATION_CHANNEL_FORBIDDEN_WORDS_DESC)}
|
||||||
.rows=${tableRows}
|
.helpLink=${helpLink}
|
||||||
.formName=${'dynamic-table-form'}
|
|
||||||
>
|
>
|
||||||
</dynamic-table-form>
|
<dynamic-table-form
|
||||||
</div>${JSON.stringify(tableRows)}`
|
.header=${tableHeader}
|
||||||
|
.schema=${tableSchema}
|
||||||
|
.rows=${tableRows}
|
||||||
|
.formName=${'forbidden-words'}
|
||||||
|
>
|
||||||
|
</dynamic-table-form>
|
||||||
|
</plugin-configuration-row>
|
||||||
|
</div>`
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
registerClientOptions.peertubeHelpers.notifier.error(err.toString())
|
peertubeHelpers.notifier.error(err.toString())
|
||||||
return html``
|
return html``
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -150,7 +185,8 @@ async function fillLabels (
|
|||||||
registerClientOptions: RegisterClientOptions,
|
registerClientOptions: RegisterClientOptions,
|
||||||
view: {[key: string] : string}
|
view: {[key: string] : string}
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const { peertubeHelpers } = registerClientOptions
|
const peertubeHelpers = registerClientOptions.peertubeHelpers
|
||||||
|
|
||||||
view.title = await peertubeHelpers.translate(LOC_LIVECHAT_CONFIGURATION_CHANNEL_TITLE)
|
view.title = await peertubeHelpers.translate(LOC_LIVECHAT_CONFIGURATION_CHANNEL_TITLE)
|
||||||
view.description = await peertubeHelpers.translate(LOC_LIVECHAT_CONFIGURATION_CHANNEL_DESC)
|
view.description = await peertubeHelpers.translate(LOC_LIVECHAT_CONFIGURATION_CHANNEL_DESC)
|
||||||
|
|
||||||
|
@ -5,7 +5,10 @@
|
|||||||
import type { RegisterClientOptions } from '@peertube/peertube-types/client'
|
import type { RegisterClientOptions } from '@peertube/peertube-types/client'
|
||||||
import { localizedHelpUrl } from '../../../utils/help'
|
import { localizedHelpUrl } from '../../../utils/help'
|
||||||
import { helpButtonSVG } from '../../../videowatch/buttons'
|
import { helpButtonSVG } from '../../../videowatch/buttons'
|
||||||
import { TemplateResult, html } from 'lit';
|
import { TemplateResult, html } from 'lit'
|
||||||
|
import { unsafeHTML } from 'lit/directives/unsafe-html.js'
|
||||||
|
import { ptTr } from './TranslationDirective'
|
||||||
|
import { unsafeSVG } from 'lit/directives/unsafe-svg.js';
|
||||||
|
|
||||||
interface HomeViewData {
|
interface HomeViewData {
|
||||||
title: string
|
title: string
|
||||||
@ -86,9 +89,9 @@ async function _fillViewHelpButtons ( // TODO: refactor with the similar functio
|
|||||||
return html`<a
|
return html`<a
|
||||||
href="${helpUrl}"
|
href="${helpUrl}"
|
||||||
target=_blank
|
target=_blank
|
||||||
title="${title}"
|
title="${ptTr(LOC_ONLINE_HELP)}"
|
||||||
class="orange-button peertube-button-link"
|
class="orange-button peertube-button-link"
|
||||||
>${helpIcon}</a>`
|
>${unsafeHTML(helpIcon)}</a>`
|
||||||
}
|
}
|
||||||
|
|
||||||
return button('documentation/user/streamers/channel')
|
return button('documentation/user/streamers/channel')
|
||||||
|
@ -398,6 +398,8 @@ livechat_configuration_channel_forbidden_words_reason_label: "Reason"
|
|||||||
livechat_configuration_channel_forbidden_words_reason_desc: "Reason to display besides deleted messages"
|
livechat_configuration_channel_forbidden_words_reason_desc: "Reason to display besides deleted messages"
|
||||||
livechat_configuration_channel_forbidden_words_regexp_label: "Consider as regular expressions"
|
livechat_configuration_channel_forbidden_words_regexp_label: "Consider as regular expressions"
|
||||||
livechat_configuration_channel_forbidden_words_regexp_desc: "By checking this option, you can use regular expressions."
|
livechat_configuration_channel_forbidden_words_regexp_desc: "By checking this option, you can use regular expressions."
|
||||||
|
livechat_configuration_channel_forbidden_words_label_label: "Label"
|
||||||
|
livechat_configuration_channel_forbidden_words_label_desc: "Label for this forbidden words rule"
|
||||||
livechat_configuration_channel_forbidden_words_applytomoderators_label: "Also moderate messages from moderators"
|
livechat_configuration_channel_forbidden_words_applytomoderators_label: "Also moderate messages from moderators"
|
||||||
livechat_configuration_channel_forbidden_words_applytomoderators_desc: |
|
livechat_configuration_channel_forbidden_words_applytomoderators_desc: |
|
||||||
By default, moderator messages will not be deleted when containing forbidden words.
|
By default, moderator messages will not be deleted when containing forbidden words.
|
||||||
|
63
package-lock.json
generated
63
package-lock.json
generated
@ -9,6 +9,8 @@
|
|||||||
"version": "10.0.2",
|
"version": "10.0.2",
|
||||||
"license": "AGPL-3.0",
|
"license": "AGPL-3.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@lit/context": "^1.1.1",
|
||||||
|
"@lit/task": "^1.0.0",
|
||||||
"@xmpp/jid": "^0.13.1",
|
"@xmpp/jid": "^0.13.1",
|
||||||
"async": "^3.2.2",
|
"async": "^3.2.2",
|
||||||
"decache": "^4.6.0",
|
"decache": "^4.6.0",
|
||||||
@ -18,6 +20,7 @@
|
|||||||
"lit": "^3.1.3",
|
"lit": "^3.1.3",
|
||||||
"log-rotate": "^0.2.8",
|
"log-rotate": "^0.2.8",
|
||||||
"openid-client": "^5.6.5",
|
"openid-client": "^5.6.5",
|
||||||
|
"rxjs": "^7.8.1",
|
||||||
"validate-color": "^2.2.1",
|
"validate-color": "^2.2.1",
|
||||||
"xmppjs-chat-bot": "^0.3.0"
|
"xmppjs-chat-bot": "^0.3.0"
|
||||||
},
|
},
|
||||||
@ -2670,6 +2673,14 @@
|
|||||||
"resolved": "https://registry.npmjs.org/@lit-labs/ssr-dom-shim/-/ssr-dom-shim-1.2.0.tgz",
|
"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=="
|
"integrity": "sha512-yWJKmpGE6lUURKAaIltoPIE/wrbY3TEkqQt+X0m+7fQNnAv0keydnYvbiJFP1PnMhizmIWRWOG5KLhYyc/xl+g=="
|
||||||
},
|
},
|
||||||
|
"node_modules/@lit/context": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@lit/context/-/context-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-q/Rw7oWSJidUP43f/RUPwqZ6f5VlY8HzinTWxL/gW1Hvm2S5q2hZvV+qM8WFcC+oLNNknc3JKsd5TwxLk1hbdg==",
|
||||||
|
"dependencies": {
|
||||||
|
"@lit/reactive-element": "^1.6.2 || ^2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@lit/reactive-element": {
|
"node_modules/@lit/reactive-element": {
|
||||||
"version": "2.0.4",
|
"version": "2.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-2.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-2.0.4.tgz",
|
||||||
@ -2678,6 +2689,14 @@
|
|||||||
"@lit-labs/ssr-dom-shim": "^1.2.0"
|
"@lit-labs/ssr-dom-shim": "^1.2.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@lit/task": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@lit/task/-/task-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-7jocGBh3yGlo3kKxQggZph2txK4X5GYNWp2FAsmV9u2spzUypwrzRzXe8I72icAb02B00+k2nlvxVcrQB6vyrw==",
|
||||||
|
"dependencies": {
|
||||||
|
"@lit/reactive-element": "^1.0.0 || ^2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@msgpackr-extract/msgpackr-extract-darwin-arm64": {
|
"node_modules/@msgpackr-extract/msgpackr-extract-darwin-arm64": {
|
||||||
"version": "3.0.2",
|
"version": "3.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-3.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-3.0.2.tgz",
|
||||||
@ -10516,6 +10535,19 @@
|
|||||||
"integrity": "sha512-cLgakCUf6PedEu15t8kbsjnwIFFR2D4RfL+W3iWFJ4iac7z4B0ZI8fxy4R3J956kAI68HclCFGL8MPoUVC3qVA==",
|
"integrity": "sha512-cLgakCUf6PedEu15t8kbsjnwIFFR2D4RfL+W3iWFJ4iac7z4B0ZI8fxy4R3J956kAI68HclCFGL8MPoUVC3qVA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/rxjs": {
|
||||||
|
"version": "7.8.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz",
|
||||||
|
"integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==",
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/rxjs/node_modules/tslib": {
|
||||||
|
"version": "2.6.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
|
||||||
|
"integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q=="
|
||||||
|
},
|
||||||
"node_modules/safe-array-concat": {
|
"node_modules/safe-array-concat": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.1.tgz",
|
||||||
@ -14289,6 +14321,14 @@
|
|||||||
"resolved": "https://registry.npmjs.org/@lit-labs/ssr-dom-shim/-/ssr-dom-shim-1.2.0.tgz",
|
"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=="
|
"integrity": "sha512-yWJKmpGE6lUURKAaIltoPIE/wrbY3TEkqQt+X0m+7fQNnAv0keydnYvbiJFP1PnMhizmIWRWOG5KLhYyc/xl+g=="
|
||||||
},
|
},
|
||||||
|
"@lit/context": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@lit/context/-/context-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-q/Rw7oWSJidUP43f/RUPwqZ6f5VlY8HzinTWxL/gW1Hvm2S5q2hZvV+qM8WFcC+oLNNknc3JKsd5TwxLk1hbdg==",
|
||||||
|
"requires": {
|
||||||
|
"@lit/reactive-element": "^1.6.2 || ^2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@lit/reactive-element": {
|
"@lit/reactive-element": {
|
||||||
"version": "2.0.4",
|
"version": "2.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-2.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-2.0.4.tgz",
|
||||||
@ -14297,6 +14337,14 @@
|
|||||||
"@lit-labs/ssr-dom-shim": "^1.2.0"
|
"@lit-labs/ssr-dom-shim": "^1.2.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@lit/task": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@lit/task/-/task-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-7jocGBh3yGlo3kKxQggZph2txK4X5GYNWp2FAsmV9u2spzUypwrzRzXe8I72icAb02B00+k2nlvxVcrQB6vyrw==",
|
||||||
|
"requires": {
|
||||||
|
"@lit/reactive-element": "^1.0.0 || ^2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@msgpackr-extract/msgpackr-extract-darwin-arm64": {
|
"@msgpackr-extract/msgpackr-extract-darwin-arm64": {
|
||||||
"version": "3.0.2",
|
"version": "3.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-3.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-3.0.2.tgz",
|
||||||
@ -20289,6 +20337,21 @@
|
|||||||
"integrity": "sha512-cLgakCUf6PedEu15t8kbsjnwIFFR2D4RfL+W3iWFJ4iac7z4B0ZI8fxy4R3J956kAI68HclCFGL8MPoUVC3qVA==",
|
"integrity": "sha512-cLgakCUf6PedEu15t8kbsjnwIFFR2D4RfL+W3iWFJ4iac7z4B0ZI8fxy4R3J956kAI68HclCFGL8MPoUVC3qVA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"rxjs": {
|
||||||
|
"version": "7.8.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz",
|
||||||
|
"integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==",
|
||||||
|
"requires": {
|
||||||
|
"tslib": "^2.1.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": {
|
||||||
|
"version": "2.6.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
|
||||||
|
"integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"safe-array-concat": {
|
"safe-array-concat": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.1.tgz",
|
||||||
|
@ -33,6 +33,8 @@
|
|||||||
"dist/assets/styles/configuration.css"
|
"dist/assets/styles/configuration.css"
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@lit/context": "^1.1.1",
|
||||||
|
"@lit/task": "^1.0.0",
|
||||||
"@xmpp/jid": "^0.13.1",
|
"@xmpp/jid": "^0.13.1",
|
||||||
"async": "^3.2.2",
|
"async": "^3.2.2",
|
||||||
"decache": "^4.6.0",
|
"decache": "^4.6.0",
|
||||||
@ -42,6 +44,7 @@
|
|||||||
"lit": "^3.1.3",
|
"lit": "^3.1.3",
|
||||||
"log-rotate": "^0.2.8",
|
"log-rotate": "^0.2.8",
|
||||||
"openid-client": "^5.6.5",
|
"openid-client": "^5.6.5",
|
||||||
|
"rxjs": "^7.8.1",
|
||||||
"validate-color": "^2.2.1",
|
"validate-color": "^2.2.1",
|
||||||
"xmppjs-chat-bot": "^0.3.0"
|
"xmppjs-chat-bot": "^0.3.0"
|
||||||
},
|
},
|
||||||
|
Loading…
x
Reference in New Issue
Block a user