diff options
Diffstat (limited to 'client/src/app/videos')
6 files changed, 16 insertions, 127 deletions
diff --git a/client/src/app/videos/+video-edit/shared/video-description.component.html b/client/src/app/videos/+video-edit/shared/video-description.component.html deleted file mode 100644 index 989292c47..000000000 --- a/client/src/app/videos/+video-edit/shared/video-description.component.html +++ /dev/null | |||
@@ -1,9 +0,0 @@ | |||
1 | <textarea | ||
2 | [(ngModel)]="description" (ngModelChange)="onModelChange()" | ||
3 | id="description" name="description"> | ||
4 | </textarea> | ||
5 | |||
6 | <tabset *ngIf="arePreviewsDisplayed()" #staticTabs class="previews"> | ||
7 | <tab heading="Truncated description preview" [innerHTML]="truncatedDescriptionHTML"></tab> | ||
8 | <tab heading="Complete description preview" [innerHTML]="descriptionHTML"></tab> | ||
9 | </tabset> | ||
diff --git a/client/src/app/videos/+video-edit/shared/video-description.component.scss b/client/src/app/videos/+video-edit/shared/video-description.component.scss deleted file mode 100644 index 2c731bee3..000000000 --- a/client/src/app/videos/+video-edit/shared/video-description.component.scss +++ /dev/null | |||
@@ -1,24 +0,0 @@ | |||
1 | @import '_variables'; | ||
2 | @import '_mixins'; | ||
3 | |||
4 | textarea { | ||
5 | @include peertube-textarea(100%, 150px); | ||
6 | |||
7 | margin-bottom: 15px; | ||
8 | } | ||
9 | |||
10 | /deep/ { | ||
11 | .nav-link { | ||
12 | display: flex !important; | ||
13 | align-items: center; | ||
14 | height: 30px !important; | ||
15 | padding: 0 15px !important; | ||
16 | } | ||
17 | |||
18 | .tab-content { | ||
19 | min-height: 75px; | ||
20 | padding: 15px; | ||
21 | font-size: 15px; | ||
22 | } | ||
23 | } | ||
24 | |||
diff --git a/client/src/app/videos/+video-edit/shared/video-description.component.ts b/client/src/app/videos/+video-edit/shared/video-description.component.ts deleted file mode 100644 index eba345412..000000000 --- a/client/src/app/videos/+video-edit/shared/video-description.component.ts +++ /dev/null | |||
@@ -1,73 +0,0 @@ | |||
1 | import { Component, forwardRef, Input, OnInit } from '@angular/core' | ||
2 | import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms' | ||
3 | import 'rxjs/add/operator/debounceTime' | ||
4 | import 'rxjs/add/operator/distinctUntilChanged' | ||
5 | import { isInMobileView } from '@app/shared/misc/utils' | ||
6 | import { Subject } from 'rxjs/Subject' | ||
7 | import { MarkdownService } from '../../shared' | ||
8 | import truncate from 'lodash-es/truncate' | ||
9 | |||
10 | @Component({ | ||
11 | selector: 'my-video-description', | ||
12 | templateUrl: './video-description.component.html', | ||
13 | styleUrls: [ './video-description.component.scss' ], | ||
14 | providers: [ | ||
15 | { | ||
16 | provide: NG_VALUE_ACCESSOR, | ||
17 | useExisting: forwardRef(() => VideoDescriptionComponent), | ||
18 | multi: true | ||
19 | } | ||
20 | ] | ||
21 | }) | ||
22 | |||
23 | export class VideoDescriptionComponent implements ControlValueAccessor, OnInit { | ||
24 | @Input() description = '' | ||
25 | truncatedDescriptionHTML = '' | ||
26 | descriptionHTML = '' | ||
27 | |||
28 | private descriptionChanged = new Subject<string>() | ||
29 | |||
30 | constructor (private markdownService: MarkdownService) {} | ||
31 | |||
32 | ngOnInit () { | ||
33 | this.descriptionChanged | ||
34 | .debounceTime(150) | ||
35 | .distinctUntilChanged() | ||
36 | .subscribe(() => this.updateDescriptionPreviews()) | ||
37 | |||
38 | this.descriptionChanged.next(this.description) | ||
39 | } | ||
40 | |||
41 | propagateChange = (_: any) => { /* empty */ } | ||
42 | |||
43 | writeValue (description: string) { | ||
44 | this.description = description | ||
45 | |||
46 | this.descriptionChanged.next(this.description) | ||
47 | } | ||
48 | |||
49 | registerOnChange (fn: (_: any) => void) { | ||
50 | this.propagateChange = fn | ||
51 | } | ||
52 | |||
53 | registerOnTouched () { | ||
54 | // Unused | ||
55 | } | ||
56 | |||
57 | onModelChange () { | ||
58 | this.propagateChange(this.description) | ||
59 | |||
60 | this.descriptionChanged.next(this.description) | ||
61 | } | ||
62 | |||
63 | arePreviewsDisplayed () { | ||
64 | return isInMobileView() === false | ||
65 | } | ||
66 | |||
67 | private updateDescriptionPreviews () { | ||
68 | if (!this.description) return | ||
69 | |||
70 | this.truncatedDescriptionHTML = this.markdownService.markdownToHTML(truncate(this.description, { length: 250 })) | ||
71 | this.descriptionHTML = this.markdownService.markdownToHTML(this.description) | ||
72 | } | ||
73 | } | ||
diff --git a/client/src/app/videos/+video-edit/shared/video-edit.component.html b/client/src/app/videos/+video-edit/shared/video-edit.component.html index 80377933e..d031825bd 100644 --- a/client/src/app/videos/+video-edit/shared/video-edit.component.html +++ b/client/src/app/videos/+video-edit/shared/video-edit.component.html | |||
@@ -12,14 +12,14 @@ | |||
12 | <div class="form-group"> | 12 | <div class="form-group"> |
13 | <label class="label-tags">Tags</label> <span>(press Enter to add)</span> | 13 | <label class="label-tags">Tags</label> <span>(press Enter to add)</span> |
14 | <tag-input | 14 | <tag-input |
15 | [ngModel]="tags" [validators]="tagValidators" [errorMessages]="tagValidatorsMessages" | 15 | [ngModel]="tags" [validators]="tagValidators" [errorMessages]="tagValidatorsMessages" |
16 | formControlName="tags" maxItems="5" modelAsStrings="true" | 16 | formControlName="tags" maxItems="5" modelAsStrings="true" |
17 | ></tag-input> | 17 | ></tag-input> |
18 | </div> | 18 | </div> |
19 | 19 | ||
20 | <div class="form-group"> | 20 | <div class="form-group"> |
21 | <label for="description">Description</label> | 21 | <label for="description">Description</label> |
22 | <my-video-description formControlName="description"></my-video-description> | 22 | <my-markdown-textarea truncate="250" formControlName="description"></my-markdown-textarea> |
23 | 23 | ||
24 | <div *ngIf="formErrors.description" class="form-error"> | 24 | <div *ngIf="formErrors.description" class="form-error"> |
25 | {{ formErrors.description }} | 25 | {{ formErrors.description }} |
diff --git a/client/src/app/videos/+video-edit/shared/video-edit.module.ts b/client/src/app/videos/+video-edit/shared/video-edit.module.ts index ce106d82f..098a71ae6 100644 --- a/client/src/app/videos/+video-edit/shared/video-edit.module.ts +++ b/client/src/app/videos/+video-edit/shared/video-edit.module.ts | |||
@@ -1,23 +1,17 @@ | |||
1 | import { NgModule } from '@angular/core' | 1 | import { NgModule } from '@angular/core' |
2 | |||
3 | import { TagInputModule } from 'ngx-chips' | ||
4 | import { TabsModule } from 'ngx-bootstrap/tabs' | 2 | import { TabsModule } from 'ngx-bootstrap/tabs' |
5 | 3 | import { TagInputModule } from 'ngx-chips' | |
6 | import { MarkdownService } from '../../shared' | ||
7 | import { SharedModule } from '../../../shared' | 4 | import { SharedModule } from '../../../shared' |
8 | import { VideoDescriptionComponent } from './video-description.component' | ||
9 | import { VideoEditComponent } from './video-edit.component' | 5 | import { VideoEditComponent } from './video-edit.component' |
10 | 6 | ||
11 | @NgModule({ | 7 | @NgModule({ |
12 | imports: [ | 8 | imports: [ |
13 | TagInputModule, | 9 | TagInputModule, |
14 | TabsModule.forRoot(), | ||
15 | 10 | ||
16 | SharedModule | 11 | SharedModule |
17 | ], | 12 | ], |
18 | 13 | ||
19 | declarations: [ | 14 | declarations: [ |
20 | VideoDescriptionComponent, | ||
21 | VideoEditComponent | 15 | VideoEditComponent |
22 | ], | 16 | ], |
23 | 17 | ||
@@ -25,12 +19,9 @@ import { VideoEditComponent } from './video-edit.component' | |||
25 | TagInputModule, | 19 | TagInputModule, |
26 | TabsModule, | 20 | TabsModule, |
27 | 21 | ||
28 | VideoDescriptionComponent, | ||
29 | VideoEditComponent | 22 | VideoEditComponent |
30 | ], | 23 | ], |
31 | 24 | ||
32 | providers: [ | 25 | providers: [] |
33 | MarkdownService | ||
34 | ] | ||
35 | }) | 26 | }) |
36 | export class VideoEditModule { } | 27 | export class VideoEditModule { } |
diff --git a/client/src/app/videos/shared/markdown.service.ts b/client/src/app/videos/shared/markdown.service.ts index 82745f0c6..fd0330f9b 100644 --- a/client/src/app/videos/shared/markdown.service.ts +++ b/client/src/app/videos/shared/markdown.service.ts | |||
@@ -14,6 +14,17 @@ export class MarkdownService { | |||
14 | .enable('link') | 14 | .enable('link') |
15 | .enable('newline') | 15 | .enable('newline') |
16 | 16 | ||
17 | this.setTargetToLinks() | ||
18 | } | ||
19 | |||
20 | markdownToHTML (markdown: string) { | ||
21 | const html = this.markdownIt.render(markdown) | ||
22 | |||
23 | // Avoid linkify truncated links | ||
24 | return html.replace(/<a[^>]+>([^<]+)<\/a>\s*...(<\/p>)?$/mi, '$1...') | ||
25 | } | ||
26 | |||
27 | private setTargetToLinks () { | ||
17 | // Snippet from markdown-it documentation: https://github.com/markdown-it/markdown-it/blob/master/docs/architecture.md#renderer | 28 | // Snippet from markdown-it documentation: https://github.com/markdown-it/markdown-it/blob/master/docs/architecture.md#renderer |
18 | const defaultRender = this.markdownIt.renderer.rules.link_open || function (tokens, idx, options, env, self) { | 29 | const defaultRender = this.markdownIt.renderer.rules.link_open || function (tokens, idx, options, env, self) { |
19 | return self.renderToken(tokens, idx, options) | 30 | return self.renderToken(tokens, idx, options) |
@@ -33,11 +44,4 @@ export class MarkdownService { | |||
33 | return defaultRender(tokens, idx, options, env, self) | 44 | return defaultRender(tokens, idx, options, env, self) |
34 | } | 45 | } |
35 | } | 46 | } |
36 | |||
37 | markdownToHTML (markdown: string) { | ||
38 | const html = this.markdownIt.render(markdown) | ||
39 | |||
40 | // Avoid linkify truncated links | ||
41 | return html.replace(/<a[^>]+>([^<]+)<\/a>\s*...(<\/p>)?$/mi, '$1...') | ||
42 | } | ||
43 | } | 47 | } |