unify inputs requiring buttons like password inputs

This commit is contained in:
Rigel Kent 2020-12-04 15:58:55 +01:00
parent aa5ee5017a
commit f8b530e0a5
No known key found for this signature in database
GPG Key ID: 5E53E96A494E452F
26 changed files with 177 additions and 100 deletions

View File

@ -122,10 +122,9 @@
</ng-container> </ng-container>
</ng-template> </ng-template>
</my-help> </my-help>
<input <my-input-toggle-hidden formControlName="password" id="password"
type="password" id="password" autocomplete="new-password" class="form-control" [ngClass]="{ 'input-error': formErrors['password'] }"
formControlName="password" [ngClass]="{ 'input-error': formErrors['password'] }" autocomplete="new-password"></my-input-toggle-hidden>
>
<div *ngIf="formErrors.password" class="form-error"> <div *ngIf="formErrors.password" class="form-error">
{{ formErrors.password }} {{ formErrors.password }}
</div> </div>

View File

@ -50,10 +50,10 @@
<div class="form-group"> <div class="form-group">
<label i18n for="password">Password</label> <label i18n for="password">Password</label>
<div> <div>
<input <my-input-toggle-hidden formControlName="password" id="password"
type="password" name="password" id="password" i18n-placeholder placeholder="Password" required tabindex="2" autocomplete="current-password" i18n-placeholder placeholder="Password"
formControlName="password" class="form-control" [ngClass]="{ 'input-error': formErrors['password'] }" [ngClass]="{ 'input-error': formErrors['password'] }"
> autocomplete="current-password"></my-input-toggle-hidden>
<a i18n-title class="forgot-password-button" (click)="openForgotPasswordModal()" title="Click here to reset your password">I forgot my password</a> <a i18n-title class="forgot-password-button" (click)="openForgotPasswordModal()" title="Click here to reset your password">I forgot my password</a>
</div> </div>
<div *ngIf="formErrors.password" class="form-error"> <div *ngIf="formErrors.password" class="form-error">

View File

@ -8,7 +8,7 @@
<h2 i18n class="applications-title">SUBSCRIPTION FEED</h2> <h2 i18n class="applications-title">SUBSCRIPTION FEED</h2>
<div i18n class="applications-description"> <div i18n class="applications-description">
Use third-party feed aggregators to retrieve the list of videos from Use third-party feed aggregators to retrieve the list of videos from
channels you subscribed to. Make sure to keep your token private. channels you subscribed to.
</div> </div>
</div> </div>
@ -16,12 +16,14 @@
<div class="form-group"> <div class="form-group">
<label i18n for="feed-url">Feed URL</label> <label i18n for="feed-url">Feed URL</label>
<my-input-readonly-copy [value]="feedUrl"></my-input-readonly-copy> <my-input-toggle-hidden [value]="feedUrl" [withToggle]="false" [withCopy]="true" [show]="true" [readonly]="true"></my-input-toggle-hidden>
</div> </div>
<div class="form-group"> <div class="form-group">
<label i18n for="feed-token">Feed Token</label> <label i18n for="feed-token">Feed Token</label>
<my-input-readonly-copy [value]="feedToken"></my-input-readonly-copy> <my-input-toggle-hidden [value]="feedToken" [withCopy]="true" [readonly]="true"></my-input-toggle-hidden>
<div class="form-group-description" i18n>⚠️ Never share your feed token with anyone.</div>
</div> </div>
</div> </div>

View File

@ -12,9 +12,8 @@
<form role="form" class="change-email" (ngSubmit)="changeEmail()" [formGroup]="form" *ngIf="user.pluginAuth === null"> <form role="form" class="change-email" (ngSubmit)="changeEmail()" [formGroup]="form" *ngIf="user.pluginAuth === null">
<div class="form-group"> <div class="form-group">
<label i18n for="new-email">New email</label>
<input <input
type="email" id="new-email" i18n-placeholder placeholder="Your new email" class="form-control" type="email" id="new-email" i18n-placeholder placeholder="New email" class="form-control"
formControlName="new-email" [ngClass]="{ 'input-error': formErrors['new-email'] }" formControlName="new-email" [ngClass]="{ 'input-error': formErrors['new-email'] }"
> >
<div *ngIf="formErrors['new-email']" class="form-error"> <div *ngIf="formErrors['new-email']" class="form-error">
@ -23,11 +22,11 @@
</div> </div>
<div class="form-group"> <div class="form-group">
<label i18n for="new-email">Your current password</label> <my-input-toggle-hidden formControlName="password"
<input id="password"
type="password" id="password" i18n-placeholder placeholder="Your password" autocomplete="off" i18n-placeholder placeholder="Current password"
formControlName="password" [ngClass]="{ 'input-error': formErrors['password'] }" class="form-control" [ngClass]="{ 'input-error': formErrors['password'] }"
> autocomplete="current-password"></my-input-toggle-hidden>
<div *ngIf="formErrors['password']" class="form-error"> <div *ngIf="formErrors['password']" class="form-error">
{{ formErrors['password'] }} {{ formErrors['password'] }}
</div> </div>

