aboutsummaryrefslogtreecommitdiffhomepage
path: root/client/src/app/shared
diff options
context:
space:
mode:
Diffstat (limited to 'client/src/app/shared')
-rw-r--r--client/src/app/shared/forms/form-validators/custom-config.ts7
-rw-r--r--client/src/app/shared/forms/markdown-textarea.component.html12
-rw-r--r--client/src/app/shared/forms/markdown-textarea.component.scss27
-rw-r--r--client/src/app/shared/forms/markdown-textarea.component.ts86
-rw-r--r--client/src/app/shared/shared.module.ts13
-rw-r--r--client/src/app/shared/video/video.service.ts8
6 files changed, 146 insertions, 7 deletions
diff --git a/client/src/app/shared/forms/form-validators/custom-config.ts b/client/src/app/shared/forms/form-validators/custom-config.ts
index 17ae0e75c..9e3fa98d8 100644
--- a/client/src/app/shared/forms/form-validators/custom-config.ts
+++ b/client/src/app/shared/forms/form-validators/custom-config.ts
@@ -1,5 +1,12 @@
1import { Validators } from '@angular/forms' 1import { Validators } from '@angular/forms'
2 2
3export const INSTANCE_NAME = {
4 VALIDATORS: [ Validators.required ],
5 MESSAGES: {
6 'required': 'Instance name is required.',
7 }
8}
9
3export const CACHE_PREVIEWS_SIZE = { 10export const CACHE_PREVIEWS_SIZE = {
4 VALIDATORS: [ Validators.required, Validators.min(1), Validators.pattern('[0-9]+') ], 11 VALIDATORS: [ Validators.required, Validators.min(1), Validators.pattern('[0-9]+') ],
5 MESSAGES: { 12 MESSAGES: {
diff --git a/client/src/app/shared/forms/markdown-textarea.component.html b/client/src/app/shared/forms/markdown-textarea.component.html
new file mode 100644
index 000000000..d2d4cf95c
--- /dev/null
+++ b/client/src/app/shared/forms/markdown-textarea.component.html
@@ -0,0 +1,12 @@
1<div class="root" [ngStyle]="{ 'flex-direction': flexDirection }">
2 <textarea
3 [(ngModel)]="description" (ngModelChange)="onModelChange()"
4 [ngClass]="classes" [ngStyle]="{ width: textareaWidth, height: textareaHeight, 'margin-right': textareaMarginRight }"
5 id="description" name="description">
6 </textarea>
7
8 <tabset *ngIf="arePreviewsDisplayed()" #staticTabs class="previews">
9 <tab *ngIf="truncate !== undefined" heading="Truncated description preview" [innerHTML]="truncatedDescriptionHTML"></tab>
10 <tab heading="Complete description preview" [innerHTML]="descriptionHTML"></tab>
11 </tabset>
12</div>
diff --git a/client/src/app/shared/forms/markdown-textarea.component.scss b/client/src/app/shared/forms/markdown-textarea.component.scss
new file mode 100644
index 000000000..82aff541d
--- /dev/null
+++ b/client/src/app/shared/forms/markdown-textarea.component.scss
@@ -0,0 +1,27 @@
1@import '_variables';
2@import '_mixins';
3
4.root {
5 display: flex;
6
7 textarea {
8 @include peertube-textarea(100%, 150px);
9
10 margin-bottom: 15px;
11 }
12
13 /deep/ {
14 .nav-link {
15 display: flex !important;
16 align-items: center;
17 height: 30px !important;
18 padding: 0 15px !important;
19 }
20
21 .tab-content {
22 min-height: 75px;
23 padding: 15px;
24 font-size: 15px;
25 }
26 }
27}
diff --git a/client/src/app/shared/forms/markdown-textarea.component.ts b/client/src/app/shared/forms/markdown-textarea.component.ts
new file mode 100644
index 000000000..20f13b28c
--- /dev/null
+++ b/client/src/app/shared/forms/markdown-textarea.component.ts
@@ -0,0 +1,86 @@
1import { Component, forwardRef, Input, OnInit } from '@angular/core'
2import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'
3import 'rxjs/add/operator/debounceTime'
4import 'rxjs/add/operator/distinctUntilChanged'
5import { isInMobileView } from '@app/shared/misc/utils'
6import { MarkdownService } from '@app/videos/shared'
7import { Subject } from 'rxjs/Subject'
8import truncate from 'lodash-es/truncate'
9
10@Component({
11 selector: 'my-markdown-textarea',
12 templateUrl: './markdown-textarea.component.html',
13 styleUrls: [ './markdown-textarea.component.scss' ],
14 providers: [
15 {
16 provide: NG_VALUE_ACCESSOR,
17 useExisting: forwardRef(() => MarkdownTextareaComponent),
18 multi: true
19 }
20 ]
21})
22
23export class MarkdownTextareaComponent implements ControlValueAccessor, OnInit {
24 @Input() description = ''
25 @Input() classes: string[] = []
26 @Input() textareaWidth = '100%'
27 @Input() textareaHeight = '150px'
28 @Input() previewColumn = false
29 @Input() truncate: number
30
31 textareaMarginRight = '0'
32 flexDirection = 'column'
33 truncatedDescriptionHTML = ''
34 descriptionHTML = ''
35
36 private descriptionChanged = new Subject<string>()
37
38 constructor (private markdownService: MarkdownService) {}
39
40 ngOnInit () {
41 this.descriptionChanged
42 .debounceTime(150)
43 .distinctUntilChanged()
44 .subscribe(() => this.updateDescriptionPreviews())
45
46 this.descriptionChanged.next(this.description)
47
48 if (this.previewColumn) {
49 this.flexDirection = 'row'
50 this.textareaMarginRight = '15px'
51 }
52 }
53
54 propagateChange = (_: any) => { /* empty */ }
55
56 writeValue (description: string) {
57 this.description = description
58
59 this.descriptionChanged.next(this.description)
60 }
61
62 registerOnChange (fn: (_: any) => void) {
63 this.propagateChange = fn
64 }
65
66 registerOnTouched () {
67 // Unused
68 }
69
70 onModelChange () {
71 this.propagateChange(this.description)
72
73 this.descriptionChanged.next(this.description)
74 }
75
76 arePreviewsDisplayed () {
77 return isInMobileView() === false
78 }
79
80 private updateDescriptionPreviews () {
81 if (this.description === null || this.description === undefined) return
82
83 this.truncatedDescriptionHTML = this.markdownService.markdownToHTML(truncate(this.description, { length: this.truncate }))
84 this.descriptionHTML = this.markdownService.markdownToHTML(this.description)
85 }
86}
diff --git a/client/src/app/shared/shared.module.ts b/client/src/app/shared/shared.module.ts
index a5c56cb46..d8f98bdf6 100644
--- a/client/src/app/shared/shared.module.ts
+++ b/client/src/app/shared/shared.module.ts
@@ -3,10 +3,13 @@ import { HttpClientModule } from '@angular/common/http'
3import { NgModule } from '@angular/core' 3import { NgModule } from '@angular/core'
4import { FormsModule, ReactiveFormsModule } from '@angular/forms' 4import { FormsModule, ReactiveFormsModule } from '@angular/forms'
5import { RouterModule } from '@angular/router' 5import { RouterModule } from '@angular/router'
6import { MarkdownTextareaComponent } from '@app/shared/forms/markdown-textarea.component'
7import { MarkdownService } from '@app/videos/shared'
6import { LoadingBarHttpClientModule } from '@ngx-loading-bar/http-client' 8import { LoadingBarHttpClientModule } from '@ngx-loading-bar/http-client'
7 9
8import { BsDropdownModule } from 'ngx-bootstrap/dropdown' 10import { BsDropdownModule } from 'ngx-bootstrap/dropdown'
9import { ModalModule } from 'ngx-bootstrap/modal' 11import { ModalModule } from 'ngx-bootstrap/modal'
12import { TabsModule } from 'ngx-bootstrap/tabs'
10import { InfiniteScrollModule } from 'ngx-infinite-scroll' 13import { InfiniteScrollModule } from 'ngx-infinite-scroll'
11import { BytesPipe, KeysPipe, NgPipesModule } from 'ngx-pipes' 14import { BytesPipe, KeysPipe, NgPipesModule } from 'ngx-pipes'
12import { SharedModule as PrimeSharedModule } from 'primeng/components/common/shared' 15import { SharedModule as PrimeSharedModule } from 'primeng/components/common/shared'
@@ -40,7 +43,8 @@ import { VideoService } from './video/video.service'
40 43
41 PrimeSharedModule, 44 PrimeSharedModule,
42 InfiniteScrollModule, 45 InfiniteScrollModule,
43 NgPipesModule 46 NgPipesModule,
47 TabsModule.forRoot()
44 ], 48 ],
45 49
46 declarations: [ 50 declarations: [
@@ -50,7 +54,8 @@ import { VideoService } from './video/video.service'
50 DeleteButtonComponent, 54 DeleteButtonComponent,
51 EditButtonComponent, 55 EditButtonComponent,
52 NumberFormatterPipe, 56 NumberFormatterPipe,
53 FromNowPipe 57 FromNowPipe,
58 MarkdownTextareaComponent
54 ], 59 ],
55 60
56 exports: [ 61 exports: [
@@ -74,6 +79,7 @@ import { VideoService } from './video/video.service'
74 VideoMiniatureComponent, 79 VideoMiniatureComponent,
75 DeleteButtonComponent, 80 DeleteButtonComponent,
76 EditButtonComponent, 81 EditButtonComponent,
82 MarkdownTextareaComponent,
77 83
78 NumberFormatterPipe, 84 NumberFormatterPipe,
79 FromNowPipe 85 FromNowPipe
@@ -86,7 +92,8 @@ import { VideoService } from './video/video.service'
86 VideoAbuseService, 92 VideoAbuseService,
87 VideoBlacklistService, 93 VideoBlacklistService,
88 UserService, 94 UserService,
89 VideoService 95 VideoService,
96 MarkdownService
90 ] 97 ]
91}) 98})
92export class SharedModule { } 99export class SharedModule { }
diff --git a/client/src/app/shared/video/video.service.ts b/client/src/app/shared/video/video.service.ts
index 50761ca0c..d4f5e258f 100644
--- a/client/src/app/shared/video/video.service.ts
+++ b/client/src/app/shared/video/video.service.ts
@@ -42,10 +42,10 @@ export class VideoService {
42 } 42 }
43 43
44 updateVideo (video: VideoEdit) { 44 updateVideo (video: VideoEdit) {
45 const language = video.language || undefined 45 const language = video.language || null
46 const licence = video.licence || undefined 46 const licence = video.licence || null
47 const category = video.category || undefined 47 const category = video.category || null
48 const description = video.description || undefined 48 const description = video.description || null
49 49
50 const body: VideoUpdate = { 50 const body: VideoUpdate = {
51 name: video.name, 51 name: video.name,