diff options
8 files changed, 35 insertions, 141 deletions
diff --git a/client/package.json b/client/package.json index e8b2a1c35..00eb0e272 100644 --- a/client/package.json +++ b/client/package.json | |||
@@ -58,7 +58,7 @@ | |||
58 | "ng-router-loader": "^1.0.2", | 58 | "ng-router-loader": "^1.0.2", |
59 | "ng2-file-upload": "^1.1.4-2", | 59 | "ng2-file-upload": "^1.1.4-2", |
60 | "ng2-smart-table": "1.0.3", | 60 | "ng2-smart-table": "1.0.3", |
61 | "ng2-tag-input": "1.0.1", | 61 | "ng2-tag-input": "^1.0.5", |
62 | "ngc-webpack": "1.1.0", | 62 | "ngc-webpack": "1.1.0", |
63 | "ngx-bootstrap": "1.6.6", | 63 | "ngx-bootstrap": "1.6.6", |
64 | "node-sass": "^4.1.1", | 64 | "node-sass": "^4.1.1", |
diff --git a/client/src/app/shared/forms/form-validators/video.ts b/client/src/app/shared/forms/form-validators/video.ts index 293fd805f..f7e4e5e4b 100644 --- a/client/src/app/shared/forms/form-validators/video.ts +++ b/client/src/app/shared/forms/form-validators/video.ts | |||
@@ -38,8 +38,9 @@ export const VIDEO_DESCRIPTION = { | |||
38 | }; | 38 | }; |
39 | 39 | ||
40 | export const VIDEO_TAGS = { | 40 | export const VIDEO_TAGS = { |
41 | VALIDATORS: [ Validators.maxLength(10) ], | 41 | VALIDATORS: [ Validators.minLength(2), Validators.maxLength(10) ], |
42 | MESSAGES: { | 42 | MESSAGES: { |
43 | 'minlength': 'A tag should be more than 2 characters long.', | ||
43 | 'maxlength': 'A tag should be less than 10 characters long.' | 44 | 'maxlength': 'A tag should be less than 10 characters long.' |
44 | } | 45 | } |
45 | }; | 46 | }; |
diff --git a/client/src/app/videos/video-edit/video-add.component.html b/client/src/app/videos/video-edit/video-add.component.html index 104747a8c..04f4f85b0 100644 --- a/client/src/app/videos/video-edit/video-add.component.html +++ b/client/src/app/videos/video-edit/video-add.component.html | |||
@@ -59,25 +59,11 @@ | |||
59 | </div> | 59 | </div> |
60 | 60 | ||
61 | <div class="form-group"> | 61 | <div class="form-group"> |
62 | <label for="tags">Tags</label> <span class="little-information">(press enter to add the tag)</span> | 62 | <label for="tags" class="label-tags">Tags</label> <span class="little-information">(press enter to add the tag)</span> |
63 | <input | 63 | <tag-input |
64 | type="text" class="form-control" id="currentTag" | 64 | [ngModel]="tags" [validators]="tagValidators" [errorMessages]="tagValidatorsMessages" |
65 | formControlName="currentTag" (keyup)="onTagKeyPress($event)" | 65 | formControlName="tags" maxItems="3" modelAsStrings="true" |
66 | > | 66 | ></tag-input> |
67 | <div *ngIf="formErrors.currentTag" class="alert alert-danger"> | ||
68 | {{ formErrors.currentTag }} | ||
69 | </div> | ||
70 | </div> | ||
71 | |||
72 | <div class="tags"> | ||
73 | <div class="label label-primary tag" *ngFor="let tag of tags"> | ||
74 | {{ tag }} | ||
75 | <span class="remove" (click)="removeTag(tag)">x</span> | ||
76 | </div> | ||
77 | </div> | ||
78 | |||
79 | <div *ngIf="tagsError" class="alert alert-danger"> | ||
80 | {{ tagsError }} | ||
81 | </div> | 67 | </div> |
82 | 68 | ||
83 | <div class="form-group"> | 69 | <div class="form-group"> |
diff --git a/client/src/app/videos/video-edit/video-add.component.ts b/client/src/app/videos/video-edit/video-add.component.ts index e3cf0e9d8..21343880d 100644 --- a/client/src/app/videos/video-edit/video-add.component.ts +++ b/client/src/app/videos/video-edit/video-add.component.ts | |||
@@ -30,6 +30,9 @@ export class VideoAddComponent extends FormReactive implements OnInit { | |||
30 | videoLicences = []; | 30 | videoLicences = []; |
31 | videoLanguages = []; | 31 | videoLanguages = []; |
32 | 32 | ||
33 | tagValidators = VIDEO_TAGS.VALIDATORS; | ||
34 | tagValidatorsMessages = VIDEO_TAGS.MESSAGES; | ||
35 | |||
33 | error: string = null; | 36 | error: string = null; |
34 | form: FormGroup; | 37 | form: FormGroup; |
35 | formErrors = { | 38 | formErrors = { |
@@ -37,20 +40,17 @@ export class VideoAddComponent extends FormReactive implements OnInit { | |||
37 | category: '', | 40 | category: '', |
38 | licence: '', | 41 | licence: '', |
39 | language: '', | 42 | language: '', |
40 | description: '', | 43 | description: '' |
41 | currentTag: '' | ||
42 | }; | 44 | }; |
43 | validationMessages = { | 45 | validationMessages = { |
44 | name: VIDEO_NAME.MESSAGES, | 46 | name: VIDEO_NAME.MESSAGES, |
45 | category: VIDEO_CATEGORY.MESSAGES, | 47 | category: VIDEO_CATEGORY.MESSAGES, |
46 | licence: VIDEO_LICENCE.MESSAGES, | 48 | licence: VIDEO_LICENCE.MESSAGES, |
47 | language: VIDEO_LANGUAGE.MESSAGES, | 49 | language: VIDEO_LANGUAGE.MESSAGES, |
48 | description: VIDEO_DESCRIPTION.MESSAGES, | 50 | description: VIDEO_DESCRIPTION.MESSAGES |
49 | currentTag: VIDEO_TAGS.MESSAGES | ||
50 | }; | 51 | }; |
51 | 52 | ||
52 | // Special error messages | 53 | // Special error messages |
53 | tagsError = ''; | ||
54 | fileError = ''; | 54 | fileError = ''; |
55 | 55 | ||
56 | constructor( | 56 | constructor( |
@@ -80,7 +80,7 @@ export class VideoAddComponent extends FormReactive implements OnInit { | |||
80 | licence: [ '', VIDEO_LICENCE.VALIDATORS ], | 80 | licence: [ '', VIDEO_LICENCE.VALIDATORS ], |
81 | language: [ '', VIDEO_LANGUAGE.VALIDATORS ], | 81 | language: [ '', VIDEO_LANGUAGE.VALIDATORS ], |
82 | description: [ '', VIDEO_DESCRIPTION.VALIDATORS ], | 82 | description: [ '', VIDEO_DESCRIPTION.VALIDATORS ], |
83 | currentTag: [ '', VIDEO_TAGS.VALIDATORS ] | 83 | tags: [ ''] |
84 | }); | 84 | }); |
85 | 85 | ||
86 | this.form.valueChanges.subscribe(data => this.onValueChanged(data)); | 86 | this.form.valueChanges.subscribe(data => this.onValueChanged(data)); |
@@ -105,6 +105,7 @@ export class VideoAddComponent extends FormReactive implements OnInit { | |||
105 | const licence = this.form.value['licence']; | 105 | const licence = this.form.value['licence']; |
106 | const language = this.form.value['language']; | 106 | const language = this.form.value['language']; |
107 | const description = this.form.value['description']; | 107 | const description = this.form.value['description']; |
108 | const tags = this.form.value['tags']; | ||
108 | 109 | ||
109 | form.append('name', name); | 110 | form.append('name', name); |
110 | form.append('category', category); | 111 | form.append('category', category); |
@@ -118,8 +119,8 @@ export class VideoAddComponent extends FormReactive implements OnInit { | |||
118 | 119 | ||
119 | form.append('description', description); | 120 | form.append('description', description); |
120 | 121 | ||
121 | for (let i = 0; i < this.tags.length; i++) { | 122 | for (let i = 0; i < tags.length; i++) { |
122 | form.append(`tags[${i}]`, this.tags[i]); | 123 | form.append(`tags[${i}]`, tags[i]); |
123 | } | 124 | } |
124 | }; | 125 | }; |
125 | 126 | ||
@@ -133,33 +134,18 @@ export class VideoAddComponent extends FormReactive implements OnInit { | |||
133 | this.fileError = 'You did not add a file.'; | 134 | this.fileError = 'You did not add a file.'; |
134 | } | 135 | } |
135 | 136 | ||
136 | return this.form.valid === true && this.tagsError === '' && this.fileError === ''; | 137 | return this.form.valid === true && this.fileError === ''; |
137 | } | 138 | } |
138 | 139 | ||
139 | fileChanged() { | 140 | fileChanged() { |
140 | this.fileError = ''; | 141 | this.fileError = ''; |
141 | } | 142 | } |
142 | 143 | ||
143 | onTagKeyPress(event: KeyboardEvent) { | ||
144 | // Enter press | ||
145 | if (event.keyCode === 13) { | ||
146 | this.addTagIfPossible(); | ||
147 | } | ||
148 | } | ||
149 | |||
150 | removeFile() { | 144 | removeFile() { |
151 | this.uploader.clearQueue(); | 145 | this.uploader.clearQueue(); |
152 | } | 146 | } |
153 | 147 | ||
154 | removeTag(tag: string) { | ||
155 | this.tags.splice(this.tags.indexOf(tag), 1); | ||
156 | this.form.get('currentTag').enable(); | ||
157 | } | ||
158 | |||
159 | upload() { | 148 | upload() { |
160 | // Maybe the user forgot to press "enter" when he filled the field | ||
161 | this.addTagIfPossible(); | ||
162 | |||
163 | if (this.checkForm() === false) { | 149 | if (this.checkForm() === false) { |
164 | return; | 150 | return; |
165 | } | 151 | } |
@@ -206,25 +192,4 @@ export class VideoAddComponent extends FormReactive implements OnInit { | |||
206 | 192 | ||
207 | this.uploader.uploadAll(); | 193 | this.uploader.uploadAll(); |
208 | } | 194 | } |
209 | |||
210 | private addTagIfPossible() { | ||
211 | const currentTag = this.form.value['currentTag']; | ||
212 | if (currentTag === undefined) return; | ||
213 | |||
214 | // Check if the tag is valid and does not already exist | ||
215 | if ( | ||
216 | currentTag.length >= 2 && | ||
217 | this.form.controls['currentTag'].valid && | ||
218 | this.tags.indexOf(currentTag) === -1 | ||
219 | ) { | ||
220 | this.tags.push(currentTag); | ||
221 | this.form.patchValue({ currentTag: '' }); | ||
222 | |||
223 | if (this.tags.length >= 3) { | ||
224 | this.form.get('currentTag').disable(); | ||
225 | } | ||
226 | |||
227 | this.tagsError = ''; | ||
228 | } | ||
229 | } | ||
230 | } | 195 | } |
diff --git a/client/src/app/videos/video-edit/video-edit.component.scss b/client/src/app/videos/video-edit/video-edit.component.scss index 92b731191..9ee0c520c 100644 --- a/client/src/app/videos/video-edit/video-edit.component.scss +++ b/client/src/app/videos/video-edit/video-edit.component.scss | |||
@@ -50,3 +50,7 @@ div.file-to-upload { | |||
50 | font-size: 0.8em; | 50 | font-size: 0.8em; |
51 | font-style: italic; | 51 | font-style: italic; |
52 | } | 52 | } |
53 | |||
54 | .label-tags { | ||
55 | margin-bottom: 0; | ||
56 | } | ||
diff --git a/client/src/app/videos/video-edit/video-update.component.html b/client/src/app/videos/video-edit/video-update.component.html index 2e10d5bf7..bedbc91b8 100644 --- a/client/src/app/videos/video-edit/video-update.component.html +++ b/client/src/app/videos/video-edit/video-update.component.html | |||
@@ -59,25 +59,11 @@ | |||
59 | </div> | 59 | </div> |
60 | 60 | ||
61 | <div class="form-group"> | 61 | <div class="form-group"> |
62 | <label for="tags">Tags</label> <span class="little-information">(press enter to add the tag)</span> | 62 | <label for="tags" class="label-tags">Tags</label> <span class="little-information">(press enter to add the tag)</span> |
63 | <input | 63 | <tag-input |
64 | type="text" class="form-control" id="currentTag" | 64 | [ngModel]="tags" [validators]="tagValidators" [errorMessages]="tagValidatorsMessages" |
65 | formControlName="currentTag" (keyup)="onTagKeyPress($event)" | 65 | formControlName="tags" maxItems="3" modelAsStrings="true" |
66 | > | 66 | ></tag-input> |
67 | <div *ngIf="formErrors.currentTag" class="alert alert-danger"> | ||
68 | {{ formErrors.currentTag }} | ||
69 | </div> | ||
70 | </div> | ||
71 | |||
72 | <div class="tags"> | ||
73 | <div class="label label-primary tag" *ngFor="let tag of tags"> | ||
74 | {{ tag }} | ||
75 | <span class="remove" (click)="removeTag(tag)">x</span> | ||
76 | </div> | ||
77 | </div> | ||
78 | |||
79 | <div *ngIf="tagsError" class="alert alert-danger"> | ||
80 | {{ tagsError }} | ||
81 | </div> | 67 | </div> |
82 | 68 | ||
83 | <div class="form-group"> | 69 | <div class="form-group"> |
diff --git a/client/src/app/videos/video-edit/video-update.component.ts b/client/src/app/videos/video-edit/video-update.component.ts index b45780a41..adb3d295c 100644 --- a/client/src/app/videos/video-edit/video-update.component.ts +++ b/client/src/app/videos/video-edit/video-update.component.ts | |||
@@ -30,6 +30,9 @@ export class VideoUpdateComponent extends FormReactive implements OnInit { | |||
30 | videoLanguages = []; | 30 | videoLanguages = []; |
31 | video: Video; | 31 | video: Video; |
32 | 32 | ||
33 | tagValidators = VIDEO_TAGS.VALIDATORS; | ||
34 | tagValidatorsMessages = VIDEO_TAGS.MESSAGES; | ||
35 | |||
33 | error: string = null; | 36 | error: string = null; |
34 | form: FormGroup; | 37 | form: FormGroup; |
35 | formErrors = { | 38 | formErrors = { |
@@ -37,20 +40,16 @@ export class VideoUpdateComponent extends FormReactive implements OnInit { | |||
37 | category: '', | 40 | category: '', |
38 | licence: '', | 41 | licence: '', |
39 | language: '', | 42 | language: '', |
40 | description: '', | 43 | description: '' |
41 | currentTag: '' | ||
42 | }; | 44 | }; |
43 | validationMessages = { | 45 | validationMessages = { |
44 | name: VIDEO_NAME.MESSAGES, | 46 | name: VIDEO_NAME.MESSAGES, |
45 | category: VIDEO_CATEGORY.MESSAGES, | 47 | category: VIDEO_CATEGORY.MESSAGES, |
46 | licence: VIDEO_LICENCE.MESSAGES, | 48 | licence: VIDEO_LICENCE.MESSAGES, |
47 | language: VIDEO_LANGUAGE.MESSAGES, | 49 | language: VIDEO_LANGUAGE.MESSAGES, |
48 | description: VIDEO_DESCRIPTION.MESSAGES, | 50 | description: VIDEO_DESCRIPTION.MESSAGES |
49 | currentTag: VIDEO_TAGS.MESSAGES | ||
50 | }; | 51 | }; |
51 | 52 | ||
52 | // Special error messages | ||
53 | tagsError = ''; | ||
54 | fileError = ''; | 53 | fileError = ''; |
55 | 54 | ||
56 | constructor( | 55 | constructor( |
@@ -73,7 +72,7 @@ export class VideoUpdateComponent extends FormReactive implements OnInit { | |||
73 | licence: [ '', VIDEO_LICENCE.VALIDATORS ], | 72 | licence: [ '', VIDEO_LICENCE.VALIDATORS ], |
74 | language: [ '', VIDEO_LANGUAGE.VALIDATORS ], | 73 | language: [ '', VIDEO_LANGUAGE.VALIDATORS ], |
75 | description: [ '', VIDEO_DESCRIPTION.VALIDATORS ], | 74 | description: [ '', VIDEO_DESCRIPTION.VALIDATORS ], |
76 | currentTag: [ '', VIDEO_TAGS.VALIDATORS ] | 75 | tags: [ '' ] |
77 | }); | 76 | }); |
78 | 77 | ||
79 | this.form.valueChanges.subscribe(data => this.onValueChanged(data)); | 78 | this.form.valueChanges.subscribe(data => this.onValueChanged(data)); |
@@ -99,33 +98,7 @@ export class VideoUpdateComponent extends FormReactive implements OnInit { | |||
99 | ); | 98 | ); |
100 | } | 99 | } |
101 | 100 | ||
102 | checkForm() { | ||
103 | this.forceCheck(); | ||
104 | |||
105 | return this.form.valid === true && this.tagsError === '' && this.fileError === ''; | ||
106 | } | ||
107 | |||
108 | |||
109 | onTagKeyPress(event: KeyboardEvent) { | ||
110 | // Enter press | ||
111 | if (event.keyCode === 13) { | ||
112 | this.addTagIfPossible(); | ||
113 | } | ||
114 | } | ||
115 | |||
116 | removeTag(tag: string) { | ||
117 | this.tags.splice(this.tags.indexOf(tag), 1); | ||
118 | this.form.get('currentTag').enable(); | ||
119 | } | ||
120 | |||
121 | update() { | 101 | update() { |
122 | // Maybe the user forgot to press "enter" when he filled the field | ||
123 | this.addTagIfPossible(); | ||
124 | |||
125 | if (this.checkForm() === false) { | ||
126 | return; | ||
127 | } | ||
128 | |||
129 | this.video.patch(this.form.value); | 102 | this.video.patch(this.form.value); |
130 | 103 | ||
131 | this.videoService.updateVideo(this.video) | 104 | this.videoService.updateVideo(this.video) |
@@ -143,27 +116,6 @@ export class VideoUpdateComponent extends FormReactive implements OnInit { | |||
143 | 116 | ||
144 | } | 117 | } |
145 | 118 | ||
146 | private addTagIfPossible() { | ||
147 | const currentTag = this.form.value['currentTag']; | ||
148 | if (currentTag === undefined) return; | ||
149 | |||
150 | // Check if the tag is valid and does not already exist | ||
151 | if ( | ||
152 | currentTag.length >= 2 && | ||
153 | this.form.controls['currentTag'].valid && | ||
154 | this.tags.indexOf(currentTag) === -1 | ||
155 | ) { | ||
156 | this.tags.push(currentTag); | ||
157 | this.form.patchValue({ currentTag: '' }); | ||
158 | |||
159 | if (this.tags.length >= 3) { | ||
160 | this.form.get('currentTag').disable(); | ||
161 | } | ||
162 | |||
163 | this.tagsError = ''; | ||
164 | } | ||
165 | } | ||
166 | |||
167 | private hydrateFormFromVideo() { | 119 | private hydrateFormFromVideo() { |
168 | this.form.patchValue(this.video.toJSON()); | 120 | this.form.patchValue(this.video.toJSON()); |
169 | } | 121 | } |
diff --git a/client/src/app/videos/videos.module.ts b/client/src/app/videos/videos.module.ts index 4f2839c85..04a06e0a3 100644 --- a/client/src/app/videos/videos.module.ts +++ b/client/src/app/videos/videos.module.ts | |||
@@ -1,6 +1,6 @@ | |||
1 | import { NgModule } from '@angular/core'; | 1 | import { NgModule } from '@angular/core'; |
2 | 2 | ||
3 | // import { TagInputModule } from 'ng2-tag-input'; | 3 | import { TagInputModule } from 'ng2-tag-input'; |
4 | 4 | ||
5 | import { VideosRoutingModule } from './videos-routing.module'; | 5 | import { VideosRoutingModule } from './videos-routing.module'; |
6 | import { VideosComponent } from './videos.component'; | 6 | import { VideosComponent } from './videos.component'; |
@@ -18,7 +18,7 @@ import { SharedModule } from '../shared'; | |||
18 | 18 | ||
19 | @NgModule({ | 19 | @NgModule({ |
20 | imports: [ | 20 | imports: [ |
21 | // TagInputModule, | 21 | TagInputModule, |
22 | 22 | ||
23 | VideosRoutingModule, | 23 | VideosRoutingModule, |
24 | SharedModule | 24 | SharedModule |