View File

@ -6,7 +6,11 @@ label {
font-size: 100%; font-size: 100%;
} }
input[type=password], my-input-toggle-hidden {
width: 340px;
display: block;
}
input[type=email] { input[type=email] {
@include peertube-input-text(340px); @include peertube-input-text(340px);
@ -20,10 +24,13 @@ input[type=submit] {
.current-email, .current-email,
.pending-email { .pending-email {
font-size: 16px;
margin-bottom: 15px; margin-bottom: 15px;
.email { .email {
font-weight: $font-semibold; font-weight: $font-semibold;
} }
} }
.form-group {
width: max-content;
}

View File

@ -3,26 +3,29 @@
<form role="form" (ngSubmit)="changePassword()" [formGroup]="form"> <form role="form" (ngSubmit)="changePassword()" [formGroup]="form">
<label i18n for="current-password">Change password</label> <label i18n for="current-password">Change password</label>
<input <my-input-toggle-hidden formControlName="current-password"
type="password" id="current-password" i18n-placeholder placeholder="Current password" autocomplete="current-password" id="current-password"
formControlName="current-password" [ngClass]="{ 'input-error': formErrors['current-password'] }" class="form-control" i18n-placeholder placeholder="Current password"
> [ngClass]="{ 'input-error': formErrors['current-password'] }"
autocomplete="current-password"></my-input-toggle-hidden>
<div *ngIf="formErrors['current-password']" class="form-error"> <div *ngIf="formErrors['current-password']" class="form-error">
{{ formErrors['current-password'] }} {{ formErrors['current-password'] }}
</div> </div>
<input <my-input-toggle-hidden formControlName="new-password"
type="password" id="new-password" i18n-placeholder placeholder="New password" autocomplete="new-password" id="new-password"
formControlName="new-password" [ngClass]="{ 'input-error': formErrors['new-password'] }" class="form-control" i18n-placeholder placeholder="New password"
> [ngClass]="{ 'input-error': formErrors['new-password'] }"
autocomplete="new-password"></my-input-toggle-hidden>
<div *ngIf="formErrors['new-password']" class="form-error"> <div *ngIf="formErrors['new-password']" class="form-error">
{{ formErrors['new-password'] }} {{ formErrors['new-password'] }}
</div> </div>
<input <my-input-toggle-hidden formControlName="new-confirmed-password"
type="password" id="new-confirmed-password" i18n-placeholder placeholder="Confirm new password" autocomplete="new-password" id="new-confirmed-password"
formControlName="new-confirmed-password" class="form-control" i18n-placeholder placeholder="Confirm new password"
> [ngClass]="{ 'input-error': formErrors['new-confirmed-password'] }"
autocomplete="new-password"></my-input-toggle-hidden>
<div *ngIf="formErrors['new-confirmed-password']" class="form-error"> <div *ngIf="formErrors['new-confirmed-password']" class="form-error">
{{ formErrors['new-confirmed-password'] }} {{ formErrors['new-confirmed-password'] }}
</div> </div>

View File

@ -6,14 +6,14 @@ label {
font-size: 100%; font-size: 100%;
} }
input[type=password] { my-input-toggle-hidden {
@include peertube-input-text(340px); width: 340px;
display: block; display: block;
}
&#new-password, #new-password,
&#new-confirmed-password { #new-confirmed-password {
margin-top: 15px; margin-top: 15px;
}
} }
input[type=submit] { input[type=submit] {
@ -22,4 +22,3 @@ input[type=submit] {
margin-top: 15px; margin-top: 15px;
} }

View File

@ -1,7 +1,7 @@
import { filter } from 'rxjs/operators' import { filter } from 'rxjs/operators'
import { Component, OnInit } from '@angular/core' import { Component, OnInit } from '@angular/core'
import { AuthService, Notifier, UserService } from '@app/core' import { AuthService, Notifier, UserService } from '@app/core'
import { USER_CONFIRM_PASSWORD_VALIDATOR, USER_PASSWORD_VALIDATOR } from '@app/shared/form-validators/user-validators' import { USER_CONFIRM_PASSWORD_VALIDATOR, USER_PASSWORD_VALIDATOR, USER_EXISTING_PASSWORD_VALIDATOR } from '@app/shared/form-validators/user-validators'
import { FormReactive, FormValidatorService } from '@app/shared/shared-forms' import { FormReactive, FormValidatorService } from '@app/shared/shared-forms'
import { User } from '@shared/models' import { User } from '@shared/models'
@ -25,7 +25,7 @@ export class MyAccountChangePasswordComponent extends FormReactive implements On
ngOnInit () { ngOnInit () {
this.buildForm({ this.buildForm({
'current-password': USER_PASSWORD_VALIDATOR, 'current-password': USER_EXISTING_PASSWORD_VALIDATOR,
'new-password': USER_PASSWORD_VALIDATOR, 'new-password': USER_PASSWORD_VALIDATOR,
'new-confirmed-password': USER_CONFIRM_PASSWORD_VALIDATOR 'new-confirmed-password': USER_CONFIRM_PASSWORD_VALIDATOR
}) })

View File

@ -2,8 +2,6 @@
@import '_mixins'; @import '_mixins';
.delete-me { .delete-me {
font-size: 15px;
button { button {
@include peertube-button; @include peertube-button;
@include danger-button; @include danger-button;

View File

@ -6,10 +6,10 @@
<form role="form" (ngSubmit)="resetPassword()" [formGroup]="form"> <form role="form" (ngSubmit)="resetPassword()" [formGroup]="form">
<div class="form-group"> <div class="form-group">
<label i18n for="password">Password</label> <label i18n for="password">Password</label>
<input <my-input-toggle-hidden formControlName="password" id="password"
type="password" name="password" id="password" i18n-placeholder placeholder="Password" required autocomplete="new-password" i18n-placeholder placeholder="Password"
formControlName="password" [ngClass]="{ 'input-error': formErrors['password'] }" [ngClass]="{ 'input-error': formErrors['password'] }"
> autocomplete="new-password"></my-input-toggle-hidden>
<div *ngIf="formErrors.password" class="form-error"> <div *ngIf="formErrors.password" class="form-error">
{{ formErrors.password }} {{ formErrors.password }}
</div> </div>
@ -17,10 +17,10 @@
<div class="form-group"> <div class="form-group">
<label i18n for="password-confirm">Confirm password</label> <label i18n for="password-confirm">Confirm password</label>
<input <my-input-toggle-hidden formControlName="password-confirm" id="password-confirm"
type="password" name="password-confirm" id="password-confirm" i18n-placeholder placeholder="Confirmed password" required autocomplete="new-password" i18n-placeholder placeholder="Confirmed password"
formControlName="password-confirm" [ngClass]="{ 'input-error': formErrors['password-confirm'] }" [ngClass]="{ 'input-error': formErrors['password-confirm'] }"
> autocomplete="new-password"></my-input-toggle-hidden>
<div *ngIf="formErrors['password-confirm']" class="form-error"> <div *ngIf="formErrors['password-confirm']" class="form-error">
{{ formErrors['password-confirm'] }} {{ formErrors['password-confirm'] }}
</div> </div>

View File

@ -54,10 +54,10 @@
<div class="form-group"> <div class="form-group">
<label for="password" i18n>Password</label> <label for="password" i18n>Password</label>
<input <my-input-toggle-hidden formControlName="password" id="password"
type="password" id="password" i18n-placeholder placeholder="Password" autocomplete="new-password" i18n-placeholder placeholder="Password"
formControlName="password" class="form-control" [ngClass]="{ 'input-error': formErrors['password'] }" [ngClass]="{ 'input-error': formErrors['password'] }"
> autocomplete="new-password"></my-input-toggle-hidden>
<div *ngIf="formErrors.password" class="form-error"> <div *ngIf="formErrors.password" class="form-error">
{{ formErrors.password }} {{ formErrors.password }}
</div> </div>

View File

@ -213,12 +213,12 @@
<div class="form-group"> <div class="form-group">
<label for="liveVideoRTMPUrl" i18n>Live RTMP Url</label> <label for="liveVideoRTMPUrl" i18n>Live RTMP Url</label>
<my-input-readonly-copy id="liveVideoRTMPUrl" [value]="liveVideo.rtmpUrl"></my-input-readonly-copy> <my-input-toggle-hidden id="liveVideoRTMPUrl" [value]="liveVideo.rtmpUrl" [withToggle]="false" [withCopy]="true" [show]="true" [readonly]="true"></my-input-toggle-hidden>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="liveVideoStreamKey" i18n>Live stream key</label> <label for="liveVideoStreamKey" i18n>Live stream key</label>
<my-input-readonly-copy id="liveVideoStreamKey" [value]="liveVideo.streamKey"></my-input-readonly-copy> <my-input-toggle-hidden id="liveVideoStreamKey" [value]="liveVideo.streamKey" [withCopy]="true" [readonly]="true"></my-input-toggle-hidden>
<div class="form-group-description" i18n>⚠️ Never share your stream key with anyone.</div> <div class="form-group-description" i18n>⚠️ Never share your stream key with anyone.</div>
</div> </div>

View File

@ -39,6 +39,15 @@ export const USER_EMAIL_VALIDATOR: BuildFormValidator = {
} }
} }
export const USER_EXISTING_PASSWORD_VALIDATOR: BuildFormValidator = {
VALIDATORS: [
Validators.required
],
MESSAGES: {
'required': $localize`Password is required.`
}
}
export const USER_PASSWORD_VALIDATOR: BuildFormValidator = { export const USER_PASSWORD_VALIDATOR: BuildFormValidator = {
VALIDATORS: [ VALIDATORS: [
Validators.required, Validators.required,

View File

@ -5,7 +5,7 @@
<input *ngIf="setting.type === 'input'" type="text" [id]="setting.name" [formControlName]="setting.name" /> <input *ngIf="setting.type === 'input'" type="text" [id]="setting.name" [formControlName]="setting.name" />
<input *ngIf="setting.type === 'input-password'" type="password" [id]="setting.name" [formControlName]="setting.name" /> <my-input-toggle-hidden *ngIf="setting.type === 'input-password'" [formControlName]="setting.name" [id]="setting.name"></my-input-toggle-hidden>
<textarea *ngIf="setting.type === 'input-textarea'" type="text" [id]="setting.name" [formControlName]="setting.name"></textarea> <textarea *ngIf="setting.type === 'input-textarea'" type="text" [id]="setting.name" [formControlName]="setting.name"></textarea>

View File

@ -1,7 +1,7 @@
export * from './form-validator.service' export * from './form-validator.service'
export * from './form-reactive' export * from './form-reactive'
export * from './select' export * from './select'
export * from './input-readonly-copy.component' export * from './input-toggle-hidden.component'
export * from './input-switch.component' export * from './input-switch.component'
export * from './markdown-textarea.component' export * from './markdown-textarea.component'
export * from './peertube-checkbox.component' export * from './peertube-checkbox.component'

View File

@ -1,9 +0,0 @@
<div class="input-group input-group-sm">
<input [id]="id" #urlInput (click)="urlInput.select()" type="text" class="form-control readonly" readonly [value]="value" />
<div class="input-group-append">
<button [cdkCopyToClipboard]="urlInput.value" (click)="activateCopiedMessage()" type="button" class="btn btn-outline-secondary">
<span class="glyphicon glyphicon-copy"></span>
</button>
</div>
</div>

View File

@ -1,3 +0,0 @@
input.readonly {
font-size: 15px;
}

View File

@ -1,18 +0,0 @@
import { Component, Input } from '@angular/core'
import { Notifier } from '@app/core'
@Component({
selector: 'my-input-readonly-copy',
templateUrl: './input-readonly-copy.component.html',
styleUrls: [ './input-readonly-copy.component.scss' ]
})
export class InputReadonlyCopyComponent {
@Input() id: string
@Input() value = ''
constructor (private notifier: Notifier) { }
activateCopiedMessage () {
this.notifier.success($localize`Copied`)
}
}

View File

@ -0,0 +1,13 @@
<div class="input-group input-group-sm">
<input [id]="id" [autocomplete]="autocomplete" [value]="value" [placeholder]="placeholder" [(ngModel)]="value" (ngModelChange)="update()" [ngClass]="{ 'readonly': readonly }" [readonly]="readonly"
#input (click)="input.select()" (input)="update()" (change)="update()" [type]="inputType" class="form-control" />
<div *ngIf="withToggle || withCopy" class="input-group-append">
<button *ngIf="withToggle" (click)="toggle()" type="button" class="btn btn-outline-secondary" [title]="toggleTitle">
<span class="glyphicon glyphicon-eye-{{ show ? 'open' : 'close' }}"></span>
</button>
<button *ngIf="withCopy" [cdkCopyToClipboard]="input.value" (click)="activateCopiedMessage()" type="button" class="btn btn-outline-secondary" i18n-title title="Copy">
<span class="glyphicon glyphicon-copy"></span>
</button>
</div>
</div>

View File

@ -0,0 +1,11 @@
@import '_variables';
@import '_mixins';
input {
@include peertube-input-text(auto);
// set again properties of peertube-input-text that are overriden by .input-group
font-size: 15px !important;
padding-left: 15px !important;
padding-right: 15px !important;
}

View File

@ -0,0 +1,66 @@
import { Component, forwardRef, Input } from '@angular/core'
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'
import { Notifier } from '@app/core'
@Component({
selector: 'my-input-toggle-hidden',
templateUrl: './input-toggle-hidden.component.html',
styleUrls: [ './input-toggle-hidden.component.scss' ],
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => InputToggleHiddenComponent),
multi: true
}
]
})
export class InputToggleHiddenComponent implements ControlValueAccessor {
@Input() id = Math.random().toString(11).slice(2, 8) // id cannot be left empty or undefined
@Input() value = ''
@Input() autocomplete = 'off'
@Input() placeholder = ''
@Input() withToggle = true
@Input() withCopy = false
@Input() readonly = false
@Input() show = false
constructor (private notifier: Notifier) { }
get inputType () {
return this.show
? 'text'
: 'password'
}
get toggleTitle () {
return this.show
? $localize`Hide`
: $localize`Show`
}
toggle () {
this.show = !this.show
}
activateCopiedMessage () {
this.notifier.success($localize`Copied`)
}
propagateChange = (_: any) => { /* empty */ }
writeValue (value: string) {
this.value = value
}
registerOnChange (fn: (_: any) => void) {
this.propagateChange = fn
}
registerOnTouched () {
// Unused
}
update () {
this.propagateChange(this.value)
}
}

View File

@ -7,7 +7,7 @@ import { SharedGlobalIconModule } from '../shared-icons'
import { SharedMainModule } from '../shared-main/shared-main.module' import { SharedMainModule } from '../shared-main/shared-main.module'
import { DynamicFormFieldComponent } from './dynamic-form-field.component' import { DynamicFormFieldComponent } from './dynamic-form-field.component'
import { FormValidatorService } from './form-validator.service' import { FormValidatorService } from './form-validator.service'
import { InputReadonlyCopyComponent } from './input-readonly-copy.component' import { InputToggleHiddenComponent } from './input-toggle-hidden.component'
import { InputSwitchComponent } from './input-switch.component' import { InputSwitchComponent } from './input-switch.component'
import { MarkdownTextareaComponent } from './markdown-textarea.component' import { MarkdownTextareaComponent } from './markdown-textarea.component'
import { PeertubeCheckboxComponent } from './peertube-checkbox.component' import { PeertubeCheckboxComponent } from './peertube-checkbox.component'
@ -30,7 +30,7 @@ import { TimestampInputComponent } from './timestamp-input.component'
], ],
declarations: [ declarations: [
InputReadonlyCopyComponent, InputToggleHiddenComponent,
MarkdownTextareaComponent, MarkdownTextareaComponent,
PeertubeCheckboxComponent, PeertubeCheckboxComponent,
PreviewUploadComponent, PreviewUploadComponent,
@ -55,7 +55,7 @@ import { TimestampInputComponent } from './timestamp-input.component'
InputMaskModule, InputMaskModule,
NgSelectModule, NgSelectModule,
InputReadonlyCopyComponent, InputToggleHiddenComponent,
MarkdownTextareaComponent, MarkdownTextareaComponent,
PeertubeCheckboxComponent, PeertubeCheckboxComponent,
PreviewUploadComponent, PreviewUploadComponent,

View File

@ -18,7 +18,7 @@
<ng-template ngbNavContent> <ng-template ngbNavContent>
<div class="nav-content"> <div class="nav-content">
<my-input-readonly-copy [value]="getPlaylistUrl()"></my-input-readonly-copy> <my-input-toggle-hidden [value]="getPlaylistUrl()" [withToggle]="false" [withCopy]="true" [show]="true" [readonly]="true"></my-input-toggle-hidden>
</div> </div>
</ng-template> </ng-template>
</ng-container> </ng-container>
@ -38,7 +38,7 @@
<ng-template ngbNavContent> <ng-template ngbNavContent>
<div class="nav-content"> <div class="nav-content">
<my-input-readonly-copy [value]="getPlaylistIframeCode()"></my-input-readonly-copy> <my-input-toggle-hidden [value]="getPlaylistIframeCode()" [withToggle]="false" [withCopy]="true" [show]="true" [readonly]="true"></my-input-toggle-hidden>
<div i18n *ngIf="notSecure()" class="alert alert-warning"> <div i18n *ngIf="notSecure()" class="alert alert-warning">
The url is not secured (no HTTPS), so the embed video won't work on HTTPS websites (web browsers block non secured HTTP requests on HTTPS websites). The url is not secured (no HTTPS), so the embed video won't work on HTTPS websites (web browsers block non secured HTTP requests on HTTPS websites).
@ -72,7 +72,7 @@
<ng-template ngbNavContent> <ng-template ngbNavContent>
<div class="nav-content"> <div class="nav-content">
<my-input-readonly-copy [value]="getVideoUrl()"></my-input-readonly-copy> <my-input-toggle-hidden [value]="getVideoUrl()" [withToggle]="false" [withCopy]="true" [show]="true" [readonly]="true"></my-input-toggle-hidden>
</div> </div>
</ng-template> </ng-template>
</ng-container> </ng-container>
@ -92,7 +92,7 @@
<ng-template ngbNavContent> <ng-template ngbNavContent>
<div class="nav-content"> <div class="nav-content">
<my-input-readonly-copy [value]="getVideoIframeCode()"></my-input-readonly-copy> <my-input-toggle-hidden [value]="getVideoIframeCode()" [withToggle]="false" [withCopy]="true" [show]="true" [readonly]="true"></my-input-toggle-hidden>
<div i18n *ngIf="notSecure()" class="alert alert-warning"> <div i18n *ngIf="notSecure()" class="alert alert-warning">
The url is not secured (no HTTPS), so the embed video won't work on HTTPS websites (web browsers block non secured HTTP requests on HTTPS websites). The url is not secured (no HTTPS), so the embed video won't work on HTTPS websites (web browsers block non secured HTTP requests on HTTPS websites).

View File

@ -1,7 +1,7 @@
@import '_mixins'; @import '_mixins';
@import '_variables'; @import '_variables';
my-input-readonly-copy { my-input-toggle-hidden {
width: 100%; width: 100%;
} }

View File

@ -13,12 +13,12 @@
<div class="form-group"> <div class="form-group">
<label for="liveVideoRTMPUrl" i18n>Live RTMP Url</label> <label for="liveVideoRTMPUrl" i18n>Live RTMP Url</label>
<my-input-readonly-copy id="liveVideoRTMPUrl" [value]="live.rtmpUrl"></my-input-readonly-copy> <my-input-toggle-hidden id="liveVideoRTMPUrl" [value]="live.rtmpUrl" [withToggle]="false" [withCopy]="true" [show]="true" [readonly]="true"></my-input-toggle-hidden>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="liveVideoStreamKey" i18n>Live stream key</label> <label for="liveVideoStreamKey" i18n>Live stream key</label>
<my-input-readonly-copy id="liveVideoStreamKey" [value]="live.streamKey"></my-input-readonly-copy> <my-input-toggle-hidden id="liveVideoStreamKey" [value]="live.streamKey" [withCopy]="true" [readonly]="true"></my-input-toggle-hidden>
<div class="form-group-description" i18n>⚠️ Never share your stream key with anyone.</div> <div class="form-group-description" i18n>⚠️ Never share your stream key with anyone.</div>
</div> </div>

View File

@ -120,7 +120,8 @@ code {
margin-top: 5px; margin-top: 5px;
} }
.input-error { .input-error
my-input-toggle-hidden ::ng-deep input {
border-color: $red !important; border-color: $red !important;
} }