aboutsummaryrefslogtreecommitdiffhomepage
path: root/client/src/app/shared/shared-forms/select
diff options
context:
space:
mode:
Diffstat (limited to 'client/src/app/shared/shared-forms/select')
-rw-r--r--client/src/app/shared/shared-forms/select/index.ts4
-rw-r--r--client/src/app/shared/shared-forms/select/select-channel.component.html16
-rw-r--r--client/src/app/shared/shared-forms/select/select-channel.component.ts58
-rw-r--r--client/src/app/shared/shared-forms/select/select-checkbox.component.html41
-rw-r--r--client/src/app/shared/shared-forms/select/select-checkbox.component.scss18
-rw-r--r--client/src/app/shared/shared-forms/select/select-checkbox.component.ts75
-rw-r--r--client/src/app/shared/shared-forms/select/select-options.component.html19
-rw-r--r--client/src/app/shared/shared-forms/select/select-options.component.ts49
-rw-r--r--client/src/app/shared/shared-forms/select/select-shared.component.scss32
-rw-r--r--client/src/app/shared/shared-forms/select/select-tags.component.html13
-rw-r--r--client/src/app/shared/shared-forms/select/select-tags.component.scss3
-rw-r--r--client/src/app/shared/shared-forms/select/select-tags.component.ts38
12 files changed, 366 insertions, 0 deletions
diff --git a/client/src/app/shared/shared-forms/select/index.ts b/client/src/app/shared/shared-forms/select/index.ts
new file mode 100644
index 000000000..33459b23b
--- /dev/null
+++ b/client/src/app/shared/shared-forms/select/index.ts
@@ -0,0 +1,4 @@
1export * from './select-channel.component'
2export * from './select-options.component'
3export * from './select-tags.component'
4export * from './select-checkbox.component'
diff --git a/client/src/app/shared/shared-forms/select/select-channel.component.html b/client/src/app/shared/shared-forms/select/select-channel.component.html
new file mode 100644
index 000000000..897d13ee7
--- /dev/null
+++ b/client/src/app/shared/shared-forms/select/select-channel.component.html
@@ -0,0 +1,16 @@
1<ng-select
2 [(ngModel)]="selectedId"
3 (ngModelChange)="onModelChange()"
4 [bindLabel]="bindLabel"
5 [bindValue]="bindValue"
6 [clearable]="clearable"
7 [searchable]="searchable"
8>
9 <ng-option *ngFor="let channel of channels" [value]="channel.id">
10 <img
11 class="avatar mr-1"
12 [src]="channel.avatarPath"
13 />
14 {{ channel.label }}
15 </ng-option>
16</ng-select>
diff --git a/client/src/app/shared/shared-forms/select/select-channel.component.ts b/client/src/app/shared/shared-forms/select/select-channel.component.ts
new file mode 100644
index 000000000..1b0db9b6f
--- /dev/null
+++ b/client/src/app/shared/shared-forms/select/select-channel.component.ts
@@ -0,0 +1,58 @@
1import { Component, forwardRef, Input } from '@angular/core'
2import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'
3import { Actor } from '@app/shared/shared-main/account/actor.model'
4
5export type SelectChannelItem = {
6 id: number
7 label: string
8 support: string
9 avatarPath?: string
10}
11
12@Component({
13 selector: 'my-select-channel',
14 styleUrls: [ './select-shared.component.scss' ],
15 templateUrl: './select-channel.component.html',
16 providers: [
17 {
18 provide: NG_VALUE_ACCESSOR,
19 useExisting: forwardRef(() => SelectChannelComponent),
20 multi: true
21 }
22 ]
23})
24export class SelectChannelComponent implements ControlValueAccessor {
25 @Input() items: SelectChannelItem[] = []
26
27 selectedId: number
28
29 // ng-select options
30 bindLabel = 'label'
31 bindValue = 'id'
32 clearable = false
33 searchable = false
34
35 get channels () {
36 return this.items.map(c => Object.assign(c, {
37 avatarPath: c.avatarPath ? c.avatarPath : Actor.GET_DEFAULT_AVATAR_URL()
38 }))
39 }
40
41 propagateChange = (_: any) => { /* empty */ }
42
43 writeValue (id: number) {
44 this.selectedId = id
45 }
46
47 registerOnChange (fn: (_: any) => void) {
48 this.propagateChange = fn
49 }
50
51 registerOnTouched () {
52 // Unused
53 }
54
55 onModelChange () {
56 this.propagateChange(this.selectedId)
57 }
58}
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
new file mode 100644
index 000000000..3f81dd152
--- /dev/null
+++ b/client/src/app/shared/shared-forms/select/select-checkbox.component.html
@@ -0,0 +1,41 @@
1<ng-select
2 [items]="availableItems"
3 [(ngModel)]="selectedItems"
4 (ngModelChange)="onModelChange()"
5 i18n-placeholder placeholder="Add a new language"
6 [clearable]="true"
7 [multiple]="true"
8 [searchable]="true"
9 [closeOnSelect]="false"
10
11 bindValue="id"
12 bindLabel="label"
13
14 notFoundText="No items found" i18n-notFoundText
15
16 [selectableGroup]="selectableGroup"
17 [selectableGroupAsModel]="selectableGroupAsModel"
18
19 groupBy="group"
20 [compareWith]="compareFn"
21
22 [maxSelectedItems]="maxSelectedItems"
23>
24
25 <ng-template ng-optgroup-tmp let-item="item" let-item$="item$" let-index="index">
26 <div class="form-group-checkbox">
27 <input id="item-{{index}}" type="checkbox" [ngModel]="item$.selected"/>
28 <span role="checkbox" [attr.aria-checked]="item$.selected"></span>
29 <span>{{ item.group }}</span>
30 </div>
31 </ng-template>
32
33 <ng-template ng-option-tmp let-item="item" let-item$="item$" let-index="index">
34 <div class="form-group-checkbox">
35 <input id="item-{{index}}" type="checkbox" [ngModel]="item$.selected"/>
36 <span role="checkbox" [attr.aria-checked]="item$.selected"></span>
37 <span>{{ item.label }}</span>
38 </div>
39 </ng-template>
40
41</ng-select>
diff --git a/client/src/app/shared/shared-forms/select/select-checkbox.component.scss b/client/src/app/shared/shared-forms/select/select-checkbox.component.scss
new file mode 100644
index 000000000..145f6b26c
--- /dev/null
+++ b/client/src/app/shared/shared-forms/select/select-checkbox.component.scss
@@ -0,0 +1,18 @@
1@import '_variables';
2@import '_mixins';
3
4ng-select ::ng-deep {
5 .ng-option {
6 display: flex;
7 align-items: center;
8 }
9
10 .form-group-checkbox {
11 display: flex;
12 align-items: center;
13
14 input {
15 @include peertube-checkbox(1px);
16 }
17 }
18}
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
new file mode 100644
index 000000000..93653fef1
--- /dev/null
+++ b/client/src/app/shared/shared-forms/select/select-checkbox.component.ts
@@ -0,0 +1,75 @@
1import { Component, Input, forwardRef } from '@angular/core'
2import { NG_VALUE_ACCESSOR, ControlValueAccessor } from '@angular/forms'
3import { SelectOptionsItem } from './select-options.component'
4
5export type ItemSelectCheckboxValue = { id?: string | number, group?: string } | string
6
7@Component({
8 selector: 'my-select-checkbox',
9 styleUrls: [ './select-shared.component.scss', 'select-checkbox.component.scss' ],
10 templateUrl: './select-checkbox.component.html',
11 providers: [
12 {
13 provide: NG_VALUE_ACCESSOR,
14 useExisting: forwardRef(() => SelectCheckboxComponent),
15 multi: true
16 }
17 ]
18})
19export class SelectCheckboxComponent implements ControlValueAccessor {
20 @Input() availableItems: SelectOptionsItem[] = []
21 @Input() selectedItems: ItemSelectCheckboxValue[] = []
22 @Input() selectableGroup: boolean
23 @Input() selectableGroupAsModel: boolean
24 @Input() maxSelectedItems: number
25
26 propagateChange = (_: any) => { /* empty */ }
27
28 writeValue (items: ItemSelectCheckboxValue[]) {
29 if (Array.isArray(items)) {
30 this.selectedItems = items.map(i => {
31 if (typeof i === 'string' || typeof i === 'number') {
32 return i + ''
33 }
34
35 if (i.group) {
36 return { group: i.group }
37 }
38
39 return { id: i.id + '' }
40 })
41 } else {
42 this.selectedItems = items
43 }
44
45 this.propagateChange(this.selectedItems)
46 }
47
48 registerOnChange (fn: (_: any) => void) {
49 this.propagateChange = fn
50 }
51
52 registerOnTouched () {
53 // Unused
54 }
55
56 onModelChange () {
57 this.propagateChange(this.selectedItems)
58 }
59
60 compareFn (item: SelectOptionsItem, selected: ItemSelectCheckboxValue) {
61 if (typeof selected === 'string') {
62 return item.id === selected
63 }
64
65 if (this.selectableGroup && item.group && selected.group) {
66 return item.group === selected.group
67 }
68
69 if (selected.id && item.id) {
70 return item.id === selected.id
71 }
72
73 return false
74 }
75}
diff --git a/client/src/app/shared/shared-forms/select/select-options.component.html b/client/src/app/shared/shared-forms/select/select-options.component.html
new file mode 100644
index 000000000..48eca1cf5
--- /dev/null
+++ b/client/src/app/shared/shared-forms/select/select-options.component.html
@@ -0,0 +1,19 @@
1<ng-select
2 [items]="items"
3 [groupBy]="groupBy"
4 [(ngModel)]="selectedId"
5 (ngModelChange)="onModelChange()"
6 [clearable]="clearable"
7 [searchable]="searchable"
8
9 bindLabel="label"
10 bindValue="id"
11>
12 <ng-template ng-option-tmp let-item="item" let-index="index">
13 {{ item.label }}
14 <ng-container *ngIf="item.description">
15 <br>
16 <span [title]="item.description" class="text-muted">{{ item.description }}</span>
17 </ng-container>
18 </ng-template>
19</ng-select>
diff --git a/client/src/app/shared/shared-forms/select/select-options.component.ts b/client/src/app/shared/shared-forms/select/select-options.component.ts
new file mode 100644
index 000000000..3ba24c732
--- /dev/null
+++ b/client/src/app/shared/shared-forms/select/select-options.component.ts
@@ -0,0 +1,49 @@
1import { Component, Input, forwardRef } from '@angular/core'
2import { NG_VALUE_ACCESSOR, ControlValueAccessor } from '@angular/forms'
3
4export type SelectOptionsItem = {
5 id: string | number
6 label: string
7 description?: string
8 group?: string
9 groupLabel?: string
10}
11
12@Component({
13 selector: 'my-select-options',
14 styleUrls: [ './select-shared.component.scss' ],
15 templateUrl: './select-options.component.html',
16 providers: [
17 {
18 provide: NG_VALUE_ACCESSOR,
19 useExisting: forwardRef(() => SelectOptionsComponent),
20 multi: true
21 }
22 ]
23})
24export class SelectOptionsComponent implements ControlValueAccessor {
25 @Input() items: SelectOptionsItem[] = []
26 @Input() clearable = false
27 @Input() searchable = false
28 @Input() groupBy: string
29
30 selectedId: number | string
31
32 propagateChange = (_: any) => { /* empty */ }
33
34 writeValue (id: number | string) {
35 this.selectedId = id
36 }
37
38 registerOnChange (fn: (_: any) => void) {
39 this.propagateChange = fn
40 }
41
42 registerOnTouched () {
43 // Unused
44 }
45
46 onModelChange () {
47 this.propagateChange(this.selectedId)
48 }
49}
diff --git a/client/src/app/shared/shared-forms/select/select-shared.component.scss b/client/src/app/shared/shared-forms/select/select-shared.component.scss
new file mode 100644
index 000000000..0b4c6b784
--- /dev/null
+++ b/client/src/app/shared/shared-forms/select/select-shared.component.scss
@@ -0,0 +1,32 @@
1@import '_variables';
2@import '_mixins';
3
4$form-base-input-width: auto;
5
6ng-select {
7 width: $form-base-input-width;
8
9 @media screen and (max-width: $form-base-input-width) {
10 width: 100%;
11 }
12}
13
14ng-select ::ng-deep {
15 .ng-value-container {
16 max-height: 100px;
17 overflow-y: auto;
18 overflow-x: hidden;
19 }
20
21 // make sure the image is vertically adjusted
22 .ng-value-label img {
23 position: relative;
24 top: -1px;
25 }
26
27 img {
28 border-radius: 50%;
29 height: 20px;
30 width: 20px;
31 }
32}
diff --git a/client/src/app/shared/shared-forms/select/select-tags.component.html b/client/src/app/shared/shared-forms/select/select-tags.component.html
new file mode 100644
index 000000000..e1cd50882
--- /dev/null
+++ b/client/src/app/shared/shared-forms/select/select-tags.component.html
@@ -0,0 +1,13 @@
1<ng-select
2 [items]="availableItems"
3 [(ngModel)]="selectedItems"
4 (ngModelChange)="onModelChange()"
5 i18n-placeholder placeholder="Enter a new tag"
6 [maxSelectedItems]="5"
7 [clearable]="true"
8 [addTag]="true"
9 [multiple]="true"
10 [isOpen]="false"
11 [searchable]="true"
12>
13</ng-select>
diff --git a/client/src/app/shared/shared-forms/select/select-tags.component.scss b/client/src/app/shared/shared-forms/select/select-tags.component.scss
new file mode 100644
index 000000000..ad76bc7ee
--- /dev/null
+++ b/client/src/app/shared/shared-forms/select/select-tags.component.scss
@@ -0,0 +1,3 @@
1ng-select ::ng-deep .ng-arrow-wrapper {
2 display: none;
3}
diff --git a/client/src/app/shared/shared-forms/select/select-tags.component.ts b/client/src/app/shared/shared-forms/select/select-tags.component.ts
new file mode 100644
index 000000000..93d199037
--- /dev/null
+++ b/client/src/app/shared/shared-forms/select/select-tags.component.ts
@@ -0,0 +1,38 @@
1import { Component, Input, forwardRef } from '@angular/core'
2import { NG_VALUE_ACCESSOR, ControlValueAccessor } from '@angular/forms'
3
4@Component({
5 selector: 'my-select-tags',
6 styleUrls: [ './select-shared.component.scss', './select-tags.component.scss' ],
7 templateUrl: './select-tags.component.html',
8 providers: [
9 {
10 provide: NG_VALUE_ACCESSOR,
11 useExisting: forwardRef(() => SelectTagsComponent),
12 multi: true
13 }
14 ]
15})
16export class SelectTagsComponent implements ControlValueAccessor {
17 @Input() availableItems: string[] = []
18 @Input() selectedItems: string[] = []
19
20 propagateChange = (_: any) => { /* empty */ }
21
22 writeValue (items: string[]) {
23 this.selectedItems = items
24 this.propagateChange(this.selectedItems)
25 }
26
27 registerOnChange (fn: (_: any) => void) {
28 this.propagateChange = fn
29 }
30
31 registerOnTouched () {
32 // Unused
33 }
34
35 onModelChange () {
36 this.propagateChange(this.selectedItems)
37 }
38}