Create peertube-container html tag

pull/4181/head
Chocobozzz 2021-06-09 09:19:36 +02:00
parent 17b064e394
commit f7894f0964
No known key found for this signature in database
GPG Key ID: 583A612D890159BE
8 changed files with 83 additions and 27 deletions

View File

@ -1 +1 @@
<div #contentWrapper></div>
<div class="custom-markup-container" #contentWrapper></div>

View File

@ -0,0 +1,10 @@
.custom-markup-container {
::ng-deep .peertube-container {
margin: 30px 0 15px;
h4 {
margin-bottom: 0;
}
}
}

View File

@ -3,7 +3,8 @@ import { CustomMarkupService } from './custom-markup.service'
@Component({
selector: 'my-custom-markup-container',
templateUrl: './custom-markup-container.component.html'
templateUrl: './custom-markup-container.component.html',
styleUrls: [ './custom-markup-container.component.scss' ]
})
export class CustomMarkupContainerComponent implements OnChanges {
@ViewChild('contentWrapper') contentWrapper: ElementRef<HTMLInputElement>

View File

@ -3,6 +3,7 @@ import { MarkdownService } from '@app/core'
import {
ButtonMarkupData,
ChannelMiniatureMarkupData,
ContainerMarkupData,
EmbedMarkupData,
PlaylistMiniatureMarkupData,
VideoMiniatureMarkupData,
@ -18,11 +19,12 @@ import {
VideosListMarkupComponent
} from './peertube-custom-tags'
type BuilderFunction = (el: HTMLElement) => ComponentRef<any>
type AngularBuilderFunction = (el: HTMLElement) => ComponentRef<any>
type HTMLBuilderFunction = (el: HTMLElement) => HTMLElement
@Injectable()
export class CustomMarkupService {
private builders: { [ selector: string ]: BuilderFunction } = {
private angularBuilders: { [ selector: string ]: AngularBuilderFunction } = {
'peertube-button': el => this.buttonBuilder(el),
'peertube-video-embed': el => this.embedBuilder(el, 'video'),
'peertube-playlist-embed': el => this.embedBuilder(el, 'playlist'),
@ -32,6 +34,10 @@ export class CustomMarkupService {
'peertube-videos-list': el => this.videosListBuilder(el)
}
private htmlBuilders: { [ selector: string ]: HTMLBuilderFunction } = {
'peertube-container': el => this.containerBuilder(el)
}
private customMarkdownRenderer: (text: string) => Promise<HTMLElement>
constructor (
@ -51,11 +57,24 @@ export class CustomMarkupService {
const rootElement = document.createElement('div')
rootElement.innerHTML = html
for (const selector of this.getSupportedTags()) {
for (const selector of Object.keys(this.htmlBuilders)) {
rootElement.querySelectorAll(selector)
.forEach((e: HTMLElement) => {
try {
const component = this.execBuilder(selector, e)
const element = this.execHTMLBuilder(selector, e)
// Insert as first child
e.insertBefore(element, e.firstChild)
} catch (err) {
console.error('Cannot inject component %s.', selector, err)
}
})
}
for (const selector of Object.keys(this.angularBuilders)) {
rootElement.querySelectorAll(selector)
.forEach((e: HTMLElement) => {
try {
const component = this.execAngularBuilder(selector, e)
this.dynamicElementService.injectElement(e, component)
} catch (err) {
@ -68,11 +87,16 @@ export class CustomMarkupService {
}
private getSupportedTags () {
return Object.keys(this.builders)
return Object.keys(this.angularBuilders)
.concat(Object.keys(this.htmlBuilders))
}
private execBuilder (selector: string, el: HTMLElement) {
return this.builders[selector](el)
private execHTMLBuilder (selector: string, el: HTMLElement) {
return this.htmlBuilders[selector](el)
}
private execAngularBuilder (selector: string, el: HTMLElement) {
return this.angularBuilders[selector](el)
}
private embedBuilder (el: HTMLElement, type: 'video' | 'playlist') {
@ -131,8 +155,6 @@ export class CustomMarkupService {
const component = this.dynamicElementService.createElement(VideosListMarkupComponent)
const model = {
title: data.title,
description: data.description,
sort: data.sort,
categoryOneOf: this.buildArrayNumber(data.categoryOneOf),
languageOneOf: this.buildArrayString(data.languageOneOf),
@ -144,6 +166,31 @@ export class CustomMarkupService {
return component
}
private containerBuilder (el: HTMLElement) {
const data = el.dataset as ContainerMarkupData
const root = document.createElement('div')
root.classList.add('peertube-container')
if (data.width) {
root.setAttribute('width', data.width)
}
if (data.title) {
const titleElement = document.createElement('h4')
titleElement.innerText = data.title
root.appendChild(titleElement)
}
if (data.description) {
const descriptionElement = document.createElement('div')
descriptionElement.innerText = data.description
root.appendChild(descriptionElement)
}
return root
}
private buildNumber (value: string) {
if (!value) return undefined

View File

@ -1,13 +1,8 @@
<div class="root">
<h4 *ngIf="title">{{ title }}</h4>
<div *ngIf="description" class="description">{{ description }}</div>
<div class="videos">
<my-video-miniature
*ngFor="let video of videos"
[video]="video" [user]="getUser()" [displayAsRow]="false"
[displayVideoActions]="false" [displayOptions]="displayOptions"
>
</my-video-miniature>
</div>
<div class="videos">
<my-video-miniature
*ngFor="let video of videos"
[video]="video" [user]="getUser()" [displayAsRow]="false"
[displayVideoActions]="false" [displayOptions]="displayOptions"
>
</my-video-miniature>
</div>

View File

@ -3,6 +3,7 @@
my-video-miniature {
@include margin-right(15px);
display: inline-block;
min-width: $video-thumbnail-width;
max-width: $video-thumbnail-width;

View File

@ -14,8 +14,6 @@ import { MiniatureDisplayOptions } from '../../shared-video-miniature'
styleUrls: [ 'videos-list-markup.component.scss' ]
})
export class VideosListMarkupComponent implements OnInit {
@Input() title: string
@Input() description: string
@Input() sort = '-publishedAt'
@Input() categoryOneOf: number[]
@Input() languageOneOf: string[]

View File

@ -19,8 +19,6 @@ export type ChannelMiniatureMarkupData = {
}
export type VideosListMarkupData = {
title: string
description: string
sort: string
categoryOneOf: string // coma separated values
languageOneOf: string // coma separated values
@ -33,3 +31,9 @@ export type ButtonMarkupData = {
label: string
blankTarget?: string
}
export type ContainerMarkupData = {
width?: string
title?: string
description?: string
}