Create peertube-container html tag
This commit is contained in:
parent
17b064e394
commit
f7894f0964
|
@ -1 +1 @@
|
||||||
<div #contentWrapper></div>
|
<div class="custom-markup-container" #contentWrapper></div>
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
.custom-markup-container {
|
||||||
|
|
||||||
|
::ng-deep .peertube-container {
|
||||||
|
margin: 30px 0 15px;
|
||||||
|
|
||||||
|
h4 {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,7 +3,8 @@ import { CustomMarkupService } from './custom-markup.service'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'my-custom-markup-container',
|
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 {
|
export class CustomMarkupContainerComponent implements OnChanges {
|
||||||
@ViewChild('contentWrapper') contentWrapper: ElementRef<HTMLInputElement>
|
@ViewChild('contentWrapper') contentWrapper: ElementRef<HTMLInputElement>
|
||||||
|
|
|
@ -3,6 +3,7 @@ import { MarkdownService } from '@app/core'
|
||||||
import {
|
import {
|
||||||
ButtonMarkupData,
|
ButtonMarkupData,
|
||||||
ChannelMiniatureMarkupData,
|
ChannelMiniatureMarkupData,
|
||||||
|
ContainerMarkupData,
|
||||||
EmbedMarkupData,
|
EmbedMarkupData,
|
||||||
PlaylistMiniatureMarkupData,
|
PlaylistMiniatureMarkupData,
|
||||||
VideoMiniatureMarkupData,
|
VideoMiniatureMarkupData,
|
||||||
|
@ -18,11 +19,12 @@ import {
|
||||||
VideosListMarkupComponent
|
VideosListMarkupComponent
|
||||||
} from './peertube-custom-tags'
|
} from './peertube-custom-tags'
|
||||||
|
|
||||||
type BuilderFunction = (el: HTMLElement) => ComponentRef<any>
|
type AngularBuilderFunction = (el: HTMLElement) => ComponentRef<any>
|
||||||
|
type HTMLBuilderFunction = (el: HTMLElement) => HTMLElement
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class CustomMarkupService {
|
export class CustomMarkupService {
|
||||||
private builders: { [ selector: string ]: BuilderFunction } = {
|
private angularBuilders: { [ selector: string ]: AngularBuilderFunction } = {
|
||||||
'peertube-button': el => this.buttonBuilder(el),
|
'peertube-button': el => this.buttonBuilder(el),
|
||||||
'peertube-video-embed': el => this.embedBuilder(el, 'video'),
|
'peertube-video-embed': el => this.embedBuilder(el, 'video'),
|
||||||
'peertube-playlist-embed': el => this.embedBuilder(el, 'playlist'),
|
'peertube-playlist-embed': el => this.embedBuilder(el, 'playlist'),
|
||||||
|
@ -32,6 +34,10 @@ export class CustomMarkupService {
|
||||||
'peertube-videos-list': el => this.videosListBuilder(el)
|
'peertube-videos-list': el => this.videosListBuilder(el)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private htmlBuilders: { [ selector: string ]: HTMLBuilderFunction } = {
|
||||||
|
'peertube-container': el => this.containerBuilder(el)
|
||||||
|
}
|
||||||
|
|
||||||
private customMarkdownRenderer: (text: string) => Promise<HTMLElement>
|
private customMarkdownRenderer: (text: string) => Promise<HTMLElement>
|
||||||
|
|
||||||
constructor (
|
constructor (
|
||||||
|
@ -51,11 +57,24 @@ export class CustomMarkupService {
|
||||||
const rootElement = document.createElement('div')
|
const rootElement = document.createElement('div')
|
||||||
rootElement.innerHTML = html
|
rootElement.innerHTML = html
|
||||||
|
|
||||||
for (const selector of this.getSupportedTags()) {
|
for (const selector of Object.keys(this.htmlBuilders)) {
|
||||||
rootElement.querySelectorAll(selector)
|
rootElement.querySelectorAll(selector)
|
||||||
.forEach((e: HTMLElement) => {
|
.forEach((e: HTMLElement) => {
|
||||||
try {
|
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)
|
this.dynamicElementService.injectElement(e, component)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
@ -68,11 +87,16 @@ export class CustomMarkupService {
|
||||||
}
|
}
|
||||||
|
|
||||||
private getSupportedTags () {
|
private getSupportedTags () {
|
||||||
return Object.keys(this.builders)
|
return Object.keys(this.angularBuilders)
|
||||||
|
.concat(Object.keys(this.htmlBuilders))
|
||||||
}
|
}
|
||||||
|
|
||||||
private execBuilder (selector: string, el: HTMLElement) {
|
private execHTMLBuilder (selector: string, el: HTMLElement) {
|
||||||
return this.builders[selector](el)
|
return this.htmlBuilders[selector](el)
|
||||||
|
}
|
||||||
|
|
||||||
|
private execAngularBuilder (selector: string, el: HTMLElement) {
|
||||||
|
return this.angularBuilders[selector](el)
|
||||||
}
|
}
|
||||||
|
|
||||||
private embedBuilder (el: HTMLElement, type: 'video' | 'playlist') {
|
private embedBuilder (el: HTMLElement, type: 'video' | 'playlist') {
|
||||||
|
@ -131,8 +155,6 @@ export class CustomMarkupService {
|
||||||
const component = this.dynamicElementService.createElement(VideosListMarkupComponent)
|
const component = this.dynamicElementService.createElement(VideosListMarkupComponent)
|
||||||
|
|
||||||
const model = {
|
const model = {
|
||||||
title: data.title,
|
|
||||||
description: data.description,
|
|
||||||
sort: data.sort,
|
sort: data.sort,
|
||||||
categoryOneOf: this.buildArrayNumber(data.categoryOneOf),
|
categoryOneOf: this.buildArrayNumber(data.categoryOneOf),
|
||||||
languageOneOf: this.buildArrayString(data.languageOneOf),
|
languageOneOf: this.buildArrayString(data.languageOneOf),
|
||||||
|
@ -144,6 +166,31 @@ export class CustomMarkupService {
|
||||||
return component
|
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) {
|
private buildNumber (value: string) {
|
||||||
if (!value) return undefined
|
if (!value) return undefined
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,8 @@
|
||||||
<div class="root">
|
<div class="videos">
|
||||||
<h4 *ngIf="title">{{ title }}</h4>
|
<my-video-miniature
|
||||||
<div *ngIf="description" class="description">{{ description }}</div>
|
*ngFor="let video of videos"
|
||||||
|
[video]="video" [user]="getUser()" [displayAsRow]="false"
|
||||||
<div class="videos">
|
[displayVideoActions]="false" [displayOptions]="displayOptions"
|
||||||
<my-video-miniature
|
>
|
||||||
*ngFor="let video of videos"
|
</my-video-miniature>
|
||||||
[video]="video" [user]="getUser()" [displayAsRow]="false"
|
|
||||||
[displayVideoActions]="false" [displayOptions]="displayOptions"
|
|
||||||
>
|
|
||||||
</my-video-miniature>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
my-video-miniature {
|
my-video-miniature {
|
||||||
@include margin-right(15px);
|
@include margin-right(15px);
|
||||||
|
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
min-width: $video-thumbnail-width;
|
min-width: $video-thumbnail-width;
|
||||||
max-width: $video-thumbnail-width;
|
max-width: $video-thumbnail-width;
|
||||||
|
|
|
@ -14,8 +14,6 @@ import { MiniatureDisplayOptions } from '../../shared-video-miniature'
|
||||||
styleUrls: [ 'videos-list-markup.component.scss' ]
|
styleUrls: [ 'videos-list-markup.component.scss' ]
|
||||||
})
|
})
|
||||||
export class VideosListMarkupComponent implements OnInit {
|
export class VideosListMarkupComponent implements OnInit {
|
||||||
@Input() title: string
|
|
||||||
@Input() description: string
|
|
||||||
@Input() sort = '-publishedAt'
|
@Input() sort = '-publishedAt'
|
||||||
@Input() categoryOneOf: number[]
|
@Input() categoryOneOf: number[]
|
||||||
@Input() languageOneOf: string[]
|
@Input() languageOneOf: string[]
|
||||||
|
|
|
@ -19,8 +19,6 @@ export type ChannelMiniatureMarkupData = {
|
||||||
}
|
}
|
||||||
|
|
||||||
export type VideosListMarkupData = {
|
export type VideosListMarkupData = {
|
||||||
title: string
|
|
||||||
description: string
|
|
||||||
sort: string
|
sort: string
|
||||||
categoryOneOf: string // coma separated values
|
categoryOneOf: string // coma separated values
|
||||||
languageOneOf: string // coma separated values
|
languageOneOf: string // coma separated values
|
||||||
|
@ -33,3 +31,9 @@ export type ButtonMarkupData = {
|
||||||
label: string
|
label: string
|
||||||
blankTarget?: string
|
blankTarget?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type ContainerMarkupData = {
|
||||||
|
width?: string
|
||||||
|
title?: string
|
||||||
|
description?: string
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue