aboutsummaryrefslogtreecommitdiffhomepage
path: root/client/src/app/shared/shared-forms
diff options
context:
space:
mode:
Diffstat (limited to 'client/src/app/shared/shared-forms')
-rw-r--r--client/src/app/shared/shared-forms/advanced-input-filter.component.ts3
-rw-r--r--client/src/app/shared/shared-forms/select/index.ts3
-rw-r--r--client/src/app/shared/shared-forms/select/select-categories.component.html8
-rw-r--r--client/src/app/shared/shared-forms/select/select-categories.component.ts71
-rw-r--r--client/src/app/shared/shared-forms/select/select-checkbox-all.component.ts115
-rw-r--r--client/src/app/shared/shared-forms/select/select-checkbox.component.html2
-rw-r--r--client/src/app/shared/shared-forms/select/select-checkbox.component.ts7
-rw-r--r--client/src/app/shared/shared-forms/select/select-languages.component.html9
-rw-r--r--client/src/app/shared/shared-forms/select/select-languages.component.ts74
-rw-r--r--client/src/app/shared/shared-forms/shared-form.module.ts9
10 files changed, 293 insertions, 8 deletions
diff --git a/client/src/app/shared/shared-forms/advanced-input-filter.component.ts b/client/src/app/shared/shared-forms/advanced-input-filter.component.ts
index c11f1ad1d..72cd6d460 100644
--- a/client/src/app/shared/shared-forms/advanced-input-filter.component.ts
+++ b/client/src/app/shared/shared-forms/advanced-input-filter.component.ts
@@ -18,6 +18,7 @@ const logger = debug('peertube:AdvancedInputFilterComponent')
18}) 18})
19export class AdvancedInputFilterComponent implements OnInit, AfterViewInit { 19export class AdvancedInputFilterComponent implements OnInit, AfterViewInit {
20 @Input() filters: AdvancedInputFilter[] = [] 20 @Input() filters: AdvancedInputFilter[] = []
21 @Input() emitOnInit = true
21 22
22 @Output() search = new EventEmitter<string>() 23 @Output() search = new EventEmitter<string>()
23 24
@@ -42,7 +43,7 @@ export class AdvancedInputFilterComponent implements OnInit, AfterViewInit {
42 this.viewInitialized = true 43 this.viewInitialized = true
43 44
44 // Init after view init to not send an event too early 45 // Init after view init to not send an event too early
45 if (this.emitSearchAfterViewInit) this.emitSearch() 46 if (this.emitOnInit && this.emitSearchAfterViewInit) this.emitSearch()
46 } 47 }
47 48
48 onInputSearch (event: Event) { 49 onInputSearch (event: Event) {
diff --git a/client/src/app/shared/shared-forms/select/index.ts b/client/src/app/shared/shared-forms/select/index.ts
index e387e1f48..a3d554ee2 100644
--- a/client/src/app/shared/shared-forms/select/index.ts
+++ b/client/src/app/shared/shared-forms/select/index.ts
@@ -1,5 +1,8 @@
1export * from './select-categories.component'
1export * from './select-channel.component' 2export * from './select-channel.component'
3export * from './select-checkbox-all.component'
2export * from './select-checkbox.component' 4export * from './select-checkbox.component'
3export * from './select-custom-value.component' 5export * from './select-custom-value.component'
6export * from './select-languages.component'
4export * from './select-options.component' 7export * from './select-options.component'
5export * from './select-tags.component' 8export * from './select-tags.component'
diff --git a/client/src/app/shared/shared-forms/select/select-categories.component.html b/client/src/app/shared/shared-forms/select/select-categories.component.html
new file mode 100644
index 000000000..2ec2f1264
--- /dev/null
+++ b/client/src/app/shared/shared-forms/select/select-categories.component.html
@@ -0,0 +1,8 @@
1<my-select-checkbox-all
2 [(ngModel)]="selectedCategories"
3 (ngModelChange)="onModelChange()"
4 [availableItems]="availableCategories"
5 i18n-placeholder placeholder="Add a new category"
6 [allGroupLabel]="allCategoriesGroup"
7>
8</my-select-checkbox-all>
diff --git a/client/src/app/shared/shared-forms/select/select-categories.component.ts b/client/src/app/shared/shared-forms/select/select-categories.component.ts
new file mode 100644
index 000000000..b921714ff
--- /dev/null
+++ b/client/src/app/shared/shared-forms/select/select-categories.component.ts
@@ -0,0 +1,71 @@
1
2import { Component, forwardRef, OnInit } from '@angular/core'
3import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'
4import { ServerService } from '@app/core'
5import { SelectOptionsItem } from '../../../../types/select-options-item.model'
6import { ItemSelectCheckboxValue } from './select-checkbox.component'
7
8@Component({
9 selector: 'my-select-categories',
10 styleUrls: [ './select-shared.component.scss' ],
11 templateUrl: './select-categories.component.html',
12 providers: [
13 {
14 provide: NG_VALUE_ACCESSOR,
15 useExisting: forwardRef(() => SelectCategoriesComponent),
16 multi: true
17 }
18 ]
19})
20export class SelectCategoriesComponent implements ControlValueAccessor, OnInit {
21 selectedCategories: ItemSelectCheckboxValue[] = []
22 availableCategories: SelectOptionsItem[] = []
23
24 allCategoriesGroup = $localize`All categories`
25
26 // Fix a bug on ng-select when we update items after we selected items
27 private toWrite: any
28 private loaded = false
29
30 constructor (
31 private server: ServerService
32 ) {
33
34 }
35
36 ngOnInit () {
37 this.server.getVideoCategories()
38 .subscribe(
39 categories => {
40 this.availableCategories = categories.map(c => ({ label: c.label, id: c.id + '', group: this.allCategoriesGroup }))
41 this.loaded = true
42 this.writeValue(this.toWrite)
43 }
44 )
45 }
46
47 propagateChange = (_: any) => { /* empty */ }
48
49 writeValue (categories: string[] | number[]) {
50 if (!this.loaded) {
51 this.toWrite = categories
52 return
53 }
54
55 this.selectedCategories = categories
56 ? categories.map(c => c + '')
57 : categories as string[]
58 }
59
60 registerOnChange (fn: (_: any) => void) {
61 this.propagateChange = fn
62 }
63
64 registerOnTouched () {
65 // Unused
66 }
67
68 onModelChange () {
69 this.propagateChange(this.selectedCategories)
70 }
71}
diff --git a/client/src/app/shared/shared-forms/select/select-checkbox-all.component.ts b/client/src/app/shared/shared-forms/select/select-checkbox-all.component.ts
new file mode 100644
index 000000000..ebf7b77a6
--- /dev/null
+++ b/client/src/app/shared/shared-forms/select/select-checkbox-all.component.ts
@@ -0,0 +1,115 @@
1import { Component, forwardRef, Input } from '@angular/core'
2import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'
3import { Notifier } from '@app/core'
4import { SelectOptionsItem } from '../../../../types/select-options-item.model'
5import { ItemSelectCheckboxValue } from './select-checkbox.component'
6
7@Component({
8 selector: 'my-select-checkbox-all',
9 styleUrls: [ './select-shared.component.scss' ],
10
11 template: `
12 <my-select-checkbox
13 [(ngModel)]="selectedItems"
14 (ngModelChange)="onModelChange()"
15 [availableItems]="availableItems"
16 [selectableGroup]="true" [selectableGroupAsModel]="true"
17 [placeholder]="placeholder"
18 (focusout)="onBlur()"
19 >
20 </my-select-checkbox>`,
21
22 providers: [
23 {
24 provide: NG_VALUE_ACCESSOR,
25 useExisting: forwardRef(() => SelectCheckboxAllComponent),
26 multi: true
27 }
28 ]
29})
30export class SelectCheckboxAllComponent implements ControlValueAccessor {
31 @Input() availableItems: SelectOptionsItem[] = []
32 @Input() allGroupLabel: string
33
34 @Input() placeholder: string
35 @Input() maxItems: number
36
37 selectedItems: ItemSelectCheckboxValue[]
38
39 constructor (
40 private notifier: Notifier
41 ) {
42
43 }
44
45 propagateChange = (_: any) => { /* empty */ }
46
47 writeValue (items: string[]) {
48 this.selectedItems = items
49 ? items.map(l => ({ id: l }))
50 : [ { group: this.allGroupLabel } ]
51 }
52
53 registerOnChange (fn: (_: any) => void) {
54 this.propagateChange = fn
55 }
56
57 registerOnTouched () {
58 // Unused
59 }
60
61 onModelChange () {
62 if (!this.isMaxConstraintValid()) return
63
64 this.propagateChange(this.buildOutputItems())
65 }
66
67 onBlur () {
68 // Automatically use "All languages" if the user did not select any language
69 if (Array.isArray(this.selectedItems) && this.selectedItems.length === 0) {
70 this.selectedItems = [ { group: this.allGroupLabel } ]
71 }
72 }
73
74 private isMaxConstraintValid () {
75 if (!this.maxItems) return true
76
77 const outputItems = this.buildOutputItems()
78 if (!outputItems) return true
79
80 if (outputItems.length >= this.maxItems) {
81 this.notifier.error($localize`You can't select more than ${this.maxItems} items`)
82
83 return false
84 }
85
86 return true
87 }
88
89 private buildOutputItems () {
90 if (!Array.isArray(this.selectedItems)) return undefined
91
92 // null means "All"
93 if (this.selectedItems.length === 0 || this.selectedItems.length === this.availableItems.length) {
94 return null
95 }
96
97 if (this.selectedItems.length === 1) {
98 const item = this.selectedItems[0]
99
100 const itemGroup = typeof item === 'string' || typeof item === 'number'
101 ? item
102 : item.group
103
104 if (itemGroup === this.allGroupLabel) return null
105 }
106
107 return this.selectedItems.map(l => {
108 if (typeof l === 'string' || typeof l === 'number') return l
109
110 if (l.group) return l.group
111
112 return l.id + ''
113 })
114 }
115}
diff --git a/client/src/app/shared/shared-forms/select/select-checkbox.component.html b/client/src/app/shared/shared-forms/select/select-checkbox.component.html
index f5af2932e..7b49a0c01 100644
--- a/client/src/app/shared/shared-forms/select/select-checkbox.component.html
+++ b/client/src/app/shared/shared-forms/select/select-checkbox.component.html
@@ -18,8 +18,6 @@
18 18
19 groupBy="group" 19 groupBy="group"
20 [compareWith]="compareFn" 20 [compareWith]="compareFn"
21
22 [maxSelectedItems]="maxSelectedItems"
23> 21>
24 22
25 <ng-template ng-optgroup-tmp let-item="item" let-item$="item$" let-index="index"> 23 <ng-template ng-optgroup-tmp let-item="item" let-item$="item$" let-index="index">
diff --git a/client/src/app/shared/shared-forms/select/select-checkbox.component.ts b/client/src/app/shared/shared-forms/select/select-checkbox.component.ts
index c2523f15c..12f697628 100644
--- a/client/src/app/shared/shared-forms/select/select-checkbox.component.ts
+++ b/client/src/app/shared/shared-forms/select/select-checkbox.component.ts
@@ -2,7 +2,7 @@ import { Component, forwardRef, Input, OnInit } from '@angular/core'
2import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms' 2import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'
3import { SelectOptionsItem } from '../../../../types/select-options-item.model' 3import { SelectOptionsItem } from '../../../../types/select-options-item.model'
4 4
5export type ItemSelectCheckboxValue = { id?: string | number, group?: string } | string 5export type ItemSelectCheckboxValue = { id?: string, group?: string } | string
6 6
7@Component({ 7@Component({
8 selector: 'my-select-checkbox', 8 selector: 'my-select-checkbox',
@@ -21,7 +21,6 @@ export class SelectCheckboxComponent implements OnInit, ControlValueAccessor {
21 @Input() selectedItems: ItemSelectCheckboxValue[] = [] 21 @Input() selectedItems: ItemSelectCheckboxValue[] = []
22 @Input() selectableGroup: boolean 22 @Input() selectableGroup: boolean
23 @Input() selectableGroupAsModel: boolean 23 @Input() selectableGroupAsModel: boolean
24 @Input() maxSelectedItems: number
25 @Input() placeholder: string 24 @Input() placeholder: string
26 25
27 ngOnInit () { 26 ngOnInit () {
@@ -46,8 +45,6 @@ export class SelectCheckboxComponent implements OnInit, ControlValueAccessor {
46 } else { 45 } else {
47 this.selectedItems = items 46 this.selectedItems = items
48 } 47 }
49
50 this.propagateChange(this.selectedItems)
51 } 48 }
52 49
53 registerOnChange (fn: (_: any) => void) { 50 registerOnChange (fn: (_: any) => void) {
@@ -63,7 +60,7 @@ export class SelectCheckboxComponent implements OnInit, ControlValueAccessor {
63 } 60 }
64 61
65 compareFn (item: SelectOptionsItem, selected: ItemSelectCheckboxValue) { 62 compareFn (item: SelectOptionsItem, selected: ItemSelectCheckboxValue) {
66 if (typeof selected === 'string') { 63 if (typeof selected === 'string' || typeof selected === 'number') {
67 return item.id === selected 64 return item.id === selected
68 } 65 }
69 66
diff --git a/client/src/app/shared/shared-forms/select/select-languages.component.html b/client/src/app/shared/shared-forms/select/select-languages.component.html
new file mode 100644
index 000000000..6eba26a56
--- /dev/null
+++ b/client/src/app/shared/shared-forms/select/select-languages.component.html
@@ -0,0 +1,9 @@
1<my-select-checkbox-all
2 [(ngModel)]="selectedLanguages"
3 (ngModelChange)="onModelChange()"
4 [availableItems]="availableLanguages"
5 [maxItems]="maxLanguages"
6 i18n-placeholder placeholder="Add a new language"
7 [allGroupLabel]="allLanguagesGroup"
8>
9</my-select-checkbox-all>
diff --git a/client/src/app/shared/shared-forms/select/select-languages.component.ts b/client/src/app/shared/shared-forms/select/select-languages.component.ts
new file mode 100644
index 000000000..742163ede
--- /dev/null
+++ b/client/src/app/shared/shared-forms/select/select-languages.component.ts
@@ -0,0 +1,74 @@
1import { Component, forwardRef, Input, OnInit } from '@angular/core'
2import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'
3import { ServerService } from '@app/core'
4import { SelectOptionsItem } from '../../../../types/select-options-item.model'
5import { ItemSelectCheckboxValue } from './select-checkbox.component'
6
7@Component({
8 selector: 'my-select-languages',
9 styleUrls: [ './select-shared.component.scss' ],
10 templateUrl: './select-languages.component.html',
11 providers: [
12 {
13 provide: NG_VALUE_ACCESSOR,
14 useExisting: forwardRef(() => SelectLanguagesComponent),
15 multi: true
16 }
17 ]
18})
19export class SelectLanguagesComponent implements ControlValueAccessor, OnInit {
20 @Input() maxLanguages: number
21
22 selectedLanguages: ItemSelectCheckboxValue[]
23 availableLanguages: SelectOptionsItem[] = []
24
25 allLanguagesGroup = $localize`All languages`
26
27 // Fix a bug on ng-select when we update items after we selected items
28 private toWrite: any
29 private loaded = false
30
31 constructor (
32 private server: ServerService
33 ) {
34
35 }
36
37 ngOnInit () {
38 this.server.getVideoLanguages()
39 .subscribe(
40 languages => {
41 this.availableLanguages = [ { label: $localize`Unknown language`, id: '_unknown', group: this.allLanguagesGroup } ]
42
43 this.availableLanguages = this.availableLanguages
44 .concat(languages.map(l => ({ label: l.label, id: l.id, group: this.allLanguagesGroup })))
45
46 this.loaded = true
47 this.writeValue(this.toWrite)
48 }
49 )
50 }
51
52 propagateChange = (_: any) => { /* empty */ }
53
54 writeValue (languages: ItemSelectCheckboxValue[]) {
55 if (!this.loaded) {
56 this.toWrite = languages
57 return
58 }
59
60 this.selectedLanguages = languages
61 }
62
63 registerOnChange (fn: (_: any) => void) {
64 this.propagateChange = fn
65 }
66
67 registerOnTouched () {
68 // Unused
69 }
70
71 onModelChange () {
72 this.propagateChange(this.selectedLanguages)
73 }
74}
diff --git a/client/src/app/shared/shared-forms/shared-form.module.ts b/client/src/app/shared/shared-forms/shared-form.module.ts
index 5417f7342..60c2f66ae 100644
--- a/client/src/app/shared/shared-forms/shared-form.module.ts
+++ b/client/src/app/shared/shared-forms/shared-form.module.ts
@@ -15,9 +15,12 @@ import { PeertubeCheckboxComponent } from './peertube-checkbox.component'
15import { PreviewUploadComponent } from './preview-upload.component' 15import { PreviewUploadComponent } from './preview-upload.component'
16import { ReactiveFileComponent } from './reactive-file.component' 16import { ReactiveFileComponent } from './reactive-file.component'
17import { 17import {
18 SelectCategoriesComponent,
18 SelectChannelComponent, 19 SelectChannelComponent,
20 SelectCheckboxAllComponent,
19 SelectCheckboxComponent, 21 SelectCheckboxComponent,
20 SelectCustomValueComponent, 22 SelectCustomValueComponent,
23 SelectLanguagesComponent,
21 SelectOptionsComponent, 24 SelectOptionsComponent,
22 SelectTagsComponent 25 SelectTagsComponent
23} from './select' 26} from './select'
@@ -52,6 +55,9 @@ import { TimestampInputComponent } from './timestamp-input.component'
52 SelectTagsComponent, 55 SelectTagsComponent,
53 SelectCheckboxComponent, 56 SelectCheckboxComponent,
54 SelectCustomValueComponent, 57 SelectCustomValueComponent,
58 SelectLanguagesComponent,
59 SelectCategoriesComponent,
60 SelectCheckboxAllComponent,
55 61
56 DynamicFormFieldComponent, 62 DynamicFormFieldComponent,
57 63
@@ -80,6 +86,9 @@ import { TimestampInputComponent } from './timestamp-input.component'
80 SelectTagsComponent, 86 SelectTagsComponent,
81 SelectCheckboxComponent, 87 SelectCheckboxComponent,
82 SelectCustomValueComponent, 88 SelectCustomValueComponent,
89 SelectLanguagesComponent,
90 SelectCategoriesComponent,
91 SelectCheckboxAllComponent,
83 92
84 DynamicFormFieldComponent, 93 DynamicFormFieldComponent,
85 94